diff options
author | Tiago Conceição <Tiago_caza@hotmail.com> | 2020-07-14 04:55:37 +0300 |
---|---|---|
committer | Tiago Conceição <Tiago_caza@hotmail.com> | 2020-07-14 04:55:37 +0300 |
commit | b2bd1c41f18f5eacfe66e271dc1e9807cbb78236 (patch) | |
tree | ae0a1dadb11e25112aaaddaf179e78bfaad3d3aa | |
parent | 2c514fe260b7939f372c745b5e600ee877b88e12 (diff) |
v0.6.2.0v0.6.2.0
* (Add) PrusaSlicer Printer: Elegoo Mars 2 Pro
* (Add) PrusaSlicer Printer: Creality LD-002H
* (Add) PrusaSlicer Printer: Voxelab Polaris
* (Add) File Format: UVJ (#8)
* (Add) Mutataor: Pixel Dimming
* (Add) Pixel Editor tab with new drawing functions
* (Add) Pixel Editor: Bursh area and shape
* (Add) Pixel Editor: Supports
* (Add) Pixel Editor: Drain holes
* (Add) Settings for pixel editor
* (Add) Setting: File open default directory
* (Add) Setting: File save default directory
* (Add) Setting: File extract default directory
* (Add) Setting: File convert default directory
* (Add) Setting: File save prompt for overwrite (#10)
* (Add) Setting: File save preffix and suffix name
* (Add) Setting: UVtools version to the title bar
* (Improvement) Force same directory as input file on dialogs
* (Improvement) Pattern: Better positioning when not using an anchor, now it's more center friendly
* (Change) Setting: Start maximized defaults to true
* (Fix) Pattern: Calculated volume was appending one margin width/height more
* (Fix) When cancel a file load, some shortcuts can crash the program as it assume file is loaded
* (Fix) pws: Encode using the same count-of-threshold method as CBDDLP (ezrec/uv3dp#79)
48 files changed, 4876 insertions, 313 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 4cc4018..95a7ae2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,31 @@ # Changelog +## 14/07/2020 - v0.6.2.0 + +* (Add) PrusaSlicer Printer: Elegoo Mars 2 Pro +* (Add) PrusaSlicer Printer: Creality LD-002H +* (Add) PrusaSlicer Printer: Voxelab Polaris +* (Add) File Format: UVJ (#8) +* (Add) Mutataor: Pixel Dimming +* (Add) Pixel Editor tab with new drawing functions +* (Add) Pixel Editor: Bursh area and shape +* (Add) Pixel Editor: Supports +* (Add) Pixel Editor: Drain holes +* (Add) Settings for pixel editor +* (Add) Setting: File open default directory +* (Add) Setting: File save default directory +* (Add) Setting: File extract default directory +* (Add) Setting: File convert default directory +* (Add) Setting: File save prompt for overwrite (#10) +* (Add) Setting: File save preffix and suffix name +* (Add) Setting: UVtools version to the title bar +* (Improvement) Force same directory as input file on dialogs +* (Improvement) Pattern: Better positioning when not using an anchor, now it's more center friendly +* (Change) Setting: Start maximized defaults to true +* (Fix) Pattern: Calculated volume was appending one margin width/height more +* (Fix) When cancel a file load, some shortcuts can crash the program as it assume file is loaded +* (Fix) pws: Encode using the same count-of-threshold method as CBDDLP (ezrec/uv3dp#79) + ## 02/07/2020 - v0.6.1.1 * (Add) Allow chitubox, phz, pws, pw0 files convert to cws @@ -9,7 +35,6 @@ * (Improvement) UVtools now generate better gcode and detect the lack of Lift and same z position and optimize the commands * (Fix) zcodex: Wasn't reporting layer decoding progress - ## 02/07/2020 - v0.6.1.0 * (Add) Thumbnail image can now saved to clipboard @@ -34,7 +59,6 @@ * (Fix) Force 1 layer scroll when using Mouse Wheel to scroll the tracker bar * (Fix) PrusaSlicer printers: Mirror vertically instead to produce equal orientation compared with chitubox - ## 29/06/2020 - v0.6.0.1 * (Improvement) Pixel edit now spare a memory cycle per pixel @@ -105,7 +129,6 @@ * (Fix) cbddlp: AntiAlias is number of _greys_, not number of significant bits (ezrec/uv3dp#75) * (Fix) Outline not working as before, due a forget to remove test code - ## 17/06/2020 - v0.5.1.2 * (Add) Able to install only the desired profiles and not the whole lot (Suggested by: Ingo Strohmenger) @@ -22,4 +22,5 @@ # Supporters * Ingo Strohmenger -* Sven Vogt
\ No newline at end of file +* Sven Vogt +* Paul Hammerstrom
\ No newline at end of file diff --git a/ImportPrusaSlicerData.bat b/ImportPrusaSlicerData.bat index ca76b0f..d036b72 100644 --- a/ImportPrusaSlicerData.bat +++ b/ImportPrusaSlicerData.bat @@ -17,23 +17,26 @@ SET files[7]=AnyCubic Photon.ini SET files[8]=AnyCubic Photon S.ini SET files[9]=AnyCubic Photon Zero.ini SET files[10]=Elegoo Mars.ini -SET files[11]=Elegoo Mars Saturn.ini -SET files[12]=Peopoly Phenom.ini -SET files[13]=Peopoly Phenom L.ini -SET files[14]=Peopoly Phenom Noir.ini -SET files[15]=QIDI Shadow5.5.ini -SET files[16]=QIDI Shadow6.0 Pro.ini -SET files[17]=Phrozen Shuffle.ini -SET files[18]=Phrozen Shuffle Lite.ini -SET files[19]=Phrozen Shuffle XL.ini -SET files[20]=Phrozen Shuffle 4K.ini -SET files[21]=Phrozen Sonic.ini -SET files[22]=Phrozen Sonic Mini.ini -SET files[23]=Phrozen Transform.ini -SET files[24]=Kelant S400.ini -SET files[25]=Wanhao D7.ini -SET files[26]=Wanhao D8.ini -SET files[27]=Creality LD-002R.ini +SET files[11]=Elegoo Mars 2 Pro.ini +SET files[12]=Elegoo Mars Saturn.ini +SET files[13]=Peopoly Phenom.ini +SET files[14]=Peopoly Phenom L.ini +SET files[15]=Peopoly Phenom Noir.ini +SET files[16]=QIDI Shadow5.5.ini +SET files[17]=QIDI Shadow6.0 Pro.ini +SET files[18]=Phrozen Shuffle.ini +SET files[19]=Phrozen Shuffle Lite.ini +SET files[20]=Phrozen Shuffle XL.ini +SET files[21]=Phrozen Shuffle 4K.ini +SET files[22]=Phrozen Sonic.ini +SET files[24]=Phrozen Sonic Mini.ini +SET files[25]=Phrozen Transform.ini +SET files[26]=Kelant S400.ini +SET files[27]=Wanhao D7.ini +SET files[28]=Wanhao D8.ini +SET files[29]=Creality LD-002R.ini +SET files[30]=Creality LD-002H.ini +SET files[31]=Voxelab Polaris.ini echo PrusaSlicer Printers Instalation echo This will replace printers, all changes will be discarded diff --git a/PrusaSlicer/printer/Creality LD-002H.ini b/PrusaSlicer/printer/Creality LD-002H.ini new file mode 100644 index 0000000..22c0ffd --- /dev/null +++ b/PrusaSlicer/printer/Creality LD-002H.ini @@ -0,0 +1,37 @@ +# generated by PrusaSlicer 2.2.0+win64 on 2020-07-13 at 23:26:09 UTC +absolute_correction = 0 +area_fill = 50 +bed_custom_model = +bed_custom_texture = +bed_shape = 0x0,130.56x0,130.56x82.62,0x82.62 +default_sla_material_profile = Prusa Orange Tough 0.05 +default_sla_print_profile = 0.05 Normal +display_height = 82.62 +display_mirror_x = 0 +display_mirror_y = 1 +display_orientation = portrait +display_pixels_x = 2560 +display_pixels_y = 1620 +display_width = 130.56 +elefant_foot_compensation = 0.2 +elefant_foot_min_width = 0.2 +fast_tilt_time = 5 +gamma_correction = 1 +inherits = Original Prusa SL1 +max_exposure_time = 120 +max_initial_exposure_time = 300 +max_print_height = 160 +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_CREALITY\nPRINTER_MODEL_LD-002H\n\nSTART_CUSTOM_VALUES\nFLIP_XY\nLayerOffTime_0\nBottomLightOffDelay_2\nBottomLiftHeight_5\nLiftHeight_7\nBottomLiftSpeed_50\nLiftSpeed_50\nRetractSpeed_150\nBottomLightPWM_255\nLightPWM_255\nAntiAliasing_4 ; Use 0 or 1 for disable AntiAliasing with "printer gamma correction" set to 0, otherwise use multiples of 2 and "gamma correction" set to 1 for enable\nEND_CUSTOM_VALUES +printer_settings_id = +printer_technology = SLA +printer_variant = default +printer_vendor = +printhost_apikey = +printhost_cafile = +relative_correction = 1,1 +slow_tilt_time = 8 +thumbnails = 400x400,800x480 diff --git a/PrusaSlicer/printer/Elegoo Mars 2 Pro.ini b/PrusaSlicer/printer/Elegoo Mars 2 Pro.ini new file mode 100644 index 0000000..d493fdf --- /dev/null +++ b/PrusaSlicer/printer/Elegoo Mars 2 Pro.ini @@ -0,0 +1,37 @@ +# generated by PrusaSlicer 2.2.0+win64 on 2020-07-13 at 23:29:07 UTC +absolute_correction = 0 +area_fill = 50 +bed_custom_model = +bed_custom_texture = +bed_shape = 0x0,130.56x0,130.56x82.62,0x82.62 +default_sla_material_profile = Prusa Orange Tough 0.05 +default_sla_print_profile = 0.05 Normal +display_height = 82.62 +display_mirror_x = 0 +display_mirror_y = 1 +display_orientation = portrait +display_pixels_x = 2560 +display_pixels_y = 1620 +display_width = 130.56 +elefant_foot_compensation = 0.2 +elefant_foot_min_width = 0.2 +fast_tilt_time = 5 +gamma_correction = 1 +inherits = Original Prusa SL1 +max_exposure_time = 120 +max_initial_exposure_time = 300 +max_print_height = 160 +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_MARS2_PRO\n\nSTART_CUSTOM_VALUES\nFLIP_XY\nLayerOffTime_0\nBottomLightOffDelay_0\nBottomLiftHeight_5\nLiftHeight_5\nBottomLiftSpeed_90\nLiftSpeed_100\nRetractSpeed_150\nBottomLightPWM_255\nLightPWM_255\nAntiAliasing_4 ; Use 0 or 1 for disable AntiAliasing with "printer gamma correction" set to 0, otherwise use multiples of 2 and "gamma correction" set to 1 for enable\nEND_CUSTOM_VALUES +printer_settings_id = +printer_technology = SLA +printer_variant = default +printer_vendor = +printhost_apikey = +printhost_cafile = +relative_correction = 1,1 +slow_tilt_time = 8 +thumbnails = 400x400,800x480 diff --git a/PrusaSlicer/printer/Voxelab Polaris.ini b/PrusaSlicer/printer/Voxelab Polaris.ini new file mode 100644 index 0000000..b65418b --- /dev/null +++ b/PrusaSlicer/printer/Voxelab Polaris.ini @@ -0,0 +1,37 @@ +# generated by PrusaSlicer 2.2.0+win64 on 2020-07-13 at 23:30:41 UTC +absolute_correction = 0 +area_fill = 50 +bed_custom_model = +bed_custom_texture = +bed_shape = 0x0,120.96x0,120.96x68.04,0x68.04 +default_sla_material_profile = Prusa Orange Tough 0.05 +default_sla_print_profile = 0.05 Normal +display_height = 68.04 +display_mirror_x = 0 +display_mirror_y = 1 +display_orientation = portrait +display_pixels_x = 2560 +display_pixels_y = 1440 +display_width = 120.96 +elefant_foot_compensation = 0.2 +elefant_foot_min_width = 0.2 +fast_tilt_time = 5 +gamma_correction = 1 +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_VOXELAB\nPRINTER_MODEL_POLARIS\n\nSTART_CUSTOM_VALUES\nFLIP_XY\nLayerOffTime_0\nBottomLightOffDelay_0\nBottomLiftHeight_5\nLiftHeight_5\nBottomLiftSpeed_65\nLiftSpeed_65\nRetractSpeed_150\nBottomLightPWM_255\nLightPWM_255\nAntiAliasing_4 ; Use 0 or 1 for disable AntiAliasing with "printer gamma correction" set to 0, otherwise use multiples of 2 and "gamma correction" set to 1 for enable\nEND_CUSTOM_VALUES +printer_settings_id = +printer_technology = SLA +printer_variant = default +printer_vendor = +printhost_apikey = +printhost_cafile = +relative_correction = 1,1 +slow_tilt_time = 8 +thumbnails = 400x400,800x480 @@ -55,6 +55,8 @@ But also, i need victims for test subject. Proceed at your own risk! * PW0 (Photon Workshop) * ZCodex (Z-Suite) * CWS (NovaMaker) +* UVJ +* Image files (png, jpg, jpeg, gif, bmp) ## Available printers for PrusaSlicer @@ -68,6 +70,7 @@ But also, i need victims for test subject. Proceed at your own risk! * AnyCubic Photon S * AnyCubic Photon Zero * Elegoo Mars +* Elegoo Mars 2 Pro * Elegoo Mars Saturn * Peopoly Phenom * Peopoly Phenom L @@ -85,6 +88,8 @@ But also, i need victims for test subject. Proceed at your own risk! * Wanhao D7 * Wanhao D8 * Creality LD-002R +* Creality LD-002H +* Voxelab Polaris ## Available profiles for PrusaSlicer @@ -130,8 +135,8 @@ After some tests without failure you can increase your confidence and ignore thi ### Mac and Linux -(Not tested nor compiled) -1. Latest Mono +(Not supported yet) + ## How to use diff --git a/UVtools.Cmd/UVtools.Cmd.csproj b/UVtools.Cmd/UVtools.Cmd.csproj index a944096..f0a0f01 100644 --- a/UVtools.Cmd/UVtools.Cmd.csproj +++ b/UVtools.Cmd/UVtools.Cmd.csproj @@ -16,6 +16,7 @@ <Copyright>Copyright © 2020 PTRTECH</Copyright> <RepositoryType>Git</RepositoryType> <PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance> + <Platforms>AnyCPU;x64</Platforms> </PropertyGroup> <ItemGroup> diff --git a/UVtools.Core/Extensions/StringExtensions.cs b/UVtools.Core/Extensions/StringExtensions.cs index 29f576f..a164211 100644 --- a/UVtools.Core/Extensions/StringExtensions.cs +++ b/UVtools.Core/Extensions/StringExtensions.cs @@ -9,6 +9,7 @@ using System; using System.ComponentModel; using System.Linq; +using System.Text; namespace UVtools.Core.Extensions { @@ -29,6 +30,9 @@ namespace UVtools.Core.Extensions } } + public static string Repeat(this string s, int n) + => n <= 0 ? string.Empty : new StringBuilder(s.Length * n).Insert(0, s, n).ToString(); + /// <summary> /// Converts a string into a target type /// </summary> diff --git a/UVtools.Core/Extensions/ZipArchiveExtensions.cs b/UVtools.Core/Extensions/ZipArchiveExtensions.cs index 6e71025..6be91bc 100644 --- a/UVtools.Core/Extensions/ZipArchiveExtensions.cs +++ b/UVtools.Core/Extensions/ZipArchiveExtensions.cs @@ -311,13 +311,16 @@ namespace UVtools.Core.Extensions } if (string.IsNullOrEmpty(content)) return entry; - Stream stream = entry.Open(); - if (mode == ZipArchiveMode.Update) stream.SetLength(0); - using (TextWriter tw = new StreamWriter(stream)) + using (Stream stream = entry.Open()) { - tw.Write(content); - tw.Close(); + if (mode == ZipArchiveMode.Update) stream.SetLength(0); + using (TextWriter tw = new StreamWriter(stream)) + { + tw.Write(content); + tw.Close(); + } } + return entry; } @@ -341,10 +344,12 @@ namespace UVtools.Core.Extensions } if (ReferenceEquals(content, null)) return entry; - Stream stream = entry.Open(); - if (mode == ZipArchiveMode.Update) stream.SetLength(0); - stream.Write(content, 0, content.Length); - stream.Close(); + using (Stream stream = entry.Open()) + { + if (mode == ZipArchiveMode.Update) stream.SetLength(0); + stream.Write(content, 0, content.Length); + stream.Close(); + } return entry; } } diff --git a/UVtools.Core/FileFormats/CWSFile.cs b/UVtools.Core/FileFormats/CWSFile.cs index f6a1ddb..84b96f9 100644 --- a/UVtools.Core/FileFormats/CWSFile.cs +++ b/UVtools.Core/FileFormats/CWSFile.cs @@ -80,8 +80,8 @@ namespace UVtools.Core.FileFormats [DisplayName("Machine Type")] public string MachineType { get; set; } = "UV_LCD"; // ;(****UVtools Configuration ******) - [DisplayName("Bottom Layer Light PWM")] public byte BottomLayerLightPWM { get; set; } = 255; - [DisplayName("Layer Light PWM")] public byte LayerLightPWM { get; set; } = 255; + [DisplayName("Bottom Layer Light PWM")] public byte BottomLightPWM { get; set; } = 255; + [DisplayName("Layer Light PWM")] public byte LightPWM { get; set; } = 255; } public class Slice @@ -115,7 +115,10 @@ namespace UVtools.Core.FileFormats new FileExtension("cws", "NovaMaker CWS Files") }; - public override Type[] ConvertToFormats { get; } = null; + public override Type[] ConvertToFormats { get; } = + { + typeof(UVJFile) + }; public override PrintParameterModifier[] PrintParameterModifiers { get; } = { PrintParameterModifier.InitialLayerCount, @@ -361,8 +364,8 @@ G1 Z-3.9 F120 var baseValue = base.GetValueFromPrintParameterModifier(modifier); if (!ReferenceEquals(baseValue, null)) return baseValue; - if (ReferenceEquals(modifier, PrintParameterModifier.BottomLightPWM)) return OutputSettings.BottomLayerLightPWM; - if (ReferenceEquals(modifier, PrintParameterModifier.LightPWM)) return OutputSettings.LayerLightPWM; + if (ReferenceEquals(modifier, PrintParameterModifier.BottomLightPWM)) return OutputSettings.BottomLightPWM; + if (ReferenceEquals(modifier, PrintParameterModifier.LightPWM)) return OutputSettings.LightPWM; return null; } @@ -427,14 +430,14 @@ G1 Z-3.9 F120 if (ReferenceEquals(modifier, PrintParameterModifier.BottomLightPWM)) { - OutputSettings.BottomLayerLightPWM = value.Convert<byte>(); + OutputSettings.BottomLightPWM = value.Convert<byte>(); UpdateGCode(); return true; } if (ReferenceEquals(modifier, PrintParameterModifier.LightPWM)) { - OutputSettings.BottomLayerLightPWM = value.Convert<byte>(); + OutputSettings.BottomLightPWM = value.Convert<byte>(); UpdateGCode(); return true; } @@ -496,7 +499,60 @@ G1 Z-3.9 F120 public override bool Convert(Type to, string fileFullPath, OperationProgress progress = null) { - throw new NotImplementedException(); + if (to == typeof(UVJFile)) + { + UVJFile defaultFormat = (UVJFile)FindByType(typeof(UVJFile)); + UVJFile file = new UVJFile + { + LayerManager = LayerManager, + JsonSettings = new UVJFile.Settings + { + Properties = new UVJFile.Properties + { + Size = new UVJFile.Size + { + X = (ushort)ResolutionX, + Y = (ushort)ResolutionY, + Millimeter = new UVJFile.Millimeter + { + X = OutputSettings.PlatformXSize, + Y = OutputSettings.PlatformYSize, + }, + LayerHeight = LayerHeight, + Layers = LayerCount + }, + Bottom = new UVJFile.Bottom + { + LiftHeight = SliceSettings.LiftDistance, + LiftSpeed = SliceSettings.LiftUpSpeed, + LightOnTime = InitialExposureTime, + //LightOffTime = SliceSettings.BottomLightOffDelay, + LightPWM = OutputSettings.BottomLightPWM, + RetractSpeed = OutputSettings.ZBottomLiftFeedRate, + Count = InitialLayerCount + //RetractHeight = LookupCustomValue<float>(Keyword_LiftHeight, defaultFormat.JsonSettings.Properties.Bottom.RetractHeight), + }, + Exposure = new UVJFile.Exposure + { + LiftHeight = SliceSettings.LiftDistance, + LiftSpeed = SliceSettings.LiftUpSpeed, + LightOnTime = InitialExposureTime, + //LightOffTime = SliceSettings.BottomLightOffDelay, + LightPWM = OutputSettings.BottomLightPWM, + RetractSpeed = SliceSettings.LiftDownSpeed, + }, + AntiAliasLevel = ValidateAntiAliasingLevel() + } + } + }; + + file.SetThumbnails(Thumbnails); + file.Encode(fileFullPath, progress); + + return true; + } + + return false; } private void UpdateGCode() @@ -521,7 +577,7 @@ G1 Z-3.9 F120 { Layer layer = this[layerIndex]; GCode.AppendLine($"{GCodeKeywordSlice} {layerIndex}"); - GCode.AppendLine($"M106 S{GetInitialLayerValueOrNormal(layerIndex, OutputSettings.BottomLayerLightPWM, OutputSettings.LayerLightPWM)}"); + GCode.AppendLine($"M106 S{GetInitialLayerValueOrNormal(layerIndex, OutputSettings.BottomLightPWM, OutputSettings.LightPWM)}"); GCode.AppendLine($"{GCodeKeywordDelay} {layer.ExposureTime}"); GCode.AppendLine("M106 S0"); GCode.AppendLine(GCodeKeywordSliceBlank); diff --git a/UVtools.Core/FileFormats/ChituboxFile.cs b/UVtools.Core/FileFormats/ChituboxFile.cs index 2ad10d1..7bb6cde 100644 --- a/UVtools.Core/FileFormats/ChituboxFile.cs +++ b/UVtools.Core/FileFormats/ChituboxFile.cs @@ -914,6 +914,7 @@ namespace UVtools.Core.FileFormats typeof(PHZFile), typeof(ZCodexFile), typeof(CWSFile), + typeof(UVJFile), }; public override PrintParameterModifier[] PrintParameterModifiers { get; } = @@ -1523,15 +1524,15 @@ namespace UVtools.Core.FileFormats Mirror = (byte) (HeaderSettings.ProjectorType == 0 ? 0 : 1), - BottomLayerLiftHeight = PrintParametersSettings.BottomLiftHeight, - LayerLiftHeight = PrintParametersSettings.LiftHeight, - BottomLayerLiftSpeed = PrintParametersSettings.BottomLiftSpeed, - LayerLiftSpeed = PrintParametersSettings.LiftSpeed, + BottomLiftHeight = PrintParametersSettings.BottomLiftHeight, + LiftHeight = PrintParametersSettings.LiftHeight, + BottomLiftSpeed = PrintParametersSettings.BottomLiftSpeed, + LiftSpeed = PrintParametersSettings.LiftSpeed, RetractSpeed = PrintParametersSettings.RetractSpeed, BottomLayCount = InitialLayerCount, BottomLayerCount = InitialLayerCount, BottomLightOffTime = PrintParametersSettings.BottomLightOffDelay, - LayerLightOffTime = PrintParametersSettings.LightOffDelay, + LightOffTime = PrintParametersSettings.LightOffDelay, BottomLayExposureTime = InitialExposureTime, BottomLayerExposureTime = InitialExposureTime, LayerExposureTime = LayerExposureTime, @@ -1754,6 +1755,58 @@ namespace UVtools.Core.FileFormats return true; } + if (to == typeof(UVJFile)) + { + UVJFile file = new UVJFile + { + LayerManager = LayerManager, + JsonSettings = new UVJFile.Settings + { + Properties = new UVJFile.Properties + { + Size = new UVJFile.Size + { + X = (ushort)ResolutionX, + Y = (ushort)ResolutionY, + Millimeter = new UVJFile.Millimeter + { + X = HeaderSettings.BedSizeX, + Y = HeaderSettings.BedSizeY, + }, + LayerHeight = LayerHeight, + Layers = LayerCount + }, + Bottom = new UVJFile.Bottom + { + LiftHeight = PrintParametersSettings.BottomLiftHeight, + LiftSpeed = PrintParametersSettings.BottomLiftSpeed, + LightOnTime = InitialExposureTime, + LightOffTime = PrintParametersSettings.BottomLightOffDelay, + LightPWM = (byte) HeaderSettings.BottomLightPWM, + RetractSpeed = PrintParametersSettings.RetractSpeed, + Count = InitialLayerCount + //RetractHeight = LookupCustomValue<float>(Keyword_LiftHeight, defaultFormat.JsonSettings.Properties.Bottom.RetractHeight), + }, + Exposure = new UVJFile.Exposure + { + LiftHeight = PrintParametersSettings.LiftHeight, + LiftSpeed = PrintParametersSettings.LiftSpeed, + LightOnTime = LayerExposureTime, + LightOffTime = PrintParametersSettings.LightOffDelay, + LightPWM = (byte) HeaderSettings.LightPWM, + RetractSpeed = PrintParametersSettings.RetractSpeed, + }, + AntiAliasLevel = ValidateAntiAliasingLevel() + } + } + }; + + file.SetThumbnails(Thumbnails); + file.Encode(fileFullPath, progress); + + return true; + } + return false; } #endregion diff --git a/UVtools.Core/FileFormats/ChituboxZipFile.cs b/UVtools.Core/FileFormats/ChituboxZipFile.cs index 07749a7..f2ec085 100644 --- a/UVtools.Core/FileFormats/ChituboxZipFile.cs +++ b/UVtools.Core/FileFormats/ChituboxZipFile.cs @@ -67,17 +67,17 @@ namespace UVtools.Core.FileFormats [DisplayName("bottomLayExposureTime")] public float BottomLayExposureTime { get; set; } = 35; // 35s [DisplayName("bottomLayerExposureTime")] public float BottomLayerExposureTime { get; set; } = 35; // 35s [DisplayName("normalDropSpeed")] public float RetractSpeed { get; set; } = 150; // 150 mm/m - [DisplayName("normalLayerLiftSpeed")] public float LayerLiftSpeed { get; set; } = 60; // 60 mm/m - [DisplayName("normalLayerLiftHeight")] public float LayerLiftHeight { get; set; } = 5; // 5 mm + [DisplayName("normalLayerLiftSpeed")] public float LiftSpeed { get; set; } = 60; // 60 mm/m + [DisplayName("normalLayerLiftHeight")] public float LiftHeight { get; set; } = 5; // 5 mm [DisplayName("zSlowUpDistance")] public float ZSlowUpDistance { get; set; } [DisplayName("bottomLayCount")] public ushort BottomLayCount { get; set; } = 4; [DisplayName("bottomLayerCount")] public ushort BottomLayerCount { get; set; } = 4; [DisplayName("mirror")] public byte Mirror { get; set; } // 0/1 [DisplayName("totalLayer")] public uint LayerCount { get; set; } - [DisplayName("bottomLayerLiftHeight")] public float BottomLayerLiftHeight { get; set; } = 5; - [DisplayName("bottomLayerLiftSpeed")] public float BottomLayerLiftSpeed { get; set; } = 60; + [DisplayName("bottomLayerLiftHeight")] public float BottomLiftHeight { get; set; } = 5; + [DisplayName("bottomLayerLiftSpeed")] public float BottomLiftSpeed { get; set; } = 60; [DisplayName("bottomLightOffTime")] public float BottomLightOffTime { get; set; } - [DisplayName("lightOffTime")] public float LayerLightOffTime { get; set; } + [DisplayName("lightOffTime")] public float LightOffTime { get; set; } [DisplayName("bottomPWMLight")] public byte BottomLightPWM { get; set; } = 255; [DisplayName("PWMLight")] public byte LayerLightPWM { get; set; } = 255; [DisplayName("antiAliasLevel")] public byte AntiAliasing { get; set; } = 1; @@ -94,7 +94,9 @@ namespace UVtools.Core.FileFormats new FileExtension("zip", "Chitubox Zip Files") }; - public override Type[] ConvertToFormats { get; } = null; + public override Type[] ConvertToFormats { get; } = { + typeof(UVJFile) + }; public override PrintParameterModifier[] PrintParameterModifiers { get; } = { PrintParameterModifier.InitialLayerCount, @@ -130,9 +132,9 @@ namespace UVtools.Core.FileFormats public override float LayerExposureTime => HeaderSettings.LayerExposureTime; - public override float LiftHeight => HeaderSettings.LayerLiftHeight; + public override float LiftHeight => HeaderSettings.LiftHeight; - public override float LiftSpeed => HeaderSettings.LayerLiftSpeed; + public override float LiftSpeed => HeaderSettings.LiftSpeed; public override float RetractSpeed => HeaderSettings.RetractSpeed; @@ -301,9 +303,9 @@ namespace UVtools.Core.FileFormats var baseValue = base.GetValueFromPrintParameterModifier(modifier); if (!ReferenceEquals(baseValue, null)) return baseValue; if (ReferenceEquals(modifier, PrintParameterModifier.BottomLayerOffTime)) return HeaderSettings.BottomLightOffTime; - if (ReferenceEquals(modifier, PrintParameterModifier.LayerOffTime)) return HeaderSettings.LayerLightOffTime; - if (ReferenceEquals(modifier, PrintParameterModifier.BottomLiftHeight)) return HeaderSettings.BottomLayerLiftHeight; - if (ReferenceEquals(modifier, PrintParameterModifier.BottomLiftSpeed)) return HeaderSettings.BottomLayerLiftSpeed; + if (ReferenceEquals(modifier, PrintParameterModifier.LayerOffTime)) return HeaderSettings.LightOffTime; + if (ReferenceEquals(modifier, PrintParameterModifier.BottomLiftHeight)) return HeaderSettings.BottomLiftHeight; + if (ReferenceEquals(modifier, PrintParameterModifier.BottomLiftSpeed)) return HeaderSettings.BottomLiftSpeed; /*if (ReferenceEquals(modifier, PrintParameterModifier.LiftHeight)) return PrintParametersSettings.LiftHeight; if (ReferenceEquals(modifier, PrintParameterModifier.LiftSpeed)) return PrintParametersSettings.LiftingSpeed; if (ReferenceEquals(modifier, PrintParameterModifier.RetractSpeed)) return PrintParametersSettings.RetractSpeed;*/ @@ -358,31 +360,31 @@ namespace UVtools.Core.FileFormats } if (ReferenceEquals(modifier, PrintParameterModifier.LayerOffTime)) { - HeaderSettings.LayerLightOffTime = value.Convert<float>(); + HeaderSettings.LightOffTime = value.Convert<float>(); UpdateGCode(); return true; } if (ReferenceEquals(modifier, PrintParameterModifier.BottomLiftHeight)) { - HeaderSettings.BottomLayerLiftHeight = value.Convert<float>(); + HeaderSettings.BottomLiftHeight = value.Convert<float>(); UpdateGCode(); return true; } if (ReferenceEquals(modifier, PrintParameterModifier.BottomLiftSpeed)) { - HeaderSettings.LayerLiftSpeed = value.Convert<float>(); + HeaderSettings.LiftSpeed = value.Convert<float>(); UpdateGCode(); return true; } if (ReferenceEquals(modifier, PrintParameterModifier.LiftHeight)) { - HeaderSettings.LayerLiftHeight = value.Convert<float>(); + HeaderSettings.LiftHeight = value.Convert<float>(); UpdateGCode(); return true; } if (ReferenceEquals(modifier, PrintParameterModifier.LiftSpeed)) { - HeaderSettings.LayerLiftSpeed = value.Convert<float>(); + HeaderSettings.LiftSpeed = value.Convert<float>(); UpdateGCode(); return true; } @@ -443,7 +445,60 @@ namespace UVtools.Core.FileFormats public override bool Convert(Type to, string fileFullPath, OperationProgress progress = null) { - throw new NotImplementedException(); + if (to == typeof(UVJFile)) + { + UVJFile defaultFormat = (UVJFile)FindByType(typeof(UVJFile)); + UVJFile file = new UVJFile + { + LayerManager = LayerManager, + JsonSettings = new UVJFile.Settings + { + Properties = new UVJFile.Properties + { + Size = new UVJFile.Size + { + X = (ushort)ResolutionX, + Y = (ushort)ResolutionY, + Millimeter = new UVJFile.Millimeter + { + X = HeaderSettings.MachineX, + Y = HeaderSettings.MachineY, + }, + LayerHeight = LayerHeight, + Layers = LayerCount + }, + Bottom = new UVJFile.Bottom + { + LiftHeight = HeaderSettings.BottomLiftHeight, + LiftSpeed = HeaderSettings.BottomLiftSpeed, + LightOnTime = InitialExposureTime, + LightOffTime = HeaderSettings.BottomLightOffTime, + LightPWM = HeaderSettings.BottomLightPWM, + RetractSpeed = HeaderSettings.RetractSpeed, + Count = InitialLayerCount + //RetractHeight = LookupCustomValue<float>(Keyword_LiftHeight, defaultFormat.JsonSettings.Properties.Bottom.RetractHeight), + }, + Exposure = new UVJFile.Exposure + { + LiftHeight = HeaderSettings.LiftHeight, + LiftSpeed = HeaderSettings.LiftSpeed, + LightOnTime = LayerExposureTime, + LightOffTime = HeaderSettings.LightOffTime, + LightPWM = HeaderSettings.LayerLightPWM, + RetractSpeed = HeaderSettings.RetractSpeed, + }, + AntiAliasLevel = ValidateAntiAliasingLevel() + } + } + }; + + file.SetThumbnails(Thumbnails); + file.Encode(fileFullPath, progress); + + return true; + } + + return false; } private void UpdateGCode() @@ -466,16 +521,16 @@ namespace UVtools.Core.FileFormats for (uint layerIndex = 0; layerIndex < LayerCount; layerIndex++) { - var liftHeight = GetInitialLayerValueOrNormal(layerIndex, HeaderSettings.BottomLayerLiftHeight, - HeaderSettings.LayerLiftHeight); + var liftHeight = GetInitialLayerValueOrNormal(layerIndex, HeaderSettings.BottomLiftHeight, + HeaderSettings.LiftHeight); var liftZHeight = liftHeight + this[layerIndex].PositionZ; - var liftZSpeed = GetInitialLayerValueOrNormal(layerIndex, HeaderSettings.BottomLayerLiftSpeed, - HeaderSettings.LayerLiftSpeed); + var liftZSpeed = GetInitialLayerValueOrNormal(layerIndex, HeaderSettings.BottomLiftSpeed, + HeaderSettings.LiftSpeed); var lightOffDelay = GetInitialLayerValueOrNormal(layerIndex, HeaderSettings.BottomLightOffTime, - HeaderSettings.LayerLightOffTime) * 1000; + HeaderSettings.LightOffTime) * 1000; var pwmValue = GetInitialLayerValueOrNormal(layerIndex, HeaderSettings.BottomLightPWM, HeaderSettings.LayerLightPWM); var exposureTime = GetInitialLayerValueOrNormal(layerIndex, InitialExposureTime, LayerExposureTime) * 1000; diff --git a/UVtools.Core/FileFormats/FileFormat.cs b/UVtools.Core/FileFormats/FileFormat.cs index 89235cc..67fc2db 100644 --- a/UVtools.Core/FileFormats/FileFormat.cs +++ b/UVtools.Core/FileFormats/FileFormat.cs @@ -136,6 +136,7 @@ namespace UVtools.Core.FileFormats new PWSFile(), // PSW new ZCodexFile(), // zcodex new CWSFile(), // CWS + new UVJFile(), // UVJ new ImageFile(), // images }; diff --git a/UVtools.Core/FileFormats/PHZFile.cs b/UVtools.Core/FileFormats/PHZFile.cs index c921493..e9a69a2 100644 --- a/UVtools.Core/FileFormats/PHZFile.cs +++ b/UVtools.Core/FileFormats/PHZFile.cs @@ -686,6 +686,7 @@ namespace UVtools.Core.FileFormats typeof(PWSFile), typeof(ZCodexFile), typeof(CWSFile), + typeof(UVJFile), }; public override PrintParameterModifier[] PrintParameterModifiers { get; } = @@ -1226,15 +1227,15 @@ namespace UVtools.Core.FileFormats Mirror = (byte) (HeaderSettings.ProjectorType == 0 ? 0 : 1), - BottomLayerLiftHeight = HeaderSettings.BottomLiftHeight, - LayerLiftHeight = HeaderSettings.LiftHeight, - BottomLayerLiftSpeed = HeaderSettings.BottomLiftSpeed, - LayerLiftSpeed = HeaderSettings.LiftSpeed, + BottomLiftHeight = HeaderSettings.BottomLiftHeight, + LiftHeight = HeaderSettings.LiftHeight, + BottomLiftSpeed = HeaderSettings.BottomLiftSpeed, + LiftSpeed = HeaderSettings.LiftSpeed, RetractSpeed = HeaderSettings.RetractSpeed, BottomLayCount = InitialLayerCount, BottomLayerCount = InitialLayerCount, BottomLightOffTime = HeaderSettings.BottomLightOffDelay, - LayerLightOffTime = HeaderSettings.LayerOffTime, + LightOffTime = HeaderSettings.LayerOffTime, BottomLayExposureTime = InitialExposureTime, BottomLayerExposureTime = InitialExposureTime, LayerExposureTime = LayerExposureTime, @@ -1409,6 +1410,58 @@ namespace UVtools.Core.FileFormats return true; } + if (to == typeof(UVJFile)) + { + UVJFile file = new UVJFile + { + LayerManager = LayerManager, + JsonSettings = new UVJFile.Settings + { + Properties = new UVJFile.Properties + { + Size = new UVJFile.Size + { + X = (ushort)ResolutionX, + Y = (ushort)ResolutionY, + Millimeter = new UVJFile.Millimeter + { + X = HeaderSettings.BedSizeX, + Y = HeaderSettings.BedSizeY, + }, + LayerHeight = LayerHeight, + Layers = LayerCount + }, + Bottom = new UVJFile.Bottom + { + LiftHeight = HeaderSettings.BottomLiftHeight, + LiftSpeed = HeaderSettings.BottomLiftSpeed, + LightOnTime = InitialExposureTime, + LightOffTime = HeaderSettings.BottomLightOffDelay, + LightPWM = (byte)HeaderSettings.BottomLightPWM, + RetractSpeed = HeaderSettings.RetractSpeed, + Count = InitialLayerCount + //RetractHeight = LookupCustomValue<float>(Keyword_LiftHeight, defaultFormat.JsonSettings.Properties.Bottom.RetractHeight), + }, + Exposure = new UVJFile.Exposure + { + LiftHeight = HeaderSettings.LiftHeight, + LiftSpeed = HeaderSettings.LiftSpeed, + LightOnTime = LayerExposureTime, + LightOffTime = HeaderSettings.LayerOffTime, + LightPWM = (byte)HeaderSettings.LightPWM, + RetractSpeed = HeaderSettings.RetractSpeed, + }, + AntiAliasLevel = ValidateAntiAliasingLevel() + } + } + }; + + file.SetThumbnails(Thumbnails); + file.Encode(fileFullPath, progress); + + return true; + } + return false; } #endregion diff --git a/UVtools.Core/FileFormats/PWSFile.cs b/UVtools.Core/FileFormats/PWSFile.cs index c4c4fce..384f339 100644 --- a/UVtools.Core/FileFormats/PWSFile.cs +++ b/UVtools.Core/FileFormats/PWSFile.cs @@ -432,8 +432,6 @@ namespace UVtools.Core.FileFormats int index = 0; for (byte bit = 0; bit < Parent.AntiAliasing; bit++) { - byte bitValue = (byte)(byte.MaxValue / ((1 << Parent.AntiAliasing) - 1) * (1 << bit)); - int pixel = 0; for (; index < EncodedRle.Length; index++) { @@ -446,7 +444,7 @@ namespace UVtools.Core.FileFormats { for (int i = 0; i < reps; i++) { - span[pixel + i] |= bitValue; + span[pixel + i]++; } } @@ -466,6 +464,18 @@ namespace UVtools.Core.FileFormats } } + for (int i = 0; i < span.Length; i++) + { + int newC = span[i] * (256 / Parent.AntiAliasing); + + if (newC > 0) + { + newC--; + } + + span[i] = (byte)newC; + } + return image; } @@ -497,10 +507,18 @@ namespace UVtools.Core.FileFormats obit = false; rep = 0; + //ngrey:= uint16(r | g | b) + // thresholds: + // aa 1: 127 + // aa 2: 255 127 + // aa 4: 255 191 127 63 + // aa 8: 255 223 191 159 127 95 63 31 + byte threshold = (byte)(256 / Parent.AntiAliasing * aalevel - 1); + for (int pixel = 0; pixel < span.Length; pixel++) { - var nbit = (span[pixel] & (1 << (8 - Parent.AntiAliasing + aalevel))) != 0; + var nbit = span[pixel] >= threshold; if (nbit == obit) { @@ -758,6 +776,7 @@ namespace UVtools.Core.FileFormats //typeof(PHZFile), typeof(PWSFile), typeof(CWSFile), + typeof(UVJFile), }; public override PrintParameterModifier[] PrintParameterModifiers { get; } = @@ -1342,6 +1361,58 @@ namespace UVtools.Core.FileFormats return true; } + if (to == typeof(UVJFile)) + { + UVJFile file = new UVJFile + { + LayerManager = LayerManager, + JsonSettings = new UVJFile.Settings + { + Properties = new UVJFile.Properties + { + Size = new UVJFile.Size + { + X = (ushort)ResolutionX, + Y = (ushort)ResolutionY, + Millimeter = new UVJFile.Millimeter + { + //X = HeaderSettings.BedSizeX, + //Y = HeaderSettings.BedSizeY, + }, + LayerHeight = LayerHeight, + Layers = LayerCount + }, + Bottom = new UVJFile.Bottom + { + LiftHeight = HeaderSettings.LiftHeight, + LiftSpeed = HeaderSettings.LiftSpeed, + LightOnTime = InitialExposureTime, + LightOffTime = HeaderSettings.LayerOffTime, + //LightPWM = (byte)HeaderSettings.LightPWM, + RetractSpeed = HeaderSettings.RetractSpeed, + Count = InitialLayerCount + //RetractHeight = LookupCustomValue<float>(Keyword_LiftHeight, defaultFormat.JsonSettings.Properties.Bottom.RetractHeight), + }, + Exposure = new UVJFile.Exposure + { + LiftHeight = HeaderSettings.LiftHeight, + LiftSpeed = HeaderSettings.LiftSpeed, + LightOnTime = LayerExposureTime, + LightOffTime = HeaderSettings.LayerOffTime, + //LightPWM = (byte)HeaderSettings.LightPWM, + RetractSpeed = HeaderSettings.RetractSpeed, + }, + AntiAliasLevel = ValidateAntiAliasingLevel() + } + } + }; + + file.SetThumbnails(Thumbnails); + file.Encode(fileFullPath, progress); + + return true; + } + return false; } #endregion diff --git a/UVtools.Core/FileFormats/SL1File.cs b/UVtools.Core/FileFormats/SL1File.cs index 3f88b2c..62ea9c0 100644 --- a/UVtools.Core/FileFormats/SL1File.cs +++ b/UVtools.Core/FileFormats/SL1File.cs @@ -299,6 +299,7 @@ namespace UVtools.Core.FileFormats typeof(PHZFile), typeof(ZCodexFile), typeof(CWSFile), + typeof(UVJFile), }; public override PrintParameterModifier[] PrintParameterModifiers { get; } = { @@ -693,15 +694,15 @@ namespace UVtools.Core.FileFormats Mirror = (byte) (PrinterSettings.DisplayMirrorX || PrinterSettings.DisplayMirrorY ? 1 : 0), - BottomLayerLiftHeight = LookupCustomValue<float>(Keyword_BottomLiftHeight, defaultFormat.HeaderSettings.BottomLayerLiftHeight), - LayerLiftHeight = LookupCustomValue<float>(Keyword_LiftHeight, defaultFormat.HeaderSettings.LayerLiftHeight), - BottomLayerLiftSpeed = LookupCustomValue<float>(Keyword_BottomLiftSpeed, defaultFormat.HeaderSettings.BottomLayerLiftSpeed), - LayerLiftSpeed = LookupCustomValue<float>(Keyword_LiftSpeed, defaultFormat.HeaderSettings.LayerLiftSpeed), + BottomLiftHeight = LookupCustomValue<float>(Keyword_BottomLiftHeight, defaultFormat.HeaderSettings.BottomLiftHeight), + LiftHeight = LookupCustomValue<float>(Keyword_LiftHeight, defaultFormat.HeaderSettings.LiftHeight), + BottomLiftSpeed = LookupCustomValue<float>(Keyword_BottomLiftSpeed, defaultFormat.HeaderSettings.BottomLiftSpeed), + LiftSpeed = LookupCustomValue<float>(Keyword_LiftSpeed, defaultFormat.HeaderSettings.LiftSpeed), RetractSpeed = LookupCustomValue<float>(Keyword_RetractSpeed, defaultFormat.HeaderSettings.RetractSpeed), BottomLayCount = InitialLayerCount, BottomLayerCount = InitialLayerCount, BottomLightOffTime = LookupCustomValue<float>(Keyword_BottomLightOffDelay, defaultFormat.HeaderSettings.BottomLightOffTime), - LayerLightOffTime = LookupCustomValue<float>(Keyword_LightOffDelay, defaultFormat.HeaderSettings.LayerLightOffTime), + LightOffTime = LookupCustomValue<float>(Keyword_LightOffDelay, defaultFormat.HeaderSettings.LightOffTime), BottomLayExposureTime = InitialExposureTime, BottomLayerExposureTime = InitialExposureTime, LayerExposureTime = LayerExposureTime, @@ -953,6 +954,65 @@ namespace UVtools.Core.FileFormats return true; } + if (to == typeof(UVJFile)) + { + UVJFile defaultFormat = (UVJFile)FindByType(typeof(UVJFile)); + UVJFile file = new UVJFile + { + LayerManager = LayerManager, + JsonSettings = new UVJFile.Settings + { + Properties = new UVJFile.Properties + { + Size = new UVJFile.Size + { + X = (ushort)ResolutionX, + Y = (ushort)ResolutionY, + Millimeter = new UVJFile.Millimeter + { + X = PrinterSettings.DisplayWidth, + Y = PrinterSettings.DisplayHeight, + }, + LayerHeight = LayerHeight, + Layers = LayerCount + }, + Bottom = new UVJFile.Bottom + { + LiftHeight = LookupCustomValue<float>(Keyword_BottomLiftHeight, defaultFormat.JsonSettings.Properties.Bottom.LiftHeight), + LiftSpeed = LookupCustomValue<float>(Keyword_BottomLiftSpeed, defaultFormat.JsonSettings.Properties.Bottom.LiftSpeed), + LightOnTime = InitialExposureTime, + LightOffTime = LookupCustomValue<float>(Keyword_BottomLightOffDelay, defaultFormat.JsonSettings.Properties.Bottom.LightOffTime), + LightPWM = LookupCustomValue<byte>(Keyword_BottomLightPWM, defaultFormat.JsonSettings.Properties.Bottom.LightPWM), + RetractSpeed = LookupCustomValue<float>(Keyword_RetractSpeed, defaultFormat.JsonSettings.Properties.Bottom.RetractSpeed), + Count = InitialLayerCount + //RetractHeight = LookupCustomValue<float>(Keyword_LiftHeight, defaultFormat.JsonSettings.Properties.Bottom.RetractHeight), + }, + Exposure = new UVJFile.Exposure + { + LiftHeight = LookupCustomValue<float>(Keyword_LiftHeight, defaultFormat.JsonSettings.Properties.Exposure.LiftHeight), + LiftSpeed = LookupCustomValue<float>(Keyword_LiftSpeed, defaultFormat.JsonSettings.Properties.Exposure.LiftSpeed), + LightOnTime = LayerExposureTime, + LightOffTime = LookupCustomValue<float>(Keyword_LightOffDelay, defaultFormat.JsonSettings.Properties.Exposure.LightOffTime), + LightPWM = LookupCustomValue<byte>(Keyword_LightPWM, defaultFormat.JsonSettings.Properties.Exposure.LightPWM), + RetractSpeed = LookupCustomValue<float>(Keyword_RetractSpeed, defaultFormat.JsonSettings.Properties.Exposure.RetractSpeed), + }, + AntiAliasLevel = ValidateAntiAliasingLevel() + } + } + }; + + if (LookupCustomValue<bool>("FLIP_XY", false, true)) + { + file.JsonSettings.Properties.Size.X = (ushort) ResolutionY; + file.JsonSettings.Properties.Size.Y = (ushort) ResolutionX; + } + + file.SetThumbnails(Thumbnails); + file.Encode(fileFullPath, progress); + + return true; + } + return false; } diff --git a/UVtools.Core/FileFormats/UVJFile.cs b/UVtools.Core/FileFormats/UVJFile.cs new file mode 100644 index 0000000..e46c722 --- /dev/null +++ b/UVtools.Core/FileFormats/UVJFile.cs @@ -0,0 +1,475 @@ +/* + * GNU AFFERO GENERAL PUBLIC LICENSE + * Version 3, 19 November 2007 + * Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/> + * Everyone is permitted to copy and distribute verbatim copies + * of this license document, but changing it is not allowed. + */ + +using System; +using System.Collections.Generic; +using System.IO; +using System.IO.Compression; +using System.Text; +using System.Text.RegularExpressions; +using Emgu.CV; +using Emgu.CV.CvEnum; +using Emgu.CV.Util; +using Newtonsoft.Json; +using UVtools.Core.Extensions; +using UVtools.Core.Operations; + +namespace UVtools.Core.FileFormats +{ + public class UVJFile : FileFormat + { + #region Constants + + private const string FileConfigName = "config.json"; + private const string FolderImageName = "slice"; + private const string FolderPreviewName = "preview"; + private const string FilePreviewHugeName = "preview/huge.png"; + private const string FilePreviewTinyName = "preview/tiny.png"; + #endregion + + #region Sub Classes + + public class Millimeter + { + public float X { get; set; } + public float Y { get; set; } + } + + public class Size + { + public ushort X { get; set; } + public ushort Y { get; set; } + + public Millimeter Millimeter { get; set; } = new Millimeter(); + + public uint Layers { get; set; } + public float LayerHeight { get; set; } + + public override string ToString() + { + return $"{nameof(X)}: {X}, {nameof(Y)}: {Y}, {nameof(Millimeter)}: {Millimeter}, {nameof(Layers)}: {Layers}, {nameof(LayerHeight)}: {LayerHeight}"; + } + } + + public class Exposure + { + public float LightOnTime { get; set; } + public float LightOffTime { get; set; } + public byte LightPWM { get; set; } = 255; + public float LiftHeight { get; set; } = 5; + public float LiftSpeed { get; set; } = 100; + public float RetractHeight { get; set; } + public float RetractSpeed { get; set; } = 100; + + public override string ToString() + { + return $"{nameof(LightOnTime)}: {LightOnTime}, {nameof(LightOffTime)}: {LightOffTime}, {nameof(LightPWM)}: {LightPWM}, {nameof(LiftHeight)}: {LiftHeight}, {nameof(LiftSpeed)}: {LiftSpeed}, {nameof(RetractHeight)}: {RetractHeight}, {nameof(RetractSpeed)}: {RetractSpeed}"; + } + } + + public class Bottom + { + public float LightOnTime { get; set; } + public float LightOffTime { get; set; } + public byte LightPWM { get; set; } = 255; + public float LiftHeight { get; set; } = 5; + public float LiftSpeed { get; set; } = 100; + public float RetractHeight { get; set; } + public float RetractSpeed { get; set; } = 100; + public ushort Count { get; set; } + + public override string ToString() + { + return $"{nameof(LightOnTime)}: {LightOnTime}, {nameof(LightOffTime)}: {LightOffTime}, {nameof(LightPWM)}: {LightPWM}, {nameof(LiftHeight)}: {LiftHeight}, {nameof(LiftSpeed)}: {LiftSpeed}, {nameof(RetractHeight)}: {RetractHeight}, {nameof(RetractSpeed)}: {RetractSpeed}, {nameof(Count)}: {Count}"; + } + } + + public class LayerData + { + public float Z { get; set; } + public Exposure Exposure { get; set; } + + public override string ToString() + { + return $"{nameof(Z)}: {Z}, {nameof(Exposure)}: {Exposure}"; + } + } + + public class Properties + { + public Size Size { get; set; } = new Size(); + public Exposure Exposure { get; set; } = new Exposure(); + public Bottom Bottom { get; set; } = new Bottom(); + public byte AntiAliasLevel { get; set; } = 1; + + public override string ToString() + { + return $"{nameof(Size)}: {Size}, {nameof(Exposure)}: {Exposure}, {nameof(Bottom)}: {Bottom}, {nameof(AntiAliasLevel)}: {AntiAliasLevel}"; + } + } + + public class Settings + { + public Properties Properties { get; set; } = new Properties(); + public List<LayerData> Layers { get; set; } = new List<LayerData>(); + + public override string ToString() + { + return $"{nameof(Properties)}: {Properties}, {nameof(Layers)}: {Layers.Count}"; + } + } + + #endregion + + #region Properties + public Settings JsonSettings { get; set; } = new Settings(); + + public override FileFormatType FileType => FileFormatType.Archive; + + public override FileExtension[] FileExtensions { get; } = { + new FileExtension("uvj", "UVJ Files") + }; + + public override Type[] ConvertToFormats { get; } = null; + + public override PrintParameterModifier[] PrintParameterModifiers { get; } = { + PrintParameterModifier.InitialLayerCount, + PrintParameterModifier.InitialExposureSeconds, + PrintParameterModifier.ExposureSeconds, + + PrintParameterModifier.BottomLayerOffTime, + PrintParameterModifier.LayerOffTime, + PrintParameterModifier.BottomLiftHeight, + PrintParameterModifier.BottomLiftSpeed, + PrintParameterModifier.LiftHeight, + PrintParameterModifier.LiftSpeed, + PrintParameterModifier.RetractSpeed, + + PrintParameterModifier.BottomLightPWM, + PrintParameterModifier.LightPWM, + }; + + public override byte ThumbnailsCount { get; } = 2; + + public override System.Drawing.Size[] ThumbnailsOriginalSize { get; } = {new System.Drawing.Size(400, 400), new System.Drawing.Size(800, 480) }; + + public override uint ResolutionX => JsonSettings.Properties.Size.X; + + public override uint ResolutionY => JsonSettings.Properties.Size.Y; + public override byte AntiAliasing => JsonSettings.Properties.AntiAliasLevel; + + public override float LayerHeight => JsonSettings.Properties.Size.LayerHeight; + + public override ushort InitialLayerCount => JsonSettings.Properties.Bottom.Count; + + public override float InitialExposureTime => JsonSettings.Properties.Bottom.LightOnTime; + + public override float LayerExposureTime => JsonSettings.Properties.Exposure.LightOnTime; + public override float LiftHeight => JsonSettings.Properties.Exposure.LiftHeight; + + public override float LiftSpeed => JsonSettings.Properties.Exposure.LiftSpeed; + + public override float RetractSpeed => JsonSettings.Properties.Exposure.RetractSpeed; + + public override float PrintTime => 0; + + public override float UsedMaterial => 0; + + public override float MaterialCost => 0; + + public override string MaterialName => null; + + public override string MachineName => null; + + public override object[] Configs => new[] {(object) JsonSettings.Properties.Size, JsonSettings.Properties.Size.Millimeter, JsonSettings.Properties.Bottom, JsonSettings.Properties.Exposure}; + #endregion + + #region Methods + + public override void Clear() + { + base.Clear(); + JsonSettings.Layers = new List<LayerData>(); + } + + public override void Encode(string fileFullPath, OperationProgress progress = null) + { + base.Encode(fileFullPath, progress); + + if (JsonSettings.Layers.Count == 0) + { + for (uint layerIndex = 0; layerIndex < LayerCount; layerIndex++) + { + JsonSettings.Layers.Add(new LayerData + { + Z = this[layerIndex].PositionZ, + Exposure = new Exposure + { + LiftHeight = GetInitialLayerValueOrNormal(layerIndex, JsonSettings.Properties.Bottom.LiftHeight, JsonSettings.Properties.Exposure.LiftHeight), + LiftSpeed = GetInitialLayerValueOrNormal(layerIndex, JsonSettings.Properties.Bottom.LiftSpeed, JsonSettings.Properties.Exposure.LiftSpeed), + LightOnTime = GetInitialLayerValueOrNormal(layerIndex, InitialExposureTime, LayerExposureTime), + LightOffTime = GetInitialLayerValueOrNormal(layerIndex, JsonSettings.Properties.Bottom.LightOffTime, JsonSettings.Properties.Exposure.LightOffTime), + LightPWM = GetInitialLayerValueOrNormal(layerIndex, JsonSettings.Properties.Bottom.LightPWM, JsonSettings.Properties.Exposure.LightPWM), + RetractSpeed = GetInitialLayerValueOrNormal(layerIndex, JsonSettings.Properties.Bottom.RetractSpeed, JsonSettings.Properties.Exposure.RetractSpeed), + } + }); + } + } + + using (ZipArchive outputFile = ZipFile.Open(fileFullPath, ZipArchiveMode.Create)) + { + outputFile.PutFileContent(FileConfigName, JsonConvert.SerializeObject(JsonSettings), ZipArchiveMode.Create); + + if (CreatedThumbnailsCount > 0) + { + using (Stream stream = outputFile.CreateEntry(FilePreviewTinyName).Open()) + { + using (var vec = new VectorOfByte()) + { + CvInvoke.Imencode(".png", Thumbnails[0], vec); + stream.WriteBytes(vec.ToArray()); + stream.Close(); + } + } + } + + if (CreatedThumbnailsCount > 1) + { + using (Stream stream = outputFile.CreateEntry(FilePreviewHugeName).Open()) + { + using (var vec = new VectorOfByte()) + { + CvInvoke.Imencode(".png", Thumbnails[1], vec); + stream.WriteBytes(vec.ToArray()); + stream.Close(); + } + } + } + + for (uint layerIndex = 0; layerIndex < LayerCount; layerIndex++) + { + progress.Token.ThrowIfCancellationRequested(); + + Layer layer = this[layerIndex]; + + var layerimagePath = $"{FolderImageName}/{layerIndex:D8}.png"; + outputFile.PutFileContent(layerimagePath, layer.CompressedBytes, ZipArchiveMode.Create); + + progress++; + } + } + } + + public override void Decode(string fileFullPath, OperationProgress progress = null) + { + base.Decode(fileFullPath, progress); + + FileFullPath = fileFullPath; + using (var inputFile = ZipFile.Open(FileFullPath, ZipArchiveMode.Read)) + { + var entry = inputFile.GetEntry(FileConfigName); + if (ReferenceEquals(entry, null)) + { + Clear(); + throw new FileLoadException($"{FileConfigName} not found", fileFullPath); + } + + JsonSettings = Helpers.JsonDeserializeObject<Settings>(entry.Open()); + + LayerManager = new LayerManager(JsonSettings.Properties.Size.Layers); + + entry = inputFile.GetEntry(FilePreviewTinyName); + if (!ReferenceEquals(entry, null)) + { + using (Stream stream = entry.Open()) + { + CvInvoke.Imdecode(stream.ToArray(), ImreadModes.AnyColor, Thumbnails[0]); + stream.Close(); + } + } + + entry = inputFile.GetEntry(FilePreviewHugeName); + if (!ReferenceEquals(entry, null)) + { + using (Stream stream = entry.Open()) + { + CvInvoke.Imdecode(stream.ToArray(), ImreadModes.AnyColor, Thumbnails[1]); + stream.Close(); + } + } + + for (uint layerIndex = 0; layerIndex < LayerCount; layerIndex++) + { + entry = inputFile.GetEntry($"{FolderImageName}/{layerIndex:D8}.png"); + if (ReferenceEquals(entry, null)) continue; + + LayerManager[layerIndex] = new Layer(layerIndex, entry.Open(), entry.Name) + { + PositionZ = JsonSettings.Layers.Count >= layerIndex ? JsonSettings.Layers[(int) layerIndex].Z : GetHeightFromLayer(layerIndex), + ExposureTime = JsonSettings.Layers.Count >= layerIndex ? JsonSettings.Layers[(int)layerIndex].Exposure.LightOnTime : GetInitialLayerValueOrNormal(layerIndex, InitialExposureTime, LayerExposureTime) + }; + } + + progress.ProcessedItems++; + } + + LayerManager.GetBoundingRectangle(progress); + } + + public override object GetValueFromPrintParameterModifier(PrintParameterModifier modifier) + { + var baseValue = base.GetValueFromPrintParameterModifier(modifier); + if (!ReferenceEquals(baseValue, null)) return baseValue; + if (ReferenceEquals(modifier, PrintParameterModifier.BottomLayerOffTime)) return JsonSettings.Properties.Bottom.LightOffTime; + if (ReferenceEquals(modifier, PrintParameterModifier.LayerOffTime)) return JsonSettings.Properties.Exposure.LightOffTime; + if (ReferenceEquals(modifier, PrintParameterModifier.BottomLiftHeight)) return JsonSettings.Properties.Bottom.LiftHeight; + if (ReferenceEquals(modifier, PrintParameterModifier.BottomLiftSpeed)) return JsonSettings.Properties.Bottom.LiftSpeed; + + if (ReferenceEquals(modifier, PrintParameterModifier.BottomLightPWM)) return JsonSettings.Properties.Bottom.LightPWM; + if (ReferenceEquals(modifier, PrintParameterModifier.LightPWM)) return JsonSettings.Properties.Exposure.LightPWM; + + return null; + } + + public override bool SetValueFromPrintParameterModifier(PrintParameterModifier modifier, string value) + { + void UpdateLayers() + { + for (uint layerIndex = 0; layerIndex < LayerCount; layerIndex++) + { + // Bottom : others + if(JsonSettings.Layers.Count <= layerIndex) break; + + JsonSettings.Layers[(int) layerIndex].Exposure.LiftHeight = + GetInitialLayerValueOrNormal(layerIndex, JsonSettings.Properties.Bottom.LiftHeight, JsonSettings.Properties.Exposure.LiftHeight); + JsonSettings.Layers[(int)layerIndex].Exposure.LightPWM = + GetInitialLayerValueOrNormal(layerIndex, JsonSettings.Properties.Bottom.LightPWM, JsonSettings.Properties.Exposure.LightPWM); + JsonSettings.Layers[(int)layerIndex].Exposure.LiftSpeed = + GetInitialLayerValueOrNormal(layerIndex, JsonSettings.Properties.Bottom.LiftSpeed, JsonSettings.Properties.Exposure.LiftSpeed); + JsonSettings.Layers[(int)layerIndex].Exposure.LightOnTime = + GetInitialLayerValueOrNormal(layerIndex, JsonSettings.Properties.Bottom.LightOnTime, JsonSettings.Properties.Exposure.LightOnTime); + JsonSettings.Layers[(int)layerIndex].Exposure.RetractSpeed = + GetInitialLayerValueOrNormal(layerIndex, JsonSettings.Properties.Bottom.RetractSpeed, JsonSettings.Properties.Exposure.RetractSpeed); + JsonSettings.Layers[(int)layerIndex].Exposure.LightOffTime = + GetInitialLayerValueOrNormal(layerIndex, JsonSettings.Properties.Bottom.LightOffTime, JsonSettings.Properties.Exposure.LightOffTime); + JsonSettings.Layers[(int)layerIndex].Exposure.RetractHeight = + GetInitialLayerValueOrNormal(layerIndex, JsonSettings.Properties.Bottom.RetractHeight, JsonSettings.Properties.Exposure.RetractHeight); + } + } + + if (ReferenceEquals(modifier, PrintParameterModifier.InitialLayerCount)) + { + JsonSettings.Properties.Bottom.Count = value.Convert<ushort>(); + UpdateLayers(); + return true; + } + if (ReferenceEquals(modifier, PrintParameterModifier.InitialExposureSeconds)) + { + JsonSettings.Properties.Bottom.LightOnTime = value.Convert<float>(); + UpdateLayers(); + return true; + } + + if (ReferenceEquals(modifier, PrintParameterModifier.ExposureSeconds)) + { + JsonSettings.Properties.Exposure.LightOnTime = value.Convert<float>(); + UpdateLayers(); + return true; + } + + if (ReferenceEquals(modifier, PrintParameterModifier.BottomLayerOffTime)) + { + JsonSettings.Properties.Bottom.LightOffTime = value.Convert<float>(); + UpdateLayers(); + return true; + } + if (ReferenceEquals(modifier, PrintParameterModifier.LayerOffTime)) + { + JsonSettings.Properties.Exposure.LightOffTime = value.Convert<float>(); + UpdateLayers(); + return true; + } + if (ReferenceEquals(modifier, PrintParameterModifier.BottomLiftHeight)) + { + JsonSettings.Properties.Bottom.LiftHeight = value.Convert<float>(); + UpdateLayers(); + return true; + } + if (ReferenceEquals(modifier, PrintParameterModifier.BottomLiftSpeed)) + { + JsonSettings.Properties.Bottom.LiftSpeed = value.Convert<float>(); + UpdateLayers(); + return true; + } + if (ReferenceEquals(modifier, PrintParameterModifier.LiftHeight)) + { + JsonSettings.Properties.Exposure.LiftHeight = value.Convert<float>(); + UpdateLayers(); + return true; + } + if (ReferenceEquals(modifier, PrintParameterModifier.LiftSpeed)) + { + JsonSettings.Properties.Exposure.LiftSpeed = value.Convert<float>(); + UpdateLayers(); + return true; + } + if (ReferenceEquals(modifier, PrintParameterModifier.RetractSpeed)) + { + JsonSettings.Properties.Exposure.RetractSpeed = value.Convert<float>(); + UpdateLayers(); + return true; + } + + if (ReferenceEquals(modifier, PrintParameterModifier.BottomLightPWM)) + { + JsonSettings.Properties.Bottom.LightPWM = value.Convert<byte>(); + UpdateLayers(); + return true; + } + if (ReferenceEquals(modifier, PrintParameterModifier.LightPWM)) + { + JsonSettings.Properties.Exposure.LightPWM = value.Convert<byte>(); + UpdateLayers(); + return true; + } + + return false; + } + + public override void SaveAs(string filePath = null, OperationProgress progress = null) + { + if (!string.IsNullOrEmpty(filePath)) + { + File.Copy(FileFullPath, filePath, true); + FileFullPath = filePath; + + } + + using (var outputFile = ZipFile.Open(FileFullPath, ZipArchiveMode.Update)) + { + outputFile.PutFileContent(FileConfigName, JsonConvert.SerializeObject(JsonSettings), ZipArchiveMode.Update); + + foreach (var layer in this) + { + if (!layer.IsModified) continue; + outputFile.PutFileContent(layer.Filename, layer.CompressedBytes, ZipArchiveMode.Update); + layer.IsModified = false; + } + } + + //Decode(FileFullPath, progress); + } + + public override bool Convert(Type to, string fileFullPath, OperationProgress progress = null) + { + throw new NotImplementedException(); + } + + #endregion + } +} diff --git a/UVtools.Core/Layer/Layer.cs b/UVtools.Core/Layer/Layer.cs index 1842d73..592cbc1 100644 --- a/UVtools.Core/Layer/Layer.cs +++ b/UVtools.Core/Layer/Layer.cs @@ -1,14 +1,20 @@ -using System; +/* + * GNU AFFERO GENERAL PUBLIC LICENSE + * Version 3, 19 November 2007 + * Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/> + * Everyone is permitted to copy and distribute verbatim copies + * of this license document, but changing it is not allowed. + */ +using System; using System.Collections.Generic; using System.Drawing; -using System.IO; -using System.Text; using Emgu.CV; using Emgu.CV.CvEnum; using Emgu.CV.Structure; using Emgu.CV.Util; using UVtools.Core.Extensions; using UVtools.Core.Operations; +using Stream = System.IO.Stream; namespace UVtools.Core { @@ -19,6 +25,8 @@ namespace UVtools.Core { #region Properties + public object Mutex = new object(); + /// <summary> /// Gets the parent layer manager /// </summary> @@ -492,6 +500,10 @@ namespace UVtools.Core else { CvInvoke.Flip(mat, mat, flipType); + /*GpuMat gpumat = new GpuMat(); + gpumat.Upload(mat); + CudaInvoke.Flip(gpumat, gpumat, flipType); + gpumat.Download(mat);*/ } LayerMat = mat; @@ -555,6 +567,91 @@ namespace UVtools.Core } } + public void MutatePixelDimming(Matrix<byte> evenPattern = null, Matrix<byte> oddPattern = null, ushort borderSize = 5) + { + var anchor = new Point(-1, -1); + var kernel = CvInvoke.GetStructuringElement(ElementShape.Rectangle, new Size(3, 3), anchor); + if (ReferenceEquals(evenPattern, null)) + { + evenPattern = new Matrix<byte>(2, 2) + { + [0, 0] = 127, + [0, 1] = 255, + [1, 0] = 255, + [1, 1] = 127, + }; + + if (ReferenceEquals(oddPattern, null)) + { + oddPattern = new Matrix<byte>(2, 2) + { + [0, 0] = 255, + [0, 1] = 127, + [1, 0] = 127, + [1, 1] = 255, + }; + } + } + + using (Mat dst = LayerMat) + { + using (Mat erode = new Mat()) + { + using (Mat diff = new Mat()) + { + using (Mat mask = dst.CloneBlank()) + { + CvInvoke.Erode(dst, erode, kernel, anchor, borderSize, BorderType.Default, default); + CvInvoke.Subtract(dst, erode, diff); + + if (Index % 2 == 0) + { + CvInvoke.Repeat(evenPattern, dst.Rows / evenPattern.Rows + 1, dst.Cols / evenPattern.Cols + 1, mask); + } + else + { + CvInvoke.Repeat(oddPattern, dst.Rows / oddPattern.Rows + 1, dst.Cols / oddPattern.Cols + 1, mask); + } + + using (var maskReshape = new Mat(mask, new Rectangle(0, 0, dst.Width, dst.Height))) + { + CvInvoke.BitwiseAnd(erode, maskReshape, dst); + } + + CvInvoke.Add(dst, diff, dst); + LayerMat = dst; + } + } + } + } + } + + public void MutatePixelDimming(Mat evenPatternMask, Mat oddPatternMask = null, ushort borderSize = 5) + { + var anchor = new Point(-1, -1); + var kernel = CvInvoke.GetStructuringElement(ElementShape.Rectangle, new Size(3, 3), anchor); + + if (ReferenceEquals(oddPatternMask, null)) + { + oddPatternMask = evenPatternMask; + } + + using (Mat dst = LayerMat) + { + using (Mat erode = new Mat()) + { + using (Mat diff = new Mat()) + { + CvInvoke.Erode(dst, erode, kernel, anchor, borderSize, BorderType.Default, default); + CvInvoke.Subtract(dst, erode, diff); + CvInvoke.BitwiseAnd(erode, Index % 2 == 0 ? evenPatternMask : oddPatternMask, dst); + CvInvoke.Add(dst, diff, dst); + LayerMat = dst; + } + } + } + } + public void MutateErode(int iterations = 1, IInputArray kernel = null, Point anchor = default, BorderType borderType = BorderType.Default, MCvScalar borderValue = default) { if (anchor.IsEmpty) anchor = new Point(-1, -1); @@ -565,6 +662,28 @@ namespace UVtools.Core using (Mat dst = LayerMat) { CvInvoke.Erode(dst, dst, kernel, anchor, iterations, borderType, borderValue); + var matrix = new Matrix<byte>(2, 4) + { + [0, 0] = 255, [0, 1] = 255, [0, 2] = 125, [0, 3] = 255, + [1, 0] = 125, [1, 1] = 255, [1, 2] = 255, [1, 3] = 255 + //[0, 0] = 1, + //[0, 0] = 1, + }; + + Mat erode = new Mat(); + kernel = CvInvoke.GetStructuringElement(ElementShape.Rectangle, new Size(3, 3), anchor); + CvInvoke.Erode(dst, erode, kernel, anchor, 5, BorderType.Default, default); + Mat diff = new Mat(); + CvInvoke.Subtract(dst, erode, diff); + + Mat test = dst.CloneBlank(); + CvInvoke.Repeat(matrix, dst.Rows/ matrix.Rows, dst.Cols/ matrix.Cols, test); + + CvInvoke.BitwiseAnd(erode, test, dst); + + CvInvoke.Add(dst, diff, dst); + + //CvInvoke.CopyMakeBorder(LayerMat, dst, 5, 5, 5, 5, BorderType.Wrap); LayerMat = dst; } } diff --git a/UVtools.Core/Layer/LayerIssue.cs b/UVtools.Core/Layer/LayerIssue.cs index 8618d89..949d897 100644 --- a/UVtools.Core/Layer/LayerIssue.cs +++ b/UVtools.Core/Layer/LayerIssue.cs @@ -1,4 +1,10 @@ -using System; +/* + * 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.Collections; using System.Collections.Generic; using System.Drawing; diff --git a/UVtools.Core/Layer/LayerManager.cs b/UVtools.Core/Layer/LayerManager.cs index cf21310..666a7ee 100644 --- a/UVtools.Core/Layer/LayerManager.cs +++ b/UVtools.Core/Layer/LayerManager.cs @@ -20,6 +20,7 @@ using Emgu.CV.Structure; using Emgu.CV.Util; using UVtools.Core.Extensions; using UVtools.Core.Operations; +using UVtools.Core.PixelEditor; namespace UVtools.Core { @@ -33,6 +34,7 @@ namespace UVtools.Core Flip, Rotate, Solidify, + PixelDimming, //LayerSmash, Erode, Dilate, @@ -379,6 +381,65 @@ namespace UVtools.Core progress.Token.ThrowIfCancellationRequested(); } + public void MutatePixelDimming(uint startLayerIndex, uint endLayerIndex, Matrix<byte> evenPattern = null, Matrix<byte> oddPattern = null, ushort borderSize = 5, OperationProgress progress = null) + { + if (ReferenceEquals(progress, null)) progress = new OperationProgress(); + progress.Reset("Dimming pixels", endLayerIndex - startLayerIndex + 1); + + if (ReferenceEquals(evenPattern, null)) + { + evenPattern = new Matrix<byte>(2, 2) + { + [0, 0] = 127, [0, 1] = 255, + [1, 0] = 255, [1, 1] = 127, + }; + + if (ReferenceEquals(oddPattern, null)) + { + oddPattern = new Matrix<byte>(2, 2) + { + [0, 0] = 255, [0, 1] = 127, + [1, 0] = 127, [1, 1] = 255, + }; + } + } + + if (ReferenceEquals(oddPattern, null)) + { + oddPattern = evenPattern; + } + + using (Mat mat = this[0].LayerMat) + { + using (var matEven = mat.CloneBlank()) + { + using (Mat matOdd = mat.CloneBlank()) + { + CvInvoke.Repeat(evenPattern, mat.Rows / evenPattern.Rows + 1, mat.Cols / evenPattern.Cols + 1, matEven); + CvInvoke.Repeat(oddPattern, mat.Rows / oddPattern.Rows + 1, mat.Cols / oddPattern.Cols + 1, matOdd); + + using (var evenPatternMask = new Mat(matEven, new Rectangle(0, 0, mat.Width, mat.Height))) + { + using (var oddPatternMask = new Mat(matOdd, new Rectangle(0, 0, mat.Width, mat.Height))) + { + Parallel.For(startLayerIndex, endLayerIndex + 1, layerIndex => + { + if (progress.Token.IsCancellationRequested) return; + this[layerIndex].MutatePixelDimming(evenPatternMask, oddPatternMask, borderSize); + lock (progress.Mutex) + { + progress++; + } + }); + } + } + } + } + } + + progress.Token.ThrowIfCancellationRequested(); + } + private void MutateGetVarsIterationFade(uint startLayerIndex, uint endLayerIndex, int iterationsStart, int iterationsEnd, ref bool isFade, out int iterationSteps, out int maxIteration) { iterationSteps = 0; @@ -1129,6 +1190,127 @@ namespace UVtools.Core } + public void DrawModifications(PixelHistory pixelHistory, OperationProgress progress = null) + { + if (ReferenceEquals(progress, null)) progress = new OperationProgress(); + progress.Reset("Drawings", (uint) pixelHistory.Count); + + ConcurrentDictionary<uint, Mat> modfiedLayers = new ConcurrentDictionary<uint, Mat>(); + for (var layerIndex = 0; layerIndex < pixelHistory.Count; layerIndex++) + { + var operation = pixelHistory[layerIndex]; + if (operation.OperationType == PixelOperation.PixelOperationType.Drawing) + { + var operationDrawing = (PixelDrawing) operation; + var mat = modfiedLayers.GetOrAdd(operation.LayerIndex, u => this[operation.LayerIndex].LayerMat); + + if (operationDrawing.Rectangle.Size.GetArea() == 1) + { + mat.SetByte(operation.Location.X, operation.Location.Y, operationDrawing.Color); + continue; + } + + switch (operationDrawing.BrushShape) + { + case PixelDrawing.BrushShapeType.Rectangle: + CvInvoke.Rectangle(mat, operationDrawing.Rectangle, new MCvScalar(operationDrawing.Color), + -1); + break; + case PixelDrawing.BrushShapeType.Circle: + CvInvoke.Circle(mat, operation.Location, operationDrawing.BrushSize / 2, + new MCvScalar(operationDrawing.Color), -1); + break; + default: + throw new ArgumentOutOfRangeException(); + } + } + else if (operation.OperationType == PixelOperation.PixelOperationType.Supports) + { + var operationSupport = (PixelSupport)operation; + int drawnLayers = 0; + for (int operationLayer = (int)operation.LayerIndex-1; operationLayer >= 0; operationLayer--) + { + var mat = modfiedLayers.GetOrAdd((uint) operationLayer, u => this[operationLayer].LayerMat); + int radius = (operationLayer > 10 ? Math.Min(operationSupport.TipDiameter + drawnLayers, operationSupport.PillarDiameter) : operationSupport.BaseDiameter) / 2; + uint whitePixels; + + int yStart = Math.Max(0, operation.Location.Y - operationSupport.TipDiameter / 2); + int xStart = Math.Max(0, operation.Location.X - operationSupport.TipDiameter / 2); + + using (Mat matCircleRoi = new Mat(mat, new Rectangle(xStart, yStart, operationSupport.TipDiameter, operationSupport.TipDiameter))) + { + using (Mat matCircleMask = matCircleRoi.CloneBlank()) + { + CvInvoke.Circle(matCircleMask, new Point(operationSupport.TipDiameter / 2, operationSupport.TipDiameter / 2), + operationSupport.TipDiameter / 2, new MCvScalar(255), -1); + CvInvoke.BitwiseAnd(matCircleRoi, matCircleMask, matCircleMask); + whitePixels = (uint) CvInvoke.CountNonZero(matCircleMask); + } + } + + if (whitePixels >= Math.Pow(operationSupport.TipDiameter, 2) / 3) + { + //CvInvoke.Circle(mat, operation.Location, radius, new MCvScalar(255), -1); + if (drawnLayers == 0) continue; // Supports nonexistent, keep digging + break; // White area end supporting + } + + CvInvoke.Circle(mat, operation.Location, radius, new MCvScalar(255), -1); + drawnLayers++; + } + } + else if (operation.OperationType == PixelOperation.PixelOperationType.DrainHole) + { + uint drawnLayers = 0; + var operationDrainHole = (PixelDrainHole)operation; + for (int operationLayer = (int)operation.LayerIndex; operationLayer >= 0; operationLayer--) + { + var mat = modfiedLayers.GetOrAdd((uint)operationLayer, u => this[operationLayer].LayerMat); + int radius = operationDrainHole.Diameter / 2; + uint blackPixels; + + int yStart = Math.Max(0, operation.Location.Y - radius); + int xStart = Math.Max(0, operation.Location.X - radius); + + using (Mat matCircleRoi = new Mat(mat, new Rectangle(xStart, yStart, operationDrainHole.Diameter, operationDrainHole.Diameter))) + { + using (Mat matCircleRoiInv = new Mat()) + { + CvInvoke.Threshold(matCircleRoi, matCircleRoiInv, 100, 255, ThresholdType.BinaryInv); + using (Mat matCircleMask = matCircleRoi.CloneBlank()) + { + CvInvoke.Circle(matCircleMask, new Point(radius, radius), radius, new MCvScalar(255), -1); + CvInvoke.BitwiseAnd(matCircleRoiInv, matCircleMask, matCircleMask); + blackPixels = (uint) CvInvoke.CountNonZero(matCircleMask); + } + } + } + + if (blackPixels >= Math.Pow(operationDrainHole.Diameter, 2) / 3) // Enough area to drain? + { + if (drawnLayers == 0) continue; // Drill not found a target yet, keep digging + break; // Stop drill drain found! + } + + CvInvoke.Circle(mat, operation.Location, radius, new MCvScalar(0), -1); + drawnLayers++; + } + } + + progress++; + } + + progress.Reset("Saving", (uint) modfiedLayers.Count); + foreach (var modfiedLayer in modfiedLayers) + { + this[modfiedLayer.Key].LayerMat = modfiedLayer.Value; + modfiedLayer.Value.Dispose(); + progress++; + } + + pixelHistory.Clear(); + } + /// <summary> /// Desmodify all layers /// </summary> diff --git a/UVtools.Core/Operations/OperationMove.cs b/UVtools.Core/Operations/OperationMove.cs index bed0879..4c8ecb6 100644 --- a/UVtools.Core/Operations/OperationMove.cs +++ b/UVtools.Core/Operations/OperationMove.cs @@ -1,4 +1,11 @@ -using System; +/* + * GNU AFFERO GENERAL PUBLIC LICENSE + * Version 3, 19 November 2007 + * Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/> + * Everyone is permitted to copy and distribute verbatim copies + * of this license document, but changing it is not allowed. + */ +using System; using System.Drawing; namespace UVtools.Core.Operations diff --git a/UVtools.Core/Operations/OperationPattern.cs b/UVtools.Core/Operations/OperationPattern.cs index 9332a7e..869ef24 100644 --- a/UVtools.Core/Operations/OperationPattern.cs +++ b/UVtools.Core/Operations/OperationPattern.cs @@ -1,4 +1,11 @@ -using System.Drawing; +/* + * 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.Drawing; namespace UVtools.Core.Operations { @@ -10,18 +17,20 @@ namespace UVtools.Core.Operations public uint ImageWidth { get; } public uint ImageHeight { get; } - public ushort MarginCol { get; set; } = 0; - public ushort MarginRow { get; set; } = 0; + public ushort MarginCol { get; set; } + public ushort MarginRow { get; set; } - public ushort MaxMarginCol => CalculateMarginCol(MaxCols); - public ushort MaxMarginRow => CalculateMarginRow(MaxRows); + public ushort MaxMarginCol { get; } + public ushort MaxMarginRow { get; } public ushort Cols { get; set; } = 1; public ushort Rows { get; set; } = 1; public ushort MaxCols { get; } public ushort MaxRows { get; } - + + public Size GetPatternVolume => new Size(Cols * SrcRoi.Width + (Cols - 1) * MarginCol, Rows * SrcRoi.Height + (Rows - 1) * MarginRow); + public OperationPattern(Rectangle srcRoi, uint imageWidth, uint imageHeight) { @@ -31,6 +40,9 @@ namespace UVtools.Core.Operations MaxCols = (ushort) (imageWidth / srcRoi.Width); MaxRows = (ushort) (imageHeight / srcRoi.Height); + + MaxMarginCol = CalculateMarginCol(MaxCols); + MaxMarginRow = CalculateMarginRow(MaxRows); } @@ -94,19 +106,19 @@ namespace UVtools.Core.Operations public ushort CalculateMarginCol(ushort cols) { + if (cols <= 1) return 0; return (ushort)((ImageWidth - SrcRoi.Width * cols) / cols); } public ushort CalculateMarginRow(ushort rows) { + if (rows <= 1) return 0; return (ushort)((ImageHeight - SrcRoi.Height * rows) / rows); } - public Size CalculatePatternVolume => new Size(Cols * SrcRoi.Width + Cols * MarginCol, Rows * SrcRoi.Height + Rows * MarginRow); - public Rectangle GetRoi(ushort col, ushort row) { - var patternVolume = CalculatePatternVolume; + var patternVolume = GetPatternVolume; return new Rectangle(new Point( (int) (col * SrcRoi.Width + col * MarginCol + (ImageWidth - patternVolume.Width) / 2), diff --git a/UVtools.Core/Operations/OperationProgress.cs b/UVtools.Core/Operations/OperationProgress.cs index 7c6ed73..a39d122 100644 --- a/UVtools.Core/Operations/OperationProgress.cs +++ b/UVtools.Core/Operations/OperationProgress.cs @@ -1,4 +1,11 @@ -using System; +/* + * GNU AFFERO GENERAL PUBLIC LICENSE + * Version 3, 19 November 2007 + * Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/> + * Everyone is permitted to copy and distribute verbatim copies + * of this license document, but changing it is not allowed. + */ +using System; using System.Threading; namespace UVtools.Core.Operations diff --git a/UVtools.Core/PixelEditor/PixelDrainHole.cs b/UVtools.Core/PixelEditor/PixelDrainHole.cs new file mode 100644 index 0000000..782579c --- /dev/null +++ b/UVtools.Core/PixelEditor/PixelDrainHole.cs @@ -0,0 +1,21 @@ +/* + * 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.Drawing; + +namespace UVtools.Core.PixelEditor +{ + public class PixelDrainHole : PixelOperation + { + public byte Diameter { get; } + + public PixelDrainHole(uint layerIndex, Point location, byte diameter) : base(PixelOperationType.DrainHole, layerIndex, location) + { + Diameter = diameter; + } + } +} diff --git a/UVtools.Core/PixelEditor/PixelDrawing.cs b/UVtools.Core/PixelEditor/PixelDrawing.cs new file mode 100644 index 0000000..c3ca7ec --- /dev/null +++ b/UVtools.Core/PixelEditor/PixelDrawing.cs @@ -0,0 +1,45 @@ +/* + * GNU AFFERO GENERAL PUBLIC LICENSE + * Version 3, 19 November 2007 + * Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/> + * Everyone is permitted to copy and distribute verbatim copies + * of this license document, but changing it is not allowed. + */ +using System; +using System.Drawing; + +namespace UVtools.Core.PixelEditor +{ + public class PixelDrawing : PixelOperation + { + public const byte MinRectangleBrush = 1; + public const byte MinCircleBrush = 7; + public enum BrushShapeType : byte + { + Rectangle = 0, + Circle + } + + public BrushShapeType BrushShape { get; } + + public ushort BrushSize { get; } + + public bool IsAdd { get; } + + public byte Color { get; } + + public Rectangle Rectangle { get; } + + public PixelDrawing(uint layerIndex, Point location, BrushShapeType brushShape, ushort brushSize, bool isAdd) : base(PixelOperationType.Drawing, layerIndex, location) + { + BrushShape = brushShape; + BrushSize = brushSize; + IsAdd = isAdd; + + Color = (byte) (isAdd ? 255 : 0); + + int shiftPos = brushSize / 2; + Rectangle = new Rectangle(Math.Max(0, location.X - shiftPos), Math.Max(0, location.Y - shiftPos), brushSize-1, brushSize-1); + } + } +} diff --git a/UVtools.Core/PixelEditor/PixelHistory.cs b/UVtools.Core/PixelEditor/PixelHistory.cs new file mode 100644 index 0000000..73f11ed --- /dev/null +++ b/UVtools.Core/PixelEditor/PixelHistory.cs @@ -0,0 +1,61 @@ +/* + * 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.Collections; +using System.Collections.Generic; +using System.Text; + +namespace UVtools.Core.PixelEditor +{ + public class PixelHistory : IEnumerable<PixelOperation> + { + public List<PixelOperation> Items { get; } = new List<PixelOperation>(); + + public int Count => Items.Count; + + #region Indexers + public PixelOperation this[uint index] => Items[(int) index]; + + public PixelOperation this[int index] => Items[index]; + + public PixelOperation this[long index] => Items[(int) index]; + + #endregion + + #region Numerators + public IEnumerator<PixelOperation> GetEnumerator() + { + return ((IEnumerable<PixelOperation>)Items).GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + #endregion + + #region Methods + + public void Add(PixelOperation item) => Items.Add(item); + public void Clear() => Items.Clear(); + + public bool Contains(PixelOperation operation) + { + for (int i = 0; i < Count; i++) + { + if (Items[i].Location == operation.Location && + Items[i].OperationType == operation.OperationType && + Items[i].LayerIndex == operation.LayerIndex) return true; + } + + return false; + } + + #endregion + + } +} diff --git a/UVtools.Core/PixelEditor/PixelOperation.cs b/UVtools.Core/PixelEditor/PixelOperation.cs new file mode 100644 index 0000000..21154d7 --- /dev/null +++ b/UVtools.Core/PixelEditor/PixelOperation.cs @@ -0,0 +1,34 @@ +/* + * 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.Drawing; + +namespace UVtools.Core.PixelEditor +{ + public class PixelOperation + { + public enum PixelOperationType : byte + { + Drawing, + Supports, + DrainHole, + } + + public PixelOperationType OperationType { get; } + public uint LayerIndex { get; } + + public Point Location { get; } + + + public PixelOperation(PixelOperationType operationType, uint layerIndex, Point location) + { + OperationType = operationType; + Location = location; + LayerIndex = layerIndex; + } + } +} diff --git a/UVtools.Core/PixelEditor/PixelSupport.cs b/UVtools.Core/PixelEditor/PixelSupport.cs new file mode 100644 index 0000000..86cb240 --- /dev/null +++ b/UVtools.Core/PixelEditor/PixelSupport.cs @@ -0,0 +1,27 @@ +/* + * 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.Drawing; + +namespace UVtools.Core.PixelEditor +{ + public class PixelSupport : PixelOperation + { + public byte TipDiameter { get; } + + public byte PillarDiameter { get; } + + public byte BaseDiameter { get; } + + public PixelSupport(uint layerIndex, Point location, byte tipDiameter, byte pillarDiameter, byte baseDiameter) : base(PixelOperationType.Supports, layerIndex, location) + { + TipDiameter = tipDiameter; + PillarDiameter = pillarDiameter; + BaseDiameter = baseDiameter; + } + } +} diff --git a/UVtools.Core/UVtools.Core.csproj b/UVtools.Core/UVtools.Core.csproj index 7fddd8e..517a003 100644 --- a/UVtools.Core/UVtools.Core.csproj +++ b/UVtools.Core/UVtools.Core.csproj @@ -10,19 +10,28 @@ <RepositoryUrl>https://github.com/sn4k3/UVtools</RepositoryUrl> <PackageProjectUrl>https://github.com/sn4k3/UVtools</PackageProjectUrl> <Description>MSLA/DLP, file analysis, repair, conversion and manipulation</Description> - <Version>0.6.1.1</Version> + <Version>0.6.2.0</Version> <Copyright>Copyright © 2020 PTRTECH</Copyright> <PackageIcon>UVtools.png</PackageIcon> + <Platforms>AnyCPU;x64</Platforms> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'"> <AllowUnsafeBlocks>true</AllowUnsafeBlocks> </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <AllowUnsafeBlocks>true</AllowUnsafeBlocks> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'"> <AllowUnsafeBlocks>true</AllowUnsafeBlocks> </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <AllowUnsafeBlocks>true</AllowUnsafeBlocks> + </PropertyGroup> + <ItemGroup> <None Include="..\LICENSE"> <Pack>True</Pack> diff --git a/UVtools.GUI/App.config b/UVtools.GUI/App.config index 6419ff5..1799304 100644 --- a/UVtools.GUI/App.config +++ b/UVtools.GUI/App.config @@ -52,7 +52,7 @@ <value>True</value> </setting> <setting name="StartMaximized" serializeAs="String"> - <value>False</value> + <value>True</value> </setting> <setting name="CheckForUpdatesOnStartup" serializeAs="String"> <value>True</value> @@ -138,6 +138,39 @@ <setting name="DefaultOpenFileExtension" serializeAs="String"> <value>0</value> </setting> + <setting name="PixelEditorAddPixelColor" serializeAs="String"> + <value>Green</value> + </setting> + <setting name="PixelEditorRemovePixelColor" serializeAs="String"> + <value>DarkRed</value> + </setting> + <setting name="PixelEditorSupportColor" serializeAs="String"> + <value>Cyan</value> + </setting> + <setting name="PixelEditorDrainHoleColor" serializeAs="String"> + <value>Purple</value> + </setting> + <setting name="FileSaveNamePreffix" serializeAs="String"> + <value /> + </setting> + <setting name="FileSaveNameSuffix" serializeAs="String"> + <value>_copy</value> + </setting> + <setting name="FileSavePromptOverwrite" serializeAs="String"> + <value>True</value> + </setting> + <setting name="FileOpenDefaultDirectory" serializeAs="String"> + <value /> + </setting> + <setting name="FileSaveDefaultDirectory" serializeAs="String"> + <value /> + </setting> + <setting name="FileConvertDefaultDirectory" serializeAs="String"> + <value /> + </setting> + <setting name="FileExtractDefaultDirectory" serializeAs="String"> + <value /> + </setting> </UVtools.GUI.Properties.Settings> </userSettings> </configuration> diff --git a/UVtools.GUI/Forms/FrmMutationPixelDimming.Designer.cs b/UVtools.GUI/Forms/FrmMutationPixelDimming.Designer.cs new file mode 100644 index 0000000..55114be --- /dev/null +++ b/UVtools.GUI/Forms/FrmMutationPixelDimming.Designer.cs @@ -0,0 +1,758 @@ +using UVtools.GUI.Controls; + +namespace UVtools.GUI.Forms +{ + partial class FrmMutationPixelDimming + { + /// <summary> + /// Required designer variable. + /// </summary> + private System.ComponentModel.IContainer components = null; + + /// <summary> + /// Clean up any resources being used. + /// </summary> + /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// <summary> + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// </summary> + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(FrmMutationPixelDimming)); + this.lbDescription = new System.Windows.Forms.Label(); + this.lbX = new System.Windows.Forms.Label(); + this.lbLayerRange = new System.Windows.Forms.Label(); + this.nmLayerRangeStart = new System.Windows.Forms.NumericUpDown(); + this.nmLayerRangeEnd = new System.Windows.Forms.NumericUpDown(); + this.lbLayerRangeTo = new System.Windows.Forms.Label(); + this.cmLayerRange = new System.Windows.Forms.ContextMenuStrip(this.components); + this.btnLayerRangeAllLayers = new System.Windows.Forms.ToolStripMenuItem(); + this.btnLayerRangeCurrentLayer = new System.Windows.Forms.ToolStripMenuItem(); + this.btnLayerRangeBottomLayers = new System.Windows.Forms.ToolStripMenuItem(); + this.btnLayerRangeNormalLayers = new System.Windows.Forms.ToolStripMenuItem(); + this.toolTip = new System.Windows.Forms.ToolTip(this.components); + this.label1 = new System.Windows.Forms.Label(); + this.label2 = new System.Windows.Forms.Label(); + this.label3 = new System.Windows.Forms.Label(); + this.label4 = new System.Windows.Forms.Label(); + this.label5 = new System.Windows.Forms.Label(); + this.label6 = new System.Windows.Forms.Label(); + this.label7 = new System.Windows.Forms.Label(); + this.btnCancel = new System.Windows.Forms.Button(); + this.btnMutate = new System.Windows.Forms.Button(); + this.nmBorderSize = new System.Windows.Forms.NumericUpDown(); + this.tbEvenPattern = new System.Windows.Forms.TextBox(); + this.nmPixelDimBrightness = new System.Windows.Forms.NumericUpDown(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.btnDimPatternWaves = new System.Windows.Forms.Button(); + this.btnPatternRandom = new System.Windows.Forms.Button(); + this.btnDimPatternSlashes = new System.Windows.Forms.Button(); + this.btnDimPatternHearts = new System.Windows.Forms.Button(); + this.btnDimPatternRhombus = new System.Windows.Forms.Button(); + this.btnDimPatternPyramid = new System.Windows.Forms.Button(); + this.btnDimPatternCrosses = new System.Windows.Forms.Button(); + this.btnDimPatternSparse = new System.Windows.Forms.Button(); + this.btnDimPatternChessBoard = new System.Windows.Forms.Button(); + this.tbOddPattern = new System.Windows.Forms.TextBox(); + this.groupBox2 = new System.Windows.Forms.GroupBox(); + this.label8 = new System.Windows.Forms.Label(); + this.btnInfillPatternWaves = new System.Windows.Forms.Button(); + this.btnInfillPatternSquareGrid = new System.Windows.Forms.Button(); + this.btnInfillPatternRectilinear = new System.Windows.Forms.Button(); + this.nmInfillThickness = new System.Windows.Forms.NumericUpDown(); + this.label9 = new System.Windows.Forms.Label(); + this.label10 = new System.Windows.Forms.Label(); + this.label11 = new System.Windows.Forms.Label(); + this.nmInfillSpacing = new System.Windows.Forms.NumericUpDown(); + this.label12 = new System.Windows.Forms.Label(); + this.label13 = new System.Windows.Forms.Label(); + this.btnLayerRangeSelect = new UVtools.GUI.Controls.SplitButton(); + ((System.ComponentModel.ISupportInitialize)(this.nmLayerRangeStart)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.nmLayerRangeEnd)).BeginInit(); + this.cmLayerRange.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.nmBorderSize)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.nmPixelDimBrightness)).BeginInit(); + this.groupBox1.SuspendLayout(); + this.groupBox2.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.nmInfillThickness)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.nmInfillSpacing)).BeginInit(); + this.SuspendLayout(); + // + // lbDescription + // + this.lbDescription.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.lbDescription.Location = new System.Drawing.Point(13, 14); + this.lbDescription.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.lbDescription.Name = "lbDescription"; + this.lbDescription.Size = new System.Drawing.Size(584, 128); + this.lbDescription.TabIndex = 0; + this.lbDescription.Text = "Description"; + // + // lbX + // + this.lbX.AutoSize = true; + this.lbX.Location = new System.Drawing.Point(17, 190); + this.lbX.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.lbX.Name = "lbX"; + this.lbX.Size = new System.Drawing.Size(93, 20); + this.lbX.TabIndex = 3; + this.lbX.Text = "Border size:"; + this.toolTip.SetToolTip(this.lbX, resources.GetString("lbX.ToolTip")); + // + // lbLayerRange + // + this.lbLayerRange.AutoSize = true; + this.lbLayerRange.Location = new System.Drawing.Point(13, 150); + this.lbLayerRange.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.lbLayerRange.Name = "lbLayerRange"; + this.lbLayerRange.Size = new System.Drawing.Size(97, 20); + this.lbLayerRange.TabIndex = 9; + this.lbLayerRange.Text = "Layer range:"; + this.toolTip.SetToolTip(this.lbLayerRange, resources.GetString("lbLayerRange.ToolTip")); + // + // nmLayerRangeStart + // + this.nmLayerRangeStart.Location = new System.Drawing.Point(118, 147); + this.nmLayerRangeStart.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.nmLayerRangeStart.Maximum = new decimal(new int[] { + 100000, + 0, + 0, + 0}); + this.nmLayerRangeStart.Name = "nmLayerRangeStart"; + this.nmLayerRangeStart.Size = new System.Drawing.Size(120, 26); + this.nmLayerRangeStart.TabIndex = 0; + // + // nmLayerRangeEnd + // + this.nmLayerRangeEnd.Location = new System.Drawing.Point(314, 147); + this.nmLayerRangeEnd.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.nmLayerRangeEnd.Maximum = new decimal(new int[] { + 100000, + 0, + 0, + 0}); + this.nmLayerRangeEnd.Name = "nmLayerRangeEnd"; + this.nmLayerRangeEnd.Size = new System.Drawing.Size(120, 26); + this.nmLayerRangeEnd.TabIndex = 1; + // + // lbLayerRangeTo + // + this.lbLayerRangeTo.AutoSize = true; + this.lbLayerRangeTo.Location = new System.Drawing.Point(275, 150); + this.lbLayerRangeTo.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.lbLayerRangeTo.Name = "lbLayerRangeTo"; + this.lbLayerRangeTo.Size = new System.Drawing.Size(31, 20); + this.lbLayerRangeTo.TabIndex = 12; + this.lbLayerRangeTo.Text = "To:"; + // + // cmLayerRange + // + this.cmLayerRange.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.btnLayerRangeAllLayers, + this.btnLayerRangeCurrentLayer, + this.btnLayerRangeBottomLayers, + this.btnLayerRangeNormalLayers}); + this.cmLayerRange.Name = "cmLayerRange"; + this.cmLayerRange.Size = new System.Drawing.Size(226, 92); + // + // btnLayerRangeAllLayers + // + this.btnLayerRangeAllLayers.Name = "btnLayerRangeAllLayers"; + this.btnLayerRangeAllLayers.ShortcutKeys = ((System.Windows.Forms.Keys)(((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Shift) + | System.Windows.Forms.Keys.A))); + this.btnLayerRangeAllLayers.Size = new System.Drawing.Size(225, 22); + this.btnLayerRangeAllLayers.Text = "&All Layers"; + this.btnLayerRangeAllLayers.Click += new System.EventHandler(this.ItemClicked); + // + // btnLayerRangeCurrentLayer + // + this.btnLayerRangeCurrentLayer.Name = "btnLayerRangeCurrentLayer"; + this.btnLayerRangeCurrentLayer.ShortcutKeys = ((System.Windows.Forms.Keys)(((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Shift) + | System.Windows.Forms.Keys.C))); + this.btnLayerRangeCurrentLayer.Size = new System.Drawing.Size(225, 22); + this.btnLayerRangeCurrentLayer.Text = "&Current Layer"; + this.btnLayerRangeCurrentLayer.Click += new System.EventHandler(this.ItemClicked); + // + // btnLayerRangeBottomLayers + // + this.btnLayerRangeBottomLayers.Name = "btnLayerRangeBottomLayers"; + this.btnLayerRangeBottomLayers.ShortcutKeys = ((System.Windows.Forms.Keys)(((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Shift) + | System.Windows.Forms.Keys.B))); + this.btnLayerRangeBottomLayers.Size = new System.Drawing.Size(225, 22); + this.btnLayerRangeBottomLayers.Text = "&Bottom Layers"; + this.btnLayerRangeBottomLayers.Click += new System.EventHandler(this.ItemClicked); + // + // btnLayerRangeNormalLayers + // + this.btnLayerRangeNormalLayers.Name = "btnLayerRangeNormalLayers"; + this.btnLayerRangeNormalLayers.ShortcutKeys = ((System.Windows.Forms.Keys)(((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Shift) + | System.Windows.Forms.Keys.N))); + this.btnLayerRangeNormalLayers.Size = new System.Drawing.Size(225, 22); + this.btnLayerRangeNormalLayers.Text = "&Normal Layers"; + this.btnLayerRangeNormalLayers.Click += new System.EventHandler(this.ItemClicked); + // + // toolTip + // + this.toolTip.AutoPopDelay = 32767; + this.toolTip.InitialDelay = 500; + this.toolTip.IsBalloon = true; + this.toolTip.ReshowDelay = 100; + this.toolTip.ToolTipIcon = System.Windows.Forms.ToolTipIcon.Info; + this.toolTip.ToolTipTitle = "Information"; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(246, 190); + this.label1.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(25, 20); + this.label1.TabIndex = 16; + this.label1.Text = "px"; + this.toolTip.SetToolTip(this.label1, resources.GetString("label1.ToolTip")); + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(17, 243); + this.label2.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(94, 80); + this.label2.TabIndex = 18; + this.label2.Text = "Even Layer\r\nPattern:\r\n0 = Black\r\n255 = White"; + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point(7, 94); + this.label3.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(65, 20); + this.label3.TabIndex = 19; + this.label3.Text = "Pattern:"; + // + // label4 + // + this.label4.AutoSize = true; + this.label4.Location = new System.Drawing.Point(7, 34); + this.label4.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(89, 20); + this.label4.TabIndex = 21; + this.label4.Text = "Brightness:"; + // + // label5 + // + this.label5.AutoSize = true; + this.label5.Location = new System.Drawing.Point(17, 363); + this.label5.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label5.Name = "label5"; + this.label5.Size = new System.Drawing.Size(94, 100); + this.label5.TabIndex = 24; + this.label5.Text = "Odd Layer\r\nPattern:\r\n0 = Black\r\n255 = White\r\n(Optional)"; + // + // label6 + // + this.label6.AutoSize = true; + this.label6.Location = new System.Drawing.Point(19, 478); + this.label6.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label6.Name = "label6"; + this.label6.Size = new System.Drawing.Size(548, 20); + this.label6.TabIndex = 25; + this.label6.Text = "(Leave this field empty to use only the even layer pattern for the layers range)"; + this.toolTip.SetToolTip(this.label6, resources.GetString("label6.ToolTip")); + // + // label7 + // + this.label7.AutoSize = true; + this.label7.Location = new System.Drawing.Point(233, 34); + this.label7.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label7.Name = "label7"; + this.label7.Size = new System.Drawing.Size(60, 20); + this.label7.TabIndex = 30; + this.label7.Text = "(0-254)"; + // + // btnCancel + // + this.btnCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); + this.btnCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.btnCancel.Image = global::UVtools.GUI.Properties.Resources.Cancel_24x24; + this.btnCancel.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft; + this.btnCancel.Location = new System.Drawing.Point(434, 854); + this.btnCancel.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.btnCancel.Name = "btnCancel"; + this.btnCancel.Size = new System.Drawing.Size(150, 48); + this.btnCancel.TabIndex = 6; + this.btnCancel.Text = "&Cancel"; + this.btnCancel.TextAlign = System.Drawing.ContentAlignment.MiddleRight; + this.btnCancel.UseVisualStyleBackColor = true; + this.btnCancel.Click += new System.EventHandler(this.ItemClicked); + // + // btnMutate + // + this.btnMutate.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); + this.btnMutate.Image = global::UVtools.GUI.Properties.Resources.Ok_24x24; + this.btnMutate.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft; + this.btnMutate.Location = new System.Drawing.Point(276, 854); + this.btnMutate.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.btnMutate.Name = "btnMutate"; + this.btnMutate.Size = new System.Drawing.Size(150, 48); + this.btnMutate.TabIndex = 5; + this.btnMutate.Text = "&Dim"; + this.btnMutate.TextAlign = System.Drawing.ContentAlignment.MiddleRight; + this.btnMutate.UseVisualStyleBackColor = true; + this.btnMutate.Click += new System.EventHandler(this.ItemClicked); + // + // nmBorderSize + // + this.nmBorderSize.Location = new System.Drawing.Point(118, 187); + this.nmBorderSize.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.nmBorderSize.Maximum = new decimal(new int[] { + 1000, + 0, + 0, + 0}); + this.nmBorderSize.Name = "nmBorderSize"; + this.nmBorderSize.Size = new System.Drawing.Size(120, 26); + this.nmBorderSize.TabIndex = 3; + this.nmBorderSize.Value = new decimal(new int[] { + 5, + 0, + 0, + 0}); + // + // tbEvenPattern + // + this.tbEvenPattern.Location = new System.Drawing.Point(118, 221); + this.tbEvenPattern.Multiline = true; + this.tbEvenPattern.Name = "tbEvenPattern"; + this.tbEvenPattern.ScrollBars = System.Windows.Forms.ScrollBars.Both; + this.tbEvenPattern.Size = new System.Drawing.Size(469, 124); + this.tbEvenPattern.TabIndex = 17; + this.tbEvenPattern.Text = "127 255 255 255\r\n255 255 127 255"; + // + // nmPixelDimBrightness + // + this.nmPixelDimBrightness.Location = new System.Drawing.Point(112, 31); + this.nmPixelDimBrightness.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.nmPixelDimBrightness.Maximum = new decimal(new int[] { + 254, + 0, + 0, + 0}); + this.nmPixelDimBrightness.Name = "nmPixelDimBrightness"; + this.nmPixelDimBrightness.Size = new System.Drawing.Size(113, 26); + this.nmPixelDimBrightness.TabIndex = 20; + this.nmPixelDimBrightness.Value = new decimal(new int[] { + 127, + 0, + 0, + 0}); + // + // groupBox1 + // + this.groupBox1.Controls.Add(this.label7); + this.groupBox1.Controls.Add(this.btnDimPatternWaves); + this.groupBox1.Controls.Add(this.btnPatternRandom); + this.groupBox1.Controls.Add(this.btnDimPatternSlashes); + this.groupBox1.Controls.Add(this.btnDimPatternHearts); + this.groupBox1.Controls.Add(this.btnDimPatternRhombus); + this.groupBox1.Controls.Add(this.btnDimPatternPyramid); + this.groupBox1.Controls.Add(this.btnDimPatternCrosses); + this.groupBox1.Controls.Add(this.btnDimPatternSparse); + this.groupBox1.Controls.Add(this.btnDimPatternChessBoard); + this.groupBox1.Controls.Add(this.nmPixelDimBrightness); + this.groupBox1.Controls.Add(this.label3); + this.groupBox1.Controls.Add(this.label4); + this.groupBox1.Location = new System.Drawing.Point(12, 517); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(575, 162); + this.groupBox1.TabIndex = 22; + this.groupBox1.TabStop = false; + this.groupBox1.Text = "Pixel dimming generator"; + // + // btnDimPatternWaves + // + this.btnDimPatternWaves.Location = new System.Drawing.Point(232, 106); + this.btnDimPatternWaves.Name = "btnDimPatternWaves"; + this.btnDimPatternWaves.Size = new System.Drawing.Size(94, 35); + this.btnDimPatternWaves.TabIndex = 29; + this.btnDimPatternWaves.Text = "Waves"; + this.btnDimPatternWaves.UseVisualStyleBackColor = true; + this.btnDimPatternWaves.Click += new System.EventHandler(this.ItemClicked); + // + // btnPatternRandom + // + this.btnPatternRandom.Location = new System.Drawing.Point(6, 121); + this.btnPatternRandom.Name = "btnPatternRandom"; + this.btnPatternRandom.Size = new System.Drawing.Size(94, 35); + this.btnPatternRandom.TabIndex = 29; + this.btnPatternRandom.Text = "Random"; + this.btnPatternRandom.UseVisualStyleBackColor = true; + this.btnPatternRandom.Visible = false; + this.btnPatternRandom.Click += new System.EventHandler(this.ItemClicked); + // + // btnDimPatternSlashes + // + this.btnDimPatternSlashes.Location = new System.Drawing.Point(332, 106); + this.btnDimPatternSlashes.Name = "btnDimPatternSlashes"; + this.btnDimPatternSlashes.Size = new System.Drawing.Size(94, 35); + this.btnDimPatternSlashes.TabIndex = 28; + this.btnDimPatternSlashes.Text = "Slashes"; + this.btnDimPatternSlashes.UseVisualStyleBackColor = true; + this.btnDimPatternSlashes.Click += new System.EventHandler(this.ItemClicked); + // + // btnDimPatternHearts + // + this.btnDimPatternHearts.Location = new System.Drawing.Point(432, 106); + this.btnDimPatternHearts.Name = "btnDimPatternHearts"; + this.btnDimPatternHearts.Size = new System.Drawing.Size(94, 35); + this.btnDimPatternHearts.TabIndex = 27; + this.btnDimPatternHearts.Text = "Hearts"; + this.btnDimPatternHearts.UseVisualStyleBackColor = true; + this.btnDimPatternHearts.Click += new System.EventHandler(this.ItemClicked); + // + // btnDimPatternRhombus + // + this.btnDimPatternRhombus.Location = new System.Drawing.Point(112, 106); + this.btnDimPatternRhombus.Name = "btnDimPatternRhombus"; + this.btnDimPatternRhombus.Size = new System.Drawing.Size(113, 35); + this.btnDimPatternRhombus.TabIndex = 26; + this.btnDimPatternRhombus.Text = "Rhombus"; + this.btnDimPatternRhombus.UseVisualStyleBackColor = true; + this.btnDimPatternRhombus.Click += new System.EventHandler(this.ItemClicked); + // + // btnDimPatternPyramid + // + this.btnDimPatternPyramid.Location = new System.Drawing.Point(432, 65); + this.btnDimPatternPyramid.Name = "btnDimPatternPyramid"; + this.btnDimPatternPyramid.Size = new System.Drawing.Size(94, 35); + this.btnDimPatternPyramid.TabIndex = 25; + this.btnDimPatternPyramid.Text = "Pyramid"; + this.btnDimPatternPyramid.UseVisualStyleBackColor = true; + this.btnDimPatternPyramid.Click += new System.EventHandler(this.ItemClicked); + // + // btnDimPatternCrosses + // + this.btnDimPatternCrosses.Location = new System.Drawing.Point(332, 65); + this.btnDimPatternCrosses.Name = "btnDimPatternCrosses"; + this.btnDimPatternCrosses.Size = new System.Drawing.Size(94, 35); + this.btnDimPatternCrosses.TabIndex = 24; + this.btnDimPatternCrosses.Text = "Crosses"; + this.btnDimPatternCrosses.UseVisualStyleBackColor = true; + this.btnDimPatternCrosses.Click += new System.EventHandler(this.ItemClicked); + // + // btnDimPatternSparse + // + this.btnDimPatternSparse.Location = new System.Drawing.Point(232, 65); + this.btnDimPatternSparse.Name = "btnDimPatternSparse"; + this.btnDimPatternSparse.Size = new System.Drawing.Size(94, 35); + this.btnDimPatternSparse.TabIndex = 23; + this.btnDimPatternSparse.Text = "Sparse"; + this.btnDimPatternSparse.UseVisualStyleBackColor = true; + this.btnDimPatternSparse.Click += new System.EventHandler(this.ItemClicked); + // + // btnDimPatternChessBoard + // + this.btnDimPatternChessBoard.Location = new System.Drawing.Point(112, 65); + this.btnDimPatternChessBoard.Name = "btnDimPatternChessBoard"; + this.btnDimPatternChessBoard.Size = new System.Drawing.Size(114, 35); + this.btnDimPatternChessBoard.TabIndex = 22; + this.btnDimPatternChessBoard.Text = "Chess Board"; + this.btnDimPatternChessBoard.UseVisualStyleBackColor = true; + this.btnDimPatternChessBoard.Click += new System.EventHandler(this.ItemClicked); + // + // tbOddPattern + // + this.tbOddPattern.Location = new System.Drawing.Point(118, 351); + this.tbOddPattern.Multiline = true; + this.tbOddPattern.Name = "tbOddPattern"; + this.tbOddPattern.ScrollBars = System.Windows.Forms.ScrollBars.Both; + this.tbOddPattern.Size = new System.Drawing.Size(469, 124); + this.tbOddPattern.TabIndex = 23; + this.tbOddPattern.Text = "255 255 127 255\r\n127 255 255 255"; + // + // groupBox2 + // + this.groupBox2.Controls.Add(this.label13); + this.groupBox2.Controls.Add(this.label11); + this.groupBox2.Controls.Add(this.nmInfillSpacing); + this.groupBox2.Controls.Add(this.label12); + this.groupBox2.Controls.Add(this.label8); + this.groupBox2.Controls.Add(this.btnInfillPatternWaves); + this.groupBox2.Controls.Add(this.btnInfillPatternSquareGrid); + this.groupBox2.Controls.Add(this.btnInfillPatternRectilinear); + this.groupBox2.Controls.Add(this.nmInfillThickness); + this.groupBox2.Controls.Add(this.label9); + this.groupBox2.Controls.Add(this.label10); + this.groupBox2.Location = new System.Drawing.Point(12, 685); + this.groupBox2.Name = "groupBox2"; + this.groupBox2.Size = new System.Drawing.Size(575, 160); + this.groupBox2.TabIndex = 26; + this.groupBox2.TabStop = false; + this.groupBox2.Text = "Infill generator"; + // + // label8 + // + this.label8.AutoSize = true; + this.label8.Location = new System.Drawing.Point(233, 76); + this.label8.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label8.Name = "label8"; + this.label8.Size = new System.Drawing.Size(25, 20); + this.label8.TabIndex = 30; + this.label8.Text = "px"; + // + // btnInfillPatternWaves + // + this.btnInfillPatternWaves.Location = new System.Drawing.Point(351, 107); + this.btnInfillPatternWaves.Name = "btnInfillPatternWaves"; + this.btnInfillPatternWaves.Size = new System.Drawing.Size(94, 35); + this.btnInfillPatternWaves.TabIndex = 28; + this.btnInfillPatternWaves.Text = "Waves"; + this.btnInfillPatternWaves.UseVisualStyleBackColor = true; + this.btnInfillPatternWaves.Click += new System.EventHandler(this.ItemClicked); + // + // btnInfillPatternSquareGrid + // + this.btnInfillPatternSquareGrid.Location = new System.Drawing.Point(232, 107); + this.btnInfillPatternSquareGrid.Name = "btnInfillPatternSquareGrid"; + this.btnInfillPatternSquareGrid.Size = new System.Drawing.Size(113, 35); + this.btnInfillPatternSquareGrid.TabIndex = 26; + this.btnInfillPatternSquareGrid.Text = "Square Grid"; + this.btnInfillPatternSquareGrid.UseVisualStyleBackColor = true; + this.btnInfillPatternSquareGrid.Click += new System.EventHandler(this.ItemClicked); + // + // btnInfillPatternRectilinear + // + this.btnInfillPatternRectilinear.Location = new System.Drawing.Point(112, 107); + this.btnInfillPatternRectilinear.Name = "btnInfillPatternRectilinear"; + this.btnInfillPatternRectilinear.Size = new System.Drawing.Size(114, 35); + this.btnInfillPatternRectilinear.TabIndex = 22; + this.btnInfillPatternRectilinear.Text = "Rectilinear"; + this.btnInfillPatternRectilinear.UseVisualStyleBackColor = true; + this.btnInfillPatternRectilinear.Click += new System.EventHandler(this.ItemClicked); + // + // nmInfillThickness + // + this.nmInfillThickness.Location = new System.Drawing.Point(112, 73); + this.nmInfillThickness.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.nmInfillThickness.Maximum = new decimal(new int[] { + 10000, + 0, + 0, + 0}); + this.nmInfillThickness.Minimum = new decimal(new int[] { + 5, + 0, + 0, + 0}); + this.nmInfillThickness.Name = "nmInfillThickness"; + this.nmInfillThickness.Size = new System.Drawing.Size(113, 26); + this.nmInfillThickness.TabIndex = 20; + this.nmInfillThickness.Value = new decimal(new int[] { + 10, + 0, + 0, + 0}); + // + // label9 + // + this.label9.AutoSize = true; + this.label9.Location = new System.Drawing.Point(7, 114); + this.label9.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label9.Name = "label9"; + this.label9.Size = new System.Drawing.Size(65, 20); + this.label9.TabIndex = 19; + this.label9.Text = "Pattern:"; + // + // label10 + // + this.label10.AutoSize = true; + this.label10.Location = new System.Drawing.Point(7, 76); + this.label10.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label10.Name = "label10"; + this.label10.Size = new System.Drawing.Size(84, 20); + this.label10.TabIndex = 21; + this.label10.Text = "Thickness:"; + // + // label11 + // + this.label11.AutoSize = true; + this.label11.Location = new System.Drawing.Point(543, 76); + this.label11.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label11.Name = "label11"; + this.label11.Size = new System.Drawing.Size(25, 20); + this.label11.TabIndex = 33; + this.label11.Text = "px"; + // + // nmInfillSpacing + // + this.nmInfillSpacing.Location = new System.Drawing.Point(422, 73); + this.nmInfillSpacing.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.nmInfillSpacing.Maximum = new decimal(new int[] { + 10000, + 0, + 0, + 0}); + this.nmInfillSpacing.Minimum = new decimal(new int[] { + 5, + 0, + 0, + 0}); + this.nmInfillSpacing.Name = "nmInfillSpacing"; + this.nmInfillSpacing.Size = new System.Drawing.Size(113, 26); + this.nmInfillSpacing.TabIndex = 31; + this.nmInfillSpacing.Value = new decimal(new int[] { + 20, + 0, + 0, + 0}); + // + // label12 + // + this.label12.AutoSize = true; + this.label12.Location = new System.Drawing.Point(343, 76); + this.label12.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label12.Name = "label12"; + this.label12.Size = new System.Drawing.Size(71, 20); + this.label12.TabIndex = 32; + this.label12.Text = "Spacing:"; + // + // label13 + // + this.label13.Location = new System.Drawing.Point(7, 22); + this.label13.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label13.Name = "label13"; + this.label13.Size = new System.Drawing.Size(561, 46); + this.label13.TabIndex = 34; + this.label13.Text = "The infill function can create a ton of resin traps, use only this tool if you kn" + + "ow what are you doing or for specific parts. You always need to ensure the drain" + + "s."; + // + // btnLayerRangeSelect + // + this.btnLayerRangeSelect.Location = new System.Drawing.Point(446, 146); + this.btnLayerRangeSelect.Menu = this.cmLayerRange; + this.btnLayerRangeSelect.Name = "btnLayerRangeSelect"; + this.btnLayerRangeSelect.Size = new System.Drawing.Size(141, 26); + this.btnLayerRangeSelect.TabIndex = 2; + this.btnLayerRangeSelect.Text = "Select"; + this.btnLayerRangeSelect.UseVisualStyleBackColor = true; + // + // FrmMutationPixelDimming + // + this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 20F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.CancelButton = this.btnCancel; + this.ClientSize = new System.Drawing.Size(599, 916); + this.Controls.Add(this.groupBox2); + this.Controls.Add(this.label6); + this.Controls.Add(this.label5); + this.Controls.Add(this.tbOddPattern); + this.Controls.Add(this.groupBox1); + this.Controls.Add(this.label2); + this.Controls.Add(this.tbEvenPattern); + this.Controls.Add(this.label1); + this.Controls.Add(this.btnLayerRangeSelect); + this.Controls.Add(this.lbLayerRangeTo); + this.Controls.Add(this.nmLayerRangeEnd); + this.Controls.Add(this.nmLayerRangeStart); + this.Controls.Add(this.lbLayerRange); + this.Controls.Add(this.btnMutate); + this.Controls.Add(this.btnCancel); + this.Controls.Add(this.nmBorderSize); + this.Controls.Add(this.lbX); + this.Controls.Add(this.lbDescription); + this.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + this.KeyPreview = true; + this.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "FrmMutationPixelDimming"; + this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "Form1"; + this.TopMost = true; + ((System.ComponentModel.ISupportInitialize)(this.nmLayerRangeStart)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.nmLayerRangeEnd)).EndInit(); + this.cmLayerRange.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.nmBorderSize)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.nmPixelDimBrightness)).EndInit(); + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + this.groupBox2.ResumeLayout(false); + this.groupBox2.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.nmInfillThickness)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.nmInfillSpacing)).EndInit(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Label lbDescription; + private System.Windows.Forms.Label lbX; + private System.Windows.Forms.Button btnCancel; + private System.Windows.Forms.Button btnMutate; + private System.Windows.Forms.Label lbLayerRange; + private System.Windows.Forms.NumericUpDown nmLayerRangeStart; + private System.Windows.Forms.NumericUpDown nmLayerRangeEnd; + private System.Windows.Forms.Label lbLayerRangeTo; + private Controls.SplitButton btnLayerRangeSelect; + private System.Windows.Forms.ContextMenuStrip cmLayerRange; + private System.Windows.Forms.ToolStripMenuItem btnLayerRangeAllLayers; + private System.Windows.Forms.ToolStripMenuItem btnLayerRangeCurrentLayer; + private System.Windows.Forms.ToolStripMenuItem btnLayerRangeBottomLayers; + private System.Windows.Forms.ToolStripMenuItem btnLayerRangeNormalLayers; + private System.Windows.Forms.ToolTip toolTip; + private System.Windows.Forms.NumericUpDown nmBorderSize; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.TextBox tbEvenPattern; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.NumericUpDown nmPixelDimBrightness; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.Button btnDimPatternChessBoard; + private System.Windows.Forms.Button btnDimPatternSparse; + private System.Windows.Forms.Button btnDimPatternPyramid; + private System.Windows.Forms.Button btnDimPatternCrosses; + private System.Windows.Forms.Button btnDimPatternRhombus; + private System.Windows.Forms.Button btnDimPatternHearts; + private System.Windows.Forms.Button btnDimPatternSlashes; + private System.Windows.Forms.Button btnPatternRandom; + private System.Windows.Forms.Button btnDimPatternWaves; + private System.Windows.Forms.Label label5; + private System.Windows.Forms.TextBox tbOddPattern; + private System.Windows.Forms.Label label6; + private System.Windows.Forms.Label label7; + private System.Windows.Forms.GroupBox groupBox2; + private System.Windows.Forms.Label label8; + private System.Windows.Forms.Button btnInfillPatternWaves; + private System.Windows.Forms.Button btnInfillPatternSquareGrid; + private System.Windows.Forms.Button btnInfillPatternRectilinear; + private System.Windows.Forms.NumericUpDown nmInfillThickness; + private System.Windows.Forms.Label label9; + private System.Windows.Forms.Label label10; + private System.Windows.Forms.Label label11; + private System.Windows.Forms.NumericUpDown nmInfillSpacing; + private System.Windows.Forms.Label label12; + private System.Windows.Forms.Label label13; + } +}
\ No newline at end of file diff --git a/UVtools.GUI/Forms/FrmMutationPixelDimming.cs b/UVtools.GUI/Forms/FrmMutationPixelDimming.cs new file mode 100644 index 0000000..1a9cc6e --- /dev/null +++ b/UVtools.GUI/Forms/FrmMutationPixelDimming.cs @@ -0,0 +1,474 @@ +/* + * GNU AFFERO GENERAL PUBLIC LICENSE + * Version 3, 19 November 2007 + * Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/> + * Everyone is permitted to copy and distribute verbatim copies + * of this license document, but changing it is not allowed. + */ + +using System; +using System.Globalization; +using System.Text; +using System.Windows.Forms; +using Emgu.CV; +using UVtools.Core.Extensions; + +namespace UVtools.GUI.Forms +{ + public partial class FrmMutationPixelDimming : Form + { + class MatrixTexbox + { + public Matrix<byte> Pattern; + public TextBox Textbox; + + public MatrixTexbox(Matrix<byte> pattern, TextBox textbox) + { + Pattern = pattern; + Textbox = textbox; + } + } + #region Properties + + private Mutation Mutation { get; } + + public uint LayerRangeStart + { + get => (uint) nmLayerRangeStart.Value; + set => nmLayerRangeStart.Value = value; + } + + public uint LayerRangeEnd + { + get => (uint)Math.Min(nmLayerRangeEnd.Value, Program.SlicerFile.LayerCount-1); + set => nmLayerRangeEnd.Value = value; + } + + public uint BorderSize + { + get => (uint)nmBorderSize.Value; + set => nmBorderSize.Value = value; + } + + public Matrix<byte> EvenPattern { get; private set; } + public Matrix<byte> OddPattern { get; private set; } + + + #endregion + + #region Constructors + public FrmMutationPixelDimming(Mutation mutation) + { + InitializeComponent(); + Mutation = mutation; + DialogResult = DialogResult.Cancel; + + nmBorderSize.Select(); + + Text = $"Mutate: {mutation.MenuName}"; + lbDescription.Text = Mutation.Description; + + nmLayerRangeEnd.Value = Program.SlicerFile.LayerCount-1; + + ItemClicked(btnDimPatternChessBoard, null); + } + #endregion + + #region Overrides + protected override void OnKeyUp(KeyEventArgs e) + { + base.OnKeyUp(e); + if (e.KeyCode == Keys.Enter) + { + if (tbEvenPattern.ContainsFocus || tbOddPattern.ContainsFocus) return; + btnMutate.PerformClick(); + e.Handled = true; + return; + } + + if ((ModifierKeys & Keys.Shift) == Keys.Shift && (ModifierKeys & Keys.Control) == Keys.Control) + { + if (e.KeyCode == Keys.A) + { + btnLayerRangeAllLayers.PerformClick(); + e.Handled = true; + return; + } + + if (e.KeyCode == Keys.C) + { + btnLayerRangeCurrentLayer.PerformClick(); + e.Handled = true; + return; + } + + if (e.KeyCode == Keys.B) + { + btnLayerRangeBottomLayers.PerformClick(); + e.Handled = true; + return; + } + + if (e.KeyCode == Keys.N) + { + btnLayerRangeNormalLayers.PerformClick(); + e.Handled = true; + return; + } + } + } + + #endregion + + #region Events + private void ItemClicked(object sender, EventArgs e) + { + if (ReferenceEquals(sender, btnLayerRangeAllLayers)) + { + nmLayerRangeStart.Value = 0; + nmLayerRangeEnd.Value = Program.SlicerFile.LayerCount-1; + return; + } + + if (ReferenceEquals(sender, btnLayerRangeCurrentLayer)) + { + nmLayerRangeStart.Value = Program.FrmMain.ActualLayer; + nmLayerRangeEnd.Value = Program.FrmMain.ActualLayer; + return; + } + + if (ReferenceEquals(sender, btnLayerRangeBottomLayers)) + { + nmLayerRangeStart.Value = 0; + nmLayerRangeEnd.Value = Program.SlicerFile.InitialLayerCount-1; + return; + } + + if (ReferenceEquals(sender, btnLayerRangeNormalLayers)) + { + nmLayerRangeStart.Value = Program.SlicerFile.InitialLayerCount - 1; + nmLayerRangeEnd.Value = Program.SlicerFile.LayerCount - 1; + return; + } + + if (ReferenceEquals(sender, btnDimPatternChessBoard)) + { + tbEvenPattern.Text = string.Format( + "255 {0}{1}" + + "{0} 255" + , nmPixelDimBrightness.Value, Environment.NewLine); + + tbOddPattern.Text = string.Format( + "{0} 255{1}" + + "255 {0}" + , nmPixelDimBrightness.Value, Environment.NewLine); + return; + } + + if (ReferenceEquals(sender, btnDimPatternSparse)) + { + + tbEvenPattern.Text = string.Format( + "{0} 255 255 255{1}" + + "255 255 {0} 255" + , nmPixelDimBrightness.Value, Environment.NewLine); + + tbOddPattern.Text = string.Format( + "255 255 {0} 255{1}" + + "{0} 255 255 255" + , nmPixelDimBrightness.Value, Environment.NewLine); + return; + } + + if (ReferenceEquals(sender, btnDimPatternCrosses)) + { + tbEvenPattern.Text = string.Format( + "{0} 255 {0} 255{1}" + + "255 {0} 255 255{1}" + + "{0} 255 {0} 255{1}" + + "255 255 255 255" + , nmPixelDimBrightness.Value, Environment.NewLine); + + tbOddPattern.Text = string.Format( + "255 255 255 255{1}" + + "{0} 255 {0} 255{1}" + + "255 {0} 255 255{1}" + + "{0} 255 {0} 255" + , nmPixelDimBrightness.Value, Environment.NewLine); + + return; + } + + if (ReferenceEquals(sender, btnDimPatternRhombus)) + { + + tbEvenPattern.Text = string.Format( + "255 {0} 255 255{1}" + + "{0} 255 {0} 255{1}" + + "255 {0} 255 255{1}" + + "255 255 255 255" + , nmPixelDimBrightness.Value, Environment.NewLine); + + tbOddPattern.Text = string.Format( + "255 255 255 255{1}" + + "255 {0} 255 255{1}" + + "{0} 255 {0} 255{1}" + + "255 {0} 255 255" + , nmPixelDimBrightness.Value, Environment.NewLine); + return; + } + + if (ReferenceEquals(sender, btnDimPatternPyramid)) + { + + tbEvenPattern.Text = string.Format( + "255 255 {0} 255 255 255{1}" + + "255 {0} 255 {0} 255 255{1}" + + "{0} 255 {0} 255 {0} 255{1}" + + "255 255 255 255 255 255" + , nmPixelDimBrightness.Value, Environment.NewLine); + + tbOddPattern.Text = string.Format( + "255 {0} 255 {0} 255 {0}{1}" + + "255 255 {0} 255 {0} 255{1}" + + "255 255 255 {0} 255 255{1}" + + "255 255 255 255 255 255" + + , nmPixelDimBrightness.Value, Environment.NewLine); + return; + } + + if (ReferenceEquals(sender, btnDimPatternHearts)) + { + + tbEvenPattern.Text = string.Format( + "255 {0} 255 {0} 255 255{1}" + + "{0} 255 {0} 255 {0} 255{1}" + + "{0} 255 255 255 {0} 255{1}" + + "255 {0} 255 {0} 255 255{1}" + + "255 255 {0} 255 255 255{1}" + + "255 255 255 255 255 255" + , nmPixelDimBrightness.Value, Environment.NewLine); + + tbOddPattern.Text = string.Format( + "255 255 255 255 255 255{1}" + + "255 255 {0} 255 {0} 255{1}" + + "255 {0} 255 {0} 255 {0}{1}" + + "255 {0} 255 255 255 {0}{1}" + + "255 255 {0} 255 {0} 255{1}" + + "255 255 255 {0} 255 255" + , nmPixelDimBrightness.Value, Environment.NewLine); + return; + } + + if (ReferenceEquals(sender, btnDimPatternSlashes)) + { + tbEvenPattern.Text = string.Format( + "{0} 255 255{1}" + + "255 {0} 255{1}" + + "255 255 {0}" + , nmPixelDimBrightness.Value, Environment.NewLine); + + tbOddPattern.Text = string.Format( + "255 255 {0}{1}" + + "255 {0} 255{1}" + + "{0} 255 255" + , nmPixelDimBrightness.Value, Environment.NewLine); + return; + } + + if (ReferenceEquals(sender, btnDimPatternWaves)) + { + tbEvenPattern.Text = string.Format( + "{0} 255 255{1}" + + "255 255 {0}" + , nmPixelDimBrightness.Value, Environment.NewLine); + + tbOddPattern.Text = string.Format( + "255 255 {0}{1}" + + "{0} 255 255" + , nmPixelDimBrightness.Value, Environment.NewLine); + /*tbPattern.Text = string.Format( + "{0} {0} 255 {0}{1}" + + "255 {0} 255 {0}{1}" + + "255 {0} {0} {0}{1}" + + "255 255 255 255" + , nmPixelDimBrightness.Value, Environment.NewLine);*/ + return; + } + + if (ReferenceEquals(sender, btnPatternRandom)) + { + var text = string.Empty; + byte size = 10; + //var bytes = new byte[size * size]; + //RNGCryptoServiceProvider provider = new RNGCryptoServiceProvider(); + //provider.GetBytes(bytes); + + Random rnd = new Random(); + + for (byte row = 0; row < size; row++) + { + for (byte col = 0; col < size; col++) + { + //byte value = bytes[rnd.Next(0, bytes.Length)]; + byte value = (byte) rnd.Next(0, 2); + text += value == 1 ? "255" : nmPixelDimBrightness.Value.ToString(CultureInfo.InvariantCulture); + if (col < size-1) + text += " "; + } + + if (row < size-1) text += Environment.NewLine; + } + + tbEvenPattern.Text = text; + + return; + } + + if (ReferenceEquals(sender, btnInfillPatternRectilinear)) + { + tbEvenPattern.Text = $"0{Environment.NewLine}".Repeat((int) nmInfillSpacing.Value) + $"255{Environment.NewLine}".Repeat((int)nmInfillSpacing.Value); + tbEvenPattern.Text = tbEvenPattern.Text.Trim('\n', '\r'); + + tbOddPattern.Text = string.Empty; + return; + } + + if (ReferenceEquals(sender, btnInfillPatternSquareGrid)) + { + var p1 = "0 ".Repeat((int)nmInfillSpacing.Value) + "255 ".Repeat((int)nmInfillThickness.Value); + p1 = p1.Trim() + Environment.NewLine; + p1 += p1.Repeat((int)nmInfillThickness.Value); + + + var p2 = "255 ".Repeat((int) nmInfillSpacing.Value) + "255 ".Repeat((int) nmInfillThickness.Value); + p2 = p2.Trim() + Environment.NewLine; + p2 += p2.Repeat((int)nmInfillThickness.Value); + + p2 = p2.Trim('\n', '\r'); + + tbEvenPattern.Text = p1 + p2; + tbOddPattern.Text = string.Empty; + return; + } + + if (ReferenceEquals(sender, btnInfillPatternWaves)) + { + var p1 = string.Empty; + var pos = 0; + for (sbyte dir = 1; dir >= -1; dir-=2) + { + while (pos >= 0 && pos <= nmInfillSpacing.Value) + { + p1 += "0 ".Repeat(pos); + p1 += "255 ".Repeat((int) nmInfillThickness.Value); + p1 += "0 ".Repeat((int)nmInfillSpacing.Value - pos); + p1 = p1.Trim() + Environment.NewLine; + + pos += dir; + } + + pos--; + } + + tbEvenPattern.Text = p1.Trim('\n', '\r'); + tbOddPattern.Text = string.Empty; + return; + } + + if (ReferenceEquals(sender, btnMutate)) + { + if (!btnMutate.Enabled) return; + if (LayerRangeStart > LayerRangeEnd) + { + MessageBox.Show("Layer range start can't be higher than layer end.\nPlease fix and try again.", Text, MessageBoxButtons.OK, MessageBoxIcon.Error); + nmLayerRangeStart.Select(); + return; + } + + var matrixTextbox = new[] + { + new MatrixTexbox(EvenPattern, tbEvenPattern), + new MatrixTexbox(OddPattern, tbOddPattern), + }; + + + foreach (var item in matrixTextbox) + { + if (string.IsNullOrWhiteSpace(item.Textbox.Text)) + { + item.Pattern = null; + } + else + { + for (var row = 0; row < item.Textbox.Lines.Length; row++) + { + + var bytes = item.Textbox.Lines[row].Trim().Split(' '); + if (row == 0) + { + /*if (tbPattern.Lines.Length % 2 != 0 || bytes.Length % 2 != 0) + { + MessageBox.Show($"Rows and columns must be in even numbers", Text, MessageBoxButtons.OK, MessageBoxIcon.Error); + return; + }*/ + item.Pattern = new Matrix<byte>(item.Textbox.Lines.Length, bytes.Length); + } + else + { + if (item.Pattern.Cols != bytes.Length) + { + MessageBox.Show($"Row {row + 1} have invalid number of pixels, the pattern must have equal pixel count per line, per defined on line 1", Text, MessageBoxButtons.OK, MessageBoxIcon.Error); + return; + } + } + + for (int col = 0; col < bytes.Length; col++) + { + if (byte.TryParse(bytes[col], out var value)) + { + item.Pattern[row, col] = value; + } + else + { + MessageBox.Show($"{bytes[col]} is a invalid number, use values from 0 to 255", Text, MessageBoxButtons.OK, MessageBoxIcon.Error); + return; + } + } + } + } + } + + + EvenPattern = matrixTextbox[0].Pattern; + OddPattern = matrixTextbox[1].Pattern; + + + /*if (X == 100 && Y == 100) + { + MessageBox.Show($"X and Y cant be 100% together.", Text, MessageBoxButtons.OK, MessageBoxIcon.Error); + return; + }*/ + + if (MessageBox.Show($"Are you sure you want to {Mutation.Mutate}?", Text, MessageBoxButtons.YesNo, + MessageBoxIcon.Question) == DialogResult.Yes) + { + DialogResult = DialogResult.OK; + Close(); + } + + return; + } + + if (ReferenceEquals(sender, btnCancel)) + { + DialogResult = DialogResult.Cancel; + return; + } + } + + + #endregion + } +} diff --git a/UVtools.GUI/Forms/FrmMutationPixelDimming.resx b/UVtools.GUI/Forms/FrmMutationPixelDimming.resx new file mode 100644 index 0000000..5195000 --- /dev/null +++ b/UVtools.GUI/Forms/FrmMutationPixelDimming.resx @@ -0,0 +1,146 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <metadata name="toolTip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>148, 17</value> + </metadata> + <data name="lbX.ToolTip" xml:space="preserve"> + <value>Selects the number of iterations/passes to perform on each layer using this mutator. +Enable the "Fade in/out" to fade the iteration over layers, you can use a start iteration higher than end to perform a inverse fade. +WARNING: Using high iteration values can destroy your model depending on the mutator being used, please use low values or with caution!</value> + </data> + <data name="lbLayerRange.ToolTip" xml:space="preserve"> + <value>Selects the layers range within start layer and end layer where mutator will operate. +Select same layer start as end to operate only within that layer. +Note: "Layer Start" start can't be higher than "Layer End".</value> + </data> + <metadata name="cmLayerRange.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>17, 17</value> + </metadata> + <data name="label1.ToolTip" xml:space="preserve"> + <value>Selects the number of iterations/passes to perform on each layer using this mutator. +Enable the "Fade in/out" to fade the iteration over layers, you can use a start iteration higher than end to perform a inverse fade. +WARNING: Using high iteration values can destroy your model depending on the mutator being used, please use low values or with caution!</value> + </data> + <data name="label6.ToolTip" xml:space="preserve"> + <value>Selects the layers range within start layer and end layer where mutator will operate. +Select same layer start as end to operate only within that layer. +Note: "Layer Start" start can't be higher than "Layer End".</value> + </data> +</root>
\ No newline at end of file diff --git a/UVtools.GUI/Forms/FrmSettings.Designer.cs b/UVtools.GUI/Forms/FrmSettings.Designer.cs index 51418df..d104701 100644 --- a/UVtools.GUI/Forms/FrmSettings.Designer.cs +++ b/UVtools.GUI/Forms/FrmSettings.Designer.cs @@ -93,11 +93,43 @@ this.cbAutoComputeIssuesClickOnTab = new System.Windows.Forms.CheckBox(); this.tabSettings = new System.Windows.Forms.TabControl(); this.tabPage1 = new System.Windows.Forms.TabPage(); + this.label22 = new System.Windows.Forms.Label(); + this.cbDefaultOpenFileExtension = new System.Windows.Forms.ComboBox(); this.tabPage2 = new System.Windows.Forms.TabPage(); - this.panel1 = new System.Windows.Forms.Panel(); this.tabPage3 = new System.Windows.Forms.TabPage(); - this.cbDefaultOpenFileExtension = new System.Windows.Forms.ComboBox(); - this.label22 = new System.Windows.Forms.Label(); + this.tabPage4 = new System.Windows.Forms.TabPage(); + this.btnPixelEditorDrainHoleColor = new System.Windows.Forms.Button(); + this.label26 = new System.Windows.Forms.Label(); + this.btnPixelEditorSupportColor = new System.Windows.Forms.Button(); + this.label25 = new System.Windows.Forms.Label(); + this.btnPixelEditorRemovePixelColor = new System.Windows.Forms.Button(); + this.label24 = new System.Windows.Forms.Label(); + this.label23 = new System.Windows.Forms.Label(); + this.btnPixelEditorAddPixelColor = new System.Windows.Forms.Button(); + this.panel1 = new System.Windows.Forms.Panel(); + this.cbFileSavePromptOverwrite = new System.Windows.Forms.CheckBox(); + this.label27 = new System.Windows.Forms.Label(); + this.tbFileSaveNamePreffix = new System.Windows.Forms.TextBox(); + this.tbFileSaveNameSuffix = new System.Windows.Forms.TextBox(); + this.label28 = new System.Windows.Forms.Label(); + this.groupBox4 = new System.Windows.Forms.GroupBox(); + this.groupBox5 = new System.Windows.Forms.GroupBox(); + this.tbFileOpenDefaultDirectory = new System.Windows.Forms.TextBox(); + this.label29 = new System.Windows.Forms.Label(); + this.btnFileOpenDefaultDirectorySearch = new System.Windows.Forms.Button(); + this.btnFileOpenDefaultDirectoryClear = new System.Windows.Forms.Button(); + this.btnFileSaveDefaultDirectoryClear = new System.Windows.Forms.Button(); + this.btnFileSaveDefaultDirectorySearch = new System.Windows.Forms.Button(); + this.label30 = new System.Windows.Forms.Label(); + this.tbFileSaveDefaultDirectory = new System.Windows.Forms.TextBox(); + this.btnFileConvertDefaultDirectoryClear = new System.Windows.Forms.Button(); + this.btnFileConvertDefaultDirectorySearch = new System.Windows.Forms.Button(); + this.label31 = new System.Windows.Forms.Label(); + this.tbFileConvertDefaultDirectory = new System.Windows.Forms.TextBox(); + this.btnFileExtractDefaultDirectoryClear = new System.Windows.Forms.Button(); + this.btnFileExtractDefaultDirectorySearch = new System.Windows.Forms.Button(); + this.label32 = new System.Windows.Forms.Label(); + this.tbFileExtractDefaultDirectory = new System.Windows.Forms.TextBox(); ((System.ComponentModel.ISupportInitialize)(this.nmOutlineHollowAreasLineThickness)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.nmOutlineLayerBoundsLineThickness)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.nmOutlinePrintVolumeBoundsLineThickness)).BeginInit(); @@ -116,8 +148,11 @@ this.tabSettings.SuspendLayout(); this.tabPage1.SuspendLayout(); this.tabPage2.SuspendLayout(); - this.panel1.SuspendLayout(); this.tabPage3.SuspendLayout(); + this.tabPage4.SuspendLayout(); + this.panel1.SuspendLayout(); + this.groupBox4.SuspendLayout(); + this.groupBox5.SuspendLayout(); this.SuspendLayout(); // // label1 @@ -308,7 +343,7 @@ // cbCheckForUpdatesOnStartup // this.cbCheckForUpdatesOnStartup.AutoSize = true; - this.cbCheckForUpdatesOnStartup.Location = new System.Drawing.Point(9, 34); + this.cbCheckForUpdatesOnStartup.Location = new System.Drawing.Point(6, 51); this.cbCheckForUpdatesOnStartup.Name = "cbCheckForUpdatesOnStartup"; this.cbCheckForUpdatesOnStartup.Size = new System.Drawing.Size(218, 22); this.cbCheckForUpdatesOnStartup.TabIndex = 7; @@ -318,7 +353,7 @@ // cbStartMaximized // this.cbStartMaximized.AutoSize = true; - this.cbStartMaximized.Location = new System.Drawing.Point(9, 6); + this.cbStartMaximized.Location = new System.Drawing.Point(6, 23); this.cbStartMaximized.Name = "cbStartMaximized"; this.cbStartMaximized.Size = new System.Drawing.Size(133, 22); this.cbStartMaximized.TabIndex = 6; @@ -941,6 +976,7 @@ this.tabSettings.Controls.Add(this.tabPage1); this.tabSettings.Controls.Add(this.tabPage2); this.tabSettings.Controls.Add(this.tabPage3); + this.tabSettings.Controls.Add(this.tabPage4); this.tabSettings.Dock = System.Windows.Forms.DockStyle.Fill; this.tabSettings.Location = new System.Drawing.Point(0, 0); this.tabSettings.Name = "tabSettings"; @@ -950,10 +986,8 @@ // // tabPage1 // - this.tabPage1.Controls.Add(this.label22); - this.tabPage1.Controls.Add(this.cbDefaultOpenFileExtension); - this.tabPage1.Controls.Add(this.cbCheckForUpdatesOnStartup); - this.tabPage1.Controls.Add(this.cbStartMaximized); + this.tabPage1.Controls.Add(this.groupBox5); + this.tabPage1.Controls.Add(this.groupBox4); this.tabPage1.Location = new System.Drawing.Point(4, 27); this.tabPage1.Name = "tabPage1"; this.tabPage1.Padding = new System.Windows.Forms.Padding(3); @@ -962,6 +996,25 @@ this.tabPage1.Text = "General"; this.tabPage1.UseVisualStyleBackColor = true; // + // label22 + // + this.label22.AutoSize = true; + this.label22.Location = new System.Drawing.Point(6, 27); + this.label22.Name = "label22"; + this.label22.Size = new System.Drawing.Size(214, 18); + this.label22.TabIndex = 9; + this.label22.Text = "File load default view extension:"; + // + // cbDefaultOpenFileExtension + // + this.cbDefaultOpenFileExtension.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.cbDefaultOpenFileExtension.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.cbDefaultOpenFileExtension.FormattingEnabled = true; + this.cbDefaultOpenFileExtension.Location = new System.Drawing.Point(225, 23); + this.cbDefaultOpenFileExtension.Name = "cbDefaultOpenFileExtension"; + this.cbDefaultOpenFileExtension.Size = new System.Drawing.Size(379, 26); + this.cbDefaultOpenFileExtension.TabIndex = 8; + // // tabPage2 // this.tabPage2.Controls.Add(this.cbZoomToFitPrintVolumeBounds); @@ -1003,17 +1056,6 @@ this.tabPage2.Text = "Layer Preview"; this.tabPage2.UseVisualStyleBackColor = true; // - // panel1 - // - this.panel1.Controls.Add(this.btnCancel); - this.panel1.Controls.Add(this.btnSave); - this.panel1.Controls.Add(this.btnReset); - this.panel1.Dock = System.Windows.Forms.DockStyle.Bottom; - this.panel1.Location = new System.Drawing.Point(0, 452); - this.panel1.Name = "panel1"; - this.panel1.Size = new System.Drawing.Size(624, 77); - this.panel1.TabIndex = 19; - // // tabPage3 // this.tabPage3.Controls.Add(this.groupBox3); @@ -1027,24 +1069,365 @@ this.tabPage3.Text = "Issues"; this.tabPage3.UseVisualStyleBackColor = true; // - // cbDefaultOpenFileExtension + // tabPage4 + // + this.tabPage4.Controls.Add(this.btnPixelEditorDrainHoleColor); + this.tabPage4.Controls.Add(this.label26); + this.tabPage4.Controls.Add(this.btnPixelEditorSupportColor); + this.tabPage4.Controls.Add(this.label25); + this.tabPage4.Controls.Add(this.btnPixelEditorRemovePixelColor); + this.tabPage4.Controls.Add(this.label24); + this.tabPage4.Controls.Add(this.label23); + this.tabPage4.Controls.Add(this.btnPixelEditorAddPixelColor); + this.tabPage4.Location = new System.Drawing.Point(4, 27); + this.tabPage4.Name = "tabPage4"; + this.tabPage4.Padding = new System.Windows.Forms.Padding(3); + this.tabPage4.Size = new System.Drawing.Size(616, 498); + this.tabPage4.TabIndex = 3; + this.tabPage4.Text = "Pixel Editor"; + this.tabPage4.UseVisualStyleBackColor = true; + // + // btnPixelEditorDrainHoleColor + // + this.btnPixelEditorDrainHoleColor.BackColor = System.Drawing.Color.White; + this.btnPixelEditorDrainHoleColor.FlatAppearance.BorderColor = System.Drawing.Color.Black; + this.btnPixelEditorDrainHoleColor.FlatAppearance.BorderSize = 2; + this.btnPixelEditorDrainHoleColor.FlatStyle = System.Windows.Forms.FlatStyle.Flat; + this.btnPixelEditorDrainHoleColor.Location = new System.Drawing.Point(152, 131); + this.btnPixelEditorDrainHoleColor.Margin = new System.Windows.Forms.Padding(4); + this.btnPixelEditorDrainHoleColor.Name = "btnPixelEditorDrainHoleColor"; + this.btnPixelEditorDrainHoleColor.Size = new System.Drawing.Size(32, 32); + this.btnPixelEditorDrainHoleColor.TabIndex = 9; + this.btnPixelEditorDrainHoleColor.UseVisualStyleBackColor = false; + this.btnPixelEditorDrainHoleColor.Click += new System.EventHandler(this.EventClick); + // + // label26 + // + this.label26.AutoSize = true; + this.label26.Location = new System.Drawing.Point(9, 138); + this.label26.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label26.Name = "label26"; + this.label26.Size = new System.Drawing.Size(117, 18); + this.label26.TabIndex = 8; + this.label26.Text = "Drain hole color:"; + // + // btnPixelEditorSupportColor + // + this.btnPixelEditorSupportColor.BackColor = System.Drawing.Color.White; + this.btnPixelEditorSupportColor.FlatAppearance.BorderColor = System.Drawing.Color.Black; + this.btnPixelEditorSupportColor.FlatAppearance.BorderSize = 2; + this.btnPixelEditorSupportColor.FlatStyle = System.Windows.Forms.FlatStyle.Flat; + this.btnPixelEditorSupportColor.Location = new System.Drawing.Point(152, 91); + this.btnPixelEditorSupportColor.Margin = new System.Windows.Forms.Padding(4); + this.btnPixelEditorSupportColor.Name = "btnPixelEditorSupportColor"; + this.btnPixelEditorSupportColor.Size = new System.Drawing.Size(32, 32); + this.btnPixelEditorSupportColor.TabIndex = 7; + this.btnPixelEditorSupportColor.UseVisualStyleBackColor = false; + this.btnPixelEditorSupportColor.Click += new System.EventHandler(this.EventClick); + // + // label25 + // + this.label25.AutoSize = true; + this.label25.Location = new System.Drawing.Point(9, 98); + this.label25.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label25.Name = "label25"; + this.label25.Size = new System.Drawing.Size(102, 18); + this.label25.TabIndex = 6; + this.label25.Text = "Support color:"; + // + // btnPixelEditorRemovePixelColor + // + this.btnPixelEditorRemovePixelColor.BackColor = System.Drawing.Color.White; + this.btnPixelEditorRemovePixelColor.FlatAppearance.BorderColor = System.Drawing.Color.Black; + this.btnPixelEditorRemovePixelColor.FlatAppearance.BorderSize = 2; + this.btnPixelEditorRemovePixelColor.FlatStyle = System.Windows.Forms.FlatStyle.Flat; + this.btnPixelEditorRemovePixelColor.Location = new System.Drawing.Point(152, 51); + this.btnPixelEditorRemovePixelColor.Margin = new System.Windows.Forms.Padding(4); + this.btnPixelEditorRemovePixelColor.Name = "btnPixelEditorRemovePixelColor"; + this.btnPixelEditorRemovePixelColor.Size = new System.Drawing.Size(32, 32); + this.btnPixelEditorRemovePixelColor.TabIndex = 5; + this.btnPixelEditorRemovePixelColor.UseVisualStyleBackColor = false; + this.btnPixelEditorRemovePixelColor.Click += new System.EventHandler(this.EventClick); + // + // label24 + // + this.label24.AutoSize = true; + this.label24.Location = new System.Drawing.Point(9, 58); + this.label24.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label24.Name = "label24"; + this.label24.Size = new System.Drawing.Size(135, 18); + this.label24.TabIndex = 4; + this.label24.Text = "Pixel remove color:"; + // + // label23 + // + this.label23.AutoSize = true; + this.label23.Location = new System.Drawing.Point(9, 17); + this.label23.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label23.Name = "label23"; + this.label23.Size = new System.Drawing.Size(109, 18); + this.label23.TabIndex = 2; + this.label23.Text = "Pixel add color:"; + // + // btnPixelEditorAddPixelColor + // + this.btnPixelEditorAddPixelColor.BackColor = System.Drawing.Color.White; + this.btnPixelEditorAddPixelColor.FlatAppearance.BorderColor = System.Drawing.Color.Black; + this.btnPixelEditorAddPixelColor.FlatAppearance.BorderSize = 2; + this.btnPixelEditorAddPixelColor.FlatStyle = System.Windows.Forms.FlatStyle.Flat; + this.btnPixelEditorAddPixelColor.Location = new System.Drawing.Point(152, 10); + this.btnPixelEditorAddPixelColor.Margin = new System.Windows.Forms.Padding(4); + this.btnPixelEditorAddPixelColor.Name = "btnPixelEditorAddPixelColor"; + this.btnPixelEditorAddPixelColor.Size = new System.Drawing.Size(32, 32); + this.btnPixelEditorAddPixelColor.TabIndex = 3; + this.btnPixelEditorAddPixelColor.UseVisualStyleBackColor = false; + this.btnPixelEditorAddPixelColor.Click += new System.EventHandler(this.EventClick); // - this.cbDefaultOpenFileExtension.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); - this.cbDefaultOpenFileExtension.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; - this.cbDefaultOpenFileExtension.FormattingEnabled = true; - this.cbDefaultOpenFileExtension.Location = new System.Drawing.Point(225, 62); - this.cbDefaultOpenFileExtension.Name = "cbDefaultOpenFileExtension"; - this.cbDefaultOpenFileExtension.Size = new System.Drawing.Size(382, 26); - this.cbDefaultOpenFileExtension.TabIndex = 8; + // panel1 // - // label22 + this.panel1.Controls.Add(this.btnCancel); + this.panel1.Controls.Add(this.btnSave); + this.panel1.Controls.Add(this.btnReset); + this.panel1.Dock = System.Windows.Forms.DockStyle.Bottom; + this.panel1.Location = new System.Drawing.Point(0, 452); + this.panel1.Name = "panel1"; + this.panel1.Size = new System.Drawing.Size(624, 77); + this.panel1.TabIndex = 19; // - this.label22.AutoSize = true; - this.label22.Location = new System.Drawing.Point(6, 66); - this.label22.Name = "label22"; - this.label22.Size = new System.Drawing.Size(213, 18); - this.label22.TabIndex = 9; - this.label22.Text = "Default file extension at file load"; + // cbFileSavePromptOverwrite + // + this.cbFileSavePromptOverwrite.AutoSize = true; + this.cbFileSavePromptOverwrite.Location = new System.Drawing.Point(9, 175); + this.cbFileSavePromptOverwrite.Name = "cbFileSavePromptOverwrite"; + this.cbFileSavePromptOverwrite.Size = new System.Drawing.Size(381, 22); + this.cbFileSavePromptOverwrite.TabIndex = 10; + this.cbFileSavePromptOverwrite.Text = "On file \"Save\" prompt for file overwrite for the first time"; + this.cbFileSavePromptOverwrite.UseVisualStyleBackColor = true; + // + // label27 + // + this.label27.AutoSize = true; + this.label27.Location = new System.Drawing.Point(9, 206); + this.label27.Name = "label27"; + this.label27.Size = new System.Drawing.Size(147, 18); + this.label27.TabIndex = 11; + this.label27.Text = "File \"Save as\" Preffix:"; + // + // tbFileSaveNamePreffix + // + this.tbFileSaveNamePreffix.Location = new System.Drawing.Point(162, 203); + this.tbFileSaveNamePreffix.Name = "tbFileSaveNamePreffix"; + this.tbFileSaveNamePreffix.Size = new System.Drawing.Size(184, 24); + this.tbFileSaveNamePreffix.TabIndex = 12; + // + // tbFileSaveNameSuffix + // + this.tbFileSaveNameSuffix.Location = new System.Drawing.Point(420, 203); + this.tbFileSaveNameSuffix.Name = "tbFileSaveNameSuffix"; + this.tbFileSaveNameSuffix.Size = new System.Drawing.Size(184, 24); + this.tbFileSaveNameSuffix.TabIndex = 13; + // + // label28 + // + this.label28.AutoSize = true; + this.label28.Location = new System.Drawing.Point(361, 206); + this.label28.Name = "label28"; + this.label28.Size = new System.Drawing.Size(48, 18); + this.label28.TabIndex = 14; + this.label28.Text = "Suffix:"; + // + // groupBox4 + // + this.groupBox4.Controls.Add(this.cbStartMaximized); + this.groupBox4.Controls.Add(this.cbCheckForUpdatesOnStartup); + this.groupBox4.Dock = System.Windows.Forms.DockStyle.Top; + this.groupBox4.Location = new System.Drawing.Point(3, 3); + this.groupBox4.Name = "groupBox4"; + this.groupBox4.Size = new System.Drawing.Size(610, 83); + this.groupBox4.TabIndex = 15; + this.groupBox4.TabStop = false; + this.groupBox4.Text = "Startup"; + // + // groupBox5 + // + this.groupBox5.Controls.Add(this.btnFileExtractDefaultDirectoryClear); + this.groupBox5.Controls.Add(this.btnFileExtractDefaultDirectorySearch); + this.groupBox5.Controls.Add(this.label32); + this.groupBox5.Controls.Add(this.tbFileExtractDefaultDirectory); + this.groupBox5.Controls.Add(this.btnFileConvertDefaultDirectoryClear); + this.groupBox5.Controls.Add(this.btnFileConvertDefaultDirectorySearch); + this.groupBox5.Controls.Add(this.label31); + this.groupBox5.Controls.Add(this.tbFileConvertDefaultDirectory); + this.groupBox5.Controls.Add(this.btnFileSaveDefaultDirectoryClear); + this.groupBox5.Controls.Add(this.btnFileSaveDefaultDirectorySearch); + this.groupBox5.Controls.Add(this.label30); + this.groupBox5.Controls.Add(this.tbFileSaveDefaultDirectory); + this.groupBox5.Controls.Add(this.btnFileOpenDefaultDirectoryClear); + this.groupBox5.Controls.Add(this.btnFileOpenDefaultDirectorySearch); + this.groupBox5.Controls.Add(this.label29); + this.groupBox5.Controls.Add(this.tbFileOpenDefaultDirectory); + this.groupBox5.Controls.Add(this.label22); + this.groupBox5.Controls.Add(this.cbDefaultOpenFileExtension); + this.groupBox5.Controls.Add(this.label28); + this.groupBox5.Controls.Add(this.cbFileSavePromptOverwrite); + this.groupBox5.Controls.Add(this.tbFileSaveNameSuffix); + this.groupBox5.Controls.Add(this.label27); + this.groupBox5.Controls.Add(this.tbFileSaveNamePreffix); + this.groupBox5.Dock = System.Windows.Forms.DockStyle.Top; + this.groupBox5.Location = new System.Drawing.Point(3, 86); + this.groupBox5.Name = "groupBox5"; + this.groupBox5.Size = new System.Drawing.Size(610, 250); + this.groupBox5.TabIndex = 16; + this.groupBox5.TabStop = false; + this.groupBox5.Text = "File operations"; + // + // tbFileOpenDefaultDirectory + // + this.tbFileOpenDefaultDirectory.Location = new System.Drawing.Point(225, 55); + this.tbFileOpenDefaultDirectory.Name = "tbFileOpenDefaultDirectory"; + this.tbFileOpenDefaultDirectory.ReadOnly = true; + this.tbFileOpenDefaultDirectory.Size = new System.Drawing.Size(307, 24); + this.tbFileOpenDefaultDirectory.TabIndex = 15; + // + // label29 + // + this.label29.AutoSize = true; + this.label29.Location = new System.Drawing.Point(6, 58); + this.label29.Name = "label29"; + this.label29.Size = new System.Drawing.Size(180, 18); + this.label29.TabIndex = 16; + this.label29.Text = "File open default directory:"; + // + // btnFileOpenDefaultDirectorySearch + // + this.btnFileOpenDefaultDirectorySearch.Image = global::UVtools.GUI.Properties.Resources.Open_16x16; + this.btnFileOpenDefaultDirectorySearch.Location = new System.Drawing.Point(538, 55); + this.btnFileOpenDefaultDirectorySearch.Name = "btnFileOpenDefaultDirectorySearch"; + this.btnFileOpenDefaultDirectorySearch.Size = new System.Drawing.Size(30, 24); + this.btnFileOpenDefaultDirectorySearch.TabIndex = 17; + this.btnFileOpenDefaultDirectorySearch.UseVisualStyleBackColor = true; + this.btnFileOpenDefaultDirectorySearch.Click += new System.EventHandler(this.EventClick); + // + // btnFileOpenDefaultDirectoryClear + // + this.btnFileOpenDefaultDirectoryClear.Image = global::UVtools.GUI.Properties.Resources.delete_16x16; + this.btnFileOpenDefaultDirectoryClear.Location = new System.Drawing.Point(574, 55); + this.btnFileOpenDefaultDirectoryClear.Name = "btnFileOpenDefaultDirectoryClear"; + this.btnFileOpenDefaultDirectoryClear.Size = new System.Drawing.Size(30, 24); + this.btnFileOpenDefaultDirectoryClear.TabIndex = 18; + this.btnFileOpenDefaultDirectoryClear.UseVisualStyleBackColor = true; + this.btnFileOpenDefaultDirectoryClear.Click += new System.EventHandler(this.EventClick); + // + // btnFileSaveDefaultDirectoryClear + // + this.btnFileSaveDefaultDirectoryClear.Image = global::UVtools.GUI.Properties.Resources.delete_16x16; + this.btnFileSaveDefaultDirectoryClear.Location = new System.Drawing.Point(574, 85); + this.btnFileSaveDefaultDirectoryClear.Name = "btnFileSaveDefaultDirectoryClear"; + this.btnFileSaveDefaultDirectoryClear.Size = new System.Drawing.Size(30, 24); + this.btnFileSaveDefaultDirectoryClear.TabIndex = 22; + this.btnFileSaveDefaultDirectoryClear.UseVisualStyleBackColor = true; + this.btnFileSaveDefaultDirectoryClear.Click += new System.EventHandler(this.EventClick); + // + // btnFileSaveDefaultDirectorySearch + // + this.btnFileSaveDefaultDirectorySearch.Image = global::UVtools.GUI.Properties.Resources.Open_16x16; + this.btnFileSaveDefaultDirectorySearch.Location = new System.Drawing.Point(538, 85); + this.btnFileSaveDefaultDirectorySearch.Name = "btnFileSaveDefaultDirectorySearch"; + this.btnFileSaveDefaultDirectorySearch.Size = new System.Drawing.Size(30, 24); + this.btnFileSaveDefaultDirectorySearch.TabIndex = 21; + this.btnFileSaveDefaultDirectorySearch.UseVisualStyleBackColor = true; + this.btnFileSaveDefaultDirectorySearch.Click += new System.EventHandler(this.EventClick); + // + // label30 + // + this.label30.AutoSize = true; + this.label30.Location = new System.Drawing.Point(6, 88); + this.label30.Name = "label30"; + this.label30.Size = new System.Drawing.Size(198, 18); + this.label30.TabIndex = 20; + this.label30.Text = "File save as default directory:"; + // + // tbFileSaveDefaultDirectory + // + this.tbFileSaveDefaultDirectory.Location = new System.Drawing.Point(225, 85); + this.tbFileSaveDefaultDirectory.Name = "tbFileSaveDefaultDirectory"; + this.tbFileSaveDefaultDirectory.ReadOnly = true; + this.tbFileSaveDefaultDirectory.Size = new System.Drawing.Size(307, 24); + this.tbFileSaveDefaultDirectory.TabIndex = 19; + // + // btnFileConvertDefaultDirectoryClear + // + this.btnFileConvertDefaultDirectoryClear.Image = global::UVtools.GUI.Properties.Resources.delete_16x16; + this.btnFileConvertDefaultDirectoryClear.Location = new System.Drawing.Point(574, 145); + this.btnFileConvertDefaultDirectoryClear.Name = "btnFileConvertDefaultDirectoryClear"; + this.btnFileConvertDefaultDirectoryClear.Size = new System.Drawing.Size(30, 24); + this.btnFileConvertDefaultDirectoryClear.TabIndex = 26; + this.btnFileConvertDefaultDirectoryClear.UseVisualStyleBackColor = true; + this.btnFileConvertDefaultDirectoryClear.Click += new System.EventHandler(this.EventClick); + // + // btnFileConvertDefaultDirectorySearch + // + this.btnFileConvertDefaultDirectorySearch.Image = global::UVtools.GUI.Properties.Resources.Open_16x16; + this.btnFileConvertDefaultDirectorySearch.Location = new System.Drawing.Point(538, 145); + this.btnFileConvertDefaultDirectorySearch.Name = "btnFileConvertDefaultDirectorySearch"; + this.btnFileConvertDefaultDirectorySearch.Size = new System.Drawing.Size(30, 24); + this.btnFileConvertDefaultDirectorySearch.TabIndex = 25; + this.btnFileConvertDefaultDirectorySearch.UseVisualStyleBackColor = true; + this.btnFileConvertDefaultDirectorySearch.Click += new System.EventHandler(this.EventClick); + // + // label31 + // + this.label31.AutoSize = true; + this.label31.Location = new System.Drawing.Point(6, 148); + this.label31.Name = "label31"; + this.label31.Size = new System.Drawing.Size(196, 18); + this.label31.TabIndex = 24; + this.label31.Text = "File convert default directory:"; + // + // tbFileConvertDefaultDirectory + // + this.tbFileConvertDefaultDirectory.Location = new System.Drawing.Point(225, 145); + this.tbFileConvertDefaultDirectory.Name = "tbFileConvertDefaultDirectory"; + this.tbFileConvertDefaultDirectory.ReadOnly = true; + this.tbFileConvertDefaultDirectory.Size = new System.Drawing.Size(307, 24); + this.tbFileConvertDefaultDirectory.TabIndex = 23; + // + // btnFileExtractDefaultDirectoryClear + // + this.btnFileExtractDefaultDirectoryClear.Image = global::UVtools.GUI.Properties.Resources.delete_16x16; + this.btnFileExtractDefaultDirectoryClear.Location = new System.Drawing.Point(574, 115); + this.btnFileExtractDefaultDirectoryClear.Name = "btnFileExtractDefaultDirectoryClear"; + this.btnFileExtractDefaultDirectoryClear.Size = new System.Drawing.Size(30, 24); + this.btnFileExtractDefaultDirectoryClear.TabIndex = 30; + this.btnFileExtractDefaultDirectoryClear.UseVisualStyleBackColor = true; + this.btnFileExtractDefaultDirectoryClear.Click += new System.EventHandler(this.EventClick); + // + // btnFileExtractDefaultDirectorySearch + // + this.btnFileExtractDefaultDirectorySearch.Image = global::UVtools.GUI.Properties.Resources.Open_16x16; + this.btnFileExtractDefaultDirectorySearch.Location = new System.Drawing.Point(538, 115); + this.btnFileExtractDefaultDirectorySearch.Name = "btnFileExtractDefaultDirectorySearch"; + this.btnFileExtractDefaultDirectorySearch.Size = new System.Drawing.Size(30, 24); + this.btnFileExtractDefaultDirectorySearch.TabIndex = 29; + this.btnFileExtractDefaultDirectorySearch.UseVisualStyleBackColor = true; + this.btnFileExtractDefaultDirectorySearch.Click += new System.EventHandler(this.EventClick); + // + // label32 + // + this.label32.AutoSize = true; + this.label32.Location = new System.Drawing.Point(6, 118); + this.label32.Name = "label32"; + this.label32.Size = new System.Drawing.Size(191, 18); + this.label32.TabIndex = 28; + this.label32.Text = "File extract default directory:"; + // + // tbFileExtractDefaultDirectory + // + this.tbFileExtractDefaultDirectory.Location = new System.Drawing.Point(225, 115); + this.tbFileExtractDefaultDirectory.Name = "tbFileExtractDefaultDirectory"; + this.tbFileExtractDefaultDirectory.ReadOnly = true; + this.tbFileExtractDefaultDirectory.Size = new System.Drawing.Size(307, 24); + this.tbFileExtractDefaultDirectory.TabIndex = 27; // // FrmSettings // @@ -1083,11 +1466,16 @@ this.groupBox1.PerformLayout(); this.tabSettings.ResumeLayout(false); this.tabPage1.ResumeLayout(false); - this.tabPage1.PerformLayout(); this.tabPage2.ResumeLayout(false); this.tabPage2.PerformLayout(); - this.panel1.ResumeLayout(false); this.tabPage3.ResumeLayout(false); + this.tabPage4.ResumeLayout(false); + this.tabPage4.PerformLayout(); + this.panel1.ResumeLayout(false); + this.groupBox4.ResumeLayout(false); + this.groupBox4.PerformLayout(); + this.groupBox5.ResumeLayout(false); + this.groupBox5.PerformLayout(); this.ResumeLayout(false); } @@ -1163,5 +1551,37 @@ private System.Windows.Forms.TabPage tabPage3; private System.Windows.Forms.Label label22; private System.Windows.Forms.ComboBox cbDefaultOpenFileExtension; + private System.Windows.Forms.TabPage tabPage4; + private System.Windows.Forms.Button btnPixelEditorRemovePixelColor; + private System.Windows.Forms.Label label24; + private System.Windows.Forms.Label label23; + private System.Windows.Forms.Button btnPixelEditorAddPixelColor; + private System.Windows.Forms.Button btnPixelEditorSupportColor; + private System.Windows.Forms.Label label25; + private System.Windows.Forms.Button btnPixelEditorDrainHoleColor; + private System.Windows.Forms.Label label26; + private System.Windows.Forms.CheckBox cbFileSavePromptOverwrite; + private System.Windows.Forms.Label label27; + private System.Windows.Forms.Label label28; + private System.Windows.Forms.TextBox tbFileSaveNameSuffix; + private System.Windows.Forms.TextBox tbFileSaveNamePreffix; + private System.Windows.Forms.GroupBox groupBox4; + private System.Windows.Forms.GroupBox groupBox5; + private System.Windows.Forms.Button btnFileOpenDefaultDirectoryClear; + private System.Windows.Forms.Button btnFileOpenDefaultDirectorySearch; + private System.Windows.Forms.Label label29; + private System.Windows.Forms.TextBox tbFileOpenDefaultDirectory; + private System.Windows.Forms.Button btnFileSaveDefaultDirectoryClear; + private System.Windows.Forms.Button btnFileSaveDefaultDirectorySearch; + private System.Windows.Forms.Label label30; + private System.Windows.Forms.TextBox tbFileSaveDefaultDirectory; + private System.Windows.Forms.Button btnFileConvertDefaultDirectoryClear; + private System.Windows.Forms.Button btnFileConvertDefaultDirectorySearch; + private System.Windows.Forms.Label label31; + private System.Windows.Forms.TextBox tbFileConvertDefaultDirectory; + private System.Windows.Forms.Button btnFileExtractDefaultDirectoryClear; + private System.Windows.Forms.Button btnFileExtractDefaultDirectorySearch; + private System.Windows.Forms.Label label32; + private System.Windows.Forms.TextBox tbFileExtractDefaultDirectory; } }
\ No newline at end of file diff --git a/UVtools.GUI/Forms/FrmSettings.cs b/UVtools.GUI/Forms/FrmSettings.cs index b385aba..9a1d1c3 100644 --- a/UVtools.GUI/Forms/FrmSettings.cs +++ b/UVtools.GUI/Forms/FrmSettings.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Linq; using System.Windows.Forms; -using UVtools.Core; using UVtools.Core.FileFormats; using UVtools.GUI.Properties; @@ -14,6 +13,8 @@ namespace UVtools.GUI.Forms { InitializeComponent(); + Text = $"UVtools - Settings [v{FrmAbout.AssemblyVersion}]"; + var fileFormats = new List<string> { FileFormat.AllSlicerFiles.Replace("*", string.Empty) @@ -31,6 +32,13 @@ namespace UVtools.GUI.Forms cbCheckForUpdatesOnStartup.Checked = Settings.Default.CheckForUpdatesOnStartup; cbStartMaximized.Checked = Settings.Default.StartMaximized; cbDefaultOpenFileExtension.SelectedIndex = Settings.Default.DefaultOpenFileExtension; + tbFileOpenDefaultDirectory.Text = Settings.Default.FileOpenDefaultDirectory; + tbFileSaveDefaultDirectory.Text = Settings.Default.FileSaveDefaultDirectory; + tbFileExtractDefaultDirectory.Text = Settings.Default.FileExtractDefaultDirectory; + tbFileConvertDefaultDirectory.Text = Settings.Default.FileConvertDefaultDirectory; + cbFileSavePromptOverwrite.Checked = Settings.Default.FileSavePromptOverwrite; + tbFileSaveNamePreffix.Text = Settings.Default.FileSaveNamePreffix; + tbFileSaveNameSuffix.Text = Settings.Default.FileSaveNameSuffix; btnPreviousNextLayerColor.BackColor = Settings.Default.PreviousNextLayerColor; btnPreviousLayerColor.BackColor = Settings.Default.PreviousLayerColor; @@ -70,6 +78,11 @@ namespace UVtools.GUI.Forms nmResinTrapRequiredAreaToProcessCheck.Value = Settings.Default.ResinTrapRequiredAreaToProcessCheck; nmResinTrapRequiredBlackPixelsToDrain.Value = Settings.Default.ResinTrapRequiredBlackPixelsToDrain; nmResinTrapMaximumPixelBrightnessToDrain.Value = Settings.Default.ResinTrapMaximumPixelBrightnessToDrain; + + btnPixelEditorAddPixelColor.BackColor = Settings.Default.PixelEditorAddPixelColor; + btnPixelEditorRemovePixelColor.BackColor = Settings.Default.PixelEditorRemovePixelColor; + btnPixelEditorSupportColor.BackColor = Settings.Default.PixelEditorSupportColor; + btnPixelEditorDrainHoleColor.BackColor = Settings.Default.PixelEditorDrainHoleColor; } catch (Exception ex) { @@ -92,7 +105,11 @@ namespace UVtools.GUI.Forms ReferenceEquals(sender, btnTouchingBoundsColor) || ReferenceEquals(sender, btnOutlinePrintVolumeBoundsColor) || ReferenceEquals(sender, btnOutlineLayerBoundsColor) || - ReferenceEquals(sender, btnOutlineHollowAreasColor) + ReferenceEquals(sender, btnOutlineHollowAreasColor) || + ReferenceEquals(sender, btnPixelEditorAddPixelColor) || + ReferenceEquals(sender, btnPixelEditorRemovePixelColor) || + ReferenceEquals(sender, btnPixelEditorSupportColor) || + ReferenceEquals(sender, btnPixelEditorDrainHoleColor) ) { Button btn = sender as Button; @@ -105,6 +122,41 @@ namespace UVtools.GUI.Forms } + if (ReferenceEquals(sender, btnFileOpenDefaultDirectorySearch) || ReferenceEquals(sender, btnFileSaveDefaultDirectorySearch) || ReferenceEquals(sender, btnFileConvertDefaultDirectorySearch) || ReferenceEquals(sender, btnFileExtractDefaultDirectorySearch)) + { + using (FolderBrowserDialog folder = new FolderBrowserDialog()) + { + if (folder.ShowDialog() != DialogResult.OK) return; + if (ReferenceEquals(sender, btnFileOpenDefaultDirectorySearch)) tbFileOpenDefaultDirectory.Text = folder.SelectedPath; + else if (ReferenceEquals(sender, btnFileSaveDefaultDirectorySearch)) tbFileSaveDefaultDirectory.Text = folder.SelectedPath; + else if (ReferenceEquals(sender, btnFileExtractDefaultDirectorySearch)) tbFileExtractDefaultDirectory.Text = folder.SelectedPath; + else if (ReferenceEquals(sender, btnFileConvertDefaultDirectorySearch)) tbFileConvertDefaultDirectory.Text = folder.SelectedPath; + } + + return; + } + + if (ReferenceEquals(sender, btnFileOpenDefaultDirectoryClear)) + { + tbFileOpenDefaultDirectory.Text = string.Empty; + return; + } + if (ReferenceEquals(sender, btnFileSaveDefaultDirectoryClear)) + { + tbFileSaveDefaultDirectory.Text = string.Empty; + return; + } + if (ReferenceEquals(sender, btnFileExtractDefaultDirectoryClear)) + { + tbFileExtractDefaultDirectory.Text = string.Empty; + return; + } + if (ReferenceEquals(sender, btnFileConvertDefaultDirectoryClear)) + { + tbFileConvertDefaultDirectory.Text = string.Empty; + return; + } + if (ReferenceEquals(sender, btnReset)) { if (MessageBox.Show("Are you sure you want to reset the settings to the default values?", @@ -122,6 +174,13 @@ namespace UVtools.GUI.Forms Settings.Default.CheckForUpdatesOnStartup = cbCheckForUpdatesOnStartup.Checked; Settings.Default.StartMaximized = cbStartMaximized.Checked; Settings.Default.DefaultOpenFileExtension = (byte) cbDefaultOpenFileExtension.SelectedIndex; + Settings.Default.FileOpenDefaultDirectory = tbFileOpenDefaultDirectory.Text; + Settings.Default.FileSaveDefaultDirectory = tbFileSaveDefaultDirectory.Text; + Settings.Default.FileExtractDefaultDirectory = tbFileExtractDefaultDirectory.Text; + Settings.Default.FileConvertDefaultDirectory = tbFileConvertDefaultDirectory.Text; + Settings.Default.FileSavePromptOverwrite = cbFileSavePromptOverwrite.Checked; + Settings.Default.FileSaveNamePreffix = tbFileSaveNamePreffix.Text.Trim(); + Settings.Default.FileSaveNameSuffix = tbFileSaveNameSuffix.Text.Trim(); Settings.Default.PreviousNextLayerColor = btnPreviousNextLayerColor.BackColor; Settings.Default.PreviousLayerColor = btnPreviousLayerColor.BackColor; @@ -162,6 +221,11 @@ namespace UVtools.GUI.Forms Settings.Default.ResinTrapRequiredBlackPixelsToDrain = (byte)nmResinTrapRequiredBlackPixelsToDrain.Value; Settings.Default.ResinTrapMaximumPixelBrightnessToDrain = (byte)nmResinTrapMaximumPixelBrightnessToDrain.Value; + Settings.Default.PixelEditorAddPixelColor = btnPixelEditorAddPixelColor.BackColor; + Settings.Default.PixelEditorRemovePixelColor = btnPixelEditorRemovePixelColor.BackColor; + Settings.Default.PixelEditorSupportColor = btnPixelEditorSupportColor.BackColor; + Settings.Default.PixelEditorDrainHoleColor = btnPixelEditorDrainHoleColor.BackColor; + Settings.Default.Save(); DialogResult = DialogResult.OK; return; diff --git a/UVtools.GUI/Forms/FrmToolPattern.cs b/UVtools.GUI/Forms/FrmToolPattern.cs index 34cc9c1..96b4062 100644 --- a/UVtools.GUI/Forms/FrmToolPattern.cs +++ b/UVtools.GUI/Forms/FrmToolPattern.cs @@ -228,8 +228,8 @@ namespace UVtools.GUI.Forms var insideBounds = btnPattern.Enabled = ValidateBounds(); lbInsideBounds.Text = "Inside Bounds: " + (insideBounds ? "Yes" : "No"); - lbVolumeWidth.Text = $"Volume/Pattern Width: {_operation.SrcRoi.Width} / {_operation.CalculatePatternVolume.Width} / {_operation.ImageWidth}"; - lbVolumeHeight.Text = $"Volume/Pattern Height: {_operation.SrcRoi.Height} / {_operation.CalculatePatternVolume.Height} / {_operation.ImageHeight}"; + lbVolumeWidth.Text = $"Volume/Pattern Width: {_operation.SrcRoi.Width} / {_operation.GetPatternVolume.Width} / {_operation.ImageWidth}"; + lbVolumeHeight.Text = $"Volume/Pattern Height: {_operation.SrcRoi.Height} / {_operation.GetPatternVolume.Height} / {_operation.ImageHeight}"; lbCols.Text = $"Columns: {nmCols.Value} / {_operation.MaxCols}"; lbRows.Text = $"Rows: {nmRows.Value} / {_operation.MaxRows}"; @@ -241,7 +241,7 @@ namespace UVtools.GUI.Forms public bool ValidateBounds() { - var volume = OperationPattern.CalculatePatternVolume; + var volume = OperationPattern.GetPatternVolume; if (volume.Width > _operation.ImageWidth) return false; if (volume.Height > _operation.ImageHeight) return false; diff --git a/UVtools.GUI/FrmMain.Designer.cs b/UVtools.GUI/FrmMain.Designer.cs index b28e316..b306950 100644 --- a/UVtools.GUI/FrmMain.Designer.cs +++ b/UVtools.GUI/FrmMain.Designer.cs @@ -132,6 +132,42 @@ this.tsIsuesRefreshResinTraps = new System.Windows.Forms.ToolStripMenuItem(); this.toolStripSeparator12 = new System.Windows.Forms.ToolStripSeparator(); this.tsIssuesRepair = new System.Windows.Forms.ToolStripButton(); + this.tabPagePixelEditor = new System.Windows.Forms.TabPage(); + this.lvPixelHistory = new System.Windows.Forms.ListView(); + this.columnHeader5 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader1 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader2 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader3 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.tsPixelEditorHistory = new System.Windows.Forms.ToolStrip(); + this.lbPixelHistoryOperations = new System.Windows.Forms.ToolStripLabel(); + this.btnPixelHistoryRemove = new System.Windows.Forms.ToolStripButton(); + this.tabControlPixelEditor = new System.Windows.Forms.TabControl(); + this.tabPage1 = new System.Windows.Forms.TabPage(); + this.label6 = new System.Windows.Forms.Label(); + this.nmPixelEditorBrushSize = new System.Windows.Forms.NumericUpDown(); + this.label3 = new System.Windows.Forms.Label(); + this.panel3 = new System.Windows.Forms.Panel(); + this.label1 = new System.Windows.Forms.Label(); + this.label2 = new System.Windows.Forms.Label(); + this.cbPixelEditorBrushShape = new System.Windows.Forms.ComboBox(); + this.tabPage2 = new System.Windows.Forms.TabPage(); + this.label10 = new System.Windows.Forms.Label(); + this.nmPixelEditorSupportsBaseDiameter = new System.Windows.Forms.NumericUpDown(); + this.label11 = new System.Windows.Forms.Label(); + this.label8 = new System.Windows.Forms.Label(); + this.nmPixelEditorSupportsPillarDiameter = new System.Windows.Forms.NumericUpDown(); + this.label9 = new System.Windows.Forms.Label(); + this.label7 = new System.Windows.Forms.Label(); + this.nmPixelEditorSupportsTipDiameter = new System.Windows.Forms.NumericUpDown(); + this.label5 = new System.Windows.Forms.Label(); + this.panel4 = new System.Windows.Forms.Panel(); + this.label4 = new System.Windows.Forms.Label(); + this.tabPage3 = new System.Windows.Forms.TabPage(); + this.label13 = new System.Windows.Forms.Label(); + this.nmPixelEditorDrainHoleDiameter = new System.Windows.Forms.NumericUpDown(); + this.label14 = new System.Windows.Forms.Label(); + this.panel5 = new System.Windows.Forms.Panel(); + this.label12 = new System.Windows.Forms.Label(); this.imageList16x16 = new System.Windows.Forms.ImageList(this.components); this.tlRight = new System.Windows.Forms.TableLayoutPanel(); this.btnPreviousLayer = new System.Windows.Forms.Button(); @@ -167,6 +203,20 @@ this.tsGCode.SuspendLayout(); this.tabPageIssues.SuspendLayout(); this.tsIssues.SuspendLayout(); + this.tabPagePixelEditor.SuspendLayout(); + this.tsPixelEditorHistory.SuspendLayout(); + this.tabControlPixelEditor.SuspendLayout(); + this.tabPage1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.nmPixelEditorBrushSize)).BeginInit(); + this.panel3.SuspendLayout(); + this.tabPage2.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.nmPixelEditorSupportsBaseDiameter)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.nmPixelEditorSupportsPillarDiameter)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.nmPixelEditorSupportsTipDiameter)).BeginInit(); + this.panel4.SuspendLayout(); + this.tabPage3.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.nmPixelEditorDrainHoleDiameter)).BeginInit(); + this.panel5.SuspendLayout(); this.tlRight.SuspendLayout(); this.panel1.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.tbLayer)).BeginInit(); @@ -478,7 +528,7 @@ this.scCenter.Panel2.Controls.Add(this.pbLayers); this.scCenter.Panel2MinSize = 18; this.scCenter.Size = new System.Drawing.Size(1228, 759); - this.scCenter.SplitterDistance = 730; + this.scCenter.SplitterDistance = 725; this.scCenter.TabIndex = 4; // // pbLayer @@ -490,7 +540,7 @@ this.pbLayer.Name = "pbLayer"; this.pbLayer.PanMode = Cyotek.Windows.Forms.ImageBoxPanMode.Left; this.pbLayer.ShowPixelGrid = true; - this.pbLayer.Size = new System.Drawing.Size(1228, 705); + this.pbLayer.Size = new System.Drawing.Size(1228, 700); this.pbLayer.TabIndex = 7; this.pbLayer.Zoomed += new System.EventHandler<Cyotek.Windows.Forms.ImageBoxZoomEventArgs>(this.pbLayer_Zoomed); this.pbLayer.MouseDoubleClick += new System.Windows.Forms.MouseEventHandler(this.EventMouseDoubleClick); @@ -692,6 +742,7 @@ this.tsLayerImagePixelEdit.Text = "Pixel Edit"; this.tsLayerImagePixelEdit.ToolTipText = "Edit layer image pixels (Righ click to add pixel and SHIFT + Right click to remov" + "e pixel)\r\nRed pixels are removed pixels\r\nGreen pixels are added pixels"; + this.tsLayerImagePixelEdit.Click += new System.EventHandler(this.EventClick); // // toolStripSeparator8 // @@ -725,7 +776,7 @@ this.pbLayers.Dock = System.Windows.Forms.DockStyle.Fill; this.pbLayers.Location = new System.Drawing.Point(0, 0); this.pbLayers.Name = "pbLayers"; - this.pbLayers.Size = new System.Drawing.Size(1228, 25); + this.pbLayers.Size = new System.Drawing.Size(1228, 30); this.pbLayers.Step = 1; this.pbLayers.TabIndex = 6; // @@ -734,6 +785,7 @@ this.tabControlLeft.Controls.Add(this.tbpThumbnailsAndInfo); this.tabControlLeft.Controls.Add(this.tabPageGCode); this.tabControlLeft.Controls.Add(this.tabPageIssues); + this.tabControlLeft.Controls.Add(this.tabPagePixelEditor); this.tabControlLeft.Dock = System.Windows.Forms.DockStyle.Fill; this.tabControlLeft.ImageList = this.imageList16x16; this.tabControlLeft.ItemSize = new System.Drawing.Size(130, 19); @@ -856,7 +908,7 @@ // this.tsThumbnailsExportFile.Image = global::UVtools.GUI.Properties.Resources.file_image_16x16; this.tsThumbnailsExportFile.Name = "tsThumbnailsExportFile"; - this.tsThumbnailsExportFile.Size = new System.Drawing.Size(180, 22); + this.tsThumbnailsExportFile.Size = new System.Drawing.Size(141, 22); this.tsThumbnailsExportFile.Text = "To &File"; this.tsThumbnailsExportFile.Click += new System.EventHandler(this.EventClick); // @@ -864,7 +916,7 @@ // this.tsThumbnailsExportClipboard.Image = global::UVtools.GUI.Properties.Resources.clipboard_16x16; this.tsThumbnailsExportClipboard.Name = "tsThumbnailsExportClipboard"; - this.tsThumbnailsExportClipboard.Size = new System.Drawing.Size(180, 22); + this.tsThumbnailsExportClipboard.Size = new System.Drawing.Size(141, 22); this.tsThumbnailsExportClipboard.Text = "To &Clipboard"; this.tsThumbnailsExportClipboard.Click += new System.EventHandler(this.EventClick); // @@ -1190,6 +1242,451 @@ this.tsIssuesRepair.ToolTipText = "Attempt to repair issues"; this.tsIssuesRepair.Click += new System.EventHandler(this.EventClick); // + // tabPagePixelEditor + // + this.tabPagePixelEditor.Controls.Add(this.lvPixelHistory); + this.tabPagePixelEditor.Controls.Add(this.tsPixelEditorHistory); + this.tabPagePixelEditor.Controls.Add(this.tabControlPixelEditor); + this.tabPagePixelEditor.ImageKey = "pixel-16x16.png"; + this.tabPagePixelEditor.Location = new System.Drawing.Point(4, 23); + this.tabPagePixelEditor.Name = "tabPagePixelEditor"; + this.tabPagePixelEditor.Padding = new System.Windows.Forms.Padding(3); + this.tabPagePixelEditor.Size = new System.Drawing.Size(386, 732); + this.tabPagePixelEditor.TabIndex = 4; + this.tabPagePixelEditor.Text = "Pixel Editor"; + this.tabPagePixelEditor.UseVisualStyleBackColor = true; + // + // lvPixelHistory + // + this.lvPixelHistory.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { + this.columnHeader5, + this.columnHeader1, + this.columnHeader2, + this.columnHeader3}); + this.lvPixelHistory.Dock = System.Windows.Forms.DockStyle.Fill; + this.lvPixelHistory.FullRowSelect = true; + this.lvPixelHistory.GridLines = true; + this.lvPixelHistory.HideSelection = false; + this.lvPixelHistory.Location = new System.Drawing.Point(3, 350); + this.lvPixelHistory.Name = "lvPixelHistory"; + this.lvPixelHistory.Size = new System.Drawing.Size(380, 379); + this.lvPixelHistory.TabIndex = 1; + this.lvPixelHistory.UseCompatibleStateImageBehavior = false; + this.lvPixelHistory.View = System.Windows.Forms.View.Details; + this.lvPixelHistory.ItemActivate += new System.EventHandler(this.EventItemActivate); + this.lvPixelHistory.SelectedIndexChanged += new System.EventHandler(this.EventSelectedIndexChanged); + this.lvPixelHistory.KeyUp += new System.Windows.Forms.KeyEventHandler(this.EventKeyUp); + // + // columnHeader5 + // + this.columnHeader5.Text = "#"; + this.columnHeader5.Width = 50; + // + // columnHeader1 + // + this.columnHeader1.Text = "Operation"; + this.columnHeader1.Width = 100; + // + // columnHeader2 + // + this.columnHeader2.Text = "Layer"; + // + // columnHeader3 + // + this.columnHeader3.Text = "Position"; + this.columnHeader3.Width = 130; + // + // tsPixelEditorHistory + // + this.tsPixelEditorHistory.GripStyle = System.Windows.Forms.ToolStripGripStyle.Hidden; + this.tsPixelEditorHistory.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.lbPixelHistoryOperations, + this.btnPixelHistoryRemove}); + this.tsPixelEditorHistory.Location = new System.Drawing.Point(3, 325); + this.tsPixelEditorHistory.Name = "tsPixelEditorHistory"; + this.tsPixelEditorHistory.Size = new System.Drawing.Size(380, 25); + this.tsPixelEditorHistory.TabIndex = 2; + // + // lbPixelHistoryOperations + // + this.lbPixelHistoryOperations.Alignment = System.Windows.Forms.ToolStripItemAlignment.Right; + this.lbPixelHistoryOperations.Name = "lbPixelHistoryOperations"; + this.lbPixelHistoryOperations.Size = new System.Drawing.Size(77, 22); + this.lbPixelHistoryOperations.Text = "Operations: 0"; + // + // btnPixelHistoryRemove + // + this.btnPixelHistoryRemove.Enabled = false; + this.btnPixelHistoryRemove.Image = global::UVtools.GUI.Properties.Resources.delete_16x16; + this.btnPixelHistoryRemove.ImageTransparentColor = System.Drawing.Color.Magenta; + this.btnPixelHistoryRemove.Name = "btnPixelHistoryRemove"; + this.btnPixelHistoryRemove.Size = new System.Drawing.Size(70, 22); + this.btnPixelHistoryRemove.Text = "Remove"; + this.btnPixelHistoryRemove.ToolTipText = "Remove selected issue when possible\r\nIslands: All pixels are removed (turn black)" + + "\r\nResinTrap: All trap areas are filled with white pixels.\r\nTouchingBounds: No ac" + + "tion, need reslice."; + this.btnPixelHistoryRemove.Click += new System.EventHandler(this.EventClick); + // + // tabControlPixelEditor + // + this.tabControlPixelEditor.Controls.Add(this.tabPage1); + this.tabControlPixelEditor.Controls.Add(this.tabPage2); + this.tabControlPixelEditor.Controls.Add(this.tabPage3); + this.tabControlPixelEditor.Dock = System.Windows.Forms.DockStyle.Top; + this.tabControlPixelEditor.Location = new System.Drawing.Point(3, 3); + this.tabControlPixelEditor.Name = "tabControlPixelEditor"; + this.tabControlPixelEditor.SelectedIndex = 0; + this.tabControlPixelEditor.Size = new System.Drawing.Size(380, 322); + this.tabControlPixelEditor.TabIndex = 0; + // + // tabPage1 + // + this.tabPage1.Controls.Add(this.label6); + this.tabPage1.Controls.Add(this.nmPixelEditorBrushSize); + this.tabPage1.Controls.Add(this.label3); + this.tabPage1.Controls.Add(this.panel3); + this.tabPage1.Controls.Add(this.label2); + this.tabPage1.Controls.Add(this.cbPixelEditorBrushShape); + this.tabPage1.Location = new System.Drawing.Point(4, 27); + this.tabPage1.Name = "tabPage1"; + this.tabPage1.Padding = new System.Windows.Forms.Padding(3); + this.tabPage1.Size = new System.Drawing.Size(372, 291); + this.tabPage1.TabIndex = 0; + this.tabPage1.Text = "Drawing"; + this.tabPage1.UseVisualStyleBackColor = true; + // + // label6 + // + this.label6.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.label6.AutoSize = true; + this.label6.Location = new System.Drawing.Point(343, 101); + this.label6.Name = "label6"; + this.label6.Size = new System.Drawing.Size(23, 18); + this.label6.TabIndex = 6; + this.label6.Text = "px"; + // + // nmPixelEditorBrushSize + // + this.nmPixelEditorBrushSize.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.nmPixelEditorBrushSize.Location = new System.Drawing.Point(108, 98); + this.nmPixelEditorBrushSize.Maximum = new decimal(new int[] { + 200, + 0, + 0, + 0}); + this.nmPixelEditorBrushSize.Minimum = new decimal(new int[] { + 1, + 0, + 0, + 0}); + this.nmPixelEditorBrushSize.Name = "nmPixelEditorBrushSize"; + this.nmPixelEditorBrushSize.Size = new System.Drawing.Size(229, 24); + this.nmPixelEditorBrushSize.TabIndex = 5; + this.nmPixelEditorBrushSize.Value = new decimal(new int[] { + 1, + 0, + 0, + 0}); + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point(16, 101); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(84, 18); + this.label3.TabIndex = 4; + this.label3.Text = "Brush area:"; + // + // panel3 + // + this.panel3.BackColor = System.Drawing.Color.WhiteSmoke; + this.panel3.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.panel3.Controls.Add(this.label1); + this.panel3.Dock = System.Windows.Forms.DockStyle.Top; + this.panel3.Location = new System.Drawing.Point(3, 3); + this.panel3.Name = "panel3"; + this.panel3.Size = new System.Drawing.Size(366, 57); + this.panel3.TabIndex = 3; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(3, 9); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(272, 36); + this.label1.TabIndex = 1; + this.label1.Text = "Right click to add white pixels\r\nShift + Right click to remove white pixels"; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(3, 70); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(95, 18); + this.label2.TabIndex = 2; + this.label2.Text = "Brush shape:"; + // + // cbPixelEditorBrushShape + // + this.cbPixelEditorBrushShape.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.cbPixelEditorBrushShape.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.cbPixelEditorBrushShape.FormattingEnabled = true; + this.cbPixelEditorBrushShape.Location = new System.Drawing.Point(108, 66); + this.cbPixelEditorBrushShape.Name = "cbPixelEditorBrushShape"; + this.cbPixelEditorBrushShape.Size = new System.Drawing.Size(258, 26); + this.cbPixelEditorBrushShape.TabIndex = 0; + this.cbPixelEditorBrushShape.SelectedIndexChanged += new System.EventHandler(this.EventSelectedIndexChanged); + // + // tabPage2 + // + this.tabPage2.Controls.Add(this.label10); + this.tabPage2.Controls.Add(this.nmPixelEditorSupportsBaseDiameter); + this.tabPage2.Controls.Add(this.label11); + this.tabPage2.Controls.Add(this.label8); + this.tabPage2.Controls.Add(this.nmPixelEditorSupportsPillarDiameter); + this.tabPage2.Controls.Add(this.label9); + this.tabPage2.Controls.Add(this.label7); + this.tabPage2.Controls.Add(this.nmPixelEditorSupportsTipDiameter); + this.tabPage2.Controls.Add(this.label5); + this.tabPage2.Controls.Add(this.panel4); + this.tabPage2.Location = new System.Drawing.Point(4, 27); + this.tabPage2.Name = "tabPage2"; + this.tabPage2.Padding = new System.Windows.Forms.Padding(3); + this.tabPage2.Size = new System.Drawing.Size(372, 291); + this.tabPage2.TabIndex = 1; + this.tabPage2.Text = "Supports"; + this.tabPage2.UseVisualStyleBackColor = true; + // + // label10 + // + this.label10.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.label10.AutoSize = true; + this.label10.Location = new System.Drawing.Point(343, 129); + this.label10.Name = "label10"; + this.label10.Size = new System.Drawing.Size(23, 18); + this.label10.TabIndex = 14; + this.label10.Text = "px"; + // + // nmPixelEditorSupportsBaseDiameter + // + this.nmPixelEditorSupportsBaseDiameter.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.nmPixelEditorSupportsBaseDiameter.Location = new System.Drawing.Point(173, 126); + this.nmPixelEditorSupportsBaseDiameter.Maximum = new decimal(new int[] { + 200, + 0, + 0, + 0}); + this.nmPixelEditorSupportsBaseDiameter.Minimum = new decimal(new int[] { + 25, + 0, + 0, + 0}); + this.nmPixelEditorSupportsBaseDiameter.Name = "nmPixelEditorSupportsBaseDiameter"; + this.nmPixelEditorSupportsBaseDiameter.Size = new System.Drawing.Size(164, 24); + this.nmPixelEditorSupportsBaseDiameter.TabIndex = 13; + this.nmPixelEditorSupportsBaseDiameter.Value = new decimal(new int[] { + 60, + 0, + 0, + 0}); + // + // label11 + // + this.label11.AutoSize = true; + this.label11.Location = new System.Drawing.Point(6, 128); + this.label11.Name = "label11"; + this.label11.Size = new System.Drawing.Size(161, 18); + this.label11.TabIndex = 12; + this.label11.Text = "Support base diameter:"; + // + // label8 + // + this.label8.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.label8.AutoSize = true; + this.label8.Location = new System.Drawing.Point(343, 99); + this.label8.Name = "label8"; + this.label8.Size = new System.Drawing.Size(23, 18); + this.label8.TabIndex = 11; + this.label8.Text = "px"; + // + // nmPixelEditorSupportsPillarDiameter + // + this.nmPixelEditorSupportsPillarDiameter.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.nmPixelEditorSupportsPillarDiameter.Location = new System.Drawing.Point(173, 96); + this.nmPixelEditorSupportsPillarDiameter.Maximum = new decimal(new int[] { + 200, + 0, + 0, + 0}); + this.nmPixelEditorSupportsPillarDiameter.Minimum = new decimal(new int[] { + 15, + 0, + 0, + 0}); + this.nmPixelEditorSupportsPillarDiameter.Name = "nmPixelEditorSupportsPillarDiameter"; + this.nmPixelEditorSupportsPillarDiameter.Size = new System.Drawing.Size(164, 24); + this.nmPixelEditorSupportsPillarDiameter.TabIndex = 10; + this.nmPixelEditorSupportsPillarDiameter.Value = new decimal(new int[] { + 32, + 0, + 0, + 0}); + // + // label9 + // + this.label9.AutoSize = true; + this.label9.Location = new System.Drawing.Point(6, 98); + this.label9.Name = "label9"; + this.label9.Size = new System.Drawing.Size(159, 18); + this.label9.TabIndex = 9; + this.label9.Text = "Support pillar diameter:"; + // + // label7 + // + this.label7.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.label7.AutoSize = true; + this.label7.Location = new System.Drawing.Point(343, 69); + this.label7.Name = "label7"; + this.label7.Size = new System.Drawing.Size(23, 18); + this.label7.TabIndex = 8; + this.label7.Text = "px"; + // + // nmPixelEditorSupportsTipDiameter + // + this.nmPixelEditorSupportsTipDiameter.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.nmPixelEditorSupportsTipDiameter.Location = new System.Drawing.Point(173, 66); + this.nmPixelEditorSupportsTipDiameter.Maximum = new decimal(new int[] { + 200, + 0, + 0, + 0}); + this.nmPixelEditorSupportsTipDiameter.Minimum = new decimal(new int[] { + 7, + 0, + 0, + 0}); + this.nmPixelEditorSupportsTipDiameter.Name = "nmPixelEditorSupportsTipDiameter"; + this.nmPixelEditorSupportsTipDiameter.Size = new System.Drawing.Size(164, 24); + this.nmPixelEditorSupportsTipDiameter.TabIndex = 7; + this.nmPixelEditorSupportsTipDiameter.Value = new decimal(new int[] { + 19, + 0, + 0, + 0}); + // + // label5 + // + this.label5.AutoSize = true; + this.label5.Location = new System.Drawing.Point(6, 68); + this.label5.Name = "label5"; + this.label5.Size = new System.Drawing.Size(144, 18); + this.label5.TabIndex = 6; + this.label5.Text = "Support tip diameter:"; + // + // panel4 + // + this.panel4.BackColor = System.Drawing.Color.WhiteSmoke; + this.panel4.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.panel4.Controls.Add(this.label4); + this.panel4.Dock = System.Windows.Forms.DockStyle.Top; + this.panel4.Location = new System.Drawing.Point(3, 3); + this.panel4.Name = "panel4"; + this.panel4.Size = new System.Drawing.Size(366, 57); + this.panel4.TabIndex = 4; + // + // label4 + // + this.label4.AutoSize = true; + this.label4.Location = new System.Drawing.Point(3, 9); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(344, 36); + this.label4.TabIndex = 1; + this.label4.Text = "Right click under a island to add a primitive support.\r\nNote: This operation can\'" + + "t be previewed."; + // + // tabPage3 + // + this.tabPage3.Controls.Add(this.label13); + this.tabPage3.Controls.Add(this.nmPixelEditorDrainHoleDiameter); + this.tabPage3.Controls.Add(this.label14); + this.tabPage3.Controls.Add(this.panel5); + this.tabPage3.Location = new System.Drawing.Point(4, 27); + this.tabPage3.Name = "tabPage3"; + this.tabPage3.Padding = new System.Windows.Forms.Padding(3); + this.tabPage3.Size = new System.Drawing.Size(372, 291); + this.tabPage3.TabIndex = 2; + this.tabPage3.Text = "Drain Holes"; + this.tabPage3.UseVisualStyleBackColor = true; + // + // label13 + // + this.label13.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.label13.AutoSize = true; + this.label13.Location = new System.Drawing.Point(341, 69); + this.label13.Name = "label13"; + this.label13.Size = new System.Drawing.Size(23, 18); + this.label13.TabIndex = 14; + this.label13.Text = "px"; + // + // nmPixelEditorDrainHoleDiameter + // + this.nmPixelEditorDrainHoleDiameter.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.nmPixelEditorDrainHoleDiameter.Location = new System.Drawing.Point(150, 66); + this.nmPixelEditorDrainHoleDiameter.Maximum = new decimal(new int[] { + 200, + 0, + 0, + 0}); + this.nmPixelEditorDrainHoleDiameter.Minimum = new decimal(new int[] { + 20, + 0, + 0, + 0}); + this.nmPixelEditorDrainHoleDiameter.Name = "nmPixelEditorDrainHoleDiameter"; + this.nmPixelEditorDrainHoleDiameter.Size = new System.Drawing.Size(185, 24); + this.nmPixelEditorDrainHoleDiameter.TabIndex = 13; + this.nmPixelEditorDrainHoleDiameter.Value = new decimal(new int[] { + 50, + 0, + 0, + 0}); + // + // label14 + // + this.label14.AutoSize = true; + this.label14.Location = new System.Drawing.Point(4, 68); + this.label14.Name = "label14"; + this.label14.Size = new System.Drawing.Size(140, 18); + this.label14.TabIndex = 12; + this.label14.Text = "Drain hole diameter:"; + // + // panel5 + // + this.panel5.BackColor = System.Drawing.Color.WhiteSmoke; + this.panel5.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.panel5.Controls.Add(this.label12); + this.panel5.Dock = System.Windows.Forms.DockStyle.Top; + this.panel5.Location = new System.Drawing.Point(3, 3); + this.panel5.Name = "panel5"; + this.panel5.Size = new System.Drawing.Size(366, 57); + this.panel5.TabIndex = 5; + // + // label12 + // + this.label12.AutoSize = true; + this.label12.Location = new System.Drawing.Point(3, 9); + this.label12.Name = "label12"; + this.label12.Size = new System.Drawing.Size(271, 36); + this.label12.TabIndex = 1; + this.label12.Text = "Right click to add a vertical drain hole.\r\nNote: This operation can\'t be previewe" + + "d."; + // // imageList16x16 // this.imageList16x16.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("imageList16x16.ImageStream"))); @@ -1198,6 +1695,7 @@ this.imageList16x16.Images.SetKeyName(1, "PhotoInfo-16x16.png"); this.imageList16x16.Images.SetKeyName(2, "GCode-16x16.png"); this.imageList16x16.Images.SetKeyName(3, "warning-16x16.png"); + this.imageList16x16.Images.SetKeyName(4, "pixel-16x16.png"); // // tlRight // @@ -1274,13 +1772,13 @@ this.panel1.Size = new System.Drawing.Size(138, 557); this.panel1.TabIndex = 13; // - // lbLayerActual + // lbActualLayer // this.lbActualLayer.AutoSize = true; this.lbActualLayer.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D; this.lbActualLayer.Location = new System.Drawing.Point(3, 248); this.lbActualLayer.Name = "lbActualLayer"; - this.lbActualLayer.Size = new System.Drawing.Size(15, 15); + this.lbActualLayer.Size = new System.Drawing.Size(18, 20); this.lbActualLayer.TabIndex = 9; this.lbActualLayer.Text = "?"; // @@ -1373,13 +1871,13 @@ // FrmMain // this.AllowDrop = true; - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 18F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.ClientSize = new System.Drawing.Size(1784, 811); this.Controls.Add(this.mainTable); this.Controls.Add(this.statusBar); this.Controls.Add(this.menu); - this.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.Font = new System.Drawing.Font("Microsoft Sans Serif", 11.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); this.KeyPreview = true; this.MainMenuStrip = this.menu; @@ -1417,6 +1915,28 @@ this.tabPageIssues.PerformLayout(); this.tsIssues.ResumeLayout(false); this.tsIssues.PerformLayout(); + this.tabPagePixelEditor.ResumeLayout(false); + this.tabPagePixelEditor.PerformLayout(); + this.tsPixelEditorHistory.ResumeLayout(false); + this.tsPixelEditorHistory.PerformLayout(); + this.tabControlPixelEditor.ResumeLayout(false); + this.tabPage1.ResumeLayout(false); + this.tabPage1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.nmPixelEditorBrushSize)).EndInit(); + this.panel3.ResumeLayout(false); + this.panel3.PerformLayout(); + this.tabPage2.ResumeLayout(false); + this.tabPage2.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.nmPixelEditorSupportsBaseDiameter)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.nmPixelEditorSupportsPillarDiameter)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.nmPixelEditorSupportsTipDiameter)).EndInit(); + this.panel4.ResumeLayout(false); + this.panel4.PerformLayout(); + this.tabPage3.ResumeLayout(false); + this.tabPage3.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.nmPixelEditorDrainHoleDiameter)).EndInit(); + this.panel5.ResumeLayout(false); + this.panel5.PerformLayout(); this.tlRight.ResumeLayout(false); this.panel1.ResumeLayout(false); this.panel1.PerformLayout(); @@ -1546,6 +2066,42 @@ private System.Windows.Forms.ToolStripSplitButton tsThumbnailsExport; private System.Windows.Forms.ToolStripMenuItem tsThumbnailsExportFile; private System.Windows.Forms.ToolStripMenuItem tsThumbnailsExportClipboard; + private System.Windows.Forms.TabPage tabPagePixelEditor; + private System.Windows.Forms.TabControl tabControlPixelEditor; + private System.Windows.Forms.TabPage tabPage1; + private System.Windows.Forms.TabPage tabPage2; + private System.Windows.Forms.ListView lvPixelHistory; + private System.Windows.Forms.ToolStrip tsPixelEditorHistory; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.ComboBox cbPixelEditorBrushShape; + private System.Windows.Forms.Panel panel3; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.NumericUpDown nmPixelEditorBrushSize; + private System.Windows.Forms.ColumnHeader columnHeader5; + private System.Windows.Forms.ColumnHeader columnHeader1; + private System.Windows.Forms.ColumnHeader columnHeader2; + private System.Windows.Forms.ColumnHeader columnHeader3; + private System.Windows.Forms.ToolStripLabel lbPixelHistoryOperations; + private System.Windows.Forms.Panel panel4; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.NumericUpDown nmPixelEditorSupportsTipDiameter; + private System.Windows.Forms.Label label5; + private System.Windows.Forms.Label label6; + private System.Windows.Forms.Label label7; + private System.Windows.Forms.Label label8; + private System.Windows.Forms.NumericUpDown nmPixelEditorSupportsPillarDiameter; + private System.Windows.Forms.Label label9; + private System.Windows.Forms.Label label10; + private System.Windows.Forms.NumericUpDown nmPixelEditorSupportsBaseDiameter; + private System.Windows.Forms.Label label11; + private System.Windows.Forms.TabPage tabPage3; + private System.Windows.Forms.Panel panel5; + private System.Windows.Forms.Label label12; + private System.Windows.Forms.Label label13; + private System.Windows.Forms.NumericUpDown nmPixelEditorDrainHoleDiameter; + private System.Windows.Forms.Label label14; + private System.Windows.Forms.ToolStripButton btnPixelHistoryRemove; } } diff --git a/UVtools.GUI/FrmMain.cs b/UVtools.GUI/FrmMain.cs index c2e9dd9..cd3b2cb 100644 --- a/UVtools.GUI/FrmMain.cs +++ b/UVtools.GUI/FrmMain.cs @@ -10,6 +10,7 @@ using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Drawing; +using System.Drawing.Drawing2D; using System.IO; using System.Net; using System.Reflection; @@ -24,6 +25,7 @@ using UVtools.Core; using UVtools.Core.Extensions; using UVtools.Core.FileFormats; using UVtools.Core.Operations; +using UVtools.Core.PixelEditor; using UVtools.GUI.Forms; using UVtools.GUI.Properties; @@ -57,7 +59,14 @@ namespace UVtools.GUI {LayerManager.Mutate.Solidify, new Mutation(LayerManager.Mutate.Solidify, null, "Solidifies the selected layers, closes all inner holes.\n" + "Warning: All surrounded holes are filled, no exceptions! Make sure you don't require any of holes in layer path.", - Properties.Resources.mutation_solidify + Resources.mutation_solidify + )}, + {LayerManager.Mutate.PixelDimming, new Mutation(LayerManager.Mutate.PixelDimming, "Pixel Dimming", + "Dims pixels in a chosen pattern over white pixels neighborhood. The selected pattern will be repeated over the image width and height as a mask. Benefits are:\n" + + "1) Reduce layer expansion in big masses\n" + + "2) Reduce cross layer exposure\n" + + "3) Extend pixels life\n" + + "NOTE: Run only this tool after all repairs and other transformations" )}, {LayerManager.Mutate.Erode, new Mutation(LayerManager.Mutate.Erode, null, "The basic idea of erosion is just like soil erosion only, it erodes away the boundaries of foreground object (Always try to keep foreground in white). " + @@ -129,6 +138,10 @@ namespace UVtools.GUI public bool IsChagingLayer { get; set; } + public PixelHistory PixelHistory { get; } = new PixelHistory(); + + public uint SavesCount { get; set; } = 0; + #endregion #region Constructors @@ -183,6 +196,14 @@ namespace UVtools.GUI lvIssues.Groups.Add(group); } + foreach (PixelDrawing.BrushShapeType brushShape in (PixelDrawing.BrushShapeType[])Enum.GetValues( + typeof(PixelDrawing.BrushShapeType))) + { + cbPixelEditorBrushShape.Items.Add(brushShape); + } + + cbPixelEditorBrushShape.SelectedIndex = 0; + tbLayer.MouseWheel += TbLayerOnMouseWheel; if (Settings.Default.CheckForUpdatesOnStartup) @@ -362,7 +383,8 @@ namespace UVtools.GUI openFile.CheckFileExists = true; openFile.Filter = FileFormat.AllFileFilters; - openFile.FilterIndex = Settings.Default.DefaultOpenFileExtension+1; + openFile.FilterIndex = Settings.Default.DefaultOpenFileExtension + 1; + openFile.InitialDirectory = Settings.Default.FileOpenDefaultDirectory; if (openFile.ShowDialog() == DialogResult.OK) { try @@ -387,6 +409,7 @@ namespace UVtools.GUI openFile.CheckFileExists = true; openFile.Filter = FileFormat.AllFileFilters; openFile.FilterIndex = Settings.Default.DefaultOpenFileExtension + 1; + openFile.InitialDirectory = Settings.Default.FileOpenDefaultDirectory; if (openFile.ShowDialog() == DialogResult.OK) { Program.NewInstance(openFile.FileName); @@ -404,6 +427,15 @@ namespace UVtools.GUI if (ReferenceEquals(sender, menuFileSave)) { + if (SavesCount == 0 && Settings.Default.FileSavePromptOverwrite) + { + if (MessageBox.Show( + "This action will overwrite the input file, if it's the original is best practice to make a copy first (Save As) and work from that copy instead.\n" + + "Do you want to continue and overwrite the file?", "Overwrite input file?", + MessageBoxButtons.YesNo, MessageBoxIcon.Question) != DialogResult.Yes) return; + } + + DisableGUI(); FrmLoading.SetDescription($"Saving {Path.GetFileName(SlicerFile.FileFullPath)}"); @@ -438,8 +470,10 @@ namespace UVtools.GUI FrmLoading.ShowDialog(); + SavesCount++; menuFileSave.Enabled = menuFileSaveAs.Enabled = false; + return; } @@ -450,8 +484,11 @@ namespace UVtools.GUI var ext = Path.GetExtension(SlicerFile.FileFullPath); dialog.Filter = $"{ext.Remove(0, 1)} files (*{ext})|*{ext}"; dialog.AddExtension = true; + dialog.InitialDirectory = string.IsNullOrEmpty(Settings.Default.FileSaveDefaultDirectory) + ? Path.GetDirectoryName(SlicerFile.FileFullPath) + : Settings.Default.FileSaveDefaultDirectory; dialog.FileName = - $"{Path.GetFileNameWithoutExtension(SlicerFile.FileFullPath)}_copy"; + $"{Settings.Default.FileSaveNamePreffix}{Path.GetFileNameWithoutExtension(SlicerFile.FileFullPath)}{Settings.Default.FileSaveNameSuffix}"; if (dialog.ShowDialog() == DialogResult.OK) { DisableGUI(); @@ -488,6 +525,7 @@ namespace UVtools.GUI FrmLoading.ShowDialog(); + SavesCount++; menuFileSave.Enabled = menuFileSaveAs.Enabled = false; UpdateTitle(); @@ -521,6 +559,7 @@ namespace UVtools.GUI { if (frmSettings.ShowDialog() != DialogResult.OK) return; } + return; } @@ -546,7 +585,9 @@ namespace UVtools.GUI using (FolderBrowserDialog folder = new FolderBrowserDialog()) { string fileNameNoExt = Path.GetFileNameWithoutExtension(SlicerFile.FileFullPath); - folder.SelectedPath = Path.GetDirectoryName(SlicerFile.FileFullPath); + folder.SelectedPath = string.IsNullOrEmpty(Settings.Default.FileExtractDefaultDirectory) + ? Path.GetDirectoryName(SlicerFile.FileFullPath) + : Settings.Default.FileExtractDefaultDirectory; folder.Description = $"A \"{fileNameNoExt}\" folder will be created on your selected folder to dump the content."; if (folder.ShowDialog() == DialogResult.OK) @@ -565,11 +606,12 @@ namespace UVtools.GUI } catch (OperationCanceledException) { - + } finally { - Invoke((MethodInvoker)delegate { + Invoke((MethodInvoker) delegate + { // Running on the UI thread EnableGUI(true); }); @@ -587,7 +629,9 @@ namespace UVtools.GUI "Extraction completed", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) { - using (Process.Start(finalPath)){} + using (Process.Start(finalPath)) + { + } } } catch (Exception exception) @@ -666,7 +710,8 @@ namespace UVtools.GUI if (repairResinTraps && ReferenceEquals(Issues, null)) { - ComputeIssues(new IslandDetectionConfiguration {Enabled = false}); // Ignore islands as we dont require it + ComputeIssues(new IslandDetectionConfiguration + {Enabled = false}); // Ignore islands as we dont require it } DisableGUI(); @@ -677,7 +722,8 @@ namespace UVtools.GUI try { SlicerFile.LayerManager.RepairLayers(layerStart, layerEnd, closingIterations, - openingIterations, repairIslands, repairResinTraps, Issues, FrmLoading.RestartProgress()); + openingIterations, repairIslands, repairResinTraps, Issues, + FrmLoading.RestartProgress()); } catch (OperationCanceledException) { @@ -698,10 +744,10 @@ namespace UVtools.GUI }); var loadingResult = FrmLoading.ShowDialog(); - /*if (loadingResult != DialogResult.OK) - { - return; - }*/ + /*if (loadingResult != DialogResult.OK) + { + return; + }*/ ShowLayer(); @@ -715,7 +761,8 @@ namespace UVtools.GUI if (ReferenceEquals(sender, menuToolsPattern)) { - using (var frm = new FrmToolPattern(SlicerFile.LayerManager.BoundingRectangle, (uint) ActualLayerImage.Width, (uint) ActualLayerImage.Height)) + using (var frm = new FrmToolPattern(SlicerFile.LayerManager.BoundingRectangle, + (uint) ActualLayerImage.Width, (uint) ActualLayerImage.Height)) { if (frm.ShowDialog() != DialogResult.OK) return; @@ -726,7 +773,8 @@ namespace UVtools.GUI { try { - SlicerFile.LayerManager.ToolPattern(frm.LayerRangeStart, frm.LayerRangeEnd, frm.OperationPattern, FrmLoading.RestartProgress()); + SlicerFile.LayerManager.ToolPattern(frm.LayerRangeStart, frm.LayerRangeEnd, + frm.OperationPattern, FrmLoading.RestartProgress()); } catch (OperationCanceledException) { @@ -738,7 +786,7 @@ namespace UVtools.GUI } finally { - Invoke((MethodInvoker)delegate + Invoke((MethodInvoker) delegate { // Running on the UI thread EnableGUI(true); @@ -755,6 +803,7 @@ namespace UVtools.GUI } + return; } @@ -767,7 +816,10 @@ namespace UVtools.GUI if (ReferenceEquals(sender, menuHelpWebsite)) { - using (Process.Start(About.Website)){} + using (Process.Start(About.Website)) + { + } + return; } @@ -778,13 +830,17 @@ namespace UVtools.GUI "If you're happy to contribute for a better program and for my work i will appreciate the tip.\n" + "A browser window will be open and forward to my paypal address after you click 'OK'.\nHappy Printing!", "Donation", MessageBoxButtons.OK, MessageBoxIcon.Information); - using (Process.Start(About.Donate)){} + using (Process.Start(About.Donate)) + { + } + return; } if (ReferenceEquals(sender, menuHelpInstallPrinters)) { - var PEFolder = $"{Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)}{Path.DirectorySeparatorChar}{Path.DirectorySeparatorChar}PrusaSlicer"; + var PEFolder = + $"{Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)}{Path.DirectorySeparatorChar}{Path.DirectorySeparatorChar}PrusaSlicer"; if (!Directory.Exists(PEFolder)) { var result = MessageBox.Show( @@ -798,14 +854,15 @@ namespace UVtools.GUI { case DialogResult.OK: using (Process.Start("https://www.prusa3d.com/prusaslicer/")) - { } + { + } return; default: return; } } - + using (FrmInstallPEProfiles form = new FrmInstallPEProfiles()) { form.ShowDialog(); @@ -819,13 +876,15 @@ namespace UVtools.GUI { try { - using (Process.Start(menuNewVersion.Tag.ToString())) { } + using (Process.Start(menuNewVersion.Tag.ToString())) + { + } } catch (Exception exception) { Debug.WriteLine(exception); } - + return; } @@ -914,6 +973,7 @@ namespace UVtools.GUI SlicerFile.Thumbnails[i].Save(dialog.FileName); } } + return; } @@ -958,7 +1018,9 @@ namespace UVtools.GUI "Properties save completed", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) { - using (Process.Start(dialog.FileName)){} + using (Process.Start(dialog.FileName)) + { + } } } @@ -990,7 +1052,9 @@ namespace UVtools.GUI "GCode save completed", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) { - using (Process.Start(dialog.FileName)){} + using (Process.Start(dialog.FileName)) + { + } } } @@ -1032,7 +1096,7 @@ namespace UVtools.GUI "Remove Issues?", MessageBoxButtons.YesNo, MessageBoxIcon.Question) != DialogResult.Yes) return; - Dictionary<uint, List<LayerIssue>> processIssues = new Dictionary<uint, List<LayerIssue>>(); + Dictionary<uint, List<LayerIssue>> processIssues = new Dictionary<uint, List<LayerIssue>>(); foreach (ListViewItem item in lvIssues.SelectedItems) { @@ -1109,7 +1173,8 @@ namespace UVtools.GUI } finally { - Invoke((MethodInvoker)delegate { + Invoke((MethodInvoker) delegate + { // Running on the UI thread EnableGUI(true); }); @@ -1134,6 +1199,7 @@ namespace UVtools.GUI item.Remove(); TotalIssues--; } + lvIssues.EndUpdate(); ShowLayer(); @@ -1160,6 +1226,23 @@ namespace UVtools.GUI return; } + if (ReferenceEquals(sender, btnPixelHistoryRemove)) + { + if (!btnPixelHistoryRemove.Enabled) return; + lvPixelHistory.BeginUpdate(); + foreach (ListViewItem item in lvPixelHistory.SelectedItems) + { + PixelOperation operation = item.Tag as PixelOperation; + item.Remove(); + PixelHistory.Items.Remove(operation); + } + lvPixelHistory.EndUpdate(); + lbPixelHistoryOperations.Text = $"Operations: {PixelHistory.Count}"; + + ShowLayer(); + } + + /************************ * Layer Menu * ***********************/ @@ -1187,6 +1270,70 @@ namespace UVtools.GUI return; } + if (ReferenceEquals(sender, tsLayerImagePixelEdit)) + { + if (tsLayerImagePixelEdit.Checked) + { + tabControlLeft.TabPages.Add(tabPagePixelEditor); + tabControlLeft.SelectedTab = tabPagePixelEditor; + } + else + { + if (PixelHistory.Count > 0) + { + var result = + MessageBox.Show( + "There are unsaved changes on image editor, do you want to apply modifications?", + "Unsaved changes on image editor", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question); + + if (result == DialogResult.Cancel) + { + tsLayerImagePixelEdit.Checked = true; + return; + } + if (result == DialogResult.Yes) + { + DisableGUI(); + FrmLoading.SetDescription($"Drawing pixels"); + + Task task = Task.Factory.StartNew(() => + { + try + { + SlicerFile.LayerManager.DrawModifications(PixelHistory, FrmLoading.RestartProgress()); + } + catch (OperationCanceledException) + { + + } + catch (Exception ex) + { + MessageBox.Show($"{ex.Message}", "Drawing was unsuccessful!", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + finally + { + Invoke((MethodInvoker)delegate { + // Running on the UI thread + EnableGUI(true); + }); + } + + return false; + }); + + FrmLoading.ShowDialog(); + } + + lvPixelHistory.Items.Clear(); + PixelHistory.Clear(); + ShowLayer(); + } + + tabControlLeft.TabPages.Remove(tabPagePixelEditor); + } + return; + } + if (ReferenceEquals(sender, tsLayerImageExport)) { tsLayerImageExport.ShowDropDown(); @@ -1285,6 +1432,7 @@ namespace UVtools.GUI { dialog.FileName = Path.GetFileNameWithoutExtension(SlicerFile.FileFullPath); dialog.Filter = fileFormat.FileFilter; + dialog.InitialDirectory = string.IsNullOrEmpty(Settings.Default.FileConvertDefaultDirectory) ? Path.GetDirectoryName(SlicerFile.FileFullPath) : Settings.Default.FileConvertDefaultDirectory; //using (FileFormat instance = (FileFormat)Activator.CreateInstance(type)) //using (CbddlpFile file = new CbddlpFile()) @@ -1362,16 +1510,21 @@ namespace UVtools.GUI if (!tsLayerImagePixelEdit.Checked || (e.Button & MouseButtons.Right) == 0) return; if (!pbLayer.IsPointInImage(e.Location)) return; var location = pbLayer.PointToImage(e.Location); + _lastPixelMouseLocation = Point.Empty; - DrawPixel(Control.ModifierKeys != Keys.Shift, location); + DrawPixel(ModifierKeys != Keys.Shift, location); - SlicerFile[ActualLayer].LayerMat = ActualLayerImage; + //SlicerFile[ActualLayer].LayerMat = ActualLayerImage; + RefreshPixelHistory(); } + private Point _lastPixelMouseLocation = Point.Empty; private void pbLayer_MouseMove(object sender, MouseEventArgs e) { if (!pbLayer.IsPointInImage(e.Location)) return; var location = pbLayer.PointToImage(e.Location); + if (_lastPixelMouseLocation == e.Location) return; + _lastPixelMouseLocation = e.Location; int x = location.X; int y = location.Y; @@ -1384,10 +1537,11 @@ namespace UVtools.GUI tsLayerImageMouseLocation.Text = $"{{X={x}, Y={y}, B={ActualLayerImage.GetByte(x, y)}}}"; - if (!tsLayerImagePixelEdit.Checked || (e.Button & MouseButtons.Right) == 0) return; + if (tabControlPixelEditor.SelectedIndex != (int) PixelOperation.PixelOperationType.Drawing) return; + if (!tsLayerImagePixelEdit.Checked || (e.Button & MouseButtons.Right) == 0) return; if (!pbLayer.IsPointInImage(e.Location)) return; - if (Control.ModifierKeys == Keys.Shift) + if (ModifierKeys == Keys.Shift) { DrawPixel(false, location); return; @@ -1470,7 +1624,8 @@ namespace UVtools.GUI /// </summary> void Clear() { - Text = $"{FrmAbout.AssemblyTitle} Version: {FrmAbout.AssemblyVersion}"; + UpdateTitle(); + SlicerFile?.Dispose(); SlicerFile = null; ActualLayer = 0; @@ -1489,6 +1644,9 @@ namespace UVtools.GUI lvIssues.EndUpdate(); UpdateIssuesInfo(); + PixelHistory.Clear(); + RefreshPixelHistory(); + lbMaxLayer.Text = lbActualLayer.Text = lbInitialLayer.Text = "???"; @@ -1554,6 +1712,8 @@ namespace UVtools.GUI btnLastLayer.Enabled = btnFindLayer.Enabled = + tsLayerImagePixelEdit.Checked = + false; tsThumbnailsCount.Text = "0/0"; @@ -1561,6 +1721,7 @@ namespace UVtools.GUI tabControlLeft.TabPages.Remove(tabPageGCode); tabControlLeft.TabPages.Remove(tabPageIssues); + tabControlLeft.TabPages.Remove(tabPagePixelEditor); tabControlLeft.SelectedIndex = 0; } @@ -1646,6 +1807,7 @@ namespace UVtools.GUI var loadingResult = FrmLoading.ShowDialog(); if (loadingResult != DialogResult.OK) { + SlicerFile = null; return; } @@ -1778,12 +1940,18 @@ namespace UVtools.GUI } } - void UpdateTitle() + private void UpdateTitle() { - Text = $"{FrmAbout.AssemblyTitle} File: {Path.GetFileName(SlicerFile.FileFullPath)} ({FrmLoading.StopWatch.ElapsedMilliseconds}ms) Version: {FrmAbout.AssemblyVersion}"; + Text = ReferenceEquals(SlicerFile, null) ? + $"{FrmAbout.AssemblyTitle} Version: {FrmAbout.AssemblyVersion}" : + $"{FrmAbout.AssemblyTitle} File: {Path.GetFileName(SlicerFile.FileFullPath)} ({FrmLoading.StopWatch.ElapsedMilliseconds}ms) Version: {FrmAbout.AssemblyVersion}"; + +#if DEBUG + Text += " [DEBUG]"; +#endif } - - void RefreshInfo() + + private void RefreshInfo() { menuEdit.DropDownItems.Clear(); @@ -1796,7 +1964,7 @@ namespace UVtools.GUI Text = $"{modifier.Name} ({SlicerFile.GetValueFromPrintParameterModifier(modifier)}{modifier.ValueUnit})", Tag = modifier, - Image = Properties.Resources.Wrench_16x16, + Image = Resources.Wrench_16x16, }; menuEdit.DropDownItems.Add(item); @@ -2084,6 +2252,50 @@ namespace UVtools.GUI } } + for (var index = 0; index < PixelHistory.Count; index++) + { + if(PixelHistory[index].LayerIndex != ActualLayer) continue; + var operation = PixelHistory[index]; + if (operation.OperationType == PixelOperation.PixelOperationType.Drawing) + { + var operationDrawing = (PixelDrawing)operation; + var color = operationDrawing.IsAdd + ? Settings.Default.PixelEditorAddPixelColor + : Settings.Default.PixelEditorRemovePixelColor; + + + if (operationDrawing.Rectangle.Size.GetArea() == 1) + { + ActualLayerImageBgr.SetByte(operation.Location.X, operation.Location.Y, new []{ color.B, color.G, color.R }); + continue; + } + + switch (operationDrawing.BrushShape) + { + case PixelDrawing.BrushShapeType.Rectangle: + CvInvoke.Rectangle(ActualLayerImageBgr, operationDrawing.Rectangle, new MCvScalar(color.B, color.G, color.R), -1); + break; + case PixelDrawing.BrushShapeType.Circle: + CvInvoke.Circle(ActualLayerImageBgr, operation.Location, operationDrawing.BrushSize / 2, new MCvScalar(color.B, color.G, color.R), -1); + break; + default: + throw new ArgumentOutOfRangeException(); + } + } + else if (operation.OperationType == PixelOperation.PixelOperationType.Supports) + { + var operationSupport = (PixelSupport)operation; + var color = Settings.Default.PixelEditorSupportColor; + CvInvoke.Circle(ActualLayerImageBgr, operation.Location, operationSupport.TipDiameter / 2, new MCvScalar(color.B, color.G, color.R), -1); + } + else if (operation.OperationType == PixelOperation.PixelOperationType.DrainHole) + { + var operationDrainHole = (PixelDrainHole)operation; + var color = Settings.Default.PixelEditorDrainHoleColor; + CvInvoke.Circle(ActualLayerImageBgr, operation.Location, operationDrainHole.Diameter / 2, new MCvScalar(color.B, color.G, color.R), -1); + } + } + if (tsLayerImageRotate.Checked) { CvInvoke.Rotate(ActualLayerImageBgr, ActualLayerImageBgr, RotateFlags.Rotate90Clockwise); @@ -2097,31 +2309,6 @@ namespace UVtools.GUI pbLayer.Image.Tag = ActualLayerImageBgr; //Debug.WriteLine(watch.ElapsedMilliseconds); - //UniversalLayer layer = new UniversalLayer(image); - //pbLayer.Image = layer.ToBitmap(image.Width, image.Height); - - - // NEW - /*Stopwatch watch = Stopwatch.StartNew(); - Bitmap bmp; - using (var ms = new MemoryStream(SlicerFile.GetLayer(layerNum))) - { - bmp = new Bitmap(ms); - } - - if (tsLayerImageRotate.Checked) - { - //watch.Restart(); - bmp.RotateFlip(RotateFlipType.Rotate90FlipNone); - //Debug.Write($"/{watch.ElapsedMilliseconds}"); - } - - - - pbLayer.Image = bmp; - Debug.WriteLine(watch.ElapsedMilliseconds); - //pbLayer.Image.Tag = image;*/ - byte percent = (byte)((layerNum + 1) * 100 / SlicerFile.LayerCount); @@ -2178,6 +2365,12 @@ namespace UVtools.GUI return; } + if (ReferenceEquals(sender, lvPixelHistory)) + { + btnPixelHistoryRemove.Enabled = lvPixelHistory.SelectedIndices.Count > 0; + return; + } + if (ReferenceEquals(sender, tabControlLeft)) { if(ReferenceEquals(tabControlLeft.SelectedTab, tabPageIssues)) @@ -2187,6 +2380,21 @@ namespace UVtools.GUI } return; } + + if (ReferenceEquals(sender, cbPixelEditorBrushShape)) + { + if (cbPixelEditorBrushShape.SelectedIndex == (int) PixelDrawing.BrushShapeType.Rectangle) + { + nmPixelEditorBrushSize.Minimum = PixelDrawing.MinRectangleBrush; + return; + } + if (cbPixelEditorBrushShape.SelectedIndex == (int)PixelDrawing.BrushShapeType.Circle) + { + nmPixelEditorBrushSize.Minimum = PixelDrawing.MinCircleBrush; + return; + } + return; + } } private void EventKeyUp(object sender, KeyEventArgs e) @@ -2247,10 +2455,7 @@ namespace UVtools.GUI { if (e.KeyCode == Keys.Escape) { - foreach (ListViewItem item in lvIssues.Items) - { - item.Selected = false; - } + lvIssues.SelectedItems.Clear(); e.Handled = true; return; } @@ -2301,6 +2506,62 @@ namespace UVtools.GUI } return; } + + if (ReferenceEquals(sender, lvPixelHistory)) + { + if (e.KeyCode == Keys.Escape) + { + lvPixelHistory.SelectedItems.Clear(); + e.Handled = true; + return; + } + + if (e.Control && e.KeyCode == Keys.A) + { + foreach (ListViewItem item in lvPixelHistory.Items) + { + item.Selected = true; + } + e.Handled = true; + return; + } + + if (e.KeyCode == Keys.Multiply) + { + foreach (ListViewItem item in lvPixelHistory.Items) + { + item.Selected = !item.Selected; + } + e.Handled = true; + return; + } + + if (e.Control && e.KeyCode == Keys.C) + { + StringBuilder clip = new StringBuilder(); + foreach (ListViewItem item in lvPixelHistory.Items) + { + if (!item.Selected) continue; + if (clip.Length > 0) clip.AppendLine(); + clip.Append($"{item.Text}: {item.SubItems[1].Text} Layer: {item.SubItems[2].Text} X,Y: {{{item.SubItems[3].Text}}}"); + } + + if (clip.Length > 0) + { + Clipboard.SetText(clip.ToString()); + } + e.Handled = true; + return; + } + + if (e.KeyCode == Keys.Delete) + { + btnPixelHistoryRemove.PerformClick(); + e.Handled = true; + return; + } + return; + } } private void EventMouseDown(object sender, MouseEventArgs e) @@ -2350,8 +2611,6 @@ namespace UVtools.GUI } #endregion - - void DrawPixel(bool isAdd, Point location) { //Stopwatch sw = Stopwatch.StartNew(); @@ -2365,37 +2624,111 @@ namespace UVtools.GUI y = ActualLayerImage.Height - 1 - location.X; } - Color color; - byte pixelColor; - //int pixel = ActualLayerImage.GetPixelPos(x, y); - var span = ActualLayerImage.GetSinglePixelSpan<byte>(x, y); + PixelOperation operation = null; + Bitmap bmp = pbLayer.Image as Bitmap; - if (isAdd) + if (tabControlPixelEditor.SelectedIndex == (int) PixelOperation.PixelOperationType.Drawing) { - if (span[0] > 200) return; - color = Color.Green; - pixelColor = 255; + PixelDrawing.BrushShapeType shapeType = + (PixelDrawing.BrushShapeType) cbPixelEditorBrushShape.SelectedIndex; + operation = new PixelDrawing(ActualLayer, new Point(x, y), + shapeType, (ushort) nmPixelEditorBrushSize.Value, isAdd); + + if (PixelHistory.Contains(operation)) return; + + using (var gfx = Graphics.FromImage(bmp)) + { + int shiftPos = (int)nmPixelEditorBrushSize.Value / 2; + gfx.SmoothingMode = SmoothingMode.HighSpeed; + + var color = isAdd ? Settings.Default.PixelEditorAddPixelColor : Settings.Default.PixelEditorRemovePixelColor; + SolidBrush brush = new SolidBrush(color); + + switch (shapeType) + { + case PixelDrawing.BrushShapeType.Rectangle: + gfx.FillRectangle(brush, Math.Max(0, location.X - shiftPos), Math.Max(0, location.Y - shiftPos), (int)nmPixelEditorBrushSize.Value, (int)nmPixelEditorBrushSize.Value); + break; + case PixelDrawing.BrushShapeType.Circle: + gfx.FillEllipse(brush, Math.Max(0, location.X - shiftPos), Math.Max(0, location.Y - shiftPos), (int)nmPixelEditorBrushSize.Value, (int)nmPixelEditorBrushSize.Value); + break; + default: + throw new ArgumentOutOfRangeException(); + } + + } } - else + else if (tabControlPixelEditor.SelectedIndex == (int) PixelOperation.PixelOperationType.Supports) { - if (span[0] == 0) return; - color = Color.DarkRed; - pixelColor = 0; - } + if (ActualLayer == 0) return; + operation = new PixelSupport(ActualLayer, new Point(x, y), + (byte) nmPixelEditorSupportsTipDiameter.Value, (byte)nmPixelEditorSupportsPillarDiameter.Value, (byte)nmPixelEditorSupportsBaseDiameter.Value); + if (PixelHistory.Contains(operation)) return; - //ActualLayerImage.SetByte(pixel, pixelColor);; - span[0] = pixelColor; - Bitmap bmp = pbLayer.Image as Bitmap; - bmp.SetPixel(location.X, location.Y, color); + SolidBrush brush = new SolidBrush(Settings.Default.PixelEditorSupportColor); + using (var gfx = Graphics.FromImage(bmp)) + { + int shiftPos = (int)nmPixelEditorSupportsTipDiameter.Value / 2; + gfx.SmoothingMode = SmoothingMode.HighSpeed; + gfx.FillEllipse(brush, Math.Max(0, location.X - shiftPos), Math.Max(0, location.Y - shiftPos), (int)nmPixelEditorSupportsTipDiameter.Value, (int)nmPixelEditorSupportsTipDiameter.Value); + } + } + else if (tabControlPixelEditor.SelectedIndex == (int)PixelOperation.PixelOperationType.DrainHole) + { + if (ActualLayer == 0) return; + operation = new PixelDrainHole(ActualLayer, new Point(x, y), (byte)nmPixelEditorDrainHoleDiameter.Value); + if (PixelHistory.Contains(operation)) return; + SolidBrush brush = new SolidBrush(Settings.Default.PixelEditorDrainHoleColor); + using (var gfx = Graphics.FromImage(bmp)) + { + int shiftPos = (int)nmPixelEditorDrainHoleDiameter.Value / 2; + gfx.SmoothingMode = SmoothingMode.HighSpeed; + gfx.FillEllipse(brush, Math.Max(0, location.X - shiftPos), Math.Max(0, location.Y - shiftPos), (int)nmPixelEditorDrainHoleDiameter.Value, (int)nmPixelEditorDrainHoleDiameter.Value); + } + } + else + { + throw new NotImplementedException("Missing pixel operation"); + } + + PixelHistory.Add(operation); + pbLayer.Invalidate(); + //pbLayer.Update(); + //pbLayer.Refresh(); menuFileSave.Enabled = menuFileSaveAs.Enabled = true; //sw.Stop(); //Debug.WriteLine(sw.ElapsedMilliseconds); } + public void RefreshPixelHistory() + { + lbPixelHistoryOperations.Text = $"Operations: {PixelHistory.Count}"; + lvPixelHistory.BeginUpdate(); + lvPixelHistory.Items.Clear(); + for (var i = PixelHistory.Count-1; i >= 0; i--) + { + var operation = PixelHistory[i]; + var item = new ListViewItem + { + Text = i.ToString(), + Tag = operation + }; + item.SubItems.Add(operation.OperationType.ToString()); + item.SubItems.Add(operation.LayerIndex.ToString()); + item.SubItems.Add(operation.Location.ToString()); + //item.SubItems.Add(operation.BrushSize.ToString()); + + lvPixelHistory.Items.Add(item); + } + + lvPixelHistory.EndUpdate(); + btnPixelHistoryRemove.Enabled = false; + } + public void MutateLayers(LayerManager.Mutate mutator) @@ -2411,6 +2744,9 @@ namespace UVtools.GUI double x = 0; double y = 0; + Matrix<byte> evenPattern = null; + Matrix<byte> oddPattern = null; + switch (mutator) { case LayerManager.Mutate.Move: @@ -2454,6 +2790,17 @@ namespace UVtools.GUI x = (double) inputBox.Value; } break; + case LayerManager.Mutate.PixelDimming: + using (FrmMutationPixelDimming inputBox = new FrmMutationPixelDimming(Mutations[mutator])) + { + if (inputBox.ShowDialog() != DialogResult.OK) return; + layerStart = inputBox.LayerRangeStart; + layerEnd = inputBox.LayerRangeEnd; + iterationsStart = inputBox.BorderSize; + evenPattern = inputBox.EvenPattern; + oddPattern = inputBox.OddPattern; + } + break; default: using (FrmMutation inputBox = new FrmMutation(Mutations[mutator])) { @@ -2508,6 +2855,9 @@ namespace UVtools.GUI case LayerManager.Mutate.Solidify: SlicerFile.LayerManager.MutateSolidify(layerStart, layerEnd, progress); break; + case LayerManager.Mutate.PixelDimming: + SlicerFile.LayerManager.MutatePixelDimming(layerStart, layerEnd, evenPattern, oddPattern, (ushort) iterationsStart, progress); + break; case LayerManager.Mutate.Erode: SlicerFile.LayerManager.MutateErode(layerStart, layerEnd, (int) iterationsStart, (int) iterationsEnd, fade, progress); break; diff --git a/UVtools.GUI/FrmMain.resx b/UVtools.GUI/FrmMain.resx index 7e07557..977692d 100644 --- a/UVtools.GUI/FrmMain.resx +++ b/UVtools.GUI/FrmMain.resx @@ -138,6 +138,9 @@ <metadata name="tsIssues.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> <value>765, 17</value> </metadata> + <metadata name="tsPixelEditorHistory.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>1155, 17</value> + </metadata> <metadata name="imageList16x16.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> <value>415, 17</value> </metadata> @@ -145,79 +148,83 @@ <value> AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0 - ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAAAo - DgAAAk1TRnQBSQFMAgEBBAEAAdgBBAHYAQQBEAEAARABAAT/ASEBAAj/AUIBTQE2BwABNgMAASgDAAFA - AwABIAMAAQEBAAEgBgABIP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8AZgADUAGjA1IBqQNS - AakDUgGpA1IBqQNSAakDUgGpA1IBqQNSAakDUgGpA1IBqQNSAakDUgGpA1ABo1wAAxUBHQFCAlkB9QFR - Am0B9wNDAXcDWwHIAkIBWQH1AlgBXwHjA0oBjAMKAQ0EAANVAbQDWQHHAy8BSQMAAQEDGwEmAxwBJwMc - AScDHAEnAxwBJwMcAScDHAEnAxwBJwMcAScDHAEnAxwBJwMCAQMEAANSAakwAANSAakQAAMnAToDMAFM - AzABTAMwAUwDMAFMAzABTAMwAUwDMAFMAzABTAMnAToUAAMFAQcDTAGSAVYCWAHBAxUBHQM9AWkBAAHI - AfMB/wEAAZAB5gH/AhYB3AH/AhYB3QH/AksB4wH/AiEB3gH/AhYB3QH/AlgBWwHLAwYBCAMAAf8DAAH/ - A0MBdwMpAT4DAAH/AwAB/wMAAf8DAAH/AwAB/wMAAf8DAAH/AwAB/wMAAf8DAAH/AwAB/wMyAVEEAANS - AakEAANQAZ0DUwGqA1MBqgNTAaoDUwGqA1MBqgNTAaoDUAGdDAADUgGpEAADTgH7AwAB/wMAAf8DAAH/ - AwAB/wMAAf8DAAH/AwAB/wMAAf8DTgH7FAABMAIxAU0BAAHJAfMB/wEAAckB9AH/AVkCYAHrAVsCXgHZ - AQABwAHxAf8BFwEfAd8B/wIZAeAB/wIZAeAB/wJSAekB/wIkAeIB/wIZAeAB/wIZAeAB/wNAAXEDUQGi - A1YBtgMqAUAEAAMQARUDEQEXAxEBFwMRARcDEQEXAxEBFwMRARcDEQEXAxEBFwMRARcDEAEWCAADUgGp - BAADUAGdA1MBqgNTAaoDHwEsHAADUgGpEwAB/wMAAf8DAAH/AwAB/wMAAf8DAAH/AwAB/wMAAf8DAAH/ - AwAB/xQAAwcBCgFZAmcB8gEAAcoB9AH/AQABygH0Af8BAAHKAfQB/wEBAaEB7gH/AhwB4wH/AhwB4wH/ - AhwB4wH/AqkB7wH/AiMB4wH/AhwB4wH/AhwB4wH/AlYBWAG5AwoBDgMRARcDAAEBOAADUgGpMAADUgGp - EwAB/wMAAf8DAAH/AwAB/wMAAf8DAAH/AwAB/wMAAf8DAAH/AwAB/wwAAxUBHQM9AWkDOgFiAVwCYAHU - AQABywH1Af8BAAHLAfUB/wEAAcsB9QH/AQQBoAHwAf8CHwHmAf8CHwHmAf8CHwHmAf8CwgH2Af8CNwHo - Af8CHwHmAf8CHwHmAf8CVwFZAb8DUgH0AwAB/wM+AWwDDgETA0IBdgNDAXcDQwF3A0MBdwNDAXcDQwF3 - A0MBdwNDAXcDQwF3A0MBdwNCAXYDFAEbBAADUgGpAyIBMgNSAakDUgGpA1IBqQNSAakDUgGpA1IBqQNS - AakDUgGpA1IBqQNSAakDIgEyA1IBqRMAAf8DAAH/AwAB/wMAAf8DAAH/AwAB/wMAAf8DAAH/AwAB/wMA - Af8MAAFLAkwBkAEAAcsB9gH/AQABywH2Af8BAAHLAfYB/wEAAcsB9gH/ASkBbgF2AfoDQwF4AyIBMgJL - AYQB+wIiAekB/wIiAekB/wLNAfgB/wJGAe0B/wIiAekB/wIiAekB/wNQAZ4DAAH+AwAB/wNDAXcDHgEr - A1cBxQNZAccDWQHHA1kBxwNZAccDWQHHA1kBxwNZAccDWQHHA1kBxwNYAcYDJgE5BAADUgGpAzQBVQM0 - AVUgAAM0AVUDNAFVA1IBqRMAAf8DAAH/AwAB/wMAAf8DAAH/AwAB/wMAAf8DAAH/AwAB/wMAAf8MAANR - AaABAAHMAfcB/wEAAcwB9wH/AQABzAH3Af8BAAHMAfcB/wNDAXcIAANKAY0CJQHsAf8CJQHsAf8CQQHv - Af8CKQHsAf8CJQHsAf8BIQEyAe0B/wFSAlMBqAMzAVMDPAFnAxQBHDgAA1IBqQM0AVUDNAFVA0YBgANS - AakDUgGpA1IBqQNSAakDUgGpA1IBqQNFAX8DNAFVAzQBVQNSAakTAAH/AwAB/wMAAf8DAAH/AwAB/wMA - Af8DAAH/AwAB/wMAAf8DAAH/DwABAQE/AkABbwE+AWsBcQH4AQABzQH3Af8BAAHNAfcB/wMSARgIAAMB - AQIDRgF+AlIBXQHwAigB7gH/ASgBKQHuAf8CQAGoAf0BRQJGAX4DAwEEAzMBUwM8AWcDFAEcOAADUgGp - AzQBVQM0AVUDPwFuAzIBUBAAAycBOwNEAXwDNAFVAzQBVQNSAakTAAH/AwAB/wMAAf8DAAH/AwAB/wMA - Af8DAAH/AwAB/wMAAf8DAAH/DwABAQE/AkABbwE+AWsBcQH4AQABzgH4Af8BAAHOAfgB/wMSARgQAAMX - ASABAgG8AfcB/wEAAcQB9wH/AUABqAGpAf0BRQJGAX4DAwEEAwAB/gMAAf8DQwF3Ax8BLANXAcUDWQHH - A1kBxwNZAccDWQHHA1kBxwNZAccDWQHHA1kBxwNZAccDWAHGAyYBOQQAA1IBqQM0AVUDNAFVAwUBBwNV - AbUDEQEXA1IBqQMpAT4EAANQAZ8DEQEXAzQBVQM0AVUDUgGpEwAB/wMAAf8DAAH/AwAB/wMAAf8DAAH/ - AwAB/wMAAf8DAAH/AwAB/wwAA1EBoAEAAc4B+AH/AQABzwH5Af8BAAHPAfkB/wEAAc8B+QH/A0MBdxAA - A0QBegEAAc8B+QH/AQABzwH5Af8BAAHPAfkB/wEAAc4B+AH/AVICUwGoA1IB9AMAAf8DPgFsAw4BEwNC - AXUDQwF3A0MBdwNDAXcDQwF3A0MBdwNDAXcDQwF3A0MBdwNDAXcDQwF3AxQBGwQAA1IBqQM0AVUDNAFV - BAADPAFoA1YBvgMjATQDVQG1AxIBGQNRAaAEAAM0AVUDNAFVA1IBqRMAAf8DAAH/AwAB/wMAAf8DAAH/ - AwAB/wMAAf8DAAH/AwAB/wNcAd8MAAFLAkwBkAEAAdAB+gH/AQAB0AH6Af8BAAHQAfoB/wEAAdAB+gH/ - ASkBbgF2AfoDQwF4AxIBGQMTARoDRAF6ASgBfAGHAfsBAAHQAfoB/wEAAdAB+gH/AQAB0AH6Af8BAAHQ - AfoB/wNKAYwDCgEOAxEBFwMAAQE4AANSAakDNAFVAzQBVQMAAQEDLQFGAwoBDgQAAzkBXwNcAc4DKAE8 - BAADNAFVAzQBVQNSAakTAAH/A4IB/wMAAf8DAAH/AwAB/wMAAf8DAAH/AwAB/wNcAd8DFwEgDAADFQEd - Az0BaQM6AWIBXAJgAdQBAAHRAfoB/wEAAdEB+gH/AQAB0AH6Af8BAAHLAfMB/wEAAcsB8wH/AQAB0AH6 - Af8BAAHRAfoB/wEAAdEB+gH/AV0CYQHiAzoBYgM9AWkDFAEcA1EBogNWAbYDKgFABAADEAEVAxEBFwMR - ARcDEQEXAxEBFwMRARcDEQEXAxEBFwMRARcDEQEXAxABFggAA1IBqQM0AVUDNAFVAzMBUwNSAaYDSgGM - BwABAQNHAYMIAAM0AVUDNAFVA1IBqRMAAf8DmQH/A4UB/wMAAf8DAAH/AwAB/wMAAf8DXAHfAxcBIBgA - AwcBCgFZAmcB8gEBAdIB+wH/AQEB0gH7Af8BAQHSAfsB/wEBAdIB+wH/AQEB0gH7Af8BAQHSAfsB/wEB - AdIB+wH/AQEB0gH7Af8BKwF/AYcB+wMRARcLAAH/AwAB/wNDAXcDKQE+AwAB/wMAAf8DAAH/AwAB/wMA - Af8DAAH/AwAB/wMAAf8DAAH/AwAB/wMAAf8DMgFRBAADUgGpAzQBVQM0AVUDEQEXA1ABngMkATYUAAM0 - AVUDNAFVA1IBqRAAA1AB+wMAAf8DAAH/AwAB/wMAAf8DAAH/A1wB3wMXASAcAAEwAjEBTQECAdIB/AH/ - AQIB0gH8Af8BWQJgAesBWwJeAdkBAgHSAfwB/wECAdIB/AH/AVsCYQHhAV0CYQHiAQIB0gH8Af8BAgHS - AfwB/wM4AV4IAANVAbQDWQHHAy8BSQMAAQEDGwEmAxwBJwMcAScDHAEnAxwBJwMcAScDHAEnAxwBJwMc - AScDHAEnAxwBJwMCAQMEAANSAakDIgEyA1IBqQNSAakDUgGpA1IBqQNSAakDUgGpA1IBqQNSAakDUgGp - A1IBqQMiATIDUgGpEAADIAEuAykBPwMpAT8DKQE/AykBPwMpAT8DEQEXIAADBQEHA0wBkgFWAlgBwQMV - AR0DPQFpAQMB0wH8Af8BAwHTAfwB/wFFAkYBfwMQARUDVgGzAUsCTAGPAwQBBkwAA1ABowNSAakDUgGp - A1IBqQNSAakDUgGpA1IBqQNSAakDUgGpA1IBqQNSAakDUgGpA1IBqQNQAaNcAAMVAR0BQgFZAVoB9QFR - Am0B9wMgAS8YAAFCAU0BPgcAAT4DAAEoAwABQAMAASADAAEBAQABAQYAAQEWAAP/gQAC/wGAAQEC/wH8 - AQECAAG/Af0B4AEHAcADAAGgAR0B4AEHAcABAAEQAQEBoQH9AeABBwHAAQABHwH/Ab8B/QHgAQcEAAGA - AQEB4AEHBAABjwHxAeABBwEDAQABHwH/AYABAQHgAQcBAwEAAR8B/wGDAcEB4AEHAQMBwAIAAYABQQHg - AQcBAwHAAgABiAERAeABBwIAAR8B/wGBAREB4AEHAgABEAEBAYEBMQHgAQ8BwAEDAgABgQHxAeABHwHA - AQMCAAGAAQEB4AE/AcABAwL/AYABAQL/AfwBPws= + ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAAA+ + EQAAAk1TRnQBSQFMAgEBBQEAAVgBBQFYAQUBEAEAARABAAT/ASEBAAj/AUIBTQE2BwABNgMAASgDAAFA + AwABIAMAAQEBAAEgBgABIC4AAxgBIgMwAUsDMAFMAzIBUOgAAyIBMQNWAbkDXQHiARoBHQEYAf8BGgEd + ARgB/wEqAS0BKAH+A1MBrANNAZUDAAEB2AADIQEwA1kB7AErAS4BKQH6AkQBQgH3AUoBTAFIAfQDUwHx + AUMBRQFBAfYDQQH5ARoBHQEYAf8DTwGbAwABAdAAAxwBKANZAesBKgEtASgB/gNWAbYDTAGSA0gBhQNI + AYUDRgGAA0gBhQEqAS0BKAH+ARoBHQEYAf8DTgGU0AADJgE4ASoBLQEoAf4DTAGTA0sBkANNAZYDSgGL + A0UBfwNDAXgDQwF4A0cBggM+AfgDUwGw0AADXAHUARoBHQEYAf8DUQGgA04BmANQAZ8DOgFhAzgBXQNC + AXQDRgGAA0gBhANMAZMDWAHjAzABTMgAAzYBWQNAAXADWQHXA0cBggNMAZMDSQGJAwEBAgQAAzABSwNE + AXkDSAGHA0sBkANXAegDMAFMyAADLQFGAzgBXgNKAY0DEgEYA1ABoxAAAykBPgNLAZADTQGVA1kB7AMw + AUzIAAMUARwDMAFNA08BnANRAaIDUwGwEAADKwFDA08BmwNQAZ4DVgG7AxUBHcgAA0QBeQM/AW4DKgFA + Ax4BKwMqAUADVQGxAwQBBQQAAzkBYANMAZIDTgGUA1YBtgNWAbjIAAM/AW0DLgFIAxoBJAMlATcDIQEw + ASsBLAErAUMDLAFEA0gBiANIAYUDSAGHA0kBiQNQAZoDWAHpAycBOsgAAwYBCAMKAQ0DUwGwAyoBQANC + AXUDFAEcAzUBWANEAXwDTgGUA0QBfANIAYgDTgHwAycBO8gAAwcBCQNVAbQDCQEMBAADQQFzAyoBQQNC + AXYDPAFnA1EBpwNaAcoDWwHWAyQBNgMfAS3QAAMBAQIDUwGsAw4BEwM7AWUEAAMwAU0DBwEJAwQBBeQA + Az8BbgMGAQgDMQFPAwMBBANTAbDsAAMxAU8DAQEC/wA1AANQAaMDUgGpA1IBqQNSAakDUgGpA1IBqQNS + AakDUgGpA1IBqQNSAakDUgGpA1IBqQNSAakDUAGjXAADFQEdAUICWQH1AVECbQH3A0MBdwNbAcgCQgFZ + AfUCWAFfAeMDSgGMAwoBDQQAA1UBtANZAccDLwFJAwABAQMbASYDHAEnAxwBJwMcAScDHAEnAxwBJwMc + AScDHAEnAxwBJwMcAScDHAEnAwIBAwQAA1IBqTAAA1IBqRAAAycBOgMwAUwDMAFMAzABTAMwAUwDMAFM + AzABTAMwAUwDMAFMAycBOhQAAwUBBwNMAZIBVgJYAcEDFQEdAz0BaQEAAcgB8wH/AQABkAHmAf8CBgHc + Af8CBgHdAf8COwHjAf8CEQHeAf8CBgHdAf8CWAFbAcsDBgEIAwAB/wMAAf8DQwF3AykBPgMAAf8DAAH/ + AwAB/wMAAf8DAAH/AwAB/wMAAf8DAAH/AwAB/wMAAf8DAAH/AzIBUQQAA1IBqQQAA1ABnQNTAaoDUwGq + A1MBqgNTAaoDUwGqA1MBqgNQAZ0MAANSAakQAANOAfsDAAH/AwAB/wMAAf8DAAH/AwAB/wMAAf8DAAH/ + AwAB/wNOAfsUAAEwAjEBTQEAAckB8wH/AQAByQH0Af8BWQJgAesBWwJeAdkBAAHAAfEB/wEHAQ8B3wH/ + AgkB4AH/AgkB4AH/AkIB6QH/AhQB4gH/AgkB4AH/AgkB4AH/A0ABcQNRAaIDVgG2AyoBQAQAAxABFQMR + ARcDEQEXAxEBFwMRARcDEQEXAxEBFwMRARcDEQEXAxEBFwMQARYIAANSAakEAANQAZ0DUwGqA1MBqgMf + ASwcAANSAakTAAH/AwAB/wMAAf8DAAH/AwAB/wMAAf8DAAH/AwAB/wMAAf8DAAH/FAADBwEKAVkCZwHy + AQABygH0Af8BAAHKAfQB/wEAAcoB9AH/AQABoQHuAf8CDAHjAf8CDAHjAf8CDAHjAf8CqQHvAf8CEwHj + Af8CDAHjAf8CDAHjAf8CVgFYAbkDCgEOAxEBFwMAAQE4AANSAakwAANSAakTAAH/AwAB/wMAAf8DAAH/ + AwAB/wMAAf8DAAH/AwAB/wMAAf8DAAH/DAADFQEdAz0BaQM6AWIBXAJgAdQBAAHLAfUB/wEAAcsB9QH/ + AQABywH1Af8BAAGgAfAB/wIPAeYB/wIPAeYB/wIPAeYB/wLCAfYB/wInAegB/wIPAeYB/wIPAeYB/wJX + AVkBvwNSAfQDAAH/Az4BbAMOARMDQgF2A0MBdwNDAXcDQwF3A0MBdwNDAXcDQwF3A0MBdwNDAXcDQwF3 + A0IBdgMUARsEAANSAakDIgEyA1IBqQNSAakDUgGpA1IBqQNSAakDUgGpA1IBqQNSAakDUgGpA1IBqQMi + ATIDUgGpEwAB/wMAAf8DAAH/AwAB/wMAAf8DAAH/AwAB/wMAAf8DAAH/AwAB/wwAAUsCTAGQAQABywH2 + Af8BAAHLAfYB/wEAAcsB9gH/AQABywH2Af8BKQFWAWYB+gNDAXgDIgEyAksBYAH7AhIB6QH/AhIB6QH/ + As0B+AH/AjYB7QH/AhIB6QH/AhIB6QH/A1ABngMAAf4DAAH/A0MBdwMeASsDVwHFA1kBxwNZAccDWQHH + A1kBxwNZAccDWQHHA1kBxwNZAccDWQHHA1gBxgMmATkEAANSAakDNAFVAzQBVSAAAzQBVQM0AVUDUgGp + EwAB/wMAAf8DAAH/AwAB/wMAAf8DAAH/AwAB/wMAAf8DAAH/AwAB/wwAA1EBoAEAAcwB9wH/AQABzAH3 + Af8BAAHMAfcB/wEAAcwB9wH/A0MBdwgAA0oBjQIVAewB/wIVAewB/wIxAe8B/wIZAewB/wIVAewB/wER + ASIB7QH/AVICUwGoAzMBUwM8AWcDFAEcOAADUgGpAzQBVQM0AVUDRgGAA1IBqQNSAakDUgGpA1IBqQNS + AakDUgGpA0UBfwM0AVUDNAFVA1IBqRMAAf8DAAH/AwAB/wMAAf8DAAH/AwAB/wMAAf8DAAH/AwAB/wMA + Af8PAAEBAT8CQAFvAT4CXAH4AQABzQH3Af8BAAHNAfcB/wMSARgIAAMBAQIDRgF+AlIBXQHwAhgB7gH/ + ARgBGQHuAf8CQAGoAf0BRQJGAX4DAwEEAzMBUwM8AWcDFAEcOAADUgGpAzQBVQM0AVUDPwFuAzIBUBAA + AycBOwNEAXwDNAFVAzQBVQNSAakTAAH/AwAB/wMAAf8DAAH/AwAB/wMAAf8DAAH/AwAB/wMAAf8DAAH/ + DwABAQE/AkABbwE+AlwB+AEAAc4B+AH/AQABzgH4Af8DEgEYEAADFwEgAQABvAH3Af8BAAHEAfcB/wFA + AqgB/QFFAkYBfgMDAQQDAAH+AwAB/wNDAXcDHwEsA1cBxQNZAccDWQHHA1kBxwNZAccDWQHHA1kBxwNZ + AccDWQHHA1kBxwNYAcYDJgE5BAADUgGpAzQBVQM0AVUDBQEHA1UBtQMRARcDUgGpAykBPgQAA1ABnwMR + ARcDNAFVAzQBVQNSAakTAAH/AwAB/wMAAf8DAAH/AwAB/wMAAf8DAAH/AwAB/wMAAf8DAAH/DAADUQGg + AQABzgH4Af8BAAHPAfkB/wEAAc8B+QH/AQABzwH5Af8DQwF3EAADRAF6AQABzwH5Af8BAAHPAfkB/wEA + Ac8B+QH/AQABzgH4Af8BUgJTAagDUgH0AwAB/wM+AWwDDgETA0IBdQNDAXcDQwF3A0MBdwNDAXcDQwF3 + A0MBdwNDAXcDQwF3A0MBdwNDAXcDFAEbBAADUgGpAzQBVQM0AVUEAAM8AWgDVgG+AyMBNANVAbUDEgEZ + A1EBoAQAAzQBVQM0AVUDUgGpEwAB/wMAAf8DAAH/AwAB/wMAAf8DAAH/AwAB/wMAAf8DAAH/A1wB3wwA + AUsCTAGQAQAB0AH6Af8BAAHQAfoB/wEAAdAB+gH/AQAB0AH6Af8BKQFWAWYB+gNDAXgDEgEZAxMBGgNE + AXoBKAFfAWcB+wEAAdAB+gH/AQAB0AH6Af8BAAHQAfoB/wEAAdAB+gH/A0oBjAMKAQ4DEQEXAwABATgA + A1IBqQM0AVUDNAFVAwABAQMtAUYDCgEOBAADOQFfA1wBzgMoATwEAAM0AVUDNAFVA1IBqRMAAf8DggH/ + AwAB/wMAAf8DAAH/AwAB/wMAAf8DAAH/A1wB3wMXASAMAAMVAR0DPQFpAzoBYgFcAmAB1AEAAdEB+gH/ + AQAB0QH6Af8BAAHQAfoB/wEAAcsB8wH/AQABywHzAf8BAAHQAfoB/wEAAdEB+gH/AQAB0QH6Af8BXQJh + AeIDOgFiAz0BaQMUARwDUQGiA1YBtgMqAUAEAAMQARUDEQEXAxEBFwMRARcDEQEXAxEBFwMRARcDEQEX + AxEBFwMRARcDEAEWCAADUgGpAzQBVQM0AVUDMwFTA1IBpgNKAYwHAAEBA0cBgwgAAzQBVQM0AVUDUgGp + EwAB/wOZAf8DhQH/AwAB/wMAAf8DAAH/AwAB/wNcAd8DFwEgGAADBwEKAVkCZwHyAQAB0gH7Af8BAAHS + AfsB/wEAAdIB+wH/AQAB0gH7Af8BAAHSAfsB/wEAAdIB+wH/AQAB0gH7Af8BAAHSAfsB/wErAV8BZwH7 + AxEBFwsAAf8DAAH/A0MBdwMpAT4DAAH/AwAB/wMAAf8DAAH/AwAB/wMAAf8DAAH/AwAB/wMAAf8DAAH/ + AwAB/wMyAVEEAANSAakDNAFVAzQBVQMRARcDUAGeAyQBNhQAAzQBVQM0AVUDUgGpEAADUAH7AwAB/wMA + Af8DAAH/AwAB/wMAAf8DXAHfAxcBIBwAATACMQFNAQAB0gH8Af8BAAHSAfwB/wFZAmAB6wFbAl4B2QEA + AdIB/AH/AQAB0gH8Af8BWwJhAeEBXQJhAeIBAAHSAfwB/wEAAdIB/AH/AzgBXggAA1UBtANZAccDLwFJ + AwABAQMbASYDHAEnAxwBJwMcAScDHAEnAxwBJwMcAScDHAEnAxwBJwMcAScDHAEnAwIBAwQAA1IBqQMi + ATIDUgGpA1IBqQNSAakDUgGpA1IBqQNSAakDUgGpA1IBqQNSAakDUgGpAyIBMgNSAakQAAMgAS4DKQE/ + AykBPwMpAT8DKQE/AykBPwMRARcgAAMFAQcDTAGSAVYCWAHBAxUBHQM9AWkBAAHTAfwB/wEAAdMB/AH/ + AUUCRgF/AxABFQNWAbMBSwJMAY8DBAEGTAADUAGjA1IBqQNSAakDUgGpA1IBqQNSAakDUgGpA1IBqQNS + AakDUgGpA1IBqQNSAakDUgGpA1ABo1wAAxUBHQFCAlkB9QFRAm0B9wMgAS8YAAFCAU0BPgcAAT4DAAEo + AwABQAMAASADAAEBAQABAQYAAQEWAAP/AQAB/gEfBgAB+AEDBgAB8AEBBgAB4AEBBgAB4AEBBgAB4AcA + AcABQAYAAcEB4AYAAcEB4AYAAcABQQYAAYABAQYAAYABAwYAARABBwYAAYQBfwYAAcEB/wYAAc8B/wYA + Av8BgAEBAv8B/AEBAgABvwH9AeABBwHAAwABoAEdAeABBwHAAQABEAEBAaEB/QHgAQcBwAEAAR8B/wG/ + Af0B4AEHBAABgAEBAeABBwQAAY8B8QHgAQcBAwEAAR8B/wGAAQEB4AEHAQMBAAEfAf8BgwHBAeABBwED + AcACAAGAAUEB4AEHAQMBwAIAAYgBEQHgAQcCAAEfAf8BgQERAeABBwIAARABAQGBATEB4AEPAcABAwIA + AYEB8QHgAR8BwAEDAgABgAEBAeABPwHAAQMC/wGAAQEC/wH8AT8L </value> </data> - <metadata name="tsGCode.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> - <value>551, 17</value> - </metadata> - <metadata name="tsIssues.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> - <value>765, 17</value> - </metadata> - <metadata name="toolTipInformation.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> - <value>863, 17</value> - </metadata> <metadata name="toolTipInformation.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> <value>863, 17</value> </metadata> diff --git a/UVtools.GUI/Properties/AssemblyInfo.cs b/UVtools.GUI/Properties/AssemblyInfo.cs index 1998be3..fabd5e0 100644 --- a/UVtools.GUI/Properties/AssemblyInfo.cs +++ b/UVtools.GUI/Properties/AssemblyInfo.cs @@ -1,5 +1,4 @@ using System.Reflection; -using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following @@ -7,7 +6,11 @@ using System.Runtime.InteropServices; // associated with an assembly. [assembly: AssemblyTitle("UVtools")] [assembly: AssemblyDescription("MSLA/DLP, file analysis, repair, conversion and manipulation")] -[assembly: AssemblyConfiguration("")] +#if DEBUG +[assembly: AssemblyConfiguration("Debug")] +#else + [assembly: AssemblyConfiguration("Release")] +#endif [assembly: AssemblyCompany("PTRTECH")] [assembly: AssemblyProduct("UVtools")] [assembly: AssemblyCopyright("Copyright © 2020 PTRTECH")] @@ -32,5 +35,5 @@ using System.Runtime.InteropServices; // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("0.6.1.1")] -[assembly: AssemblyFileVersion("0.6.1.1")] +[assembly: AssemblyVersion("0.6.2.0")] +[assembly: AssemblyFileVersion("0.6.2.0")] diff --git a/UVtools.GUI/Properties/Settings.Designer.cs b/UVtools.GUI/Properties/Settings.Designer.cs index 2e4f061..78a5e87 100644 --- a/UVtools.GUI/Properties/Settings.Designer.cs +++ b/UVtools.GUI/Properties/Settings.Designer.cs @@ -109,7 +109,7 @@ namespace UVtools.GUI.Properties { [global::System.Configuration.UserScopedSettingAttribute()] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Configuration.DefaultSettingValueAttribute("False")] + [global::System.Configuration.DefaultSettingValueAttribute("True")] public bool StartMaximized { get { return ((bool)(this["StartMaximized"])); @@ -454,5 +454,137 @@ namespace UVtools.GUI.Properties { this["DefaultOpenFileExtension"] = value; } } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("Green")] + public global::System.Drawing.Color PixelEditorAddPixelColor { + get { + return ((global::System.Drawing.Color)(this["PixelEditorAddPixelColor"])); + } + set { + this["PixelEditorAddPixelColor"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("DarkRed")] + public global::System.Drawing.Color PixelEditorRemovePixelColor { + get { + return ((global::System.Drawing.Color)(this["PixelEditorRemovePixelColor"])); + } + set { + this["PixelEditorRemovePixelColor"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("Cyan")] + public global::System.Drawing.Color PixelEditorSupportColor { + get { + return ((global::System.Drawing.Color)(this["PixelEditorSupportColor"])); + } + set { + this["PixelEditorSupportColor"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("Purple")] + public global::System.Drawing.Color PixelEditorDrainHoleColor { + get { + return ((global::System.Drawing.Color)(this["PixelEditorDrainHoleColor"])); + } + set { + this["PixelEditorDrainHoleColor"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("")] + public string FileSaveNamePreffix { + get { + return ((string)(this["FileSaveNamePreffix"])); + } + set { + this["FileSaveNamePreffix"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("_copy")] + public string FileSaveNameSuffix { + get { + return ((string)(this["FileSaveNameSuffix"])); + } + set { + this["FileSaveNameSuffix"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("True")] + public bool FileSavePromptOverwrite { + get { + return ((bool)(this["FileSavePromptOverwrite"])); + } + set { + this["FileSavePromptOverwrite"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("")] + public string FileOpenDefaultDirectory { + get { + return ((string)(this["FileOpenDefaultDirectory"])); + } + set { + this["FileOpenDefaultDirectory"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("")] + public string FileSaveDefaultDirectory { + get { + return ((string)(this["FileSaveDefaultDirectory"])); + } + set { + this["FileSaveDefaultDirectory"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("")] + public string FileConvertDefaultDirectory { + get { + return ((string)(this["FileConvertDefaultDirectory"])); + } + set { + this["FileConvertDefaultDirectory"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("")] + public string FileExtractDefaultDirectory { + get { + return ((string)(this["FileExtractDefaultDirectory"])); + } + set { + this["FileExtractDefaultDirectory"] = value; + } + } } } diff --git a/UVtools.GUI/Properties/Settings.settings b/UVtools.GUI/Properties/Settings.settings index 7054f1d..36c6298 100644 --- a/UVtools.GUI/Properties/Settings.settings +++ b/UVtools.GUI/Properties/Settings.settings @@ -24,7 +24,7 @@ <Value Profile="(Default)">True</Value> </Setting> <Setting Name="StartMaximized" Type="System.Boolean" Scope="User"> - <Value Profile="(Default)">False</Value> + <Value Profile="(Default)">True</Value> </Setting> <Setting Name="CheckForUpdatesOnStartup" Type="System.Boolean" Scope="User"> <Value Profile="(Default)">True</Value> @@ -110,5 +110,38 @@ <Setting Name="DefaultOpenFileExtension" Type="System.Byte" Scope="User"> <Value Profile="(Default)">0</Value> </Setting> + <Setting Name="PixelEditorAddPixelColor" Type="System.Drawing.Color" Scope="User"> + <Value Profile="(Default)">Green</Value> + </Setting> + <Setting Name="PixelEditorRemovePixelColor" Type="System.Drawing.Color" Scope="User"> + <Value Profile="(Default)">DarkRed</Value> + </Setting> + <Setting Name="PixelEditorSupportColor" Type="System.Drawing.Color" Scope="User"> + <Value Profile="(Default)">Cyan</Value> + </Setting> + <Setting Name="PixelEditorDrainHoleColor" Type="System.Drawing.Color" Scope="User"> + <Value Profile="(Default)">Purple</Value> + </Setting> + <Setting Name="FileSaveNamePreffix" Type="System.String" Scope="User"> + <Value Profile="(Default)" /> + </Setting> + <Setting Name="FileSaveNameSuffix" Type="System.String" Scope="User"> + <Value Profile="(Default)">_copy</Value> + </Setting> + <Setting Name="FileSavePromptOverwrite" Type="System.Boolean" Scope="User"> + <Value Profile="(Default)">True</Value> + </Setting> + <Setting Name="FileOpenDefaultDirectory" Type="System.String" Scope="User"> + <Value Profile="(Default)" /> + </Setting> + <Setting Name="FileSaveDefaultDirectory" Type="System.String" Scope="User"> + <Value Profile="(Default)" /> + </Setting> + <Setting Name="FileConvertDefaultDirectory" Type="System.String" Scope="User"> + <Value Profile="(Default)" /> + </Setting> + <Setting Name="FileExtractDefaultDirectory" Type="System.String" Scope="User"> + <Value Profile="(Default)" /> + </Setting> </Settings> </SettingsFile>
\ No newline at end of file diff --git a/UVtools.GUI/UVtools.GUI.csproj b/UVtools.GUI/UVtools.GUI.csproj index a2181cc..5661f2a 100644 --- a/UVtools.GUI/UVtools.GUI.csproj +++ b/UVtools.GUI/UVtools.GUI.csproj @@ -58,6 +58,26 @@ <PropertyGroup> <StartupObject>UVtools.GUI.Program</StartupObject> </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'"> + <DebugSymbols>true</DebugSymbols> + <OutputPath>bin\x64\Debug\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <DebugType>full</DebugType> + <PlatformTarget>x64</PlatformTarget> + <LangVersion>7.3</LangVersion> + <ErrorReport>prompt</ErrorReport> + <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'"> + <OutputPath>bin\x64\Release\</OutputPath> + <DefineConstants>TRACE</DefineConstants> + <Optimize>true</Optimize> + <DebugType>pdbonly</DebugType> + <PlatformTarget>x64</PlatformTarget> + <LangVersion>7.3</LangVersion> + <ErrorReport>prompt</ErrorReport> + <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet> + </PropertyGroup> <ItemGroup> <Reference Include="ApplicationManagement"> <HintPath>Libraries\ApplicationManagement.dll</HintPath> @@ -132,6 +152,12 @@ <Compile Include="Forms\FrmInstallPEProfiles.Designer.cs"> <DependentUpon>FrmInstallPEProfiles.cs</DependentUpon> </Compile> + <Compile Include="Forms\FrmMutationPixelDimming.cs"> + <SubType>Form</SubType> + </Compile> + <Compile Include="Forms\FrmMutationPixelDimming.Designer.cs"> + <DependentUpon>FrmMutationPixelDimming.cs</DependentUpon> + </Compile> <Compile Include="Forms\FrmToolPattern.cs"> <SubType>Form</SubType> </Compile> @@ -214,6 +240,9 @@ <EmbeddedResource Include="Forms\FrmInstallPEProfiles.resx"> <DependentUpon>FrmInstallPEProfiles.cs</DependentUpon> </EmbeddedResource> + <EmbeddedResource Include="Forms\FrmMutationPixelDimming.resx"> + <DependentUpon>FrmMutationPixelDimming.cs</DependentUpon> + </EmbeddedResource> <EmbeddedResource Include="Forms\FrmToolPattern.resx"> <DependentUpon>FrmToolPattern.cs</DependentUpon> </EmbeddedResource> diff --git a/UVtools.Installer/UVtools.Installer.wixproj b/UVtools.Installer/UVtools.Installer.wixproj index 5fe9d8d..d8b77b4 100644 --- a/UVtools.Installer/UVtools.Installer.wixproj +++ b/UVtools.Installer/UVtools.Installer.wixproj @@ -37,6 +37,18 @@ <DefineConstants>MSIProductVersion=$(MSIProductVersion)</DefineConstants> <WixVariables>WixUIBannerBmp=Resources\Banner.jpg;WixUIDialogBmp=Resources\Dialog.jpg;WixUILicenseRtf=Resources\EULA.rtf</WixVariables> </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x64' "> + <DefineConstants>Debug;MSIProductVersion=$(MSIProductVersion)</DefineConstants> + <WixVariables>WixUIBannerBmp=Resources\Banner.jpg;WixUIDialogBmp=Resources\Dialog.jpg;WixUILicenseRtf=Resources\EULA.rtf</WixVariables> + <OutputPath>bin\$(Platform)\$(Configuration)\</OutputPath> + <IntermediateOutputPath>obj\$(Platform)\$(Configuration)\</IntermediateOutputPath> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x64' "> + <DefineConstants>MSIProductVersion=$(MSIProductVersion)</DefineConstants> + <WixVariables>WixUIBannerBmp=Resources\Banner.jpg;WixUIDialogBmp=Resources\Dialog.jpg;WixUILicenseRtf=Resources\EULA.rtf</WixVariables> + <OutputPath>bin\$(Platform)\$(Configuration)\</OutputPath> + <IntermediateOutputPath>obj\$(Platform)\$(Configuration)\</IntermediateOutputPath> + </PropertyGroup> <ItemGroup> <Folder Include="Code" /> </ItemGroup> diff --git a/UVtools.InstallerMM/UVtools.InstallerMM.wixproj b/UVtools.InstallerMM/UVtools.InstallerMM.wixproj index 98f876f..d308515 100644 --- a/UVtools.InstallerMM/UVtools.InstallerMM.wixproj +++ b/UVtools.InstallerMM/UVtools.InstallerMM.wixproj @@ -19,6 +19,15 @@ <OutputPath>bin\$(Configuration)\</OutputPath> <IntermediateOutputPath>obj\$(Configuration)\</IntermediateOutputPath> </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x64' "> + <DefineConstants>Debug</DefineConstants> + <OutputPath>bin\$(Platform)\$(Configuration)\</OutputPath> + <IntermediateOutputPath>obj\$(Platform)\$(Configuration)\</IntermediateOutputPath> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x64' "> + <OutputPath>bin\$(Platform)\$(Configuration)\</OutputPath> + <IntermediateOutputPath>obj\$(Platform)\$(Configuration)\</IntermediateOutputPath> + </PropertyGroup> <ItemGroup> <Compile Include="UVtools.InstallerMM.wxs" /> <Compile Include="UVtools.InstallerMMcustom.wxs" /> diff --git a/UVtools.InstallerMM/UVtools.InstallerMM.wxs b/UVtools.InstallerMM/UVtools.InstallerMM.wxs index 879293b..dfa20d2 100644 --- a/UVtools.InstallerMM/UVtools.InstallerMM.wxs +++ b/UVtools.InstallerMM/UVtools.InstallerMM.wxs @@ -124,9 +124,15 @@ <Component Id="owc9F0ED1D4E7D104FE0DC61D9F7CFE999A" Guid="9d8198ed-268b-949f-3b40-9967c446da71"> <File Id="owf9F0ED1D4E7D104FE0DC61D9F7CFE999A" Source="$(var.SourceDir)\PrusaSlicer\printer\AnyCubic Photon.ini" KeyPath="yes" /> </Component> + <Component Id="owc2D65B5F143AFF68394B6D49E35F733CB" Guid="f40836a1-6896-dfa1-8626-d57f46549860"> + <File Id="owf2D65B5F143AFF68394B6D49E35F733CB" Source="$(var.SourceDir)\PrusaSlicer\printer\Creality LD-002H.ini" KeyPath="yes" /> + </Component> <Component Id="owc7EDB8251A3EA203AF2B7D4CA7ACE2CD2" Guid="ee32d320-1828-deba-29ca-a05a60720cfc"> <File Id="owf7EDB8251A3EA203AF2B7D4CA7ACE2CD2" Source="$(var.SourceDir)\PrusaSlicer\printer\Creality LD-002R.ini" KeyPath="yes" /> </Component> + <Component Id="owc9F847F8652D12A49A3141CEED1453FBE" Guid="94d9a62e-4dd1-7b92-a5cd-2ba6b168a7fa"> + <File Id="owf9F847F8652D12A49A3141CEED1453FBE" Source="$(var.SourceDir)\PrusaSlicer\printer\Elegoo Mars 2 Pro.ini" KeyPath="yes" /> + </Component> <Component Id="owc260A3135FA730F1E8324D011F6A1C4B0" Guid="7a4e2e49-81f9-7ad2-786a-4b4434c0707f"> <File Id="owf260A3135FA730F1E8324D011F6A1C4B0" Source="$(var.SourceDir)\PrusaSlicer\printer\Elegoo Mars Saturn.ini" KeyPath="yes" /> </Component> @@ -136,6 +142,9 @@ <Component Id="owc76AABDF1DF0C1F5E05FF1F07A1630357" Guid="e472beae-9800-814f-adcb-846954b58041"> <File Id="owf76AABDF1DF0C1F5E05FF1F07A1630357" Source="$(var.SourceDir)\PrusaSlicer\printer\EPAX X1.ini" KeyPath="yes" /> </Component> + <Component Id="owcDA2EA6E2743E70BDDA7CAB980D1B2CEC" Guid="5ee7032c-2c78-95e0-56d7-695c7fff3ad9"> + <File Id="owfDA2EA6E2743E70BDDA7CAB980D1B2CEC" Source="$(var.SourceDir)\PrusaSlicer\printer\EPAX X10 4K Mono.ini" KeyPath="yes" /> + </Component> <Component Id="owc96C59034EB76D71E85BCE617CECE04D8" Guid="c082b835-0284-a751-669b-6171ff55fd10"> <File Id="owf96C59034EB76D71E85BCE617CECE04D8" Source="$(var.SourceDir)\PrusaSlicer\printer\EPAX X10.ini" KeyPath="yes" /> </Component> @@ -187,6 +196,9 @@ <Component Id="owcA3F28F12E3289ECC5D85DE40DF866B26" Guid="509cc36e-f75c-132e-2c61-66f31434a7cb"> <File Id="owfA3F28F12E3289ECC5D85DE40DF866B26" Source="$(var.SourceDir)\PrusaSlicer\printer\QIDI Shadow6.0 Pro.ini" KeyPath="yes" /> </Component> + <Component Id="owcA2B1227B6887F96BE420BAA2A0E92921" Guid="74a541bf-cf28-0f5f-60f4-7196cc1880ce"> + <File Id="owfA2B1227B6887F96BE420BAA2A0E92921" Source="$(var.SourceDir)\PrusaSlicer\printer\Voxelab Polaris.ini" KeyPath="yes" /> + </Component> <Component Id="owcB527CA38F45FBB0A2DD46961788AE79C" Guid="743425a9-38e2-6c9a-c52e-f64281bf0ec5"> <File Id="owfB527CA38F45FBB0A2DD46961788AE79C" Source="$(var.SourceDir)\PrusaSlicer\printer\Wanhao D7.ini" KeyPath="yes" /> </Component> diff --git a/UVtools.sln b/UVtools.sln index a39a495..ce4d296 100644 --- a/UVtools.sln +++ b/UVtools.sln @@ -22,45 +22,63 @@ EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 Debug|x86 = Debug|x86 Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {E7389EE3-CF56-464B-9BA1-816B31D1E6FF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {E7389EE3-CF56-464B-9BA1-816B31D1E6FF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E7389EE3-CF56-464B-9BA1-816B31D1E6FF}.Debug|x64.ActiveCfg = Debug|x64 + {E7389EE3-CF56-464B-9BA1-816B31D1E6FF}.Debug|x64.Build.0 = Debug|x64 {E7389EE3-CF56-464B-9BA1-816B31D1E6FF}.Debug|x86.ActiveCfg = Debug|Any CPU {E7389EE3-CF56-464B-9BA1-816B31D1E6FF}.Debug|x86.Build.0 = Debug|Any CPU {E7389EE3-CF56-464B-9BA1-816B31D1E6FF}.Release|Any CPU.ActiveCfg = Release|Any CPU {E7389EE3-CF56-464B-9BA1-816B31D1E6FF}.Release|Any CPU.Build.0 = Release|Any CPU + {E7389EE3-CF56-464B-9BA1-816B31D1E6FF}.Release|x64.ActiveCfg = Release|x64 + {E7389EE3-CF56-464B-9BA1-816B31D1E6FF}.Release|x64.Build.0 = Release|x64 {E7389EE3-CF56-464B-9BA1-816B31D1E6FF}.Release|x86.ActiveCfg = Release|Any CPU {E7389EE3-CF56-464B-9BA1-816B31D1E6FF}.Release|x86.Build.0 = Release|Any CPU {E53BAA5D-29A8-4287-B3AA-1AFF5A4BDC6C}.Debug|Any CPU.ActiveCfg = Debug|x86 + {E53BAA5D-29A8-4287-B3AA-1AFF5A4BDC6C}.Debug|x64.ActiveCfg = Debug|x86 {E53BAA5D-29A8-4287-B3AA-1AFF5A4BDC6C}.Debug|x86.ActiveCfg = Debug|x86 {E53BAA5D-29A8-4287-B3AA-1AFF5A4BDC6C}.Debug|x86.Build.0 = Debug|x86 {E53BAA5D-29A8-4287-B3AA-1AFF5A4BDC6C}.Release|Any CPU.ActiveCfg = Release|x86 + {E53BAA5D-29A8-4287-B3AA-1AFF5A4BDC6C}.Release|x64.ActiveCfg = Release|x86 {E53BAA5D-29A8-4287-B3AA-1AFF5A4BDC6C}.Release|x86.ActiveCfg = Release|x86 {E53BAA5D-29A8-4287-B3AA-1AFF5A4BDC6C}.Release|x86.Build.0 = Release|x86 {41224896-08E9-4F22-9E56-5F9D46DEC7D2}.Debug|Any CPU.ActiveCfg = Debug|x86 + {41224896-08E9-4F22-9E56-5F9D46DEC7D2}.Debug|x64.ActiveCfg = Debug|x86 {41224896-08E9-4F22-9E56-5F9D46DEC7D2}.Debug|x86.ActiveCfg = Debug|x86 {41224896-08E9-4F22-9E56-5F9D46DEC7D2}.Debug|x86.Build.0 = Debug|x86 {41224896-08E9-4F22-9E56-5F9D46DEC7D2}.Release|Any CPU.ActiveCfg = Release|x86 + {41224896-08E9-4F22-9E56-5F9D46DEC7D2}.Release|x64.ActiveCfg = Release|x86 {41224896-08E9-4F22-9E56-5F9D46DEC7D2}.Release|x86.ActiveCfg = Release|x86 {41224896-08E9-4F22-9E56-5F9D46DEC7D2}.Release|x86.Build.0 = Release|x86 {7C9927F8-132E-4A37-B894-440E0FD5AA3D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {7C9927F8-132E-4A37-B894-440E0FD5AA3D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7C9927F8-132E-4A37-B894-440E0FD5AA3D}.Debug|x64.ActiveCfg = Debug|x64 + {7C9927F8-132E-4A37-B894-440E0FD5AA3D}.Debug|x64.Build.0 = Debug|x64 {7C9927F8-132E-4A37-B894-440E0FD5AA3D}.Debug|x86.ActiveCfg = Debug|Any CPU {7C9927F8-132E-4A37-B894-440E0FD5AA3D}.Debug|x86.Build.0 = Debug|Any CPU {7C9927F8-132E-4A37-B894-440E0FD5AA3D}.Release|Any CPU.ActiveCfg = Release|Any CPU {7C9927F8-132E-4A37-B894-440E0FD5AA3D}.Release|Any CPU.Build.0 = Release|Any CPU + {7C9927F8-132E-4A37-B894-440E0FD5AA3D}.Release|x64.ActiveCfg = Release|x64 + {7C9927F8-132E-4A37-B894-440E0FD5AA3D}.Release|x64.Build.0 = Release|x64 {7C9927F8-132E-4A37-B894-440E0FD5AA3D}.Release|x86.ActiveCfg = Release|Any CPU {7C9927F8-132E-4A37-B894-440E0FD5AA3D}.Release|x86.Build.0 = Release|Any CPU {36E5877E-6AA6-4368-A9EA-46D7C7C90302}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {36E5877E-6AA6-4368-A9EA-46D7C7C90302}.Debug|Any CPU.Build.0 = Debug|Any CPU + {36E5877E-6AA6-4368-A9EA-46D7C7C90302}.Debug|x64.ActiveCfg = Debug|x64 + {36E5877E-6AA6-4368-A9EA-46D7C7C90302}.Debug|x64.Build.0 = Debug|x64 {36E5877E-6AA6-4368-A9EA-46D7C7C90302}.Debug|x86.ActiveCfg = Debug|Any CPU {36E5877E-6AA6-4368-A9EA-46D7C7C90302}.Debug|x86.Build.0 = Debug|Any CPU {36E5877E-6AA6-4368-A9EA-46D7C7C90302}.Release|Any CPU.ActiveCfg = Release|Any CPU {36E5877E-6AA6-4368-A9EA-46D7C7C90302}.Release|Any CPU.Build.0 = Release|Any CPU + {36E5877E-6AA6-4368-A9EA-46D7C7C90302}.Release|x64.ActiveCfg = Release|x64 + {36E5877E-6AA6-4368-A9EA-46D7C7C90302}.Release|x64.Build.0 = Release|x64 {36E5877E-6AA6-4368-A9EA-46D7C7C90302}.Release|x86.ActiveCfg = Release|Any CPU {36E5877E-6AA6-4368-A9EA-46D7C7C90302}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection |