diff --git a/UVtools.ScriptSample/ScriptDebandingZSample.cs b/UVtools.ScriptSample/ScriptDebandingZSample.cs new file mode 100644 index 0000000..5d33739 --- /dev/null +++ b/UVtools.ScriptSample/ScriptDebandingZSample.cs @@ -0,0 +1,166 @@ +/* + * GNU AFFERO GENERAL PUBLIC LICENSE + * Version 3, 19 November 2007 + * Copyright (C) 2007 Free Software Foundation, Inc. + * Everyone is permitted to copy and distribute verbatim copies + * of this license document, but changing it is not allowed. + */ + +using System; +using UVtools.Core.Extensions; +using UVtools.Core.Scripting; + +namespace UVtools.ScriptSample +{ + /// + /// Change layer properties to random values + /// + public class ScriptDebandingZSample : ScriptGlobals + { + ScriptCheckBoxInput CreateEmptyLayerInput = new() + { + Label = "Create a first empty layer to overcome printer firmware limitation", + ToolTip = "Some printers will not respect wait time for the first layer, introducing the problem once again. Use this option to by pass that", + Value = true + }; + + ScriptNumericalInput BottomSafeDebandingHeightInput = new() + { + Label = "Safe height for the large debanding time", + //ToolTip = "Margin in pixels to inset from object edge", + Unit = "mm", + Minimum = 0.1m, + Maximum = 50, + Increment = 0.5m, + Value = 0.5m, + DecimalPlates = 2, + }; + + ScriptNumericalInput BottomWaitTimeBeforeCureInput = new() + { + Label = "Large debanding wait time before cure", + ToolTip = "Time to wait before cure a debanding layer", + Unit = "s", + Minimum = 5, + Maximum = 300, + Increment = 1, + Value = 40, + DecimalPlates = 2, + }; + + ScriptNumericalInput NormalWaitTimeBeforeCureInput = new() + { + Label = "Normal wait time before cure", + ToolTip = "Time to wait before cure a normal layer", + Unit = "s", + Minimum = 1, + Maximum = 300, + Increment = 1, + Value = 3, + DecimalPlates = 2, + }; + + ScriptNumericalInput BottomWaitTimeAfterCureInput = new() + { + Label = "Bottom wait time after cure", + ToolTip = "Time to wait after cure a bottom layer", + Unit = "s", + Minimum = 0, + Maximum = 100, + Increment = 1, + Value = 5, + DecimalPlates = 2, + }; + + ScriptNumericalInput NormalWaitTimeAfterCureInput = new() + { + Label = "Normal wait time after cure", + ToolTip = "Time to wait after cure a normal layer", + Unit = "s", + Minimum = 0, + Maximum = 100, + Increment = 1, + Value = 2, + DecimalPlates = 2, + }; + + /// + /// Set configurations here, this function trigger just after load a script + /// + public void ScriptInit() + { + Script.Name = "Debanding Z with wait time"; + Script.Description = "Applies wait time at certain layers to help layer adhesion and deband the Z axis.\n" + + "Based on the guide: https://bit.ly/3nkXAOa\n"; + Script.Author = "Tiago Conceição"; + Script.Version = new Version(0, 1); + if (SlicerFile.SupportsGCode) CreateEmptyLayerInput.Value = false; + Script.UserInputs.Add(CreateEmptyLayerInput); + Script.UserInputs.Add(BottomSafeDebandingHeightInput); + Script.UserInputs.Add(BottomWaitTimeBeforeCureInput); + Script.UserInputs.Add(NormalWaitTimeBeforeCureInput); + if(SlicerFile.CanUseBottomWaitTimeAfterCure) Script.UserInputs.Add(BottomWaitTimeAfterCureInput); + if(SlicerFile.CanUseWaitTimeAfterCure) Script.UserInputs.Add(NormalWaitTimeAfterCureInput); + } + + /// + /// Validate user inputs here, this function trigger when user click on execute + /// + /// A error message, empty or null if validation passes. + public string ScriptValidate() + { + return SlicerFile.CanUseAnyLightOffDelay || SlicerFile.CanUseAnyWaitTimeBeforeCure ? null : "Your printer/file format is not supported."; + } + + /// + /// Execute the script, this function trigger when when user click on execute and validation passes + /// + /// True if executes successfully to the end, otherwise false. + public bool ScriptExecute() + { + Progress.Reset("Changing layers", Operation.LayerRangeCount); // Sets the progress name and number of items to process + + if (SlicerFile.CanUseAnyWaitTime) + { + SlicerFile.BottomLightOffDelay = 0; + SlicerFile.LightOffDelay = 0; + SlicerFile.BottomWaitTimeBeforeCure = (float) BottomWaitTimeBeforeCureInput.Value; + + SlicerFile.WaitTimeBeforeCure = (float)NormalWaitTimeBeforeCureInput.Value; + } + else + { + SlicerFile.SetBottomLightOffDelay((float)BottomWaitTimeBeforeCureInput.Value); + SlicerFile.SetNormalLightOffDelay((float)NormalWaitTimeBeforeCureInput.Value); + } + + if (SlicerFile.CanUseBottomWaitTimeAfterCure) SlicerFile.BottomWaitTimeAfterCure = (float) BottomWaitTimeAfterCureInput.Value; + if (SlicerFile.CanUseWaitTimeAfterCure) SlicerFile.WaitTimeAfterCure = (float)NormalWaitTimeAfterCureInput.Value; + + foreach (var layer in SlicerFile) + { + if((decimal)layer.PositionZ > BottomSafeDebandingHeightInput.Value) break; + layer.SetWaitTimeBeforeCureOrLightOffDelay((float) BottomWaitTimeBeforeCureInput.Value); + } + + if (CreateEmptyLayerInput.Value) + { + var firstLayer = SlicerFile.FirstLayer.Clone(); + using var mat = EmguExtensions.InitMat(SlicerFile.Resolution); + var pixelPos = firstLayer.BoundingRectangle.Center(); + mat.SetByte(pixelPos.X, pixelPos.Y, 1); // Print a very fade pixel to ignore empty layer detection + firstLayer.LayerMat = mat; + firstLayer.ExposureTime = SlicerFile.SupportsGCode ? 0 : 0.1f; + firstLayer.SetNoDelays(); + SlicerFile.SuppressRebuildPropertiesWork(() => + { + SlicerFile.LayerManager.Prepend(firstLayer); + }); + + } + + // return true if not cancelled by user + return !Progress.Token.IsCancellationRequested; + } + } +}