Browse Source

Fixed mouse movement controller

flabbet 5 years ago
parent
commit
6b1f26499d

+ 17 - 0
PixiEditor/Exceptions/LengthMismatchException.cs

@@ -0,0 +1,17 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace PixiEditor.Exceptions
+{
+    public class ArrayLengthMismatchException : Exception
+    {
+        public const string DefaultMessage = "First array length doesn't match second array length";
+
+        public ArrayLengthMismatchException() : base(DefaultMessage) { }
+        public ArrayLengthMismatchException(string message) : base(message)
+        {
+
+        }
+    }
+}

BIN
PixiEditor/Images/MoveImage.png


+ 2 - 2
PixiEditor/Models/Controllers/BitmapManager.cs

@@ -139,7 +139,7 @@ namespace PixiEditor.Models.Controllers
                 if (IsOperationTool(SelectedTool))
                 {
                     BitmapOperations.ExecuteTool(e.NewPosition,
-                        MouseController.LastMouseMoveCoordinates, (BitmapOperationTool)SelectedTool);
+                        MouseController.LastMouseMoveCoordinates.ToList(), (BitmapOperationTool)SelectedTool);
                 }
                 else
                 {
@@ -209,7 +209,7 @@ namespace PixiEditor.Models.Controllers
         }
 
 
-        private bool IsOperationTool(Tool tool)
+        public static bool IsOperationTool(Tool tool)
         {
             return typeof(BitmapOperationTool).IsAssignableFrom(tool.GetType());
         }

+ 1 - 1
PixiEditor/Models/Controllers/MouseMovementController.cs

@@ -27,7 +27,7 @@ namespace PixiEditor.Models.Controllers
         {
             if (IsRecordingChanges == true)
             {
-                if (LastMouseMoveCoordinates.Count == 0 || mouseCoordinates != LastMouseMoveCoordinates[LastMouseMoveCoordinates.Count - 1])
+                if (LastMouseMoveCoordinates.Count == 0 || mouseCoordinates != LastMouseMoveCoordinates[^1])
                 {
                     LastMouseMoveCoordinates.Add(mouseCoordinates);
                     MousePositionChanged?.Invoke(this, new MouseMovementEventArgs(mouseCoordinates));

+ 33 - 0
PixiEditor/Models/ImageManipulation/Transform.cs

@@ -0,0 +1,33 @@
+using PixiEditor.Models.Position;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace PixiEditor.Models.ImageManipulation
+{
+    public static class Transform
+    {
+        /// <summary>
+        /// Returns translation between two coordinates.
+        /// </summary>
+        /// <param name="from">Starting coordinate</param>
+        /// <param name="to">New coordinate</param>
+        /// <returns>Translation as coordinate</returns>
+        public static Coordinates GetTranslation(Coordinates from, Coordinates to)
+        {
+            int translationX = to.X - from.X;
+            int translationY = to.Y - from.Y;
+            return new Coordinates(translationX, translationY);
+        }
+
+        public static Coordinates[] Translate(Coordinates[] points, Coordinates vector)
+        {
+            Coordinates[] translatedPoints = new Coordinates[points.Length];
+            for (int i = 0; i < translatedPoints.Length; i++)
+            {
+                translatedPoints[i] = new Coordinates(points[i].X + vector.X, points[i].Y + vector.Y);
+            }
+            return translatedPoints;
+        }
+    }
+}

+ 1 - 1
PixiEditor/Models/Tools/BitmapOperationTool.cs

@@ -9,7 +9,7 @@ namespace PixiEditor.Models.Tools
 {
     public abstract class BitmapOperationTool : Tool
     {
-        public abstract BitmapPixelChanges Use(Layer layer, Coordinates[] pixels, Color color);
+        public abstract BitmapPixelChanges Use(Layer layer, Coordinates[] mouseMove, Color color);
         public bool RequiresPreviewLayer { get; set; }
 
     }

+ 19 - 1
PixiEditor/Models/Tools/BitmapPixelChanges.cs

@@ -1,6 +1,8 @@
-using PixiEditor.Models.Position;
+using PixiEditor.Exceptions;
+using PixiEditor.Models.Position;
 using System;
 using System.Collections.Generic;
+using System.Linq;
 using System.Text;
 using System.Windows.Media;
 
@@ -25,5 +27,21 @@ namespace PixiEditor.Models.Tools
             }
             return new BitmapPixelChanges(dict);
         }
+
+        public static BitmapPixelChanges FromArrays(IEnumerable<Coordinates> coordinates, IEnumerable<Color> color)
+        {
+            var coordinateArray = coordinates.ToArray();
+            var colorArray = color.ToArray();
+            if(coordinateArray.Length != colorArray.Length)
+            {
+                throw new ArrayLengthMismatchException();
+            }
+            Dictionary<Coordinates, Color> dict = new Dictionary<Coordinates, Color>();
+            for (int i = 0; i < coordinateArray.Length; i++)
+            {
+                dict.Add(coordinateArray[i], colorArray[i]);
+            }
+            return new BitmapPixelChanges(dict);
+        }
     }
 }

+ 1 - 1
PixiEditor/Models/Tools/ToolType.cs

@@ -8,6 +8,6 @@ namespace PixiEditor.Models.Tools
 {
     public enum ToolType
     {
-        None, Select, Pen, Bucket, Line, Circle, Rectangle, Earser, Brightness, ColorPicker
+        None, Move, Pen, Select, Bucket, Line, Circle, Rectangle, Earser, Brightness, ColorPicker
     }
 }

+ 68 - 0
PixiEditor/Models/Tools/Tools/MoveTool.cs

@@ -0,0 +1,68 @@
+using PixiEditor.Helpers.Extensions;
+using PixiEditor.Models.DataHolders;
+using PixiEditor.Models.Layers;
+using PixiEditor.Models.Position;
+using PixiEditor.ViewModels;
+using System.Linq;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+
+namespace PixiEditor.Models.Tools.Tools
+{
+    public class MoveTool : BitmapOperationTool
+    {
+        public override ToolType ToolType => ToolType.Move;
+        private Coordinates[] _startSelection;
+        private Coordinates _lastStartMousePos;
+        private Color[] _startPixelColors;
+
+        public MoveTool()
+        {
+            Tooltip = "Moves selected pixels. (M)";
+            Cursor = Cursors.Arrow;
+            HideHighlight = true;
+            RequiresPreviewLayer = true;
+        }
+
+        public override BitmapPixelChanges Use(Layer layer, Coordinates[] mouseMove, Color color)
+        {
+            Coordinates start = mouseMove[^1];
+            Coordinates end = mouseMove[0];
+
+            if (_lastStartMousePos != start)
+            {
+                _lastStartMousePos = start;
+                _startSelection = ViewModelMain.Current.ActiveSelection.SelectedPoints;
+                _startPixelColors = GetPixelsForSelection(layer, _startSelection);
+            }
+
+            Coordinates translation = ImageManipulation.Transform.GetTranslation(start, end);
+
+                Coordinates[] previousSelection = ViewModelMain.Current.ActiveSelection.SelectedPoints.ToArray();
+                ViewModelMain.Current.ActiveSelection = 
+                    new Selection(ImageManipulation.Transform.Translate(previousSelection, translation));
+                //BitmapPixelChanges changes = 
+                  //  BitmapPixelChanges.FromSingleColoredArray(previousSelection, System.Windows.Media.Colors.Transparent);
+                BitmapPixelChanges changes = BitmapPixelChanges.FromArrays(
+                        ViewModelMain.Current.ActiveSelection.SelectedPoints, _startPixelColors);
+            return changes;
+        }
+
+        private Color[] GetPixelsForSelection(Layer layer, Coordinates[] selection)
+        {
+            Color[] pixels = new Color[_startSelection.Length];
+            layer.LayerBitmap.Lock();
+
+            for (int i = 0; i < pixels.Length; i++)
+            {
+                Coordinates position = selection[i];
+                if (position.X < 0 || position.X > layer.Width - 1 || position.Y < 0 || position.Y > layer.Height - 1)
+                    continue;
+                pixels[i] = layer.LayerBitmap.GetPixel(position.X, position.Y);
+            }
+            layer.LayerBitmap.Unlock();
+            return pixels;
+        }
+    }
+}

+ 2 - 0
PixiEditor/PixiEditor.csproj

@@ -16,6 +16,7 @@
   </PropertyGroup>
 
   <ItemGroup>
+    <None Remove="Images\MoveImage.png" />
     <None Remove="Images\PixiEditorLogo.png" />
     <None Remove="Images\SelectImage.png" />
     <None Remove="Images\SwapArrows.png" />
@@ -49,6 +50,7 @@
     <Resource Include="Images\EarserImage.png" />
     <Resource Include="Images\BrightnessImage.png" />
     <Resource Include="Images\LineImage.png" />
+    <Resource Include="Images\MoveImage.png" />
     <Resource Include="Images\PenImage.png" />
     <Resource Include="Images\ColorPickerImage.png" />
     <Resource Include="Images\PixiEditorLogo.png">

+ 3 - 3
PixiEditor/ViewModels/ViewModelMain.cs

@@ -164,7 +164,7 @@ namespace PixiEditor.ViewModels
             SwapColorsCommand = new RelayCommand(SwapColors);
             KeyDownCommand = new RelayCommand(KeyDown);
             RenameLayerCommand = new RelayCommand(RenameLayer);
-            ToolSet = new ObservableCollection<Tool> { new SelectTool(), new PenTool(), new FloodFill(), new LineTool(),
+            ToolSet = new ObservableCollection<Tool> {new MoveTool(), new PenTool(), new SelectTool(), new FloodFill(), new LineTool(),
             new CircleTool(), new RectangleTool(), new EarserTool(), new ColorPickerTool(), new BrightnessTool()};
             ShortcutController = new ShortcutController
             {
@@ -187,7 +187,7 @@ namespace PixiEditor.ViewModels
                 }
             };
             UndoManager.SetMainRoot(this);
-            SetActiveTool(ToolType.Pen);
+            SetActiveTool(ToolType.Move);
             BitmapManager.PrimaryColor = PrimaryColor;
             Current = this;
         }
@@ -209,7 +209,7 @@ namespace PixiEditor.ViewModels
 
         private void MouseController_StoppedRecordingChanges(object sender, EventArgs e)
         {
-            if (BitmapManager.SelectedTool is BitmapOperationTool)
+            if (BitmapManager.IsOperationTool(BitmapManager.SelectedTool))
             {
                 Tuple<LayerChanges, LayerChanges> changes = ChangesController.PopChanges();
                 if (changes.Item1.PixelChanges.ChangedPixels.Count > 0)