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>2022-02-21 08:15:55 +0300
committerTiago Conceição <Tiago_caza@hotmail.com>2022-02-21 08:15:55 +0300
commit069c521d721c9b18ed264d1bbeba9b34af995aa0 (patch)
tree8571641235dc7b778c1fe856824827033c7f180f
parentef305b0abef8ce7484cff38d8ebcceeee59f6672 (diff)
v2.29.0v2.29.0
- **File formats:** - (Add) Transition layer count to the supported files and auto compute transition time on corresponding layers in software mode - (Add) `HaveTransitionLayers`, `TransitionLayersType`, `BottomLayers`, `NormalLayers`, `TransitionLayers`, `TsmcLayers` properties - (Add) Layer: `IsTransitionLayer` property - (Add) SL1: Keyword `TransitionLayerCount_xxx` - Sets the number of transition layers - (Improvement) CTB, PHZ, FDG: Implement the `ModifiedTimestampMinutes` field, it was the MysteriousId before as an unknown field - (Fix) CWS: Open in partial mode will cause an exception and prevent file from load - **CCode:** - (Add) Allow inverse lifts to work as an retract - (Fix) Parsing of WaitTimeAfterLift was incorrect when lacking a lift sequence - (Fix) Layers lacking an exposure time was defaulting to global time, now defaults to 0 - (Fix) Layers without a LED ON (M106) was setting `LightPWM` to the max value (255), now defaults to 0 - **Tools:** - **Timelapse:** - (Add) Information: Raise Layer count equivalence - (Add) Information: Additional lifts to be generated - (Add) Option: Ensure the last layer - If enabled, it will generate an obligatory layer to cover the last layer - (Improvement) Optimize lift for virtual layer mode, allowing set a slow and fast lift / retract by using another virtual layyer to emulate a lift - (Improvement) Allow to define slow and fast speed for virtual layer mode even if TSMC isn't supported - (Add) Fade exposure time: Setting 'Disable firmware transition layers' - Attempt to disable firmware strict transition layers in favor of this tool - (Add) Calibration tests: Attempt to auto disable the firmware transifiton layers - (Change) Edit print parameters: Allow set `BottomLiftHeight` and `LiftHeight` to 0mm - **UI:** - (Improvement) Disallow drop files into UI when is processing data / disabled and prevent crashing from that action - (Improvement) Information tab visibility and MinHeight for data grids - (Improvement) Hide/show GCode tab when necessary (dependent on file format) - (Improvement) The 'save as' will show the new file into 'Open recent' files - **PrusaSlicer printers:** - (Add) Elegoo Jupiter - (Add) EPAX X1 4KS - (Add) EPAX DX1 Pro - (Add) EPAX DX10 Pro 5K - (Add) EPAX DX10 Pro 8K - (Add) EPAX E10 8K - (Add) EPAX X133 6K
-rw-r--r--CHANGELOG.md38
-rw-r--r--PrusaSlicer/printer/EPAX DX1 PRO.ini41
-rw-r--r--PrusaSlicer/printer/EPAX DX10 Pro 5K.ini41
-rw-r--r--PrusaSlicer/printer/EPAX DX10 Pro 8K.ini41
-rw-r--r--PrusaSlicer/printer/EPAX E10 8K.ini41
-rw-r--r--PrusaSlicer/printer/EPAX X133 6K.ini41
-rw-r--r--PrusaSlicer/printer/Elegoo Jupiter.ini41
-rw-r--r--PrusaSlicer/printer/Epax X1 4KS.ini41
-rw-r--r--README.md1
-rw-r--r--Scripts/010 Editor/ctb.bt2
-rw-r--r--Scripts/010 Editor/fdg.bt127
-rw-r--r--Scripts/010 Editor/phz.bt127
-rw-r--r--Scripts/ImportPrusaSlicerData.bat118
-rw-r--r--Scripts/ImportPrusaSlicerData.ps110
-rw-r--r--UVtools.Core/Extensions/DateTimeExtensions.cs51
-rw-r--r--UVtools.Core/FileFormats/CTBEncryptedFile.cs11
-rw-r--r--UVtools.Core/FileFormats/CWSFile.cs2
-rw-r--r--UVtools.Core/FileFormats/ChituboxFile.cs49
-rw-r--r--UVtools.Core/FileFormats/FDGFile.cs9
-rw-r--r--UVtools.Core/FileFormats/FileFormat.cs194
-rw-r--r--UVtools.Core/FileFormats/GenericZIPFile.cs2
-rw-r--r--UVtools.Core/FileFormats/PHZFile.cs13
-rw-r--r--UVtools.Core/FileFormats/PhotonWorkshopFile.cs9
-rw-r--r--UVtools.Core/FileFormats/SL1File.cs11
-rw-r--r--UVtools.Core/GCode/GCodeBuilder.cs8
-rw-r--r--UVtools.Core/GCode/GCodeLayer.cs30
-rw-r--r--UVtools.Core/Layers/Layer.cs12
-rw-r--r--UVtools.Core/Layers/LayerManager.cs24
-rw-r--r--UVtools.Core/Objects/RangeObservableCollection.cs2
-rw-r--r--UVtools.Core/Operations/OperationCalibrateElephantFoot.cs1
-rw-r--r--UVtools.Core/Operations/OperationCalibrateExposureFinder.cs1
-rw-r--r--UVtools.Core/Operations/OperationCalibrateGrayscale.cs1
-rw-r--r--UVtools.Core/Operations/OperationCalibrateLiftHeight.cs1
-rw-r--r--UVtools.Core/Operations/OperationCalibrateTolerance.cs1
-rw-r--r--UVtools.Core/Operations/OperationCalibrateXYZAccuracy.cs1
-rw-r--r--UVtools.Core/Operations/OperationFadeExposureTime.cs18
-rw-r--r--UVtools.Core/Operations/OperationTimelapse.cs147
-rw-r--r--UVtools.Core/UVtools.Core.csproj4
-rw-r--r--UVtools.WPF/Controls/Tools/ToolFadeExposureTimeControl.axaml14
-rw-r--r--UVtools.WPF/Controls/Tools/ToolTimelapseControl.axaml319
-rw-r--r--UVtools.WPF/MainWindow.axaml384
-rw-r--r--UVtools.WPF/MainWindow.axaml.cs13
-rw-r--r--UVtools.WPF/UVtools.WPF.csproj2
43 files changed, 1489 insertions, 555 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 72c96dd..66823e9 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,43 @@
# Changelog
+## 21/02/2022 - v2.29.0
+
+- **File formats:**
+ - (Add) Transition layer count to the supported files and auto compute transition time on corresponding layers in software mode
+ - (Add) `HaveTransitionLayers`, `TransitionLayersType`, `BottomLayers`, `NormalLayers`, `TransitionLayers`, `TsmcLayers` properties
+ - (Add) Layer: `IsTransitionLayer` property
+ - (Add) SL1: Keyword `TransitionLayerCount_xxx` - Sets the number of transition layers
+ - (Improvement) CTB, PHZ, FDG: Implement the `ModifiedTimestampMinutes` field, it was the MysteriousId before as an unknown field
+ - (Fix) CWS: Open in partial mode will cause an exception and prevent file from load
+- **CCode:**
+ - (Add) Allow inverse lifts to work as an retract
+ - (Fix) Parsing of WaitTimeAfterLift was incorrect when lacking a lift sequence
+ - (Fix) Layers lacking an exposure time was defaulting to global time, now defaults to 0
+ - (Fix) Layers without a LED ON (M106) was setting `LightPWM` to the max value (255), now defaults to 0
+- **Tools:**
+ - **Timelapse:**
+ - (Add) Information: Raise Layer count equivalence
+ - (Add) Information: Additional lifts to be generated
+ - (Add) Option: Ensure the last layer - If enabled, it will generate an obligatory layer to cover the last layer
+ - (Improvement) Optimize lift for virtual layer mode, allowing set a slow and fast lift / retract by using another virtual layyer to emulate a lift
+ - (Improvement) Allow to define slow and fast speed for virtual layer mode even if TSMC isn't supported
+ - (Add) Fade exposure time: Setting 'Disable firmware transition layers' - Attempt to disable firmware strict transition layers in favor of this tool
+ - (Add) Calibration tests: Attempt to auto disable the firmware transifiton layers
+ - (Change) Edit print parameters: Allow set `BottomLiftHeight` and `LiftHeight` to 0mm
+- **UI:**
+ - (Improvement) Disallow drop files into UI when is processing data / disabled and prevent crashing from that action
+ - (Improvement) Information tab visibility and MinHeight for data grids
+ - (Improvement) Hide/show GCode tab when necessary (dependent on file format)
+ - (Improvement) The 'save as' will show the new file into 'Open recent' files
+- **PrusaSlicer printers:**
+ - (Add) Elegoo Jupiter
+ - (Add) EPAX X1 4KS
+ - (Add) EPAX DX1 Pro
+ - (Add) EPAX DX10 Pro 5K
+ - (Add) EPAX DX10 Pro 8K
+ - (Add) EPAX E10 8K
+ - (Add) EPAX X133 6K
+
## 15/02/2022 - v2.28.1
- (Add) File - Terminal: Inject C# code into UVtools with an interactive terminal
diff --git a/PrusaSlicer/printer/EPAX DX1 PRO.ini b/PrusaSlicer/printer/EPAX DX1 PRO.ini
new file mode 100644
index 0000000..b24bcf5
--- /dev/null
+++ b/PrusaSlicer/printer/EPAX DX1 PRO.ini
@@ -0,0 +1,41 @@
+# generated by PrusaSlicer 2.4.0+win64 on 2022-02-19 at 22:23:26 UTC
+absolute_correction = 0
+area_fill = 50
+bed_custom_model =
+bed_custom_texture =
+bed_shape = 0x0,143.43x0,143.43x89.6,0x89.6
+default_sla_material_profile = Prusa Orange Tough 0.05
+default_sla_print_profile = 0.05 Normal
+display_height = 89.6
+display_mirror_x = 1
+display_mirror_y = 0
+display_orientation = landscape
+display_pixels_x = 4098
+display_pixels_y = 2560
+display_width = 143.43
+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 = 155
+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_EPAX\nPRINTER_MODEL_DX1-PRO\nFILEFORMAT_ENCRYPTED.CTB\n\nSTART_CUSTOM_VALUES\nBottomWaitTimeBeforeCure_3\nWaitTimeBeforeCure_2.5\nBottomWaitTimeAfterCure_3\nWaitTimeAfterCure_1\nBottomLiftHeight_5\nLiftHeight_5\nBottomLiftSpeed_80\nLiftSpeed_100\nBottomWaitTimeAfterLift_0\nWaitTimeAfterLift_0\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
+relative_correction_x = 1
+relative_correction_y = 1
+relative_correction_z = 1
+slow_tilt_time = 8
+thumbnails = 400x400,800x480
diff --git a/PrusaSlicer/printer/EPAX DX10 Pro 5K.ini b/PrusaSlicer/printer/EPAX DX10 Pro 5K.ini
new file mode 100644
index 0000000..c4cf49c
--- /dev/null
+++ b/PrusaSlicer/printer/EPAX DX10 Pro 5K.ini
@@ -0,0 +1,41 @@
+# generated by PrusaSlicer 2.4.0+win64 on 2022-02-19 at 22:25:33 UTC
+absolute_correction = 0
+area_fill = 50
+bed_custom_model =
+bed_custom_texture =
+bed_shape = 0x0,221.4x0,221.4x129.6,0x129.6
+default_sla_material_profile = Prusa Orange Tough 0.05
+default_sla_print_profile = 0.05 Normal
+display_height = 129.6
+display_mirror_x = 1
+display_mirror_y = 0
+display_orientation = landscape
+display_pixels_x = 4920
+display_pixels_y = 2880
+display_width = 221.4
+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 = 120
+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_EPAX\nPRINTER_MODEL_DX10-PRO-5K\nFILEFORMAT_ENCRYPTED.CTB\n\nSTART_CUSTOM_VALUES\nBottomWaitTimeBeforeCure_3\nWaitTimeBeforeCure_2.5\nBottomWaitTimeAfterCure_3\nWaitTimeAfterCure_1\nBottomLiftHeight_7\nLiftHeight_7\nBottomLiftSpeed_80\nLiftSpeed_100\nBottomWaitTimeAfterLift_0\nWaitTimeAfterLift_0\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
+relative_correction_x = 1
+relative_correction_y = 1
+relative_correction_z = 1
+slow_tilt_time = 8
+thumbnails = 400x400,800x480
diff --git a/PrusaSlicer/printer/EPAX DX10 Pro 8K.ini b/PrusaSlicer/printer/EPAX DX10 Pro 8K.ini
new file mode 100644
index 0000000..4e33d44
--- /dev/null
+++ b/PrusaSlicer/printer/EPAX DX10 Pro 8K.ini
@@ -0,0 +1,41 @@
+# generated by PrusaSlicer 2.4.0+win64 on 2022-02-19 at 22:27:00 UTC
+absolute_correction = 0
+area_fill = 50
+bed_custom_model =
+bed_custom_texture =
+bed_shape = 0x0,218.88x0,218.88x123.12,0x123.12
+default_sla_material_profile = Prusa Orange Tough 0.05
+default_sla_print_profile = 0.05 Normal
+display_height = 123.12
+display_mirror_x = 1
+display_mirror_y = 0
+display_orientation = landscape
+display_pixels_x = 7680
+display_pixels_y = 4320
+display_width = 218.88
+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 = 120
+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_EPAX\nPRINTER_MODEL_DX10-PRO-8K\nFILEFORMAT_ENCRYPTED.CTB\n\nSTART_CUSTOM_VALUES\nBottomWaitTimeBeforeCure_3\nWaitTimeBeforeCure_2.5\nBottomWaitTimeAfterCure_3\nWaitTimeAfterCure_1\nBottomLiftHeight_7\nLiftHeight_7\nBottomLiftSpeed_80\nLiftSpeed_100\nBottomWaitTimeAfterLift_0\nWaitTimeAfterLift_0\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
+relative_correction_x = 1
+relative_correction_y = 1
+relative_correction_z = 1
+slow_tilt_time = 8
+thumbnails = 400x400,800x480
diff --git a/PrusaSlicer/printer/EPAX E10 8K.ini b/PrusaSlicer/printer/EPAX E10 8K.ini
new file mode 100644
index 0000000..8f16870
--- /dev/null
+++ b/PrusaSlicer/printer/EPAX E10 8K.ini
@@ -0,0 +1,41 @@
+# generated by PrusaSlicer 2.4.0+win64 on 2022-02-19 at 22:30:45 UTC
+absolute_correction = 0
+area_fill = 50
+bed_custom_model =
+bed_custom_texture =
+bed_shape = 0x0,218.88x0,218.88x123.12,0x123.12
+default_sla_material_profile = Prusa Orange Tough 0.05
+default_sla_print_profile = 0.05 Normal
+display_height = 123.12
+display_mirror_x = 1
+display_mirror_y = 0
+display_orientation = landscape
+display_pixels_x = 7680
+display_pixels_y = 4320
+display_width = 218.88
+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 = 250
+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_EPAX\nPRINTER_MODEL_E10-8K\nFILEFORMAT_ENCRYPTED.CTB\n\nSTART_CUSTOM_VALUES\nBottomWaitTimeBeforeCure_3\nWaitTimeBeforeCure_2.5\nBottomWaitTimeAfterCure_3\nWaitTimeAfterCure_1\nBottomLiftHeight_7\nLiftHeight_7\nBottomLiftSpeed_80\nLiftSpeed_100\nBottomWaitTimeAfterLift_0\nWaitTimeAfterLift_0\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
+relative_correction_x = 1
+relative_correction_y = 1
+relative_correction_z = 1
+slow_tilt_time = 8
+thumbnails = 400x400,800x480
diff --git a/PrusaSlicer/printer/EPAX X133 6K.ini b/PrusaSlicer/printer/EPAX X133 6K.ini
new file mode 100644
index 0000000..ae2badf
--- /dev/null
+++ b/PrusaSlicer/printer/EPAX X133 6K.ini
@@ -0,0 +1,41 @@
+# generated by PrusaSlicer 2.4.0+win64 on 2022-02-19 at 22:42:26 UTC
+absolute_correction = 0
+area_fill = 50
+bed_custom_model =
+bed_custom_texture =
+bed_shape = 0x0,288x0,288x162,0x162
+default_sla_material_profile = Prusa Orange Tough 0.05
+default_sla_print_profile = 0.05 Normal
+display_height = 162
+display_mirror_x = 1
+display_mirror_y = 0
+display_orientation = landscape
+display_pixels_x = 5760
+display_pixels_y = 3240
+display_width = 288
+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 = 400
+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_EPAX\nPRINTER_MODEL_X133-6K\nFILEFORMAT_ENCRYPTED.CTB\n\nSTART_CUSTOM_VALUES\nBottomWaitTimeBeforeCure_3\nWaitTimeBeforeCure_2.5\nBottomWaitTimeAfterCure_3\nWaitTimeAfterCure_1\nBottomLiftHeight_15\nLiftHeight_12\nBottomLiftSpeed_80\nLiftSpeed_100\nBottomWaitTimeAfterLift_0\nWaitTimeAfterLift_0\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
+relative_correction_x = 1
+relative_correction_y = 1
+relative_correction_z = 1
+slow_tilt_time = 8
+thumbnails = 400x400,800x480
diff --git a/PrusaSlicer/printer/Elegoo Jupiter.ini b/PrusaSlicer/printer/Elegoo Jupiter.ini
new file mode 100644
index 0000000..c2ffd2f
--- /dev/null
+++ b/PrusaSlicer/printer/Elegoo Jupiter.ini
@@ -0,0 +1,41 @@
+# generated by PrusaSlicer 2.4.0+win64 on 2022-02-19 at 22:18:01 UTC
+absolute_correction = 0
+area_fill = 50
+bed_custom_model =
+bed_custom_texture =
+bed_shape = 0x0,277.848x0,277.848x156.264,0x156.264
+default_sla_material_profile = Prusa Orange Tough 0.05
+default_sla_print_profile = 0.05 Normal
+display_height = 156.264
+display_mirror_x = 1
+display_mirror_y = 0
+display_orientation = landscape
+display_pixels_x = 5448
+display_pixels_y = 3064
+display_width = 277.848
+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 = 300
+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_ELEGOO\nPRINTER_MODEL_JUPITER\nFILEFORMAT_ENCRYPTED.CTB\n\nSTART_CUSTOM_VALUES\nBottomWaitTimeBeforeCure_3\nWaitTimeBeforeCure_2.5\nBottomWaitTimeAfterCure_3\nWaitTimeAfterCure_1\nBottomLiftHeight_7\nLiftHeight_7\nBottomLiftSpeed_80\nLiftSpeed_100\nBottomWaitTimeAfterLift_0\nWaitTimeAfterLift_0\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
+relative_correction_x = 1
+relative_correction_y = 1
+relative_correction_z = 1
+slow_tilt_time = 8
+thumbnails = 400x400,800x480
diff --git a/PrusaSlicer/printer/Epax X1 4KS.ini b/PrusaSlicer/printer/Epax X1 4KS.ini
new file mode 100644
index 0000000..09072ad
--- /dev/null
+++ b/PrusaSlicer/printer/Epax X1 4KS.ini
@@ -0,0 +1,41 @@
+# generated by PrusaSlicer 2.4.0+win64 on 2022-02-19 at 22:22:10 UTC
+absolute_correction = 0
+area_fill = 50
+bed_custom_model =
+bed_custom_texture =
+bed_shape = 0x0,143.43x0,143.43x89.6,0x89.6
+default_sla_material_profile = Prusa Orange Tough 0.05
+default_sla_print_profile = 0.05 Normal
+display_height = 89.6
+display_mirror_x = 1
+display_mirror_y = 0
+display_orientation = landscape
+display_pixels_x = 4098
+display_pixels_y = 2560
+display_width = 143.43
+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 = 155
+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_EPAX\nPRINTER_MODEL_X1-4KS\nFILEFORMAT_ENCRYPTED.CTB\n\nSTART_CUSTOM_VALUES\nBottomWaitTimeBeforeCure_3\nWaitTimeBeforeCure_2.5\nBottomWaitTimeAfterCure_3\nWaitTimeAfterCure_1\nBottomLiftHeight_5\nLiftHeight_5\nBottomLiftSpeed_80\nLiftSpeed_100\nBottomWaitTimeAfterLift_0\nWaitTimeAfterLift_0\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
+relative_correction_x = 1
+relative_correction_y = 1
+relative_correction_z = 1
+slow_tilt_time = 8
+thumbnails = 400x400,800x480
diff --git a/README.md b/README.md
index 38f18d6..4865be9 100644
--- a/README.md
+++ b/README.md
@@ -123,6 +123,7 @@ Complete guide: https://github.com/sn4k3/UVtools/wiki/Setup-PrusaSlicer
Note that some variables will only work if the target format supports them, otherwise they will be ignored.
Replace the "xxx" by your desired value in the correct units
+- **TransitionLayerCount_xxx:** Sets the number of transition layers
- **BottomLightOffDelay_xxx:** Sets the bottom light off delay time in seconds
- **LightOffDelay_xxx:** Sets the light off delay time in seconds
- **BottomWaitTimeBeforeCure_xxx:** Sets the bottom wait time before cure in seconds
diff --git a/Scripts/010 Editor/ctb.bt b/Scripts/010 Editor/ctb.bt
index c331ad8..fcb67ef 100644
--- a/Scripts/010 Editor/ctb.bt
+++ b/Scripts/010 Editor/ctb.bt
@@ -86,7 +86,7 @@ struct SLICER_INFO {
uint MachineNameAddress <fgcolor=cBlack, bgcolor=cRed>;
uint MachineNameSize <fgcolor=cBlack, bgcolor=cRed>;
uint PerLayerSettings <fgcolor=cBlack, bgcolor=cRed, format=hex>; // 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
- uint MysteriousId <fgcolor=cBlack, bgcolor=cRed>; // v3 = 305419896 | v4 lightoff? = 27093086 | v4 rest? = 27093090
+ uint TimestampMinutes <fgcolor=cBlack, bgcolor=cRed>;
uint AntiAliasLevel <fgcolor=cBlack, bgcolor=cRed>;
uint SoftwareVersion <fgcolor=cBlack, bgcolor=cRed, format=hex>; // ctb v3 = 17171200 | ctb v4 pro = 16777216
float RestTimeAfterRetract <fgcolor=cBlack, bgcolor=cRed>;
diff --git a/Scripts/010 Editor/fdg.bt b/Scripts/010 Editor/fdg.bt
new file mode 100644
index 0000000..d939785
--- /dev/null
+++ b/Scripts/010 Editor/fdg.bt
@@ -0,0 +1,127 @@
+//------------------------------------------------
+//--- 010 Editor v8.0.1 Binary Template
+//
+// File: fdg
+// Authors: Tiago Conceição
+//------------------------------------------------
+
+LittleEndian();
+
+struct HEADER {
+ uint Magic <fgcolor=cBlack, bgcolor=cRed>;
+ uint Version <fgcolor=cBlack, bgcolor=cRed>;
+ uint LayerCount <fgcolor=cBlack, bgcolor=cRed>;
+ uint BottomLayersCount <fgcolor=cBlack, bgcolor=cRed>;
+ uint ProjectorType <fgcolor=cBlack, bgcolor=cRed>;
+ uint BottomLayersCount2 <fgcolor=cBlack, bgcolor=cRed>;
+ uint ResolutionX <fgcolor=cBlack, bgcolor=cRed>;
+ uint ResolutionY <fgcolor=cBlack, bgcolor=cRed>;
+ float LayerHeightMilimeter <fgcolor=cBlack, bgcolor=cRed>;
+ float LayerExposureSeconds <fgcolor=cBlack, bgcolor=cRed>;
+ float BottomExposureSeconds <fgcolor=cBlack, bgcolor=cRed>;
+ uint PreviewLargeOffsetAddress <fgcolor=cBlack, bgcolor=cRed>;
+ uint PreviewSmallOffsetAddress <fgcolor=cBlack, bgcolor=cRed>;
+ uint LayersDefinitionOffsetAddress <fgcolor=cBlack, bgcolor=cRed>;
+ uint PrintTime <fgcolor=cBlack, bgcolor=cRed>;
+ uint AntiAliasLevel <fgcolor=cBlack, bgcolor=cRed>;
+ ushort LightPWM <fgcolor=cBlack, bgcolor=cRed>;
+ ushort BottomLightPWM <fgcolor=cBlack, bgcolor=cRed>;
+ uint Padding <fgcolor=cBlack, bgcolor=cRed>;
+ uint Padding <fgcolor=cBlack, bgcolor=cRed>;
+ float TotalHeightMilimeter <fgcolor=cBlack, bgcolor=cRed>;
+ float BedSizeX <fgcolor=cBlack, bgcolor=cRed>;
+ float BedSizeY <fgcolor=cBlack, bgcolor=cRed>;
+ float BedSizeZ <fgcolor=cBlack, bgcolor=cRed>;
+ uint EncryptionKey <fgcolor=cBlack, bgcolor=cRed>;
+ uint AntiAliasLevelInfo <fgcolor=cBlack, bgcolor=cRed>;
+ uint EncryptionMode <fgcolor=cBlack, bgcolor=cRed>;
+ float VolumeMl <fgcolor=cBlack, bgcolor=cRed>;
+ float WeightG <fgcolor=cBlack, bgcolor=cRed>;
+ float CostDollars <fgcolor=cBlack, bgcolor=cRed>;
+ uint MachineNameAddress <fgcolor=cBlack, bgcolor=cRed>;
+ uint MachineNameSize <fgcolor=cBlack, bgcolor=cRed>;
+ float BottomLightOffDelay <fgcolor=cBlack, bgcolor=cRed>;
+ float LightOffDelay <fgcolor=cBlack, bgcolor=cRed>;
+ uint Padding <fgcolor=cBlack, bgcolor=cRed>;
+ 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>;
+ uint Padding <fgcolor=cBlack, bgcolor=cRed>;
+ uint Padding <fgcolor=cBlack, bgcolor=cRed>;
+ uint Padding <fgcolor=cBlack, bgcolor=cRed>;
+ uint Padding <fgcolor=cBlack, bgcolor=cRed>;
+ uint Padding <fgcolor=cBlack, bgcolor=cRed>;
+ uint Padding <fgcolor=cBlack, bgcolor=cRed>;
+ uint Padding <fgcolor=cBlack, bgcolor=cRed>;
+ uint TimestampMinutes <fgcolor=cBlack, bgcolor=cRed>;
+ uint SoftwareVersion <fgcolor=cBlack, bgcolor=cRed>;
+ uint Padding <fgcolor=cBlack, bgcolor=cRed>;
+ uint Padding <fgcolor=cBlack, bgcolor=cRed>;
+ uint Padding <fgcolor=cBlack, bgcolor=cRed>;
+ uint Padding <fgcolor=cBlack, bgcolor=cRed>;
+ uint Padding <fgcolor=cBlack, bgcolor=cRed>;
+ uint Padding <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>;
+
+ ubyte Data[ImageLength] <fgcolor=cBlack, bgcolor=cYellow>;
+};
+
+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.MachineNameAddress > 0 && header.MachineNameSize > 0)
+{
+ FSeek(header.MachineNameAddress);
+ char MachineName[header.MachineNameSize] <fgcolor=cBlack, bgcolor=cGreen>;
+}
+
+struct LAYER_DATA {
+ float PositionZ <fgcolor=cBlack, bgcolor=cRed>;
+ float Exposure <fgcolor=cBlack, bgcolor=cRed>;
+ float LightOffSeconds <fgcolor=cBlack, bgcolor=cRed>;
+ uint DataAddress <fgcolor=cBlack, bgcolor=cRed>;
+ uint DataSize <fgcolor=cBlack, bgcolor=cRed>;
+ uint Unknown <fgcolor=cBlack, bgcolor=cRed>;
+ uint Unknown <fgcolor=cBlack, bgcolor=cRed>;
+ uint Unknown <fgcolor=cBlack, bgcolor=cRed>;
+ uint Unknown <fgcolor=cBlack, bgcolor=cRed>;
+};
+
+typedef struct(int size) {
+ ubyte layerDataBlock[size] <fgcolor=cBlack, bgcolor=cGreen>;
+} LAYER_RLE;
+
+FSeek(header.LayersDefinitionOffsetAddress);
+struct LAYERS {
+
+ local int i = 0;
+ local uint currentPos;
+ for( i = 0; i < header.LayerCount; i++ ){
+ LAYER_DATA layerData <fgcolor=cBlack, bgcolor=cYellow>;
+ currentPos = FTell();
+ FSeek(layerData.DataAddress);
+ LAYER_RLE layerRLE(layerData.DataSize);
+ FSeek(currentPos);
+ }
+
+} layers;
diff --git a/Scripts/010 Editor/phz.bt b/Scripts/010 Editor/phz.bt
new file mode 100644
index 0000000..f50bbfd
--- /dev/null
+++ b/Scripts/010 Editor/phz.bt
@@ -0,0 +1,127 @@
+//------------------------------------------------
+//--- 010 Editor v8.0.1 Binary Template
+//
+// File: phz
+// Authors: Tiago Conceição
+//------------------------------------------------
+
+LittleEndian();
+
+struct HEADER {
+ uint Magic <fgcolor=cBlack, bgcolor=cRed>;
+ uint Version <fgcolor=cBlack, bgcolor=cRed>;
+ float LayerHeightMilimeter <fgcolor=cBlack, bgcolor=cRed>;
+ float LayerExposureSeconds <fgcolor=cBlack, bgcolor=cRed>;
+ float BottomExposureSeconds <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 AntiAliasLevel <fgcolor=cBlack, bgcolor=cRed>;
+ ushort LightPWM <fgcolor=cBlack, bgcolor=cRed>;
+ ushort BottomLightPWM <fgcolor=cBlack, bgcolor=cRed>;
+ uint Padding <fgcolor=cBlack, bgcolor=cRed>;
+ uint Padding <fgcolor=cBlack, bgcolor=cRed>;
+ float TotalHeightMilimeter <fgcolor=cBlack, bgcolor=cRed>;
+ float BedSizeX <fgcolor=cBlack, bgcolor=cRed>;
+ float BedSizeY <fgcolor=cBlack, bgcolor=cRed>;
+ float BedSizeZ <fgcolor=cBlack, bgcolor=cRed>;
+ uint EncryptionKey <fgcolor=cBlack, bgcolor=cRed>;
+ float BottomLightOffDelay <fgcolor=cBlack, bgcolor=cRed>;
+ float LightOffDelay <fgcolor=cBlack, bgcolor=cRed>;
+ uint BottomLayersCount2 <fgcolor=cBlack, bgcolor=cRed>;
+ uint Padding <fgcolor=cBlack, bgcolor=cRed>;
+ 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>;
+ uint Padding <fgcolor=cBlack, bgcolor=cRed>;
+ uint MachineNameAddress <fgcolor=cBlack, bgcolor=cRed>;
+ uint MachineNameSize <fgcolor=cBlack, bgcolor=cRed>;
+ uint Padding <fgcolor=cBlack, bgcolor=cRed>;
+ uint Padding <fgcolor=cBlack, bgcolor=cRed>;
+ uint Padding <fgcolor=cBlack, bgcolor=cRed>;
+ uint Padding <fgcolor=cBlack, bgcolor=cRed>;
+ uint Padding <fgcolor=cBlack, bgcolor=cRed>;
+ uint Padding <fgcolor=cBlack, bgcolor=cRed>;
+ uint EncryptionMode <fgcolor=cBlack, bgcolor=cRed>;
+ uint TimestampMinutes <fgcolor=cBlack, bgcolor=cRed>;
+ uint AntiAliasLevelInfo <fgcolor=cBlack, bgcolor=cRed>;
+ uint SoftwareVersion <fgcolor=cBlack, bgcolor=cRed>;
+ uint Padding <fgcolor=cBlack, bgcolor=cRed>;
+ uint Padding <fgcolor=cBlack, bgcolor=cRed>;
+ uint Padding <fgcolor=cBlack, bgcolor=cRed>;
+ uint Padding <fgcolor=cBlack, bgcolor=cRed>;
+ uint Padding <fgcolor=cBlack, bgcolor=cRed>;
+ uint Padding <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>;
+
+ ubyte Data[ImageLength] <fgcolor=cBlack, bgcolor=cYellow>;
+};
+
+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.MachineNameAddress > 0 && header.MachineNameSize > 0)
+{
+ FSeek(header.MachineNameAddress);
+ char MachineName[header.MachineNameSize] <fgcolor=cBlack, bgcolor=cGreen>;
+}
+
+struct LAYER_DATA {
+ float PositionZ <fgcolor=cBlack, bgcolor=cRed>;
+ float Exposure <fgcolor=cBlack, bgcolor=cRed>;
+ float LightOffSeconds <fgcolor=cBlack, bgcolor=cRed>;
+ uint DataAddress <fgcolor=cBlack, bgcolor=cRed>;
+ uint DataSize <fgcolor=cBlack, bgcolor=cRed>;
+ uint Unknown <fgcolor=cBlack, bgcolor=cRed>;
+ uint Unknown <fgcolor=cBlack, bgcolor=cRed>;
+ uint Unknown <fgcolor=cBlack, bgcolor=cRed>;
+ uint Unknown <fgcolor=cBlack, bgcolor=cRed>;
+};
+
+typedef struct(int size) {
+ ubyte layerDataBlock[size] <fgcolor=cBlack, bgcolor=cGreen>;
+} LAYER_RLE;
+
+FSeek(header.LayersDefinitionOffsetAddress);
+struct LAYERS {
+
+ local int i = 0;
+ local uint currentPos;
+ for( i = 0; i < header.LayerCount; i++ ){
+ LAYER_DATA layerData <fgcolor=cBlack, bgcolor=cYellow>;
+ currentPos = FTell();
+ FSeek(layerData.DataAddress);
+ LAYER_RLE layerRLE(layerData.DataSize);
+ FSeek(currentPos);
+ }
+
+} layers;
diff --git a/Scripts/ImportPrusaSlicerData.bat b/Scripts/ImportPrusaSlicerData.bat
deleted file mode 100644
index 9ce12c2..0000000
--- a/Scripts/ImportPrusaSlicerData.bat
+++ /dev/null
@@ -1,118 +0,0 @@
-@echo off
-SET DIR=%~dp0
-cd ..
-SET INPUT_DIR=%AppData%\PrusaSlicer
-SET OUTPUT_DIR=PrusaSlicer
-
-SET PRINT_DIR=sla_print
-SET PRINTER_DIR=printer
-
-SET files[0]=UVtools Prusa SL1.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 E10 5K.ini
-SET files[5]=EPAX X1.ini
-SET files[6]=EPAX X10.ini
-SET files[7]=EPAX X10 4K Mono.ini
-SET files[8]=EPAX X10 5K.ini
-SET files[9]=EPAX X133 4K Mono.ini
-SET files[10]=EPAX X156 4K Color.ini
-SET files[11]=EPAX X1K 2K Mono.ini
-SET files[12]=Zortrax Inkspire.ini
-SET files[13]=Nova3D Elfin.ini
-SET files[14]=Nova3D Elfin2.ini
-SET files[15]=Nova3D Elfin2 Mono SE.ini
-SET files[16]=Nova3D Elfin3 Mini.ini
-SET files[17]=Nova3D Bene4.ini
-SET files[18]=Nova3D Bene4 Mono.ini
-SET files[19]=Nova3D Bene5.ini
-SET files[20]=Nova3D Whale.ini
-SET files[21]=Nova3D Whale2.ini
-SET files[22]=AnyCubic Photon.ini
-SET files[23]=AnyCubic Photon S.ini
-SET files[24]=AnyCubic Photon Zero.ini
-SET files[25]=AnyCubic Photon X.ini
-SET files[26]=AnyCubic Photon Ultra.ini
-SET files[27]=AnyCubic Photon Mono.ini
-SET files[28]=AnyCubic Photon Mono 4K.ini
-SET files[29]=AnyCubic Photon Mono SE.ini
-SET files[30]=AnyCubic Photon Mono X.ini
-SET files[31]=AnyCubic Photon Mono X 6K.ini
-SET files[32]=AnyCubic Photon Mono SQ.ini
-SET files[33]=Elegoo Mars.ini
-SET files[34]=Elegoo Mars 2 Pro.ini
-SET files[35]=Elegoo Mars 3.ini
-SET files[36]=Elegoo Mars C.ini
-SET files[37]=Elegoo Saturn.ini
-SET files[38]=Peopoly Phenom.ini
-SET files[39]=Peopoly Phenom L.ini
-SET files[40]=Peopoly Phenom Noir.ini
-SET files[41]=Peopoly Phenom XXL.ini
-SET files[42]=QIDI Shadow5.5.ini
-SET files[43]=QIDI Shadow6.0 Pro.ini
-SET files[44]=QIDI S-Box.ini
-SET files[45]=QIDI I-Box Mono.ini
-SET files[46]=Phrozen Shuffle.ini
-SET files[47]=Phrozen Shuffle Lite.ini
-SET files[48]=Phrozen Shuffle XL.ini
-SET files[49]=Phrozen Shuffle XL Lite.ini
-SET files[50]=Phrozen Shuffle 16.ini
-SET files[51]=Phrozen Shuffle 4K.ini
-SET files[52]=Phrozen Sonic.ini
-SET files[53]=Phrozen Sonic 4K.ini
-SET files[54]=Phrozen Sonic Mighty 4K.ini
-SET files[55]=Phrozen Sonic Mini.ini
-SET files[56]=Phrozen Sonic Mini 4K.ini
-SET files[57]=Phrozen Sonic Mini 8K.ini
-SET files[58]=Phrozen Transform.ini
-SET files[59]=Phrozen Sonic Mega 8K.ini
-SET files[60]=Kelant S400.ini
-SET files[61]=Wanhao D7.ini
-SET files[62]=Wanhao D8.ini
-SET files[63]=Wanhao CGR Mini Mono.ini
-SET files[64]=Wanhao CGR Mono.ini
-SET files[65]=Creality LD-002R.ini
-SET files[66]=Creality LD-002H.ini
-SET files[67]=Creality LD-006.ini
-SET files[68]=Creality HALOT-ONE CL-60.ini
-SET files[69]=Creality HALOT-SKY CL-89.ini
-SET files[70]=Creality HALOT-MAX CL-133.ini
-SET files[71]=Voxelab Polaris 5.5.ini
-SET files[72]=Voxelab Proxima 6.ini
-SET files[73]=Voxelab Ceres 8.9.ini
-SET files[74]=Longer Orange 10.ini
-SET files[75]=Longer Orange 30.ini
-SET files[76]=Longer Orange 120.ini
-SET files[77]=Longer Orange 4K.ini
-SET files[78]=Uniz IBEE.ini
-SET files[79]=FlashForge Explorer MAX.ini
-SET files[80]=FlashForge Focus 8.9.ini
-SET files[81]=FlashForge Focus 13.3.ini
-SET files[82]=FlashForge Foto 6.0.ini
-SET files[83]=FlashForge Foto 8.9.ini
-SET files[84]=FlashForge Foto 13.3.ini
-SET files[85]=FlashForge Hunter.ini
-
-echo PrusaSlicer Printers Instalation
-echo This will replace printers, all changes will be discarded
-echo %INPUT_DIR%
-echo %OUTPUT_DIR%
-
-echo Importing Printers
-for /F "tokens=2 delims==" %%s in ('set files[') do xcopy /d /y "%INPUT_DIR%\%PRINTER_DIR%\%%s" "%OUTPUT_DIR%\%PRINTER_DIR%\"
-
-echo Importing Profiles
-xcopy /i /y /d %INPUT_DIR%\%PRINT_DIR% %OUTPUT_DIR%\%PRINT_DIR%
-
-REM /s Copies directories and subdirectories, unless they are empty. If you omit /s, xcopy works within a single directory.
-REM /y Suppresses prompting to confirm that you want to overwrite an existing destination file.
-REM /i If Source is a directory or contains wildcards and Destination does not exist,
-REM xcopy assumes Destination specifies a directory name and creates a new directory.
-REM Then, xcopy copies all specified files into the new directory.
-REM By default, xcopy prompts you to specify whether Destination is a file or a directory.
-REM /d Copies source files changed on or after the specified date only.
-REM If you do not include a MM-DD-YYYY value, xcopy copies all Source files that are newer than existing Destination files.
-REM This command-line option allows you to update files that have changed.
-
-pause \ No newline at end of file
diff --git a/Scripts/ImportPrusaSlicerData.ps1 b/Scripts/ImportPrusaSlicerData.ps1
index 756e951..2d492bb 100644
--- a/Scripts/ImportPrusaSlicerData.ps1
+++ b/Scripts/ImportPrusaSlicerData.ps1
@@ -11,13 +11,20 @@ $printers =
'EPAX E6 Mono.ini',
'EPAX E10 Mono.ini',
'EPAX E10 5K.ini',
+ 'EPAX E10 8K.ini',
+ 'EPAX X10 8K.ini',
'EPAX X1.ini',
+ 'EPAX X1 4KS.ini',
+ 'EPAX X1K 2K Mono.ini',
'EPAX X10.ini',
'EPAX X10 4K Mono.ini',
'EPAX X10 5K.ini',
'EPAX X133 4K Mono.ini',
+ 'EPAX X133 6K.ini',
'EPAX X156 4K Color.ini',
- 'EPAX X1K 2K Mono.ini',
+ 'EPAX DX1 Pro.ini',
+ 'EPAX DX10 Pro 5K.ini',
+ 'EPAX DX10 Pro 8K.ini',
'Zortrax Inkspire.ini',
'Nova3D Elfin.ini',
'Nova3D Elfin2.ini',
@@ -44,6 +51,7 @@ $printers =
'Elegoo Mars 3.ini',
'Elegoo Mars C.ini',
'Elegoo Saturn.ini',
+ 'Elegoo Jupiter.ini',
'Peopoly Phenom.ini',
'Peopoly Phenom L.ini',
'Peopoly Phenom Noir.ini',
diff --git a/UVtools.Core/Extensions/DateTimeExtensions.cs b/UVtools.Core/Extensions/DateTimeExtensions.cs
new file mode 100644
index 0000000..f2c4b11
--- /dev/null
+++ b/UVtools.Core/Extensions/DateTimeExtensions.cs
@@ -0,0 +1,51 @@
+/*
+ * GNU AFFERO GENERAL PUBLIC LICENSE
+ * Version 3, 19 November 2007
+ * Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
+ * Everyone is permitted to copy and distribute verbatim copies
+ * of this license document, but changing it is not allowed.
+ */
+
+
+using System;
+
+namespace UVtools.Core.Extensions
+{
+ public static class DateTimeExtensions
+ {
+ /// <summary>
+ /// Gets the Unix timestamp since Jan 1, 1970 UTC
+ /// </summary>
+ public static TimeSpan Timestamp => DateTime.UtcNow.Subtract(DateTime.UnixEpoch);
+
+ /// <summary>
+ /// Gets the Unix timestamp in seconds since Jan 1, 1970 UTC
+ /// </summary>
+ public static double TimestampSeconds => Timestamp.TotalSeconds;
+
+ /// <summary>
+ /// Gets the Unix minutes in seconds since Jan 1, 1970 UTC
+ /// </summary>
+ public static double TimestampMinutes => Timestamp.TotalMinutes;
+
+ /// <summary>
+ /// Gets the <see cref="DateTime"/> from a unix timestamp in seconds
+ /// </summary>
+ /// <param name="seconds"></param>
+ /// <returns></returns>
+ public static DateTime GetDateTimeFromTimestampSeconds(double seconds)
+ {
+ return DateTime.UnixEpoch.AddSeconds(seconds);
+ }
+
+ /// <summary>
+ /// Gets the <see cref="DateTime"/> from a unix timestamp in minutes
+ /// </summary>
+ /// <param name="minutes"></param>
+ /// <returns></returns>
+ public static DateTime GetDateTimeFromTimestampMinutes(double minutes)
+ {
+ return DateTime.UnixEpoch.AddMinutes(minutes);
+ }
+ }
+}
diff --git a/UVtools.Core/FileFormats/CTBEncryptedFile.cs b/UVtools.Core/FileFormats/CTBEncryptedFile.cs
index 4766f84..4142cab 100644
--- a/UVtools.Core/FileFormats/CTBEncryptedFile.cs
+++ b/UVtools.Core/FileFormats/CTBEncryptedFile.cs
@@ -140,7 +140,7 @@ namespace UVtools.Core.FileFormats
[FieldOrder(55)] public float RestTimeAfterLift3 { get; set; }
[FieldOrder(56)] public float RestTimeBeforeLift { get; set; }
[FieldOrder(57)] public float BottomRetractHeight2 { get; set; }
- [FieldOrder(58)] public float Unknown6 { get; set; } // Same as CTBv4.PrintParametersV4.Unknown1)
+ [FieldOrder(58)] public uint Unknown6 { get; set; } // Same as CTBv4.PrintParametersV4.Unknown1)
[FieldOrder(59)] public uint Unknown7 { get; set; } // Same as CTBv4.PrintParametersV4.Unknown2)
[FieldOrder(60)] public uint Unknown8 { get; set; } = 4; // Same as CTBv4.PrintParametersV4.Unknown3)
[FieldOrder(61)] public uint LastLayerIndex { get; set; }
@@ -601,6 +601,7 @@ namespace UVtools.Core.FileFormats
public override PrintParameterModifier[] PrintParameterModifiers { get; } = {
PrintParameterModifier.BottomLayerCount,
+ PrintParameterModifier.TransitionLayerCount,
PrintParameterModifier.BottomLightOffDelay,
PrintParameterModifier.LightOffDelay,
@@ -756,6 +757,14 @@ namespace UVtools.Core.FileFormats
set => base.BottomLayerCount = (ushort)(Settings.BottomLayerCount = value);
}
+ public override TransitionLayerTypes TransitionLayerType => TransitionLayerTypes.Software;
+
+ public override ushort TransitionLayerCount
+ {
+ get => (ushort)Settings.TransitionLayerCount;
+ set => base.TransitionLayerCount = (ushort)(Settings.TransitionLayerCount = Math.Min(value, MaximumPossibleTransitionLayerCount));
+ }
+
public override float BottomLightOffDelay
{
get => Settings.BottomLightOffDelay;
diff --git a/UVtools.Core/FileFormats/CWSFile.cs b/UVtools.Core/FileFormats/CWSFile.cs
index ae85c0e..efefca6 100644
--- a/UVtools.Core/FileFormats/CWSFile.cs
+++ b/UVtools.Core/FileFormats/CWSFile.cs
@@ -854,7 +854,7 @@ namespace UVtools.Core.FileFormats
GCode.ParseLayersFromGCode(this);
var firstLayer = FirstLayer;
- if (firstLayer is not null)
+ if (firstLayer is not null && DecodeType == FileDecodeType.Full)
{
if (Printer == PrinterType.Unknown)
{
diff --git a/UVtools.Core/FileFormats/ChituboxFile.cs b/UVtools.Core/FileFormats/ChituboxFile.cs
index 0bc0765..2d0d4ba 100644
--- a/UVtools.Core/FileFormats/ChituboxFile.cs
+++ b/UVtools.Core/FileFormats/ChituboxFile.cs
@@ -309,9 +309,11 @@ namespace UVtools.Core.FileFormats
[FieldOrder(9)] public uint PerLayerSettings { get; set; } = PERLAYER_SETTINGS_DISALLOW;
/// <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.
+ /// Gets the minutes since Jan 1, 1970 UTC
/// </summary>
- [FieldOrder(10)] public uint MysteriousId { get; set; } = 305419896; // v3 = 305419896 | v4 = 27087675
+ [FieldOrder(10)] public uint ModifiedTimestampMinutes { get; set; } = (uint)DateTimeExtensions.Timestamp.TotalMinutes;
+
+ [Ignore] public string ModifiedDate => DateTimeExtensions.GetDateTimeFromTimestampMinutes(ModifiedTimestampMinutes).ToString("dd/MM/yyyy HH:mm");
/// <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.
@@ -352,7 +354,7 @@ namespace UVtools.Core.FileFormats
public override string ToString()
{
- return $"{nameof(BottomLiftHeight2)}: {BottomLiftHeight2}, {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(PerLayerSettings)}: {PerLayerSettings}, {nameof(MysteriousId)}: {MysteriousId}, {nameof(AntiAliasLevel)}: {AntiAliasLevel}, {nameof(SoftwareVersion)}: {SoftwareVersion}, {nameof(RestTimeAfterRetract)}: {RestTimeAfterRetract}, {nameof(RestTimeAfterLift2)}: {RestTimeAfterLift2}, {nameof(TransitionLayerCount)}: {TransitionLayerCount}, {nameof(PrintParametersV4Address)}: {PrintParametersV4Address}, {nameof(Padding2)}: {Padding2}, {nameof(Padding3)}: {Padding3}, {nameof(MachineName)}: {MachineName}";
+ return $"{nameof(BottomLiftHeight2)}: {BottomLiftHeight2}, {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(PerLayerSettings)}: {PerLayerSettings}, {nameof(ModifiedTimestampMinutes)}: {ModifiedTimestampMinutes}, {nameof(ModifiedDate)}: {ModifiedDate}, {nameof(AntiAliasLevel)}: {AntiAliasLevel}, {nameof(SoftwareVersion)}: {SoftwareVersion}, {nameof(RestTimeAfterRetract)}: {RestTimeAfterRetract}, {nameof(RestTimeAfterLift2)}: {RestTimeAfterLift2}, {nameof(TransitionLayerCount)}: {TransitionLayerCount}, {nameof(PrintParametersV4Address)}: {PrintParametersV4Address}, {nameof(Padding2)}: {Padding2}, {nameof(Padding3)}: {Padding3}, {nameof(MachineName)}: {MachineName}";
}
}
@@ -1085,6 +1087,7 @@ namespace UVtools.Core.FileFormats
{
PrintParameterModifier.BottomLayerCount,
+ PrintParameterModifier.TransitionLayerCount,
PrintParameterModifier.BottomLightOffDelay,
PrintParameterModifier.LightOffDelay,
@@ -1122,6 +1125,27 @@ namespace UVtools.Core.FileFormats
};
}
+ if (HeaderSettings.Version == 3)
+ {
+ return new[]
+ {
+
+ PrintParameterModifier.BottomLayerCount,
+ PrintParameterModifier.TransitionLayerCount,
+
+ PrintParameterModifier.BottomLightOffDelay,
+ PrintParameterModifier.LightOffDelay,
+ PrintParameterModifier.BottomExposureTime,
+ PrintParameterModifier.ExposureTime,
+
+ PrintParameterModifier.BottomLiftHeight,
+ PrintParameterModifier.BottomLiftSpeed,
+ PrintParameterModifier.LiftHeight,
+ PrintParameterModifier.LiftSpeed,
+ PrintParameterModifier.RetractSpeed,
+ };
+ }
+
return new[]
{
@@ -1327,6 +1351,14 @@ namespace UVtools.Core.FileFormats
set => base.BottomLayerCount = (ushort) (HeaderSettings.BottomLayersCount = PrintParametersSettings.BottomLayerCount = value);
}
+ public override TransitionLayerTypes TransitionLayerType => TransitionLayerTypes.Software;
+
+ public override ushort TransitionLayerCount
+ {
+ get => (ushort)SlicerInfoSettings.TransitionLayerCount;
+ set => base.TransitionLayerCount = (ushort)(SlicerInfoSettings.TransitionLayerCount = Math.Min(value, MaximumPossibleTransitionLayerCount));
+ }
+
public override float BottomLightOffDelay
{
get => PrintParametersSettings.BottomLightOffDelay;
@@ -1730,25 +1762,18 @@ namespace UVtools.Core.FileFormats
{
SlicerInfoSettings.PerLayerSettings = PERLAYER_SETTINGS_CTBv2;
PrintParametersSettings.Padding4 = 0x1234; // 4660
-
- if (SlicerInfoSettings.MysteriousId == 0)
- SlicerInfoSettings.MysteriousId = 305419896;
}
else if (HeaderSettings.Version == 3)
{
SlicerInfoSettings.PerLayerSettings = LayerManager.AllLayersAreUsingGlobalParameters ? PERLAYER_SETTINGS_DISALLOW : PERLAYER_SETTINGS_CTBv3;
-
- if (SlicerInfoSettings.MysteriousId == 0)
- SlicerInfoSettings.MysteriousId = 305419896;
}
else if (HeaderSettings.Version >= 4)
{
SlicerInfoSettings.PerLayerSettings = LayerManager.AllLayersAreUsingGlobalParameters ? PERLAYER_SETTINGS_DISALLOW : PERLAYER_SETTINGS_CTBv4;
-
- if (SlicerInfoSettings.MysteriousId == 0)
- SlicerInfoSettings.MysteriousId = 27087820;
}
}
+
+ SlicerInfoSettings.ModifiedTimestampMinutes = (uint)DateTimeExtensions.TimestampMinutes;
}
private void SanitizeMagicVersion()
diff --git a/UVtools.Core/FileFormats/FDGFile.cs b/UVtools.Core/FileFormats/FDGFile.cs
index bdc88cc..6b45888 100644
--- a/UVtools.Core/FileFormats/FDGFile.cs
+++ b/UVtools.Core/FileFormats/FDGFile.cs
@@ -251,7 +251,9 @@ namespace UVtools.Core.FileFormats
/// <summary>
/// Gets the minutes since Jan 1, 1970 UTC
/// </summary>
- [FieldOrder(47)] public uint Timestamp { get; set; }
+ [FieldOrder(47)] public uint ModifiedTimestampMinutes { get; set; } = (uint) DateTimeExtensions.Timestamp.TotalMinutes;
+
+ [Ignore] public string ModifiedDate => DateTimeExtensions.GetDateTimeFromTimestampMinutes(ModifiedTimestampMinutes).ToString("dd/MM/yyyy HH:mm");
[FieldOrder(48)] public uint SoftwareVersion { get; set; } = 0x01060300;
@@ -264,7 +266,7 @@ namespace UVtools.Core.FileFormats
public override string ToString()
{
- return $"{nameof(Magic)}: {Magic}, {nameof(Version)}: {Version}, {nameof(LayerCount)}: {LayerCount}, {nameof(BottomLayersCount)}: {BottomLayersCount}, {nameof(ProjectorType)}: {ProjectorType}, {nameof(BottomLayersCount2)}: {BottomLayersCount2}, {nameof(ResolutionX)}: {ResolutionX}, {nameof(ResolutionY)}: {ResolutionY}, {nameof(LayerHeightMilimeter)}: {LayerHeightMilimeter}, {nameof(LayerExposureSeconds)}: {LayerExposureSeconds}, {nameof(BottomExposureSeconds)}: {BottomExposureSeconds}, {nameof(PreviewLargeOffsetAddress)}: {PreviewLargeOffsetAddress}, {nameof(PreviewSmallOffsetAddress)}: {PreviewSmallOffsetAddress}, {nameof(LayersDefinitionOffsetAddress)}: {LayersDefinitionOffsetAddress}, {nameof(PrintTime)}: {PrintTime}, {nameof(AntiAliasLevel)}: {AntiAliasLevel}, {nameof(LightPWM)}: {LightPWM}, {nameof(BottomLightPWM)}: {BottomLightPWM}, {nameof(Padding1)}: {Padding1}, {nameof(Padding2)}: {Padding2}, {nameof(OverallHeightMilimeter)}: {OverallHeightMilimeter}, {nameof(BedSizeX)}: {BedSizeX}, {nameof(BedSizeY)}: {BedSizeY}, {nameof(BedSizeZ)}: {BedSizeZ}, {nameof(EncryptionKey)}: {EncryptionKey}, {nameof(AntiAliasLevelInfo)}: {AntiAliasLevelInfo}, {nameof(EncryptionMode)}: {EncryptionMode}, {nameof(VolumeMl)}: {VolumeMl}, {nameof(WeightG)}: {WeightG}, {nameof(CostDollars)}: {CostDollars}, {nameof(MachineNameAddress)}: {MachineNameAddress}, {nameof(MachineNameSize)}: {MachineNameSize}, {nameof(MachineName)}: {MachineName}, {nameof(BottomLightOffDelay)}: {BottomLightOffDelay}, {nameof(LightOffDelay)}: {LightOffDelay}, {nameof(Padding4)}: {Padding4}, {nameof(BottomLiftHeight)}: {BottomLiftHeight}, {nameof(BottomLiftSpeed)}: {BottomLiftSpeed}, {nameof(LiftHeight)}: {LiftHeight}, {nameof(LiftSpeed)}: {LiftSpeed}, {nameof(RetractSpeed)}: {RetractSpeed}, {nameof(Padding5)}: {Padding5}, {nameof(Padding6)}: {Padding6}, {nameof(Padding7)}: {Padding7}, {nameof(Padding8)}: {Padding8}, {nameof(Padding9)}: {Padding9}, {nameof(Padding10)}: {Padding10}, {nameof(Padding11)}: {Padding11}, {nameof(Timestamp)}: {Timestamp}, {nameof(SoftwareVersion)}: {SoftwareVersion}, {nameof(Padding12)}: {Padding12}, {nameof(Padding13)}: {Padding13}, {nameof(Padding14)}: {Padding14}, {nameof(Padding15)}: {Padding15}, {nameof(Padding16)}: {Padding16}, {nameof(Padding17)}: {Padding17}";
+ return $"{nameof(_machineName)}: {_machineName}, {nameof(Magic)}: {Magic}, {nameof(Version)}: {Version}, {nameof(LayerCount)}: {LayerCount}, {nameof(BottomLayersCount)}: {BottomLayersCount}, {nameof(ProjectorType)}: {ProjectorType}, {nameof(BottomLayersCount2)}: {BottomLayersCount2}, {nameof(ResolutionX)}: {ResolutionX}, {nameof(ResolutionY)}: {ResolutionY}, {nameof(LayerHeightMilimeter)}: {LayerHeightMilimeter}, {nameof(LayerExposureSeconds)}: {LayerExposureSeconds}, {nameof(BottomExposureSeconds)}: {BottomExposureSeconds}, {nameof(PreviewLargeOffsetAddress)}: {PreviewLargeOffsetAddress}, {nameof(PreviewSmallOffsetAddress)}: {PreviewSmallOffsetAddress}, {nameof(LayersDefinitionOffsetAddress)}: {LayersDefinitionOffsetAddress}, {nameof(PrintTime)}: {PrintTime}, {nameof(AntiAliasLevel)}: {AntiAliasLevel}, {nameof(LightPWM)}: {LightPWM}, {nameof(BottomLightPWM)}: {BottomLightPWM}, {nameof(Padding1)}: {Padding1}, {nameof(Padding2)}: {Padding2}, {nameof(OverallHeightMilimeter)}: {OverallHeightMilimeter}, {nameof(BedSizeX)}: {BedSizeX}, {nameof(BedSizeY)}: {BedSizeY}, {nameof(BedSizeZ)}: {BedSizeZ}, {nameof(EncryptionKey)}: {EncryptionKey}, {nameof(AntiAliasLevelInfo)}: {AntiAliasLevelInfo}, {nameof(EncryptionMode)}: {EncryptionMode}, {nameof(VolumeMl)}: {VolumeMl}, {nameof(WeightG)}: {WeightG}, {nameof(CostDollars)}: {CostDollars}, {nameof(MachineNameAddress)}: {MachineNameAddress}, {nameof(MachineNameSize)}: {MachineNameSize}, {nameof(MachineName)}: {MachineName}, {nameof(BottomLightOffDelay)}: {BottomLightOffDelay}, {nameof(LightOffDelay)}: {LightOffDelay}, {nameof(Padding4)}: {Padding4}, {nameof(BottomLiftHeight)}: {BottomLiftHeight}, {nameof(BottomLiftSpeed)}: {BottomLiftSpeed}, {nameof(LiftHeight)}: {LiftHeight}, {nameof(LiftSpeed)}: {LiftSpeed}, {nameof(RetractSpeed)}: {RetractSpeed}, {nameof(Padding5)}: {Padding5}, {nameof(Padding6)}: {Padding6}, {nameof(Padding7)}: {Padding7}, {nameof(Padding8)}: {Padding8}, {nameof(Padding9)}: {Padding9}, {nameof(Padding10)}: {Padding10}, {nameof(Padding11)}: {Padding11}, {nameof(ModifiedTimestampMinutes)}: {ModifiedTimestampMinutes}, {nameof(ModifiedDate)}: {ModifiedDate}, {nameof(SoftwareVersion)}: {SoftwareVersion}, {nameof(Padding12)}: {Padding12}, {nameof(Padding13)}: {Padding13}, {nameof(Padding14)}: {Padding14}, {nameof(Padding15)}: {Padding15}, {nameof(Padding16)}: {Padding16}, {nameof(Padding17)}: {Padding17}";
}
}
#endregion
@@ -1021,7 +1023,7 @@ namespace UVtools.Core.FileFormats
}
}
-
+ HeaderSettings.ModifiedTimestampMinutes = (uint)DateTimeExtensions.TimestampMinutes;
outputFile.Seek(0, SeekOrigin.Begin);
Helpers.SerializeWriteFileStream(outputFile, HeaderSettings);
@@ -1126,6 +1128,7 @@ namespace UVtools.Core.FileFormats
protected override void PartialSaveInternally(OperationProgress progress)
{
+ HeaderSettings.ModifiedTimestampMinutes = (uint)DateTimeExtensions.TimestampMinutes;
using var outputFile = new FileStream(FileFullPath, FileMode.Open, FileAccess.Write);
outputFile.Seek(0, SeekOrigin.Begin);
Helpers.SerializeWriteFileStream(outputFile, HeaderSettings);
diff --git a/UVtools.Core/FileFormats/FileFormat.cs b/UVtools.Core/FileFormats/FileFormat.cs
index ce5ad49..badebc7 100644
--- a/UVtools.Core/FileFormats/FileFormat.cs
+++ b/UVtools.Core/FileFormats/FileFormat.cs
@@ -45,6 +45,7 @@ namespace UVtools.Core.FileFormats
public const float DefaultLayerHeight = 0.05f;
public const ushort DefaultBottomLayerCount = 4;
+ public const ushort DefaultTransitionLayerCount = 0;
public const float DefaultBottomExposureTime = 30;
public const float DefaultExposureTime = 3;
@@ -125,6 +126,19 @@ namespace UVtools.Core.FileFormats
Large
}
+ public enum TransitionLayerTypes : byte
+ {
+ /// <summary>
+ /// Firmware transition layers are handled by printer firmware
+ /// </summary>
+ Firmware,
+
+ /// <summary>
+ /// Software transition layers are handled by software and written on layer data
+ /// </summary>
+ Software
+ }
+
public enum FileDecodeType : byte
{
/// <summary>
@@ -147,8 +161,9 @@ namespace UVtools.Core.FileFormats
{
#region Instances
- public static PrintParameterModifier PositionZ { get; } = new ("Position Z", "Absolute Z position", "mm",0, 100000, 0.01, Layer.HeightPrecision);
- public static PrintParameterModifier BottomLayerCount { get; } = new ("Bottom layers count", "Number of bottom/burn-in layers", "layers",0, ushort.MaxValue, 1, 0);
+ public static PrintParameterModifier PositionZ { get; } = new ("Position Z", "Absolute Z position", "mm", 0, 100000, 0.01, Layer.HeightPrecision);
+ public static PrintParameterModifier BottomLayerCount { get; } = new ("Bottom layer count", "Number of bottom/burn-in layers", "layers", 0, ushort.MaxValue, 1, 0);
+ public static PrintParameterModifier TransitionLayerCount { get; } = new ("Transition layer count", "Number of transition layers", "layers",0, ushort.MaxValue, 1, 0);
public static PrintParameterModifier BottomLightOffDelay { get; } = new("Bottom light-off seconds", "Total motor movement time + rest time to wait before cure a new bottom layer", "s");
public static PrintParameterModifier LightOffDelay { get; } = new("Light-off seconds", "Total motor movement time + rest time to wait before cure a new layer", "s");
@@ -162,8 +177,8 @@ namespace UVtools.Core.FileFormats
public static PrintParameterModifier BottomWaitTimeAfterCure { get; } = new("Bottom wait after cure", "Time to wait/rest after cure a new bottom layer\nChitubox: Rest before lift\nLychee: Wait after print", "s");
public static PrintParameterModifier WaitTimeAfterCure { get; } = new("Wait after cure", "Time to wait/rest after cure a new bottom layer\nChitubox: Rest before lift\nLychee: Wait after print", "s");
- public static PrintParameterModifier BottomLiftHeight { get; } = new ("Bottom lift height", "Bottom lift/peel height between layers", "mm", 1);
- public static PrintParameterModifier LiftHeight { get; } = new ("Lift height", @"Lift/peel height between layers", "mm", 1);
+ public static PrintParameterModifier BottomLiftHeight { get; } = new ("Bottom lift height", "Bottom lift/peel height between layers", "mm");
+ public static PrintParameterModifier LiftHeight { get; } = new ("Lift height", @"Lift/peel height between layers", "mm");
public static PrintParameterModifier BottomLiftSpeed { get; } = new ("Bottom lift speed", null, "mm/min", 10, 5000, 5);
public static PrintParameterModifier LiftSpeed { get; } = new ("Lift speed", null, "mm/min", 10, 5000, 5);
@@ -789,6 +804,8 @@ namespace UVtools.Core.FileFormats
private byte _antiAliasing = 1;
private ushort _bottomLayerCount = DefaultBottomLayerCount;
+ private ushort _transitionLayerCount = DefaultTransitionLayerCount;
+
private float _bottomLightOffDelay;
private float _lightOffDelay;
@@ -1056,7 +1073,7 @@ namespace UVtools.Core.FileFormats
public Layer LastBottomLayer => LayerManager.LastOrDefault(layer => layer.IsBottomLayer);
/// <summary>
- /// Gets the first layer normal layer
+ /// Gets the first normal layer
/// </summary>
public Layer FirstNormalLayer => LayerManager.FirstOrDefault(layer => layer.IsNormalLayer);
@@ -1066,6 +1083,30 @@ namespace UVtools.Core.FileFormats
public Layer LastLayer => LayerManager.LastLayer;
/// <summary>
+ /// Gets all bottom layers
+ /// </summary>
+ /// <returns></returns>
+ public IEnumerable<Layer> BottomLayers => LayerManager.BottomLayers;
+
+ /// <summary>
+ /// Gets all normal layers
+ /// </summary>
+ /// <returns></returns>
+ public IEnumerable<Layer> NormalLayers => LayerManager.NormalLayers;
+
+ /// <summary>
+ /// Gets all transition layers
+ /// </summary>
+ /// <returns></returns>
+ public IEnumerable<Layer> TransitionLayers => LayerManager.TransitionLayers;
+
+ /// <summary>
+ /// Gets all layers that use TSMC values
+ /// </summary>
+ /// <returns></returns>
+ public IEnumerable<Layer> TsmcLayers => LayerManager.TsmcLayers;
+
+ /// <summary>
/// Gets the bounding rectangle of the object
/// </summary>
public Rectangle BoundingRectangle => LayerManager.BoundingRectangle;
@@ -1377,6 +1418,44 @@ namespace UVtools.Core.FileFormats
}
/// <summary>
+ /// Gets the transition layer type
+ /// </summary>
+ public virtual TransitionLayerTypes TransitionLayerType => TransitionLayerTypes.Firmware;
+
+ /// <summary>
+ /// Gets or sets the number of transition layers
+ /// </summary>
+ public virtual ushort TransitionLayerCount
+ {
+ get => _transitionLayerCount;
+ set
+ {
+ RaiseAndSet(ref _transitionLayerCount, (ushort)Math.Min(value, MaximumPossibleTransitionLayerCount));
+ RaisePropertyChanged(nameof(HaveTransitionLayers));
+ }
+ }
+
+ /// <summary>
+ /// Gets if have transition layers
+ /// </summary>
+ public bool HaveTransitionLayers => _transitionLayerCount > 0;
+
+ /// <summary>
+ /// Gets the maximum transition layers this layer collection supports
+ /// </summary>
+ public uint MaximumPossibleTransitionLayerCount
+ {
+ get
+ {
+ if (BottomLayerCount == 0) return 0;
+ if (LayerManager.Layers is null) return uint.MaxValue;
+ int layerCount = (int)LayerCount - BottomLayerCount - 1;
+ if (layerCount <= 0) return 0;
+ return (uint)layerCount;
+ }
+ }
+
+ /// <summary>
/// Gets the number of normal layer count
/// </summary>
public uint NormalLayerCount => LayerCount - BottomLayerCount;
@@ -1785,10 +1864,10 @@ namespace UVtools.Core.FileFormats
get
{
float speed = float.MaxValue;
- if (BottomLiftSpeed > 0) speed = Math.Min(speed, BottomLiftSpeed);
- if (BottomLiftSpeed2 > 0) speed = Math.Min(speed, BottomLiftSpeed2);
- if (BottomRetractSpeed > 0) speed = Math.Min(speed, BottomRetractSpeed);
- if (BottomRetractSpeed2 > 0) speed = Math.Min(speed, BottomRetractSpeed2);
+ if (BottomLiftSpeed > 0) speed = Math.Min(speed, BottomLiftSpeed);
+ if (CanUseBottomLiftSpeed2 && BottomLiftSpeed2 > 0) speed = Math.Min(speed, BottomLiftSpeed2);
+ if (CanUseBottomRetractSpeed && BottomRetractSpeed > 0) speed = Math.Min(speed, BottomRetractSpeed);
+ if (CanUseBottomRetractSpeed2 && BottomRetractSpeed2 > 0) speed = Math.Min(speed, BottomRetractSpeed2);
if (Math.Abs(speed - float.MaxValue) < 0.01) return 0;
return speed;
@@ -1803,10 +1882,10 @@ namespace UVtools.Core.FileFormats
get
{
float speed = float.MaxValue;
- if (LiftSpeed > 0) speed = Math.Min(speed, LiftSpeed);
- if (LiftSpeed2 > 0) speed = Math.Min(speed, LiftSpeed2);
- if (RetractSpeed > 0) speed = Math.Min(speed, RetractSpeed);
- if (RetractSpeed2 > 0) speed = Math.Min(speed, RetractSpeed2);
+ if (LiftSpeed > 0) speed = Math.Min(speed, LiftSpeed);
+ if (CanUseLiftSpeed2 && LiftSpeed2 > 0) speed = Math.Min(speed, LiftSpeed2);
+ if (CanUseRetractSpeed && RetractSpeed > 0) speed = Math.Min(speed, RetractSpeed);
+ if (CanUseRetractSpeed2 && RetractSpeed2 > 0) speed = Math.Min(speed, RetractSpeed2);
if (Math.Abs(speed - float.MaxValue) < 0.01) return 0;
return speed;
@@ -1837,9 +1916,9 @@ namespace UVtools.Core.FileFormats
get
{
float speed = BottomLiftSpeed;
- speed = Math.Max(speed, BottomLiftSpeed2);
- speed = Math.Max(speed, BottomRetractSpeed);
- speed = Math.Max(speed, BottomRetractSpeed2);
+ if (CanUseBottomLiftSpeed2) speed = Math.Max(speed, BottomLiftSpeed2);
+ if (CanUseBottomRetractSpeed) speed = Math.Max(speed, BottomRetractSpeed);
+ if (CanUseBottomRetractSpeed2) speed = Math.Max(speed, BottomRetractSpeed2);
return speed;
}
@@ -1853,9 +1932,9 @@ namespace UVtools.Core.FileFormats
get
{
float speed = LiftSpeed;
- speed = Math.Max(speed, LiftSpeed2);
- speed = Math.Max(speed, RetractSpeed);
- speed = Math.Max(speed, RetractSpeed2);
+ if (CanUseLiftSpeed2) speed = Math.Max(speed, LiftSpeed2);
+ if (CanUseRetractSpeed) speed = Math.Max(speed, RetractSpeed);
+ if (CanUseRetractSpeed2) speed = Math.Max(speed, RetractSpeed2);
return speed;
}
@@ -1867,6 +1946,7 @@ namespace UVtools.Core.FileFormats
public float MaximumSpeed => Math.Max(MaximumBottomSpeed, MaximumNormalSpeed);
public bool CanUseBottomLayerCount => HavePrintParameterModifier(PrintParameterModifier.BottomLayerCount);
+ public bool CanUseTransitionLayerCount => HavePrintParameterModifier(PrintParameterModifier.TransitionLayerCount);
public bool CanUseBottomLightOffDelay => HavePrintParameterModifier(PrintParameterModifier.BottomLightOffDelay);
public bool CanUseLightOffDelay => HavePrintParameterModifier(PrintParameterModifier.LightOffDelay);
@@ -2488,9 +2568,25 @@ namespace UVtools.Core.FileFormats
)
{
LayerManager.RebuildLayersProperties(false, e.PropertyName);
+ if(e.PropertyName
+ is nameof(BottomLayerCount)
+ or nameof(BottomExposureTime)
+ or nameof(ExposureTime)
+ && TransitionLayerType == TransitionLayerTypes.Software
+ ) ResetCurrentTransitionLayers(false);
+
+ if(e.PropertyName
+ is not nameof(BottomLightPWM)
+ and not nameof(LightPWM)
+ ) UpdatePrintTimeQueued();
+
+ return;
+ }
- if(e.PropertyName != nameof(BottomLightPWM) && e.PropertyName != nameof(LightPWM))
- UpdatePrintTimeQueued();
+ // Fix transition layers times in software mode
+ if (e.PropertyName is nameof(TransitionLayerCount) && TransitionLayerType == TransitionLayerTypes.Software)
+ {
+ ResetCurrentTransitionLayers();
return;
}
}
@@ -3005,6 +3101,47 @@ namespace UVtools.Core.FileFormats
}
/// <summary>
+ /// Re-set exposure time to the transition layers
+ /// </summary>
+ /// <param name="resetExposureTimes">True to default all the previous transition layers exposure time, otherwise false</param>
+ public void ResetCurrentTransitionLayers(bool resetExposureTimes = true)
+ {
+ if (TransitionLayerType != TransitionLayerTypes.Software) return;
+ SetTransitionLayers(TransitionLayerCount, resetExposureTimes);
+ }
+
+ /// <summary>
+ /// Set transition layers and exposure times, but do not set that count to file property <see cref="TransitionLayerCount"/>
+ /// </summary>
+ /// <param name="transitionLayerCount">Number of transition layers to set</param>
+ /// <param name="resetExposureTimes">True to default all the previous transition layers exposure time, otherwise false</param>
+ public void SetTransitionLayers(ushort transitionLayerCount, bool resetExposureTimes = true)
+ {
+ if (resetExposureTimes)
+ {
+ for (uint layerIndex = BottomLayerCount; layerIndex < LayerCount; layerIndex++)
+ {
+ var layer = this[layerIndex];
+ if (layer.ExposureTime == ExposureTime) break; // First equal layer, transition ended
+
+ layer.ExposureTime = ExposureTime;
+ }
+ }
+
+ if (transitionLayerCount == 0) return;
+
+ float increment = Math.Max((BottomExposureTime - ExposureTime) / (transitionLayerCount + 1), 0f);
+ if (increment <= 0) return;
+
+ uint appliedLayers = 0;
+ for (uint layerIndex = BottomLayerCount; appliedLayers < transitionLayerCount && layerIndex < LayerCount; layerIndex++)
+ {
+ appliedLayers++;
+ this[layerIndex].ExposureTime = Math.Clamp(BottomExposureTime - (increment * appliedLayers), ExposureTime, BottomExposureTime);
+ }
+ }
+
+ /// <summary>
/// Get height in mm from layer height
/// </summary>
/// <param name="layerIndex"></param>
@@ -3052,6 +3189,11 @@ namespace UVtools.Core.FileFormats
PrintParameterModifier.BottomLayerCount.Value = BottomLayerCount;
}
+ if (PrintParameterModifiers.Contains(PrintParameterModifier.TransitionLayerCount))
+ {
+ PrintParameterModifier.TransitionLayerCount.Value = TransitionLayerCount;
+ }
+
if (PrintParameterModifiers.Contains(PrintParameterModifier.BottomLightOffDelay))
{
PrintParameterModifier.BottomLightOffDelay.Value = (decimal)BottomLightOffDelay;
@@ -3272,6 +3414,9 @@ namespace UVtools.Core.FileFormats
if (ReferenceEquals(modifier, PrintParameterModifier.BottomLayerCount))
return BottomLayerCount;
+ if (ReferenceEquals(modifier, PrintParameterModifier.TransitionLayerCount))
+ return TransitionLayerCount;
+
if (ReferenceEquals(modifier, PrintParameterModifier.BottomLightOffDelay))
return BottomLightOffDelay;
if (ReferenceEquals(modifier, PrintParameterModifier.LightOffDelay))
@@ -3353,6 +3498,12 @@ namespace UVtools.Core.FileFormats
return true;
}
+ if (ReferenceEquals(modifier, PrintParameterModifier.TransitionLayerCount))
+ {
+ TransitionLayerCount = (ushort)value;
+ return true;
+ }
+
if (ReferenceEquals(modifier, PrintParameterModifier.BottomLightOffDelay))
{
BottomLightOffDelay = (float)value;
@@ -3746,6 +3897,7 @@ namespace UVtools.Core.FileFormats
slicerFile.AntiAliasing = ValidateAntiAliasingLevel();
slicerFile.LayerCount = LayerManager.LayerCount;
slicerFile.BottomLayerCount = BottomLayerCount;
+ slicerFile.TransitionLayerCount = TransitionLayerCount;
slicerFile.LayerHeight = LayerHeight;
slicerFile.ResolutionX = ResolutionX;
slicerFile.ResolutionY = ResolutionY;
diff --git a/UVtools.Core/FileFormats/GenericZIPFile.cs b/UVtools.Core/FileFormats/GenericZIPFile.cs
index 34b353c..b90e038 100644
--- a/UVtools.Core/FileFormats/GenericZIPFile.cs
+++ b/UVtools.Core/FileFormats/GenericZIPFile.cs
@@ -229,7 +229,7 @@ namespace UVtools.Core.FileFormats
using var stream = entry.Open();
ManifestFile = (GenericZipManifest) serializer.Deserialize(stream);
}
- catch (Exception e)
+ catch (Exception)
{
// Not required
//Clear();
diff --git a/UVtools.Core/FileFormats/PHZFile.cs b/UVtools.Core/FileFormats/PHZFile.cs
index ea78b7f..9ad433f 100644
--- a/UVtools.Core/FileFormats/PHZFile.cs
+++ b/UVtools.Core/FileFormats/PHZFile.cs
@@ -261,13 +261,12 @@ namespace UVtools.Core.FileFormats
[FieldOrder(45)] public uint EncryptionMode { get; set; } = 28;
/// <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.
+ /// Gets the minutes since Jan 1, 1970 UTC
/// </summary>
- [FieldOrder(46)] public uint MysteriousId { get; set; }
+ [FieldOrder(46)] public uint ModifiedTimestampMinutes { get; set; } = (uint)DateTimeExtensions.Timestamp.TotalMinutes;
+
+ [Ignore] public string ModifiedDate => DateTimeExtensions.GetDateTimeFromTimestampMinutes(ModifiedTimestampMinutes).ToString("dd/MM/yyyy HH:mm");
- /// <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(47)] public uint AntiAliasLevelInfo { get; set; }
[FieldOrder(48)] public uint SoftwareVersion { get; set; } = 0x01060300;
@@ -281,7 +280,7 @@ namespace UVtools.Core.FileFormats
public override string ToString()
{
- return $"{nameof(Magic)}: {Magic}, {nameof(Version)}: {Version}, {nameof(LayerHeightMilimeter)}: {LayerHeightMilimeter}, {nameof(LayerExposureSeconds)}: {LayerExposureSeconds}, {nameof(BottomExposureSeconds)}: {BottomExposureSeconds}, {nameof(BottomLayersCount)}: {BottomLayersCount}, {nameof(ResolutionX)}: {ResolutionX}, {nameof(ResolutionY)}: {ResolutionY}, {nameof(PreviewLargeOffsetAddress)}: {PreviewLargeOffsetAddress}, {nameof(LayersDefinitionOffsetAddress)}: {LayersDefinitionOffsetAddress}, {nameof(LayerCount)}: {LayerCount}, {nameof(PreviewSmallOffsetAddress)}: {PreviewSmallOffsetAddress}, {nameof(PrintTime)}: {PrintTime}, {nameof(ProjectorType)}: {ProjectorType}, {nameof(AntiAliasLevel)}: {AntiAliasLevel}, {nameof(LightPWM)}: {LightPWM}, {nameof(BottomLightPWM)}: {BottomLightPWM}, {nameof(Padding1)}: {Padding1}, {nameof(Padding2)}: {Padding2}, {nameof(OverallHeightMilimeter)}: {OverallHeightMilimeter}, {nameof(BedSizeX)}: {BedSizeX}, {nameof(BedSizeY)}: {BedSizeY}, {nameof(BedSizeZ)}: {BedSizeZ}, {nameof(EncryptionKey)}: {EncryptionKey}, {nameof(BottomLightOffDelay)}: {BottomLightOffDelay}, {nameof(LightOffDelay)}: {LightOffDelay}, {nameof(BottomLayersCount2)}: {BottomLayersCount2}, {nameof(Padding3)}: {Padding3}, {nameof(BottomLiftHeight)}: {BottomLiftHeight}, {nameof(BottomLiftSpeed)}: {BottomLiftSpeed}, {nameof(LiftHeight)}: {LiftHeight}, {nameof(LiftSpeed)}: {LiftSpeed}, {nameof(RetractSpeed)}: {RetractSpeed}, {nameof(VolumeMl)}: {VolumeMl}, {nameof(WeightG)}: {WeightG}, {nameof(CostDollars)}: {CostDollars}, {nameof(Padding4)}: {Padding4}, {nameof(MachineNameAddress)}: {MachineNameAddress}, {nameof(MachineNameSize)}: {MachineNameSize}, {nameof(MachineName)}: {MachineName}, {nameof(Padding5)}: {Padding5}, {nameof(Padding6)}: {Padding6}, {nameof(Padding7)}: {Padding7}, {nameof(Padding8)}: {Padding8}, {nameof(Padding9)}: {Padding9}, {nameof(Padding10)}: {Padding10}, {nameof(EncryptionMode)}: {EncryptionMode}, {nameof(MysteriousId)}: {MysteriousId}, {nameof(AntiAliasLevelInfo)}: {AntiAliasLevelInfo}, {nameof(SoftwareVersion)}: {SoftwareVersion}, {nameof(Padding11)}: {Padding11}, {nameof(Padding12)}: {Padding12}, {nameof(Padding13)}: {Padding13}, {nameof(Padding14)}: {Padding14}, {nameof(Padding15)}: {Padding15}, {nameof(Padding16)}: {Padding16}";
+ return $"{nameof(Magic)}: {Magic}, {nameof(Version)}: {Version}, {nameof(LayerHeightMilimeter)}: {LayerHeightMilimeter}, {nameof(LayerExposureSeconds)}: {LayerExposureSeconds}, {nameof(BottomExposureSeconds)}: {BottomExposureSeconds}, {nameof(BottomLayersCount)}: {BottomLayersCount}, {nameof(ResolutionX)}: {ResolutionX}, {nameof(ResolutionY)}: {ResolutionY}, {nameof(PreviewLargeOffsetAddress)}: {PreviewLargeOffsetAddress}, {nameof(LayersDefinitionOffsetAddress)}: {LayersDefinitionOffsetAddress}, {nameof(LayerCount)}: {LayerCount}, {nameof(PreviewSmallOffsetAddress)}: {PreviewSmallOffsetAddress}, {nameof(PrintTime)}: {PrintTime}, {nameof(ProjectorType)}: {ProjectorType}, {nameof(AntiAliasLevel)}: {AntiAliasLevel}, {nameof(LightPWM)}: {LightPWM}, {nameof(BottomLightPWM)}: {BottomLightPWM}, {nameof(Padding1)}: {Padding1}, {nameof(Padding2)}: {Padding2}, {nameof(OverallHeightMilimeter)}: {OverallHeightMilimeter}, {nameof(BedSizeX)}: {BedSizeX}, {nameof(BedSizeY)}: {BedSizeY}, {nameof(BedSizeZ)}: {BedSizeZ}, {nameof(EncryptionKey)}: {EncryptionKey}, {nameof(BottomLightOffDelay)}: {BottomLightOffDelay}, {nameof(LightOffDelay)}: {LightOffDelay}, {nameof(BottomLayersCount2)}: {BottomLayersCount2}, {nameof(Padding3)}: {Padding3}, {nameof(BottomLiftHeight)}: {BottomLiftHeight}, {nameof(BottomLiftSpeed)}: {BottomLiftSpeed}, {nameof(LiftHeight)}: {LiftHeight}, {nameof(LiftSpeed)}: {LiftSpeed}, {nameof(RetractSpeed)}: {RetractSpeed}, {nameof(VolumeMl)}: {VolumeMl}, {nameof(WeightG)}: {WeightG}, {nameof(CostDollars)}: {CostDollars}, {nameof(Padding4)}: {Padding4}, {nameof(MachineNameAddress)}: {MachineNameAddress}, {nameof(MachineNameSize)}: {MachineNameSize}, {nameof(MachineName)}: {MachineName}, {nameof(Padding5)}: {Padding5}, {nameof(Padding6)}: {Padding6}, {nameof(Padding7)}: {Padding7}, {nameof(Padding8)}: {Padding8}, {nameof(Padding9)}: {Padding9}, {nameof(Padding10)}: {Padding10}, {nameof(EncryptionMode)}: {EncryptionMode}, {nameof(ModifiedTimestampMinutes)}: {ModifiedTimestampMinutes}, {nameof(ModifiedDate)}: {ModifiedDate}, {nameof(AntiAliasLevelInfo)}: {AntiAliasLevelInfo}, {nameof(SoftwareVersion)}: {SoftwareVersion}, {nameof(Padding11)}: {Padding11}, {nameof(Padding12)}: {Padding12}, {nameof(Padding13)}: {Padding13}, {nameof(Padding14)}: {Padding14}, {nameof(Padding15)}: {Padding15}, {nameof(Padding16)}: {Padding16}";
}
}
#endregion
@@ -1051,6 +1050,7 @@ namespace UVtools.Core.FileFormats
}
}
+ HeaderSettings.ModifiedTimestampMinutes = (uint) DateTimeExtensions.TimestampMinutes;
outputFile.Seek(0, SeekOrigin.Begin);
Helpers.SerializeWriteFileStream(outputFile, HeaderSettings);
@@ -1153,6 +1153,7 @@ namespace UVtools.Core.FileFormats
protected override void PartialSaveInternally(OperationProgress progress)
{
+ HeaderSettings.ModifiedTimestampMinutes = (uint) DateTimeExtensions.TimestampMinutes;
using var outputFile = new FileStream(FileFullPath, FileMode.Open, FileAccess.Write);
outputFile.Seek(0, SeekOrigin.Begin);
Helpers.SerializeWriteFileStream(outputFile, HeaderSettings);
diff --git a/UVtools.Core/FileFormats/PhotonWorkshopFile.cs b/UVtools.Core/FileFormats/PhotonWorkshopFile.cs
index ddc6081..d66690e 100644
--- a/UVtools.Core/FileFormats/PhotonWorkshopFile.cs
+++ b/UVtools.Core/FileFormats/PhotonWorkshopFile.cs
@@ -1056,6 +1056,7 @@ namespace UVtools.Core.FileFormats
return new[]
{
PrintParameterModifier.BottomLayerCount,
+ PrintParameterModifier.TransitionLayerCount,
PrintParameterModifier.WaitTimeBeforeCure,
@@ -1262,6 +1263,14 @@ namespace UVtools.Core.FileFormats
set => base.BottomLayerCount = (ushort) (HeaderSettings.BottomLayersCount = value);
}
+ public override TransitionLayerTypes TransitionLayerType => TransitionLayerTypes.Firmware;
+
+ public override ushort TransitionLayerCount
+ {
+ get => (ushort)(Version >= VERSION_516 ? HeaderSettings.TransitionLayerCount : 0);
+ set => base.TransitionLayerCount = (ushort)(HeaderSettings.TransitionLayerCount = Math.Min(value, MaximumPossibleTransitionLayerCount));
+ }
+
public override float BottomLightOffDelay => BottomWaitTimeBeforeCure;
public override float LightOffDelay => WaitTimeBeforeCure;
diff --git a/UVtools.Core/FileFormats/SL1File.cs b/UVtools.Core/FileFormats/SL1File.cs
index 34c45fa..115129e 100644
--- a/UVtools.Core/FileFormats/SL1File.cs
+++ b/UVtools.Core/FileFormats/SL1File.cs
@@ -31,6 +31,7 @@ namespace UVtools.Core.FileFormats
public const string Keyword_FileFormat = "FILEFORMAT";
public const string Keyword_FileVersion = "FILEVERSION";
+ public const string Keyword_TransitionLayerCount = "TransitionLayerCount";
public const string Keyword_BottomLightOffDelay = "BottomLightOffDelay";
public const string Keyword_LightOffDelay = "LightOffDelay";
public const string Keyword_BottomWaitTimeBeforeCure = "BottomWaitTimeBeforeCure";
@@ -679,9 +680,10 @@ namespace UVtools.Core.FileFormats
{
throw new FileLoadException($"Malformed file: {IniPrusaslicer} is missing.");
}
-
+
SuppressRebuildPropertiesWork(() =>
{
+ TransitionLayerCount = LookupCustomValue<ushort>(Keyword_TransitionLayerCount, 0);
BottomLightOffDelay = LookupCustomValue(Keyword_BottomLightOffDelay, 0f);
LightOffDelay = LookupCustomValue(Keyword_LightOffDelay, 0f);
@@ -716,7 +718,7 @@ namespace UVtools.Core.FileFormats
BottomLightPWM = LookupCustomValue(Keyword_BottomLightPWM, DefaultLightPWM);
LightPWM = LookupCustomValue(Keyword_LightPWM, DefaultBottomLightPWM);
});
-
+
LayerManager.Init(OutputConfigSettings.NumSlow + OutputConfigSettings.NumFast, DecodeType == FileDecodeType.Partial);
progress.ItemCount = LayerCount;
@@ -754,6 +756,11 @@ namespace UVtools.Core.FileFormats
}
}
+ if (TransitionLayerCount > 0)
+ {
+ SetTransitionLayers(TransitionLayerCount, false);
+ }
+
LayerManager.GetBoundingRectangle(progress);
Statistics.ExecutionTime.Stop();
diff --git a/UVtools.Core/GCode/GCodeBuilder.cs b/UVtools.Core/GCode/GCodeBuilder.cs
index 4ee83cc..b1e9cd3 100644
--- a/UVtools.Core/GCode/GCodeBuilder.cs
+++ b/UVtools.Core/GCode/GCodeBuilder.cs
@@ -678,10 +678,10 @@ namespace UVtools.Core.GCode
switch (GCodePositioningType)
{
case GCodePositioningTypes.Absolute:
- AppendMoveGx(layer.PositionZ, lastZPosition < layer.PositionZ ? Math.Max(liftSpeed, liftSpeed2) : Math.Max(retractSpeed, retractSpeed2));
+ AppendMoveGx(layer.PositionZ, lastZPosition < layer.PositionZ ? liftSpeed : retractSpeed);
break;
case GCodePositioningTypes.Partial:
- AppendMoveGx(Layer.RoundHeight(layer.PositionZ - lastZPosition), lastZPosition < layer.PositionZ ? Math.Max(liftSpeed, liftSpeed2) : Math.Max(retractSpeed, retractSpeed2));
+ AppendMoveGx(Layer.RoundHeight(layer.PositionZ - lastZPosition), lastZPosition < layer.PositionZ ? liftSpeed : retractSpeed);
break;
}
@@ -899,6 +899,7 @@ namespace UVtools.Core.GCode
var waitTime = float.Parse(match.Groups[1].Value);
if (layerBlock.PositionZ.HasValue &&
+ layerBlock.LiftHeight.HasValue &&
!layerBlock.RetractSpeed.HasValue) // Must be wait time after lift, if not, don't blame me!
{
layerBlock.WaitTimeAfterLift ??= 0;
@@ -922,8 +923,7 @@ namespace UVtools.Core.GCode
if (layerBlock.IsAfterLightOff)
{
- if (!layerBlock.WaitTimeBeforeCure
- .HasValue) // Novamaker fix, delay on last line, broke logic but safer
+ if (!layerBlock.WaitTimeBeforeCure.HasValue) // Novamaker fix, delay on last line, broke logic but safer
{
layerBlock.WaitTimeBeforeCure ??= 0;
layerBlock.WaitTimeBeforeCure += ConvertToSeconds(waitTime);
diff --git a/UVtools.Core/GCode/GCodeLayer.cs b/UVtools.Core/GCode/GCodeLayer.cs
index 2ff853e..659a0df 100644
--- a/UVtools.Core/GCode/GCodeLayer.cs
+++ b/UVtools.Core/GCode/GCodeLayer.cs
@@ -208,6 +208,14 @@ namespace UVtools.Core.GCode
if (partialPositionZ == 0) continue;
var height = Math.Abs(partialPositionZ);
+ if (currentZ < PreviousPositionZ) // Check for inverse lifts
+ {
+ LiftHeight ??= 0;
+ LiftHeight = Math.Min(LiftHeight.Value, -currentZ);
+ LiftSpeed = speed;
+ continue;
+ }
+
if (partialPositionZ > 0) // Is a lift
{
// Lift 1
@@ -241,11 +249,23 @@ namespace UVtools.Core.GCode
}
// Sanitize
- if (PositionZ.HasValue && LiftHeight.HasValue && !IsExposed) // Lift before exposure order, need to remove layer height as offset
+ if (PositionZ.HasValue && LiftHeight.HasValue)
+ {
+ if (LiftHeight < 0) // Inverse lift
+ {
+ LiftHeight = Layer.RoundHeight(Math.Abs(PositionZ.Value + LiftHeight.Value));
+ }
+ else if (!IsExposed) // Lift before exposure order, need to remove layer height as offset
+ {
+ var liftHeight = Layer.RoundHeight(LiftHeight.Value - (PositionZ.Value - PreviousPositionZ));
+ if (liftHeight <= 0) return; // Something not right or not the correct moment, skip
+ LiftHeight = liftHeight;
+ }
+ }
+
+ if (PositionZ.HasValue && LiftHeight.HasValue && !IsExposed)
{
- var liftHeight = Layer.RoundHeight(LiftHeight.Value - (PositionZ.Value - PreviousPositionZ));
- if(liftHeight <= 0) return; // Something not right or not the correct moment, skip
- LiftHeight = liftHeight;
+
}
if (RetractHeight2.HasValue) // Need to fix the purpose of this value
@@ -272,7 +292,7 @@ namespace UVtools.Core.GCode
PositionZ ??= PreviousPositionZ;
layer.PositionZ = PositionZ.Value;
layer.WaitTimeBeforeCure = WaitTimeBeforeCure ?? 0;
- layer.ExposureTime = ExposureTime ?? SlicerFile.GetBottomOrNormalValue(layer, SlicerFile.BottomExposureTime, SlicerFile.ExposureTime);
+ layer.ExposureTime = ExposureTime ?? 0;
layer.WaitTimeAfterCure = WaitTimeAfterCure ?? 0;
layer.LiftHeight = LiftHeight ?? 0;
layer.LiftSpeed = LiftSpeed ?? SlicerFile.GetBottomOrNormalValue(layer, SlicerFile.BottomLiftSpeed, SlicerFile.LiftSpeed);
diff --git a/UVtools.Core/Layers/Layer.cs b/UVtools.Core/Layers/Layer.cs
index 60283f4..408d5d6 100644
--- a/UVtools.Core/Layers/Layer.cs
+++ b/UVtools.Core/Layers/Layer.cs
@@ -154,6 +154,18 @@ namespace UVtools.Core.Layers
public bool IsNormalLayer => !IsBottomLayer;
/// <summary>
+ /// Gets if this layer is also an transition layer
+ /// </summary>
+ public bool IsTransitionLayer
+ {
+ get
+ {
+ if (SlicerFile is null) return false;
+ return SlicerFile.TransitionLayerCount <= Number;
+ }
+ }
+
+ /// <summary>
/// Gets the previous layer, returns null if no previous layer
/// </summary>
public Layer PreviousLayer
diff --git a/UVtools.Core/Layers/LayerManager.cs b/UVtools.Core/Layers/LayerManager.cs
index cfa7611..1863120 100644
--- a/UVtools.Core/Layers/LayerManager.cs
+++ b/UVtools.Core/Layers/LayerManager.cs
@@ -140,6 +140,30 @@ namespace UVtools.Core
/// </summary>
public Layer LargestLayer => _layers?.MaxBy(layer => layer.NonZeroPixelCount).FirstOrDefault();
+ /// <summary>
+ /// Gets all bottom layers
+ /// </summary>
+ /// <returns></returns>
+ public IEnumerable<Layer> BottomLayers => this.Where(layer => layer.IsBottomLayer);
+
+ /// <summary>
+ /// Gets all normal layers
+ /// </summary>
+ /// <returns></returns>
+ public IEnumerable<Layer> NormalLayers => this.Where(layer => layer.IsNormalLayer);
+
+ /// <summary>
+ /// Gets all transition layers
+ /// </summary>
+ /// <returns></returns>
+ public IEnumerable<Layer> TransitionLayers => this.Where(layer => layer.IsTransitionLayer);
+
+ /// <summary>
+ /// Gets all layers that use TSMC values
+ /// </summary>
+ /// <returns></returns>
+ public IEnumerable<Layer> TsmcLayers => this.Where(layer => layer.IsUsingTSMC);
+
/// <summary>
/// Gets the bounding rectangle of the object
diff --git a/UVtools.Core/Objects/RangeObservableCollection.cs b/UVtools.Core/Objects/RangeObservableCollection.cs
index fb77ad4..0e73004 100644
--- a/UVtools.Core/Objects/RangeObservableCollection.cs
+++ b/UVtools.Core/Objects/RangeObservableCollection.cs
@@ -283,7 +283,7 @@
return 0;
//List<T>? cluster = null;
- var clusterIndex = -1;
+ //var clusterIndex = -1;
var removedCount = 0;
using (BlockReentrancy())
diff --git a/UVtools.Core/Operations/OperationCalibrateElephantFoot.cs b/UVtools.Core/Operations/OperationCalibrateElephantFoot.cs
index a3c2ff3..f84c3b0 100644
--- a/UVtools.Core/Operations/OperationCalibrateElephantFoot.cs
+++ b/UVtools.Core/Operations/OperationCalibrateElephantFoot.cs
@@ -775,6 +775,7 @@ namespace UVtools.Core.Operations
SlicerFile.BottomExposureTime = (float)BottomExposure;
SlicerFile.ExposureTime = (float)NormalExposure;
SlicerFile.BottomLayerCount = BottomLayers;
+ SlicerFile.TransitionLayerCount = 0;
SlicerFile.LayerManager.Layers = newLayers;
}, true);
diff --git a/UVtools.Core/Operations/OperationCalibrateExposureFinder.cs b/UVtools.Core/Operations/OperationCalibrateExposureFinder.cs
index 84d6730..2785828 100644
--- a/UVtools.Core/Operations/OperationCalibrateExposureFinder.cs
+++ b/UVtools.Core/Operations/OperationCalibrateExposureFinder.cs
@@ -2240,6 +2240,7 @@ namespace UVtools.Core.Operations
SlicerFile.BottomExposureTime = (float)BottomExposure;
SlicerFile.ExposureTime = (float)NormalExposure;
SlicerFile.BottomLayerCount = BottomLayers;
+ SlicerFile.TransitionLayerCount = 0;
SlicerFile.LayerManager.Layers = newLayers.ToArray();
});
diff --git a/UVtools.Core/Operations/OperationCalibrateGrayscale.cs b/UVtools.Core/Operations/OperationCalibrateGrayscale.cs
index 91d3b66..bc8610a 100644
--- a/UVtools.Core/Operations/OperationCalibrateGrayscale.cs
+++ b/UVtools.Core/Operations/OperationCalibrateGrayscale.cs
@@ -550,6 +550,7 @@ namespace UVtools.Core.Operations
SlicerFile.BottomExposureTime = (float)BottomExposure;
SlicerFile.ExposureTime = (float)NormalExposure;
SlicerFile.BottomLayerCount = BottomLayers;
+ SlicerFile.TransitionLayerCount = 0;
SlicerFile.LayerManager.Layers = newLayers;
}, true);
diff --git a/UVtools.Core/Operations/OperationCalibrateLiftHeight.cs b/UVtools.Core/Operations/OperationCalibrateLiftHeight.cs
index a177d63..c979a23 100644
--- a/UVtools.Core/Operations/OperationCalibrateLiftHeight.cs
+++ b/UVtools.Core/Operations/OperationCalibrateLiftHeight.cs
@@ -431,6 +431,7 @@ namespace UVtools.Core.Operations
SlicerFile.LiftSpeed = (float)_liftSpeed;
SlicerFile.RetractSpeed = (float)_retractSpeed;
SlicerFile.BottomLayerCount = _bottomLayers;
+ SlicerFile.TransitionLayerCount = 0;
SlicerFile.LayerManager.Layers = newLayers;
}, true);
diff --git a/UVtools.Core/Operations/OperationCalibrateTolerance.cs b/UVtools.Core/Operations/OperationCalibrateTolerance.cs
index 935ceef..8b43115 100644
--- a/UVtools.Core/Operations/OperationCalibrateTolerance.cs
+++ b/UVtools.Core/Operations/OperationCalibrateTolerance.cs
@@ -745,6 +745,7 @@ namespace UVtools.Core.Operations
SlicerFile.BottomExposureTime = (float)BottomExposure;
SlicerFile.ExposureTime = (float)NormalExposure;
SlicerFile.BottomLayerCount = BottomLayers;
+ SlicerFile.TransitionLayerCount = 0;
SlicerFile.LayerManager.Layers = newLayers;
}, true);
diff --git a/UVtools.Core/Operations/OperationCalibrateXYZAccuracy.cs b/UVtools.Core/Operations/OperationCalibrateXYZAccuracy.cs
index 8b568ae..a475515 100644
--- a/UVtools.Core/Operations/OperationCalibrateXYZAccuracy.cs
+++ b/UVtools.Core/Operations/OperationCalibrateXYZAccuracy.cs
@@ -802,6 +802,7 @@ namespace UVtools.Core.Operations
SlicerFile.BottomExposureTime = (float)BottomExposure;
SlicerFile.ExposureTime = (float)NormalExposure;
SlicerFile.BottomLayerCount = BottomLayers;
+ SlicerFile.TransitionLayerCount = 0;
SlicerFile.LayerManager.Layers = newLayers;
}, true);
diff --git a/UVtools.Core/Operations/OperationFadeExposureTime.cs b/UVtools.Core/Operations/OperationFadeExposureTime.cs
index 328ea66..345cfbf 100644
--- a/UVtools.Core/Operations/OperationFadeExposureTime.cs
+++ b/UVtools.Core/Operations/OperationFadeExposureTime.cs
@@ -21,6 +21,7 @@ namespace UVtools.Core.Operations
private uint _layerCount = 10;
private decimal _fromExposureTime;
private decimal _toExposureTime;
+ private bool _disableFirmwareTransitionLayers = true;
#endregion
@@ -124,6 +125,12 @@ namespace UVtools.Core.Operations
}
}
+ public bool DisableFirmwareTransitionLayers
+ {
+ get => _disableFirmwareTransitionLayers;
+ set => RaiseAndSetIfChanged(ref _disableFirmwareTransitionLayers, value);
+ }
+
public decimal IncrementValue => Math.Round(IncrementValueRaw, 2);
public decimal IncrementValueRaw => (_toExposureTime - _fromExposureTime) / (LayerRangeCount + 1);
@@ -150,7 +157,7 @@ namespace UVtools.Core.Operations
protected bool Equals(OperationFadeExposureTime other)
{
- return _fromExposureTime == other._fromExposureTime && _toExposureTime == other._toExposureTime && _layerCount == other._layerCount;
+ return _layerCount == other._layerCount && _fromExposureTime == other._fromExposureTime && _toExposureTime == other._toExposureTime && _disableFirmwareTransitionLayers == other._disableFirmwareTransitionLayers;
}
public override bool Equals(object obj)
@@ -158,12 +165,12 @@ namespace UVtools.Core.Operations
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != this.GetType()) return false;
- return Equals((OperationFadeExposureTime)obj);
+ return Equals((OperationFadeExposureTime) obj);
}
public override int GetHashCode()
{
- return HashCode.Combine(_fromExposureTime, _toExposureTime, _layerCount);
+ return HashCode.Combine(_layerCount, _fromExposureTime, _toExposureTime, _disableFirmwareTransitionLayers);
}
#endregion
@@ -174,6 +181,11 @@ namespace UVtools.Core.Operations
{
LayerIndexEnd = LayerIndexStart + _layerCount - 1; // Sanitize
+ if (_disableFirmwareTransitionLayers)
+ {
+ SlicerFile.TransitionLayerCount = 0;
+ }
+
var increment = IncrementValueRaw;
var exposure = _fromExposureTime;
for (uint layerIndex = LayerIndexStart; layerIndex <= LayerIndexEnd; layerIndex++)
diff --git a/UVtools.Core/Operations/OperationTimelapse.cs b/UVtools.Core/Operations/OperationTimelapse.cs
index 075bee4..a2483f5 100644
--- a/UVtools.Core/Operations/OperationTimelapse.cs
+++ b/UVtools.Core/Operations/OperationTimelapse.cs
@@ -40,6 +40,7 @@ namespace UVtools.Core.Operations
private TimelapseRaiseMode _raiseMode = TimelapseRaiseMode.LiftHeight;
private decimal _waitTimeAfterLift = 1;
private decimal _exposureTime = 1;
+ private bool _ensureLastLayer = true;
private bool _useCustomLift;
private decimal _slowLiftHeight = 3;
private decimal _liftSpeed;
@@ -61,7 +62,7 @@ namespace UVtools.Core.Operations
"NOTE: Only use this tool once. It will delay the total print time significantly.";
public override string ConfirmationText =>
- $"raise the platform at every odd-even {_raiseEachNthHeight}mm to Z={_raisePositionZ}mm";
+ $"raise the platform at every odd-even {_raiseEachNthHeight}mm to Z={_raisePositionZ}mm and generate {NumberOfLifts} additional lifts?";
public override string ProgressTitle => "Raising layers";
@@ -113,6 +114,7 @@ namespace UVtools.Core.Operations
if(!RaiseAndSetIfChanged(ref _raiseMode, value)) return;
RaisePropertyChanged(nameof(IsLiftHeightMode));
RaisePropertyChanged(nameof(IsVirtualLayerMode));
+ RaisePropertyChanged(nameof(NumberOfLifts));
}
}
@@ -143,9 +145,17 @@ namespace UVtools.Core.Operations
public decimal RaiseEachNthHeight
{
get => _raiseEachNthHeight;
- set => RaiseAndSetIfChanged(ref _raiseEachNthHeight, Math.Max(0, value));
+ set
+ {
+ if(!RaiseAndSetIfChanged(ref _raiseEachNthHeight, Math.Max(0, Layer.RoundHeight(value)))) return;
+ RaisePropertyChanged(nameof(RaiseEachNthLayers));
+ RaisePropertyChanged(nameof(NumberOfLifts));
+ }
}
+ /// <summary>
+ /// Gets or sets the alternating layer count to raise when, it will raise only at each defined layers and skip the same next layers
+ /// </summary>
public ushort RaiseEachNthLayers
{
get
@@ -153,8 +163,15 @@ namespace UVtools.Core.Operations
if (_raiseEachNthHeight == 0) return 1;
return (ushort)Math.Max(1, _raiseEachNthHeight / (decimal)SlicerFile.LayerHeight);
}
+ set => RaiseEachNthHeight = (decimal)SlicerFile.LayerHeight * value;
}
+ /// <summary>
+ /// Gets the total number of additional lifts
+ /// </summary>
+ public uint NumberOfLifts => (uint)(Math.Min(SlicerFile.PrintHeight, (float)_raisePositionZ) / Math.Max(SlicerFile.LayerHeight, (float)_raiseEachNthHeight))
+ + (_ensureLastLayer && _raiseMode == TimelapseRaiseMode.VirtualLayer ? 1u : 0);
+
public decimal WaitTimeAfterLift
{
get => _waitTimeAfterLift;
@@ -167,6 +184,20 @@ namespace UVtools.Core.Operations
set => RaiseAndSetIfChanged(ref _exposureTime, Math.Max(0, value));
}
+ /// <summary>
+ /// Gets or sets if last layer must be ensured in the sequence,
+ /// If true, it will generate an obligatory additional layer to cover the last layer
+ /// </summary>
+ public bool EnsureLastLayer
+ {
+ get => _ensureLastLayer;
+ set
+ {
+ if(!RaiseAndSetIfChanged(ref _ensureLastLayer, value)) return;
+ RaisePropertyChanged(nameof(NumberOfLifts));
+ }
+ }
+
public bool UseCustomLift
{
get => _useCustomLift;
@@ -215,9 +246,7 @@ namespace UVtools.Core.Operations
#region Constructor
- public OperationTimelapse()
- {
- }
+ public OperationTimelapse() { }
public OperationTimelapse(FileFormat slicerFile) : base(slicerFile)
{
@@ -235,6 +264,7 @@ namespace UVtools.Core.Operations
else
{
if (_retractSpeed <= 0) _retractSpeed = (decimal)SlicerFile.RetractSpeed;
+ if (_retractSpeed2 <= 0) _retractSpeed2 = (decimal)SlicerFile.MaximumSpeed;
}
}
@@ -245,7 +275,7 @@ namespace UVtools.Core.Operations
protected bool Equals(OperationTimelapse other)
{
- return _raisePositionZ == other._raisePositionZ && _outputDummyPixel == other._outputDummyPixel && _raiseEachNthHeight == other._raiseEachNthHeight && _raiseMode == other._raiseMode && _waitTimeAfterLift == other._waitTimeAfterLift && _exposureTime == other._exposureTime && _useCustomLift == other._useCustomLift && _slowLiftHeight == other._slowLiftHeight && _liftSpeed == other._liftSpeed && _liftSpeed2 == other._liftSpeed2 && _slowRetractHeight == other._slowRetractHeight && _retractSpeed == other._retractSpeed && _retractSpeed2 == other._retractSpeed2;
+ return _raisePositionZ == other._raisePositionZ && _outputDummyPixel == other._outputDummyPixel && _raiseEachNthHeight == other._raiseEachNthHeight && _raiseMode == other._raiseMode && _waitTimeAfterLift == other._waitTimeAfterLift && _exposureTime == other._exposureTime && _ensureLastLayer == other._ensureLastLayer && _useCustomLift == other._useCustomLift && _slowLiftHeight == other._slowLiftHeight && _liftSpeed == other._liftSpeed && _liftSpeed2 == other._liftSpeed2 && _slowRetractHeight == other._slowRetractHeight && _retractSpeed == other._retractSpeed && _retractSpeed2 == other._retractSpeed2;
}
public override bool Equals(object obj)
@@ -265,6 +295,7 @@ namespace UVtools.Core.Operations
hashCode.Add((int) _raiseMode);
hashCode.Add(_waitTimeAfterLift);
hashCode.Add(_exposureTime);
+ hashCode.Add(_ensureLastLayer);
hashCode.Add(_useCustomLift);
hashCode.Add(_slowLiftHeight);
hashCode.Add(_liftSpeed);
@@ -293,12 +324,18 @@ namespace UVtools.Core.Operations
{
var virtualLayers = new List<uint>();
float checkpointHeight = SlicerFile[0].PositionZ;
+
for (uint layerIndex = LayerIndexStart; layerIndex <= LayerIndexEnd; layerIndex++)
{
progress++;
var layer = SlicerFile[layerIndex];
- if (_raiseEachNthHeight > 0 && (decimal)Layer.RoundHeight(layer.PositionZ - checkpointHeight) < _raiseEachNthHeight) continue;
if ((decimal)layer.PositionZ >= _raisePositionZ) break; // pass the target height, do not continue
+ if (_raiseMode == TimelapseRaiseMode.VirtualLayer && _ensureLastLayer && layerIndex == LayerIndexEnd)
+ {
+ virtualLayers.Add(layerIndex+1);
+ break;
+ }
+ if (_raiseEachNthHeight > 0 && (decimal)Layer.RoundHeight(layer.PositionZ - checkpointHeight) < _raiseEachNthHeight) continue;
checkpointHeight = layer.PositionZ;
switch (_raiseMode)
@@ -355,70 +392,88 @@ namespace UVtools.Core.Operations
if (virtualLayers.Count > 0 && _raiseMode == TimelapseRaiseMode.VirtualLayer)
{
+ var minLiftSpeed = CanUseCustomLift ? (float)Math.Min(_liftSpeed, _liftSpeed2) : SlicerFile.MinimumNormalSpeed;
+ var minRetractSpeed = CanUseCustomLift ? (float)Math.Min(_retractSpeed, _retractSpeed2) : SlicerFile.MinimumNormalSpeed;
+ var maxLiftSpeed = CanUseCustomLift ? (float)Math.Max(_liftSpeed, _liftSpeed2) : SlicerFile.MaximumSpeed;
+ var maxRetractSpeed = CanUseCustomLift ? (float)Math.Max(_retractSpeed, _retractSpeed2) : SlicerFile.MaximumSpeed;
+
using var mat = _outputDummyPixel
? SlicerFile.CreateMatWithDummyPixel()
: SlicerFile.CreateMat();
- var layer = new Layer(SlicerFile.LayerCount, mat, SlicerFile)
+ var virtualSlowLiftLayer = new Layer(SlicerFile.LayerCount, mat, SlicerFile)
{
- PositionZ = (float) _raisePositionZ,
- ExposureTime = (float) _exposureTime,
- // This layer does not require a lift procedure
+ PositionZ = (float)_raisePositionZ,
+ ExposureTime = SlicerFile.SupportsGCode ? 0 : 0.01f,
LiftHeightTotal = SlicerFile.SupportsGCode ? 0 : 0.1f,
- LiftSpeed = SlicerFile.MaximumSpeed,
- LiftSpeed2 = SlicerFile.MaximumSpeed,
- RetractSpeed = SlicerFile.MaximumSpeed,
- RetractSpeed2 = SlicerFile.MaximumSpeed,
+ LiftSpeed = minLiftSpeed,
+ LiftSpeed2 = maxLiftSpeed,
+ RetractSpeed = maxRetractSpeed,
+ RetractSpeed2 = maxRetractSpeed,
RetractHeight2 = 0
};
- if (CanUseCustomLift)
- {
- layer.LiftSpeed = (float)_liftSpeed;
- layer.RetractSpeed = (float)_retractSpeed;
+ virtualSlowLiftLayer.SetNoDelays();
- /*if (SlicerFile.CanUseLayerLiftHeight2)
- {
- layer.LiftHeight = (float)_slowLiftHeight;
- }*/
-
- if (SlicerFile.CanUseLayerLiftSpeed2)
- {
- layer.LiftSpeed2 = (float)_liftSpeed2;
- }
+ var virtualPhotoLayer = virtualSlowLiftLayer.Clone();
+ virtualPhotoLayer.ExposureTime = (float)_exposureTime;
+ virtualPhotoLayer.LiftSpeed = maxLiftSpeed;
- if (SlicerFile.CanUseLayerRetractSpeed2)
- {
- layer.RetractSpeed2 = (float)_retractSpeed2;
- }
- }
+ virtualSlowLiftLayer.LightPWM = 0; // Disable light power if possible
- layer.SetNoDelays();
+ var slowLiftHeight = CanUseCustomLift ? (float)_slowLiftHeight : SlicerFile.LiftHeight;
var layers = SlicerFile.ToList();
- for (int i = 0; i < virtualLayers.Count; i++)
+ uint insertedLayers = 0;
+ foreach (var insertIndex in virtualLayers)
{
- int insertIndex = (int)virtualLayers[i];
- SlicerFile[insertIndex].LiftHeightTotal = SlicerFile.SupportsGCode ? 0 : 0.1f;
-
- if (CanUseCustomLift)
+ if (insertIndex < LayerIndexEnd)
{
- SlicerFile[insertIndex].LiftSpeed = (float)_liftSpeed;
- SlicerFile[insertIndex].RetractSpeed = (float)_retractSpeed;
+ // Replace lift with retract
+ if (SlicerFile.CanUseLayerRetractHeight2 && SlicerFile[insertIndex].RetractHeight2 > 0)
+ {
+ SlicerFile[insertIndex].LiftHeightTotal = SlicerFile[insertIndex].RetractHeight2;
+ }
+
+ SlicerFile[insertIndex].RetractHeight2 = 0;
+ SlicerFile[insertIndex].LiftSpeed = maxRetractSpeed;
- if (SlicerFile.CanUseLayerLiftSpeed2)
+ if (CanUseCustomLift)
{
- SlicerFile[insertIndex].LiftSpeed2 = (float)_retractSpeed2;
+ SlicerFile[insertIndex].LiftHeight = (float) _slowRetractHeight;
+ SlicerFile[insertIndex].RetractSpeed = minRetractSpeed;
+
+ if (SlicerFile.CanUseLayerLiftSpeed2)
+ {
+ SlicerFile[insertIndex].LiftSpeed2 = maxLiftSpeed;
+ }
+
+ if (SlicerFile.CanUseLayerRetractSpeed2)
+ {
+ SlicerFile[insertIndex].RetractSpeed2 = maxRetractSpeed;
+ }
}
+ }
- if (SlicerFile.CanUseLayerRetractSpeed2)
+ layers.Insert((int)(insertIndex + insertedLayers), virtualPhotoLayer.Clone());
+
+ if (slowLiftHeight > 0 && insertIndex > 0)
+ {
+ virtualSlowLiftLayer.PositionZ = SlicerFile[insertIndex - 1].PositionZ + slowLiftHeight;
+ if (virtualSlowLiftLayer.PositionZ >= virtualPhotoLayer.PositionZ)
{
- SlicerFile[insertIndex].RetractSpeed2 = (float)_retractSpeed2;
+ // Slow lift layer must be lower than photo layer, break this insertion from now on
+ slowLiftHeight = 0;
+ virtualPhotoLayer.LiftSpeed = minLiftSpeed;
+ continue;
}
+ layers.Insert((int)(insertIndex + insertedLayers), virtualSlowLiftLayer.Clone());
+ insertedLayers++;
}
- layers.Insert(insertIndex + i, layer.Clone());
+ insertedLayers++;
}
+
SlicerFile.SuppressRebuildPropertiesWork(() => SlicerFile.LayerManager.Layers = layers.ToArray());
}
diff --git a/UVtools.Core/UVtools.Core.csproj b/UVtools.Core/UVtools.Core.csproj
index b0724ec..22ca56b 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.28.1</Version>
+ <Version>2.29.0</Version>
<Copyright>Copyright © 2020 PTRTECH</Copyright>
<PackageIcon>UVtools.png</PackageIcon>
<Platforms>AnyCPU;x64</Platforms>
@@ -62,7 +62,7 @@
<PackageReference Include="BinarySerializer" Version="8.6.2.2" />
<PackageReference Include="Emgu.CV" Version="4.5.5.4823" />
<PackageReference Include="KdTree" Version="1.4.1" />
- <PackageReference Include="Microsoft.CodeAnalysis.CSharp.Scripting" Version="4.1.0-3.final" />
+ <PackageReference Include="Microsoft.CodeAnalysis.CSharp.Scripting" Version="4.1.0" />
<PackageReference Include="Microsoft.Win32.Registry" Version="6.0.0-preview.5.21301.5" />
<PackageReference Include="morelinq" Version="3.3.2" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
diff --git a/UVtools.WPF/Controls/Tools/ToolFadeExposureTimeControl.axaml b/UVtools.WPF/Controls/Tools/ToolFadeExposureTimeControl.axaml
index 1c6c73e..3bb43a2 100644
--- a/UVtools.WPF/Controls/Tools/ToolFadeExposureTimeControl.axaml
+++ b/UVtools.WPF/Controls/Tools/ToolFadeExposureTimeControl.axaml
@@ -4,7 +4,7 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="UVtools.WPF.Controls.Tools.ToolFadeExposureTimeControl">
- <Grid RowDefinitions="Auto,10,Auto,10,Auto,10,Auto"
+ <Grid RowDefinitions="Auto,10,Auto,10,Auto,10,Auto,10,Auto"
ColumnDefinitions="Auto,10,180,5,Auto,5,180">
<TextBlock Grid.Row="0" Grid.Column="0"
@@ -50,5 +50,17 @@
VerticalAlignment="Center"
Text="/ per layer"/>
+ <CheckBox Grid.Row="6" Grid.Column="2" Grid.ColumnSpan="5"
+ IsChecked="{Binding Operation.DisableFirmwareTransitionLayers}"
+ ToolTip.Tip="Attempt to disable firmware strict transition layers in favor of this tool"
+ Content="Disable firmware transition layers">
+ <CheckBox.IsVisible>
+ <MultiBinding Converter="{x:Static BoolConverters.And}">
+ <Binding Path="SlicerFile.CanUseTransitionLayerCount"/>
+ <Binding Path="SlicerFile.HaveTransitionLayers"/>
+ </MultiBinding>
+ </CheckBox.IsVisible>
+ </CheckBox>
+
</Grid>
</UserControl>
diff --git a/UVtools.WPF/Controls/Tools/ToolTimelapseControl.axaml b/UVtools.WPF/Controls/Tools/ToolTimelapseControl.axaml
index 57d9702..4989987 100644
--- a/UVtools.WPF/Controls/Tools/ToolTimelapseControl.axaml
+++ b/UVtools.WPF/Controls/Tools/ToolTimelapseControl.axaml
@@ -5,7 +5,7 @@
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="UVtools.WPF.Controls.Tools.ToolTimelapseControl">
<StackPanel Spacing="10" Orientation="Vertical">
- <Grid RowDefinitions="Auto,10,Auto,10,Auto,10,Auto,10,Auto"
+ <Grid RowDefinitions="Auto,10,Auto,10,Auto,10,Auto,10,Auto,10,Auto"
ColumnDefinitions="Auto,10,Auto">
<TextBlock Grid.Row="0" Grid.Column="0"
@@ -47,15 +47,25 @@
&#x0a;Use 0mm to raise at each layer."
Text="Raise each:"/>
- <NumericUpDown Grid.Row="4" Grid.Column="2"
- Classes="ValueLabel ValueLabel_mm"
- HorizontalAlignment="Left"
- Minimum="0"
- Maximum="10000"
- Increment="0.5"
- Width="100"
- Value="{Binding Operation.RaiseEachNthHeight}"/>
+ <StackPanel Grid.Row="4" Grid.Column="2"
+ Orientation="Horizontal" Spacing="5">
+ <NumericUpDown Classes="ValueLabel ValueLabel_mm"
+ HorizontalAlignment="Left"
+ Minimum="0"
+ Maximum="10000"
+ Increment="0.5"
+ Width="100"
+ Value="{Binding Operation.RaiseEachNthHeight}"/>
+
+ <TextBlock VerticalAlignment="Center"
+ Text="{Binding Operation.RaiseEachNthLayers, StringFormat={}{0} layer(s) |}"/>
+
+ <TextBlock VerticalAlignment="Center"
+ Margin="5,0,0,0"
+ FontWeight="Bold"
+ Text="{Binding Operation.NumberOfLifts, StringFormat=Lifts: {0}}"/>
+ </StackPanel>
<!-- LiftHeight: Wait time after lift -->
<TextBlock Grid.Row="6" Grid.Column="0"
@@ -147,16 +157,20 @@
<CheckBox Grid.Row="8" Grid.Column="2"
VerticalAlignment="Center"
+ Content="Ensure the last layer"
+ ToolTip.Tip="If enabled, it will generate an obligatory layer to cover the last layer.
+&#x0a;Use this option to make sure you have the whole and complete model on your last photo."
+ IsVisible="{Binding Operation.IsVirtualLayerMode}"
+ IsChecked="{Binding Operation.EnsureLastLayer}"/>
+
+ <CheckBox Grid.Row="10" Grid.Column="2"
+ VerticalAlignment="Center"
Content="Set custom lift parameters"
- IsChecked="{Binding Operation.UseCustomLift}">
- <CheckBox.IsVisible>
- <MultiBinding Converter="{x:Static BoolConverters.And}">
- <Binding Path="SlicerFile.CanUseLayerLiftHeight"/>
- </MultiBinding>
- </CheckBox.IsVisible>
- </CheckBox>
+ IsVisible="{Binding SlicerFile.CanUseLayerLiftHeight}"
+ IsChecked="{Binding Operation.UseCustomLift}"/>
</Grid>
+ <!-- Custom lift -->
<Grid RowDefinitions="Auto,10,Auto,10,Auto,10,Auto,10,Auto"
ColumnDefinitions="Auto,10,210,5,Auto,5,210">
<Grid.IsVisible>
@@ -166,136 +180,175 @@
</MultiBinding>
</Grid.IsVisible>
- <TextBlock Grid.Row="0" Grid.Column="0"
- VerticalAlignment="Center"
- ToolTip.Tip="The slow first lift sequence (TSMC).
+ <!-- Slow lift height-->
+ <TextBlock Grid.Row="0" Grid.Column="0"
+ VerticalAlignment="Center"
+ ToolTip.Tip="The slow first lift sequence (TSMC).
&#x0a;Use a low value or 0 to disable."
- IsVisible="{Binding !Operation.IsVirtualLayerMode}"
- Text="Slow lift height:"/>
+ Text="Slow lift height:"/>
- <NumericUpDown Grid.Row="0" Grid.Column="2"
- Classes="ValueLabel ValueLabel_mm"
- Minimum="0"
- Maximum="20"
- Increment="1"
- Value="{Binding Operation.SlowLiftHeight}">
- <NumericUpDown.IsVisible>
- <MultiBinding Converter="{x:Static BoolConverters.And}">
- <Binding Path="SlicerFile.CanUseLayerLiftHeight2"/>
- <Binding Path="!Operation.IsVirtualLayerMode"/>
- </MultiBinding>
- </NumericUpDown.IsVisible>
- </NumericUpDown>
+ <NumericUpDown Grid.Row="0" Grid.Column="2"
+ Classes="ValueLabel ValueLabel_mm"
+ Minimum="0"
+ Maximum="20"
+ Increment="1"
+ Value="{Binding Operation.SlowLiftHeight}">
+ <NumericUpDown.IsVisible>
+ <MultiBinding Converter="{x:Static BoolConverters.Or}">
+ <Binding Path="SlicerFile.CanUseLayerLiftHeight2"/>
+ <Binding Path="Operation.IsVirtualLayerMode"/>
+ </MultiBinding>
+ </NumericUpDown.IsVisible>
+ </NumericUpDown>
- <TextBlock Grid.Row="0" Grid.Column="2"
- VerticalAlignment="Center"
- ToolTip.Tip="(Not supported by your printer / file format)"
- Text="(Not supported)">
- <TextBlock.IsVisible>
- <MultiBinding Converter="{x:Static BoolConverters.And}">
- <Binding Path="!SlicerFile.CanUseLayerLiftHeight2"/>
- <Binding Path="!Operation.IsVirtualLayerMode"/>
- </MultiBinding>
- </TextBlock.IsVisible>
- </TextBlock>
-
- <TextBlock Grid.Row="2" Grid.Column="0"
- VerticalAlignment="Center"
- Text="Lift speed:"/>
-
- <NumericUpDown Grid.Row="2" Grid.Column="2"
- Classes="ValueLabel ValueLabel_mmmin"
- Minimum="0"
- Maximum="10000"
- Increment="10"
- IsVisible="{Binding SlicerFile.CanUseLayerLiftSpeed}"
- Value="{Binding Operation.LiftSpeed}">
- </NumericUpDown>
+ <TextBlock Grid.Row="0" Grid.Column="2"
+ VerticalAlignment="Center"
+ ToolTip.Tip="(Not supported by your printer / file format)"
+ Text="(Not supported)">
+ <TextBlock.IsVisible>
+ <MultiBinding Converter="{x:Static BoolConverters.And}">
+ <Binding Path="!SlicerFile.CanUseLayerLiftHeight2"/>
+ <Binding Path="!Operation.IsVirtualLayerMode"/>
+ </MultiBinding>
+ </TextBlock.IsVisible>
+ </TextBlock>
+
+ <!-- Lift Speed -->
+ <TextBlock Grid.Row="2" Grid.Column="0"
+ VerticalAlignment="Center"
+ Text="Lift speed:"/>
- <TextBlock Grid.Row="2" Grid.Column="2"
- VerticalAlignment="Center"
- ToolTip.Tip="(Not supported by your printer / file format)"
- IsVisible="{Binding !SlicerFile.CanUseLayerLiftSpeed}"
- Text="(Not supported)"/>
+ <NumericUpDown Grid.Row="2" Grid.Column="2"
+ Classes="ValueLabel ValueLabel_mmmin"
+ Minimum="0"
+ Maximum="10000"
+ Increment="10"
+ IsVisible="{Binding SlicerFile.CanUseLayerLiftSpeed}"
+ Value="{Binding Operation.LiftSpeed}">
+ </NumericUpDown>
- <TextBlock Grid.Row="2" Grid.Column="4"
- VerticalAlignment="Center"
- IsVisible="{Binding SlicerFile.CanUseLayerLiftSpeed2}"
- Text="-"/>
+ <TextBlock Grid.Row="2" Grid.Column="2"
+ VerticalAlignment="Center"
+ ToolTip.Tip="(Not supported by your printer / file format)"
+ Text="(Not supported)">
+ <TextBlock.IsVisible>
+ <MultiBinding Converter="{x:Static BoolConverters.And}">
+ <Binding Path="!SlicerFile.CanUseLayerLiftSpeed"/>
+ <Binding Path="!Operation.IsVirtualLayerMode"/>
+ </MultiBinding>
+ </TextBlock.IsVisible>
+ </TextBlock>
- <NumericUpDown Grid.Row="2" Grid.Column="6"
- Classes="ValueLabel ValueLabel_mmmin"
- Minimum="0"
- Maximum="10000"
- Increment="10"
- IsVisible="{Binding SlicerFile.CanUseLayerLiftSpeed2}"
- Value="{Binding Operation.LiftSpeed2}"/>
+ <TextBlock Grid.Row="2" Grid.Column="4"
+ VerticalAlignment="Center"
+ Text="-">
+ <TextBlock.IsVisible>
+ <MultiBinding Converter="{x:Static BoolConverters.Or}">
+ <Binding Path="SlicerFile.CanUseLayerLiftSpeed2"/>
+ <Binding Path="Operation.IsVirtualLayerMode"/>
+ </MultiBinding>
+ </TextBlock.IsVisible>
+ </TextBlock>
+
+ <NumericUpDown Grid.Row="2" Grid.Column="6"
+ Classes="ValueLabel ValueLabel_mmmin"
+ Minimum="0"
+ Maximum="10000"
+ Increment="10"
+ Value="{Binding Operation.LiftSpeed2}">
+ <NumericUpDown.IsVisible>
+ <MultiBinding Converter="{x:Static BoolConverters.Or}">
+ <Binding Path="SlicerFile.CanUseLayerLiftSpeed2"/>
+ <Binding Path="Operation.IsVirtualLayerMode"/>
+ </MultiBinding>
+ </NumericUpDown.IsVisible>
+ </NumericUpDown>
- <TextBlock Grid.Row="4" Grid.Column="0"
- VerticalAlignment="Center"
- ToolTip.Tip="The slow last retract sequence (TSMC).
+ <!-- Slow retract -->
+ <TextBlock Grid.Row="4" Grid.Column="0"
+ VerticalAlignment="Center"
+ ToolTip.Tip="The slow last retract sequence (TSMC).
&#x0a;Use a low value or 0 to disable."
- IsVisible="{Binding !Operation.IsVirtualLayerMode}"
- Text="Slow retract height:"/>
+ Text="Slow retract height:"/>
- <NumericUpDown Grid.Row="4" Grid.Column="2"
- Classes="ValueLabel ValueLabel_mm"
- Minimum="0"
- Maximum="20"
- Increment="1"
- Value="{Binding Operation.SlowRetractHeight}">
- <NumericUpDown.IsVisible>
- <MultiBinding Converter="{x:Static BoolConverters.And}">
- <Binding Path="SlicerFile.CanUseLayerRetractHeight2"/>
- <Binding Path="!Operation.IsVirtualLayerMode"/>
- </MultiBinding>
- </NumericUpDown.IsVisible>
- </NumericUpDown>
+ <NumericUpDown Grid.Row="4" Grid.Column="2"
+ Classes="ValueLabel ValueLabel_mm"
+ Minimum="0"
+ Maximum="20"
+ Increment="1"
+ Value="{Binding Operation.SlowRetractHeight}">
+ <NumericUpDown.IsVisible>
+ <MultiBinding Converter="{x:Static BoolConverters.Or}">
+ <Binding Path="SlicerFile.CanUseLayerRetractHeight2"/>
+ <Binding Path="Operation.IsVirtualLayerMode"/>
+ </MultiBinding>
+ </NumericUpDown.IsVisible>
+ </NumericUpDown>
- <TextBlock Grid.Row="4" Grid.Column="2"
- VerticalAlignment="Center"
- ToolTip.Tip="(Not supported by your printer / file format)"
- Text="(Not supported)">
- <TextBlock.IsVisible>
- <MultiBinding Converter="{x:Static BoolConverters.And}">
- <Binding Path="!SlicerFile.CanUseLayerRetractHeight2"/>
- <Binding Path="!Operation.IsVirtualLayerMode"/>
- </MultiBinding>
- </TextBlock.IsVisible>
- </TextBlock>
-
-
- <TextBlock Grid.Row="6" Grid.Column="0"
- VerticalAlignment="Center"
- Text="Retract speed:"/>
-
- <NumericUpDown Grid.Row="6" Grid.Column="2"
- Classes="ValueLabel ValueLabel_mmmin"
- Minimum="0"
- Maximum="10000"
- Increment="10"
- IsVisible="{Binding SlicerFile.CanUseLayerRetractSpeed}"
- Value="{Binding Operation.RetractSpeed}">
- </NumericUpDown>
+ <TextBlock Grid.Row="4" Grid.Column="2"
+ VerticalAlignment="Center"
+ ToolTip.Tip="(Not supported by your printer / file format)"
+ Text="(Not supported)">
+ <TextBlock.IsVisible>
+ <MultiBinding Converter="{x:Static BoolConverters.And}">
+ <Binding Path="!SlicerFile.CanUseLayerRetractHeight2"/>
+ <Binding Path="!Operation.IsVirtualLayerMode"/>
+ </MultiBinding>
+ </TextBlock.IsVisible>
+ </TextBlock>
+
+
+ <!-- Retract speed -->
+ <TextBlock Grid.Row="6" Grid.Column="0"
+ VerticalAlignment="Center"
+ Text="Retract speed:"/>
- <TextBlock Grid.Row="6" Grid.Column="2"
- VerticalAlignment="Center"
- ToolTip.Tip="(Not supported by your printer / file format)"
- IsVisible="{Binding !SlicerFile.CanUseLayerRetractSpeed}"
- Text="(Not supported)"/>
+ <NumericUpDown Grid.Row="6" Grid.Column="2"
+ Classes="ValueLabel ValueLabel_mmmin"
+ Minimum="0"
+ Maximum="10000"
+ Increment="10"
+ IsVisible="{Binding SlicerFile.CanUseLayerRetractSpeed}"
+ Value="{Binding Operation.RetractSpeed}">
+ </NumericUpDown>
- <TextBlock Grid.Row="6" Grid.Column="4"
- VerticalAlignment="Center"
- IsVisible="{Binding SlicerFile.CanUseLayerRetractSpeed2}"
- Text="-"/>
+ <TextBlock Grid.Row="6" Grid.Column="2"
+ VerticalAlignment="Center"
+ ToolTip.Tip="(Not supported by your printer / file format)"
+ Text="(Not supported)">
+ <TextBlock.IsVisible>
+ <MultiBinding Converter="{x:Static BoolConverters.And}">
+ <Binding Path="!SlicerFile.CanUseLayerRetractSpeed"/>
+ <Binding Path="!Operation.IsVirtualLayerMode"/>
+ </MultiBinding>
+ </TextBlock.IsVisible>
+ </TextBlock>
- <NumericUpDown Grid.Row="6" Grid.Column="6"
- Classes="ValueLabel ValueLabel_mmmin"
- Minimum="0"
- Maximum="10000"
- Increment="10"
- IsVisible="{Binding SlicerFile.CanUseLayerRetractSpeed2}"
- Value="{Binding Operation.RetractSpeed2}"/>
+ <TextBlock Grid.Row="6" Grid.Column="4"
+ VerticalAlignment="Center"
+ Text="-">
+ <TextBlock.IsVisible>
+ <MultiBinding Converter="{x:Static BoolConverters.Or}">
+ <Binding Path="SlicerFile.CanUseLayerRetractSpeed2"/>
+ <Binding Path="Operation.IsVirtualLayerMode"/>
+ </MultiBinding>
+ </TextBlock.IsVisible>
+ </TextBlock>
+
+
+ <NumericUpDown Grid.Row="6" Grid.Column="6"
+ Classes="ValueLabel ValueLabel_mmmin"
+ Minimum="0"
+ Maximum="10000"
+ Increment="10"
+ Value="{Binding Operation.RetractSpeed2}">
+ <NumericUpDown.IsVisible>
+ <MultiBinding Converter="{x:Static BoolConverters.Or}">
+ <Binding Path="SlicerFile.CanUseLayerRetractSpeed2"/>
+ <Binding Path="Operation.IsVirtualLayerMode"/>
+ </MultiBinding>
+ </NumericUpDown.IsVisible>
+ </NumericUpDown>
</Grid>
diff --git a/UVtools.WPF/MainWindow.axaml b/UVtools.WPF/MainWindow.axaml
index 9fff996..7774735 100644
--- a/UVtools.WPF/MainWindow.axaml
+++ b/UVtools.WPF/MainWindow.axaml
@@ -400,7 +400,7 @@
<TabItem
Name="TabInformation"
ToolTip.Tip="Information"
- IsEnabled="{Binding IsFileLoaded}" >
+ IsEnabled="{Binding IsFileLoaded}">
<TabItem.Header>
<StackPanel VerticalAlignment="Center" Orientation="Horizontal">
<Image Source="/Assets/Icons/info-circle-32x32.png" Width="32"/>
@@ -408,202 +408,204 @@
</StackPanel>
</TabItem.Header>
- <Grid
- IsVisible="{Binding IsFileLoaded}"
- RowDefinitions="Auto,Auto,Auto,Auto,*,Auto,Auto">
- <!-- Thumbnails -->
- <StackPanel
- IsVisible="{Binding SlicerFile.CreatedThumbnailsCount}"
- Grid.Row="0"
- Orientation="Horizontal"
- Spacing="5"
- VerticalAlignment="Center">
- <Button
- IsEnabled="{Binding ThumbnailCanGoPrevious}"
- Command="{Binding ThumbnailGoPrevious}"
- >
- <Image Source="/Assets/Icons/back-16x16.png" Width="16"/>
- </Button>
-
- <TextBlock VerticalAlignment="Center">
- <TextBlock.Text>
- <MultiBinding StringFormat="{}{0}/{1}">
- <Binding Path="VisibleThumbnailIndex"/>
- <Binding Path="SlicerFile.CreatedThumbnailsCount"/>
- </MultiBinding>
- </TextBlock.Text>
- </TextBlock>
-
- <Button
- IsEnabled="{Binding ThumbnailCanGoNext}"
- Command="{Binding ThumbnailGoNext}"
- >
- <Image Source="/Assets/Icons/next-16x16.png" Width="16"/>
- </Button>
-
- </StackPanel>
-
- <StackPanel
- IsVisible="{Binding SlicerFile.CreatedThumbnailsCount}"
- Grid.Row="0"
- Orientation="Horizontal"
- Spacing="2"
- HorizontalAlignment="Right"
- VerticalAlignment="Center">
- <TextBlock VerticalAlignment="Center"
- Text="{Binding VisibleThumbnailResolution}"/>
-
- <Button
- IsEnabled="{Binding VisibleThumbnailIndex}"
- ToolTip.Tip="Replace the current preview image"
- Command="{Binding OnClickThumbnailImport}">
- <Image Source="/Assets/Icons/photo-16x16.png" />
- </Button>
-
- <Button
- IsEnabled="{Binding VisibleThumbnailIndex}"
- ToolTip.Tip="Save thumbnail image to a file"
- Command="{Binding OnClickThumbnailSave}">
- <Image Source="/Assets/Icons/save-16x16.png" />
- </Button>
-
- </StackPanel>
-
- <!-- Preview image -->
- <Image
- IsVisible="{Binding SlicerFile.CreatedThumbnailsCount}"
- Stretch="Uniform"
- Grid.Row="1" Source="{Binding VisibleThumbnailImage}"/>
-
- <GridSplitter Grid.Row="2" ResizeDirection="Rows" ResizeBehavior="PreviousAndNext" Background="Transparent" Height="5"/>
-
- <!-- Properties -->
- <StackPanel
- IsVisible="{Binding SlicerProperties.Count}"
- Grid.Row="3"
- Orientation="Horizontal"
- Spacing="5"
- VerticalAlignment="Center">
-
- <TextBlock
- VerticalAlignment="Center"
- Text="{Binding SlicerProperties.Count, StringFormat=Properties: \{0\}}"
- />
-
- <TextBlock Text="|"/>
-
- <TextBlock
- VerticalAlignment="Center"
- Text="{Binding SlicerFile.Configs.Length, StringFormat=Groups: \{0\}}"
- />
-
- </StackPanel>
-
- <StackPanel
- IsVisible="{Binding SlicerProperties.Count}"
- Grid.Row="3"
- Orientation="Horizontal"
- Spacing="2"
- HorizontalAlignment="Right"
- VerticalAlignment="Center">
-
- <Button
- Name="PropertiesSaveButton"
- IsEnabled="{Binding SlicerFile.CreatedThumbnailsCount}"
- ToolTip.Tip="Save properties to a file or clipboard"
- Command="{Binding OpenContextMenu}"
- CommandParameter="PropertiesSave"
- >
- <Button.ContextMenu>
- <ContextMenu Name="PropertiesSaveContextMenu" PlacementMode="Bottom">
- <MenuItem
- Command="{Binding OnClickPropertiesSaveFile}"
- Header="To File">
- <MenuItem.Icon>
- <Image Source="/Assets/Icons/file-image-16x16.png"/>
- </MenuItem.Icon>
- </MenuItem>
-
- <MenuItem
- Command="{Binding OnClickPropertiesSaveClipboard}"
- Header="To Clipboard">
- <MenuItem.Icon>
- <Image Source="/Assets/Icons/clipboard-16x16.png"/>
- </MenuItem.Icon>
- </MenuItem>
-
- </ContextMenu>
- </Button.ContextMenu>
- <StackPanel Orientation="Horizontal">
- <Image Source="/Assets/Icons/save-16x16.png" />
- <TextBlock Text=" ⮟"/>
- </StackPanel>
- </Button>
-
- </StackPanel>
-
- <DataGrid
- IsVisible="{Binding SlicerProperties.Count}"
- Name="PropertiesGrid"
- Grid.Row="4"
- CanUserReorderColumns="True"
- CanUserResizeColumns="True"
- CanUserSortColumns="True"
- GridLinesVisibility="Horizontal"
- IsReadOnly="True"
- SelectionMode="Extended"
- ClipboardCopyMode="IncludeHeader"
- Items="{Binding SlicerProperties}">
- <DataGrid.Columns>
- <DataGridTextColumn Header="Name"
- Binding="{Binding Name}"
- Width="Auto" />
- <DataGridTextColumn Header="Value"
- Binding="{Binding Value}"
- Width="Auto" />
- <DataGridTextColumn Header="Group"
- Binding="{Binding Group}"
- Width="Auto" />
- </DataGrid.Columns>
-
- </DataGrid>
-
- <!-- Layer data -->
- <TextBlock Grid.Row="5"
- Text="Layer data"
- ToolTip.Tip="Shows the properties for the current selected layer"
- FontWeight="Bold"
- TextAlignment="Center"
- Padding="0,10"/>
- <DataGrid
- IsVisible="{Binding IsFileLoaded}"
- Name="CurrentLayerGrid"
- Grid.Row="6"
- CanUserReorderColumns="False"
- CanUserResizeColumns="False"
- CanUserSortColumns="False"
- GridLinesVisibility="Horizontal"
- IsReadOnly="True"
- ClipboardCopyMode="IncludeHeader"
- Items="{Binding CurrentLayerProperties}">
- <DataGrid.Columns>
- <DataGridTextColumn Header="Name"
- Binding="{Binding Description}"
- Width="Auto" />
- <DataGridTextColumn Header="Value"
- Binding="{Binding Value}"
- Width="Auto" />
- </DataGrid.Columns>
-
- </DataGrid>
-
- </Grid>
+ <Grid ColumnDefinitions="*" IsVisible="{Binding IsFileLoaded}">
+ <Grid.RowDefinitions>
+ <RowDefinition Height="Auto"/>
+ <RowDefinition Height="Auto" MaxHeight="400"/>
+ <RowDefinition Height="Auto"/>
+ <RowDefinition Height="Auto"/>
+ <RowDefinition Height="*" MinHeight="200"/>
+ <RowDefinition Height="Auto"/>
+ <RowDefinition Height="Auto" MinHeight="220"/>
+ </Grid.RowDefinitions>
+ <!-- Thumbnails -->
+ <StackPanel Grid.Row="0"
+ IsVisible="{Binding SlicerFile.CreatedThumbnailsCount}"
+ Orientation="Horizontal"
+ Spacing="5"
+ VerticalAlignment="Center">
+ <Button IsEnabled="{Binding ThumbnailCanGoPrevious}"
+ Command="{Binding ThumbnailGoPrevious}">
+ <Image Source="/Assets/Icons/back-16x16.png" Width="16"/>
+ </Button>
+
+ <TextBlock VerticalAlignment="Center">
+ <TextBlock.Text>
+ <MultiBinding StringFormat="{}{0}/{1}">
+ <Binding Path="VisibleThumbnailIndex"/>
+ <Binding Path="SlicerFile.CreatedThumbnailsCount"/>
+ </MultiBinding>
+ </TextBlock.Text>
+ </TextBlock>
+
+ <Button IsEnabled="{Binding ThumbnailCanGoNext}"
+ Command="{Binding ThumbnailGoNext}">
+ <Image Source="/Assets/Icons/next-16x16.png" Width="16"/>
+ </Button>
+
+ </StackPanel>
+
+ <StackPanel Grid.Row="0"
+ IsVisible="{Binding SlicerFile.CreatedThumbnailsCount}"
+ Orientation="Horizontal"
+ Spacing="2"
+ HorizontalAlignment="Right"
+ VerticalAlignment="Center">
+ <TextBlock VerticalAlignment="Center"
+ Text="{Binding VisibleThumbnailResolution}"/>
+
+ <Button IsEnabled="{Binding VisibleThumbnailIndex}"
+ ToolTip.Tip="Replace the current preview image"
+ Command="{Binding OnClickThumbnailImport}">
+ <Image Source="/Assets/Icons/photo-16x16.png" />
+ </Button>
+
+ <Button IsEnabled="{Binding VisibleThumbnailIndex}"
+ ToolTip.Tip="Save thumbnail image to a file"
+ Command="{Binding OnClickThumbnailSave}">
+ <Image Source="/Assets/Icons/save-16x16.png" />
+ </Button>
+
+ </StackPanel>
+
+ <!-- Preview image -->
+ <Image Grid.Row="1"
+ IsVisible="{Binding SlicerFile.CreatedThumbnailsCount}"
+ Stretch="Uniform"
+ Source="{Binding VisibleThumbnailImage}"/>
+
+ <GridSplitter Grid.Row="2" ResizeDirection="Rows" ResizeBehavior="PreviousAndNext" Background="White" Height="5"/>
+
+ <!-- Properties -->
+ <StackPanel
+ IsVisible="{Binding SlicerProperties.Count}"
+ Grid.Row="3"
+ Orientation="Horizontal"
+ Spacing="5"
+ VerticalAlignment="Center">
+
+ <TextBlock
+ VerticalAlignment="Center"
+ Text="{Binding SlicerProperties.Count, StringFormat=Properties: \{0\}}"/>
+
+ <TextBlock VerticalAlignment="Center" Text="|"/>
+
+ <TextBlock
+ VerticalAlignment="Center"
+ Text="{Binding SlicerFile.Configs.Length, StringFormat=Groups: \{0\}}"/>
+
+ </StackPanel>
+
+ <StackPanel
+ IsVisible="{Binding SlicerProperties.Count}"
+ Grid.Row="3"
+ Orientation="Horizontal"
+ Spacing="2"
+ HorizontalAlignment="Right"
+ VerticalAlignment="Center">
+
+ <Button
+ Name="PropertiesSaveButton"
+ IsEnabled="{Binding SlicerFile.CreatedThumbnailsCount}"
+ ToolTip.Tip="Save properties to a file or clipboard"
+ Command="{Binding OpenContextMenu}"
+ CommandParameter="PropertiesSave">
+ <Button.ContextMenu>
+ <ContextMenu Name="PropertiesSaveContextMenu" PlacementMode="Bottom">
+ <MenuItem
+ Command="{Binding OnClickPropertiesSaveFile}"
+ Header="To File">
+ <MenuItem.Icon>
+ <Image Source="/Assets/Icons/file-image-16x16.png"/>
+ </MenuItem.Icon>
+ </MenuItem>
+
+ <MenuItem
+ Command="{Binding OnClickPropertiesSaveClipboard}"
+ Header="To Clipboard">
+ <MenuItem.Icon>
+ <Image Source="/Assets/Icons/clipboard-16x16.png"/>
+ </MenuItem.Icon>
+ </MenuItem>
+
+ </ContextMenu>
+ </Button.ContextMenu>
+ <StackPanel Orientation="Horizontal">
+ <Image Source="/Assets/Icons/save-16x16.png" />
+ <TextBlock Text=" ⮟"/>
+ </StackPanel>
+ </Button>
+
+ </StackPanel>
+
+ <DataGrid
+ IsVisible="{Binding SlicerProperties.Count}"
+ Name="PropertiesGrid"
+ Grid.Row="4"
+ CanUserReorderColumns="True"
+ CanUserResizeColumns="True"
+ CanUserSortColumns="True"
+ GridLinesVisibility="Horizontal"
+ IsReadOnly="True"
+ SelectionMode="Extended"
+ ClipboardCopyMode="IncludeHeader"
+ Items="{Binding SlicerProperties}">
+ <DataGrid.Columns>
+ <DataGridTextColumn Header="Name"
+ Binding="{Binding Name}"
+ Width="Auto" />
+ <DataGridTextColumn Header="Value"
+ Binding="{Binding Value}"
+ Width="Auto" />
+ <DataGridTextColumn Header="Group"
+ Binding="{Binding Group}"
+ Width="Auto" />
+ </DataGrid.Columns>
+
+ </DataGrid>
+
+ <GridSplitter Grid.Row="5" ResizeDirection="Rows" ResizeBehavior="PreviousAndNext" Background="White" Height="5"/>
+
+ <!-- Layer data -->
+ <Grid Grid.Row="6"
+ RowDefinitions="Auto,5,*" ColumnDefinitions="*">
+ <TextBlock Grid.Row="0"
+ Text="Layer data"
+ ToolTip.Tip="Shows the properties for the current selected layer"
+ FontWeight="Bold"
+ TextAlignment="Center"/>
+ <DataGrid Grid.Row="2"
+ IsVisible="{Binding IsFileLoaded}"
+ Name="CurrentLayerGrid"
+ CanUserReorderColumns="False"
+ CanUserResizeColumns="False"
+ CanUserSortColumns="False"
+ GridLinesVisibility="Horizontal"
+ IsReadOnly="True"
+ ClipboardCopyMode="IncludeHeader"
+ Items="{Binding CurrentLayerProperties}">
+ <DataGrid.Columns>
+ <DataGridTextColumn Header="Name"
+ Binding="{Binding Description}"
+ Width="Auto" />
+ <DataGridTextColumn Header="Value"
+ Binding="{Binding Value}"
+ Width="Auto" />
+ </DataGrid.Columns>
+
+ </DataGrid>
+ </Grid>
+
+
+
+ </Grid>
</TabItem>
<TabItem
Name="TabGCode"
ToolTip.Tip="GCode"
+ IsVisible="False"
IsEnabled="{Binding HaveGCode}">
<TabItem.Header>
<StackPanel VerticalAlignment="Center" Orientation="Horizontal">
diff --git a/UVtools.WPF/MainWindow.axaml.cs b/UVtools.WPF/MainWindow.axaml.cs
index c5e7297..a96ebaa 100644
--- a/UVtools.WPF/MainWindow.axaml.cs
+++ b/UVtools.WPF/MainWindow.axaml.cs
@@ -466,9 +466,14 @@ namespace UVtools.WPF
if (!RaiseAndSetIfChanged(ref _isGUIEnabled, value)) return;
if (!_isGUIEnabled)
{
+ DragDrop.SetAllowDrop(this, false);
//ProgressWindow = new ProgressWindow();
return;
}
+ else
+ {
+ DragDrop.SetAllowDrop(this, true);
+ }
LastStopWatch = Progress.StopWatch;
ProgressFinish();
@@ -515,7 +520,7 @@ namespace UVtools.WPF
_firstTimeOnIssues = false;
if (ReferenceEquals(_selectedTabItem, TabIssues) && Settings.Issues.ComputeIssuesOnClickTab)
{
- OnClickDetectIssues();
+ OnClickDetectIssues().ConfigureAwait(false);
}
}
}
@@ -617,6 +622,7 @@ namespace UVtools.WPF
AddHandler(DragDrop.DropEvent, (sender, e) =>
{
+ if (!_isGUIEnabled) return;
ProcessFiles(e.Data.GetFileNames()?.ToArray());
});
@@ -1312,6 +1318,8 @@ namespace UVtools.WPF
ClipboardManager.Instance.Reset();
+ TabGCode.IsVisible = false;
+
IssuesClear(true);
SlicerFile?.Dispose();
SlicerFile = null;
@@ -1946,6 +1954,8 @@ namespace UVtools.WPF
}
}
+ TabGCode.IsVisible = HaveGCode;
+
SlicerFile.PropertyChanged += SlicerFileOnPropertyChanged;
PopulateSuggestions();
@@ -2170,6 +2180,7 @@ namespace UVtools.WPF
SavesCount++;
CanSave = false;
UpdateTitle();
+ if(oldFile != SlicerFile.FileFullPath) AddRecentFile(SlicerFile.FileFullPath);
}
return task;
diff --git a/UVtools.WPF/UVtools.WPF.csproj b/UVtools.WPF/UVtools.WPF.csproj
index 052eca7..30a1c47 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.28.1</Version>
+ <Version>2.29.0</Version>
<Platforms>AnyCPU;x64</Platforms>
<PackageIcon>UVtools.png</PackageIcon>
<PackageReadmeFile>README.md</PackageReadmeFile>