Browse Source

Loading screen, fill tool, minor fix in TransformOverlay

Equbuxu 3 years ago
parent
commit
a8b643175e

+ 2 - 0
src/PixiEditor/Models/DocumentModels/Public/DocumentToolsModule.cs

@@ -31,4 +31,6 @@ internal class DocumentToolsModule
     public void UseSelectTool() => Internals.ChangeController.TryStartUpdateableChange<SelectToolExecutor>();
 
     public void UseBrightnessTool() => Internals.ChangeController.TryStartUpdateableChange<BrightnessToolExecutor>();
+
+    public void UseFloodFillTool() => Internals.ChangeController.TryStartUpdateableChange<FloodFillToolExecutor>();
 }

+ 55 - 0
src/PixiEditor/Models/DocumentModels/UpdateableChangeExecutors/FloodFillToolExecutor.cs

@@ -0,0 +1,55 @@
+using ChunkyImageLib.DataHolders;
+using PixiEditor.ChangeableDocument.Actions.Undo;
+using PixiEditor.Models.Enums;
+using PixiEditor.ViewModels.SubViewModels.Document;
+using PixiEditor.ViewModels.SubViewModels.Tools.Tools;
+
+namespace PixiEditor.Models.DocumentModels.UpdateableChangeExecutors;
+#nullable enable
+internal class FloodFillToolExecutor : UpdateableChangeExecutor
+{
+    private bool considerAllLayers;
+    private bool drawOnMask;
+    private Guid memberGuid;
+    private SKColor color;
+
+    public override ExecutionState Start()
+    {
+        var fillTool = ViewModelMain.Current?.ToolsSubViewModel.GetTool<FloodFillToolViewModel>();
+        ColorsViewModel? colorsVM = ViewModelMain.Current?.ColorsSubViewModel;
+        var member = document!.SelectedStructureMember;
+
+        if (fillTool is null || member is null || colorsVM is null)
+            return ExecutionState.Error;
+        drawOnMask = member is LayerViewModel layer ? layer.ShouldDrawOnMask : true;
+        if (drawOnMask && !member.HasMaskBindable)
+            return ExecutionState.Error;
+        if (!drawOnMask && member is not LayerViewModel)
+            return ExecutionState.Error;
+
+        memberGuid = member.GuidValue;
+        considerAllLayers = fillTool.ConsiderAllLayers;
+        color = colorsVM.PrimaryColor;
+        var pos = controller!.LastPixelPosition;
+
+        internals!.ActionAccumulator.AddActions(new FloodFill_Action(memberGuid, pos, color, considerAllLayers, drawOnMask));
+
+        return ExecutionState.Success;
+    }
+
+    public override void OnPixelPositionChange(VecI pos)
+    {
+        internals!.ActionAccumulator.AddActions(new FloodFill_Action(memberGuid, pos, color, considerAllLayers, drawOnMask));
+    }
+
+    public override void OnLeftMouseButtonUp()
+    {
+        internals!.ActionAccumulator.AddActions(new ChangeBoundary_Action());
+        onEnded!(this);
+    }
+
+    public override void ForceStop()
+    {
+        internals!.ActionAccumulator.AddActions(new ChangeBoundary_Action());
+    }
+}

+ 4 - 2
src/PixiEditor/ViewModels/SubViewModels/Main/SearchViewModel.cs

@@ -1,5 +1,4 @@
 using System.Windows.Input;
-using PixiEditor.Models.Commands.Attributes;
 using PixiEditor.Models.Commands.Attributes.Commands;
 
 namespace PixiEditor.ViewModels.SubViewModels.Main;
@@ -25,7 +24,10 @@ internal class SearchViewModel : SubViewModel<ViewModelMain>
     public SearchViewModel(ViewModelMain owner) : base(owner)
     { }
 
-    [Command.Basic("PixiEditor.Search.Toggle", "", "Command Search", "Open the command search window", Key = Key.K, Modifiers = ModifierKeys.Control)]
+    [Evaluator.CanExecute("PixiEditor.Search.CanOpenSearchWindow")]
+    public bool CanToggleSeachWindow() => !ViewModelMain.Current?.DocumentManagerSubViewModel.ActiveDocument?.Busy ?? true;
+
+    [Command.Basic("PixiEditor.Search.Toggle", "", "Command Search", "Open the command search window", Key = Key.K, Modifiers = ModifierKeys.Control, CanExecute = "PixiEditor.Search.CanOpenSearchWindow")]
     public void ToggleSearchWindow(string searchTerm)
     {
         SearchWindowOpen = !SearchWindowOpen;

+ 25 - 2
src/PixiEditor/ViewModels/SubViewModels/Tools/Tools/FloodFillToolViewModel.cs

@@ -1,4 +1,5 @@
 using System.Windows.Input;
+using ChunkyImageLib.DataHolders;
 using PixiEditor.Models.Commands.Attributes.Commands;
 using PixiEditor.Views.UserControls.BrushShapeOverlay;
 
@@ -7,14 +8,36 @@ namespace PixiEditor.ViewModels.SubViewModels.Tools.Tools;
 [Command.Tool(Key = Key.G)]
 internal class FloodFillToolViewModel : ToolViewModel
 {
+    private readonly string defaultActionDisplay = "Press on an area to fill it. Hold down Ctrl to consider all layers.";
     private SKPaint fillPaint = new SKPaint() { BlendMode = SKBlendMode.Src };
 
     public override BrushShape BrushShape => BrushShape.Pixel;
 
+    public override string Tooltip => $"Fills area with color. ({Shortcut})";
+
+    public bool ConsiderAllLayers { get; private set; }
+
     public FloodFillToolViewModel()
     {
-        ActionDisplay = "Press on an area to fill it.";
+        ActionDisplay = defaultActionDisplay;
     }
 
-    public override string Tooltip => $"Fills area with color. ({Shortcut})";
+    public override void UpdateActionDisplay(bool ctrlIsDown, bool shiftIsDown, bool altIsDown)
+    {
+        if (ctrlIsDown)
+        {
+            ConsiderAllLayers = true;
+            ActionDisplay = "Press on an area to fill it. Release Ctrl to only consider the current layers.";
+        }
+        else
+        {
+            ConsiderAllLayers = false;
+            ActionDisplay = defaultActionDisplay;
+        }
+    }
+
+    public override void OnLeftMouseButtonDown(VecD pos)
+    {
+        ViewModelMain.Current?.DocumentManagerSubViewModel.ActiveDocument?.Tools.UseFloodFillTool();
+    }
 }

+ 20 - 13
src/PixiEditor/Views/Dialogs/PalettesBrowser.xaml

@@ -1,18 +1,25 @@
 <Window
     x:ClassModifier="internal"
-             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
-             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
-             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
-             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
-             xmlns:local="clr-namespace:PixiEditor.Views.UserControls.Palettes" xmlns:converters="clr-namespace:PixiEditor.Helpers.Converters" 
-             xmlns:gif="http://wpfanimatedgif.codeplex.com" xmlns:usercontrols="clr-namespace:PixiEditor.Views.UserControls" xmlns:views="clr-namespace:PixiEditor.Views"
-             xmlns:behaviours="clr-namespace:PixiEditor.Helpers.Behaviours"
-             xmlns:PixiEditor="clr-namespace:PixiEditor"
-             xmlns:dialogs="clr-namespace:PixiEditor.Views.Dialogs"
-             x:Class="PixiEditor.Views.Dialogs.PalettesBrowser"
-             mc:Ignorable="d"
-             Title="Palettes Browser" WindowStartupLocation="CenterScreen" MinWidth="200" Height="600" Width="850" WindowStyle="None"
-             x:Name="palettesBrowser">
+    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
+    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
+    xmlns:local="clr-namespace:PixiEditor.Views.UserControls.Palettes" 
+    xmlns:converters="clr-namespace:PixiEditor.Helpers.Converters" 
+    xmlns:gif="http://wpfanimatedgif.codeplex.com" 
+    xmlns:usercontrols="clr-namespace:PixiEditor.Views.UserControls" 
+    xmlns:views="clr-namespace:PixiEditor.Views"
+    xmlns:behaviours="clr-namespace:PixiEditor.Helpers.Behaviours"
+    xmlns:PixiEditor="clr-namespace:PixiEditor"
+    xmlns:dialogs="clr-namespace:PixiEditor.Views.Dialogs"
+    x:Class="PixiEditor.Views.Dialogs.PalettesBrowser"
+    mc:Ignorable="d"
+    Title="Palettes Browser" 
+    WindowStartupLocation="CenterScreen" 
+    MinWidth="200" 
+    Height="600" Width="850" 
+    WindowStyle="None"
+    x:Name="palettesBrowser">
     <Window.Resources>
         <BooleanToVisibilityConverter x:Key="BoolToVisibilityConverter"/>
     </Window.Resources>

+ 14 - 0
src/PixiEditor/Views/MainWindow.xaml

@@ -5,6 +5,7 @@
     MinWidth="700"
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+    xmlns:gif="http://wpfanimatedgif.codeplex.com" 
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
     xmlns:local="clr-namespace:PixiEditor"
@@ -477,6 +478,7 @@
                     </ItemsControl.ItemTemplate>
                 </ItemsControl>
             </StackPanel>
+
             <Grid Grid.Column="1" Grid.Row="2" Background="#303030" >
                 <Grid AllowDrop="True" Drop="MainWindow_Drop">
                     <DockingManager 
@@ -733,6 +735,18 @@
                 </Grid>
             </Border>
 
+            <Border 
+                Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="2" 
+                Background="#881d1d1d"
+                Cursor=""
+                Visibility="{Binding DocumentManagerSubViewModel.ActiveDocument.Busy, Converter={StaticResource BoolToVisibilityConverter}, FallbackValue={x:Static Visibility.Collapsed}, Source={vm:MainVM}}">
+                <Image 
+                    gif:ImageBehavior.AnimatedSource="/Images/Processing.gif" 
+                    HorizontalAlignment="Center" VerticalAlignment="Center"
+                    Height="50" 
+                    gif:ImageBehavior.AnimationSpeedRatio="1.5"/>
+            </Border>
+            
             <Grid
                 Grid.Row="3"
                 Grid.Column="1">

+ 16 - 13
src/PixiEditor/Views/UserControls/TransformOverlay/TransformOverlay.cs

@@ -127,6 +127,7 @@ internal class TransformOverlay : Decorator
     {
         base.OnRender(drawingContext);
         DrawOverlay(drawingContext, new(ActualWidth, ActualHeight), Corners, InternalState.Origin, ZoomboxScale);
+        UpdateRotationCursor(TransformHelper.ToVecD(Mouse.GetPosition(this)));
     }
 
     private void DrawOverlay
@@ -234,22 +235,24 @@ internal class TransformOverlay : Decorator
         return TransformHelper.GetAnchorInPosition(mousePos, Corners, InternalState.Origin, ZoomboxScale, 15) is not null;
     }
 
-    protected override void OnMouseMove(MouseEventArgs e)
+    private void UpdateRotationCursor(VecD mousePos)
     {
+        if (!ShouldRotate(mousePos))
         {
-            var vector = TransformHelper.ToVecD(e.GetPosition(this));
-            if (!ShouldRotate(vector))
-            {
-                rotateCursorGeometry.Transform = new ScaleTransform(0, 0);
-            }
-            else
-            {
-                var matrix = new TranslateTransform(vector.X, vector.Y).Value;
-                matrix.RotateAt((vector - InternalState.Origin).Angle * 180 / Math.PI - 90, vector.X, vector.Y);
-                //matrix.ScaleAt(0.035, 0.035, vector.X, vector.Y);
-                rotateCursorGeometry.Transform = new MatrixTransform(matrix);
-            }
+            rotateCursorGeometry.Transform = new ScaleTransform(0, 0);
+        }
+        else
+        {
+            var matrix = new TranslateTransform(mousePos.X, mousePos.Y).Value;
+            matrix.RotateAt((mousePos - InternalState.Origin).Angle * 180 / Math.PI - 90, mousePos.X, mousePos.Y);
+            matrix.ScaleAt(8 / ZoomboxScale, 8 / ZoomboxScale, mousePos.X, mousePos.Y);
+            rotateCursorGeometry.Transform = new MatrixTransform(matrix);
         }
+    }
+
+    protected override void OnMouseMove(MouseEventArgs e)
+    {
+        UpdateRotationCursor(TransformHelper.ToVecD(e.GetPosition(this)));
 
         if (capturedAnchor is not null)
         {