/*
* 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
{
readonly 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
};
readonly 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,
};
readonly 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,
};
readonly 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,
};
readonly 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,
};
readonly 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 debanding the Z axis.\n" +
"Based on the guide: https://bit.ly/3nkXAOa\n\n" +
"NOTE: Do not use this script! it's outdated and replaced by inbuilt UVtools suggestion (Wait time before cure).\n" +
"Check the Shield icon/tab and look for 'Wait time before cure' suggestion, you can also configure it and offers more possibilities.";
Script.Author = "Tiago Conceição";
Script.Version = new Version(0, 3);
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()
{
throw new NotSupportedException(
"Do not use this script! it's outdated and replaced by inbuilt UVtools suggestion (Wait time before cure).\n" +
"Check the Shield icon/tab and look for 'Wait time before cure' suggestion, you can also configure it and offers more possibilities.");
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;
if (firstLayer is not null)
{
if (firstLayer.NonZeroPixelCount > 1) // First layer is not blank as it seems, lets create one
{
firstLayer = 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.05f;
firstLayer.SetNoDelays();
SlicerFile.SuppressRebuildPropertiesWork(() => { SlicerFile.Prepend(firstLayer); });
}
}
}
// return true if not cancelled by user
return !Progress.Token.IsCancellationRequested;
}
}