Browse Source

Fixed movetool

flabbet 5 years ago
parent
commit
42b27ef8b7

+ 3 - 2
PixiEditor/Models/Controllers/UndoManager.cs

@@ -36,6 +36,7 @@ namespace PixiEditor.Models.Controllers
             ) //Clears RedoStack if las move wasn't redo or undo and if redo stack is greater than 0
                 RedoStack.Clear();
             _lastChangeWasUndo = false;
+            change.Root ??= MainRoot;
             UndoStack.Push(change);
         }
 
@@ -47,7 +48,7 @@ namespace PixiEditor.Models.Controllers
             _lastChangeWasUndo = true;
             Change change = UndoStack.Pop();
             if (change.ReverseProcess == null)
-                SetPropertyValue(MainRoot, change.Property, change.OldValue);
+                SetPropertyValue(change.Root, change.Property, change.OldValue);
             else
                 change.ReverseProcess(change.ReverseProcessArguments);
             RedoStack.Push(change);
@@ -61,7 +62,7 @@ namespace PixiEditor.Models.Controllers
             _lastChangeWasUndo = true;
             Change change = RedoStack.Pop();
             if (change.ReverseProcess == null)
-                SetPropertyValue(MainRoot, change.Property, change.NewValue);
+                SetPropertyValue(change.Root, change.Property, change.NewValue);
             else
                 change.Process(change.ProcessArguments);
             UndoStack.Push(change);

+ 5 - 2
PixiEditor/Models/DataHolders/Change.cs

@@ -17,24 +17,27 @@ namespace PixiEditor.Models.DataHolders
         public Action<object[]> Process { get; set; }
         public object[] ProcessArguments;
         public object[] ReverseProcessArguments;
+        public object Root { get; set; }
 
 
-        public Change(string property, object oldValue, object newValue, string description = "")
+        public Change(string property, object oldValue, object newValue, string description = "", object root = null)
         {
             Property = property;
             OldValue = oldValue;
             Description = description;
             NewValue = newValue;
+            Root = root;
         }
 
         public Change(string property, Action<object[]> reverseProcess, object[] reverseArguments,
-            object newValue, string description = "")
+            object newValue, string description = "", object root = null)
         {
             Property = property;
             ReverseProcess = reverseProcess;
             ReverseProcessArguments = reverseArguments;
             NewValue = newValue;
             Description = description;
+            Root = root;
         }
 
         public Change(string property, Action<object[]> reverseProcess, object[] reverseArguments,

+ 4 - 5
PixiEditor/Models/DataHolders/Selection.cs

@@ -30,14 +30,13 @@ namespace PixiEditor.Models.DataHolders
         public Selection(Coordinates[] selectedPoints)
         {
             SelectedPoints = new ObservableCollection<Coordinates>(selectedPoints);
-            SelectionLayer = new Layer("_selectionLayer", ViewModelMain.Current.BitmapManager.ActiveDocument.Width,
-                ViewModelMain.Current.BitmapManager.ActiveDocument.Height);
+            SelectionLayer = new Layer("_selectionLayer");
             _selectionBlue = Color.FromArgb(127, 142, 202, 255);
         }
 
         public void SetSelection(Coordinates[] selection, SelectionType mode)
         {
-            Color _selectionColor = _selectionBlue;
+            Color selectionColor = _selectionBlue;
             switch (mode)
             {
                 case SelectionType.New:
@@ -49,11 +48,11 @@ namespace PixiEditor.Models.DataHolders
                     break;
                 case SelectionType.Subtract:
                     SelectedPoints = new ObservableCollection<Coordinates>(SelectedPoints.Except(selection));
-                    _selectionColor = System.Windows.Media.Colors.Transparent;
+                    selectionColor = System.Windows.Media.Colors.Transparent;
                     break;
             }
 
-            SelectionLayer.ApplyPixels(BitmapPixelChanges.FromSingleColoredArray(selection, _selectionColor));
+            SelectionLayer.ApplyPixels(BitmapPixelChanges.FromSingleColoredArray(selection, selectionColor));
         }
 
         public void Clear()

+ 10 - 8
PixiEditor/Models/Images/BitmapUtils.cs

@@ -61,18 +61,20 @@ namespace PixiEditor.Models.Images
             for (int i = 0; i < layers.Length; i++)
             {
                 Color[] pixels = new Color[selection.Length];
-                layers[i].LayerBitmap.Lock();
 
-                for (int j = 0; j < pixels.Length; j++)
+                using (layers[i].LayerBitmap.GetBitmapContext())
                 {
-                    Coordinates position = selection[j];
-                    if (position.X < 0 || position.X > layers[i].Width - 1 || position.Y < 0 ||
-                        position.Y > layers[i].Height - 1)
-                        continue;
-                    pixels[j] = layers[i].LayerBitmap.GetPixel(position.X, position.Y);
+
+                    for (int j = 0; j < pixels.Length; j++)
+                    {
+                        Coordinates position = layers[i].GetRelativePosition(selection[j]);
+                        if (position.X < 0 || position.X > layers[i].Width - 1 || position.Y < 0 ||
+                            position.Y > layers[i].Height - 1)
+                            continue;
+                        pixels[j] = layers[i].GetPixel(position.X, position.Y);
+                    }
                 }
 
-                layers[i].LayerBitmap.Unlock();
 
                 result[layers[i]] = pixels;
             }

+ 9 - 0
PixiEditor/Models/Layers/Layer.cs

@@ -92,6 +92,15 @@ namespace PixiEditor.Models.Layers
 
         public Dictionary<Coordinates,Color> LastRelativeCoordinates;
 
+        public Layer(string name)
+        {
+            Name = name;
+            Layer layer = LayerGenerator.Generate(0, 0);
+            LayerBitmap = layer.LayerBitmap;
+            Width = 0;
+            Height = 0;
+        }
+
         public Layer(string name, int width, int height)
         {
             Name = name;

+ 2 - 0
PixiEditor/Models/Layers/SerializableLayer.cs

@@ -1,4 +1,5 @@
 using System;
+using System.Windows;
 using PixiEditor.Models.Layers;
 
 namespace PixiEditor.Models.DataHolders
@@ -11,6 +12,7 @@ namespace PixiEditor.Models.DataHolders
         public int Height { get; set; }
         public byte[] BitmapBytes { get; set; }
         public bool IsVisible { get; set; }
+        public Thickness Offset { get; set; }
 
         public SerializableLayer(Layer layer)
         {

+ 67 - 23
PixiEditor/Models/Tools/Tools/MoveTool.cs

@@ -1,5 +1,7 @@
-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
 using System.Linq;
+using System.Windows;
 using System.Windows.Input;
 using System.Windows.Media;
 using PixiEditor.Helpers.Extensions;
@@ -25,6 +27,7 @@ namespace PixiEditor.Models.Tools.Tools
         private Coordinates _lastMouseMove;
         private Coordinates _lastStartMousePos;
         private Dictionary<Layer, Color[]> _startPixelColors;
+        private Dictionary<Layer, Thickness> _startingOffsets;
         private Coordinates[] _startSelection;
         private bool _updateViewModelSelection = true;
 
@@ -39,38 +42,57 @@ namespace PixiEditor.Models.Tools.Tools
 
         public override void AfterAddedUndo()
         {
-            //Inject to default undo system change custom changes made by this tool
-            foreach (var item in _startPixelColors)
+            if (_currentSelection.Length != 0)
             {
-                BitmapPixelChanges beforeMovePixels = BitmapPixelChanges.FromArrays(_startSelection, item.Value);
-                Change changes = UndoManager.UndoStack.Peek();
-                int layerIndex = ViewModelMain.Current.BitmapManager.ActiveDocument.Layers.IndexOf(item.Key);
+                //Inject to default undo system change custom changes made by this tool
+                foreach (var item in _startPixelColors)
+                {
+                    BitmapPixelChanges beforeMovePixels = BitmapPixelChanges.FromArrays(_startSelection, item.Value);
+                    Change changes = UndoManager.UndoStack.Peek();
+                    int layerIndex = ViewModelMain.Current.BitmapManager.ActiveDocument.Layers.IndexOf(item.Key);
 
-                ((LayerChange[]) changes.OldValue)[layerIndex].PixelChanges.ChangedPixels
-                    .AddRangeOverride(beforeMovePixels.ChangedPixels);
+                    ((LayerChange[]) changes.OldValue).First(x=> x.LayerIndex == layerIndex).PixelChanges.ChangedPixels
+                        .AddRangeOverride(beforeMovePixels.ChangedPixels);
 
-                ((LayerChange[]) changes.NewValue)[layerIndex].PixelChanges.ChangedPixels
-                    .AddRangeNewOnly(BitmapPixelChanges.FromSingleColoredArray(_startSelection, System.Windows.Media.Colors.Transparent).ChangedPixels);
+                    ((LayerChange[]) changes.NewValue).First(x => x.LayerIndex == layerIndex).PixelChanges.ChangedPixels
+                        .AddRangeNewOnly(BitmapPixelChanges
+                            .FromSingleColoredArray(_startSelection, System.Windows.Media.Colors.Transparent)
+                            .ChangedPixels);
+                }
+            }
+        }
+
+        public override void OnMouseUp() //This adds undo if there is no selection, reason why this isn't in AfterUndoAdded,
+        {   //is because it doesn't fire if no pixel changes were made.
+            if (_currentSelection.Length == 0)
+            {
+                UndoManager.AddUndoChange(new Change("Offset", ApplyOffsets, new object[]{_startingOffsets}, 
+                    ApplyOffsets, new object[] { GetOffsets(_affectedLayers)}, "Move layers"));
+            }
+        }
+
+        private void ApplyOffsets(object[] parameters)
+        {
+            Dictionary<Layer, Thickness> offsets = (Dictionary<Layer, Thickness>)parameters[0];
+            foreach (var offset in offsets)
+            {
+                offset.Key.Offset = offset.Value;
             }
         }
 
         public override LayerChange[] Use(Layer layer, Coordinates[] mouseMove, Color color)
         {
             Coordinates start = mouseMove[^1];
-            if (_lastStartMousePos != start
-            ) //I am aware that this could be moved to OnMouseDown, but it is executed before Use, so I didn't want to complicate for now
+            if (_lastStartMousePos != start) //I am aware that this could be moved to OnMouseDown, but it is executed before Use, so I didn't want to complicate for now
             {
                 ResetSelectionValues(start);
-                if (ViewModelMain.Current.ActiveSelection.SelectedPoints.Count == 0
-                ) //Move every pixel if none is selected
+                if (ViewModelMain.Current.ActiveSelection.SelectedPoints.Count > 0) //Move offset if no selection
                 {
-                    SelectTool select = new SelectTool();
-                    _currentSelection = select.GetAllSelection();
-                    _updateViewModelSelection = false;
+                    _currentSelection = ViewModelMain.Current.ActiveSelection.SelectedPoints.ToArray();
                 }
                 else
                 {
-                    _currentSelection = ViewModelMain.Current.ActiveSelection.SelectedPoints.ToArray();
+                    _currentSelection = Array.Empty<Coordinates>();
                 }
 
                 if (Keyboard.IsKeyDown(Key.LeftCtrl) || MoveAll)
@@ -81,21 +103,41 @@ namespace PixiEditor.Models.Tools.Tools
 
                 _startSelection = _currentSelection;
                 _startPixelColors = BitmapUtils.GetPixelsForSelection(_affectedLayers, _startSelection);
+                _startingOffsets = GetOffsets(_affectedLayers);
             }
 
             LayerChange[] result = new LayerChange[_affectedLayers.Length];
-
+            var end = mouseMove[0];
             for (int i = 0; i < _affectedLayers.Length; i++)
             {
-                var changes = MoveSelection(_affectedLayers[i], mouseMove);
-                changes = RemoveTransparentPixels(changes);
+                if (_currentSelection.Length > 0)
+                {
+                    var changes = MoveSelection(_affectedLayers[i], mouseMove);
+                    changes = RemoveTransparentPixels(changes);
 
-                result[i] = new LayerChange(changes, _affectedLayers[i]);
+                    result[i] = new LayerChange(changes, _affectedLayers[i]);
+                }
+                else
+                {
+                    var vector = Transform.GetTranslation(_lastMouseMove, end);
+                    _affectedLayers[i].Offset = new Thickness(_affectedLayers[i].OffsetX + vector.X, _affectedLayers[i].OffsetY + vector.Y, 0, 0);
+                    result[i] = new LayerChange(BitmapPixelChanges.Empty, _affectedLayers[i]);
+                }
             }
+            _lastMouseMove = end;
 
+            return result;
+        }
 
+        private Dictionary<Layer, Thickness> GetOffsets(Layer[] layers)
+        {
+            Dictionary<Layer, Thickness> dict = new Dictionary<Layer, Thickness>();
+            for (int i = 0; i < layers.Length; i++)
+            {
+                dict.Add(layers[i], layers[i].Offset);
+            }
 
-            return result;
+            return dict;
         }
 
         private BitmapPixelChanges RemoveTransparentPixels(BitmapPixelChanges pixels)
@@ -125,6 +167,8 @@ namespace PixiEditor.Models.Tools.Tools
             _lastMouseMove = start;
             _clearedPixels = new Dictionary<Layer, bool>();
             _updateViewModelSelection = true;
+            _startPixelColors = null;
+            _startSelection = null;
         }
 
         private Coordinates[] TranslateSelection(Coordinates end, out Coordinates[] previousSelection)

+ 5 - 4
PixiEditor/Views/MainWindow.xaml

@@ -182,8 +182,8 @@
                                 </ItemsControl.ItemsPanel>
                                 <ItemsControl.ItemTemplate>
                                     <DataTemplate>
-                                        <Border Width="{Binding Width}" Height="{Binding Height}" Margin="{Binding Offset}"  BorderThickness="0.1" BorderBrush="DodgerBlue">
-                                        <Image VerticalAlignment="Top" HorizontalAlignment="Left" Source="{Binding LayerBitmap}"
+                                        <Border VerticalAlignment="Top" HorizontalAlignment="Left" Width="{Binding Width}" Height="{Binding Height}" Margin="{Binding Offset}"  BorderThickness="0.1" BorderBrush="DodgerBlue">
+                                        <Image Source="{Binding LayerBitmap}"
                                                Visibility="{Binding IsVisible, Converter={StaticResource BoolToVisibilityConverter}}"
                                                RenderOptions.BitmapScalingMode="NearestNeighbor" Stretch="Uniform"
                                                Width="{Binding Width}" Height="{Binding Height}" />
@@ -191,10 +191,11 @@
                                     </DataTemplate>
                                 </ItemsControl.ItemTemplate>
                             </ItemsControl>
-                            <Image Source="{Binding ActiveSelection.SelectionLayer.LayerBitmap}"
+                            <Image VerticalAlignment="Top" HorizontalAlignment="Left" Source="{Binding ActiveSelection.SelectionLayer.LayerBitmap}"
                                    RenderOptions.BitmapScalingMode="NearestNeighbor" Stretch="Uniform"
                                    Width="{Binding ActiveSelection.SelectionLayer.Width}"
-                                   Height="{Binding ActiveSelection.SelectionLayer.Height}" />
+                                   Height="{Binding ActiveSelection.SelectionLayer.Height}" 
+                                   Margin="{Binding ActiveSelection.SelectionLayer.Offset}" />
                         </Canvas>
                     </vws:MainDrawingPanel.Item>
                 </vws:MainDrawingPanel>