From 3577589fd974c47ab29bf51fc5832c2ecf66a4ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tiago=20Concei=C3=A7=C3=A3o?= Date: Mon, 6 Dec 2021 23:06:03 +0000 Subject: v2.26.0 - **File formats - Photon Workshop: (#360)** - (Add) Allow to globally edit bottom lift height and bottom lift speed - (Add) Support for file version 515, 516 and TSMC - (Add) AnyCubic Photon Ultra (DLP) - (Add) AnyCubic Photon Mono SQ (PMSQ) - (Add) AnyCubic Photon Mono 4K (PMSA) - (Add) AnyCubic Photon Mono X 6K (PMSB) - **PrusaSlicer printers:** - (Add) AnyCubic Photon Mono 4K - (Add) Photon Mono X 6K - (Add) PrusaSlicer profiles manager: Allow to install profiles into SuperSlicer (#355) - (Fix) CTBv4: Setting the LiftHeight2 was defining the base.LiftHeight2 to BottomLiftHeight2 - (Fix) CWS: Typo on the "resolution must be multiple of 3" error --- CHANGELOG.md | 16 + PrusaSlicer/printer/AnyCubic Photon Mono 4K.ini | 38 ++ PrusaSlicer/printer/AnyCubic Photon Mono SE.ini | 4 +- PrusaSlicer/printer/AnyCubic Photon Mono SQ.ini | 4 +- PrusaSlicer/printer/AnyCubic Photon Mono X 6K.ini | 38 ++ PrusaSlicer/printer/AnyCubic Photon Mono X.ini | 4 +- PrusaSlicer/printer/AnyCubic Photon Mono.ini | 4 +- PrusaSlicer/printer/AnyCubic Photon S.ini | 4 +- PrusaSlicer/printer/AnyCubic Photon Ultra.ini | 4 +- PrusaSlicer/printer/AnyCubic Photon X.ini | 4 +- PrusaSlicer/printer/AnyCubic Photon Zero.ini | 4 +- README.md | 3 + Scripts/010 Editor/PhotonWorkshop.bt | 62 ++- Scripts/ImportPrusaSlicerData.bat | 108 ++--- UVtools.Core/FileFormats/CWSFile.cs | 2 +- UVtools.Core/FileFormats/ChituboxFile.cs | 4 +- UVtools.Core/FileFormats/PhotonWorkshopFile.cs | 521 ++++++++++++++++++--- UVtools.Core/UVtools.Core.csproj | 2 +- UVtools.InstallerMM/UVtools.InstallerMM.wxs | 6 + UVtools.Powershell/Erode-Bottom.ps1 | 2 +- UVtools.Powershell/List-Layers.ps1 | 2 +- UVtools.Powershell/README.md | 4 +- UVtools.WPF/App.axaml.cs | 23 +- UVtools.WPF/Assets/Icons/PrusaSlicer-32.png | Bin 0 -> 694 bytes UVtools.WPF/Assets/Icons/SuperSlicer-32.png | Bin 0 -> 1520 bytes UVtools.WPF/MainWindow.axaml.cs | 25 +- UVtools.WPF/Structures/PEProfileFolder.cs | 147 ------ UVtools.WPF/Structures/PSProfileFolder.cs | 148 ++++++ UVtools.WPF/UVtools.WPF.csproj | 2 +- UVtools.WPF/Windows/PrusaSlicerManagerWindow.axaml | 340 +++++++++----- .../Windows/PrusaSlicerManagerWindow.axaml.cs | 68 ++- 31 files changed, 1146 insertions(+), 447 deletions(-) create mode 100644 PrusaSlicer/printer/AnyCubic Photon Mono 4K.ini create mode 100644 PrusaSlicer/printer/AnyCubic Photon Mono X 6K.ini create mode 100644 UVtools.WPF/Assets/Icons/PrusaSlicer-32.png create mode 100644 UVtools.WPF/Assets/Icons/SuperSlicer-32.png delete mode 100644 UVtools.WPF/Structures/PEProfileFolder.cs create mode 100644 UVtools.WPF/Structures/PSProfileFolder.cs diff --git a/CHANGELOG.md b/CHANGELOG.md index 44e3855..949dd20 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,21 @@ # Changelog +## 06/12/2021 - v2.26.0 + +- **File formats - Photon Workshop: (#360)** + - (Add) Allow to globally edit bottom lift height and bottom lift speed + - (Add) Support for file version 515, 516 and TSMC + - (Add) AnyCubic Photon Ultra (DLP) + - (Add) AnyCubic Photon Mono SQ (PMSQ) + - (Add) AnyCubic Photon Mono 4K (PMSA) + - (Add) AnyCubic Photon Mono X 6K (PMSB) +- **PrusaSlicer printers:** + - (Add) AnyCubic Photon Mono 4K + - (Add) Photon Mono X 6K +- (Add) PrusaSlicer profiles manager: Allow to install profiles into SuperSlicer (#355) +- (Fix) CTBv4: Setting the LiftHeight2 was defining the base.LiftHeight2 to BottomLiftHeight2 +- (Fix) CWS: Typo on the "resolution must be multiple of 3" error + ## 02/12/2021 - v2.25.3 - **File - Send to:** diff --git a/PrusaSlicer/printer/AnyCubic Photon Mono 4K.ini b/PrusaSlicer/printer/AnyCubic Photon Mono 4K.ini new file mode 100644 index 0000000..c797db1 --- /dev/null +++ b/PrusaSlicer/printer/AnyCubic Photon Mono 4K.ini @@ -0,0 +1,38 @@ +# generated by PrusaSlicer 2.3.3+win64 on 2021-12-06 at 03:22:23 UTC +absolute_correction = 0 +area_fill = 50 +bed_custom_model = +bed_custom_texture = +bed_shape = 0x0,132.9x0,132.9x80,0x80 +default_sla_material_profile = Prusa Orange Tough 0.05 +default_sla_print_profile = 0.05 Normal +display_height = 80 +display_mirror_x = 1 +display_mirror_y = 0 +display_orientation = landscape +display_pixels_x = 3840 +display_pixels_y = 2400 +display_width = 132.9 +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 = 165 +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_ANYCUBIC\nPRINTER_MODEL_PHOTON_MONO_4K\nFILEFORMAT_PWMA\n\nSTART_CUSTOM_VALUES\nWaitTimeBeforeCure_2.5\nBottomLiftHeight_6\nLiftHeight_6\nBottomLiftSpeed_150\nLiftSpeed_150\nRetractSpeed_150\nBottomLightPWM_255\nLightPWM_255\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/AnyCubic Photon Mono SE.ini b/PrusaSlicer/printer/AnyCubic Photon Mono SE.ini index 3318815..ed8287e 100644 --- a/PrusaSlicer/printer/AnyCubic Photon Mono SE.ini +++ b/PrusaSlicer/printer/AnyCubic Photon Mono SE.ini @@ -1,4 +1,4 @@ -# generated by PrusaSlicer 2.3.0+win64 on 2021-01-13 at 02:41:49 UTC +# generated by PrusaSlicer 2.3.3+win64 on 2021-12-06 at 03:22:28 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_ANYCUBIC\nPRINTER_MODEL_PHOTON_MONO_SE\nFILEFORMAT_PWMS\n\nSTART_CUSTOM_VALUES\nLightOffDelay_0\nBottomLightOffDelay_0\nBottomLiftHeight_6\nLiftHeight_6\nBottomLiftSpeed_150\nLiftSpeed_150\nRetractSpeed_150\nBottomLightPWM_255\nLightPWM_255\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_ANYCUBIC\nPRINTER_MODEL_PHOTON_MONO_SE\nFILEFORMAT_PWMS\n\nSTART_CUSTOM_VALUES\nWaitTimeBeforeCure_2.5\nBottomLiftHeight_6\nLiftHeight_6\nBottomLiftSpeed_150\nLiftSpeed_150\nRetractSpeed_150\nBottomLightPWM_255\nLightPWM_255\nEND_CUSTOM_VALUES printer_settings_id = printer_technology = SLA printer_variant = default diff --git a/PrusaSlicer/printer/AnyCubic Photon Mono SQ.ini b/PrusaSlicer/printer/AnyCubic Photon Mono SQ.ini index b0f9c9b..e151aa6 100644 --- a/PrusaSlicer/printer/AnyCubic Photon Mono SQ.ini +++ b/PrusaSlicer/printer/AnyCubic Photon Mono SQ.ini @@ -1,4 +1,4 @@ -# generated by PrusaSlicer 2.3.1+win64 on 2021-08-23 at 15:24:23 UTC +# generated by PrusaSlicer 2.3.3+win64 on 2021-12-06 at 03:22:33 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_ANYCUBIC\nPRINTER_MODEL_PHOTON_MONO_SQ\nFILEFORMAT_PMSQ\n\nSTART_CUSTOM_VALUES\nLightOffDelay_0\nBottomLightOffDelay_0\nBottomLiftHeight_8\nLiftHeight_8\nBottomLiftSpeed_150\nLiftSpeed_150\nRetractSpeed_150\nBottomLightPWM_255\nLightPWM_255\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_ANYCUBIC\nPRINTER_MODEL_PHOTON_MONO_SQ\nFILEFORMAT_PMSQ\n\nSTART_CUSTOM_VALUES\nWaitTimeBeforeCure_2.5\nBottomLiftHeight_8\nLiftHeight_8\nBottomLiftSpeed_150\nLiftSpeed_150\nRetractSpeed_150\nBottomLightPWM_255\nLightPWM_255\nEND_CUSTOM_VALUES printer_settings_id = printer_technology = SLA printer_variant = default diff --git a/PrusaSlicer/printer/AnyCubic Photon Mono X 6K.ini b/PrusaSlicer/printer/AnyCubic Photon Mono X 6K.ini new file mode 100644 index 0000000..db0b7c6 --- /dev/null +++ b/PrusaSlicer/printer/AnyCubic Photon Mono X 6K.ini @@ -0,0 +1,38 @@ +# generated by PrusaSlicer 2.3.3+win64 on 2021-12-06 at 03:22:41 UTC +absolute_correction = 0 +area_fill = 50 +bed_custom_model = +bed_custom_texture = +bed_shape = 0x0,197x0,197x122.8,0x122.8 +default_sla_material_profile = Prusa Orange Tough 0.05 +default_sla_print_profile = 0.05 Normal +display_height = 122.8 +display_mirror_x = 1 +display_mirror_y = 0 +display_orientation = landscape +display_pixels_x = 5760 +display_pixels_y = 3600 +display_width = 197 +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 = 245 +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_ANYCUBIC\nPRINTER_MODEL_PHOTON_MONO_X_6K\nFILEFORMAT_PWMB\n\nSTART_CUSTOM_VALUES\nWaitTimeBeforeCure_2.5\nBottomLiftHeight_8\nLiftHeight_8\nBottomLiftSpeed_120\nLiftSpeed_120\nRetractSpeed_120\nBottomLightPWM_255\nLightPWM_255\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/AnyCubic Photon Mono X.ini b/PrusaSlicer/printer/AnyCubic Photon Mono X.ini index 7c1c19c..26f4de0 100644 --- a/PrusaSlicer/printer/AnyCubic Photon Mono X.ini +++ b/PrusaSlicer/printer/AnyCubic Photon Mono X.ini @@ -1,4 +1,4 @@ -# generated by PrusaSlicer 2.3.0+win64 on 2021-01-13 at 02:41:30 UTC +# generated by PrusaSlicer 2.3.3+win64 on 2021-12-06 at 03:22:37 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_ANYCUBIC\nPRINTER_MODEL_PHOTON_MONO_X\nFILEFORMAT_PWMX\n\nSTART_CUSTOM_VALUES\nLightOffDelay_0\nBottomLightOffDelay_0\nBottomLiftHeight_8\nLiftHeight_8\nBottomLiftSpeed_120\nLiftSpeed_120\nRetractSpeed_120\nBottomLightPWM_255\nLightPWM_255\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_ANYCUBIC\nPRINTER_MODEL_PHOTON_MONO_X\nFILEFORMAT_PWMX\n\nSTART_CUSTOM_VALUES\nWaitTimeBeforeCure_2.5\nBottomLiftHeight_8\nLiftHeight_8\nBottomLiftSpeed_120\nLiftSpeed_120\nRetractSpeed_120\nBottomLightPWM_255\nLightPWM_255\nEND_CUSTOM_VALUES printer_settings_id = printer_technology = SLA printer_variant = default diff --git a/PrusaSlicer/printer/AnyCubic Photon Mono.ini b/PrusaSlicer/printer/AnyCubic Photon Mono.ini index 9df8b45..8e96119 100644 --- a/PrusaSlicer/printer/AnyCubic Photon Mono.ini +++ b/PrusaSlicer/printer/AnyCubic Photon Mono.ini @@ -1,4 +1,4 @@ -# generated by PrusaSlicer 2.3.0+win64 on 2021-01-13 at 02:42:13 UTC +# generated by PrusaSlicer 2.3.3+win64 on 2021-12-06 at 03:22:18 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_ANYCUBIC\nPRINTER_MODEL_PHOTON_MONO\nFILEFORMAT_PWMO\n\nSTART_CUSTOM_VALUES\nLightOffDelay_0\nBottomLightOffDelay_0\nBottomLiftHeight_6\nLiftHeight_6\nBottomLiftSpeed_150\nLiftSpeed_150\nRetractSpeed_150\nBottomLightPWM_255\nLightPWM_255\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_ANYCUBIC\nPRINTER_MODEL_PHOTON_MONO\nFILEFORMAT_PWMO\n\nSTART_CUSTOM_VALUES\nWaitTimeBeforeCure_2.5\nBottomLiftHeight_6\nLiftHeight_6\nBottomLiftSpeed_150\nLiftSpeed_150\nRetractSpeed_150\nBottomLightPWM_255\nLightPWM_255\nEND_CUSTOM_VALUES printer_settings_id = printer_technology = SLA printer_variant = default diff --git a/PrusaSlicer/printer/AnyCubic Photon S.ini b/PrusaSlicer/printer/AnyCubic Photon S.ini index e5fdb20..e546fab 100644 --- a/PrusaSlicer/printer/AnyCubic Photon S.ini +++ b/PrusaSlicer/printer/AnyCubic Photon S.ini @@ -1,4 +1,4 @@ -# generated by PrusaSlicer 2.3.0+win64 on 2021-01-13 at 02:41:23 UTC +# generated by PrusaSlicer 2.3.3+win64 on 2021-12-06 at 03:22:49 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_ANYCUBIC\nPRINTER_MODEL_PHOTON_S\nFILEFORMAT_PWS\n\nSTART_CUSTOM_VALUES\nLightOffDelay_0\nLiftHeight_6\nLiftSpeed_60\nRetractSpeed_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_ANYCUBIC\nPRINTER_MODEL_PHOTON_S\nFILEFORMAT_PWS\n\nSTART_CUSTOM_VALUES\nWaitTimeBeforeCure_2.5\nLiftHeight_6\nLiftSpeed_60\nRetractSpeed_150\nEND_CUSTOM_VALUES printer_settings_id = printer_technology = SLA printer_variant = default diff --git a/PrusaSlicer/printer/AnyCubic Photon Ultra.ini b/PrusaSlicer/printer/AnyCubic Photon Ultra.ini index 41b441c..ad56617 100644 --- a/PrusaSlicer/printer/AnyCubic Photon Ultra.ini +++ b/PrusaSlicer/printer/AnyCubic Photon Ultra.ini @@ -1,4 +1,4 @@ -# generated by PrusaSlicer 2.3.1+win64 on 2021-08-23 at 15:46:01 UTC +# generated by PrusaSlicer 2.3.3+win64 on 2021-12-06 at 03:22:53 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_ANYCUBIC\nPRINTER_MODEL_PHOTON_ULTRA\nFILEFORMAT_DLP\n\nSTART_CUSTOM_VALUES\nLightOffDelay_0\nBottomLightOffDelay_0\nBottomLiftHeight_6\nLiftHeight_5\nBottomLiftSpeed_150\nLiftSpeed_150\nRetractSpeed_150\nBottomLightPWM_255\nLightPWM_255\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_ANYCUBIC\nPRINTER_MODEL_PHOTON_ULTRA\nFILEFORMAT_DLP\n\nSTART_CUSTOM_VALUES\nWaitTimeBeforeCure_2.5\nBottomLiftHeight_6\nLiftHeight_5\nBottomLiftSpeed_150\nLiftSpeed_150\nRetractSpeed_150\nBottomLightPWM_255\nLightPWM_255\nEND_CUSTOM_VALUES printer_settings_id = printer_technology = SLA printer_variant = default diff --git a/PrusaSlicer/printer/AnyCubic Photon X.ini b/PrusaSlicer/printer/AnyCubic Photon X.ini index 963f5ee..c20e937 100644 --- a/PrusaSlicer/printer/AnyCubic Photon X.ini +++ b/PrusaSlicer/printer/AnyCubic Photon X.ini @@ -1,4 +1,4 @@ -# generated by PrusaSlicer 2.3.0+win64 on 2021-01-13 at 02:41:05 UTC +# generated by PrusaSlicer 2.3.3+win64 on 2021-12-06 at 03:22:58 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_ANYCUBIC\nPRINTER_MODEL_PHOTON_X\nFILEFORMAT_PWX\n\nSTART_CUSTOM_VALUES\nLightOffDelay_0\nBottomLightOffDelay_0\nBottomLiftHeight_8\nLiftHeight_8\nBottomLiftSpeed_150\nLiftSpeed_150\nRetractSpeed_150\nBottomLightPWM_255\nLightPWM_255\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_ANYCUBIC\nPRINTER_MODEL_PHOTON_X\nFILEFORMAT_PWX\n\nSTART_CUSTOM_VALUES\nWaitTimeBeforeCure_2.5\nBottomLiftHeight_8\nLiftHeight_8\nBottomLiftSpeed_150\nLiftSpeed_150\nRetractSpeed_150\nBottomLightPWM_255\nLightPWM_255\nEND_CUSTOM_VALUES printer_settings_id = printer_technology = SLA printer_variant = default diff --git a/PrusaSlicer/printer/AnyCubic Photon Zero.ini b/PrusaSlicer/printer/AnyCubic Photon Zero.ini index dde504d..b2bcb7f 100644 --- a/PrusaSlicer/printer/AnyCubic Photon Zero.ini +++ b/PrusaSlicer/printer/AnyCubic Photon Zero.ini @@ -1,4 +1,4 @@ -# generated by PrusaSlicer 2.3.0+win64 on 2021-03-17 at 02:45:57 UTC +# generated by PrusaSlicer 2.3.3+win64 on 2021-12-06 at 03:23:03 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_ANYCUBIC\nPRINTER_MODEL_PHOTON_ZERO\nFILEFORMAT_PW0\n\nSTART_CUSTOM_VALUES\nLightOffDelay_0\nLiftHeight_6\nLiftingSpeed_60\nRetractSpeed_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_ANYCUBIC\nPRINTER_MODEL_PHOTON_ZERO\nFILEFORMAT_PW0\n\nSTART_CUSTOM_VALUES\nWaitTimeBeforeCure_2.5\nLiftHeight_6\nLiftingSpeed_60\nRetractSpeed_150\nEND_CUSTOM_VALUES printer_settings_id = printer_technology = SLA printer_variant = default diff --git a/README.md b/README.md index 384a33d..8f127f9 100644 --- a/README.md +++ b/README.md @@ -78,8 +78,11 @@ But also, i need victims for test subject. Proceed at your own risk! - PW0 (Photon Workshop) - PWX (Photon Workshop) - PWMO (Photon Workshop) +- PWMA (Photon Workshop) - PWMS (Photon Workshop) - PWMX (Photon Workshop) +- PWMB (Photon Workshop) +- PWSQ (Photon Workshop) - ZCode (UnizMaker) - ZCodex (Z-Suite) - CWS (NovaMaker) diff --git a/Scripts/010 Editor/PhotonWorkshop.bt b/Scripts/010 Editor/PhotonWorkshop.bt index f233b28..96ad451 100644 --- a/Scripts/010 Editor/PhotonWorkshop.bt +++ b/Scripts/010 Editor/PhotonWorkshop.bt @@ -9,15 +9,23 @@ LittleEndian(); struct FILEMARK { char Mark[12] ; - uint Version ; // 1 or 515 + uint Version ; // 1 or 515 or 516 uint AreaNum ; uint HeaderAddress ; - uint Padding1 ; + uint Unknown ; // 6357060 for 516 uint PreviewAddress ; uint PreviewEndAddress ; // Version 515 only uint LayerDefinitionAddress ; - uint Padding3 ; - uint LayerImageAddress ; + uint ExtraAddress ; + + if(Version < 516) + { + uint LayerImageAddress ; + } + else{ + uint MachineAddress ; + uint LayerImageAddress ; + } } fileMark; struct SECTION { @@ -47,8 +55,12 @@ struct HEADER { uint PriceCurrencyDec ; uint PerLayerOverride ; uint PrintTime ; - uint Padding1 ; - uint Padding2 ; + uint TransitionLayerCount ; + uint Padding ; + + if(fileMark.Version > 515){ + uint Padding ; + } }; if(fileMark.HeaderAddress > 0){ @@ -74,6 +86,11 @@ struct PREVIEW { if(fileMark.PreviewAddress > 0){ FSeek(fileMark.PreviewAddress); PREVIEW preview; + + if(fileMark.Version >= 515) + { + uint Reserved[7] ; + } } @@ -103,6 +120,39 @@ struct LAYER_DEF { }; +if(fileMark.Version >= 516 && fileMark.ExtraAddress > 0){ + FSeek(fileMark.ExtraAddress); + struct EXTRA { + SECTION section; + uint Unknown ; // 2 + float BottomLiftHeight0 ; + float BottomLiftSpeed0 ; + float BottomRetractSpeed0 ; + float BottomLiftHeight1 ; + float BottomLiftSpeed1 ; + float BottomRetractSpeed1 ; + uint Unknown ; // 2 + float LiftHeight0 ; + float LiftSpeed0 ; + float RetractSpeed0 ; + float LiftHeight1 ; + float LiftSpeed1 ; + float RetractSpeed1 ; + } extra; +} + +if(fileMark.Version >= 516 && fileMark.MachineAddress > 0){ + struct MACHINE { + SECTION section; + char MachineName[96] ; + char ImageFormat[24] ; + float DisplayWidth ; + float DisplayHeight ; + float MachineZ ; + uint Version ; // Version again? 516 + uint Unknown ; // 6506241 + } machine; +} if(fileMark.LayerDefinitionAddress > 0){ FSeek(fileMark.LayerDefinitionAddress); diff --git a/Scripts/ImportPrusaSlicerData.bat b/Scripts/ImportPrusaSlicerData.bat index afadec9..0be9ace 100644 --- a/Scripts/ImportPrusaSlicerData.bat +++ b/Scripts/ImportPrusaSlicerData.bat @@ -33,59 +33,61 @@ SET files[22]=AnyCubic Photon Zero.ini SET files[23]=AnyCubic Photon X.ini SET files[24]=AnyCubic Photon Ultra.ini SET files[25]=AnyCubic Photon Mono.ini -SET files[26]=AnyCubic Photon Mono SE.ini -SET files[27]=AnyCubic Photon Mono X.ini -SET files[28]=AnyCubic Photon Mono SQ.ini -SET files[29]=Elegoo Mars.ini -SET files[30]=Elegoo Mars 2 Pro.ini -SET files[31]=Elegoo Mars C.ini -SET files[32]=Elegoo Saturn.ini -SET files[33]=Peopoly Phenom.ini -SET files[34]=Peopoly Phenom L.ini -SET files[35]=Peopoly Phenom Noir.ini -SET files[36]=Peopoly Phenom XXL.ini -SET files[37]=QIDI Shadow5.5.ini -SET files[38]=QIDI Shadow6.0 Pro.ini -SET files[39]=QIDI S-Box.ini -SET files[40]=QIDI I-Box Mono.ini -SET files[41]=Phrozen Shuffle.ini -SET files[42]=Phrozen Shuffle Lite.ini -SET files[43]=Phrozen Shuffle XL.ini -SET files[44]=Phrozen Shuffle XL Lite.ini -SET files[45]=Phrozen Shuffle 16.ini -SET files[46]=Phrozen Shuffle 4K.ini -SET files[47]=Phrozen Sonic.ini -SET files[48]=Phrozen Sonic 4K.ini -SET files[49]=Phrozen Sonic Mighty 4K.ini -SET files[50]=Phrozen Sonic Mini.ini -SET files[51]=Phrozen Sonic Mini 4K.ini -SET files[52]=Phrozen Transform.ini -SET files[53]=Kelant S400.ini -SET files[54]=Wanhao D7.ini -SET files[55]=Wanhao D8.ini -SET files[56]=Wanhao CGR Mini Mono.ini -SET files[57]=Wanhao CGR Mono.ini -SET files[58]=Creality LD-002R.ini -SET files[59]=Creality LD-002H.ini -SET files[60]=Creality LD-006.ini -SET files[61]=Creality HALOT-ONE CL-60.ini -SET files[62]=Creality HALOT-SKY CL-89.ini -SET files[63]=Creality HALOT-MAX CL-133.ini -SET files[64]=Voxelab Polaris 5.5.ini -SET files[65]=Voxelab Proxima 6.ini -SET files[66]=Voxelab Ceres 8.9.ini -SET files[67]=Longer Orange 10.ini -SET files[68]=Longer Orange 30.ini -SET files[69]=Longer Orange 120.ini -SET files[70]=Longer Orange 4K.ini -SET files[71]=Uniz IBEE.ini -SET files[72]=FlashForge Explorer MAX.ini -SET files[73]=FlashForge Focus 8.9.ini -SET files[74]=FlashForge Focus 13.3.ini -SET files[75]=FlashForge Foto 6.0.ini -SET files[76]=FlashForge Foto 8.9.ini -SET files[77]=FlashForge Foto 13.3.ini -SET files[78]=FlashForge Hunter.ini +SET files[26]=AnyCubic Photon Mono 4K.ini +SET files[27]=AnyCubic Photon Mono SE.ini +SET files[28]=AnyCubic Photon Mono X.ini +SET files[29]=AnyCubic Photon Mono X 6K.ini +SET files[30]=AnyCubic Photon Mono SQ.ini +SET files[31]=Elegoo Mars.ini +SET files[32]=Elegoo Mars 2 Pro.ini +SET files[33]=Elegoo Mars C.ini +SET files[34]=Elegoo Saturn.ini +SET files[35]=Peopoly Phenom.ini +SET files[36]=Peopoly Phenom L.ini +SET files[37]=Peopoly Phenom Noir.ini +SET files[38]=Peopoly Phenom XXL.ini +SET files[39]=QIDI Shadow5.5.ini +SET files[40]=QIDI Shadow6.0 Pro.ini +SET files[41]=QIDI S-Box.ini +SET files[42]=QIDI I-Box Mono.ini +SET files[43]=Phrozen Shuffle.ini +SET files[44]=Phrozen Shuffle Lite.ini +SET files[45]=Phrozen Shuffle XL.ini +SET files[46]=Phrozen Shuffle XL Lite.ini +SET files[47]=Phrozen Shuffle 16.ini +SET files[48]=Phrozen Shuffle 4K.ini +SET files[49]=Phrozen Sonic.ini +SET files[50]=Phrozen Sonic 4K.ini +SET files[51]=Phrozen Sonic Mighty 4K.ini +SET files[52]=Phrozen Sonic Mini.ini +SET files[53]=Phrozen Sonic Mini 4K.ini +SET files[54]=Phrozen Transform.ini +SET files[55]=Kelant S400.ini +SET files[56]=Wanhao D7.ini +SET files[57]=Wanhao D8.ini +SET files[58]=Wanhao CGR Mini Mono.ini +SET files[59]=Wanhao CGR Mono.ini +SET files[60]=Creality LD-002R.ini +SET files[61]=Creality LD-002H.ini +SET files[62]=Creality LD-006.ini +SET files[63]=Creality HALOT-ONE CL-60.ini +SET files[64]=Creality HALOT-SKY CL-89.ini +SET files[65]=Creality HALOT-MAX CL-133.ini +SET files[66]=Voxelab Polaris 5.5.ini +SET files[67]=Voxelab Proxima 6.ini +SET files[68]=Voxelab Ceres 8.9.ini +SET files[69]=Longer Orange 10.ini +SET files[70]=Longer Orange 30.ini +SET files[71]=Longer Orange 120.ini +SET files[72]=Longer Orange 4K.ini +SET files[73]=Uniz IBEE.ini +SET files[74]=FlashForge Explorer MAX.ini +SET files[75]=FlashForge Focus 8.9.ini +SET files[76]=FlashForge Focus 13.3.ini +SET files[77]=FlashForge Foto 6.0.ini +SET files[78]=FlashForge Foto 8.9.ini +SET files[79]=FlashForge Foto 13.3.ini +SET files[80]=FlashForge Hunter.ini echo PrusaSlicer Printers Instalation echo This will replace printers, all changes will be discarded diff --git a/UVtools.Core/FileFormats/CWSFile.cs b/UVtools.Core/FileFormats/CWSFile.cs index d7f1c6b..9531cc9 100644 --- a/UVtools.Core/FileFormats/CWSFile.cs +++ b/UVtools.Core/FileFormats/CWSFile.cs @@ -594,7 +594,7 @@ namespace UVtools.Core.FileFormats if (ResolutionX % 3 != 0) { throw new InvalidOperationException($"Resolution width of {ResolutionX}px is invalid. Width must be in multiples of 3.\n" + - $"Fix your printer slicing settings with the correct with."); + "Fix your printer slicing settings with the correct width that is multiple of 3."); } } diff --git a/UVtools.Core/FileFormats/ChituboxFile.cs b/UVtools.Core/FileFormats/ChituboxFile.cs index 213b50a..cc31f1f 100644 --- a/UVtools.Core/FileFormats/ChituboxFile.cs +++ b/UVtools.Core/FileFormats/ChituboxFile.cs @@ -1426,7 +1426,7 @@ namespace UVtools.Core.FileFormats get { if (HeaderSettings.Version <= 3) return PrintParametersSettings.BottomLiftHeight; - return Math.Max(0, PrintParametersSettings.BottomLiftHeight - SlicerInfoSettings.BottomLiftHeight2); + return (float)Math.Round(Math.Max(0, PrintParametersSettings.BottomLiftHeight - SlicerInfoSettings.BottomLiftHeight2), 2); } set { @@ -1497,7 +1497,7 @@ namespace UVtools.Core.FileFormats var liftHeight = LiftHeight; SlicerInfoSettings.LiftHeight2 = (float)Math.Round(value, 2); LiftHeight = liftHeight; - base.LiftHeight2 = SlicerInfoSettings.BottomLiftHeight2; + base.LiftHeight2 = SlicerInfoSettings.LiftHeight2; } } diff --git a/UVtools.Core/FileFormats/PhotonWorkshopFile.cs b/UVtools.Core/FileFormats/PhotonWorkshopFile.cs index 246d6b2..51e1784 100644 --- a/UVtools.Core/FileFormats/PhotonWorkshopFile.cs +++ b/UVtools.Core/FileFormats/PhotonWorkshopFile.cs @@ -26,11 +26,23 @@ namespace UVtools.Core.FileFormats #region Constants public const byte VERSION_1 = 1; public const ushort VERSION_515 = 515; + public const ushort VERSION_516 = 516; public const byte MarkSize = 12; public const byte RLE1EncodingLimit = 0x7d; // 125; public const ushort RLE4EncodingLimit = 0xfff; // 4095; + public static readonly uint[] ReservedUintsAfterPreview = + { + 0, + 16, + uint.MaxValue, + uint.MaxValue, + uint.MaxValue, + uint.MaxValue, + 0 + }; + // CRC-16-ANSI (aka CRC-16-IMB) Polynomial: x^16 + x^15 + x^2 + 1 public static readonly int[] CRC16Table = { 0x0000, 0xc0c1, 0xc181, 0x0140, 0xc301, 0x03c0, 0x0280, 0xc241, @@ -84,7 +96,9 @@ namespace UVtools.Core.FileFormats AnyCubicPhotonUltra, AnyCubicPhotonMono, AnyCubicPhotonMonoSE, + AnyCubicPhotonMono4K, AnyCubicPhotonMonoX, + AnyCubicPhotonMonoX6K, AnyCubicPhotonMonoSQ, } #endregion @@ -114,9 +128,9 @@ namespace UVtools.Core.FileFormats /// /// Gets the area num - /// 10 + /// 10, 4 for v1, 5 for v515, 8 for v516? /// - [FieldOrder(2)] public uint AreaNum { get; set; } = 4; + [FieldOrder(2)] public uint AreaNum { get; set; } /// /// Gets the header start address @@ -136,7 +150,7 @@ namespace UVtools.Core.FileFormats [FieldOrder(5)] public uint PreviewAddress { get; set; } /// - /// 20, Spoted on version 515 only + /// 20, Spotted on version 515 only /// [FieldOrder(6)] public uint PreviewEndAddress { get; set; } @@ -147,19 +161,24 @@ namespace UVtools.Core.FileFormats [FieldOrder(7)] public uint LayerDefinitionAddress { get; set; } /// - /// 28 + /// 28, Spotted on version 516 only + /// + [FieldOrder(8)] public uint ExtraAddress { get; set; } + + /// + /// 2C, Spotted on version 516 only /// - [FieldOrder(8)] public uint Padding2 { get; set; } + [SerializeWhen(nameof(Version), VERSION_516)] + [FieldOrder(9)] public uint MachineAddress { get; set; } /// /// Gets layer image start address - /// 2C /// - [FieldOrder(9)] public uint LayerImageAddress { get; set; } + [FieldOrder(10)] public uint LayerImageAddress { get; set; } public override string ToString() { - return $"{nameof(Mark)}: {Mark}, {nameof(Version)}: {Version}, {nameof(AreaNum)}: {AreaNum}, {nameof(HeaderAddress)}: {HeaderAddress}, {nameof(Padding1)}: {Padding1}, {nameof(PreviewAddress)}: {PreviewAddress}, {nameof(PreviewEndAddress)}: {PreviewEndAddress}, {nameof(LayerDefinitionAddress)}: {LayerDefinitionAddress}, {nameof(Padding2)}: {Padding2}, {nameof(LayerImageAddress)}: {LayerImageAddress}"; + return $"{nameof(Mark)}: {Mark}, {nameof(Version)}: {Version}, {nameof(AreaNum)}: {AreaNum}, {nameof(HeaderAddress)}: {HeaderAddress}, {nameof(Padding1)}: {Padding1}, {nameof(PreviewAddress)}: {PreviewAddress}, {nameof(PreviewEndAddress)}: {PreviewEndAddress}, {nameof(LayerDefinitionAddress)}: {LayerDefinitionAddress}, {nameof(ExtraAddress)}: {ExtraAddress}, {nameof(MachineAddress)}: {MachineAddress}, {nameof(LayerImageAddress)}: {LayerImageAddress}"; } } #endregion @@ -183,10 +202,10 @@ namespace UVtools.Core.FileFormats public SectionHeader() { } - public SectionHeader(string mark, object obj) : this(mark) + public SectionHeader(string mark, object obj, int extraLength = 0) : this(mark) { //Debug.WriteLine(Helpers.Serializer.SizeOf(obj)); - Length = (uint)Helpers.Serializer.SizeOf(obj); + Length = (uint)(Helpers.Serializer.SizeOf(obj) + extraLength); } public SectionHeader(string mark, uint length = 0) @@ -341,25 +360,28 @@ namespace UVtools.Core.FileFormats [FieldOrder(18)] public uint PrintTime { get; set; } /// - /// 88 + /// 88, spotted on 516 /// - [FieldOrder(19)] public uint Padding1 { get; set; } + [FieldOrder(19)] public uint TransitionLayerCount { get; set; } /// /// 8C /// [FieldOrder(20)] public uint Padding2 { get; set; } + //[SerializeUntil((char)'P')] [FieldOrder(21)] public List Offset { get; set; } = new(); + public Header() { Section = new SectionHeader(SectionMark, this); } - public override string ToString() => $"{nameof(Section)}: {Section}, {nameof(PixelSizeUm)}: {PixelSizeUm}, {nameof(LayerHeight)}: {LayerHeight}, {nameof(ExposureTime)}: {ExposureTime}, {nameof(WaitTimeBeforeCure)}: {WaitTimeBeforeCure}, {nameof(BottomExposureTime)}: {BottomExposureTime}, {nameof(BottomLayersCount)}: {BottomLayersCount}, {nameof(LiftHeight)}: {LiftHeight}, {nameof(LiftSpeed)}: {LiftSpeed}, {nameof(RetractSpeed)}: {RetractSpeed}, {nameof(VolumeMl)}: {VolumeMl}, {nameof(AntiAliasing)}: {AntiAliasing}, {nameof(ResolutionX)}: {ResolutionX}, {nameof(ResolutionY)}: {ResolutionY}, {nameof(WeightG)}: {WeightG}, {nameof(Price)}: {Price}, {nameof(PriceCurrencyDec)}: {PriceCurrencyDec}, {nameof(PerLayerOverride)}: {PerLayerOverride}, {nameof(PrintTime)}: {PrintTime}, {nameof(Padding1)}: {Padding1}, {nameof(Padding2)}: {Padding2}"; - public void Validate() + public override string ToString() => $"{nameof(Section)}: {Section}, {nameof(PixelSizeUm)}: {PixelSizeUm}, {nameof(LayerHeight)}: {LayerHeight}, {nameof(ExposureTime)}: {ExposureTime}, {nameof(WaitTimeBeforeCure)}: {WaitTimeBeforeCure}, {nameof(BottomExposureTime)}: {BottomExposureTime}, {nameof(BottomLayersCount)}: {BottomLayersCount}, {nameof(LiftHeight)}: {LiftHeight}, {nameof(LiftSpeed)}: {LiftSpeed}, {nameof(RetractSpeed)}: {RetractSpeed}, {nameof(VolumeMl)}: {VolumeMl}, {nameof(AntiAliasing)}: {AntiAliasing}, {nameof(ResolutionX)}: {ResolutionX}, {nameof(ResolutionY)}: {ResolutionY}, {nameof(WeightG)}: {WeightG}, {nameof(Price)}: {Price}, {nameof(PriceCurrencyDec)}: {PriceCurrencyDec}, {nameof(PerLayerOverride)}: {PerLayerOverride}, {nameof(PrintTime)}: {PrintTime}, {nameof(TransitionLayerCount)}: {TransitionLayerCount}, {nameof(Padding2)}: {Padding2}"; + + public void Validate(int offset = 0) { - Section.Validate(SectionMark, (int)-Helpers.Serializer.SizeOf(Section), this); + Section.Validate(SectionMark, (int)-Helpers.Serializer.SizeOf(Section)+offset, this); } } @@ -549,7 +571,7 @@ namespace UVtools.Core.FileFormats public Mat Decode(bool consumeData = true) { - var result = Parent.LayerFormat == LayerRleFormat.PWS ? DecodePWS() : DecodePW0(); + var result = Parent.LayerImageFormat == LayerRleFormat.PWS ? DecodePWS() : DecodePW0(); if (consumeData) EncodedRle = null; @@ -558,7 +580,7 @@ namespace UVtools.Core.FileFormats public byte[] Encode(Mat image) { - EncodedRle = Parent.LayerFormat == LayerRleFormat.PWS ? EncodePWS(image) : EncodePW0(image); + EncodedRle = Parent.LayerImageFormat == LayerRleFormat.PWS ? EncodePWS(image) : EncodePW0(image); return EncodedRle; } @@ -910,6 +932,78 @@ namespace UVtools.Core.FileFormats } #endregion + #region Extra + public class Extra + { + public const string SectionMark = "EXTRA"; + + //[FieldOrder(0)] public SectionHeader Section { get; set; } + [FieldOrder(0)] [FieldLength(MarkSize)] [SerializeAs(SerializedType.TerminatedString)] public string Marker { get; set; } + [FieldOrder(1)] public uint Unknown0 { get; set; } = 24; + [FieldOrder(2)] public uint Unknown1 { get; set; } = 2; + [FieldOrder(3)] public float BottomLiftHeight1 { get; set; } + [FieldOrder(4)] public float BottomLiftSpeed1 { get; set; } + [FieldOrder(5)] public float BottomRetractSpeed1 { get; set; } + [FieldOrder(6)] public float BottomLiftHeight2 { get; set; } + [FieldOrder(7)] public float BottomLiftSpeed2 { get; set; } + [FieldOrder(8)] public float BottomRetractSpeed2 { get; set; } + [FieldOrder(9)] public uint Unknown2 { get; set; } = 2; + [FieldOrder(10)] public float LiftHeight1 { get; set; } + [FieldOrder(11)] public float LiftSpeed1 { get; set; } + [FieldOrder(12)] public float RetractSpeed1 { get; set; } + [FieldOrder(13)] public float LiftHeight2 { get; set; } + [FieldOrder(14)] public float LiftSpeed2 { get; set; } + [FieldOrder(15)] public float RetractSpeed2 { get; set; } + + public Extra() + { + //Section = new SectionHeader(SectionMark, this); + } + + public override string ToString() + { + return $"{nameof(Marker)}: {Marker}, {nameof(Unknown0)}: {Unknown0}, {nameof(Unknown1)}: {Unknown1}, {nameof(BottomLiftHeight1)}: {BottomLiftHeight1}, {nameof(BottomLiftSpeed1)}: {BottomLiftSpeed1}, {nameof(BottomRetractSpeed1)}: {BottomRetractSpeed1}, {nameof(BottomLiftHeight2)}: {BottomLiftHeight2}, {nameof(BottomLiftSpeed2)}: {BottomLiftSpeed2}, {nameof(BottomRetractSpeed2)}: {BottomRetractSpeed2}, {nameof(Unknown2)}: {Unknown2}, {nameof(LiftHeight1)}: {LiftHeight1}, {nameof(LiftSpeed1)}: {LiftSpeed1}, {nameof(RetractSpeed1)}: {RetractSpeed1}, {nameof(LiftHeight2)}: {LiftHeight2}, {nameof(LiftSpeed2)}: {LiftSpeed2}, {nameof(RetractSpeed2)}: {RetractSpeed2}"; + } + + public void Validate() + { + //Section.Validate(SectionMark, (int)-Helpers.Serializer.SizeOf(Section), this); + } + } + #endregion + + #region Machine + public class Machine + { + public const string SectionMark = "MACHINE"; + + [FieldOrder(0)] public SectionHeader Section { get; set; } + [FieldOrder(1)] [FieldLength(96)] [SerializeAs(SerializedType.TerminatedString)] public string MachineName { get; set; } + [FieldOrder(2)] [FieldLength(24)] [SerializeAs(SerializedType.TerminatedString)] public string LayerImageFormat { get; set; } = "pw0img"; + [FieldOrder(3)] public float DisplayWidth { get; set; } + [FieldOrder(4)] public float DisplayHeight { get; set; } + [FieldOrder(5)] public float MachineZ { get; set; } + [FieldOrder(6)] public uint Version { get; set; } = VERSION_516; + [FieldOrder(7)] public uint Unknown { get; set; } = 6506241; + + public override string ToString() + { + return $"{nameof(Section)}: {Section}, {nameof(MachineName)}: {MachineName}, {nameof(LayerImageFormat)}: {LayerImageFormat}, {nameof(DisplayWidth)}: {DisplayWidth}, {nameof(DisplayHeight)}: {DisplayHeight}, {nameof(MachineZ)}: {MachineZ}, {nameof(Version)}: {Version}, {nameof(Unknown)}: {Unknown}"; + } + + + public Machine() + { + Section = new SectionHeader(SectionMark, this); + } + + public void Validate() + { + Section.Validate(SectionMark, 0, this); + } + } + #endregion + #endregion #region Properties @@ -921,6 +1015,8 @@ namespace UVtools.Core.FileFormats public Preview PreviewSettings { get; protected internal set; } = new(); public LayerDefinition LayersDefinition { get; protected internal set; } = new(); + public Extra ExtraSettings { get; protected internal set; } = new(); + public Machine MachineSettings { get; protected internal set; } = new(); public override FileFormatType FileType => FileFormatType.Binary; @@ -929,28 +1025,68 @@ namespace UVtools.Core.FileFormats new(typeof(PhotonWorkshopFile), "pws", "Photon / Photon S (PWS)"), new(typeof(PhotonWorkshopFile), "pw0", "Photon Zero (PW0)"), new(typeof(PhotonWorkshopFile), "pwx", "Photon X (PWX)"), - new(typeof(PhotonWorkshopFile), "dlp", "Photon Ultra (DLP)", false, false), + new(typeof(PhotonWorkshopFile), "dlp", "Photon Ultra (DLP)"), new(typeof(PhotonWorkshopFile), "pwmx", "Photon Mono X (PWMX)"), - new(typeof(PhotonWorkshopFile), "pwms", "Photon Mono SE (PWMS)"), + new(typeof(PhotonWorkshopFile), "pwmb", "Photon Mono X 6K (PWMB)"), new(typeof(PhotonWorkshopFile), "pwmo", "Photon Mono (PWMO)"), - new(typeof(PhotonWorkshopFile), "pmsq", "Photon Mono SQ (PMSQ)", false, false), + new(typeof(PhotonWorkshopFile), "pwms", "Photon Mono SE (PWMS)"), + new(typeof(PhotonWorkshopFile), "pwma", "Photon Mono 4K (PWMA)"), + new(typeof(PhotonWorkshopFile), "pmsq", "Photon Mono SQ (PMSQ)"), }; - public override PrintParameterModifier[] PrintParameterModifiers { get; } = + public override PrintParameterModifier[] PrintParameterModifiers { - PrintParameterModifier.BottomLayerCount, + get + { + if (FileMarkSettings.Version >= VERSION_516) + { + return new[] + { + PrintParameterModifier.BottomLayerCount, + + PrintParameterModifier.WaitTimeBeforeCure, + + PrintParameterModifier.BottomExposureTime, + PrintParameterModifier.ExposureTime, + + PrintParameterModifier.BottomLiftHeight, + PrintParameterModifier.BottomLiftSpeed, + PrintParameterModifier.LiftHeight, + PrintParameterModifier.LiftSpeed, + PrintParameterModifier.BottomLiftHeight2, + PrintParameterModifier.BottomLiftSpeed2, + PrintParameterModifier.LiftHeight2, + PrintParameterModifier.LiftSpeed2, + + PrintParameterModifier.BottomRetractSpeed, + PrintParameterModifier.RetractSpeed, + //PrintParameterModifier.BottomRetractHeight2, + PrintParameterModifier.BottomRetractSpeed2, + //PrintParameterModifier.RetractHeight2, + PrintParameterModifier.RetractSpeed2, + }; + } - PrintParameterModifier.WaitTimeBeforeCure, + return new[] + { + PrintParameterModifier.BottomLayerCount, - PrintParameterModifier.BottomExposureTime, - PrintParameterModifier.ExposureTime, + PrintParameterModifier.WaitTimeBeforeCure, - PrintParameterModifier.LiftHeight, - PrintParameterModifier.LiftSpeed, - PrintParameterModifier.RetractSpeed, - }; + PrintParameterModifier.BottomExposureTime, + PrintParameterModifier.ExposureTime, + + PrintParameterModifier.BottomLiftHeight, + PrintParameterModifier.BottomLiftSpeed, + PrintParameterModifier.LiftHeight, + PrintParameterModifier.LiftSpeed, + + PrintParameterModifier.RetractSpeed, + }; + } + } public override PrintParameterModifier[] PrintParameterPerLayerModifiers { get; } = { PrintParameterModifier.ExposureTime, @@ -984,6 +1120,7 @@ namespace UVtools.Core.FileFormats { get { + if (MachineSettings.DisplayWidth > 0) return MachineSettings.DisplayWidth; return PrinterModel switch { AnyCubicMachine.AnyCubicPhotonS => 68.04f, @@ -992,17 +1129,24 @@ namespace UVtools.Core.FileFormats AnyCubicMachine.AnyCubicPhotonUltra => 102.40f, AnyCubicMachine.AnyCubicPhotonMono => 82.62f, AnyCubicMachine.AnyCubicPhotonMonoSE => 82.62f, + AnyCubicMachine.AnyCubicPhotonMono4K => 132.90f, AnyCubicMachine.AnyCubicPhotonMonoX => 192, + AnyCubicMachine.AnyCubicPhotonMonoX6K => 197, AnyCubicMachine.AnyCubicPhotonMonoSQ => 120, _ => 0 }; } - set { } + set + { + MachineSettings.DisplayWidth = (float)Math.Round(value, 2); + RaisePropertyChanged(); + } } public override float DisplayHeight { get { + if (MachineSettings.DisplayHeight > 0) return MachineSettings.DisplayHeight; return PrinterModel switch { AnyCubicMachine.AnyCubicPhotonS => 120.96f, @@ -1011,18 +1155,25 @@ namespace UVtools.Core.FileFormats AnyCubicMachine.AnyCubicPhotonUltra => 57.60f, AnyCubicMachine.AnyCubicPhotonMono => 130.56f, AnyCubicMachine.AnyCubicPhotonMonoSE => 130.56f, + AnyCubicMachine.AnyCubicPhotonMono4K => 80, AnyCubicMachine.AnyCubicPhotonMonoX => 120, + AnyCubicMachine.AnyCubicPhotonMonoX6K => 122.80f, AnyCubicMachine.AnyCubicPhotonMonoSQ => 128, _ => 0 }; } - set { } + set + { + MachineSettings.DisplayHeight = (float)Math.Round(value, 2); + RaisePropertyChanged(); + } } public override float MachineZ { get { + if (MachineSettings.MachineZ > 0) return MachineSettings.MachineZ; return PrinterModel switch { AnyCubicMachine.AnyCubicPhotonS => 165, @@ -1031,12 +1182,18 @@ namespace UVtools.Core.FileFormats AnyCubicMachine.AnyCubicPhotonUltra => 165, AnyCubicMachine.AnyCubicPhotonMono => 165, AnyCubicMachine.AnyCubicPhotonMonoSE => 160, + AnyCubicMachine.AnyCubicPhotonMono4K => 165, AnyCubicMachine.AnyCubicPhotonMonoX => 245, + AnyCubicMachine.AnyCubicPhotonMonoX6K => 245, AnyCubicMachine.AnyCubicPhotonMonoSQ => 200, _ => 0 }; } - set { } + set + { + MachineSettings.MachineZ = (float)Math.Round(value, 2); + RaisePropertyChanged(); + } } public override Enumerations.FlipDirection DisplayMirror @@ -1103,38 +1260,189 @@ namespace UVtools.Core.FileFormats set => base.ExposureTime = HeaderSettings.ExposureTime = (float) Math.Round(value, 2); } - public override float BottomLiftHeight => LiftHeight; + public override float BottomLiftHeight + { + get + { + if (FileMarkSettings.Version >= VERSION_516) return ExtraSettings.BottomLiftHeight1; + return base.BottomLiftHeight > 0 ? base.BottomLiftHeight : FirstLayer?.LiftHeight ?? 0; + } + set + { + value = (float)Math.Round(value, 2); + ExtraSettings.BottomLiftHeight1 = value; + if (FileMarkSettings.Version >= VERSION_516) + { + base.BottomLiftHeight = (float)Math.Round(value + ExtraSettings.BottomLiftHeight2, 2); + foreach (var layer in this) // Fix layer value + { + if (!layer.IsBottomLayer) continue; + layer.LiftHeight = base.BottomLiftHeight; + } + } + else base.BottomLiftHeight = value; + } + } - public override float LiftHeight + public override float BottomLiftSpeed { - get => HeaderSettings.LiftHeight; - set => base.LiftHeight = HeaderSettings.LiftHeight = (float) Math.Round(value, 2); + get + { + if (FileMarkSettings.Version >= VERSION_516) return (float)Math.Round(ExtraSettings.BottomLiftSpeed1 * 60, 2); + return base.BottomLiftSpeed > 0 ? base.BottomLiftSpeed : FirstLayer?.LiftSpeed ?? 0; + } + set + { + value = (float)Math.Round(value, 2); + ExtraSettings.BottomLiftSpeed1 = (float)Math.Round(value / 60, 2); + base.BottomLiftSpeed = value; + } } - public override float BottomLiftSpeed => LiftSpeed; + public override float LiftHeight + { + get + { + if (FileMarkSettings.Version >= VERSION_516) return ExtraSettings.LiftHeight1; + return HeaderSettings.LiftHeight; + } + set + { + value = (float)Math.Round(value, 2); + ExtraSettings.LiftHeight1 = value; + if (FileMarkSettings.Version >= VERSION_516) + { + base.LiftHeight = HeaderSettings.LiftHeight = (float)Math.Round(value + ExtraSettings.LiftHeight2, 2); + foreach (var layer in this) // Fix layer value + { + if(!layer.IsNormalLayer) continue; + layer.LiftHeight = base.LiftHeight; + } + } + else base.LiftHeight = value; + } + } public override float LiftSpeed { - get => (float)Math.Round(HeaderSettings.LiftSpeed * 60, 2); + get + { + if (FileMarkSettings.Version >= VERSION_516) return (float)Math.Round(ExtraSettings.LiftSpeed1 * 60, 2); + return (float)Math.Round(HeaderSettings.LiftSpeed * 60, 2); + } set { - HeaderSettings.LiftSpeed = (float) Math.Round(value / 60, 2); + value = (float)Math.Round(value, 2); + HeaderSettings.LiftSpeed = ExtraSettings.LiftSpeed1 = (float)Math.Round(value / 60, 2); base.LiftSpeed = value; } } - public override float BottomRetractSpeed => RetractSpeed; + public override float BottomLiftHeight2 + { + get => FileMarkSettings.Version >= VERSION_516 ? ExtraSettings.BottomLiftHeight2 : 0; + set + { + if (FileMarkSettings.Version < VERSION_516) return; + var bottomLiftHeight = BottomLiftHeight; + ExtraSettings.BottomLiftHeight2 = (float)Math.Round(value, 2); + BottomLiftHeight = bottomLiftHeight; + base.BottomLiftHeight2 = ExtraSettings.BottomLiftHeight2; + } + } + + public override float BottomLiftSpeed2 + { + get => FileMarkSettings.Version >= VERSION_516 ? (float)Math.Round(ExtraSettings.BottomLiftSpeed2 * 60, 2) : 0; + set + { + if (FileMarkSettings.Version < VERSION_516) return; + value = (float)Math.Round(value, 2); + ExtraSettings.BottomLiftSpeed2 = (float)Math.Round(value / 60, 2); + base.BottomLiftSpeed2 = value; + } + } + + public override float LiftHeight2 + { + get => FileMarkSettings.Version >= VERSION_516 ? ExtraSettings.LiftHeight2 : 0; + set + { + if (FileMarkSettings.Version < VERSION_516) return; + var liftHeight = LiftHeight; + ExtraSettings.LiftHeight2 = (float)Math.Round(value, 2); + LiftHeight = liftHeight; + base.BottomLiftHeight2 = ExtraSettings.LiftHeight2; + } + } + + public override float LiftSpeed2 + { + get => FileMarkSettings.Version >= VERSION_516 ? (float)Math.Round(ExtraSettings.LiftSpeed2 * 60, 2) : 0; + set + { + if (FileMarkSettings.Version < VERSION_516) return; + base.LiftSpeed2 = ExtraSettings.LiftSpeed2 = (float)Math.Round(value / 60, 2); + } + } + + public override float BottomRetractSpeed + { + get + { + if (FileMarkSettings.Version >= VERSION_516) return (float)Math.Round(ExtraSettings.BottomRetractSpeed1 * 60, 2); + return RetractSpeed; + } + set + { + value = (float)Math.Round(value, 2); + + if (FileMarkSettings.Version >= VERSION_516) + { + ExtraSettings.BottomRetractSpeed1 = (float)Math.Round(value / 60, 2); + } + else + { + RetractSpeed = value; + } + } + } public override float RetractSpeed { get => (float)Math.Round(HeaderSettings.RetractSpeed * 60, 2); set { - HeaderSettings.RetractSpeed = (float) Math.Round(value / 60, 2); + value = (float)Math.Round(value, 2); + ExtraSettings.RetractSpeed1 = HeaderSettings.RetractSpeed = (float) Math.Round(value / 60, 2); base.RetractSpeed = value; } } + public override float BottomRetractSpeed2 + { + get => FileMarkSettings.Version >= VERSION_516 ? (float)Math.Round(ExtraSettings.BottomRetractSpeed2 * 60, 2) : 0; + set + { + if (FileMarkSettings.Version < VERSION_516) return; + value = (float)Math.Round(value, 2); + ExtraSettings.BottomRetractSpeed2 = (float)Math.Round(value / 60, 2); + base.BottomRetractSpeed2 = value; + } + } + + public override float RetractSpeed2 + { + get => FileMarkSettings.Version >= VERSION_516 ? (float)Math.Round(ExtraSettings.RetractSpeed2 * 60, 2) : 0; + set + { + if (FileMarkSettings.Version < VERSION_516) return; + value = (float)Math.Round(value, 2); + ExtraSettings.RetractSpeed2 = (float)Math.Round(value / 60, 2); + base.RetractSpeed2 = value; + } + } + public override float PrintTime { get => base.PrintTime; @@ -1171,24 +1479,28 @@ namespace UVtools.Core.FileFormats { get { + if (string.IsNullOrWhiteSpace(MachineSettings.MachineName)) return MachineSettings.MachineName; return PrinterModel switch { - AnyCubicMachine.AnyCubicPhotonS => "AnyCubic Photon S", - AnyCubicMachine.AnyCubicPhotonZero => "AnyCubic Photon Zero", - AnyCubicMachine.AnyCubicPhotonX => "AnyCubic Photon X", - AnyCubicMachine.AnyCubicPhotonUltra => "AnyCubic Photon Ultra", - AnyCubicMachine.AnyCubicPhotonMono => "AnyCubic Photon Mono", - AnyCubicMachine.AnyCubicPhotonMonoSE => "AnyCubic Photon Mono SE", - AnyCubicMachine.AnyCubicPhotonMonoX => "AnyCubic Photon Mono X", - AnyCubicMachine.AnyCubicPhotonMonoSQ => "AnyCubic Photon Mono SQ", + AnyCubicMachine.AnyCubicPhotonS => "Photon S", + AnyCubicMachine.AnyCubicPhotonZero => "Photon Zero", + AnyCubicMachine.AnyCubicPhotonX => "Photon X", + AnyCubicMachine.AnyCubicPhotonUltra => "Photon Ultra", + AnyCubicMachine.AnyCubicPhotonMono => "Photon Mono", + AnyCubicMachine.AnyCubicPhotonMonoSE => "Photon Mono SE", + AnyCubicMachine.AnyCubicPhotonMono4K => "Photon Mono 4K", + AnyCubicMachine.AnyCubicPhotonMonoX => "Photon Mono X", + AnyCubicMachine.AnyCubicPhotonMonoX6K => "Photon Mono X 6K", + AnyCubicMachine.AnyCubicPhotonMonoSQ => "Photon Mono SQ", _ => base.MachineName }; } + set => base.MachineName = MachineSettings.MachineName = value; } - public override object[] Configs => new object[] { FileMarkSettings, HeaderSettings, PreviewSettings, LayersDefinition }; + public override object[] Configs => new object[] { FileMarkSettings, HeaderSettings, PreviewSettings, LayersDefinition, ExtraSettings, MachineSettings }; - public LayerRleFormat LayerFormat => + public LayerRleFormat LayerImageFormat => FileEndsWith(".pws") ? LayerRleFormat.PWS : LayerRleFormat.PW0; @@ -1227,11 +1539,21 @@ namespace UVtools.Core.FileFormats return AnyCubicMachine.AnyCubicPhotonMonoSE; } + if (FileEndsWith(".pwma")) + { + return AnyCubicMachine.AnyCubicPhotonMono4K; + } + if (FileEndsWith(".pwmx")) { return AnyCubicMachine.AnyCubicPhotonMonoX; } + if (FileEndsWith(".pwmb")) + { + return AnyCubicMachine.AnyCubicPhotonMonoX6K; + } + if (FileEndsWith(".pmsq")) { return AnyCubicMachine.AnyCubicPhotonMonoSQ; @@ -1258,20 +1580,18 @@ namespace UVtools.Core.FileFormats protected override void EncodeInternally(OperationProgress progress) { + /*if (FileMarkSettings.AreaNum == 0) + {*/ + FileMarkSettings.AreaNum = FileMarkSettings.Version switch + { + VERSION_1 => 4, + VERSION_515 => 5, + VERSION_516 => 8, + _ => 4 + }; + //} HeaderSettings.PixelSizeUm = PixelSizeMicronsMax; - - /*PrinterModel switch - { - AnyCubicMachine.AnyCubicPhotonS => 47.25f, - AnyCubicMachine.AnyCubicPhotonZero => 115.5f, - AnyCubicMachine.AnyCubicPhotonX => 75, - AnyCubicMachine.AnyCubicPhotonUltra => 80, - AnyCubicMachine.AnyCubicPhotonMono => 51, - AnyCubicMachine.AnyCubicPhotonMonoSE => 51, - AnyCubicMachine.AnyCubicPhotonMonoX => 50, - AnyCubicMachine.AnyCubicPhotonMonoSQ => 50, - _ => 47.25f - };*/ + MachineSettings.LayerImageFormat = $"{LayerImageFormat.ToString().ToLower()}Img"; HeaderSettings.PerLayerOverride = (byte)(LayerManager.AllLayersAreUsingGlobalParameters ? 0 : 1); @@ -1280,6 +1600,10 @@ namespace UVtools.Core.FileFormats using var outputFile = new FileStream(FileFullPath, FileMode.Create, FileAccess.Write); outputFile.Seek((int)FileMarkSettings.HeaderAddress, SeekOrigin.Begin); Helpers.SerializeWriteFileStream(outputFile, HeaderSettings); + if (FileMarkSettings.Version >= VERSION_516) + { + outputFile.Seek(4, SeekOrigin.Current); // Extra padding + } if (CreatedThumbnailsCount > 0) { @@ -1294,12 +1618,38 @@ namespace UVtools.Core.FileFormats FileMarkSettings.PreviewEndAddress = (uint)outputFile.Position; } + if (FileMarkSettings.Version >= VERSION_515) + { + foreach (var uint32 in ReservedUintsAfterPreview) + { + outputFile.WriteUIntLittleEndian(uint32); + } + } + progress.Reset(OperationProgress.StatusEncodeLayers, LayerCount); FileMarkSettings.LayerDefinitionAddress = (uint)outputFile.Position; LayersDefinition = new LayerDefinition(LayerCount); Helpers.SerializeWriteFileStream(outputFile, LayersDefinition); uint layerDefOffset = (uint)outputFile.Position; - uint layerRleOffset = FileMarkSettings.LayerImageAddress = (uint)(layerDefOffset + Helpers.Serializer.SizeOf(new LayerDef()) * LayerCount); + uint layerRleOffset = (uint)(layerDefOffset + Helpers.Serializer.SizeOf(new LayerDef()) * LayerCount); + + if (FileMarkSettings.Version >= VERSION_516) + { + outputFile.Seek(layerRleOffset, SeekOrigin.Begin); + FileMarkSettings.ExtraAddress = layerRleOffset; + Helpers.SerializeWriteFileStream(outputFile, ExtraSettings); + FileMarkSettings.MachineAddress = (uint)outputFile.Position; + Helpers.SerializeWriteFileStream(outputFile, MachineSettings); + layerRleOffset = (uint)outputFile.Position; + outputFile.Seek(layerDefOffset, SeekOrigin.Begin); + } + else if (FileMarkSettings.Version == VERSION_515) + { + FileMarkSettings.ExtraAddress = layerRleOffset; + } + + FileMarkSettings.LayerImageAddress = layerRleOffset; + var layersHash = new Dictionary(); foreach (var batch in BatchLayersIndexes()) @@ -1362,18 +1712,22 @@ namespace UVtools.Core.FileFormats $"Invalid Filemark {FileMarkSettings.Mark}, expected {FileMark.SectionMarkFile}", FileFullPath); } - if (FileMarkSettings.Version is not VERSION_1 and not VERSION_515) + if (FileMarkSettings.Version is not VERSION_1 and not VERSION_515 and not VERSION_516) { - throw new FileLoadException($"Invalid Version {FileMarkSettings.Version}, expected {VERSION_1} or {VERSION_515}", FileFullPath); + throw new FileLoadException($"Invalid Version {FileMarkSettings.Version}, expected {VERSION_1} or {VERSION_515} or {VERSION_516}", FileFullPath); } inputFile.Seek(FileMarkSettings.HeaderAddress, SeekOrigin.Begin); HeaderSettings = Helpers.Deserialize
(inputFile); + if (FileMarkSettings.Version >= VERSION_516) + { + inputFile.Seek(4, SeekOrigin.Current); // Extra padding + } Debug.Write("Header -> "); Debug.WriteLine(HeaderSettings); - HeaderSettings.Validate(); + HeaderSettings.Validate(FileMarkSettings.Version >= VERSION_516 ? 4 : 0); if (FileMarkSettings.PreviewAddress > 0) { @@ -1393,6 +1747,24 @@ namespace UVtools.Core.FileFormats PreviewSettings.Data = null; } + if (FileMarkSettings.Version >= VERSION_516 && FileMarkSettings.ExtraAddress > 0) + { + inputFile.Seek(FileMarkSettings.ExtraAddress, SeekOrigin.Begin); + ExtraSettings = Helpers.Deserialize(inputFile); + ExtraSettings.Validate(); + Debug.Write("Extra -> "); + Debug.WriteLine(ExtraSettings); + } + + if (FileMarkSettings.Version >= VERSION_516 && FileMarkSettings.MachineAddress > 0) + { + inputFile.Seek(FileMarkSettings.MachineAddress, SeekOrigin.Begin); + MachineSettings = Helpers.Deserialize(inputFile); + MachineSettings.Validate(); + Debug.Write("Machine -> "); + Debug.WriteLine(MachineSettings); + } + inputFile.Seek(FileMarkSettings.LayerDefinitionAddress, SeekOrigin.Begin); LayersDefinition = Helpers.Deserialize(inputFile); @@ -1403,7 +1775,7 @@ namespace UVtools.Core.FileFormats LayersDefinition.Layers = new LayerDef[LayerCount]; LayersDefinition.Validate(); - + progress.Reset(OperationProgress.StatusDecodeLayers, LayerCount); foreach (var batch in BatchLayersIndexes()) { @@ -1458,6 +1830,17 @@ namespace UVtools.Core.FileFormats outputFile.Seek(FileMarkSettings.HeaderAddress, SeekOrigin.Begin); Helpers.SerializeWriteFileStream(outputFile, HeaderSettings); + if (FileMarkSettings.ExtraAddress > 0) + { + outputFile.Seek(FileMarkSettings.ExtraAddress, SeekOrigin.Begin); + Helpers.SerializeWriteFileStream(outputFile, ExtraSettings); + } + + if (FileMarkSettings.MachineAddress > 0) + { + outputFile.Seek(FileMarkSettings.MachineAddress, SeekOrigin.Begin); + Helpers.SerializeWriteFileStream(outputFile, MachineSettings); + } outputFile.Seek(FileMarkSettings.LayerDefinitionAddress + Helpers.Serializer.SizeOf(LayersDefinition), SeekOrigin.Begin); for (uint layerIndex = 0; layerIndex < LayerCount; layerIndex++) diff --git a/UVtools.Core/UVtools.Core.csproj b/UVtools.Core/UVtools.Core.csproj index 949e014..cdab473 100644 --- a/UVtools.Core/UVtools.Core.csproj +++ b/UVtools.Core/UVtools.Core.csproj @@ -10,7 +10,7 @@ https://github.com/sn4k3/UVtools https://github.com/sn4k3/UVtools MSLA/DLP, file analysis, calibration, repair, conversion and manipulation - 2.25.3 + 2.26.0 Copyright © 2020 PTRTECH UVtools.png AnyCPU;x64 diff --git a/UVtools.InstallerMM/UVtools.InstallerMM.wxs b/UVtools.InstallerMM/UVtools.InstallerMM.wxs index e3352b0..f935d27 100644 --- a/UVtools.InstallerMM/UVtools.InstallerMM.wxs +++ b/UVtools.InstallerMM/UVtools.InstallerMM.wxs @@ -885,12 +885,18 @@ + + + + + + diff --git a/UVtools.Powershell/Erode-Bottom.ps1 b/UVtools.Powershell/Erode-Bottom.ps1 index 84bce80..527b8aa 100644 --- a/UVtools.Powershell/Erode-Bottom.ps1 +++ b/UVtools.Powershell/Erode-Bottom.ps1 @@ -78,7 +78,7 @@ $inputFile = read-host "Enter input file" $inputFile = $null } else { - $slicerFile = [UVtools.Core.FileFormats.FileFormat]::FindByExtension($inputFile, $true, $true) + $slicerFile = [UVtools.Core.FileFormats.FileFormat]::FindByExtensionOrFilePath($inputFile, $true) if(!$slicerFile){ Write-host "Invalid file format, re-enter." $inputFile = $null diff --git a/UVtools.Powershell/List-Layers.ps1 b/UVtools.Powershell/List-Layers.ps1 index 1eb5cee..4aef1ee 100644 --- a/UVtools.Powershell/List-Layers.ps1 +++ b/UVtools.Powershell/List-Layers.ps1 @@ -78,7 +78,7 @@ $inputFile = read-host "Enter input file" $inputFile = $null } else { - $slicerFile = [UVtools.Core.FileFormats.FileFormat]::FindByExtension($inputFile, $true, $true) + $slicerFile = [UVtools.Core.FileFormats.FileFormat]::FindByExtensionOrFilePath($inputFile, $true) if(!$slicerFile){ Write-host "Invalid file format, re-enter." $inputFile = $null diff --git a/UVtools.Powershell/README.md b/UVtools.Powershell/README.md index 0659626..2867f60 100644 --- a/UVtools.Powershell/README.md +++ b/UVtools.Powershell/README.md @@ -46,12 +46,12 @@ Take **[Erode-Bottom.ps1](https://github.com/sn4k3/UVtools/blob/master/UVtools.S * [Core - Source code](https://github.com/sn4k3/UVtools/tree/master/UVtools.Core) -* [IFileFormat.cs - File format functions & variables](https://github.com/sn4k3/UVtools/blob/master/UVtools.Core/FileFormats/IFileFormat.cs) +* [FileFormat.cs - File format functions & variables](https://github.com/sn4k3/UVtools/blob/master/UVtools.Core/FileFormats/FileFormat.cs) * How to load file: ```Powershell # Find a file format given a file path, $true = is file path, $true = Create a new instance # Returns null if file is invalid - $slicerFile = [UVtools.Core.FileFormats.FileFormat]::FindByExtension($inputFile, $true, $true) + $slicerFile = [UVtools.Core.FileFormats.FileFormat]::FindByExtensionOrFilePath($inputFile, $true) if(!$slicerFile){ return } # Invalid file, exit $slicerFile.Decode($inputFile) ``` diff --git a/UVtools.WPF/App.axaml.cs b/UVtools.WPF/App.axaml.cs index 54e4889..5ab32f6 100644 --- a/UVtools.WPF/App.axaml.cs +++ b/UVtools.WPF/App.axaml.cs @@ -150,24 +150,35 @@ namespace UVtools.WPF public static string ApplicationPath => Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); - public static string GetPrusaSlicerDirectory() + public static string GetPrusaSlicerDirectory(bool isSuperSlicer = false) { + var slicerFolder = isSuperSlicer ? "SuperSlicer" : "PrusaSlicer"; if (OperatingSystem.IsWindows()) { - return $"{Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)}{Path.DirectorySeparatorChar}PrusaSlicer"; + return Path.Combine( + Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), + slicerFolder); } if (OperatingSystem.IsLinux()) { - var folder1 = $"{Environment.GetFolderPath(Environment.SpecialFolder.UserProfile)}{Path.DirectorySeparatorChar}.config{Path.DirectorySeparatorChar}PrusaSlicer"; + var folder1 = Path.Combine( + Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), + ".config", + slicerFolder); if (Directory.Exists(folder1)) return folder1; - return $"{Environment.GetFolderPath(Environment.SpecialFolder.UserProfile)}{Path.DirectorySeparatorChar}.PrusaSlicer"; + return Path.Combine( + Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), + $".{slicerFolder}"); } if (OperatingSystem.IsMacOS()) { - return string.Format("{0}{1}Library{1}Application Support{1}PrusaSlicer", - Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), Path.DirectorySeparatorChar); + return Path.Combine( + Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), + "Library", + "Application Support", + slicerFolder); } return null; diff --git a/UVtools.WPF/Assets/Icons/PrusaSlicer-32.png b/UVtools.WPF/Assets/Icons/PrusaSlicer-32.png new file mode 100644 index 0000000..64cd61d Binary files /dev/null and b/UVtools.WPF/Assets/Icons/PrusaSlicer-32.png differ diff --git a/UVtools.WPF/Assets/Icons/SuperSlicer-32.png b/UVtools.WPF/Assets/Icons/SuperSlicer-32.png new file mode 100644 index 0000000..eae951a Binary files /dev/null and b/UVtools.WPF/Assets/Icons/SuperSlicer-32.png differ diff --git a/UVtools.WPF/MainWindow.axaml.cs b/UVtools.WPF/MainWindow.axaml.cs index 182ee9c..444d8ba 100644 --- a/UVtools.WPF/MainWindow.axaml.cs +++ b/UVtools.WPF/MainWindow.axaml.cs @@ -1386,16 +1386,21 @@ namespace UVtools.WPF public async void MenuHelpInstallProfilesClicked() { - var PEFolder = App.GetPrusaSlicerDirectory(); - if (string.IsNullOrEmpty(PEFolder) || !Directory.Exists(PEFolder)) - { - if(await this.MessageBoxQuestion( - "Unable to detect PrusaSlicer on your system, please ensure you have latest version installed.\n" + - $"Was looking on: {PEFolder}\n\n" + - "Click 'Yes' to open the PrusaSlicer webpage for download\n" + - "Click 'No' to dismiss", - "Unable to detect PrusaSlicer") == ButtonResult.Yes) SystemAware.OpenBrowser("https://www.prusa3d.com/prusaslicer/"); - return; + var PSFolder = App.GetPrusaSlicerDirectory(); + if (string.IsNullOrEmpty(PSFolder) || !Directory.Exists(PSFolder)) + { + var SSFolder = App.GetPrusaSlicerDirectory(true); + if (string.IsNullOrEmpty(SSFolder) || !Directory.Exists(SSFolder)) + { + if (await this.MessageBoxQuestion( + "Unable to detect PrusaSlicer nor SuperSlicer on your system, please ensure you have latest version installed.\n" + + $"Was looking on: {PSFolder} and {SSFolder}\n\n" + + "Click 'Yes' to open the PrusaSlicer webpage for download\n" + + "Click 'No' to dismiss", + "Unable to detect PrusaSlicer") == ButtonResult.Yes) + SystemAware.OpenBrowser("https://www.prusa3d.com/prusaslicer/"); + return; + } } await new PrusaSlicerManagerWindow().ShowDialog(this); } diff --git a/UVtools.WPF/Structures/PEProfileFolder.cs b/UVtools.WPF/Structures/PEProfileFolder.cs deleted file mode 100644 index 2c6a410..0000000 --- a/UVtools.WPF/Structures/PEProfileFolder.cs +++ /dev/null @@ -1,147 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.IO; -using System.Linq; -using System.Text; -using Avalonia.Controls; -using Avalonia.Media; -using UVtools.Core.Objects; - -namespace UVtools.WPF.Structures -{ - public class PEProfileFolder : BindableBase - { - private RangeObservableCollection _items = new (); - private ushort _installed; - private ushort _updates; - - public enum FolderType - { - Print, - Printer - } - - public FolderType Type { get; } - - public string SourcePath { get; } - public string TargetPath { get; } - - public RangeObservableCollection Items - { - get => _items; - set => RaiseAndSetIfChanged(ref _items, value); - } - - public ushort Installed - { - get => _installed; - set => RaiseAndSetIfChanged(ref _installed, value); - } - - public ushort Updates - { - get => _updates; - set => RaiseAndSetIfChanged(ref _updates, value); - } - - public string SelectedFiles - { - get - { - StringBuilder sb = new(); - foreach (CheckBox item in Items) - { - if (!item.IsChecked.HasValue || !item.IsChecked.Value) continue; - sb.AppendLine(item.Content.ToString()); - } - - return sb.ToString(); - } - } - - public PEProfileFolder(FolderType type) - { - Type = type; - - switch (type) - { - case FolderType.Print: - SourcePath = string.Format("{0}{1}Assets{1}PrusaSlicer{1}sla_print", - App.ApplicationPath, Path.DirectorySeparatorChar); - TargetPath = $"{App.GetPrusaSlicerDirectory()}{Path.DirectorySeparatorChar}sla_print"; - break; - case FolderType.Printer: - SourcePath = string.Format("{0}{1}Assets{1}PrusaSlicer{1}printer", - App.ApplicationPath, Path.DirectorySeparatorChar); - TargetPath = $"{App.GetPrusaSlicerDirectory()}{Path.DirectorySeparatorChar}printer"; - break; - } - - Reset(); - } - - public void Reset() - { - Items.Clear(); - Updates = 0; - Installed = 0; - if (!Directory.Exists(SourcePath)) return; - DirectoryInfo di = new(SourcePath); - var files = di.GetFiles("*.ini"); - if (files.Length == 0) return; - - bool folderExists = Directory.Exists(TargetPath); - - for (int i = 0; i < files.Length; i++) - { - Items.Add(new CheckBox - { - Content = Path.GetFileNameWithoutExtension(files[i].Name), - Tag = files[i] - }); - - if (folderExists) - { - var targetFile = $"{TargetPath}{Path.DirectorySeparatorChar}{files[i].Name}"; - FileInfo targetFileInfo = new(targetFile); - if (targetFileInfo.Exists) - { - Installed++; - if (targetFileInfo.Length != files[i].Length || !StaticObjects.GetHashSha256(targetFileInfo.FullName).SequenceEqual(StaticObjects.GetHashSha256(files[i].FullName))) - { - Items[i].Foreground = Brushes.Red; - Items[i].IsChecked = true; - Updates++; - } - else - { - Items[i].Foreground = Brushes.Green; - Items[i].IsEnabled = false; - } - } - else - { - Updates++; - } - } - } - } - - public void SelectNone() - { - foreach (var checkBox in Items) - { - checkBox.IsChecked = false; - } - } - - public void SelectAll() - { - foreach (var checkBox in Items) - { - checkBox.IsChecked = checkBox.IsEnabled; - } - } - } -} diff --git a/UVtools.WPF/Structures/PSProfileFolder.cs b/UVtools.WPF/Structures/PSProfileFolder.cs new file mode 100644 index 0000000..751640d --- /dev/null +++ b/UVtools.WPF/Structures/PSProfileFolder.cs @@ -0,0 +1,148 @@ +using System; +using System.Collections.ObjectModel; +using System.IO; +using System.Linq; +using System.Text; +using Avalonia.Controls; +using Avalonia.Media; +using UVtools.Core.Objects; + +namespace UVtools.WPF.Structures +{ + public class PSProfileFolder : BindableBase + { + public static string AssetsPrusaSlicer => Path.Combine(App.ApplicationPath, "Assets", "PrusaSlicer"); + private RangeObservableCollection _items = new (); + private ushort _installed; + private ushort _updates; + + public enum FolderType + { + Print, + Printer + } + + public FolderType Type { get; } + + public bool IsSuperSlicer { get; } + + public string SourcePath { get; } + public string TargetPath { get; } + + public RangeObservableCollection Items + { + get => _items; + set => RaiseAndSetIfChanged(ref _items, value); + } + + public ushort Installed + { + get => _installed; + set => RaiseAndSetIfChanged(ref _installed, value); + } + + public ushort Updates + { + get => _updates; + set => RaiseAndSetIfChanged(ref _updates, value); + } + + public string SelectedFiles + { + get + { + StringBuilder sb = new(); + foreach (var item in Items) + { + if (!item.IsChecked.HasValue || !item.IsChecked.Value) continue; + sb.AppendLine(item.Content.ToString()); + } + + return sb.ToString(); + } + } + + public PSProfileFolder(FolderType type, bool isSuperSlicer = false) + { + Type = type; + IsSuperSlicer = isSuperSlicer; + + switch (type) + { + case FolderType.Print: + SourcePath = Path.Combine(AssetsPrusaSlicer, "sla_print"); + TargetPath = Path.Combine(App.GetPrusaSlicerDirectory(isSuperSlicer), "sla_print"); + break; + case FolderType.Printer: + SourcePath = Path.Combine(AssetsPrusaSlicer, "printer"); + TargetPath = Path.Combine(App.GetPrusaSlicerDirectory(isSuperSlicer), "printer"); + break; + default: + throw new ArgumentOutOfRangeException(nameof(type), type, null); + } + + Reset(); + } + + public void Reset() + { + Items.Clear(); + Updates = 0; + Installed = 0; + if (!Directory.Exists(SourcePath)) return; + DirectoryInfo di = new(SourcePath); + var files = di.GetFiles("*.ini"); + if (files.Length == 0) return; + + bool folderExists = Directory.Exists(TargetPath); + + for (int i = 0; i < files.Length; i++) + { + Items.Add(new CheckBox + { + Content = Path.GetFileNameWithoutExtension(files[i].Name), + Tag = files[i] + }); + + if (!folderExists) continue; + var targetFile = $"{TargetPath}{Path.DirectorySeparatorChar}{files[i].Name}"; + FileInfo targetFileInfo = new(targetFile); + if (targetFileInfo.Exists) + { + Installed++; + if (targetFileInfo.Length != files[i].Length || !StaticObjects.GetHashSha256(targetFileInfo.FullName).SequenceEqual(StaticObjects.GetHashSha256(files[i].FullName))) + { + Items[i].Foreground = Brushes.Red; + Items[i].IsChecked = true; + Updates++; + } + else + { + Items[i].Foreground = Brushes.Green; + Items[i].IsEnabled = false; + } + } + else + { + Updates++; + } + } + } + + public void SelectNone() + { + foreach (var checkBox in Items) + { + checkBox.IsChecked = false; + } + } + + public void SelectAll() + { + foreach (var checkBox in Items) + { + checkBox.IsChecked = checkBox.IsEnabled; + } + } + } +} diff --git a/UVtools.WPF/UVtools.WPF.csproj b/UVtools.WPF/UVtools.WPF.csproj index e04e08c..b9b0c31 100644 --- a/UVtools.WPF/UVtools.WPF.csproj +++ b/UVtools.WPF/UVtools.WPF.csproj @@ -12,7 +12,7 @@ LICENSE https://github.com/sn4k3/UVtools Git - 2.25.3 + 2.26.0 AnyCPU;x64 diff --git a/UVtools.WPF/Windows/PrusaSlicerManagerWindow.axaml b/UVtools.WPF/Windows/PrusaSlicerManagerWindow.axaml index cb8880c..0d5ec67 100644 --- a/UVtools.WPF/Windows/PrusaSlicerManagerWindow.axaml +++ b/UVtools.WPF/Windows/PrusaSlicerManagerWindow.axaml @@ -133,116 +133,234 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/UVtools.WPF/Windows/PrusaSlicerManagerWindow.axaml.cs b/UVtools.WPF/Windows/PrusaSlicerManagerWindow.axaml.cs index 4b30c9c..29e09ac 100644 --- a/UVtools.WPF/Windows/PrusaSlicerManagerWindow.axaml.cs +++ b/UVtools.WPF/Windows/PrusaSlicerManagerWindow.axaml.cs @@ -1,6 +1,5 @@ using System; using System.IO; -using Avalonia; using Avalonia.Controls; using Avalonia.Markup.Xaml; using MessageBox.Avalonia.Enums; @@ -12,17 +11,38 @@ namespace UVtools.WPF.Windows { public class PrusaSlicerManagerWindow : WindowEx { - public PEProfileFolder[] Profiles { get;} + public PSProfileFolder[] PrusaSlicerProfiles { get; } = { + new (PSProfileFolder.FolderType.Print), + new (PSProfileFolder.FolderType.Printer), + }; + public PSProfileFolder[] SuperSlicerProfiles { get; } = { + new (PSProfileFolder.FolderType.Print, true), + new (PSProfileFolder.FolderType.Printer, true), + }; + + public bool HavePrusaSlicer + { + get + { + var PSFolder = App.GetPrusaSlicerDirectory(); + return !string.IsNullOrEmpty(PSFolder) && Directory.Exists(PSFolder); + } + } + + public bool HaveSuperSlicer + { + get + { + var SSFolder = App.GetPrusaSlicerDirectory(true); + return !string.IsNullOrEmpty(SSFolder) && Directory.Exists(SSFolder); + } + } + + public int TabSlicerSelectedIndex { get; set; } public PrusaSlicerManagerWindow() { InitializeComponent(); - Profiles = new[] - { - new PEProfileFolder(PEProfileFolder.FolderType.Print), - new PEProfileFolder(PEProfileFolder.FolderType.Printer), - }; - DataContext = this; } @@ -33,7 +53,12 @@ namespace UVtools.WPF.Windows public void RefreshProfiles() { - foreach (var profile in Profiles) + foreach (var profile in PrusaSlicerProfiles) + { + profile.Reset(); + } + + foreach (var profile in SuperSlicerProfiles) { profile.Reset(); } @@ -41,8 +66,10 @@ namespace UVtools.WPF.Windows public async void InstallProfiles() { - var printProfiles = Profiles[0].SelectedFiles; - var printerProfiles = Profiles[1].SelectedFiles; + bool isSuperSlicer = TabSlicerSelectedIndex == 1; + var printProfiles = isSuperSlicer ? SuperSlicerProfiles[0].SelectedFiles : PrusaSlicerProfiles[0].SelectedFiles; + var printerProfiles = isSuperSlicer ? SuperSlicerProfiles[1].SelectedFiles : PrusaSlicerProfiles[1].SelectedFiles; + var slicerName = isSuperSlicer ? "SuperSlicer" : "PrusaSlicer"; if (string.IsNullOrEmpty(printProfiles) && string.IsNullOrEmpty(printerProfiles)) { @@ -51,40 +78,41 @@ namespace UVtools.WPF.Windows } if (await this.MessageBoxQuestion( - "This action will install and override the following profiles into PrusaSlicer:\n" + + $"This action will install and override the following profiles into {slicerName}:\n" + "---------- PRINT PROFILES ----------\n" + - Profiles[0].SelectedFiles + + printProfiles + "--------- PRINTER PROFILES ---------\n" + - Profiles[1].SelectedFiles + + printerProfiles + "---------------\n" + "Click 'Yes' to continue\n" + "Click 'No' to cancel this operation", - "Install printers into PrusaSlicer") != ButtonResult.Yes) return; + $"Install printers into {slicerName}") != ButtonResult.Yes) return; ushort count = 0; try { - foreach (var profile in Profiles) + foreach (var profile in isSuperSlicer ? SuperSlicerProfiles : PrusaSlicerProfiles) { - foreach (CheckBox item in profile.Items) + foreach (var item in profile.Items) { if (!item.IsChecked.HasValue || !item.IsChecked.Value) continue; var fi = item.Tag as FileInfo; - fi.CopyTo($"{profile.TargetPath}{Path.DirectorySeparatorChar}{fi.Name}", true); + if (fi is null) continue; + fi.CopyTo(Path.Combine(profile.TargetPath, fi.Name), true); count++; } } } catch (Exception exception) { - await this.MessageBoxError(exception.ToString(), "Unable to install the profiles"); + await this.MessageBoxError(exception.Message, "Unable to install the profiles"); return; } await this.MessageBoxInfo( - $"{count} profiles were installed.\nRestart PrusaSlicer and check if profiles are present.", + $"{count} profiles were installed.\nRestart {slicerName} and check if profiles are present.", "Operation completed"); RefreshProfiles(); -- cgit v1.2.3