ソースを参照

Refactored tool system and implemented tools

Fixed few bugs as well
flabbet 5 年 前
コミット
d2d4936b62

+ 1 - 1
PixiEditorDotNetCore3/Models/Layer.cs

@@ -47,7 +47,7 @@ namespace PixiEditorDotNetCore3.Models
         {
             foreach (var coords in pixels.ChangedCoordinates)
             {
-                LayerBitmap.SetPixel(coords.X, coords.Y, color);
+                LayerBitmap.SetPixel(Math.Clamp(coords.X, 0, Width - 1), Math.Clamp(coords.Y, 0, Height - 1), color);
             }
         }
     }

+ 1 - 1
PixiEditorDotNetCore3/Models/MousePositionConverter.cs

@@ -18,6 +18,6 @@ namespace PixiEditorDotNetCore3.Models
             int xCoord = (int)(mousePosition.X / baseLayer.Width);
             int yCoord = (int)(mousePosition.Y / baseLayer.Height);
             return new Coordinates(xCoord, yCoord);
-        }
+        }       
     }
 }

+ 41 - 0
PixiEditorDotNetCore3/Models/Tools/ShapeTool.cs

@@ -0,0 +1,41 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Windows.Media;
+
+namespace PixiEditorDotNetCore3.Models.Tools
+{
+    public abstract class ShapeTool : Tool
+    {
+        public override abstract ToolType ToolType { get; }
+
+        public ShapeTool()
+        {
+            ExecutesItself = true;
+        }
+
+        public abstract override BitmapPixelChanges Use(Layer layer, Coordinates startingCoords, Color color, int toolSize);
+
+        protected DoubleCords CalculateCoordinatesForShapeRotation(Coordinates startingCords)
+        {
+            Coordinates currentCoordinates = MousePositionConverter.CurrentCoordinates;
+
+            if (startingCords.X > currentCoordinates.X && startingCords.Y > currentCoordinates.Y)
+            {
+                return new DoubleCords(new Coordinates(currentCoordinates.X, currentCoordinates.Y), new Coordinates(startingCords.X, startingCords.Y));
+            }
+            else if (startingCords.X < currentCoordinates.X && startingCords.Y < currentCoordinates.Y)
+            {
+                return new DoubleCords(new Coordinates(startingCords.X, startingCords.Y), new Coordinates(currentCoordinates.X, currentCoordinates.Y));
+            }
+            else if (startingCords.Y > currentCoordinates.Y)
+            {
+                return new DoubleCords(new Coordinates(startingCords.X, currentCoordinates.Y), new Coordinates(currentCoordinates.X, startingCords.Y));
+            }
+            else
+            {
+                return new DoubleCords(new Coordinates(currentCoordinates.X, startingCords.Y), new Coordinates(startingCords.X, currentCoordinates.Y));
+            }
+        }
+    }
+}

+ 0 - 1
PixiEditorDotNetCore3/Models/Tools/Tool.cs

@@ -7,7 +7,6 @@ namespace PixiEditorDotNetCore3.Models.Tools
 {
     public abstract class Tool
     {
-        public bool IsShapeCreating = false;
         public abstract BitmapPixelChanges Use(Layer layer, Coordinates startingCoords, Color color, int toolSize);
         public abstract ToolType ToolType { get; }
         public bool ExecutesItself = false;

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

@@ -8,6 +8,6 @@ namespace PixiEditorDotNetCore3.Models.Tools
 {
     public enum ToolType
     {
-        Pen = 0, Bucket, Line, Circle, Rectangle, ColorPicker, Earser, Lighten
+        Pen = 0, Bucket, Line, Circle, Rectangle, ColorPicker, Earser, Brightness
     }
 }

+ 30 - 0
PixiEditorDotNetCore3/Models/Tools/Tools/BrightnessTool.cs

@@ -0,0 +1,30 @@
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+
+namespace PixiEditorDotNetCore3.Models.Tools.Tools
+{
+    public class BrightnessTool : Tool
+    {
+        public override ToolType ToolType => ToolType.Brightness;
+        public const float DarkenFactor = -0.06f;
+        public const float LightenFactor = 0.1f;
+
+        public override BitmapPixelChanges Use(Layer layer, Coordinates startingCoords, Color color, int toolSize)
+        {
+            if(Mouse.LeftButton == MouseButtonState.Pressed)
+            {
+                return ChangeBrightness(layer, startingCoords, toolSize, LightenFactor);
+            }
+                return ChangeBrightness(layer, startingCoords, toolSize, DarkenFactor);
+        }       
+
+        private BitmapPixelChanges ChangeBrightness(Layer layer, Coordinates coordinates, int toolSize, float correctionFactor)
+        {
+            PenTool pen = new PenTool();
+            Color pixel = layer.LayerBitmap.GetPixel(coordinates.X, coordinates.Y);
+            Color newColor = ExColor.ChangeColorBrightness(System.Drawing.Color.FromArgb(pixel.R, pixel.G, pixel.B), correctionFactor);
+            return pen.Draw(coordinates, newColor, toolSize);
+        }
+    }
+}

+ 28 - 0
PixiEditorDotNetCore3/Models/Tools/Tools/CircleTool.cs

@@ -0,0 +1,28 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+
+namespace PixiEditorDotNetCore3.Models.Tools.Tools
+{
+    public class CircleTool : ShapeTool
+    {
+        public override ToolType ToolType => ToolType.Circle;
+
+        public override BitmapPixelChanges Use(Layer layer, Coordinates startingCoords, Color color, int toolSize)
+        {
+            CreateCircle(layer, startingCoords, color, toolSize);
+            return new BitmapPixelChanges();
+        }
+
+        public void CreateCircle(Layer layer, Coordinates coordinates, Color color, int size)
+        {
+            DoubleCords calculatedCords = CalculateCoordinatesForShapeRotation(coordinates);
+            layer.LayerBitmap.DrawEllipse(calculatedCords.Coords1.X, calculatedCords.Coords1.Y, calculatedCords.Coords2.X,
+                calculatedCords.Coords2.Y, color);
+        }
+
+        
+    }
+}

+ 18 - 0
PixiEditorDotNetCore3/Models/Tools/Tools/EarserTool.cs

@@ -0,0 +1,18 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Windows.Media;
+
+namespace PixiEditorDotNetCore3.Models.Tools.Tools
+{
+    public class EarserTool : Tool
+    {
+        public override ToolType ToolType => ToolType.Earser;
+
+        public override BitmapPixelChanges Use(Layer layer, Coordinates startingCoords, Color color, int toolSize)
+        {
+            PenTool pen = new PenTool();
+            return pen.Draw(startingCoords, Colors.Transparent, toolSize);
+        }
+    }
+}

+ 4 - 19
PixiEditorDotNetCore3/Models/Tools/Tools/LineTool.cs

@@ -1,37 +1,22 @@
-using System;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.Text;
-using System.Threading.Tasks;
-using System.Windows;
-using System.Windows.Input;
-using System.Windows.Media;
+using System.Windows.Media;
 using System.Windows.Media.Imaging;
 
 namespace PixiEditorDotNetCore3.Models.Tools.Tools
 {
-    public class LineTool : Tool
+    public class LineTool : ShapeTool
     {
         public override ToolType ToolType => ToolType.Line;
 
-        public LineTool()
-        {
-            ExecutesItself = true;
-            IsShapeCreating = true;
-        }
-
         public override BitmapPixelChanges Use(Layer layer, Coordinates startingCoords, Color color, int toolSize)
         {
-            Line(layer, startingCoords, color, toolSize);
+            CreateLine(layer, startingCoords, color, toolSize);
             return new BitmapPixelChanges();
         }
 
-        public void Line(Layer layer, Coordinates coordinates, Color color, int size)
+        public void CreateLine(Layer layer, Coordinates coordinates, Color color, int size)
         {           
             layer.LayerBitmap.DrawLineBresenham(coordinates.X, coordinates.Y, MousePositionConverter.CurrentCoordinates.X,
                 MousePositionConverter.CurrentCoordinates.Y, color);
-
-
         }
     }
 }

+ 1 - 1
PixiEditorDotNetCore3/Models/Tools/Tools/Pen.cs → PixiEditorDotNetCore3/Models/Tools/Tools/PenTool.cs

@@ -5,7 +5,7 @@ using System.Windows.Media;
 
 namespace PixiEditorDotNetCore3.Models.Tools.Tools
 {
-    public class Pen : Tool
+    public class PenTool : Tool
     {
         public override ToolType ToolType => ToolType.Pen;
 

+ 22 - 0
PixiEditorDotNetCore3/Models/Tools/Tools/RectangleTool.cs

@@ -0,0 +1,22 @@
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+
+namespace PixiEditorDotNetCore3.Models.Tools.Tools
+{
+    public class RectangleTool : ShapeTool
+    {
+        public override ToolType ToolType => ToolType.Rectangle;
+
+        public override BitmapPixelChanges Use(Layer layer, Coordinates startingCoords, Color color, int toolSize)
+        {
+            CreateRectangle(layer,startingCoords,color,toolSize);
+            return new BitmapPixelChanges();
+        }
+
+        public void CreateRectangle(Layer layer, Coordinates startingCoords, Color color, int toolSize)
+        {
+            DoubleCords coordinates = CalculateCoordinatesForShapeRotation(startingCoords);
+            layer.LayerBitmap.DrawRectangle(coordinates.Coords1.X, coordinates.Coords1.Y, coordinates.Coords2.X, coordinates.Coords2.Y, color);
+        }
+    }
+}

+ 4 - 44
PixiEditorDotNetCore3/Models/Tools/ToolsManager.cs

@@ -47,9 +47,10 @@ namespace PixiEditorDotNetCore3.Models.Tools
                     _layer.LayerBitmap.Blit(new Rect(new Size(_layer.Width, _layer.Height)), _clonedBitmap, new Rect(new Size(_layer.Width, _layer.Height)), WriteableBitmapExtensions.BlendMode.Additive);
                 }
                 BitmapPixelChanges changes = SelectedTool.Use(_layer, _startCoordinates, _color, _toolSzie);
+
                 if (!SelectedTool.ExecutesItself)
                 {
-                    _layer.ApplyPixels(changes, _color);
+                    _layer.ApplyPixels(changes, changes.PixelsColor);
                 }
             });
         }
@@ -74,7 +75,7 @@ namespace PixiEditorDotNetCore3.Models.Tools
 
         private void CloneBitmapIfToolIsShape()
         {
-            if (SelectedTool.IsShapeCreating == true)
+            if (SelectedTool.GetType().BaseType == typeof(ShapeTool))
             {
                 _clonedBitmap = _layer.LayerBitmap.Clone();                
             }
@@ -94,7 +95,7 @@ namespace PixiEditorDotNetCore3.Models.Tools
             if (toolSize < 1)
                 return;
 
-            if(_toolRecievedData == false || (_toolRecievedData == true && !SelectedTool.IsShapeCreating))
+            if(_toolRecievedData == false || (_toolRecievedData == true && SelectedTool.GetType().BaseType != typeof(ShapeTool)))
             {
                 _startCoordinates = startingCoords;
                 _layer = layer;
@@ -110,46 +111,5 @@ namespace PixiEditorDotNetCore3.Models.Tools
             }
         }
 
-      
-
-       
-        /// <summary>
-        /// Returns color of pixel.
-        /// </summary>
-        /// <param name="layer">Layer in which bitmap with pixels are stored.</param>
-        /// <param name="coordinates">Pixel coordinate.</param>
-        /// <returns></returns>
-        public static Color ColorPicker(Layer layer, Coordinates coordinates)
-        {
-            return layer.LayerBitmap.GetPixel(coordinates.X, coordinates.Y);
-        }
-        /// <summary>
-        /// Ligtens pixel color.
-        /// </summary>
-        /// <param name="bitmap">Bitmap to work on.</param>
-        /// <param name="coordinates">Pixel coordinates.</param>
-        /// <returns></returns>
-        private WriteableBitmap Lighten(WriteableBitmap bitmap, Coordinates coordinates)
-        {
-            WriteableBitmap wb = bitmap;
-            Color pixel = wb.GetPixel(coordinates.X, coordinates.Y);
-            Color newColor = ExColor.ChangeColorBrightness(System.Drawing.Color.FromArgb(pixel.R, pixel.G, pixel.B), 0.1f);
-            wb.SetPixel(coordinates.X, coordinates.Y, newColor);
-            return wb;
-        }
-        /// <summary>
-        /// Darkens pixel color.
-        /// </summary>
-        /// <param name="bitmap">Bitmap to work on.</param>
-        /// <param name="coordinates">Pixel coordinates.</param>
-        /// <returns></returns>
-        private WriteableBitmap Darken(WriteableBitmap bitmap, Coordinates coordinates)
-        {
-            WriteableBitmap wb = bitmap;
-            Color pixel = wb.GetPixel(coordinates.X, coordinates.Y);
-            Color newColor = ExColor.ChangeColorBrightness(System.Drawing.Color.FromArgb(pixel.R,pixel.G,pixel.B), -0.06f);
-            wb.SetPixel(coordinates.X, coordinates.Y, newColor);
-            return wb;
-        }
     }
 }

+ 1 - 0
PixiEditorDotNetCore3/ViewModels/NewFileMenuViewModel.cs

@@ -1,4 +1,5 @@
 using PixiEditor.Helpers;
+using PixiEditorDotNetCore3.Models;
 using System;
 using System.Collections.Generic;
 using System.Diagnostics;

+ 31 - 4
PixiEditorDotNetCore3/ViewModels/ViewModelMain.cs

@@ -68,7 +68,13 @@ namespace PixiEditor.ViewModels
 
         public LightLayer ActiveLightLayer
         {
-            get => new LightLayer(_activeLayer.LayerBitmap.ToByteArray(), ActiveLayer.Height, ActiveLayer.Width);
+            get 
+            {
+                if (_activeLayer != null)
+                    return new LightLayer(_activeLayer.LayerBitmap.ToByteArray(), ActiveLayer.Height, ActiveLayer.Width);
+                else
+                    return null;
+            }
             set => ActiveLayer = new Layer(BitmapConverter.BytesToWriteableBitmap(ActiveLayer.Width, ActiveLayer.Height,value.LayerBytes));
         }
 
@@ -159,7 +165,8 @@ namespace PixiEditor.ViewModels
             MouseUpCommand = new RelayCommand(MouseUp);
             RecenterZoomboxCommand = new RelayCommand(RecenterZoombox);
             OpenFileCommand = new RelayCommand(OpenFile);
-            primaryToolSet = new ToolsManager(new List<Tool> { new PixiTools.Pen(), new PixiTools.FloodFill(), new PixiTools.LineTool() });
+            primaryToolSet = new ToolsManager(new List<Tool> { new PixiTools.PenTool(), new PixiTools.FloodFill(), new PixiTools.LineTool(),
+            new PixiTools.CircleTool(), new PixiTools.RectangleTool(), new PixiTools.EarserTool(), new PixiTools.BrightnessTool()});
             UndoManager.SetMainRoot(this);
             primaryToolSet.SetTool(SelectedTool);
         }
@@ -241,8 +248,28 @@ namespace PixiEditor.ViewModels
             {
                 return;
             }
-            primaryToolSet.ExecuteTool(ActiveLayer, cords, SelectedColor, ToolSize);
-            RefreshImage();
+
+            if (SelectedTool != ToolType.ColorPicker)
+            {
+                primaryToolSet.ExecuteTool(ActiveLayer, cords, SelectedColor, ToolSize);
+                RefreshImage();
+            }
+            else
+            {
+                ExecuteColorPicker(cords);
+            }
+        }
+
+        private void ExecuteColorPicker(Coordinates cords)
+        {
+            if (Mouse.LeftButton == MouseButtonState.Pressed)
+            {
+                PrimaryColor = ActiveLayer.LayerBitmap.GetPixel(cords.X, cords.Y);
+            }
+            else
+            {
+                SecondaryColor = ActiveLayer.LayerBitmap.GetPixel(cords.X, cords.Y);
+            }
         }
 
         private void RefreshImage()

+ 3 - 3
PixiEditorDotNetCore3/Views/MainWindow.xaml

@@ -175,7 +175,7 @@
                     <ImageBrush ImageSource="/Images/EarserImage.png" Stretch="Uniform"/>
                 </Button.Background>
             </Button>
-            <Button Style="{StaticResource ToolButtonStyle}" Command="{Binding SelectToolCommand, Mode=OneWay}" CommandParameter="Lighten" ToolTip="Makes pixel brighter or darker pixel (U)">
+            <Button Style="{StaticResource ToolButtonStyle}" Command="{Binding SelectToolCommand, Mode=OneWay}" CommandParameter="Brightness" ToolTip="Makes pixel brighter or darker pixel (U)">
                 <Button.Background>
                     <ImageBrush ImageSource="/Images/LightenImage.png" Stretch="Uniform"/>
                 </Button.Background>
@@ -183,12 +183,12 @@
         </StackPanel>
 
         <Grid VerticalAlignment="Bottom" HorizontalAlignment="Center" Width="60" Grid.Column="0" Grid.Row="1" Margin="0,0,0,0" Height="65">
-            <Rectangle Height="40" Width="40" HorizontalAlignment="Left" VerticalAlignment="Top" Stroke="Black" StrokeThickness="1">
+            <Rectangle Height="40" Width="40" HorizontalAlignment="Left" VerticalAlignment="Top" Stroke="Black" StrokeThickness="1" Panel.ZIndex="1">
                 <Rectangle.Fill>
                     <SolidColorBrush Color="{Binding PrimaryColor, Mode=OneWay}"/>
                 </Rectangle.Fill>
             </Rectangle>
-            <xctk:ColorPicker Width="40" Height="40" VerticalAlignment="Top" HorizontalAlignment="Left" UsingAlphaChannel="True" AvailableColorsSortingMode="Alphabetical" ShowDropDownButton="False" Background="Transparent" BorderThickness="0" ShowRecentColors="True" SelectedColor="{Binding PrimaryColor, Mode=TwoWay}"></xctk:ColorPicker>
+            <xctk:ColorPicker Width="40" Panel.ZIndex="2" Height="40" VerticalAlignment="Top" HorizontalAlignment="Left" UsingAlphaChannel="True" AvailableColorsSortingMode="Alphabetical" ShowDropDownButton="False" Background="Transparent" BorderThickness="0" ShowRecentColors="True" SelectedColor="{Binding PrimaryColor, Mode=TwoWay}"></xctk:ColorPicker>
             <Rectangle Height="40" Width="40" HorizontalAlignment="Right" VerticalAlignment="Bottom" Stroke="Black" StrokeThickness="1" Margin="0,0,4,5">
                 <Rectangle.Fill>
                     <SolidColorBrush Color="{Binding SecondaryColor, Mode=OneWay}"/>