mirror of
https://github.com/riegera2412/UVtools.git
synced 2026-07-09 01:52:32 +02:00
v2.28.1
- (Add) File - Terminal: Inject C# code into UVtools with an interactive terminal - (Improvement) Modifiers: Better increment values for the spin up/down buttons - (Improvement) Tool - Timelapse: Better lift and feeds for virtual layer, also allow to set custom lift speed for that mode - (Fix) Tool - Edit print parameters: Disallow to change PositionZ in layers with an active alternating pattern - (Fix) GCode: When generating layers higher than the next, it will not return to the correct position z
This commit is contained in:
@@ -1,5 +1,13 @@
|
||||
# Changelog
|
||||
|
||||
## 15/02/2022 - v2.28.1
|
||||
|
||||
- (Add) File - Terminal: Inject C# code into UVtools with an interactive terminal
|
||||
- (Improvement) Modifiers: Better increment values for the spin up/down buttons
|
||||
- (Improvement) Tool - Timelapse: Better lift and feeds for virtual layer, also allow to set custom lift speed for that mode
|
||||
- (Fix) Tool - Edit print parameters: Disallow to change PositionZ in layers with an active alternating pattern
|
||||
- (Fix) GCode: When generating layers higher than the next, it will not return to the correct position z
|
||||
|
||||
## 13/02/2022 - v2.28.0
|
||||
|
||||
- **Core:**
|
||||
|
||||
@@ -147,46 +147,46 @@ namespace UVtools.Core.FileFormats
|
||||
{
|
||||
|
||||
#region Instances
|
||||
public static PrintParameterModifier PositionZ { get; } = new ("Position Z", "Absolute Z position", "mm",0, 100000, Layer.HeightPrecision);
|
||||
public static PrintParameterModifier BottomLayerCount { get; } = new ("Bottom layers count", "Number of bottom/burn-in layers", "layers",0, ushort.MaxValue, 0);
|
||||
|
||||
public static PrintParameterModifier PositionZ { get; } = new ("Position Z", "Absolute Z position", "mm",0, 100000, 0.01, Layer.HeightPrecision);
|
||||
public static PrintParameterModifier BottomLayerCount { get; } = new ("Bottom layers count", "Number of bottom/burn-in layers", "layers",0, ushort.MaxValue, 1, 0);
|
||||
|
||||
public static PrintParameterModifier BottomLightOffDelay { get; } = new("Bottom light-off seconds", "Total motor movement time + rest time to wait before cure a new bottom layer", "s");
|
||||
public static PrintParameterModifier LightOffDelay { get; } = new("Light-off seconds", "Total motor movement time + rest time to wait before cure a new layer", "s");
|
||||
|
||||
public static PrintParameterModifier BottomWaitTimeBeforeCure { get; } = new ("Bottom wait before cure", "Time to wait/rest before cure a new bottom layer\nChitubox: Rest after retract\nLychee: Wait before print", "s", 0, 1000, 2);
|
||||
public static PrintParameterModifier WaitTimeBeforeCure { get; } = new ("Wait before cure", "Time to wait/rest before cure a new layer\nChitubox: Rest after retract\nLychee: Wait before print", "s", 0, 1000, 2);
|
||||
public static PrintParameterModifier BottomWaitTimeBeforeCure { get; } = new ("Bottom wait before cure", "Time to wait/rest before cure a new bottom layer\nChitubox: Rest after retract\nLychee: Wait before print", "s");
|
||||
public static PrintParameterModifier WaitTimeBeforeCure { get; } = new ("Wait before cure", "Time to wait/rest before cure a new layer\nChitubox: Rest after retract\nLychee: Wait before print", "s");
|
||||
|
||||
public static PrintParameterModifier BottomExposureTime { get; } = new ("Bottom exposure time", "Bottom layers cure time", "s", 0.1M, 1000, 2);
|
||||
public static PrintParameterModifier ExposureTime { get; } = new ("Exposure time", "Layers cure time", "s", 0.1M, 1000, 2);
|
||||
public static PrintParameterModifier BottomExposureTime { get; } = new ("Bottom exposure time", "Bottom layers cure time", "s", 0.1M);
|
||||
public static PrintParameterModifier ExposureTime { get; } = new ("Exposure time", "Layers cure time", "s", 0.1M);
|
||||
|
||||
public static PrintParameterModifier BottomWaitTimeAfterCure { get; } = new("Bottom wait after cure", "Time to wait/rest after cure a new bottom layer\nChitubox: Rest before lift\nLychee: Wait after print", "s", 0, 1000, 2);
|
||||
public static PrintParameterModifier WaitTimeAfterCure { get; } = new("Wait after cure", "Time to wait/rest after cure a new bottom layer\nChitubox: Rest before lift\nLychee: Wait after print", "s", 0, 1000, 2);
|
||||
public static PrintParameterModifier BottomWaitTimeAfterCure { get; } = new("Bottom wait after cure", "Time to wait/rest after cure a new bottom layer\nChitubox: Rest before lift\nLychee: Wait after print", "s");
|
||||
public static PrintParameterModifier WaitTimeAfterCure { get; } = new("Wait after cure", "Time to wait/rest after cure a new bottom layer\nChitubox: Rest before lift\nLychee: Wait after print", "s");
|
||||
|
||||
public static PrintParameterModifier BottomLiftHeight { get; } = new ("Bottom lift height", "Bottom lift/peel height between layers", "mm", 1);
|
||||
public static PrintParameterModifier LiftHeight { get; } = new ("Lift height", @"Lift/peel height between layers", "mm", 1);
|
||||
|
||||
public static PrintParameterModifier BottomLiftSpeed { get; } = new ("Bottom lift speed", null, "mm/min", 10, 5000, 2);
|
||||
public static PrintParameterModifier LiftSpeed { get; } = new ("Lift speed", null, "mm/min", 10, 5000, 2);
|
||||
public static PrintParameterModifier BottomLiftSpeed { get; } = new ("Bottom lift speed", null, "mm/min", 10, 5000, 5);
|
||||
public static PrintParameterModifier LiftSpeed { get; } = new ("Lift speed", null, "mm/min", 10, 5000, 5);
|
||||
|
||||
public static PrintParameterModifier BottomLiftHeight2 { get; } = new("2) Bottom lift height", "Bottom second lift/peel height between layers", "mm");
|
||||
public static PrintParameterModifier LiftHeight2 { get; } = new("2) Lift height", @"Second lift/peel height between layers", "mm");
|
||||
|
||||
public static PrintParameterModifier BottomLiftSpeed2 { get; } = new("2) Bottom lift speed", null, "mm/min", 10, 5000, 2);
|
||||
public static PrintParameterModifier LiftSpeed2 { get; } = new("2) Lift speed", null, "mm/min", 10, 5000, 2);
|
||||
public static PrintParameterModifier BottomLiftSpeed2 { get; } = new("2) Bottom lift speed", null, "mm/min", 10, 5000, 5);
|
||||
public static PrintParameterModifier LiftSpeed2 { get; } = new("2) Lift speed", null, "mm/min", 10, 5000, 5);
|
||||
|
||||
public static PrintParameterModifier BottomWaitTimeAfterLift { get; } = new("Bottom wait after lift", "Time to wait/rest after a lift/peel sequence at bottom layers\nChitubox: Rest after lift\nLychee: Wait after lift", "s", 0, 1000, 2);
|
||||
public static PrintParameterModifier WaitTimeAfterLift { get; } = new("Wait after lift", "Time to wait/rest after a lift/peel sequence at layers\nChitubox: Rest after lift\nLychee: Wait after lift", "s", 0, 1000, 2);
|
||||
public static PrintParameterModifier BottomWaitTimeAfterLift { get; } = new("Bottom wait after lift", "Time to wait/rest after a lift/peel sequence at bottom layers\nChitubox: Rest after lift\nLychee: Wait after lift", "s");
|
||||
public static PrintParameterModifier WaitTimeAfterLift { get; } = new("Wait after lift", "Time to wait/rest after a lift/peel sequence at layers\nChitubox: Rest after lift\nLychee: Wait after lift", "s");
|
||||
|
||||
public static PrintParameterModifier BottomRetractSpeed { get; } = new ("Bottom retract speed", "Bottom down speed from lift height to next layer cure position", "mm/min", 10, 5000, 2);
|
||||
public static PrintParameterModifier RetractSpeed { get; } = new ("Retract speed", "Down speed from lift height to next layer cure position", "mm/min", 10, 5000, 2);
|
||||
public static PrintParameterModifier BottomRetractSpeed { get; } = new ("Bottom retract speed", "Bottom down speed from lift height to next layer cure position", "mm/min", 10, 5000, 5);
|
||||
public static PrintParameterModifier RetractSpeed { get; } = new ("Retract speed", "Down speed from lift height to next layer cure position", "mm/min", 10, 5000, 5);
|
||||
|
||||
public static PrintParameterModifier BottomRetractHeight2 { get; } = new("2) Bottom retract height", null, "mm");
|
||||
public static PrintParameterModifier RetractHeight2 { get; } = new("2) Retract height", null, "mm");
|
||||
public static PrintParameterModifier BottomRetractSpeed2 { get; } = new("2) Bottom retract speed", null, "mm/min", 10, 5000, 2);
|
||||
public static PrintParameterModifier RetractSpeed2 { get; } = new("2) Retract speed", null, "mm/min", 10, 5000, 2);
|
||||
public static PrintParameterModifier BottomRetractSpeed2 { get; } = new("2) Bottom retract speed", null, "mm/min", 10, 5000, 5);
|
||||
public static PrintParameterModifier RetractSpeed2 { get; } = new("2) Retract speed", null, "mm/min", 10, 5000, 5);
|
||||
|
||||
public static PrintParameterModifier BottomLightPWM { get; } = new ("Bottom light PWM", "UV LED power for bottom layers", "☀", 1, byte.MaxValue, 0);
|
||||
public static PrintParameterModifier LightPWM { get; } = new ("Light PWM", "UV LED power for layers", "☀", 1, byte.MaxValue, 0);
|
||||
public static PrintParameterModifier BottomLightPWM { get; } = new ("Bottom light PWM", "UV LED power for bottom layers", "☀", 1, byte.MaxValue, 5, 0);
|
||||
public static PrintParameterModifier LightPWM { get; } = new ("Light PWM", "UV LED power for layers", "☀", 1, byte.MaxValue, 5, 0);
|
||||
|
||||
/*public static PrintParameterModifier[] Parameters = {
|
||||
BottomLayerCount,
|
||||
@@ -240,6 +240,11 @@ namespace UVtools.Core.FileFormats
|
||||
/// </summary>
|
||||
public decimal Maximum { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the incrementing value for the dropdown
|
||||
/// </summary>
|
||||
public double Increment { get; set; } = 1;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the number of decimal plates
|
||||
/// </summary>
|
||||
@@ -268,13 +273,14 @@ namespace UVtools.Core.FileFormats
|
||||
#endregion
|
||||
|
||||
#region Constructor
|
||||
public PrintParameterModifier(string name, string description = null, string valueUnit = null, decimal minimum = 0, decimal maximum = 1000, byte decimalPlates = 2)
|
||||
public PrintParameterModifier(string name, string description = null, string valueUnit = null, decimal minimum = 0, decimal maximum = 1000, double increment = 0.5, byte decimalPlates = 2)
|
||||
{
|
||||
Name = name;
|
||||
Description = description ?? $"Modify '{name}'";
|
||||
ValueUnit = valueUnit ?? string.Empty;
|
||||
Minimum = minimum;
|
||||
Maximum = maximum;
|
||||
Increment = decimalPlates == 0 ? Math.Max(1, increment) : increment;
|
||||
DecimalPlates = decimalPlates;
|
||||
}
|
||||
#endregion
|
||||
|
||||
@@ -673,15 +673,15 @@ namespace UVtools.Core.GCode
|
||||
{
|
||||
AppendLiftMoveGx(lifts, retracts, waitAfterLift, 0, layer);
|
||||
}
|
||||
else if (lastZPosition < layer.PositionZ) // Ensure Z is on correct position
|
||||
else if (lastZPosition != layer.PositionZ) // Ensure Z is on correct position
|
||||
{
|
||||
switch (GCodePositioningType)
|
||||
{
|
||||
case GCodePositioningTypes.Absolute:
|
||||
AppendMoveGx(layer.PositionZ, liftSpeed);
|
||||
AppendMoveGx(layer.PositionZ, lastZPosition < layer.PositionZ ? Math.Max(liftSpeed, liftSpeed2) : Math.Max(retractSpeed, retractSpeed2));
|
||||
break;
|
||||
case GCodePositioningTypes.Partial:
|
||||
AppendMoveGx(Layer.RoundHeight(layer.PositionZ - lastZPosition), liftSpeed);
|
||||
AppendMoveGx(Layer.RoundHeight(layer.PositionZ - lastZPosition), lastZPosition < layer.PositionZ ? Math.Max(liftSpeed, liftSpeed2) : Math.Max(retractSpeed, retractSpeed2));
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace UVtools.Core.Operations
|
||||
private bool _propagateModificationsToLayers = true;
|
||||
private bool _perLayerOverride;
|
||||
private uint _setNumberOfLayer = 1;
|
||||
private uint _skipNumberOfLayer = 0;
|
||||
private uint _skipNumberOfLayer;
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -92,6 +92,15 @@ namespace UVtools.Core.Operations
|
||||
sb.AppendLine("Nothing changed\nDo some changes or cancel the operation.");
|
||||
}
|
||||
|
||||
if (Modifiers.Contains(FileFormat.PrintParameterModifier.PositionZ)
|
||||
&& FileFormat.PrintParameterModifier.PositionZ.HasChanged
|
||||
&& _skipNumberOfLayer > 0
|
||||
&& LayerRangeCount > 1
|
||||
&& _setNumberOfLayer + _skipNumberOfLayer < LayerRangeCount)
|
||||
{
|
||||
sb.AppendLine("Can not change the PositionZ in layers with an active alternating pattern.");
|
||||
}
|
||||
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
@@ -156,18 +165,18 @@ namespace UVtools.Core.Operations
|
||||
|
||||
protected override bool ExecuteInternally(OperationProgress progress)
|
||||
{
|
||||
if (PerLayerOverride)
|
||||
if (_perLayerOverride)
|
||||
{
|
||||
uint setLayers = 0;
|
||||
for (uint layerIndex = LayerIndexStart; layerIndex <= LayerIndexEnd; layerIndex++)
|
||||
{
|
||||
SlicerFile[layerIndex].SetValuesFromPrintParametersModifiers(Modifiers);
|
||||
if (SkipNumberOfLayer <= 0) continue;
|
||||
if (_skipNumberOfLayer == 0) continue;
|
||||
setLayers++;
|
||||
if (setLayers >= SetNumberOfLayer)
|
||||
if (setLayers >= _setNumberOfLayer)
|
||||
{
|
||||
setLayers = 0;
|
||||
layerIndex += SkipNumberOfLayer;
|
||||
layerIndex += _skipNumberOfLayer;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -105,11 +105,6 @@ namespace UVtools.Core.Operations
|
||||
|
||||
#region Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets the minimum possible
|
||||
/// </summary>
|
||||
public float MinimumPositionZ => Layer.RoundHeight(SlicerFile.PrintHeight + SlicerFile.LayerHeight);
|
||||
|
||||
public TimelapseRaiseMode RaiseMode
|
||||
{
|
||||
get => _raiseMode;
|
||||
@@ -178,6 +173,8 @@ namespace UVtools.Core.Operations
|
||||
set => RaiseAndSetIfChanged(ref _useCustomLift, value);
|
||||
}
|
||||
|
||||
public bool CanUseCustomLift => _useCustomLift && SlicerFile.CanUseLayerLiftHeight;
|
||||
|
||||
public decimal SlowLiftHeight
|
||||
{
|
||||
get => _slowLiftHeight;
|
||||
@@ -307,7 +304,7 @@ namespace UVtools.Core.Operations
|
||||
switch (_raiseMode)
|
||||
{
|
||||
case TimelapseRaiseMode.LiftHeight:
|
||||
if (_useCustomLift)
|
||||
if (CanUseCustomLift)
|
||||
{
|
||||
layer.LiftSpeed = (float)_liftSpeed;
|
||||
layer.RetractSpeed = (float)_retractSpeed;
|
||||
@@ -333,7 +330,7 @@ namespace UVtools.Core.Operations
|
||||
}
|
||||
}
|
||||
|
||||
if (SlicerFile.CanUseLayerLiftHeight2 && (layer.LiftHeight2 > 0 || _useCustomLift && _slowLiftHeight > 0)) // TSMC
|
||||
if (SlicerFile.CanUseLayerLiftHeight2 && (layer.LiftHeight2 > 0 || CanUseCustomLift && _slowLiftHeight > 0)) // TSMC
|
||||
{
|
||||
layer.LiftHeight2 = Math.Max(0, (float)_raisePositionZ - layer.PositionZ - layer.LiftHeight);
|
||||
}
|
||||
@@ -375,37 +372,52 @@ namespace UVtools.Core.Operations
|
||||
RetractHeight2 = 0
|
||||
};
|
||||
|
||||
layer.SetNoDelays();
|
||||
|
||||
/*if (_useCustomLift)
|
||||
if (CanUseCustomLift)
|
||||
{
|
||||
layer.LiftSpeed = (float) _liftSpeed;
|
||||
layer.RetractSpeed = (float) _retractSpeed;
|
||||
layer.LiftSpeed = (float)_liftSpeed;
|
||||
layer.RetractSpeed = (float)_retractSpeed;
|
||||
|
||||
/*if (SlicerFile.CanUseLayerLiftHeight2)
|
||||
{
|
||||
layer.LiftHeight = (float)_slowLiftHeight;
|
||||
}*/
|
||||
|
||||
if (SlicerFile.CanUseLayerLiftSpeed2)
|
||||
{
|
||||
layer.LiftSpeed2 = (float) _liftSpeed2;
|
||||
layer.LiftSpeed2 = (float)_liftSpeed2;
|
||||
}
|
||||
|
||||
if (SlicerFile.CanUseLayerRetractSpeed2)
|
||||
{
|
||||
layer.RetractSpeed2 = (float) _retractSpeed2;
|
||||
layer.RetractSpeed2 = (float)_retractSpeed2;
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
layer.SetNoDelays();
|
||||
|
||||
var layers = SlicerFile.ToList();
|
||||
for (int i = 0; i < virtualLayers.Count; i++)
|
||||
{
|
||||
/*var newLayer = layer.Clone();
|
||||
if (!_useCustomLift)
|
||||
int insertIndex = (int)virtualLayers[i];
|
||||
SlicerFile[insertIndex].LiftHeightTotal = SlicerFile.SupportsGCode ? 0 : 0.1f;
|
||||
|
||||
if (CanUseCustomLift)
|
||||
{
|
||||
var intersectLayer = Math.Clamp(virtualLayers[i] + i, 0, SlicerFile.LastLayerIndex);
|
||||
SlicerFile[intersectLayer].CopyLiftTo(newLayer);
|
||||
// This layer does not require a lift procedure
|
||||
newLayer.LiftHeightTotal = SlicerFile.SupportsGCode ? 0 : 0.1f;
|
||||
newLayer.RetractHeight2 = 0;
|
||||
}*/
|
||||
layers.Insert((int)(virtualLayers[i] + i), layer.Clone());
|
||||
SlicerFile[insertIndex].LiftSpeed = (float)_liftSpeed;
|
||||
SlicerFile[insertIndex].RetractSpeed = (float)_retractSpeed;
|
||||
|
||||
if (SlicerFile.CanUseLayerLiftSpeed2)
|
||||
{
|
||||
SlicerFile[insertIndex].LiftSpeed2 = (float)_retractSpeed2;
|
||||
}
|
||||
|
||||
if (SlicerFile.CanUseLayerRetractSpeed2)
|
||||
{
|
||||
SlicerFile[insertIndex].RetractSpeed2 = (float)_retractSpeed2;
|
||||
}
|
||||
}
|
||||
|
||||
layers.Insert(insertIndex + i, layer.Clone());
|
||||
}
|
||||
SlicerFile.SuppressRebuildPropertiesWork(() => SlicerFile.LayerManager.Layers = layers.ToArray());
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<RepositoryUrl>https://github.com/sn4k3/UVtools</RepositoryUrl>
|
||||
<PackageProjectUrl>https://github.com/sn4k3/UVtools</PackageProjectUrl>
|
||||
<Description>MSLA/DLP, file analysis, calibration, repair, conversion and manipulation</Description>
|
||||
<Version>2.28.0</Version>
|
||||
<Version>2.28.1</Version>
|
||||
<Copyright>Copyright © 2020 PTRTECH</Copyright>
|
||||
<PackageIcon>UVtools.png</PackageIcon>
|
||||
<Platforms>AnyCPU;x64</Platforms>
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 123 B |
@@ -62,7 +62,7 @@ namespace UVtools.WPF.Controls.Tools
|
||||
HorizontalAlignment = HorizontalAlignment.Stretch,
|
||||
Minimum = (double) modifier.Minimum,
|
||||
Maximum = (double) modifier.Maximum,
|
||||
Increment = modifier.DecimalPlates == 0 ? 1 : 0.5,
|
||||
Increment = modifier.Increment,
|
||||
Value = (double)modifier.NewValue,
|
||||
Tag = this,
|
||||
//Width = 100,
|
||||
@@ -70,7 +70,7 @@ namespace UVtools.WPF.Controls.Tools
|
||||
};
|
||||
if (modifier.DecimalPlates > 0)
|
||||
{
|
||||
NewValue.FormatString = "F02";
|
||||
NewValue.FormatString = $"F{modifier.DecimalPlates}";
|
||||
}
|
||||
|
||||
Unit = new TextBlock
|
||||
|
||||
@@ -151,7 +151,6 @@
|
||||
IsChecked="{Binding Operation.UseCustomLift}">
|
||||
<CheckBox.IsVisible>
|
||||
<MultiBinding Converter="{x:Static BoolConverters.And}">
|
||||
<Binding Path="Operation.IsLiftHeightMode"/>
|
||||
<Binding Path="SlicerFile.CanUseLayerLiftHeight"/>
|
||||
</MultiBinding>
|
||||
</CheckBox.IsVisible>
|
||||
@@ -162,7 +161,6 @@
|
||||
ColumnDefinitions="Auto,10,210,5,Auto,5,210">
|
||||
<Grid.IsVisible>
|
||||
<MultiBinding Converter="{x:Static BoolConverters.And}">
|
||||
<Binding Path="Operation.IsLiftHeightMode"/>
|
||||
<Binding Path="Operation.UseCustomLift"/>
|
||||
<Binding Path="SlicerFile.CanUseLayerLiftHeight"/>
|
||||
</MultiBinding>
|
||||
@@ -172,6 +170,7 @@
|
||||
VerticalAlignment="Center"
|
||||
ToolTip.Tip="The slow first lift sequence (TSMC).
|
||||

Use a low value or 0 to disable."
|
||||
IsVisible="{Binding !Operation.IsVirtualLayerMode}"
|
||||
Text="Slow lift height:"/>
|
||||
|
||||
<NumericUpDown Grid.Row="0" Grid.Column="2"
|
||||
@@ -179,15 +178,26 @@
|
||||
Minimum="0"
|
||||
Maximum="20"
|
||||
Increment="1"
|
||||
IsVisible="{Binding SlicerFile.CanUseLayerLiftHeight2}"
|
||||
Value="{Binding Operation.SlowLiftHeight}">
|
||||
<NumericUpDown.IsVisible>
|
||||
<MultiBinding Converter="{x:Static BoolConverters.And}">
|
||||
<Binding Path="SlicerFile.CanUseLayerLiftHeight2"/>
|
||||
<Binding Path="!Operation.IsVirtualLayerMode"/>
|
||||
</MultiBinding>
|
||||
</NumericUpDown.IsVisible>
|
||||
</NumericUpDown>
|
||||
|
||||
<TextBlock Grid.Row="0" Grid.Column="2"
|
||||
VerticalAlignment="Center"
|
||||
ToolTip.Tip="(Not supported by your printer / file format)"
|
||||
IsVisible="{Binding !SlicerFile.CanUseLayerLiftHeight2}"
|
||||
Text="(Not supported)"/>
|
||||
Text="(Not supported)">
|
||||
<TextBlock.IsVisible>
|
||||
<MultiBinding Converter="{x:Static BoolConverters.And}">
|
||||
<Binding Path="!SlicerFile.CanUseLayerLiftHeight2"/>
|
||||
<Binding Path="!Operation.IsVirtualLayerMode"/>
|
||||
</MultiBinding>
|
||||
</TextBlock.IsVisible>
|
||||
</TextBlock>
|
||||
|
||||
<TextBlock Grid.Row="2" Grid.Column="0"
|
||||
VerticalAlignment="Center"
|
||||
@@ -225,6 +235,7 @@
|
||||
VerticalAlignment="Center"
|
||||
ToolTip.Tip="The slow last retract sequence (TSMC).
|
||||

Use a low value or 0 to disable."
|
||||
IsVisible="{Binding !Operation.IsVirtualLayerMode}"
|
||||
Text="Slow retract height:"/>
|
||||
|
||||
<NumericUpDown Grid.Row="4" Grid.Column="2"
|
||||
@@ -232,15 +243,26 @@
|
||||
Minimum="0"
|
||||
Maximum="20"
|
||||
Increment="1"
|
||||
IsVisible="{Binding SlicerFile.CanUseLayerRetractHeight2}"
|
||||
Value="{Binding Operation.SlowRetractHeight}">
|
||||
<NumericUpDown.IsVisible>
|
||||
<MultiBinding Converter="{x:Static BoolConverters.And}">
|
||||
<Binding Path="SlicerFile.CanUseLayerRetractHeight2"/>
|
||||
<Binding Path="!Operation.IsVirtualLayerMode"/>
|
||||
</MultiBinding>
|
||||
</NumericUpDown.IsVisible>
|
||||
</NumericUpDown>
|
||||
|
||||
<TextBlock Grid.Row="4" Grid.Column="2"
|
||||
VerticalAlignment="Center"
|
||||
ToolTip.Tip="(Not supported by your printer / file format)"
|
||||
IsVisible="{Binding !SlicerFile.CanUseLayerRetractHeight2}"
|
||||
Text="(Not supported)"/>
|
||||
Text="(Not supported)">
|
||||
<TextBlock.IsVisible>
|
||||
<MultiBinding Converter="{x:Static BoolConverters.And}">
|
||||
<Binding Path="!SlicerFile.CanUseLayerRetractHeight2"/>
|
||||
<Binding Path="!Operation.IsVirtualLayerMode"/>
|
||||
</MultiBinding>
|
||||
</TextBlock.IsVisible>
|
||||
</TextBlock>
|
||||
|
||||
|
||||
<TextBlock Grid.Row="6" Grid.Column="0"
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace UVtools.WPF.Extensions
|
||||
public static class WindowExtensions
|
||||
{
|
||||
public static async Task<ButtonResult> MessageBoxGeneric(this Window window, string message, string title = null,
|
||||
ButtonEnum buttons = ButtonEnum.Ok, Icon icon = Icon.None, bool topMost = false, WindowStartupLocation location = WindowStartupLocation.CenterOwner, Style style = Style.None)
|
||||
ButtonEnum buttons = ButtonEnum.Ok, Icon icon = Icon.None, bool topMost = false, WindowStartupLocation location = WindowStartupLocation.CenterOwner)
|
||||
{
|
||||
var messageBoxStandardWindow = MessageBox.Avalonia.MessageBoxManager.GetMessageBoxStandardWindow(
|
||||
new MessageBoxStandardParams
|
||||
@@ -29,7 +29,6 @@ namespace UVtools.WPF.Extensions
|
||||
ContentTitle = title ?? window.Title,
|
||||
ContentMessage = message,
|
||||
Icon = icon,
|
||||
Style = style,
|
||||
WindowIcon = new WindowIcon(App.GetAsset("/Assets/Icons/UVtools.ico")),
|
||||
WindowStartupLocation = location,
|
||||
CanResize = UserSettings.Instance.General.WindowsCanResize,
|
||||
@@ -42,17 +41,17 @@ namespace UVtools.WPF.Extensions
|
||||
return await messageBoxStandardWindow.ShowDialog(window);
|
||||
}
|
||||
|
||||
public static async Task<ButtonResult> MessageBoxInfo(this Window window, string message, string title = null, ButtonEnum buttons = ButtonEnum.Ok, bool topMost = false, Style style = Style.None)
|
||||
=> await window.MessageBoxGeneric(message, title ?? $"{window.Title} - Information", buttons, Icon.Info, topMost, WindowStartupLocation.CenterOwner, style);
|
||||
public static async Task<ButtonResult> MessageBoxInfo(this Window window, string message, string title = null, ButtonEnum buttons = ButtonEnum.Ok, bool topMost = false)
|
||||
=> await window.MessageBoxGeneric(message, title ?? $"{window.Title} - Information", buttons, Icon.Info, topMost, WindowStartupLocation.CenterOwner);
|
||||
|
||||
public static async Task<ButtonResult> MessageBoxError(this Window window, string message, string title = null, ButtonEnum buttons = ButtonEnum.Ok, bool topMost = false, Style style = Style.None)
|
||||
=> await window.MessageBoxGeneric(message, title ?? $"{window.Title} - Error", buttons, Icon.Error, topMost, WindowStartupLocation.CenterOwner, style);
|
||||
public static async Task<ButtonResult> MessageBoxError(this Window window, string message, string title = null, ButtonEnum buttons = ButtonEnum.Ok, bool topMost = false)
|
||||
=> await window.MessageBoxGeneric(message, title ?? $"{window.Title} - Error", buttons, Icon.Error, topMost, WindowStartupLocation.CenterOwner);
|
||||
|
||||
public static async Task<ButtonResult> MessageBoxQuestion(this Window window, string message, string title = null, ButtonEnum buttons = ButtonEnum.YesNo, bool topMost = false, Style style = Style.None)
|
||||
=> await window.MessageBoxGeneric(message, title ?? $"{window.Title} - Question", buttons, Icon.Setting, topMost, WindowStartupLocation.CenterOwner, style);
|
||||
public static async Task<ButtonResult> MessageBoxQuestion(this Window window, string message, string title = null, ButtonEnum buttons = ButtonEnum.YesNo, bool topMost = false)
|
||||
=> await window.MessageBoxGeneric(message, title ?? $"{window.Title} - Question", buttons, Icon.Setting, topMost, WindowStartupLocation.CenterOwner);
|
||||
|
||||
public static async Task<ButtonResult> MessageBoxWaring(this Window window, string message, string title = null, ButtonEnum buttons = ButtonEnum.Ok, bool topMost = false, Style style = Style.None)
|
||||
=> await window.MessageBoxGeneric(message, title ?? $"{window.Title} - Question", buttons, Icon.Warning, topMost, WindowStartupLocation.CenterOwner, style);
|
||||
public static async Task<ButtonResult> MessageBoxWaring(this Window window, string message, string title = null, ButtonEnum buttons = ButtonEnum.Ok, bool topMost = false)
|
||||
=> await window.MessageBoxGeneric(message, title ?? $"{window.Title} - Question", buttons, Icon.Warning, topMost, WindowStartupLocation.CenterOwner);
|
||||
|
||||
|
||||
public static void ShowDialogSync(this Window window, Window parent = null)
|
||||
|
||||
@@ -127,8 +127,19 @@
|
||||
<Image Source="\Assets\Icons\extract-object-16x16.png"/>
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
|
||||
<MenuItem
|
||||
|
||||
<MenuItem Name="MainMenu.File.Terminal"
|
||||
HotKey="Ctrl+Shift+T" InputGesture="Ctrl+Shift+T"
|
||||
Header="_Terminal"
|
||||
Command="{Binding OpenTerminal}"
|
||||
IsEnabled="{Binding IsFileLoaded}">
|
||||
<MenuItem.Icon>
|
||||
<Image Source="\Assets\Icons\terminal-16x16.png"/>
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
|
||||
|
||||
<MenuItem
|
||||
Name="MainMenu.File.Convert"
|
||||
Header="_Convert to"
|
||||
IsEnabled="{Binding IsFileLoaded}"
|
||||
|
||||
@@ -617,7 +617,7 @@ namespace UVtools.WPF
|
||||
|
||||
AddHandler(DragDrop.DropEvent, (sender, e) =>
|
||||
{
|
||||
ProcessFiles(e.Data.GetFileNames().ToArray());
|
||||
ProcessFiles(e.Data.GetFileNames()?.ToArray());
|
||||
});
|
||||
|
||||
_menuFileSendTo = this.FindControl<MenuItem>("MainMenu.File.SendTo");
|
||||
@@ -1823,8 +1823,6 @@ namespace UVtools.WPF
|
||||
|
||||
VisibleThumbnailIndex = 1;
|
||||
|
||||
RefreshProperties();
|
||||
|
||||
UpdateTitle();
|
||||
|
||||
if (mat is not null)
|
||||
@@ -1904,7 +1902,7 @@ namespace UVtools.WPF
|
||||
$"Ratio: {xRatio}:{yRatio}\n",
|
||||
"Incorrect image ratio detected");
|
||||
}
|
||||
|
||||
RefreshProperties();
|
||||
ResetDataContext();
|
||||
|
||||
ForceUpdateActualLayer(actualLayer.Clamp(actualLayer, SliderMaximumValue));
|
||||
@@ -2234,6 +2232,11 @@ namespace UVtools.WPF
|
||||
|
||||
}
|
||||
|
||||
public void OpenTerminal()
|
||||
{
|
||||
new TerminalWindow().Show(this);
|
||||
}
|
||||
|
||||
#region Operations
|
||||
|
||||
public async Task<Operation> ShowRunOperation(Operation loadOperation) =>
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
<PackageLicenseFile>LICENSE</PackageLicenseFile>
|
||||
<RepositoryUrl>https://github.com/sn4k3/UVtools</RepositoryUrl>
|
||||
<RepositoryType>Git</RepositoryType>
|
||||
<Version>2.28.0</Version>
|
||||
<Version>2.28.1</Version>
|
||||
<Platforms>AnyCPU;x64</Platforms>
|
||||
<PackageIcon>UVtools.png</PackageIcon>
|
||||
<PackageReadmeFile>README.md</PackageReadmeFile>
|
||||
@@ -44,7 +44,7 @@
|
||||
<PackageReference Include="Avalonia.Desktop" Version="0.10.12" />
|
||||
<PackageReference Include="Avalonia.Diagnostics" Version="0.10.12" />
|
||||
<PackageReference Include="Emgu.CV.runtime.windows" Version="4.5.5.4823" />
|
||||
<PackageReference Include="MessageBox.Avalonia" Version="1.7.1" />
|
||||
<PackageReference Include="MessageBox.Avalonia" Version="1.8.1-night" />
|
||||
<PackageReference Include="ThemeEditor.Controls.ColorPicker" Version="0.10.12" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
<uc:WindowEx xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:uc="clr-namespace:UVtools.WPF.Controls"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="500"
|
||||
MinWidth="500"
|
||||
MinHeight="300"
|
||||
Width="800"
|
||||
Height="500"
|
||||
Padding="10"
|
||||
WindowStartupLocation="CenterOwner"
|
||||
DragDrop.AllowDrop="True"
|
||||
Icon="/Assets/Icons/UVtools.ico"
|
||||
x:Class="UVtools.WPF.Windows.TerminalWindow"
|
||||
Title="UVtools interactive terminal">
|
||||
<Grid RowDefinitions="4*,5,*,5,Auto">
|
||||
<TextBox Grid.Row="0"
|
||||
Name="TerminalTextBox"
|
||||
AcceptsReturn="True"
|
||||
IsReadOnly="True"
|
||||
Watermark="Terminal"
|
||||
UseFloatingWatermark="True"
|
||||
Text="{Binding TerminalText}"/>
|
||||
|
||||
<GridSplitter Grid.Row="1"
|
||||
ResizeDirection="Rows"
|
||||
ResizeBehavior="PreviousAndNext"/>
|
||||
|
||||
<TextBox Grid.Row="2"
|
||||
AcceptsReturn="{Binding MultiLine}"
|
||||
Watermark="> Type in the command or text to send
|
||||

Alt + enter: Shortcut to send the command"
|
||||
Text="{Binding CommandText}"/>
|
||||
|
||||
<WrapPanel Grid.Row="4" Orientation="Horizontal" HorizontalAlignment="Right">
|
||||
<!--
|
||||
<ToggleSwitch VerticalAlignment="Center"
|
||||
IsChecked="{Binding MultiLine}"
|
||||
OnContent="Multi line"
|
||||
OffContent="Single line"/>
|
||||
-->
|
||||
<ToggleButton Margin="0,0,0,0"
|
||||
VerticalAlignment="Center"
|
||||
IsChecked="{Binding Verbose}"
|
||||
ToolTip.Tip="Sent command appears on the terminal text"
|
||||
Content="Verbose"/>
|
||||
|
||||
<ToggleButton Margin="2,0,0,0"
|
||||
VerticalAlignment="Center"
|
||||
IsChecked="{Binding ClearCommandAfterSend}"
|
||||
ToolTip.Tip="Clears the sent command on the input box"
|
||||
Content="Clear"/>
|
||||
|
||||
<ToggleButton Margin="2,0,0,0"
|
||||
VerticalAlignment="Center"
|
||||
IsChecked="{Binding AutoScroll}"
|
||||
Content="Auto scroll"/>
|
||||
|
||||
|
||||
<Button Margin="15,0,0,0"
|
||||
Content="Clear"
|
||||
VerticalAlignment="Center"
|
||||
Command="{Binding Clear}"
|
||||
ToolTip.Tip="Clears the terminal text (cls)
|
||||

Alt + delete"
|
||||
HotKey="Alt+Delete"/>
|
||||
<Button Margin="5,0,0,0"
|
||||
Content="Send"
|
||||
Padding="40,6"
|
||||
VerticalAlignment="Center"
|
||||
Command="{Binding SendCommand}"
|
||||
IsDefault="True"
|
||||
HotKey="Alt+Enter"/>
|
||||
</WrapPanel>
|
||||
|
||||
</Grid>
|
||||
</uc:WindowEx>
|
||||
@@ -0,0 +1,200 @@
|
||||
/*
|
||||
* 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.IO;
|
||||
using System.Text;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using Microsoft.CodeAnalysis.CSharp.Scripting;
|
||||
using Microsoft.CodeAnalysis.Scripting;
|
||||
using UVtools.Core;
|
||||
using UVtools.WPF.Controls;
|
||||
|
||||
namespace UVtools.WPF.Windows
|
||||
{
|
||||
public partial class TerminalWindow : WindowEx
|
||||
{
|
||||
private static readonly string DefaultTerminalText = $"> Welcome to {About.Software} interactive terminal.\n" +
|
||||
"> Type in some commands in C# language to inject code.\n" +
|
||||
"> Example 1: SlicerFile.FirstLayer\n" +
|
||||
"> Example 2: SlicerFile.ExposureTime = 3\n\n";
|
||||
|
||||
private string _terminalText = DefaultTerminalText;
|
||||
private string _commandText = string.Empty;
|
||||
|
||||
private bool _multiLine = true;
|
||||
private bool _autoScroll = true;
|
||||
private bool _verbose;
|
||||
private bool _clearCommandAfterSend = true;
|
||||
|
||||
private readonly TextBox _terminalTextBox;
|
||||
public ScriptState _scriptState;
|
||||
|
||||
#region Properties
|
||||
|
||||
public string TerminalText
|
||||
{
|
||||
get => _terminalText;
|
||||
set
|
||||
{
|
||||
if(!RaiseAndSetIfChanged(ref _terminalText, value)) return;
|
||||
if(_autoScroll) _terminalTextBox.CaretIndex = _terminalText.Length - 1;
|
||||
}
|
||||
}
|
||||
|
||||
public string CommandText
|
||||
{
|
||||
get => _commandText;
|
||||
set => RaiseAndSetIfChanged(ref _commandText, value ?? string.Empty);
|
||||
}
|
||||
|
||||
public bool MultiLine
|
||||
{
|
||||
get => _multiLine;
|
||||
set => RaiseAndSetIfChanged(ref _multiLine, value);
|
||||
}
|
||||
|
||||
public bool AutoScroll
|
||||
{
|
||||
get => _autoScroll;
|
||||
set => RaiseAndSetIfChanged(ref _autoScroll, value);
|
||||
}
|
||||
|
||||
public bool Verbose
|
||||
{
|
||||
get => _verbose;
|
||||
set => RaiseAndSetIfChanged(ref _verbose, value);
|
||||
}
|
||||
|
||||
public bool ClearCommandAfterSend
|
||||
{
|
||||
get => _clearCommandAfterSend;
|
||||
set => RaiseAndSetIfChanged(ref _clearCommandAfterSend, value);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public TerminalWindow()
|
||||
{
|
||||
InitializeComponent();
|
||||
#if DEBUG
|
||||
this.AttachDevTools();
|
||||
#endif
|
||||
|
||||
_terminalTextBox = this.FindControl<TextBox>("TerminalTextBox");
|
||||
AddHandler(DragDrop.DropEvent, (sender, e) =>
|
||||
{
|
||||
var text = e.Data.GetText();
|
||||
if (text is not null)
|
||||
{
|
||||
CommandText = text;
|
||||
return;
|
||||
}
|
||||
|
||||
var fileNames = e.Data.GetFileNames();
|
||||
if (fileNames is not null)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
foreach (var fileName in fileNames)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!File.Exists(fileName)) continue;
|
||||
var fi = new FileInfo(fileName);
|
||||
if(fi.Length > 5000000) continue; // 5Mb only!
|
||||
sb.AppendLine(File.ReadAllText(fi.FullName));
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
Console.WriteLine(exception);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
CommandText = sb.ToString();
|
||||
}
|
||||
});
|
||||
|
||||
DataContext = this;
|
||||
}
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
TerminalText = DefaultTerminalText;
|
||||
}
|
||||
|
||||
public async void SendCommand()
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(_commandText))
|
||||
{
|
||||
TerminalText += '\n';
|
||||
return;
|
||||
}
|
||||
|
||||
var output = new StringBuilder(_terminalText);
|
||||
if (_verbose) output.AppendLine(_commandText);
|
||||
|
||||
try
|
||||
{
|
||||
if (_scriptState is null)
|
||||
{
|
||||
_scriptState = CSharpScript.RunAsync(_commandText,
|
||||
ScriptOptions.Default
|
||||
.AddReferences(typeof(About).Assembly)
|
||||
.AddImports(
|
||||
"System",
|
||||
"System.Collections.Generic",
|
||||
"System.Math",
|
||||
"System.IO",
|
||||
"System.Linq",
|
||||
"System.Threading",
|
||||
"System.Threading.Tasks",
|
||||
"UVtools.Core",
|
||||
"UVtools.Core.Extensions",
|
||||
"UVtools.Core.FileFormats",
|
||||
"UVtools.Core.Layers",
|
||||
"UVtools.Core.Objects",
|
||||
"UVtools.Core.Operations")
|
||||
.WithAllowUnsafe(true), this).Result;
|
||||
}
|
||||
else
|
||||
{
|
||||
_scriptState = await _scriptState.ContinueWithAsync(_commandText);
|
||||
}
|
||||
|
||||
if (_scriptState.ReturnValue is not null)
|
||||
{
|
||||
output.AppendLine(_scriptState.ReturnValue.ToString());
|
||||
}
|
||||
else if (_scriptState.Exception is not null)
|
||||
{
|
||||
output.AppendLine(_scriptState.Exception.ToString());
|
||||
}
|
||||
else if(!_verbose)
|
||||
{
|
||||
output.AppendLine(_commandText);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
output.AppendLine(e.Message);
|
||||
}
|
||||
|
||||
TerminalText = output.ToString();
|
||||
|
||||
if (_clearCommandAfterSend) CommandText = string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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.Collections.ObjectModel;
|
||||
using System.Drawing;
|
||||
using Avalonia;
|
||||
|
||||
Reference in New Issue
Block a user