|
@@ -11,12 +11,14 @@ using PixiEditor.Helpers;
|
|
using PixiEditor.Helpers.Extensions;
|
|
using PixiEditor.Helpers.Extensions;
|
|
using Drawie.Backend.Core.Numerics;
|
|
using Drawie.Backend.Core.Numerics;
|
|
using Drawie.Backend.Core.Surfaces;
|
|
using Drawie.Backend.Core.Surfaces;
|
|
|
|
+using Drawie.Backend.Core.Surfaces.PaintImpl;
|
|
using Drawie.Backend.Core.Surfaces.Vector;
|
|
using Drawie.Backend.Core.Surfaces.Vector;
|
|
using PixiEditor.Extensions.UI.Overlays;
|
|
using PixiEditor.Extensions.UI.Overlays;
|
|
using PixiEditor.Helpers.UI;
|
|
using PixiEditor.Helpers.UI;
|
|
using PixiEditor.Models.Controllers.InputDevice;
|
|
using PixiEditor.Models.Controllers.InputDevice;
|
|
using Drawie.Numerics;
|
|
using Drawie.Numerics;
|
|
using PixiEditor.Views.Overlays.Handles;
|
|
using PixiEditor.Views.Overlays.Handles;
|
|
|
|
+using Colors = Drawie.Backend.Core.ColorsImpl.Colors;
|
|
using Point = Avalonia.Point;
|
|
using Point = Avalonia.Point;
|
|
|
|
|
|
namespace PixiEditor.Views.Overlays.TransformOverlay;
|
|
namespace PixiEditor.Views.Overlays.TransformOverlay;
|
|
@@ -153,11 +155,52 @@ internal class TransformOverlay : Overlay
|
|
private VecD mousePosOnStartAnchorDrag;
|
|
private VecD mousePosOnStartAnchorDrag;
|
|
private VecD originOnStartAnchorDrag;
|
|
private VecD originOnStartAnchorDrag;
|
|
|
|
|
|
- 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 Pen blackFreqDashedPen = new Pen(Brushes.Black, 1) { DashStyle = new DashStyle(new double[] { 2, 2 }, 0) };
|
|
|
|
- private Pen whiteFreqDashedPen = new Pen(Brushes.White, 1) { DashStyle = new DashStyle(new double[] { 2, 2 }, 2) };
|
|
|
|
|
|
+ private Paint blackPen = new Paint()
|
|
|
|
+ {
|
|
|
|
+ Color = Colors.Black, StrokeWidth = 1, Style = PaintStyle.Stroke, IsAntiAliased = true
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ private Paint whiteFillPen = new Paint()
|
|
|
|
+ {
|
|
|
|
+ Color = Colors.White, StrokeWidth = 1, Style = PaintStyle.Fill, IsAntiAliased = true
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ private Paint blackDashedPen = new Paint()
|
|
|
|
+ {
|
|
|
|
+ Color = Colors.Black,
|
|
|
|
+ StrokeWidth = 1,
|
|
|
|
+ Style = PaintStyle.Stroke,
|
|
|
|
+ PathEffect = PathEffect.CreateDash(
|
|
|
|
+ [2, 4], 0),
|
|
|
|
+ IsAntiAliased = true
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ private Paint whiteDashedPen = new Paint()
|
|
|
|
+ {
|
|
|
|
+ Color = Colors.White,
|
|
|
|
+ StrokeWidth = 1,
|
|
|
|
+ Style = PaintStyle.Stroke,
|
|
|
|
+ PathEffect = PathEffect.CreateDash([2, 4], 2),
|
|
|
|
+ IsAntiAliased = true
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ private Paint blackFreqDashedPen = new Paint()
|
|
|
|
+ {
|
|
|
|
+ Color = Colors.Black,
|
|
|
|
+ StrokeWidth = 1,
|
|
|
|
+ Style = PaintStyle.Stroke,
|
|
|
|
+ PathEffect = PathEffect.CreateDash([2, 2], 0),
|
|
|
|
+ IsAntiAliased = true
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ private Paint whiteFreqDashedPen = new Paint()
|
|
|
|
+ {
|
|
|
|
+ Color = Colors.White,
|
|
|
|
+ StrokeWidth = 1,
|
|
|
|
+ Style = PaintStyle.Stroke,
|
|
|
|
+ PathEffect = PathEffect.CreateDash([2, 2], 2),
|
|
|
|
+ IsAntiAliased = true
|
|
|
|
+ };
|
|
|
|
|
|
private AnchorHandle topLeftHandle;
|
|
private AnchorHandle topLeftHandle;
|
|
private AnchorHandle topRightHandle;
|
|
private AnchorHandle topRightHandle;
|
|
@@ -176,6 +219,7 @@ internal class TransformOverlay : Overlay
|
|
private Handle? snapHandleOfOrigin;
|
|
private Handle? snapHandleOfOrigin;
|
|
|
|
|
|
private VectorPath rotateCursorGeometry = Handle.GetHandleGeometry("RotateHandle");
|
|
private VectorPath rotateCursorGeometry = Handle.GetHandleGeometry("RotateHandle");
|
|
|
|
+ private bool rotationCursorActive = false;
|
|
|
|
|
|
private VecD lastPointerPos;
|
|
private VecD lastPointerPos;
|
|
|
|
|
|
@@ -193,14 +237,7 @@ internal class TransformOverlay : Overlay
|
|
centerHandle = new RectangleHandle(this);
|
|
centerHandle = new RectangleHandle(this);
|
|
centerHandle.Size = rightHandle.Size;
|
|
centerHandle.Size = rightHandle.Size;
|
|
|
|
|
|
- // TODO: Fix this
|
|
|
|
- /*originHandle = new(this)
|
|
|
|
- {
|
|
|
|
- StrokePaint = blackFreqDashedPen,
|
|
|
|
- SecondaryHandlePen = whiteFreqDashedPen,
|
|
|
|
- };*/
|
|
|
|
-
|
|
|
|
- return;
|
|
|
|
|
|
+ originHandle = new(this) { StrokePaint = blackFreqDashedPen, SecondaryHandlePen = whiteFreqDashedPen, };
|
|
|
|
|
|
AddHandle(originHandle);
|
|
AddHandle(originHandle);
|
|
AddHandle(topLeftHandle);
|
|
AddHandle(topLeftHandle);
|
|
@@ -243,11 +280,10 @@ internal class TransformOverlay : Overlay
|
|
|
|
|
|
public override void RenderOverlay(Canvas drawingContext, RectD canvasBounds)
|
|
public override void RenderOverlay(Canvas drawingContext, RectD canvasBounds)
|
|
{
|
|
{
|
|
- /*base.Render(drawingContext);
|
|
|
|
- DrawOverlay(drawingContext, new(Bounds.Width, Bounds.Height), Corners, InternalState.Origin, ZoomScale);
|
|
|
|
|
|
+ DrawOverlay(drawingContext, new(Bounds.Width, Bounds.Height), Corners, InternalState.Origin, (float)ZoomScale);
|
|
|
|
|
|
if (capturedAnchor is null)
|
|
if (capturedAnchor is null)
|
|
- UpdateRotationCursor(lastPointerPos);*/
|
|
|
|
|
|
+ UpdateRotationCursor(lastPointerPos);
|
|
}
|
|
}
|
|
|
|
|
|
private void DrawMouseInputArea(Canvas context, VecD size)
|
|
private void DrawMouseInputArea(Canvas context, VecD size)
|
|
@@ -274,16 +310,28 @@ internal class TransformOverlay : Overlay
|
|
}
|
|
}
|
|
|
|
|
|
private void DrawOverlay
|
|
private void DrawOverlay
|
|
- (Canvas context, VecD size, ShapeCorners corners, VecD origin, double zoomboxScale)
|
|
|
|
|
|
+ (Canvas context, VecD size, ShapeCorners corners, VecD origin, float zoomboxScale)
|
|
{
|
|
{
|
|
// draw transparent background to enable mouse input
|
|
// draw transparent background to enable mouse input
|
|
DrawMouseInputArea(context, size);
|
|
DrawMouseInputArea(context, size);
|
|
|
|
|
|
- blackPen.Thickness = 1 / zoomboxScale;
|
|
|
|
- blackDashedPen.Thickness = 1 / zoomboxScale;
|
|
|
|
- whiteDashedPen.Thickness = 1 / zoomboxScale;
|
|
|
|
- blackFreqDashedPen.Thickness = 1 / zoomboxScale;
|
|
|
|
- whiteFreqDashedPen.Thickness = 1 / zoomboxScale;
|
|
|
|
|
|
+ blackPen.StrokeWidth = 1 / zoomboxScale;
|
|
|
|
+ blackDashedPen.StrokeWidth = 1 / zoomboxScale;
|
|
|
|
+ whiteDashedPen.StrokeWidth = 1 / zoomboxScale;
|
|
|
|
+ blackFreqDashedPen.StrokeWidth = 1 / zoomboxScale;
|
|
|
|
+ whiteFreqDashedPen.StrokeWidth = 1 / zoomboxScale;
|
|
|
|
+
|
|
|
|
+ blackDashedPen.PathEffect?.Dispose();
|
|
|
|
+ blackDashedPen.PathEffect = PathEffect.CreateDash([2 / zoomboxScale, 4 / zoomboxScale], 0);
|
|
|
|
+
|
|
|
|
+ whiteDashedPen.PathEffect?.Dispose();
|
|
|
|
+ whiteDashedPen.PathEffect = PathEffect.CreateDash([2 / zoomboxScale, 4 / zoomboxScale], 2);
|
|
|
|
+
|
|
|
|
+ blackFreqDashedPen.PathEffect?.Dispose();
|
|
|
|
+ blackFreqDashedPen.PathEffect = PathEffect.CreateDash([2 / zoomboxScale, 2 / zoomboxScale], 0);
|
|
|
|
+
|
|
|
|
+ whiteFreqDashedPen.PathEffect?.Dispose();
|
|
|
|
+ whiteFreqDashedPen.PathEffect = PathEffect.CreateDash([2 / zoomboxScale, 2 / zoomboxScale], 2);
|
|
|
|
|
|
VecD topLeft = corners.TopLeft;
|
|
VecD topLeft = corners.TopLeft;
|
|
VecD topRight = corners.TopRight;
|
|
VecD topRight = corners.TopRight;
|
|
@@ -295,15 +343,14 @@ internal class TransformOverlay : Overlay
|
|
VecD right = (topRight + bottomRight) / 2;
|
|
VecD right = (topRight + bottomRight) / 2;
|
|
|
|
|
|
// lines
|
|
// lines
|
|
- // 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(topLeft, topRight, blackDashedPen);
|
|
|
|
+ context.DrawLine(topLeft, topRight, whiteDashedPen);
|
|
|
|
+ context.DrawLine(topLeft, bottomLeft, blackDashedPen);
|
|
|
|
+ context.DrawLine(topLeft, bottomLeft, whiteDashedPen);
|
|
|
|
+ context.DrawLine(bottomRight, bottomLeft, blackDashedPen);
|
|
|
|
+ context.DrawLine(bottomRight, bottomLeft, whiteDashedPen);
|
|
|
|
+ context.DrawLine(bottomRight, topRight, blackDashedPen);
|
|
|
|
+ context.DrawLine(bottomRight, topRight, whiteDashedPen);
|
|
|
|
|
|
// corner anchors
|
|
// corner anchors
|
|
|
|
|
|
@@ -336,9 +383,22 @@ internal class TransformOverlay : Overlay
|
|
centerHandle.Draw(context);
|
|
centerHandle.Draw(context);
|
|
}
|
|
}
|
|
|
|
|
|
- // rotate cursor
|
|
|
|
- // TODO: Implement
|
|
|
|
- //context.DrawGeometry(Brushes.White, blackPen, rotateCursorGeometry);
|
|
|
|
|
|
+ int saved = context.Save();
|
|
|
|
+ if (rotationCursorActive)
|
|
|
|
+ {
|
|
|
|
+ var matrix = Matrix3X3.CreateTranslation((float)lastPointerPos.X, (float)lastPointerPos.Y);
|
|
|
|
+ double angle = (lastPointerPos - InternalState.Origin).Angle * 180 / Math.PI - 90;
|
|
|
|
+ matrix = matrix.PostConcat(Matrix3X3.CreateRotationDegrees((float)angle, (float)lastPointerPos.X,
|
|
|
|
+ (float)lastPointerPos.Y));
|
|
|
|
+ matrix = matrix.PostConcat(Matrix3X3.CreateScale(8f / (float)ZoomScale, 8 / (float)ZoomScale,
|
|
|
|
+ (float)lastPointerPos.X, (float)lastPointerPos.Y));
|
|
|
|
+ context.SetMatrix(context.TotalMatrix.Concat(matrix));
|
|
|
|
+
|
|
|
|
+ context.DrawPath(rotateCursorGeometry, blackPen);
|
|
|
|
+ context.DrawPath(rotateCursorGeometry, whiteFillPen);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ context.RestoreToCount(saved);
|
|
}
|
|
}
|
|
|
|
|
|
private void OnAnchorHandlePressed(Handle source, VecD position)
|
|
private void OnAnchorHandlePressed(Handle source, VecD position)
|
|
@@ -361,7 +421,7 @@ internal class TransformOverlay : Overlay
|
|
|
|
|
|
protected override void OnOverlayPointerExited(OverlayPointerArgs args)
|
|
protected override void OnOverlayPointerExited(OverlayPointerArgs args)
|
|
{
|
|
{
|
|
- //rotateCursorGeometry.Transform = new ScaleTransform(0, 0);
|
|
|
|
|
|
+ rotationCursorActive = false;
|
|
Refresh();
|
|
Refresh();
|
|
}
|
|
}
|
|
|
|
|
|
@@ -565,15 +625,11 @@ internal class TransformOverlay : Overlay
|
|
{
|
|
{
|
|
if ((!CanRotate(mousePos) && !isRotating) || LockRotation)
|
|
if ((!CanRotate(mousePos) && !isRotating) || LockRotation)
|
|
{
|
|
{
|
|
- //rotateCursorGeometry.Transform = new ScaleTransform(0, 0);
|
|
|
|
|
|
+ rotationCursorActive = false;
|
|
return false;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
- var matrix = new TranslateTransform(mousePos.X, mousePos.Y).Value;
|
|
|
|
- double angle = (mousePos - InternalState.Origin).Angle * 180 / Math.PI - 90;
|
|
|
|
- matrix = matrix.RotateAt(angle, mousePos.X, mousePos.Y);
|
|
|
|
- matrix = matrix.ScaleAt(8 / ZoomScale, 8 / ZoomScale, mousePos.X, mousePos.Y);
|
|
|
|
- //rotateCursorGeometry.Transform = new MatrixTransform(matrix);
|
|
|
|
|
|
+ rotationCursorActive = true;
|
|
return true;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -638,7 +694,7 @@ internal class TransformOverlay : Overlay
|
|
{
|
|
{
|
|
snapped = TrySnapAnchor(targetPos);
|
|
snapped = TrySnapAnchor(targetPos);
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
if (snapped.Delta == VecD.Zero)
|
|
if (snapped.Delta == VecD.Zero)
|
|
{
|
|
{
|
|
adjacentPos = TransformHelper.GetAnchorPosition(cornersOnStartAnchorDrag, adjacentAnchors.Item2);
|
|
adjacentPos = TransformHelper.GetAnchorPosition(cornersOnStartAnchorDrag, adjacentAnchors.Item2);
|
|
@@ -706,12 +762,12 @@ internal class TransformOverlay : Overlay
|
|
|
|
|
|
return snapped;
|
|
return snapped;
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private SnapData FindProjectedAnchorSnap(VecD projected)
|
|
private SnapData FindProjectedAnchorSnap(VecD projected)
|
|
{
|
|
{
|
|
VecD origin = InternalState.Origin;
|
|
VecD origin = InternalState.Origin;
|
|
var snapped = TrySnapAnchorAlongLine(projected, origin);
|
|
var snapped = TrySnapAnchorAlongLine(projected, origin);
|
|
-
|
|
|
|
|
|
+
|
|
return snapped;
|
|
return snapped;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -753,7 +809,7 @@ internal class TransformOverlay : Overlay
|
|
{
|
|
{
|
|
return new VecD(p2.X, y);
|
|
return new VecD(p2.X, y);
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
double yIntercept = p1.Y - slope * p1.X;
|
|
double yIntercept = p1.Y - slope * p1.X;
|
|
double x = (y - yIntercept) / slope;
|
|
double x = (y - yIntercept) / slope;
|
|
|
|
|
|
@@ -767,7 +823,7 @@ internal class TransformOverlay : Overlay
|
|
{
|
|
{
|
|
return new VecD(x, p2.Y);
|
|
return new VecD(x, p2.Y);
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
double yIntercept = p1.Y - slope * p1.X;
|
|
double yIntercept = p1.Y - slope * p1.X;
|
|
double y = slope * x + yIntercept;
|
|
double y = slope * x + yIntercept;
|
|
|
|
|