瀏覽代碼

Drawie based overlays wip

flabbet 9 月之前
父節點
當前提交
683000cb0b

+ 1 - 0
src/PixiEditor.Extensions/PixiEditor.Extensions.csproj

@@ -21,6 +21,7 @@
     </ItemGroup>
 
     <ItemGroup>
+      <ProjectReference Include="..\Drawie\src\Drawie.Backend.Core\Drawie.Backend.Core.csproj" />
       <ProjectReference Include="..\Drawie\src\Drawie.Numerics\Drawie.Numerics.csproj" />
       <ProjectReference Include="..\PixiEditor.Extensions.CommonApi\PixiEditor.Extensions.CommonApi.csproj" />
     </ItemGroup>

+ 5 - 4
src/PixiEditor.Extensions/UI/Overlays/IHandle.cs

@@ -1,14 +1,15 @@
-using Avalonia.Media;
+using Drawie.Backend.Core.Surfaces;
+using Drawie.Backend.Core.Surfaces.PaintImpl;
 
 namespace PixiEditor.Extensions.UI.Overlays;
 
 public interface IHandle
 {
     public IOverlay Owner { get; }
-    public IBrush HandleBrush { get; set; }
-    public IPen? HandlePen { get; set; }
+    public Paint? FillPaint { get; set; }
+    public Paint? StrokePaint { get; set; }
     public double ZoomScale { get; set; }
 
-    public void Draw(DrawingContext context);
+    public void Draw(Canvas target);
     protected void OnPressed(OverlayPointerArgs args);
 }

+ 7 - 5
src/PixiEditor/Views/Overlays/Handles/AnchorHandle.cs

@@ -1,24 +1,26 @@
 using Avalonia.Controls;
 using Avalonia.Media;
 using Drawie.Backend.Core.Numerics;
+using Drawie.Backend.Core.Surfaces.PaintImpl;
 using PixiEditor.Extensions.UI.Overlays;
 using Drawie.Numerics;
+using Canvas = Drawie.Backend.Core.Surfaces.Canvas;
 
 namespace PixiEditor.Views.Overlays.Handles;
 
 public class AnchorHandle : RectangleHandle
 {
-    private Pen pen;
+    private Paint paint;
     public AnchorHandle(Overlay owner) : base(owner)
     {
         Size = new VecD(GetResource<double>("AnchorHandleSize"));
-        pen = new Pen(GetResource<SolidColorBrush>("HandleBrush"));
-        HandlePen = pen;
+        paint = GetPaint("HandleBrush");
+        StrokePaint = paint;
     }
 
-    public override void Draw(DrawingContext context)
+    public override void Draw(Canvas context)
     {
-        pen.Thickness = 1.0 / ZoomScale;
+        paint.StrokeWidth = (float)(1.0 / ZoomScale);
         base.Draw(context);
     }
 }

+ 15 - 7
src/PixiEditor/Views/Overlays/Handles/Handle.cs

@@ -5,9 +5,12 @@ using Avalonia.Input;
 using Avalonia.Media;
 using PixiEditor.Helpers;
 using Drawie.Backend.Core.Numerics;
+using Drawie.Backend.Core.Surfaces.PaintImpl;
 using PixiEditor.Extensions.UI.Overlays;
 using Drawie.Numerics;
+using PixiEditor.Helpers.Extensions;
 using PixiEditor.Views.Overlays.TransformOverlay;
+using Canvas = Drawie.Backend.Core.Surfaces.Canvas;
 using Path = Avalonia.Controls.Shapes.Path;
 
 namespace PixiEditor.Views.Overlays.Handles;
@@ -15,8 +18,8 @@ namespace PixiEditor.Views.Overlays.Handles;
 public delegate void HandleEvent(Handle source, VecD position);
 public abstract class Handle : IHandle
 {
-    public IBrush HandleBrush { get; set; } = GetBrush("HandleBackgroundBrush");
-    public IPen? HandlePen { get; set; }
+    public Paint? FillPaint { get; set; } = GetPaint("HandleBackgroundBrush");
+    public Paint? StrokePaint { get; set; } = GetPaint("HandleStrokeBrush", PaintStyle.Stroke);
     public double ZoomScale { get; set; } = 1.0;
     public IOverlay Owner { get; set; } = null!;
     public VecD Position { get; set; }
@@ -44,7 +47,7 @@ public abstract class Handle : IHandle
         Owner.PointerReleasedOverlay += OnPointerReleased;
     }
 
-    public abstract void Draw(DrawingContext context);
+    public abstract void Draw(Canvas target);
 
     public virtual void OnPressed(OverlayPointerArgs args) { }
 
@@ -85,14 +88,19 @@ public abstract class Handle : IHandle
         return null;
     }
 
-    protected static IBrush GetBrush(string key)
+    protected static Paint? GetPaint(string key, PaintStyle style = PaintStyle.Fill)
     {
-        if (Application.Current.Styles.TryGetResource(key, null, out object brush))
+        if (Application.Current.Styles.TryGetResource(key, null, out object paint))
         {
-            return (IBrush)brush;
+            if (paint is SolidColorBrush solidColorBrush)
+            {
+                return new Paint() { Color = solidColorBrush.Color.ToColor(), Style = style, IsAntiAliased = true };
+            }
+            
+            throw new InvalidOperationException("Invalid paint style");
         }
 
-        return Brushes.Black;
+        return null;
     }
 
     private void OnPointerPressed(OverlayPointerArgs args)

+ 5 - 2
src/PixiEditor/Views/Overlays/Handles/HandleGlyph.cs

@@ -1,6 +1,7 @@
 using Avalonia;
 using Avalonia.Media;
 using Drawie.Backend.Core.Numerics;
+using Drawie.Backend.Core.Surfaces;
 using Drawie.Numerics;
 
 namespace PixiEditor.Views.Overlays.Handles;
@@ -19,7 +20,7 @@ public class HandleGlyph
         originalBounds = glyph.GetBounds();
     }
 
-    public void Draw(DrawingContext context, double zoomboxScale, VecD position)
+    public void Draw(Canvas context, double zoomboxScale, VecD position)
     {
         VecD scale = NormalizeGlyph(zoomboxScale);
         VecD offset = CalculateOffset(zoomboxScale, position);
@@ -30,7 +31,9 @@ public class HandleGlyph
                 0, scale.Y,
                 offset.X, offset.Y)
         );
-        Glyph.Draw(context);
+        
+        // TODO: Implement
+        //Glyph.Draw(context);
     }
 
     private VecD CalculateOffset(double zoomboxScale, VecD position)

+ 10 - 5
src/PixiEditor/Views/Overlays/Handles/OriginAnchor.cs

@@ -1,23 +1,28 @@
 using Avalonia.Controls;
 using Avalonia.Media;
+using Drawie.Backend.Core.Surfaces.PaintImpl;
+using Drawie.Numerics;
 using PixiEditor.Extensions.UI.Overlays;
 using PixiEditor.Views.Overlays.TransformOverlay;
+using Canvas = Drawie.Backend.Core.Surfaces.Canvas;
+using Colors = Drawie.Backend.Core.ColorsImpl.Colors;
 
 namespace PixiEditor.Views.Overlays.Handles;
 
 public class OriginAnchor : Handle
 {
-    public IPen? SecondaryHandlePen { get; set; } = new Pen(Brushes.White, 1);
-
+    public Paint SecondaryHandlePen { get; set; } = new Paint() { Color = Colors.White, StrokeWidth = 1 };
+    
     public OriginAnchor(Overlay owner) : base(owner)
     {
 
     }
 
-    public override void Draw(DrawingContext context)
+    public override void Draw(Canvas context)
     {
         double radius = Size.LongestAxis / ZoomScale / 2;
-        context.DrawEllipse(HandleBrush, HandlePen, TransformHelper.ToPoint(Position), radius, radius);
-        context.DrawEllipse(HandleBrush, SecondaryHandlePen, TransformHelper.ToPoint(Position), radius, radius);
+        
+        context.DrawOval(Position, new VecD(radius), StrokePaint);
+        context.DrawOval(Position, new VecD(radius), SecondaryHandlePen);
     }
 }

+ 12 - 2
src/PixiEditor/Views/Overlays/Handles/RectangleHandle.cs

@@ -1,7 +1,9 @@
 using Avalonia.Controls;
 using Avalonia.Media;
+using Drawie.Numerics;
 using PixiEditor.Extensions.UI.Overlays;
 using PixiEditor.Views.Overlays.TransformOverlay;
+using Canvas = Drawie.Backend.Core.Surfaces.Canvas;
 
 namespace PixiEditor.Views.Overlays.Handles;
 
@@ -12,10 +14,18 @@ public class RectangleHandle : Handle
     {
     }
 
-    public override void Draw(DrawingContext context)
+    public override void Draw(Canvas context)
     {
         double scaleMultiplier = (1.0 / ZoomScale);
         double radius = AnchorRadius * scaleMultiplier;
-        context.DrawRectangle(HandleBrush, HandlePen, TransformHelper.ToHandleRect(Position, Size, ZoomScale), radius, radius);
+        RectD handleRect = TransformHelper.ToHandleRect(Position, Size, ZoomScale);
+        context.DrawRoundRect((float)handleRect.X, (float)handleRect.Y, (float)handleRect.Width, (float)handleRect.Height,
+            (float)radius, (float)radius, FillPaint);
+        if (StrokePaint != null)
+        {
+            context.DrawRoundRect((float)handleRect.X, (float)handleRect.Y, (float)handleRect.Width,
+                (float)handleRect.Height,
+                (float)radius, (float)radius, StrokePaint);
+        }
     }
 }

+ 15 - 3
src/PixiEditor/Views/Overlays/Handles/TransformHandle.cs

@@ -2,16 +2,18 @@
 using Avalonia.Input;
 using Avalonia.Media;
 using Drawie.Backend.Core.Numerics;
+using Drawie.Backend.Core.Surfaces.PaintImpl;
 using PixiEditor.Extensions.UI.Overlays;
 using Drawie.Numerics;
 using PixiEditor.Views.Overlays.TransformOverlay;
+using Canvas = Drawie.Backend.Core.Surfaces.Canvas;
 
 namespace PixiEditor.Views.Overlays.Handles;
 
 public class TransformHandle : Handle
 {
     public double AnchorRadius { get; set; } = GetResource<double>("AnchorRadius");
-    public IBrush GlyphBrush { get; set; } = GetBrush("HandleGlyphBrush");
+    public Paint GlyphPaint { get; set; } = GetPaint("HandleGlyphBrush");
 
     private HandleGlyph handleGeometry;
 
@@ -23,12 +25,22 @@ public class TransformHandle : Handle
         Cursor = new Cursor(StandardCursorType.SizeAll);
     }
 
-    public override void Draw(DrawingContext context)
+    public override void Draw(Canvas context)
     {
         double scaleMultiplier = (1.0 / ZoomScale);
         double radius = AnchorRadius * scaleMultiplier;
 
-        context.DrawRectangle(HandleBrush, HandlePen, TransformHelper.ToHandleRect(Position, Size, ZoomScale), radius, radius);
+        RectD handleRect = TransformHelper.ToHandleRect(Position, Size, ZoomScale);
+        context.DrawRoundRect((float)handleRect.X, (float)handleRect.Y, (float)handleRect.Width, (float)handleRect.Height,
+            (float)radius, (float)radius, FillPaint);
+
+        if (StrokePaint != null)
+        {
+            context.DrawRoundRect((float)handleRect.X, (float)handleRect.Y, (float)handleRect.Width,
+                (float)handleRect.Height,
+                (float)radius, (float)radius, StrokePaint);
+        }
+        
         handleGeometry.Draw(context, ZoomScale, Position);
     }
 }

+ 24 - 12
src/PixiEditor/Views/Overlays/LineToolOverlay/LineToolOverlay.cs

@@ -6,10 +6,13 @@ using ChunkyImageLib.DataHolders;
 using PixiEditor.Models.Controllers.InputDevice;
 using Drawie.Backend.Core.Numerics;
 using Drawie.Backend.Core.Surfaces;
+using Drawie.Backend.Core.Surfaces.PaintImpl;
+using Drawie.Backend.Core.Surfaces.Vector;
 using PixiEditor.Extensions.UI.Overlays;
 using Drawie.Numerics;
 using PixiEditor.Views.Overlays.Handles;
 using PixiEditor.Views.Overlays.TransformOverlay;
+using Colors = Drawie.Backend.Core.ColorsImpl.Colors;
 using Point = Avalonia.Point;
 
 namespace PixiEditor.Views.Overlays.LineToolOverlay;
@@ -56,10 +59,11 @@ internal class LineToolOverlay : Overlay
         LineStartProperty.Changed.Subscribe(RenderAffectingPropertyChanged);
         LineEndProperty.Changed.Subscribe(RenderAffectingPropertyChanged);
     }
+    
 
-    private Pen blackPen = new Pen(Brushes.Black, 1);
-    private Pen blackDashedPen = new Pen(Brushes.Black, 1) { DashStyle = new DashStyle(new double[] { 2, 4 }, 0) };
-    private Pen whiteDashedPen = new Pen(Brushes.White, 1) { DashStyle = new DashStyle(new double[] { 2, 4 }, 2) };
+    private Paint blackPaint = new Paint() { Color = Colors.Black, StrokeWidth = 1, Style = PaintStyle.Stroke, IsAntiAliased = true };
+    private Paint whiteDashPaint = new Paint() { Color = Colors.White, StrokeWidth = 1, Style = PaintStyle.Stroke, PathEffect = PathEffect.CreateDash(
+        [2, 2], 2), IsAntiAliased = true };
 
     private VecD mouseDownPos = VecD.Zero;
     private VecD lineStartOnMouseDown = VecD.Zero;
@@ -79,14 +83,14 @@ internal class LineToolOverlay : Overlay
         Cursor = new Cursor(StandardCursorType.Arrow);
 
         startHandle = new AnchorHandle(this);
-        startHandle.HandlePen = blackPen;
+        startHandle.StrokePaint = blackPaint;
         startHandle.OnDrag += StartHandleOnDrag;
         startHandle.OnHover += handle => Refresh();
         startHandle.OnRelease += OnHandleRelease;
         AddHandle(startHandle);
 
         endHandle = new AnchorHandle(this);
-        endHandle.HandlePen = blackPen;
+        endHandle.StrokePaint = blackPaint;
         endHandle.OnDrag += EndHandleOnDrag;
         endHandle.Cursor = new Cursor(StandardCursorType.Arrow);
         endHandle.OnHover += handle => Refresh();
@@ -94,7 +98,7 @@ internal class LineToolOverlay : Overlay
         AddHandle(endHandle);
 
         moveHandle = new TransformHandle(this);
-        moveHandle.HandlePen = blackPen;
+        moveHandle.StrokePaint = blackPaint;
         moveHandle.OnDrag += MoveHandleOnDrag;
         endHandle.Cursor = new Cursor(StandardCursorType.Arrow);
         moveHandle.OnHover += handle => Refresh();
@@ -114,9 +118,17 @@ internal class LineToolOverlay : Overlay
 
     protected override void ZoomChanged(double newZoom)
     {
-        blackPen.Thickness = 1.0 / newZoom;
-        blackDashedPen.Thickness = 2.0 / newZoom;
-        whiteDashedPen.Thickness = 2.0 / newZoom;
+        blackPaint.StrokeWidth = (float)(1.0 / newZoom);
+        
+        whiteDashPaint.StrokeWidth = (float)(2.0 / newZoom);
+        whiteDashPaint?.PathEffect?.Dispose();
+        
+        float[] dashes = new float[] { whiteDashPaint.StrokeWidth * 4, whiteDashPaint.StrokeWidth * 3 }; 
+
+        dashes[0] = whiteDashPaint.StrokeWidth * 4;
+        dashes[1] = whiteDashPaint.StrokeWidth * 3;
+        
+        whiteDashPaint.PathEffect = PathEffect.CreateDash(dashes, 2);
     }
 
     public override void RenderOverlay(Canvas context, RectD canvasBounds)
@@ -132,12 +144,12 @@ internal class LineToolOverlay : Overlay
         
         moveHandle.Position = TransformHelper.GetHandlePos(new ShapeCorners(center, size), ZoomScale, moveHandle.Size);
 
-        /*context.DrawLine(blackDashedPen, new Point(mappedStart.X, mappedStart.Y), new Point(mappedEnd.X, mappedEnd.Y));
-        context.DrawLine(whiteDashedPen, new Point(mappedStart.X, mappedStart.Y), new Point(mappedEnd.X, mappedEnd.Y));
+        context.DrawLine(new VecD(mappedStart.X, mappedStart.Y), new VecD(mappedEnd.X, mappedEnd.Y), blackPaint);
+        context.DrawLine(new VecD(mappedStart.X, mappedStart.Y), new VecD(mappedEnd.X, mappedEnd.Y), whiteDashPaint);
         
         startHandle.Draw(context);
         endHandle.Draw(context);
-        moveHandle.Draw(context);*/
+        moveHandle.Draw(context);
     }
 
     protected override void OnOverlayPointerPressed(OverlayPointerArgs args)

+ 2 - 2
src/PixiEditor/Views/Overlays/TransformOverlay/TransformHelper.cs

@@ -10,11 +10,11 @@ using Point = Avalonia.Point;
 namespace PixiEditor.Views.Overlays.TransformOverlay;
 internal static class TransformHelper
 {
-    public static Rect ToHandleRect(VecD pos, VecD size, double zoomboxScale)
+    public static RectD ToHandleRect(VecD pos, VecD size, double zoomboxScale)
     {
         double scaledX = size.X / zoomboxScale;
         double scaledY = size.Y / zoomboxScale;
-        return new Rect(pos.X - scaledX / 2, pos.Y - scaledY / 2, scaledX, scaledY);
+        return new RectD(pos.X - scaledX / 2, pos.Y - scaledY / 2, scaledX, scaledY);
     }
 
     public static VecD ToVecD(Point pos) => new VecD(pos.X, pos.Y);

+ 17 - 12
src/PixiEditor/Views/Overlays/TransformOverlay/TransformOverlay.cs

@@ -192,12 +192,14 @@ internal class TransformOverlay : Overlay
         centerHandle = new RectangleHandle(this);
         centerHandle.Size = rightHandle.Size;
 
-        originHandle = new(this)
+        // TODO: Fix this
+        /*originHandle = new(this)
         {
-            HandlePen = blackFreqDashedPen,
+            StrokePaint = blackFreqDashedPen,
             SecondaryHandlePen = whiteFreqDashedPen,
-            HandleBrush = Brushes.Transparent
-        };
+        };*/
+
+        return;
 
         AddHandle(originHandle);
         AddHandle(topLeftHandle);
@@ -247,12 +249,12 @@ internal class TransformOverlay : Overlay
             UpdateRotationCursor(lastPointerPos);*/
     }
 
-    private void DrawMouseInputArea(DrawingContext context, VecD size)
+    private void DrawMouseInputArea(Canvas context, VecD size)
     {
         if (CoverWholeScreen)
         {
-            context.DrawRectangle(Brushes.Transparent, null,
-                new Rect(new Point(-size.X * 50, -size.Y * 50), new Size(size.X * 101, size.Y * 101)));
+            // TODO: Is it needed? Seems like it makes a hit area for avalonia
+            //context.DrawRect(new RectD(new VecD(-size.X * 50, -size.Y * 50), new VecD(size.X * 101, size.Y * 101)));
             return;
         }
 
@@ -266,11 +268,12 @@ internal class TransformOverlay : Overlay
             ctx.EndFigure(true);
         }
 
-        context.DrawGeometry(Brushes.Transparent, null, geometry);
+        // TODO: Is it needed? Seems like it makes a hit area for avalonia
+        //context.DrawGeometry(Brushes.Transparent, null, geometry);
     }
 
     private void DrawOverlay
-        (DrawingContext context, VecD size, ShapeCorners corners, VecD origin, double zoomboxScale)
+        (Canvas context, VecD size, ShapeCorners corners, VecD origin, double zoomboxScale)
     {
         // draw transparent background to enable mouse input
         DrawMouseInputArea(context, size);
@@ -291,14 +294,15 @@ internal class TransformOverlay : Overlay
         VecD right = (topRight + bottomRight) / 2;
 
         // lines
-        context.DrawLine(blackDashedPen, TransformHelper.ToPoint(topLeft), TransformHelper.ToPoint(topRight));
+        // TODO: Implement
+        /*context.DrawLine(blackDashedPen, TransformHelper.ToPoint(topLeft), TransformHelper.ToPoint(topRight));
         context.DrawLine(whiteDashedPen, TransformHelper.ToPoint(topLeft), TransformHelper.ToPoint(topRight));
         context.DrawLine(blackDashedPen, TransformHelper.ToPoint(topLeft), TransformHelper.ToPoint(bottomLeft));
         context.DrawLine(whiteDashedPen, TransformHelper.ToPoint(topLeft), TransformHelper.ToPoint(bottomLeft));
         context.DrawLine(blackDashedPen, TransformHelper.ToPoint(bottomRight), TransformHelper.ToPoint(bottomLeft));
         context.DrawLine(whiteDashedPen, TransformHelper.ToPoint(bottomRight), TransformHelper.ToPoint(bottomLeft));
         context.DrawLine(blackDashedPen, TransformHelper.ToPoint(bottomRight), TransformHelper.ToPoint(topRight));
-        context.DrawLine(whiteDashedPen, TransformHelper.ToPoint(bottomRight), TransformHelper.ToPoint(topRight));
+        context.DrawLine(whiteDashedPen, TransformHelper.ToPoint(bottomRight), TransformHelper.ToPoint(topRight));*/
 
         // corner anchors
 
@@ -332,7 +336,8 @@ internal class TransformOverlay : Overlay
         }
 
         // rotate cursor
-        context.DrawGeometry(Brushes.White, blackPen, rotateCursorGeometry);
+        // TODO: Implement
+        //context.DrawGeometry(Brushes.White, blackPen, rotateCursorGeometry);
     }
 
     private void OnAnchorHandlePressed(Handle source, VecD position)