|
@@ -2,10 +2,14 @@
|
|
using ChunkyImageLib.DataHolders;
|
|
using ChunkyImageLib.DataHolders;
|
|
using Drawie.Backend.Core.Vector;
|
|
using Drawie.Backend.Core.Vector;
|
|
using Drawie.Numerics;
|
|
using Drawie.Numerics;
|
|
|
|
+using PixiEditor.ChangeableDocument;
|
|
using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes.Shapes.Data;
|
|
using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes.Shapes.Data;
|
|
using PixiEditor.Models.Handlers;
|
|
using PixiEditor.Models.Handlers;
|
|
using PixiEditor.Models.Handlers.Tools;
|
|
using PixiEditor.Models.Handlers.Tools;
|
|
using PixiEditor.ChangeableDocument.Actions.Generated;
|
|
using PixiEditor.ChangeableDocument.Actions.Generated;
|
|
|
|
+using PixiEditor.ChangeableDocument.Changeables.Animations;
|
|
|
|
+using PixiEditor.ChangeableDocument.Changeables.Graph.Interfaces.Shapes;
|
|
|
|
+using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
|
|
using PixiEditor.Helpers.Extensions;
|
|
using PixiEditor.Helpers.Extensions;
|
|
using PixiEditor.Models.Controllers.InputDevice;
|
|
using PixiEditor.Models.Controllers.InputDevice;
|
|
using PixiEditor.Models.DocumentModels.UpdateableChangeExecutors.Features;
|
|
using PixiEditor.Models.DocumentModels.UpdateableChangeExecutors.Features;
|
|
@@ -22,6 +26,7 @@ internal class VectorPathToolExecutor : UpdateableChangeExecutor, IPathExecutorF
|
|
private VectorPath startingPath;
|
|
private VectorPath startingPath;
|
|
private IVectorPathToolHandler vectorPathToolHandler;
|
|
private IVectorPathToolHandler vectorPathToolHandler;
|
|
private IBasicShapeToolbar toolbar;
|
|
private IBasicShapeToolbar toolbar;
|
|
|
|
+ private IColorsHandler colorHandler;
|
|
|
|
|
|
public override ExecutorType Type => ExecutorType.ToolLinked;
|
|
public override ExecutorType Type => ExecutorType.ToolLinked;
|
|
|
|
|
|
@@ -30,6 +35,8 @@ internal class VectorPathToolExecutor : UpdateableChangeExecutor, IPathExecutorF
|
|
|
|
|
|
public override bool BlocksOtherActions => false;
|
|
public override bool BlocksOtherActions => false;
|
|
|
|
|
|
|
|
+ private bool mouseDown;
|
|
|
|
+
|
|
public override ExecutionState Start()
|
|
public override ExecutionState Start()
|
|
{
|
|
{
|
|
vectorPathToolHandler = GetHandler<IVectorPathToolHandler>();
|
|
vectorPathToolHandler = GetHandler<IVectorPathToolHandler>();
|
|
@@ -42,6 +49,7 @@ internal class VectorPathToolExecutor : UpdateableChangeExecutor, IPathExecutorF
|
|
}
|
|
}
|
|
|
|
|
|
toolbar = (IBasicShapeToolbar)vectorPathToolHandler.Toolbar;
|
|
toolbar = (IBasicShapeToolbar)vectorPathToolHandler.Toolbar;
|
|
|
|
+ colorHandler = GetHandler<IColorsHandler>();
|
|
|
|
|
|
if (member is IVectorLayerHandler vectorLayerHandler)
|
|
if (member is IVectorLayerHandler vectorLayerHandler)
|
|
{
|
|
{
|
|
@@ -62,24 +70,32 @@ internal class VectorPathToolExecutor : UpdateableChangeExecutor, IPathExecutorF
|
|
return ExecutionState.Error;
|
|
return ExecutionState.Error;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ document.PathOverlayHandler.Show(startingPath, false);
|
|
if (controller.LeftMousePressed)
|
|
if (controller.LeftMousePressed)
|
|
{
|
|
{
|
|
|
|
+ var snapped =
|
|
|
|
+ document.SnappingHandler.SnappingController.GetSnapPoint(controller.LastPrecisePosition, out _,
|
|
|
|
+ out _);
|
|
if (wasNull)
|
|
if (wasNull)
|
|
{
|
|
{
|
|
- startingPath.MoveTo((VecF)controller.LastPrecisePosition);
|
|
|
|
|
|
+ startingPath.MoveTo((VecF)snapped);
|
|
}
|
|
}
|
|
else
|
|
else
|
|
{
|
|
{
|
|
- startingPath.LineTo((VecF)controller.LastPrecisePosition);
|
|
|
|
|
|
+ startingPath.LineTo((VecF)snapped);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (toolbar.SyncWithPrimaryColor)
|
|
|
|
+ {
|
|
|
|
+ toolbar.StrokeColor = colorHandler.PrimaryColor.ToColor();
|
|
|
|
+ toolbar.FillColor = colorHandler.PrimaryColor.ToColor();
|
|
}
|
|
}
|
|
|
|
|
|
//below forces undo before starting new path
|
|
//below forces undo before starting new path
|
|
internals.ActionAccumulator.AddFinishedActions(new EndSetShapeGeometry_Action());
|
|
internals.ActionAccumulator.AddFinishedActions(new EndSetShapeGeometry_Action());
|
|
-
|
|
|
|
|
|
+
|
|
internals.ActionAccumulator.AddActions(new SetShapeGeometry_Action(member.Id, ConstructShapeData()));
|
|
internals.ActionAccumulator.AddActions(new SetShapeGeometry_Action(member.Id, ConstructShapeData()));
|
|
}
|
|
}
|
|
-
|
|
|
|
- document.PathOverlayHandler.Show(startingPath, false);
|
|
|
|
}
|
|
}
|
|
else
|
|
else
|
|
{
|
|
{
|
|
@@ -90,19 +106,68 @@ internal class VectorPathToolExecutor : UpdateableChangeExecutor, IPathExecutorF
|
|
return ExecutionState.Success;
|
|
return ExecutionState.Success;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ public override void OnPrecisePositionChange(VecD pos)
|
|
|
|
+ {
|
|
|
|
+ if (mouseDown)
|
|
|
|
+ {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ VecD mouseSnap =
|
|
|
|
+ document.SnappingHandler.SnappingController.GetSnapPoint(pos, out string snapXAxis,
|
|
|
|
+ out string snapYAxis);
|
|
|
|
+ HighlightSnapping(snapXAxis, snapYAxis);
|
|
|
|
+
|
|
|
|
+ if (!string.IsNullOrEmpty(snapXAxis) || !string.IsNullOrEmpty(snapYAxis))
|
|
|
|
+ {
|
|
|
|
+ document.SnappingHandler.SnappingController.HighlightedPoint = mouseSnap;
|
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ document.SnappingHandler.SnappingController.HighlightedPoint = null;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
public override void OnLeftMouseButtonDown(MouseOnCanvasEventArgs args)
|
|
public override void OnLeftMouseButtonDown(MouseOnCanvasEventArgs args)
|
|
{
|
|
{
|
|
if (startingPath.IsClosed)
|
|
if (startingPath.IsClosed)
|
|
{
|
|
{
|
|
|
|
+ if (NeedsNewLayer(document.SelectedStructureMember, document.AnimationHandler.ActiveFrameTime))
|
|
|
|
+ {
|
|
|
|
+ Guid? created =
|
|
|
|
+ document.Operations.CreateStructureMember(typeof(VectorLayerNode), ActionSource.Automated);
|
|
|
|
+
|
|
|
|
+ if (created is null) return;
|
|
|
|
+
|
|
|
|
+ document.Operations.SetSelectedMember(created.Value);
|
|
|
|
+ }
|
|
|
|
+
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
- startingPath.LineTo((VecF)args.PositionOnCanvas);
|
|
|
|
|
|
+ VecD mouseSnap =
|
|
|
|
+ document.SnappingHandler.SnappingController.GetSnapPoint(args.PositionOnCanvas, out _,
|
|
|
|
+ out _);
|
|
|
|
+
|
|
|
|
+ if (startingPath.Points.Count > 0 && startingPath.Points[0] == (VecF)mouseSnap)
|
|
|
|
+ {
|
|
|
|
+ startingPath.Close();
|
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ startingPath.LineTo((VecF)mouseSnap);
|
|
|
|
+ }
|
|
|
|
+
|
|
PathVectorData vectorData = ConstructShapeData();
|
|
PathVectorData vectorData = ConstructShapeData();
|
|
|
|
|
|
internals.ActionAccumulator.AddActions(new SetShapeGeometry_Action(member.Id, vectorData));
|
|
internals.ActionAccumulator.AddActions(new SetShapeGeometry_Action(member.Id, vectorData));
|
|
|
|
+ mouseDown = true;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ public override void OnLeftMouseButtonUp(VecD pos)
|
|
|
|
+ {
|
|
|
|
+ mouseDown = false;
|
|
|
|
+ }
|
|
|
|
|
|
public override void OnColorChanged(Color color, bool primary)
|
|
public override void OnColorChanged(Color color, bool primary)
|
|
{
|
|
{
|
|
@@ -164,4 +229,22 @@ internal class VectorPathToolExecutor : UpdateableChangeExecutor, IPathExecutorF
|
|
{
|
|
{
|
|
document.PathOverlayHandler.Redo();
|
|
document.PathOverlayHandler.Redo();
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ protected void HighlightSnapping(string? snapX, string? snapY)
|
|
|
|
+ {
|
|
|
|
+ document!.SnappingHandler.SnappingController.HighlightedXAxis = snapX;
|
|
|
|
+ document!.SnappingHandler.SnappingController.HighlightedYAxis = snapY;
|
|
|
|
+ document.SnappingHandler.SnappingController.HighlightedPoint = null;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private bool NeedsNewLayer(IStructureMemberHandler? member, KeyFrameTime frameTime)
|
|
|
|
+ {
|
|
|
|
+ var shapeData = (member as IVectorLayerHandler).GetShapeData(frameTime);
|
|
|
|
+ if (shapeData is null)
|
|
|
|
+ {
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return shapeData is not IReadOnlyPathData pathData || pathData.Path.IsClosed;
|
|
|
|
+ }
|
|
}
|
|
}
|