diff options
author | Tiago Conceição <Tiago_caza@hotmail.com> | 2021-05-11 21:10:36 +0300 |
---|---|---|
committer | Tiago Conceição <Tiago_caza@hotmail.com> | 2021-05-11 21:10:36 +0300 |
commit | 3cd46728f1ca599d1f2211d9ff07273135d670af (patch) | |
tree | 0f322d5ae72f35be4a0b793d0f82c7825a2ceb4d /UVtools.WPF | |
parent | dc0e90a61311b2d78104e46ac34c8faf382dcbd3 (diff) |
v2.11.1v2.11.1
- **Shortcuts:**
- (Add) (Ctrl + Shift + R) to turn on and cycle the Rotate modes
- (Add) (Ctrl + Shift + F) to turn on and cycle the Flip modes
- (Add) (Ctrl + Shift + B) to select the build volume as ROI
- **GUI:**
- (Add) Allow to drag and drop '.uvtop' files into UVtools to sequential show and load operations from files
- (Change) Rotate icon on layer preview
- (Upgrade) AvaloniaUI from 0.10.3 to 0.10.4
- **Tools:**
- (Add) 'Reset to defaults' button on every dialog
- (Improvement) Window size and position handling
- (Improvement) Constrain profile box width to not stretch the window
- (Improvement) ROI section design
- **Dynamic lift:**
- (Add) View buttons to show the largest/smallest layers
- (Add) Light-off mode: Set the light-off with an extra delay
- (Add) Light-off mode: Set the light-off without an extra delay
- (Add) Light-off mode: Set the light-off to zero
- (Improvement) Disable bottom and/or normal layer fields when the selected range is outside
- (Add) Settings - Automations: Light-off delay set modes
- (Fix) Exposure time finder: Add staircase, bullseye and counter triangles to feature count at thumbnail
Diffstat (limited to 'UVtools.WPF')
32 files changed, 594 insertions, 249 deletions
diff --git a/UVtools.WPF/Controls/Calibrators/CalibrateElephantFootControl.axaml.cs b/UVtools.WPF/Controls/Calibrators/CalibrateElephantFootControl.axaml.cs index f5ec546..d4c9d89 100644 --- a/UVtools.WPF/Controls/Calibrators/CalibrateElephantFootControl.axaml.cs +++ b/UVtools.WPF/Controls/Calibrators/CalibrateElephantFootControl.axaml.cs @@ -53,7 +53,7 @@ namespace UVtools.WPF.Controls.Calibrators switch (callback) { case ToolWindow.Callbacks.Init: - case ToolWindow.Callbacks.ProfileLoaded: + case ToolWindow.Callbacks.Loaded: Operation.PropertyChanged += (sender, e) => { _timer.Stop(); diff --git a/UVtools.WPF/Controls/Calibrators/CalibrateExposureFinderControl.axaml.cs b/UVtools.WPF/Controls/Calibrators/CalibrateExposureFinderControl.axaml.cs index 1d0e252..52aaf61 100644 --- a/UVtools.WPF/Controls/Calibrators/CalibrateExposureFinderControl.axaml.cs +++ b/UVtools.WPF/Controls/Calibrators/CalibrateExposureFinderControl.axaml.cs @@ -57,7 +57,7 @@ namespace UVtools.WPF.Controls.Calibrators switch (callback) { case ToolWindow.Callbacks.Init: - case ToolWindow.Callbacks.ProfileLoaded: + case ToolWindow.Callbacks.Loaded: Operation.PropertyChanged += (sender, e) => { _timer.Stop(); diff --git a/UVtools.WPF/Controls/Calibrators/CalibrateGrayscaleControl.axaml.cs b/UVtools.WPF/Controls/Calibrators/CalibrateGrayscaleControl.axaml.cs index ebf1a31..b585105 100644 --- a/UVtools.WPF/Controls/Calibrators/CalibrateGrayscaleControl.axaml.cs +++ b/UVtools.WPF/Controls/Calibrators/CalibrateGrayscaleControl.axaml.cs @@ -46,7 +46,7 @@ namespace UVtools.WPF.Controls.Calibrators switch (callback) { case ToolWindow.Callbacks.Init: - case ToolWindow.Callbacks.ProfileLoaded: + case ToolWindow.Callbacks.Loaded: Operation.PropertyChanged += (sender, e) => { _timer.Stop(); diff --git a/UVtools.WPF/Controls/Calibrators/CalibrateStressTowerControl.axaml.cs b/UVtools.WPF/Controls/Calibrators/CalibrateStressTowerControl.axaml.cs index 4825095..60f3fe7 100644 --- a/UVtools.WPF/Controls/Calibrators/CalibrateStressTowerControl.axaml.cs +++ b/UVtools.WPF/Controls/Calibrators/CalibrateStressTowerControl.axaml.cs @@ -31,7 +31,7 @@ namespace UVtools.WPF.Controls.Calibrators switch (callback) { case ToolWindow.Callbacks.Init: - case ToolWindow.Callbacks.ProfileLoaded: + case ToolWindow.Callbacks.Loaded: break; } }*/ diff --git a/UVtools.WPF/Controls/Calibrators/CalibrateToleranceControl.axaml.cs b/UVtools.WPF/Controls/Calibrators/CalibrateToleranceControl.axaml.cs index 19e4103..544b49a 100644 --- a/UVtools.WPF/Controls/Calibrators/CalibrateToleranceControl.axaml.cs +++ b/UVtools.WPF/Controls/Calibrators/CalibrateToleranceControl.axaml.cs @@ -59,7 +59,7 @@ namespace UVtools.WPF.Controls.Calibrators switch (callback) { case ToolWindow.Callbacks.Init: - case ToolWindow.Callbacks.ProfileLoaded: + case ToolWindow.Callbacks.Loaded: Operation.PropertyChanged += (sender, e) => { _timer.Stop(); diff --git a/UVtools.WPF/Controls/Calibrators/CalibrateXYZAccuracyControl.axaml.cs b/UVtools.WPF/Controls/Calibrators/CalibrateXYZAccuracyControl.axaml.cs index 26b515b..09c514f 100644 --- a/UVtools.WPF/Controls/Calibrators/CalibrateXYZAccuracyControl.axaml.cs +++ b/UVtools.WPF/Controls/Calibrators/CalibrateXYZAccuracyControl.axaml.cs @@ -57,7 +57,7 @@ namespace UVtools.WPF.Controls.Calibrators switch (callback) { case ToolWindow.Callbacks.Init: - case ToolWindow.Callbacks.ProfileLoaded: + case ToolWindow.Callbacks.Loaded: Operation.PropertyChanged += (sender, e) => { _timer.Stop(); diff --git a/UVtools.WPF/Controls/Tools/ToolCalculatorControl.axaml.cs b/UVtools.WPF/Controls/Tools/ToolCalculatorControl.axaml.cs index 347f91c..a31547f 100644 --- a/UVtools.WPF/Controls/Tools/ToolCalculatorControl.axaml.cs +++ b/UVtools.WPF/Controls/Tools/ToolCalculatorControl.axaml.cs @@ -2,6 +2,7 @@ using Avalonia.Markup.Xaml; using UVtools.Core.FileFormats; using UVtools.Core.Operations; +using UVtools.WPF.Windows; namespace UVtools.WPF.Controls.Tools { @@ -20,18 +21,6 @@ namespace UVtools.WPF.Controls.Tools { InitializeComponent(); BaseOperation = new OperationCalculator(SlicerFile); - Operation.CalcLightOffDelay.PropertyChanged += (sender, e) => - { - if (e.PropertyName != nameof(Operation.CalcLightOffDelay.LightOffDelay) && - e.PropertyName != nameof(Operation.CalcLightOffDelay.BottomLightOffDelay)) return; - LightOffDelayPrintTimeHours = Math.Round( - (FileFormat.ExtraPrintTime + - SlicerFile.BottomLayerCount * (Operation.CalcLightOffDelay.BottomLightOffDelay + (decimal) SlicerFile.BottomExposureTime) + - SlicerFile.NormalLayerCount * (Operation.CalcLightOffDelay.LightOffDelay + (decimal)SlicerFile.ExposureTime)) - / 3600, 2); - }; - - _lightOffDelayPrintTimeHours = (decimal) SlicerFile.PrintTimeHours; } private void InitializeComponent() @@ -39,6 +28,28 @@ namespace UVtools.WPF.Controls.Tools AvaloniaXamlLoader.Load(this); } + public override void Callback(ToolWindow.Callbacks callback) + { + switch (callback) + { + case ToolWindow.Callbacks.Init: + case ToolWindow.Callbacks.Loaded: + Operation.CalcLightOffDelay.PropertyChanged += (sender, e) => + { + if (e.PropertyName != nameof(Operation.CalcLightOffDelay.LightOffDelay) && + e.PropertyName != nameof(Operation.CalcLightOffDelay.BottomLightOffDelay)) return; + LightOffDelayPrintTimeHours = Math.Round( + (FileFormat.ExtraPrintTime + + SlicerFile.BottomLayerCount * (Operation.CalcLightOffDelay.BottomLightOffDelay + (decimal)SlicerFile.BottomExposureTime) + + SlicerFile.NormalLayerCount * (Operation.CalcLightOffDelay.LightOffDelay + (decimal)SlicerFile.ExposureTime)) + / 3600, 2); + }; + + _lightOffDelayPrintTimeHours = (decimal)SlicerFile.PrintTimeHours; + break; + } + } + public void LightOffDelaySetParameters(byte side) { if (side == 0) // Bottom layers diff --git a/UVtools.WPF/Controls/Tools/ToolChangeResolutionControl.axaml.cs b/UVtools.WPF/Controls/Tools/ToolChangeResolutionControl.axaml.cs index 059a13d..8f60728 100644 --- a/UVtools.WPF/Controls/Tools/ToolChangeResolutionControl.axaml.cs +++ b/UVtools.WPF/Controls/Tools/ToolChangeResolutionControl.axaml.cs @@ -21,7 +21,7 @@ namespace UVtools.WPF.Controls.Tools Operation.NewResolutionY = _selectedPresetItem.ResolutionY; //SelectedPresetItem = null; - Timer timer = new Timer(1); + Timer timer = new(1); timer.Elapsed += (sender, args) => { SelectedPresetItem = null; diff --git a/UVtools.WPF/Controls/Tools/ToolControl.axaml.cs b/UVtools.WPF/Controls/Tools/ToolControl.axaml.cs index 09dc732..d4937a1 100644 --- a/UVtools.WPF/Controls/Tools/ToolControl.axaml.cs +++ b/UVtools.WPF/Controls/Tools/ToolControl.axaml.cs @@ -16,8 +16,16 @@ namespace UVtools.WPF.Controls.Tools get => _baseOperation; set { + bool wasNullBefore = _baseOperation is null; _baseOperation = value; + _baseOperation.SlicerFile = SlicerFile; RaisePropertyChanged(); + + if (!wasNullBefore) + { + Callback(ToolWindow.Callbacks.Loaded); + } + if (DataContext is null) return; ResetDataContext(); } diff --git a/UVtools.WPF/Controls/Tools/ToolDynamicLayerHeightControl.axaml.cs b/UVtools.WPF/Controls/Tools/ToolDynamicLayerHeightControl.axaml.cs index c83933c..489c950 100644 --- a/UVtools.WPF/Controls/Tools/ToolDynamicLayerHeightControl.axaml.cs +++ b/UVtools.WPF/Controls/Tools/ToolDynamicLayerHeightControl.axaml.cs @@ -70,7 +70,7 @@ namespace UVtools.WPF.Controls.Tools switch (callback) { case ToolWindow.Callbacks.Init: - case ToolWindow.Callbacks.ProfileLoaded: + case ToolWindow.Callbacks.Loaded: /*Operation.PropertyChanged += (sender, e) => { if (e.PropertyName.Equals(nameof(Operation.CacheObjectCount))) diff --git a/UVtools.WPF/Controls/Tools/ToolDynamicLiftsControl.axaml b/UVtools.WPF/Controls/Tools/ToolDynamicLiftsControl.axaml index 1a638c1..91a4219 100644 --- a/UVtools.WPF/Controls/Tools/ToolDynamicLiftsControl.axaml +++ b/UVtools.WPF/Controls/Tools/ToolDynamicLiftsControl.axaml @@ -5,8 +5,51 @@ mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" x:Class="UVtools.WPF.Controls.Tools.ToolDynamicLiftsControl"> <StackPanel Spacing="10"> - <Grid RowDefinitions="Auto,10,Auto,10,Auto,10,Auto,10,Auto" - ColumnDefinitions="Auto,10,150,20,150,5,Auto"> + + <!-- + <Grid RowDefinitions="Auto,5,Auto" + ColumnDefinitions="Auto,5,Auto,5,Auto" + HorizontalAlignment="Center"> + + <TextBlock Grid.Row="0" Grid.Column="0" + VerticalAlignment="Center" + FontWeight="Bold" + Text="View smallest:"/> + + <TextBlock Grid.Row="2" Grid.Column="0" + VerticalAlignment="Center" + FontWeight="Bold" + Text="View largest:"/> + + + <Button Grid.Row="0" Grid.Column="2" + VerticalAlignment="Stretch" + HorizontalAlignment="Stretch" + HorizontalContentAlignment="Center" + Content="Bottom"/> + + <Button Grid.Row="0" Grid.Column="4" + VerticalAlignment="Stretch" + HorizontalAlignment="Stretch" + HorizontalContentAlignment="Center" + Content="Normal"/> + + <Button Grid.Row="2" Grid.Column="2" + VerticalAlignment="Stretch" + HorizontalAlignment="Stretch" + HorizontalContentAlignment="Center" + Content="Bottom"/> + + <Button Grid.Row="2" Grid.Column="4" + VerticalAlignment="Stretch" + HorizontalAlignment="Stretch" + HorizontalContentAlignment="Center" + Content="Normal"/> + + </Grid> +--> + <Grid RowDefinitions="Auto,10,Auto,10,Auto,10,Auto,10,Auto,10,Auto,10,Auto,5,Auto" + ColumnDefinitions="Auto,10,150,20,150,5,Auto,10,Auto"> <TextBlock Grid.Row="0" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Center" @@ -31,11 +74,19 @@ FontWeight="Bold" Text="Unit"/> + <TextBlock Grid.Row="0" Grid.Column="8" + VerticalAlignment="Center" + HorizontalAlignment="Center" + FontWeight="Bold" + Text="View"/> + <TextBlock Grid.Row="2" Grid.Column="0" + IsEnabled="{Binding Operation.IsBottomLayersEnabled}" VerticalAlignment="Center" Text="Bottom lift height:"/> <NumericUpDown Grid.Row="2" Grid.Column="2" + IsEnabled="{Binding Operation.IsBottomLayersEnabled}" VerticalAlignment="Center" Minimum="1" Maximum="100" @@ -44,11 +95,13 @@ Value="{Binding Operation.MinBottomLiftHeight}"/> <TextBlock Grid.Row="2" Grid.Column="3" + IsEnabled="{Binding Operation.IsBottomLayersEnabled}" VerticalAlignment="Center" HorizontalAlignment="Center" Text="/"/> <NumericUpDown Grid.Row="2" Grid.Column="4" + IsEnabled="{Binding Operation.IsBottomLayersEnabled}" VerticalAlignment="Center" Minimum="1" Maximum="100" @@ -57,14 +110,27 @@ Value="{Binding Operation.MaxBottomLiftHeight}"/> <TextBlock Grid.Row="2" Grid.Column="6" + IsEnabled="{Binding Operation.IsBottomLayersEnabled}" VerticalAlignment="Center" Text="mm"/> + <Button Grid.Row="2" Grid.Column="8" + IsEnabled="{Binding Operation.IsBottomLayersEnabled}" + VerticalAlignment="Stretch" + HorizontalAlignment="Stretch" + HorizontalContentAlignment="Center" + ToolTip.Tip="View the smallest bottom layer for the selected layer range" + Command="{Binding ViewSmallestLayer}" + CommandParameter="True" + Content="Smallest"/> + <TextBlock Grid.Row="4" Grid.Column="0" + IsEnabled="{Binding Operation.IsBottomLayersEnabled}" VerticalAlignment="Center" Text="Bottom lift speed:"/> <NumericUpDown Grid.Row="4" Grid.Column="2" + IsEnabled="{Binding Operation.IsBottomLayersEnabled}" VerticalAlignment="Center" Minimum="5" Maximum="1000" @@ -73,11 +139,13 @@ Value="{Binding Operation.MinBottomLiftSpeed}"/> <TextBlock Grid.Row="4" Grid.Column="3" + IsEnabled="{Binding Operation.IsBottomLayersEnabled}" VerticalAlignment="Center" HorizontalAlignment="Center" Text="/"/> <NumericUpDown Grid.Row="4" Grid.Column="4" + IsEnabled="{Binding Operation.IsBottomLayersEnabled}" VerticalAlignment="Center" Minimum="5" Maximum="1000" @@ -86,15 +154,28 @@ Value="{Binding Operation.MaxBottomLiftSpeed}"/> <TextBlock Grid.Row="4" Grid.Column="6" + IsEnabled="{Binding Operation.IsBottomLayersEnabled}" VerticalAlignment="Center" Text="mm/min"/> + <Button Grid.Row="4" Grid.Column="8" + IsEnabled="{Binding Operation.IsBottomLayersEnabled}" + VerticalAlignment="Stretch" + HorizontalAlignment="Stretch" + HorizontalContentAlignment="Center" + Command="{Binding ViewLargestLayer}" + CommandParameter="True" + ToolTip.Tip="View the largest bottom layer for the selected layer range" + Content="Largest"/> + <TextBlock Grid.Row="6" Grid.Column="0" + IsEnabled="{Binding Operation.IsNormalLayersEnabled}" VerticalAlignment="Center" Text="Lift height:"/> <NumericUpDown Grid.Row="6" Grid.Column="2" + IsEnabled="{Binding Operation.IsNormalLayersEnabled}" VerticalAlignment="Center" Minimum="1" Maximum="100" @@ -103,11 +184,13 @@ Value="{Binding Operation.MinLiftHeight}"/> <TextBlock Grid.Row="6" Grid.Column="3" + IsEnabled="{Binding Operation.IsNormalLayersEnabled}" VerticalAlignment="Center" HorizontalAlignment="Center" Text="/"/> <NumericUpDown Grid.Row="6" Grid.Column="4" + IsEnabled="{Binding Operation.IsNormalLayersEnabled}" VerticalAlignment="Center" Minimum="1" Maximum="100" @@ -116,14 +199,27 @@ Value="{Binding Operation.MaxLiftHeight}"/> <TextBlock Grid.Row="6" Grid.Column="6" + IsEnabled="{Binding Operation.IsNormalLayersEnabled}" VerticalAlignment="Center" Text="mm"/> + <Button Grid.Row="6" Grid.Column="8" + IsEnabled="{Binding Operation.IsNormalLayersEnabled}" + VerticalAlignment="Stretch" + HorizontalAlignment="Stretch" + HorizontalContentAlignment="Center" + Command="{Binding ViewSmallestLayer}" + CommandParameter="False" + ToolTip.Tip="View the smallest normal layer for the selected layer range" + Content="Smallest"/> + <TextBlock Grid.Row="8" Grid.Column="0" + IsEnabled="{Binding Operation.IsNormalLayersEnabled}" VerticalAlignment="Center" Text="Lift speed:"/> <NumericUpDown Grid.Row="8" Grid.Column="2" + IsEnabled="{Binding Operation.IsNormalLayersEnabled}" VerticalAlignment="Center" Minimum="5" Maximum="1000" @@ -132,11 +228,13 @@ Value="{Binding Operation.MinLiftSpeed}"/> <TextBlock Grid.Row="8" Grid.Column="3" + IsEnabled="{Binding Operation.IsNormalLayersEnabled}" VerticalAlignment="Center" HorizontalAlignment="Center" Text="/"/> <NumericUpDown Grid.Row="8" Grid.Column="4" + IsEnabled="{Binding Operation.IsNormalLayersEnabled}" VerticalAlignment="Center" Minimum="5" Maximum="1000" @@ -145,63 +243,86 @@ Value="{Binding Operation.MaxLiftSpeed}"/> <TextBlock Grid.Row="8" Grid.Column="6" + IsEnabled="{Binding Operation.IsNormalLayersEnabled}" VerticalAlignment="Center" Text="mm/min"/> - </Grid> - <CheckBox - Content="Update light-off delay accordingly" - ToolTip.Tip="If enabled, it will auto calculate the correct light-off delay based on the set lift" - IsChecked="{Binding Operation.UpdateLightOffDelay}"/> + <Button Grid.Row="8" Grid.Column="8" + IsEnabled="{Binding Operation.IsNormalLayersEnabled}" + VerticalAlignment="Stretch" + HorizontalAlignment="Stretch" + HorizontalContentAlignment="Center" + Command="{Binding ViewLargestLayer}" + CommandParameter="False" + ToolTip.Tip="View the largest normal layer for the selected layer range" + Content="Largest"/> + + <TextBlock Grid.Row="10" Grid.Column="0" + VerticalAlignment="Center" + Text="Light-off mode:"/> - <Grid RowDefinitions="Auto,10,Auto" - ColumnDefinitions="Auto,20,Auto,5,Auto" - IsEnabled="{Binding Operation.UpdateLightOffDelay}"> + <ComboBox Grid.Row="10" Grid.Column="2" + Grid.ColumnSpan="3" + HorizontalAlignment="Stretch" + Items="{Binding Operation.LightOffDelaySetMode, Converter={StaticResource EnumToCollectionConverter}, Mode=OneTime}" + SelectedItem="{Binding Operation.LightOffDelaySetMode, Converter={StaticResource FromValueDescriptionToEnumConverter}}"/> - <TextBlock Grid.Row="0" Grid.Column="0" - VerticalAlignment="Center" - HorizontalAlignment="Center" - FontWeight="Bold" - Text="Bottom light-off extra time"/> + <TextBlock Grid.Row="12" Grid.Column="2" + IsEnabled="{Binding !Operation.LightOffSetMode}" + IsVisible="{Binding !Operation.LightOffSetMode}" + VerticalAlignment="Center" + HorizontalAlignment="Center" + FontWeight="Bold" + Text="Bottom extra time"/> - <TextBlock Grid.Row="0" Grid.Column="1" - VerticalAlignment="Center" - HorizontalAlignment="Center" - FontWeight="Bold" - Text="/"/> + <TextBlock Grid.Row="12" Grid.Column="4" + IsEnabled="{Binding !Operation.LightOffSetMode}" + IsVisible="{Binding !Operation.LightOffSetMode}" + VerticalAlignment="Center" + HorizontalAlignment="Center" + FontWeight="Bold" + Text="Normal extra time"/> - <TextBlock Grid.Row="0" Grid.Column="2" - VerticalAlignment="Center" - HorizontalAlignment="Center" - FontWeight="Bold" - Text="Normal light-off extra time"/> + <TextBlock Grid.Row="14" Grid.Column="0" + IsEnabled="{Binding !Operation.LightOffSetMode}" + IsVisible="{Binding !Operation.LightOffSetMode}" + VerticalAlignment="Center" + Text="Light-off delay:"/> + + <NumericUpDown Grid.Row="14" Grid.Column="2" + IsEnabled="{Binding !Operation.LightOffSetMode}" + IsVisible="{Binding !Operation.LightOffSetMode}" + VerticalAlignment="Center" + Minimum="0" + Maximum="100" + Increment="1" + FormatString="F2" + Value="{Binding Operation.LightOffDelayBottomExtraTime}"/> - <NumericUpDown Grid.Row="2" Grid.Column="0" - VerticalAlignment="Center" - Minimum="0" - Maximum="100" - Increment="1" - FormatString="F2" - Value="{Binding Operation.LightOffDelayBottomExtraTime}"/> + <TextBlock Grid.Row="14" Grid.Column="3" + IsEnabled="{Binding !Operation.LightOffSetMode}" + IsVisible="{Binding !Operation.LightOffSetMode}" + VerticalAlignment="Center" + HorizontalAlignment="Center" + FontWeight="Bold" + Text="/"/> - <TextBlock Grid.Row="2" Grid.Column="1" - VerticalAlignment="Center" - HorizontalAlignment="Center" - Text="/"/> - - <NumericUpDown Grid.Row="2" Grid.Column="2" - VerticalAlignment="Center" - Minimum="0" - Maximum="100" - Increment="1" - FormatString="F2" - Value="{Binding Operation.LightOffDelayExtraTime}"/> - - <TextBlock Grid.Row="2" Grid.Column="4" - VerticalAlignment="Center" - Text="s"/> + <NumericUpDown Grid.Row="14" Grid.Column="4" + IsEnabled="{Binding !Operation.LightOffSetMode}" + IsVisible="{Binding !Operation.LightOffSetMode}" + VerticalAlignment="Center" + Minimum="0" + Maximum="100" + Increment="1" + FormatString="F2" + Value="{Binding Operation.LightOffDelayExtraTime}"/> - </Grid> + <TextBlock Grid.Row="14" Grid.Column="6" + IsEnabled="{Binding !Operation.LightOffSetMode}" + IsVisible="{Binding !Operation.LightOffSetMode}" + VerticalAlignment="Center" + Text="s"/> + </Grid> </StackPanel> </UserControl> diff --git a/UVtools.WPF/Controls/Tools/ToolDynamicLiftsControl.axaml.cs b/UVtools.WPF/Controls/Tools/ToolDynamicLiftsControl.axaml.cs index 8bd4573..ef0e742 100644 --- a/UVtools.WPF/Controls/Tools/ToolDynamicLiftsControl.axaml.cs +++ b/UVtools.WPF/Controls/Tools/ToolDynamicLiftsControl.axaml.cs @@ -1,4 +1,6 @@ +using System.Linq; using Avalonia.Markup.Xaml; +using MoreLinq.Extensions; using UVtools.Core.FileFormats; using UVtools.Core.Operations; using UVtools.WPF.Extensions; @@ -24,5 +26,19 @@ namespace UVtools.WPF.Controls.Tools { AvaloniaXamlLoader.Load(this); } + + public void ViewSmallestLayer(bool isBottom) + { + var layerFound = Operation.GetSmallestLayer(isBottom); + if (layerFound is null) return; + App.MainWindow.ActualLayer = layerFound.Index; + } + + public void ViewLargestLayer(bool isBottom) + { + var layerFound = Operation.GetLargestLayer(isBottom); + if (layerFound is null) return; + App.MainWindow.ActualLayer = layerFound.Index; + } } } diff --git a/UVtools.WPF/Controls/Tools/ToolEditParametersControl.axaml.cs b/UVtools.WPF/Controls/Tools/ToolEditParametersControl.axaml.cs index 0b88b49..f71bef9 100644 --- a/UVtools.WPF/Controls/Tools/ToolEditParametersControl.axaml.cs +++ b/UVtools.WPF/Controls/Tools/ToolEditParametersControl.axaml.cs @@ -185,18 +185,15 @@ namespace UVtools.WPF.Controls.Tools switch (callback) { case ToolWindow.Callbacks.Init: - case ToolWindow.Callbacks.ProfileLoaded: - ParentWindow.IsButton1Visible = true; - ParentWindow.SelectCurrentLayer(); - ParentWindow.LayerRangeSync = true; - PopulateGrid(); - Operation.PropertyChanged += OperationOnPropertyChanged; - break; - case ToolWindow.Callbacks.Button1: - foreach (var rowControl in RowControls) + case ToolWindow.Callbacks.Loaded: + if (callback is ToolWindow.Callbacks.Init) { - rowControl.NewValue.Value = (double) rowControl.Modifier.OldValue; + ParentWindow.SelectCurrentLayer(); + ParentWindow.LayerRangeSync = true; } + + PopulateGrid(); + Operation.PropertyChanged += OperationOnPropertyChanged; break; } } diff --git a/UVtools.WPF/Controls/Tools/ToolLayerArithmeticControl.axaml.cs b/UVtools.WPF/Controls/Tools/ToolLayerArithmeticControl.axaml.cs index fc07e66..eaf2b35 100644 --- a/UVtools.WPF/Controls/Tools/ToolLayerArithmeticControl.axaml.cs +++ b/UVtools.WPF/Controls/Tools/ToolLayerArithmeticControl.axaml.cs @@ -24,7 +24,7 @@ namespace UVtools.WPF.Controls.Tools switch (callback) { case ToolWindow.Callbacks.Init: - case ToolWindow.Callbacks.ProfileLoaded: + case ToolWindow.Callbacks.Loaded: ParentWindow.ButtonOkEnabled = !string.IsNullOrWhiteSpace(Operation.Sentence); Operation.PropertyChanged += (sender, e) => { diff --git a/UVtools.WPF/Controls/Tools/ToolLayerCloneControl.axaml.cs b/UVtools.WPF/Controls/Tools/ToolLayerCloneControl.axaml.cs index 774f1cb..f562ba8 100644 --- a/UVtools.WPF/Controls/Tools/ToolLayerCloneControl.axaml.cs +++ b/UVtools.WPF/Controls/Tools/ToolLayerCloneControl.axaml.cs @@ -2,6 +2,7 @@ using Avalonia.Markup.Xaml; using UVtools.Core; using UVtools.Core.Operations; +using UVtools.WPF.Windows; namespace UVtools.WPF.Controls.Tools { @@ -33,17 +34,26 @@ namespace UVtools.WPF.Controls.Tools { InitializeComponent(); BaseOperation = new OperationLayerClone(SlicerFile); - Operation.PropertyChanged += (sender, args) => - { - RaisePropertyChanged(nameof(InfoLayersStr)); - RaisePropertyChanged(nameof(InfoHeightsStr)); - }; - } private void InitializeComponent() { AvaloniaXamlLoader.Load(this); } + + public override void Callback(ToolWindow.Callbacks callback) + { + switch (callback) + { + case ToolWindow.Callbacks.Init: + case ToolWindow.Callbacks.Loaded: + Operation.PropertyChanged += (sender, args) => + { + RaisePropertyChanged(nameof(InfoLayersStr)); + RaisePropertyChanged(nameof(InfoHeightsStr)); + }; + break; + } + } } } diff --git a/UVtools.WPF/Controls/Tools/ToolLayerImportControl.axaml.cs b/UVtools.WPF/Controls/Tools/ToolLayerImportControl.axaml.cs index c0e52f5..dbb6600 100644 --- a/UVtools.WPF/Controls/Tools/ToolLayerImportControl.axaml.cs +++ b/UVtools.WPF/Controls/Tools/ToolLayerImportControl.axaml.cs @@ -145,7 +145,7 @@ namespace UVtools.WPF.Controls.Tools switch (callback) { case ToolWindow.Callbacks.Init: - case ToolWindow.Callbacks.ProfileLoaded: + case ToolWindow.Callbacks.Loaded: RefreshGUI(); Operation.Files.CollectionChanged += (sender, args) => RefreshGUI(); Operation.PropertyChanged += (sender, args) => RefreshGUI(); diff --git a/UVtools.WPF/Controls/Tools/ToolLayerRemoveControl.axaml.cs b/UVtools.WPF/Controls/Tools/ToolLayerRemoveControl.axaml.cs index b3a9ea1..dc0a3bd 100644 --- a/UVtools.WPF/Controls/Tools/ToolLayerRemoveControl.axaml.cs +++ b/UVtools.WPF/Controls/Tools/ToolLayerRemoveControl.axaml.cs @@ -2,6 +2,7 @@ using Avalonia.Markup.Xaml; using UVtools.Core; using UVtools.Core.Operations; +using UVtools.WPF.Windows; namespace UVtools.WPF.Controls.Tools { @@ -33,17 +34,26 @@ namespace UVtools.WPF.Controls.Tools { InitializeComponent(); BaseOperation = new OperationLayerRemove(SlicerFile); - Operation.PropertyChanged += (sender, args) => - { - RaisePropertyChanged(nameof(InfoLayersStr)); - RaisePropertyChanged(nameof(InfoHeightsStr)); - }; - } private void InitializeComponent() { AvaloniaXamlLoader.Load(this); } + + public override void Callback(ToolWindow.Callbacks callback) + { + switch (callback) + { + case ToolWindow.Callbacks.Init: + case ToolWindow.Callbacks.Loaded: + Operation.PropertyChanged += (sender, args) => + { + RaisePropertyChanged(nameof(InfoLayersStr)); + RaisePropertyChanged(nameof(InfoHeightsStr)); + }; + break; + } + } } } diff --git a/UVtools.WPF/Controls/Tools/ToolMaskControl.axaml.cs b/UVtools.WPF/Controls/Tools/ToolMaskControl.axaml.cs index 4369133..bd389d6 100644 --- a/UVtools.WPF/Controls/Tools/ToolMaskControl.axaml.cs +++ b/UVtools.WPF/Controls/Tools/ToolMaskControl.axaml.cs @@ -84,6 +84,7 @@ namespace UVtools.WPF.Controls.Tools case ToolWindow.Callbacks.Init: ParentWindow.ButtonOkEnabled = false; break; + case ToolWindow.Callbacks.Loaded: case ToolWindow.Callbacks.ClearROI: Operation.Mask = null; MaskImage = null; diff --git a/UVtools.WPF/Controls/Tools/ToolMoveControl.axaml.cs b/UVtools.WPF/Controls/Tools/ToolMoveControl.axaml.cs index 5e01d2b..3754a4b 100644 --- a/UVtools.WPF/Controls/Tools/ToolMoveControl.axaml.cs +++ b/UVtools.WPF/Controls/Tools/ToolMoveControl.axaml.cs @@ -18,8 +18,8 @@ namespace UVtools.WPF.Controls.Tools public ToolMoveControl() { InitializeComponent(); - var roi = App.MainWindow.ROI; - BaseOperation = new OperationMove(SlicerFile, roi); + + BaseOperation = new OperationMove(SlicerFile); Operation.PropertyChanged += (sender, e) => { @@ -40,16 +40,13 @@ namespace UVtools.WPF.Controls.Tools switch (callback) { case ToolWindow.Callbacks.Init: - ParentWindow.IsButton1Visible = true; + case ToolWindow.Callbacks.Loaded: + Operation.ROI = App.MainWindow.ROI.IsEmpty ? SlicerFile.BoundingRectangle : App.MainWindow.ROI; break; case ToolWindow.Callbacks.ClearROI: - Operation.ROI = App.SlicerFile.LayerManager.BoundingRectangle; + Operation.ROI = SlicerFile.BoundingRectangle; Operation.Reset(); break; - case ToolWindow.Callbacks.Button1: - Operation.Reset(); - IsMiddleCenterChecked = true; - break; } } } diff --git a/UVtools.WPF/Controls/Tools/ToolPatternControl.axaml.cs b/UVtools.WPF/Controls/Tools/ToolPatternControl.axaml.cs index 319ec32..5c31b45 100644 --- a/UVtools.WPF/Controls/Tools/ToolPatternControl.axaml.cs +++ b/UVtools.WPF/Controls/Tools/ToolPatternControl.axaml.cs @@ -30,15 +30,6 @@ namespace UVtools.WPF.Controls.Tools CanRun = false; return; } - - - Operation.PropertyChanged += (sender, e) => - { - if (e.PropertyName.Equals(nameof(Operation.IsWithinBoundary))) - { - ParentWindow.ButtonOkEnabled = Operation.IsWithinBoundary; - } - }; } private void InitializeComponent() @@ -51,14 +42,18 @@ namespace UVtools.WPF.Controls.Tools switch (callback) { case ToolWindow.Callbacks.Init: - ParentWindow.IsButton1Visible = true; + case ToolWindow.Callbacks.Loaded: + Operation.ROI = App.MainWindow.ROI.IsEmpty ? SlicerFile.BoundingRectangle : App.MainWindow.ROI; + Operation.PropertyChanged += (sender, e) => + { + if (e.PropertyName.Equals(nameof(Operation.IsWithinBoundary))) + { + ParentWindow.ButtonOkEnabled = Operation.IsWithinBoundary; + } + }; break; case ToolWindow.Callbacks.ClearROI: - Operation.SetRoi(App.SlicerFile.LayerManager.BoundingRectangle); - break; - case ToolWindow.Callbacks.Button1: - Operation.Fill(); - IsDefaultAnchorChecked = true; + Operation.SetRoi(SlicerFile.BoundingRectangle); break; } } diff --git a/UVtools.WPF/Controls/Tools/ToolRedrawModelControl.axaml.cs b/UVtools.WPF/Controls/Tools/ToolRedrawModelControl.axaml.cs index ad5cd81..07778e8 100644 --- a/UVtools.WPF/Controls/Tools/ToolRedrawModelControl.axaml.cs +++ b/UVtools.WPF/Controls/Tools/ToolRedrawModelControl.axaml.cs @@ -26,7 +26,7 @@ namespace UVtools.WPF.Controls.Tools switch (callback) { case ToolWindow.Callbacks.Init: - case ToolWindow.Callbacks.ProfileLoaded: + case ToolWindow.Callbacks.Loaded: ParentWindow.ButtonOkEnabled = !string.IsNullOrWhiteSpace(Operation.FilePath); Operation.PropertyChanged += (sender, e) => { diff --git a/UVtools.WPF/Controls/Tools/ToolRepairLayersControl.axaml b/UVtools.WPF/Controls/Tools/ToolRepairLayersControl.axaml index 4080dd5..fcc7036 100644 --- a/UVtools.WPF/Controls/Tools/ToolRepairLayersControl.axaml +++ b/UVtools.WPF/Controls/Tools/ToolRepairLayersControl.axaml @@ -3,6 +3,7 @@ xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" + MinWidth="550" x:Class="UVtools.WPF.Controls.Tools.ToolRepairLayersControl"> <StackPanel Orientation="Vertical" Spacing="10"> diff --git a/UVtools.WPF/Controls/Tools/ToolRepairLayersControl.axaml.cs b/UVtools.WPF/Controls/Tools/ToolRepairLayersControl.axaml.cs index 0cefc50..6b038b4 100644 --- a/UVtools.WPF/Controls/Tools/ToolRepairLayersControl.axaml.cs +++ b/UVtools.WPF/Controls/Tools/ToolRepairLayersControl.axaml.cs @@ -11,7 +11,7 @@ namespace UVtools.WPF.Controls.Tools public ToolRepairLayersControl() { InitializeComponent(); - BaseOperation = GetOperationRepairLayers(); + BaseOperation = new OperationRepairLayers(SlicerFile); } private void InitializeComponent() @@ -30,13 +30,30 @@ namespace UVtools.WPF.Controls.Tools NoiseRemovalIterations = UserSettings.Instance.LayerRepair.OpeningIterations, }; + public void SetFromUserSettings() + { + Operation.RepairIslands = UserSettings.Instance.LayerRepair.RepairIslands; + Operation.RepairResinTraps = UserSettings.Instance.LayerRepair.RepairResinTraps; + Operation.RemoveEmptyLayers = UserSettings.Instance.LayerRepair.RemoveEmptyLayers; + Operation.RemoveIslandsBelowEqualPixelCount = UserSettings.Instance.LayerRepair.RemoveIslandsBelowEqualPixels; + Operation.RemoveIslandsRecursiveIterations = UserSettings.Instance.LayerRepair.RemoveIslandsRecursiveIterations; + Operation.GapClosingIterations = UserSettings.Instance.LayerRepair.ClosingIterations; + Operation.NoiseRemovalIterations = UserSettings.Instance.LayerRepair.OpeningIterations; + } + public override void Callback(ToolWindow.Callbacks callback) { switch (callback) { case ToolWindow.Callbacks.Init: - ParentWindow.LayerRangeVisible = false; - ParentWindow.IsCheckBox1Visible = true; + case ToolWindow.Callbacks.Loaded: + if (callback is ToolWindow.Callbacks.Init) + { + ParentWindow.LayerRangeVisible = false; + ParentWindow.IsCheckBox1Visible = true; + } + + SetFromUserSettings(); break; case ToolWindow.Callbacks.Checkbox1: ParentWindow.LayerRangeVisible = ParentWindow.IsCheckBox1Checked; diff --git a/UVtools.WPF/Controls/Tools/ToolScriptingControl.axaml.cs b/UVtools.WPF/Controls/Tools/ToolScriptingControl.axaml.cs index f68e6f2..7a82216 100644 --- a/UVtools.WPF/Controls/Tools/ToolScriptingControl.axaml.cs +++ b/UVtools.WPF/Controls/Tools/ToolScriptingControl.axaml.cs @@ -37,6 +37,7 @@ namespace UVtools.WPF.Controls.Tools switch (callback) { case ToolWindow.Callbacks.Init: + case ToolWindow.Callbacks.Loaded: ParentWindow.ButtonOkEnabled = Operation.CanExecute; ReloadGUI(); Operation.PropertyChanged += (sender, e) => diff --git a/UVtools.WPF/MainWindow.LayerPreview.cs b/UVtools.WPF/MainWindow.LayerPreview.cs index af64239..5553887 100644 --- a/UVtools.WPF/MainWindow.LayerPreview.cs +++ b/UVtools.WPF/MainWindow.LayerPreview.cs @@ -567,7 +567,7 @@ namespace UVtools.WPF var rect = LayerImageBox.SelectionRegion; return rect.IsEmpty ? Rectangle.Empty : GetTransposedRectangle(rect.ToDotNet(), true); } - set => LayerImageBox.SelectionRegion = value.ToAvalonia(); + set => LayerImageBox.SelectionRegion = GetTransposedRectangle(value).ToAvalonia(); } public RectangleF ROIMillimeters @@ -1600,7 +1600,59 @@ namespace UVtools.WPF if ((e.KeyModifiers & KeyModifiers.Control) != 0) { - if (e.Key == Key.D0 || e.Key == Key.NumPad0) + if (e.Key is Key.LeftShift or Key.RightShift || (e.KeyModifiers & KeyModifiers.Shift) != 0) // Ctrl + Shift + { + if (e.Key == Key.R) + { + ShowLayerImageRotated = true; + if (_showLayerImageRotateCwDirection) + { + ShowLayerImageRotateCWDirection = false; + ShowLayerImageRotateCCWDirection = true; + } + else + { + ShowLayerImageRotateCCWDirection = false; + ShowLayerImageRotateCWDirection = true; + } + e.Handled = true; + return; + } + + if (e.Key == Key.F) + { + ShowLayerImageFlipped = true; + if (!_showLayerImageFlippedHorizontally && !_showLayerImageFlippedVertically) + { + ShowLayerImageFlippedHorizontally = true; + } + else if (_showLayerImageFlippedHorizontally && !_showLayerImageFlippedVertically) + { + ShowLayerImageFlippedHorizontally = false; + ShowLayerImageFlippedVertically = true; + } + else if (!_showLayerImageFlippedHorizontally && _showLayerImageFlippedVertically) + { + ShowLayerImageFlippedHorizontally = true; + } + else if (_showLayerImageFlippedHorizontally && _showLayerImageFlippedVertically) + { + ShowLayerImageFlippedVertically = false; + } + + e.Handled = true; + return; + } + + if (e.Key == Key.B) + { + ROI = SlicerFile.BoundingRectangle; + return; + } + + } + + if (e.Key is Key.D0 or Key.NumPad0) { ZoomToFit(); e.Handled = true; @@ -1682,8 +1734,7 @@ namespace UVtools.WPF if (CvInvoke.PointPolygonTest(LayerCache.LayerContours[i], point, false) >= 0) { - var rectangle = - GetTransposedRectangle(CvInvoke.BoundingRectangle(LayerCache.LayerContours[i])); + var rectangle = CvInvoke.BoundingRectangle(LayerCache.LayerContours[i]); ROI = rectangle; return true; @@ -1714,7 +1765,7 @@ namespace UVtools.WPF roiRectangle = Rectangle.Union(roiRectangle, rectangle); } - ROI = GetTransposedRectangle(roiRectangle); + ROI = roiRectangle; return (uint)rectangles.Count; } diff --git a/UVtools.WPF/MainWindow.axaml b/UVtools.WPF/MainWindow.axaml index 01577b8..ce4c87d 100644 --- a/UVtools.WPF/MainWindow.axaml +++ b/UVtools.WPF/MainWindow.axaml @@ -1730,7 +1730,7 @@ </ContextMenu> </Button.ContextMenu> <StackPanel Orientation="Horizontal"> - <Image Source="/Assets/Icons/undo-alt-16x16.png"/> + <Image Source="/Assets/Icons/sync-16x16.png"/> <TextBlock Margin="5,0,5,0" Text="Rotate ⮟"/> </StackPanel> </ToggleButton> @@ -1890,7 +1890,7 @@ BorderThickness="5" > <uc:AdvancedImageBox - ShowGrid="{Binding Settings.LayerPreview.ShowBackgroudGrid}" + ShowGrid="{Binding Settings.LayerPreview.ShowBackgroudGrid}" GridCellSize="15" Name="LayerImage" /> diff --git a/UVtools.WPF/MainWindow.axaml.cs b/UVtools.WPF/MainWindow.axaml.cs index fd456c1..29d85ba 100644 --- a/UVtools.WPF/MainWindow.axaml.cs +++ b/UVtools.WPF/MainWindow.axaml.cs @@ -19,6 +19,7 @@ using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; +using System.Text.RegularExpressions; using System.Threading.Tasks; using UVtools.Core; using UVtools.Core.Extensions; @@ -651,11 +652,8 @@ namespace UVtools.WPF protected override void OnKeyUp(KeyEventArgs e) { - base.OnKeyUp(e); _globalModifiers = e.KeyModifiers; - if ((e.Key == Key.LeftShift || - e.Key == Key.RightShift || - (e.KeyModifiers & KeyModifiers.Shift) != 0) && + if ((e.Key is Key.LeftShift or Key.RightShift || (e.KeyModifiers & KeyModifiers.Shift) != 0) && (e.KeyModifiers & KeyModifiers.Control) != 0 && e.Key == Key.Z) { @@ -663,11 +661,9 @@ namespace UVtools.WPF ClipboardUndo(true); return; } - - if (e.Key == Key.LeftShift || - e.Key == Key.RightShift || - (e.KeyModifiers & KeyModifiers.Shift) == 0 || - (e.KeyModifiers & KeyModifiers.Control) == 0) + + if (e.Key is Key.LeftShift or Key.RightShift + || (e.KeyModifiers & KeyModifiers.Shift) == 0 || (e.KeyModifiers & KeyModifiers.Control) == 0) { LayerImageBox.TrackerImage = null; LayerImageBox.Cursor = StaticControls.ArrowCursor; @@ -675,7 +671,12 @@ namespace UVtools.WPF LayerImageBox.SelectionMode = AdvancedImageBox.SelectionModes.None; IsTooltipOverlayVisible = false; e.Handled = true; + return; } + + + + base.OnKeyUp(e); } public void OpenContextMenu(string name) @@ -934,12 +935,42 @@ namespace UVtools.WPF #endif } - public void ProcessFiles(string[] files, bool openNewWindow = false) + public async void ProcessFiles(string[] files, bool openNewWindow = false) { if (files is null || files.Length == 0) return; for (int i = 0; i < files.Length; i++) { + if (!File.Exists(files[i])) continue; + + if (files[i].EndsWith(".uvtop")) + { + if(!IsFileLoaded) continue; + try + { + var fileText = File.ReadAllText(files[i]); + var match = Regex.Match(fileText, @"(?:<\/\s*Operation)([a-zA-Z0-9_]+)(?:\s*>)"); + if(!match.Success) continue; + if(match.Groups.Count < 1) continue; + var operationName = match.Groups[1].Value; + var baseType = typeof(Operation).FullName; + if(string.IsNullOrWhiteSpace(baseType)) continue; + var classname = baseType + operationName+", UVtools.Core"; + var type = Type.GetType(classname); + if(type is null) continue; + var operation = Operation.Deserialize(files[i], type); + await ShowRunOperation(type, operation); + } + catch (Exception e) + { + Debug.WriteLine(e); + throw; + } + + continue; + } + + if (i == 0 && !openNewWindow && (_globalModifiers & KeyModifiers.Shift) == 0) { ProcessFile(files[i]); @@ -1066,15 +1097,16 @@ namespace UVtools.WPF } bool modified = false; - if ( - Settings.Automations.BottomLightOffDelay > 0 && - SlicerFile.PrintParameterModifiers is not null && - SlicerFile.PrintParameterModifiers.Contains(FileFormat.PrintParameterModifier.BottomLightOffDelay) && - (!Settings.Automations.ChangeOnlyLightOffDelayIfZero || Settings.Automations.ChangeOnlyLightOffDelayIfZero && SlicerFile.BottomLightOffDelay <= 0) - ) - { - var lightOff = OperationCalculator.LightOffDelayC.CalculateSeconds(SlicerFile.BottomLiftHeight, - SlicerFile.BottomLiftSpeed, SlicerFile.RetractSpeed, (float)Settings.Automations.BottomLightOffDelay); + if (Settings.Automations.LightOffDelaySetMode != Enumerations.LightOffDelaySetMode.NoAction && + SlicerFile.CanUseBottomLightOffDelay && + (Settings.Automations.ChangeOnlyLightOffDelayIfZero && SlicerFile.BottomLightOffDelay == 0 || !Settings.Automations.ChangeOnlyLightOffDelayIfZero)) + { + float lightOff = Settings.Automations.LightOffDelaySetMode switch + { + Enumerations.LightOffDelaySetMode.UpdateWithExtraDelay => SlicerFile.CalculateBottomLightOffDelay((float) Settings.Automations.BottomLightOffDelay), + Enumerations.LightOffDelaySetMode.UpdateWithoutExtraDelay => SlicerFile.CalculateBottomLightOffDelay(), + _ => 0 + }; if (lightOff != SlicerFile.BottomLightOffDelay) { modified = true; @@ -1082,13 +1114,16 @@ namespace UVtools.WPF } } - if (Settings.Automations.LightOffDelay > 0 && - SlicerFile.PrintParameterModifiers is not null && - SlicerFile.PrintParameterModifiers.Contains(FileFormat.PrintParameterModifier.LightOffDelay) && - (!Settings.Automations.ChangeOnlyLightOffDelayIfZero || Settings.Automations.ChangeOnlyLightOffDelayIfZero && SlicerFile.LightOffDelay <= 0)) + if (Settings.Automations.LightOffDelaySetMode != Enumerations.LightOffDelaySetMode.NoAction && + SlicerFile.CanUseLightOffDelay && + (Settings.Automations.ChangeOnlyLightOffDelayIfZero && SlicerFile.LightOffDelay == 0 || !Settings.Automations.ChangeOnlyLightOffDelayIfZero)) { - var lightOff = OperationCalculator.LightOffDelayC.CalculateSeconds(SlicerFile.LiftHeight, - SlicerFile.LiftSpeed, SlicerFile.RetractSpeed, (float)Settings.Automations.LightOffDelay); + float lightOff = Settings.Automations.LightOffDelaySetMode switch + { + Enumerations.LightOffDelaySetMode.UpdateWithExtraDelay => SlicerFile.CalculateNormalLightOffDelay((float)Settings.Automations.LightOffDelay), + Enumerations.LightOffDelaySetMode.UpdateWithoutExtraDelay => SlicerFile.CalculateNormalLightOffDelay(), + _ => 0 + }; if (lightOff != SlicerFile.LightOffDelay) { modified = true; @@ -1470,7 +1505,7 @@ namespace UVtools.WPF { //controlType = toolTypeBase; removeContent = true; - control = new ToolControl(type.CreateInstance<Operation>()); + control = new ToolControl(type.CreateInstance<Operation>(SlicerFile)); } else { @@ -1478,9 +1513,6 @@ namespace UVtools.WPF if (control is null) return null; } - if(loadOperation is not null) - control.BaseOperation = loadOperation; - if (!control.CanRun) { return null; @@ -1492,7 +1524,10 @@ namespace UVtools.WPF } var window = new ToolWindow(control); - //window.ShowDialog(this); + if (loadOperation is not null) + { + control.BaseOperation = loadOperation; + } await window.ShowDialog(this); if (window.DialogResult != DialogResults.OK) return null; var operation = control.BaseOperation; @@ -1540,6 +1575,7 @@ namespace UVtools.WPF IsGUIEnabled = false; ShowProgressWindow(baseOperation.ProgressTitle, baseOperation.CanCancel); + OperationSessionManager.Instance.Add(baseOperation); Clipboard.Snapshot(); @@ -1561,8 +1597,6 @@ namespace UVtools.WPF return false; }); - OperationSessionManager.Instance.Add(baseOperation); - IsGUIEnabled = true; if (result) diff --git a/UVtools.WPF/UVtools.WPF.csproj b/UVtools.WPF/UVtools.WPF.csproj index 1793bcc..e1abb73 100644 --- a/UVtools.WPF/UVtools.WPF.csproj +++ b/UVtools.WPF/UVtools.WPF.csproj @@ -12,7 +12,7 @@ <PackageLicenseFile>LICENSE</PackageLicenseFile> <RepositoryUrl>https://github.com/sn4k3/UVtools</RepositoryUrl> <RepositoryType>Git</RepositoryType> - <Version>2.11.0</Version> + <Version>2.11.1</Version> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'"> @@ -24,14 +24,14 @@ <NoWarn>1701;1702;</NoWarn> </PropertyGroup> <ItemGroup> - <PackageReference Include="Avalonia" Version="0.10.3" /> + <PackageReference Include="Avalonia" Version="0.10.4" /> <PackageReference Include="Avalonia.Angle.Windows.Natives" Version="2.1.0.2020091801" /> - <PackageReference Include="Avalonia.Controls.DataGrid" Version="0.10.3" /> - <PackageReference Include="Avalonia.Desktop" Version="0.10.3" /> - <PackageReference Include="Avalonia.Diagnostics" Version="0.10.3" /> + <PackageReference Include="Avalonia.Controls.DataGrid" Version="0.10.4" /> + <PackageReference Include="Avalonia.Desktop" Version="0.10.4" /> + <PackageReference Include="Avalonia.Diagnostics" Version="0.10.4" /> <PackageReference Include="Emgu.CV.runtime.windows" Version="4.5.1.4349" /> <PackageReference Include="MessageBox.Avalonia" Version="1.2.0" /> - <PackageReference Include="ThemeEditor.Controls.ColorPicker" Version="0.10.3" /> + <PackageReference Include="ThemeEditor.Controls.ColorPicker" Version="0.10.4" /> </ItemGroup> <ItemGroup> <ProjectReference Include="..\UVtools.Core\UVtools.Core.csproj" /> diff --git a/UVtools.WPF/UserSettings.cs b/UVtools.WPF/UserSettings.cs index 26fc181..c66f81e 100644 --- a/UVtools.WPF/UserSettings.cs +++ b/UVtools.WPF/UserSettings.cs @@ -22,7 +22,7 @@ namespace UVtools.WPF public sealed class UserSettings : BindableBase { #region Constants - public const ushort SETTINGS_VERSION = 3; + public const ushort SETTINGS_VERSION = 4; #endregion #region Sub classes @@ -1159,6 +1159,7 @@ namespace UVtools.WPF { private bool _saveFileAfterModifications = true; private bool _autoConvertFiles = true; + private Enumerations.LightOffDelaySetMode _lightOffDelayDelaySetMode = Enumerations.LightOffDelaySetMode.UpdateWithExtraDelay; private bool _changeOnlyLightOffDelayIfZero = true; private decimal _lightOffDelay = 2.5m; private decimal _bottomLightOffDelay = 3m; @@ -1175,12 +1176,28 @@ namespace UVtools.WPF set => RaiseAndSetIfChanged(ref _autoConvertFiles, value); } + public Enumerations.LightOffDelaySetMode LightOffDelaySetMode + { + get => _lightOffDelayDelaySetMode; + set + { + if(!RaiseAndSetIfChanged(ref _lightOffDelayDelaySetMode, value)) return; + RaisePropertyChanged(nameof(ChangeOnlyLightOffDelayIfZeroVisible)); + RaisePropertyChanged(nameof(LightOffDelayExtraTimeVisible)); + } + } + public bool ChangeOnlyLightOffDelayIfZero { get => _changeOnlyLightOffDelayIfZero; set => RaiseAndSetIfChanged(ref _changeOnlyLightOffDelayIfZero, value); } + public bool ChangeOnlyLightOffDelayIfZeroVisible => + _lightOffDelayDelaySetMode + is not Enumerations.LightOffDelaySetMode.NoAction + and not Enumerations.LightOffDelaySetMode.SetToZero; + public decimal LightOffDelay { @@ -1193,6 +1210,9 @@ namespace UVtools.WPF get => _bottomLightOffDelay; set => RaiseAndSetIfChanged(ref _bottomLightOffDelay, value); } + + public bool LightOffDelayExtraTimeVisible => _lightOffDelayDelaySetMode + is Enumerations.LightOffDelaySetMode.UpdateWithExtraDelay; } #endregion diff --git a/UVtools.WPF/Windows/SettingsWindow.axaml b/UVtools.WPF/Windows/SettingsWindow.axaml index c12fcb8..3ff30f1 100644 --- a/UVtools.WPF/Windows/SettingsWindow.axaml +++ b/UVtools.WPF/Windows/SettingsWindow.axaml @@ -1487,20 +1487,27 @@ <StackPanel Orientation="Vertical"> <TextBlock Padding="10" Background="LightBlue" FontWeight="Bold" Text="Light-off delay"/> - <CheckBox Margin="10,10,10,0" + <ComboBox + Margin="10" + HorizontalAlignment="Stretch" + Items="{Binding Settings.Automations.LightOffDelaySetMode, Converter={StaticResource EnumToCollectionConverter}, Mode=OneTime}" + SelectedItem="{Binding Settings.Automations.LightOffDelaySetMode, Converter={StaticResource FromValueDescriptionToEnumConverter}}"/> + + <CheckBox Margin="10,0,10,10" Content="Change only light-off delay if value is zero" ToolTip.Tip="If enabled, it will only change light-off delay to the defined values if the original value is zero. 
If disabled, it will always change the light-off delay to the defined values." + IsVisible="{Binding Settings.Automations.ChangeOnlyLightOffDelayIfZeroVisible}" IsChecked="{Binding Settings.Automations.ChangeOnlyLightOffDelayIfZero}"/> - <Grid Margin="10" + <Grid Margin="10,0,10,10" + IsVisible="{Binding Settings.Automations.LightOffDelayExtraTimeVisible}" RowDefinitions="Auto" ColumnDefinitions="Auto,10,150,5,Auto,30,Auto,10,150,5,Auto"> <TextBlock Grid.Row="0" Grid.Column="0" VerticalAlignment="Center" - ToolTip.Tip="Auto set the extra 'light-off delay' based on lift height and speed. -
Use '0' to ignore this automation." + ToolTip.Tip="Auto set the extra 'light-off delay' based on lift height and speed." Text="Light-off delay:" /> <NumericUpDown Grid.Row="0" Grid.Column="2" @@ -1517,8 +1524,7 @@ <TextBlock Grid.Row="0" Grid.Column="6" VerticalAlignment="Center" - ToolTip.Tip="Auto set the extra 'bottom light-off delay' based on bottom lift height and speed. -
Use '0' to ignore this automation." + ToolTip.Tip="Auto set the extra 'bottom light-off delay' based on bottom lift height and speed." Text="Bottom light-off delay:" /> <NumericUpDown Grid.Row="0" Grid.Column="8" diff --git a/UVtools.WPF/Windows/ToolWindow.axaml b/UVtools.WPF/Windows/ToolWindow.axaml index ff1936d..5b244dc 100644 --- a/UVtools.WPF/Windows/ToolWindow.axaml +++ b/UVtools.WPF/Windows/ToolWindow.axaml @@ -195,40 +195,42 @@ IsVisible="{Binding IsROIOrMasksVisible}"> <StackPanel Orientation="Vertical"> - <TextBlock - Classes="GroupBoxHeader" - Text="Region of interest (ROI) and Masks"/> - <StackPanel Margin="15" Spacing="10"> - <StackPanel Spacing="10" - Orientation="Horizontal" - IsVisible="{Binding IsROIVisible}"> - <TextBlock VerticalAlignment="Center" - Text="{Binding ROI, StringFormat=Region: \{0\}}" /> + <Grid + ColumnDefinitions="Auto,*" Background="LightBlue"> + <TextBlock + Padding="10" FontWeight="Bold" + VerticalAlignment="Center" + Text="Region of interest (ROI) and Masks" /> + + <StackPanel Orientation="Horizontal" + Grid.Column="1" + HorizontalAlignment="Right" + Spacing="1"> + <Button + VerticalAlignment="Center" + Content="Clear ROI" + IsVisible="{Binding IsROIVisible}" + Command="{Binding ClearROI}"/> + <Button + VerticalAlignment="Center" + Content="{Binding Masks.Length, StringFormat=Clear \{0\} mask(s)}" + IsVisible="{Binding IsMasksVisible}" + Command="{Binding ClearMasks}"/> + + </StackPanel> + + </Grid> + + <StackPanel Margin="15" Spacing="5"> + <TextBlock VerticalAlignment="Center" + Text="{Binding ROI, StringFormat=Region: \{0\}}" /> + + <CheckBox + Content="Clear ROI and Masks after perform the operation" + IsChecked="{Binding ClearROIAndMaskAfterOperation}"/> - <Button - Padding="5" - Content="Clear ROI" - Command="{Binding ClearROI}"/> - </StackPanel> - - <StackPanel Spacing="10" - Orientation="Horizontal" - IsVisible="{Binding IsMasksVisible}"> - <TextBlock VerticalAlignment="Center" - Text="{Binding Masks.Length, StringFormat=Masks: \{0\}}" /> - - <Button - Padding="5" - Content="Clear Masks" - Command="{Binding ClearMasks}"/> - </StackPanel> - - <CheckBox - Content="Clear ROI and Masks after perform the operation" - IsChecked="{Binding ClearROIAndMaskAfterOperation}"/> - - </StackPanel> + </StackPanel> </StackPanel> @@ -274,12 +276,14 @@ > <ComboBox + Name="ProfileComboBox" Margin="0,0,0,10" IsEnabled="{Binding Profiles.Count}" IsVisible="{Binding Profiles.Count}" SelectedItem="{Binding SelectedProfileItem}" HorizontalAlignment="Stretch" - Items="{Binding Profiles}" /> + Items="{Binding Profiles}" + Width="{Binding ProfileBoxMaxWidth}"/> <Button Grid.Row="0" @@ -320,11 +324,14 @@ </Button> <TextBox + Name="ProfileName" Grid.Row="1" Grid.Column="0" IsEnabled="{Binding ButtonOkEnabled}" Text="{Binding ProfileText}" - Watermark="Profile name or leave empty for auto name"/> + Watermark="Profile name or leave empty for auto name" + Width="{Binding ProfileBoxMaxWidth}" + /> <Button Grid.Row="1" @@ -399,6 +406,16 @@ <Image Source="/Assets/Icons/file-export-16x16.png"/> </MenuItem.Icon> </MenuItem> + + <Separator IsVisible="{Binding CanHaveProfiles}"/> + + <MenuItem + Command="{Binding ResetToDefaults}" + Header="Reset to defaults"> + <MenuItem.Icon> + <Image Source="/Assets/Icons/undo-alt-16x16.png"/> + </MenuItem.Icon> + </MenuItem> </ContextMenu> </Button.ContextMenu> </Button> diff --git a/UVtools.WPF/Windows/ToolWindow.axaml.cs b/UVtools.WPF/Windows/ToolWindow.axaml.cs index de40575..60e0ff4 100644 --- a/UVtools.WPF/Windows/ToolWindow.axaml.cs +++ b/UVtools.WPF/Windows/ToolWindow.axaml.cs @@ -1,5 +1,6 @@ using System; using System.Collections.ObjectModel; +using System.Diagnostics; using System.Drawing; using System.IO; using System.Xml.Serialization; @@ -27,7 +28,7 @@ namespace UVtools.WPF.Windows { Init, ClearROI, - ProfileLoaded, + Loaded, Button1, // Reset to defaults Checkbox1, // Show Advanced } @@ -35,6 +36,8 @@ namespace UVtools.WPF.Windows public ToolControl ToolControl; private string _description; private double _descriptionMaxWidth; + private double _expanderHeaderMaxWidth = double.NaN; + private double _profileBoxMaxWidth = double.NaN; private bool _layerRangeVisible = true; private bool _layerRangeSync; private uint _layerIndexStart; @@ -61,7 +64,7 @@ namespace UVtools.WPF.Windows private bool _buttonOkEnabled = true; private string _buttonOkText = "Ok"; private bool _buttonOkVisible = true; - private double _expanderHeaderMaxWidth; + #region Description @@ -83,6 +86,12 @@ namespace UVtools.WPF.Windows set => RaiseAndSetIfChanged(ref _expanderHeaderMaxWidth, value); } + public double ProfileBoxMaxWidth + { + get => _profileBoxMaxWidth; + set => RaiseAndSetIfChanged(ref _profileBoxMaxWidth, value); + } + #endregion #region Layer Selector @@ -295,7 +304,7 @@ namespace UVtools.WPF.Windows get => App.MainWindow.ROI; set { - App.MainWindow.ROI = App.MainWindow.GetTransposedRectangle(value); + App.MainWindow.ROI = value; ToolControl.BaseOperation.ROI = value; IsROIVisible = !value.IsEmpty; RaisePropertyChanged(); @@ -322,6 +331,7 @@ namespace UVtools.WPF.Windows public async void ClearMasks() { + var layer = SlicerFile.LayerManager.LargestNormalLayer; if (await this.MessageBoxQuestion("Are you sure you want to clear all masks?\n" + "This action can not be reverted, to select another mask(s) you must quit this window and select it on layer preview.", "Clear the all masks?") != ButtonResult.Yes) return; @@ -363,7 +373,7 @@ namespace UVtools.WPF.Windows if (ToolControl is null) return; var operation = _selectedProfileItem.Clone(); operation.ProfileName = null; - operation.SlicerFile = SlicerFile; + operation.ImportedFrom = Operation.OperationImportFrom.Profile; ToolControl.BaseOperation = operation; switch (operation.LayerRangeSelection) { @@ -376,8 +386,8 @@ namespace UVtools.WPF.Windows break; } - ToolControl.Callback(Callbacks.ProfileLoaded); - ToolControl.ResetDataContext(); + //ToolControl.Callback(Callbacks.Loaded); + //ToolControl.ResetDataContext(); } } @@ -590,31 +600,21 @@ namespace UVtools.WPF.Windows _buttonOkText = toolControl.BaseOperation.ButtonOkText; _buttonOkVisible = ButtonOkEnabled = toolControl.BaseOperation.HaveAction; - bool fromSession = false; - if (!toolControl.BaseOperation.HaveExecuted && Settings.Tools.RestoreLastUsedSettings) + bool loadedFromSession = false; + if (!toolControl.BaseOperation.HaveExecuted + && toolControl.BaseOperation.ImportedFrom is Operation.OperationImportFrom.None + && Settings.Tools.RestoreLastUsedSettings) { var operation = OperationSessionManager.Instance.Find(toolControl.BaseOperation.GetType()); if (operation is not null) { toolControl.BaseOperation = operation.Clone(); - toolControl.BaseOperation.ClearROIandMasks(); - - switch (operation.LayerRangeSelection) - { - case Enumerations.LayerRangeSelection.None: - LayerIndexStart = operation.LayerIndexStart; - LayerIndexEnd = operation.LayerIndexEnd; - break; - default: - SelectLayers(operation.LayerRangeSelection); - break; - } - - fromSession = true; + loadedFromSession = true; } } - if (toolControl.BaseOperation.HaveExecuted) // Come from a redo or session + if (toolControl.BaseOperation.HaveExecuted + || toolControl.BaseOperation.ImportedFrom is not Operation.OperationImportFrom.None) // Loaded from something { if (toolControl.BaseOperation.HaveROI) { @@ -626,22 +626,30 @@ namespace UVtools.WPF.Windows App.MainWindow.AddMaskPoints(toolControl.BaseOperation.MaskPoints); } - LayerIndexStart = toolControl.BaseOperation.LayerIndexStart; - LayerIndexEnd = toolControl.BaseOperation.LayerIndexEnd; + if (toolControl.BaseOperation.LayerRangeSelection == Enumerations.LayerRangeSelection.None) + { + LayerIndexStart = toolControl.BaseOperation.LayerIndexStart; + LayerIndexEnd = toolControl.BaseOperation.LayerIndexEnd; + } + else + { + SelectLayers(toolControl.BaseOperation.LayerRangeSelection); + } } else { SelectLayers(toolControl.BaseOperation.StartLayerRangeSelection); } + if (ToolControl.BaseOperation.CanHaveProfiles) { _isProfilesVisible = true; var profiles = OperationProfiles.GetOperations(ToolControl.BaseOperation.GetType()); _profiles.AddRange(profiles); - if (!toolControl.BaseOperation.HaveExecuted || - (toolControl.BaseOperation.HaveExecuted && fromSession && !Settings.Tools.LastUsedSettingsPriorityOverDefaultProfile)) + if (toolControl.BaseOperation.ImportedFrom is Operation.OperationImportFrom.None || + (loadedFromSession && !Settings.Tools.LastUsedSettingsPriorityOverDefaultProfile)) { //Operation profile = _profiles.FirstOrDefault(operation => operation.ProfileIsDefault); foreach (var operation in Profiles) @@ -655,19 +663,13 @@ namespace UVtools.WPF.Windows } } - if (!ReferenceEquals(toolControl.BaseOperation.SlicerFile, SlicerFile)) // Sanitize - { - toolControl.BaseOperation.SlicerFile = SlicerFile; - } - - //RaisePropertyChanged(nameof(IsContentVisible)); //RaisePropertyChanged(nameof(IsROIVisible)); // Ensure the description don't stretch window - DispatcherTimer.Run(() => + /*DispatcherTimer.Run(() => { if (Bounds.Width == 0) return true; //ScrollViewerMaxHeight = this.GetScreenWorkingArea().Height - Bounds.Height + ToolControl.Bounds.Height - UserSettings.Instance.General.WindowsVerticalMargin; @@ -690,7 +692,7 @@ namespace UVtools.WPF.Windows }, TimeSpan.FromMilliseconds(2)); return false; - }, TimeSpan.FromMilliseconds(1)); + }, TimeSpan.FromMilliseconds(1));*/ toolControl.Callback(Callbacks.Init); toolControl.DataContext = toolControl; @@ -702,6 +704,30 @@ namespace UVtools.WPF.Windows AvaloniaXamlLoader.Load(this); } + protected override void OnOpened(EventArgs e) + { + base.OnOpened(e); + var profileTextBox = this.FindControl<TextBox>("ProfileName"); + DescriptionMaxWidth = Math.Max(Bounds.Width, ToolControl.Bounds.Width) - 20; + ExpanderHeaderMaxWidth = DescriptionMaxWidth - 40; + ProfileBoxMaxWidth = profileTextBox.Bounds.Width; + Height = MaxHeight; + + DispatcherTimer.Run(() => + { + if (Math.Max((int)_contentScrollViewer.Extent.Height - (int)_contentScrollViewer.Viewport.Height, 0) == 0) + { + Height = 10; + SizeToContent = SizeToContent.WidthAndHeight; + } + Position = new PixelPoint( + (int)(App.MainWindow.Position.X + App.MainWindow.Width / 2 - Width / 2), + App.MainWindow.Position.Y + 20 + ); + return false; + }, TimeSpan.FromMilliseconds(1)); + } + public void FitToSize() { SizeToContent = SizeToContent.Manual; @@ -817,9 +843,7 @@ namespace UVtools.WPF.Windows try { - XmlSerializer serializer = new(ToolControl.BaseOperation.GetType()); - await using StreamWriter writer = new(file); - serializer.Serialize(writer, ToolControl.BaseOperation); + ToolControl.BaseOperation.Serialize(file); } catch (Exception e) { @@ -841,11 +865,8 @@ namespace UVtools.WPF.Windows try { - XmlSerializer serializer = new(ToolControl.BaseOperation.GetType()); - await using var stream = File.OpenRead(files[0]); - var operation = (Operation)serializer.Deserialize(stream); + var operation = Operation.Deserialize(files[0], ToolControl.BaseOperation); - operation.SlicerFile = SlicerFile; ToolControl.BaseOperation = operation; switch (operation.LayerRangeSelection) { @@ -858,12 +879,23 @@ namespace UVtools.WPF.Windows break; } - ToolControl.Callback(Callbacks.ProfileLoaded); + } catch (Exception e) { await this.MessageBoxError(e.ToString(), "Error while trying to import the settings"); } } + + public void ResetToDefaults() + { + var operation = ToolControl.BaseOperation.GetType().CreateInstance<Operation>(SlicerFile); + operation.LayerIndexStart = ToolControl.BaseOperation.LayerIndexStart; + operation.LayerIndexEnd = ToolControl.BaseOperation.LayerIndexEnd; + operation.LayerRangeSelection = ToolControl.BaseOperation.LayerRangeSelection; + operation.ROI = ToolControl.BaseOperation.ROI; + operation.MaskPoints = ToolControl.BaseOperation.MaskPoints; + ToolControl.BaseOperation = operation; + } } } |