Explorar el Código

rotate layer wip

flabbet hace 3 años
padre
commit
7e49f95df8

+ 36 - 0
PixiEditor/Models/DataHolders/Document/Document.Operations.cs

@@ -2,6 +2,7 @@
 using PixiEditor.Models.Enums;
 using PixiEditor.Models.Layers;
 using PixiEditor.Models.Undo;
+using SkiaSharp;
 using System;
 using System.Linq;
 using System.Windows;
@@ -46,6 +47,41 @@ namespace PixiEditor.Models.DataHolders
             DocumentSizeChanged?.Invoke(this, new DocumentSizeChangedEventArgs(oldWidth, oldHeight, width, height));
         }
 
+        public void RotateActiveLayer(float degrees)
+        {
+            Guid layerGuid = ActiveLayer.LayerGuid;
+
+            object[] processArgs = { layerGuid, degrees };
+            object[] reverseProcessArgs = { layerGuid, -degrees };
+
+            RotateLayerProcess(processArgs);
+
+            UndoManager.AddUndoChange(new Change(
+                RotateLayerProcess,
+                reverseProcessArgs,
+                RotateLayerProcess,
+                processArgs,
+                "Rotate layer"));
+        }
+
+        private void RotateLayerProcess(object[] parameters)
+        {
+            Layer layer = Layers.First(x => x.LayerGuid == (Guid)parameters[0]);
+            float degrees = (float)parameters[1];
+
+            using (new SKAutoCanvasRestore(layer.LayerBitmap.SkiaSurface.Canvas, true))
+            {
+                var copy = layer.LayerBitmap.SkiaSurface.Snapshot();
+                var canvas = layer.LayerBitmap.SkiaSurface.Canvas;
+                canvas.Clear();
+                canvas.RotateDegrees(degrees, layer.MaxWidth / 2, layer.MaxHeight / 2);
+                canvas.DrawImage(copy, new SKPoint(0, 0));
+                copy.Dispose();
+            }
+
+            layer.InvokeLayerBitmapChange();
+        }
+
         /// <summary>
         ///     Resizes all document layers using NearestNeighbor interpolation.
         /// </summary>

+ 11 - 0
PixiEditor/ViewModels/SubViewModels/Main/DocumentViewModel.cs

@@ -19,6 +19,8 @@ namespace PixiEditor.ViewModels.SubViewModels.Main
 
         public RelayCommand OpenResizePopupCommand { get; set; }
 
+        public RelayCommand RotateToRightCommand { get; set; }
+
         public DocumentViewModel(ViewModelMain owner)
             : base(owner)
         {
@@ -26,6 +28,15 @@ namespace PixiEditor.ViewModels.SubViewModels.Main
             ClipCanvasCommand = new RelayCommand(ClipCanvas, Owner.DocumentIsNotNull);
             DeletePixelsCommand = new RelayCommand(DeletePixels, Owner.SelectionSubViewModel.SelectionIsNotEmpty);
             OpenResizePopupCommand = new RelayCommand(OpenResizePopup, Owner.DocumentIsNotNull);
+            RotateToRightCommand = new RelayCommand(RotateLayer, Owner.DocumentIsNotNull);
+        }
+
+        public void RotateLayer(object parameter)
+        {
+            if (parameter is double angle)
+            {
+                Owner.BitmapManager.ActiveDocument?.RotateActiveLayer((float)angle);
+            }
         }
 
         public void ClipCanvas(object parameter)

+ 12 - 1
PixiEditor/Views/MainWindow.xaml

@@ -13,7 +13,7 @@
         xmlns:cmd="http://www.galasoft.ch/mvvmlight" 
         xmlns:avalondock="https://github.com/Dirkster99/AvalonDock"
         xmlns:colorpicker="clr-namespace:ColorPicker;assembly=ColorPicker" xmlns:usercontrols="clr-namespace:PixiEditor.Views.UserControls" xmlns:behaviours="clr-namespace:PixiEditor.Helpers.Behaviours" 
-        xmlns:avalonDockTheme="clr-namespace:PixiEditor.Styles.AvalonDock" xmlns:layerUserControls="clr-namespace:PixiEditor.Views.UserControls.Layers" d:DataContext="{d:DesignInstance Type=vm:ViewModelMain}"
+        xmlns:avalonDockTheme="clr-namespace:PixiEditor.Styles.AvalonDock" xmlns:layerUserControls="clr-namespace:PixiEditor.Views.UserControls.Layers" xmlns:sys="clr-namespace:System;assembly=System.Runtime" d:DataContext="{d:DesignInstance Type=vm:ViewModelMain}"
         mc:Ignorable="d" WindowStyle="None" Initialized="MainWindow_Initialized"
         Title="PixiEditor" Name="mainWindow" Height="1000" Width="1600" Background="{StaticResource MainColor}"
         WindowStartupLocation="CenterScreen" WindowState="Maximized">
@@ -134,6 +134,17 @@
                     <MenuItem Header="_Clip Canvas" Command="{Binding DocumentSubViewModel.ClipCanvasCommand}" />
                     <Separator/>
                     <MenuItem Header="_Center Content" Command="{Binding DocumentSubViewModel.CenterContentCommand}" />
+                    <Separator/>
+                    <MenuItem Header="_Rotate to right 90&#186;" Command="{Binding DocumentSubViewModel.RotateToRightCommand}">
+                        <MenuItem.CommandParameter>
+                            <sys:Double>90</sys:Double>
+                        </MenuItem.CommandParameter>
+                    </MenuItem>
+                    <MenuItem Header="_Rotate to left 90&#186;" Command="{Binding DocumentSubViewModel.RotateToRightCommand}">
+                        <MenuItem.CommandParameter>
+                            <sys:Double>-90</sys:Double>
+                        </MenuItem.CommandParameter>
+                    </MenuItem>
                 </MenuItem>
                 <MenuItem Header="_View">
                     <MenuItem Header="_Show Grid Lines" IsChecked="{Binding ViewportSubViewModel.GridLinesEnabled, Mode=TwoWay}"