mirror of
https://github.com/riegera2412/UVtools.git
synced 2026-07-08 17:42:31 +02:00
8e4995a6a5
- **UVtoolsCmd:**
- **print-properties:**
- (Change) `-b`, `--base` option to `-a`, `-all` to indicate all properties and sub-properties, now defaults to only show base properties
- (Add) `-r`, `--range` option to prints only the matching layer(s) index(es) in a range
- (Add) `-i`, `--indexes` option to prints only the matching layer(s) index(es)
- (Add) Command: `set-properties <input-file> <property=value> Set properties in a file or to it layers with new values`
- (Add) Command: `print-issues <input-file> Detect and print issues in a file`
- (Add) New option to the `run` command: `-p, --property <property=value> Set a property with a new value (Compatible with operations only)`
- (Remove) Command: `print-layers` as it has been moved to `print-properties`, use `-r :` to obtain same result as default on `print-layers`
- **Issues:**
- (Fix) Issues groups with only one issue was displaying the wrong area value
- (Fix) Volume incorrectly calculated, resulting in a high value for group of issues
- (Fix) Incorrect calculation of the bounding rectangle for a group of issues
- **Repair layers:**
- (Add) Switch to opt between "Re-detect the selected issues before repair" and "Use and repair the previous detected issues" (Default)
- (Improvement) Do not allow to run the tool if there are no detected issues when the option "Use and repair the previous detected issues" is selected
- (Improvement) Linux: Recompile libcvextern.so on a older system to be able to run on both older and newest system (#603)
- (Upgrade) .NET from 6.0.10 to 6.0.11
205 lines
7.0 KiB
C#
205 lines
7.0 KiB
C#
/*
|
|
* 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.Text;
|
|
using UVtools.Core.Extensions;
|
|
using UVtools.Core.FileFormats;
|
|
using UVtools.Core.Layers;
|
|
|
|
namespace UVtools.Core.Operations;
|
|
|
|
|
|
public class OperationRaiseOnPrintFinish : Operation
|
|
{
|
|
#region Constants
|
|
#endregion
|
|
|
|
#region Members
|
|
private decimal _positionZ;
|
|
private decimal _waitTime = 1200; // 20m
|
|
private bool _outputDummyPixel = true;
|
|
|
|
#endregion
|
|
|
|
#region Overrides
|
|
|
|
public override LayerRangeSelection StartLayerRangeSelection => LayerRangeSelection.None;
|
|
public override string IconClass => "fa-solid fa-level-up-alt";
|
|
public override string Title => "Raise platform on print finish";
|
|
public override string Description =>
|
|
"Raise the build platform to a set position after finish the print.\n\n" +
|
|
"NOTE: Only use this tool once and if your printer firmware don't already raise the build platform after finish the print.\n" +
|
|
"This will create a \"empty\" layer on end to simulate a print at a defined height.\n" +
|
|
"Not compatible with all printers, still it won't cause any harm if printer don't support this strategy.";
|
|
|
|
public override string ConfirmationText =>
|
|
$"raise the platform on print finish to Z={_positionZ}mm";
|
|
|
|
public override string ProgressTitle =>
|
|
$"Inserting dummy layer on end";
|
|
|
|
public override string ProgressAction => "Inserted layer";
|
|
|
|
public override string? ValidateSpawn()
|
|
{
|
|
if(!SlicerFile.CanUseLayerPositionZ)
|
|
{
|
|
return NotSupportedMessage;
|
|
}
|
|
|
|
if (SlicerFile.LayerCount >= 2)
|
|
{
|
|
var layerHeight = SlicerFile.LastLayer!.LayerHeight;
|
|
var criteria = Math.Max((float) Layer.MaximumHeight, SlicerFile.LayerHeight);
|
|
|
|
if (layerHeight > criteria)
|
|
{
|
|
return $"With a difference of {layerHeight}mm between the last two layers, it looks like this tool had already been applied.\n" +
|
|
$"The difference must be less or equal to {criteria}mm in order to run this tool.";
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
public override string? ValidateInternally()
|
|
{
|
|
var sb = new StringBuilder();
|
|
|
|
if (!ValidateSpawn(out var message))
|
|
{
|
|
sb.AppendLine(message);
|
|
}
|
|
if((float)_positionZ < SlicerFile.PrintHeight)
|
|
{
|
|
sb.AppendLine($"Can't raise to {_positionZ}mm, because it's below the maximum print height of {SlicerFile.PrintHeight}mm.");
|
|
}
|
|
else if ((float)_positionZ == SlicerFile.PrintHeight)
|
|
{
|
|
sb.AppendLine($"Raise to {_positionZ}mm will have no effect because it's the same height as last layer of {SlicerFile.PrintHeight}mm.");
|
|
}
|
|
|
|
return sb.ToString();
|
|
}
|
|
|
|
public override string ToString()
|
|
{
|
|
var result = $"[Z={_positionZ}mm] [Wait: {_waitTime}s] [Dummy pixel: {_outputDummyPixel}]";
|
|
if (!string.IsNullOrEmpty(ProfileName)) result = $"{ProfileName}: {result}";
|
|
return result;
|
|
}
|
|
#endregion
|
|
|
|
#region Properties
|
|
|
|
public float MinimumPositionZ => Layer.RoundHeight(SlicerFile.PrintHeight + SlicerFile.LayerHeight);
|
|
public float MediumPositionZ => Layer.RoundHeight(MinimumPositionZ + (MaximumPositionZ - MinimumPositionZ) / 2);
|
|
public float MaximumPositionZ => Math.Max(MinimumPositionZ, Layer.RoundHeight(SlicerFile.MachineZ));
|
|
|
|
/// <summary>
|
|
/// Gets or sets the Z position to raise to
|
|
/// </summary>
|
|
public decimal PositionZ
|
|
{
|
|
get => _positionZ;
|
|
set => RaiseAndSetIfChanged(ref _positionZ, Layer.RoundHeight(value));
|
|
}
|
|
|
|
/// <summary>
|
|
/// <para>Gets or sets the ensured wait time to stay still on the desired position.</para>
|
|
/// <para>This is useful if the printer firmware always move to top and you want to stay still on the set position for at least the desired time.</para>
|
|
/// <para>Note: The print time calculation will take this wait into consideration and display a longer print time.</para>
|
|
/// </summary>
|
|
public decimal WaitTime
|
|
{
|
|
get => _waitTime;
|
|
set => RaiseAndSetIfChanged(ref _waitTime, Math.Round(Math.Max(0, value), 2));
|
|
}
|
|
|
|
/// <summary>
|
|
/// True to output a dummy pixel on bounding rectangle position to avoid empty layer and blank image, otherwise set to false
|
|
/// </summary>
|
|
public bool OutputDummyPixel
|
|
{
|
|
get => _outputDummyPixel;
|
|
set => RaiseAndSetIfChanged(ref _outputDummyPixel, value);
|
|
}
|
|
#endregion
|
|
|
|
#region Constructor
|
|
|
|
public OperationRaiseOnPrintFinish()
|
|
{
|
|
//_outputDummyPixel = !SlicerFile.SupportsGCode;
|
|
}
|
|
|
|
public OperationRaiseOnPrintFinish(FileFormat slicerFile) : base(slicerFile)
|
|
{ }
|
|
|
|
public override void InitWithSlicerFile()
|
|
{
|
|
if (_positionZ <= 0) _positionZ = (decimal)SlicerFile.MachineZ;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Equality
|
|
|
|
protected bool Equals(OperationRaiseOnPrintFinish other)
|
|
{
|
|
return _positionZ == other._positionZ && _outputDummyPixel == other._outputDummyPixel && _waitTime == other._waitTime;
|
|
}
|
|
|
|
public override bool Equals(object? obj)
|
|
{
|
|
if (ReferenceEquals(null, obj)) return false;
|
|
if (ReferenceEquals(this, obj)) return true;
|
|
if (obj.GetType() != this.GetType()) return false;
|
|
return Equals((OperationRaiseOnPrintFinish) obj);
|
|
}
|
|
|
|
public override int GetHashCode()
|
|
{
|
|
return HashCode.Combine(_positionZ, _outputDummyPixel, _waitTime);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Methods
|
|
|
|
public void SetToMinimumPosition() => PositionZ = (decimal)MinimumPositionZ;
|
|
public void SetToMediumPosition() => PositionZ = (decimal)MediumPositionZ;
|
|
public void SetToMaximumPosition() => PositionZ = (decimal)MaximumPositionZ;
|
|
|
|
public void SetWaitTime(decimal time) => WaitTime = time;
|
|
|
|
protected override bool ExecuteInternally(OperationProgress progress)
|
|
{
|
|
var layer = SlicerFile.LastLayer!.Clone();
|
|
layer.PositionZ = (float)_positionZ;
|
|
layer.ExposureTime = SlicerFile.SupportsGCode ? 0 : 0.05f; // Very low exposure time
|
|
layer.LightPWM = 0; // Try to disable light if possible
|
|
layer.SetNoDelays();
|
|
using var newMat = _outputDummyPixel
|
|
? SlicerFile.CreateMatWithDummyPixel(layer.BoundingRectangle.Center())
|
|
: SlicerFile.CreateMat();
|
|
|
|
layer.LayerMat = newMat;
|
|
|
|
if(_waitTime > 0) layer.SetWaitTimeBeforeCureOrLightOffDelay((float)_waitTime);
|
|
|
|
SlicerFile.SuppressRebuildPropertiesWork(() =>
|
|
{
|
|
SlicerFile.Append(layer);
|
|
});
|
|
return true;
|
|
//return !progress.Token.IsCancellationRequested;
|
|
}
|
|
#endregion
|
|
} |