Example #1
0
        public override void OnPointerPressed(DesignCanvas canvas, PointerRoutedEventArgs args)
        {
            base.OnPointerPressed(canvas, args);

            var ptPoint = args.GetCurrentPoint(canvas);

            if (ptPoint.Properties.IsLeftButtonPressed && canvas.Layer is Data.Layer layer)
            {
                var pos = canvas.FromClientPosition(ptPoint.Position);
                // TODO: should we ignore Anchor/Component etc. here?
                var tappedItem = canvas.HitTest(pos, testSegments: true);
                var selPoint   = GetSelectedPoint(layer);

                _screenOrigin = ptPoint.Position;
                _undoGroup    = layer.CreateUndoGroup();
                if (tappedItem is Data.Point tappedPoint && tappedPoint.Type != Data.PointType.None)
                {
                    var tappedPath = tappedPoint.Parent;

                    if (Is.AtOpenBoundary(tappedPoint))
                    {
                        // If we click a boundary from another boundary, join the paths
                        if (selPoint != null && Is.AtOpenBoundary(selPoint) && AreVisiblyDistinct(canvas, selPoint, tappedPoint))
                        {
                            var selPath   = selPoint.Parent;
                            var selPoints = selPath.Points;
                            if (selPoint.Type == Data.PointType.None)
                            {
                                selPoint.IsSelected = false;
                                selPoints.Pop();
                                var lastOn = selPoints.Last();
                                _stashedOffCurve = (selPoint, lastOn.IsSmooth);
                                lastOn.IsSmooth  = false;
                            }
                            Outline.JoinPaths(selPath, selPoints[0] == selPoint,
                                              tappedPath, tappedPath.Points[0] == tappedPoint);
                            // Drag a control point, except if we're joining a different path (as we're not at boundary
                            // of the resulting path)
                            if (selPath == tappedPath)
                            {
                                _path = selPath;
                            }
                        }
                        // Otherwise reverse the path if needed and we'll drag the boundary point
                        else
                        {
                            if (tappedPoint == tappedPath.Points.First())
                            {
                                tappedPath.Reverse();
                            }

                            _path = tappedPath;
                        }
                    }
                    // If we clicked on an inside point, just break its path open.
                    else
                    {
                        TryRemoveTrailingOffCurve(layer);
                        layer.ClearSelection();

                        Outline.BreakPath(tappedPath, tappedPath.Points.IndexOf(tappedPoint));
                    }

                    if (selPoint != null)
                    {
                        selPoint.IsSelected = false;
                    }
                    tappedPoint.IsSelected = true;
                }
                else if (tappedItem is Data.Segment segment)
                {
                    var result = segment.ProjectPoint(pos.ToVector2());

                    if (result.HasValue)
                    {
                        var t = result.Value.Item2;

                        if (!args.KeyModifiers.HasFlag(VirtualKeyModifiers.Shift))
                        {
                            layer.ClearSelection();
                        }
                        var otherSegment = segment.SplitAt(t);

                        foreach (var point in Enumerable.Concat(segment.Points, otherSegment.OffCurves))
                        {
                            point.X = Outline.RoundToGrid(point.X);
                            point.Y = Outline.RoundToGrid(point.Y);
                        }

                        _point            = segment.OnCurve;
                        _point.IsSelected = true;

                        _undoGroup.Dispose();
                        _undoGroup = layer.CreateUndoGroup();
                    }
                }
                else
                {
                    ObserverList <Data.Point> points;
                    Data.PointType            type;
                    // Add a point to the current path, if any
                    if (selPoint != null && Is.AtOpenBoundary(selPoint))
                    {
                        _path  = selPoint.Parent;
                        points = _path.Points;
                        var lastPoint = points.Last();
                        lastPoint.IsSelected = false;
                        if (lastPoint.Type == Data.PointType.None)
                        {
                            points.Pop();
                            var lastOn = points.Last();
                            _stashedOffCurve = (lastPoint, lastOn.IsSmooth);
                            lastOn.IsSmooth  = false;
                            // For shift origin, always use an onCurve
                            lastPoint = lastOn;
                        }
                        if (args.KeyModifiers.HasFlag(VirtualKeyModifiers.Shift))
                        {
                            pos = ClampToOrigin(pos, new Point(lastPoint.X, lastPoint.Y));
                        }
                        type = Data.PointType.Line;
                    }
                    // Else just create a new one
                    else
                    {
                        _path  = new Data.Path();
                        points = _path.Points;
                        layer.Paths.Add(_path);
                        type = Data.PointType.Move;
                    }

                    // In any case, unselect all points (*click*) and enable new point
                    layer.ClearSelection();
                    var x = Outline.RoundToGrid((float)pos.X);
                    var y = Outline.RoundToGrid((float)pos.Y);
                    points.Add(new Data.Point(x, y, type)
                    {
                        IsSelected = true
                    });
                }

                ((App)Application.Current).InvalidateData();
            }