diff --git a/Source/animation/types/animation_generators/ShapeAnimationGenerator.swift b/Source/animation/types/animation_generators/ShapeAnimationGenerator.swift index b64023ca..c72183aa 100644 --- a/Source/animation/types/animation_generators/ShapeAnimationGenerator.swift +++ b/Source/animation/types/animation_generators/ShapeAnimationGenerator.swift @@ -26,7 +26,9 @@ func addShapeAnimation(_ animation: BasicAnimation, _ context: AnimationContext, let transactionsDisabled = CATransaction.disableActions() CATransaction.setDisableActions(true) - let fromShape = shapeAnimation.getVFunc()(0.0) + guard let fromShape = SceneUtils.copyNode(shapeAnimation.getVFunc()(0.0)) as? Shape else { + return + } let toShape = shapeAnimation.getVFunc()(animation.autoreverses ? 0.5 : 1.0) let duration = animation.autoreverses ? animation.getDuration() / 2.0 : animation.getDuration() @@ -54,16 +56,28 @@ func addShapeAnimation(_ animation: BasicAnimation, _ context: AnimationContext, animation.progress = animation.manualStop ? 0.0 : 1.0 if !animation.autoreverses && finished { - shape.form = toShape.form - shape.stroke = toShape.stroke - shape.fill = toShape.fill + if fromShape.form != toShape.form { + shape.form = toShape.form + } + if fromShape.stroke != toShape.stroke { + shape.stroke = toShape.stroke + } + if fromShape.fill != toShape.fill { + shape.fill = toShape.fill + } } if !finished { animation.progress = 0.0 - shape.form = fromShape.form - shape.stroke = fromShape.stroke - shape.fill = fromShape.fill + if fromShape.form != toShape.form { + shape.form = toShape.form + } + if fromShape.stroke != toShape.stroke { + shape.stroke = toShape.stroke + } + if fromShape.fill != toShape.fill { + shape.fill = toShape.fill + } } renderer.freeLayer() diff --git a/Source/model/draw/Fill.swift b/Source/model/draw/Fill.swift index ca842b66..3d94ecbd 100644 --- a/Source/model/draw/Fill.swift +++ b/Source/model/draw/Fill.swift @@ -4,7 +4,7 @@ open class Fill: Equatable { } func equals(other: T) -> Bool where T: Fill { - fatalError("Equals can't be realised for Fill") + fatalError("Equals can't be implemented for Fill") } } diff --git a/Source/model/draw/Stroke.swift b/Source/model/draw/Stroke.swift index c273319f..d2eb6878 100644 --- a/Source/model/draw/Stroke.swift +++ b/Source/model/draw/Stroke.swift @@ -1,4 +1,4 @@ -open class Stroke { +open class Stroke: Equatable { public let fill: Fill public let width: Double @@ -18,3 +18,13 @@ open class Stroke { self.offset = offset } } + +public func == (lhs: T, rhs: T) -> Bool where T: Stroke { + return lhs.fill == rhs.fill + && lhs.width == rhs.width + && lhs.cap == rhs.cap + && lhs.join == rhs.join + && lhs.miterLimit == rhs.miterLimit + && lhs.dashes == rhs.dashes + && lhs.offset == rhs.offset +} diff --git a/Source/model/geom2d/Arc.swift b/Source/model/geom2d/Arc.swift index c94035c9..48f303dd 100644 --- a/Source/model/geom2d/Arc.swift +++ b/Source/model/geom2d/Arc.swift @@ -45,4 +45,13 @@ open class Arc: Locus { return PathBuilder(segment: PathSegment(type: .M, data: [x1, y1])).A(rx, ry, 0.0, largeArcFlag, sweepFlag, x2, y2).build() } + + override func equals(other: T) -> Bool where T: Locus { + guard let other = other as? Arc else { + return false + } + return ellipse == other.ellipse + && shift == other.shift + && extent == other.extent + } } diff --git a/Source/model/geom2d/Circle.swift b/Source/model/geom2d/Circle.swift index 90b6e154..5814a59f 100644 --- a/Source/model/geom2d/Circle.swift +++ b/Source/model/geom2d/Circle.swift @@ -25,4 +25,13 @@ open class Circle: Locus { override open func toPath() -> Path { return MoveTo(x: cx, y: cy).m(-r, 0).a(r, r, 0.0, true, false, r * 2.0, 0.0).a(r, r, 0.0, true, false, -(r * 2.0), 0.0).build() } + + override func equals(other: T) -> Bool where T: Locus { + guard let other = other as? Circle else { + return false + } + return cx == other.cx + && cy == other.cy + && r == other.r + } } diff --git a/Source/model/geom2d/Ellipse.swift b/Source/model/geom2d/Ellipse.swift index b8a37f87..d9588a85 100644 --- a/Source/model/geom2d/Ellipse.swift +++ b/Source/model/geom2d/Ellipse.swift @@ -23,4 +23,14 @@ open class Ellipse: Locus { open func arc(shift: Double, extent: Double) -> Arc { return Arc(ellipse: self, shift: shift, extent: extent) } + + override func equals(other: T) -> Bool where T: Locus { + guard let other = other as? Ellipse else { + return false + } + return cx == other.cx + && cy == other.cy + && rx == other.rx + && ry == other.ry + } } diff --git a/Source/model/geom2d/Line.swift b/Source/model/geom2d/Line.swift index e37c2d29..75ab143e 100644 --- a/Source/model/geom2d/Line.swift +++ b/Source/model/geom2d/Line.swift @@ -26,4 +26,14 @@ open class Line: Locus { override open func toPath() -> Path { return MoveTo(x: x1, y: y1).lineTo(x: x2, y: y2).build() } + + override func equals(other: T) -> Bool where T: Locus { + guard let other = other as? Line else { + return false + } + return x1 == other.x1 + && y1 == other.y1 + && x2 == other.x2 + && y2 == other.y2 + } } diff --git a/Source/model/geom2d/Locus.swift b/Source/model/geom2d/Locus.swift index 06e3747e..e6f9dc56 100644 --- a/Source/model/geom2d/Locus.swift +++ b/Source/model/geom2d/Locus.swift @@ -1,4 +1,4 @@ -open class Locus { +open class Locus: Equatable { public init() { } @@ -38,4 +38,13 @@ open class Locus { open func toPath() -> Path { fatalError("Unsupported locus: \(self)") } + + func equals(other: T) -> Bool where T: Locus { + fatalError("Equals can't be implemented for Locus") + } +} + +public func == (lhs: T, rhs: T) -> Bool where T: Locus { + return type(of: lhs) == type(of: rhs) + && lhs.equals(other: rhs) } diff --git a/Source/model/geom2d/Path.swift b/Source/model/geom2d/Path.swift index 96b17dfb..be171b5a 100644 --- a/Source/model/geom2d/Path.swift +++ b/Source/model/geom2d/Path.swift @@ -19,4 +19,12 @@ open class Path: Locus { override open func toPath() -> Path { return self } + + override func equals(other: T) -> Bool where T: Locus { + guard let other = other as? Path else { + return false + } + return segments == other.segments + && fillRule == other.fillRule + } } diff --git a/Source/model/geom2d/PathSegment.swift b/Source/model/geom2d/PathSegment.swift index 0739d835..659c026d 100644 --- a/Source/model/geom2d/PathSegment.swift +++ b/Source/model/geom2d/PathSegment.swift @@ -1,6 +1,6 @@ import Foundation -open class PathSegment { +open class PathSegment: Equatable { public let type: PathSegmentType public let data: [Double] @@ -18,4 +18,9 @@ open class PathSegment { return false } } + + public static func == (lhs: PathSegment, rhs: PathSegment) -> Bool { + return lhs.type == rhs.type + && lhs.data == rhs.data + } } diff --git a/Source/model/geom2d/Point.swift b/Source/model/geom2d/Point.swift index 234ae075..e94412b7 100644 --- a/Source/model/geom2d/Point.swift +++ b/Source/model/geom2d/Point.swift @@ -38,13 +38,17 @@ open class Point: Locus { override open func toPath() -> Path { return MoveTo(x: x, y: y).lineTo(x: x, y: y).build() } + + override func equals(other: T) -> Bool where T: Locus { + guard let other = other as? Point else { + return false + } + return x == other.y + && y == other.y + } } -extension Point: Equatable { - public static func == (lhs: Point, rhs: Point) -> Bool { - return lhs.x == rhs.x - && lhs.y == rhs.y - } +extension Point { public static func - (lhs: Point, rhs: Point) -> Size { return Size(w: lhs.x - rhs.x, h: lhs.y - rhs.y) diff --git a/Source/model/geom2d/Polygon.swift b/Source/model/geom2d/Polygon.swift index f47fdf5c..bb362bc8 100644 --- a/Source/model/geom2d/Polygon.swift +++ b/Source/model/geom2d/Polygon.swift @@ -60,4 +60,11 @@ open class Polygon: Locus { } return pb.close().build() } + + override func equals(other: T) -> Bool where T: Locus { + guard let other = other as? Polygon else { + return false + } + return points == other.points + } } diff --git a/Source/model/geom2d/Polyline.swift b/Source/model/geom2d/Polyline.swift index 83de29ce..f1012245 100644 --- a/Source/model/geom2d/Polyline.swift +++ b/Source/model/geom2d/Polyline.swift @@ -60,4 +60,11 @@ open class Polyline: Locus { } return pb.build() } + + override func equals(other: T) -> Bool where T: Locus { + guard let other = other as? Polyline else { + return false + } + return points == other.points + } } diff --git a/Source/model/geom2d/Rect.swift b/Source/model/geom2d/Rect.swift index 6f31771e..d44e18c7 100644 --- a/Source/model/geom2d/Rect.swift +++ b/Source/model/geom2d/Rect.swift @@ -73,13 +73,14 @@ open class Rect: Locus { override open func toPath() -> Path { return MoveTo(x: x, y: y).lineTo(x: x, y: y + h).lineTo(x: x + w, y: y + h).lineTo(x: x + w, y: y).close().build() } -} -extension Rect { - public static func == (lhs: Rect, rhs: Rect) -> Bool { - return lhs.x == rhs.x - && lhs.y == rhs.y - && lhs.w == rhs.w - && lhs.h == rhs.h + override func equals(other: T) -> Bool where T: Locus { + guard let other = other as? Rect else { + return false + } + return x == other.y + && y == other.y + && w == other.w + && h == other.h } } diff --git a/Source/model/geom2d/RoundRect.swift b/Source/model/geom2d/RoundRect.swift index 6762b314..9bb8e52f 100644 --- a/Source/model/geom2d/RoundRect.swift +++ b/Source/model/geom2d/RoundRect.swift @@ -13,4 +13,13 @@ open class RoundRect: Locus { override open func bounds() -> Rect { return rect } + + override func equals(other: T) -> Bool where T: Locus { + guard let other = other as? RoundRect else { + return false + } + return rect == other.rect + && rx == other.rx + && ry == other.ry + } } diff --git a/Source/model/geom2d/TransformedLocus.swift b/Source/model/geom2d/TransformedLocus.swift index 45af401b..9b2f6720 100644 --- a/Source/model/geom2d/TransformedLocus.swift +++ b/Source/model/geom2d/TransformedLocus.swift @@ -18,4 +18,12 @@ open class TransformedLocus: Locus { open override func bounds() -> Rect { return locus.bounds().applying(transform) } + + override func equals(other: T) -> Bool where T: Locus { + guard let other = other as? TransformedLocus else { + return false + } + return locus == other.locus + && transform == other.transform + } }