Commit 55e5e287 by Daniel Dahan

progress commit for MotionCoreAnimationViewContext

parent 7b809595
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
965FE9671FDD99800098BDD0 /* Motion+Start.swift in Sources */ = {isa = PBXBuildFile; fileRef = 965FE9661FDD99800098BDD0 /* Motion+Start.swift */; }; 965FE9671FDD99800098BDD0 /* Motion+Start.swift in Sources */ = {isa = PBXBuildFile; fileRef = 965FE9661FDD99800098BDD0 /* Motion+Start.swift */; };
965FE9691FDDA1F20098BDD0 /* MotionViewOrderStrategy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 965FE9681FDDA1F20098BDD0 /* MotionViewOrderStrategy.swift */; }; 965FE9691FDDA1F20098BDD0 /* MotionViewOrderStrategy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 965FE9681FDDA1F20098BDD0 /* MotionViewOrderStrategy.swift */; };
965FE96B1FDDA4EA0098BDD0 /* BaseMotionPreprocessor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 965FE96A1FDDA4EA0098BDD0 /* BaseMotionPreprocessor.swift */; }; 965FE96B1FDDA4EA0098BDD0 /* BaseMotionPreprocessor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 965FE96A1FDDA4EA0098BDD0 /* BaseMotionPreprocessor.swift */; };
965FE96D1FDDA6400098BDD0 /* BaseMotionAnimator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 965FE96C1FDDA6400098BDD0 /* BaseMotionAnimator.swift */; }; 965FE96D1FDDA6400098BDD0 /* MotionCoreAnimator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 965FE96C1FDDA6400098BDD0 /* MotionCoreAnimator.swift */; };
965FE96F1FDEFA8B0098BDD0 /* Motion+Animate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 965FE96E1FDEFA8B0098BDD0 /* Motion+Animate.swift */; }; 965FE96F1FDEFA8B0098BDD0 /* Motion+Animate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 965FE96E1FDEFA8B0098BDD0 /* Motion+Animate.swift */; };
96E409651F24F7370015A2B5 /* MotionAnimator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96E4093D1F24F7370015A2B5 /* MotionAnimator.swift */; }; 96E409651F24F7370015A2B5 /* MotionAnimator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96E4093D1F24F7370015A2B5 /* MotionAnimator.swift */; };
96E409661F24F7370015A2B5 /* MotionAnimatorViewContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96E4093E1F24F7370015A2B5 /* MotionAnimatorViewContext.swift */; }; 96E409661F24F7370015A2B5 /* MotionAnimatorViewContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96E4093E1F24F7370015A2B5 /* MotionAnimatorViewContext.swift */; };
...@@ -91,7 +91,7 @@ ...@@ -91,7 +91,7 @@
965FE9661FDD99800098BDD0 /* Motion+Start.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Motion+Start.swift"; sourceTree = "<group>"; }; 965FE9661FDD99800098BDD0 /* Motion+Start.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Motion+Start.swift"; sourceTree = "<group>"; };
965FE9681FDDA1F20098BDD0 /* MotionViewOrderStrategy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MotionViewOrderStrategy.swift; sourceTree = "<group>"; }; 965FE9681FDDA1F20098BDD0 /* MotionViewOrderStrategy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MotionViewOrderStrategy.swift; sourceTree = "<group>"; };
965FE96A1FDDA4EA0098BDD0 /* BaseMotionPreprocessor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseMotionPreprocessor.swift; sourceTree = "<group>"; }; 965FE96A1FDDA4EA0098BDD0 /* BaseMotionPreprocessor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseMotionPreprocessor.swift; sourceTree = "<group>"; };
965FE96C1FDDA6400098BDD0 /* BaseMotionAnimator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseMotionAnimator.swift; sourceTree = "<group>"; }; 965FE96C1FDDA6400098BDD0 /* MotionCoreAnimator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MotionCoreAnimator.swift; sourceTree = "<group>"; };
965FE96E1FDEFA8B0098BDD0 /* Motion+Animate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Motion+Animate.swift"; sourceTree = "<group>"; }; 965FE96E1FDEFA8B0098BDD0 /* Motion+Animate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Motion+Animate.swift"; sourceTree = "<group>"; };
96C98DD11E424AB000B22906 /* Motion.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Motion.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 96C98DD11E424AB000B22906 /* Motion.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Motion.framework; sourceTree = BUILT_PRODUCTS_DIR; };
96E4093D1F24F7370015A2B5 /* MotionAnimator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MotionAnimator.swift; sourceTree = "<group>"; }; 96E4093D1F24F7370015A2B5 /* MotionAnimator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MotionAnimator.swift; sourceTree = "<group>"; };
...@@ -183,7 +183,7 @@ ...@@ -183,7 +183,7 @@
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
96E4093D1F24F7370015A2B5 /* MotionAnimator.swift */, 96E4093D1F24F7370015A2B5 /* MotionAnimator.swift */,
965FE96C1FDDA6400098BDD0 /* BaseMotionAnimator.swift */, 965FE96C1FDDA6400098BDD0 /* MotionCoreAnimator.swift */,
96E4093E1F24F7370015A2B5 /* MotionAnimatorViewContext.swift */, 96E4093E1F24F7370015A2B5 /* MotionAnimatorViewContext.swift */,
96E4093F1F24F7370015A2B5 /* MotionCoreAnimationViewContext.swift */, 96E4093F1F24F7370015A2B5 /* MotionCoreAnimationViewContext.swift */,
96E409401F24F7370015A2B5 /* MotionHasInsertOrder.swift */, 96E409401F24F7370015A2B5 /* MotionHasInsertOrder.swift */,
...@@ -332,7 +332,7 @@ ...@@ -332,7 +332,7 @@
965FE9631FDCCE030098BDD0 /* Motion+Complete.swift in Sources */, 965FE9631FDCCE030098BDD0 /* Motion+Complete.swift in Sources */,
96E4097D1F24F7370015A2B5 /* MotionPlugin.swift in Sources */, 96E4097D1F24F7370015A2B5 /* MotionPlugin.swift in Sources */,
96E409681F24F7370015A2B5 /* MotionHasInsertOrder.swift in Sources */, 96E409681F24F7370015A2B5 /* MotionHasInsertOrder.swift in Sources */,
965FE96D1FDDA6400098BDD0 /* BaseMotionAnimator.swift in Sources */, 965FE96D1FDDA6400098BDD0 /* MotionCoreAnimator.swift in Sources */,
96E4096E1F24F7370015A2B5 /* Motion+CG.swift in Sources */, 96E4096E1F24F7370015A2B5 /* Motion+CG.swift in Sources */,
96E409851F24F7370015A2B5 /* MatchPreprocessor.swift in Sources */, 96E409851F24F7370015A2B5 /* MatchPreprocessor.swift in Sources */,
96E409861F24F7370015A2B5 /* MotionPreprocessor.swift in Sources */, 96E409861F24F7370015A2B5 /* MotionPreprocessor.swift in Sources */,
......
...@@ -30,17 +30,20 @@ import UIKit ...@@ -30,17 +30,20 @@ import UIKit
internal class MotionAnimatorViewContext { internal class MotionAnimatorViewContext {
/// An optional reference to a MotionAnimator. /// An optional reference to a MotionAnimator.
var animator: BaseMotionAnimator? var animator: MotionCoreAnimator?
/// A reference to the snapshot UIView. /// A reference to the snapshot UIView.
var snapshot: UIView var snapshot: UIView
/// Animation duration time.
var duration: TimeInterval = 0
/// The animation target state. /// The animation target state.
var targetState: MotionTransitionState var targetState: MotionTransitionState
/// A boolean indicating if the view is appearing.
var isAppearing: Bool
/// Animation duration time.
var duration: TimeInterval = 0
/// The computed current time of the snapshot layer. /// The computed current time of the snapshot layer.
var currentTime: TimeInterval { var currentTime: TimeInterval {
return snapshot.layer.convertTime(CACurrentMediaTime(), from: nil) return snapshot.layer.convertTime(CACurrentMediaTime(), from: nil)
...@@ -56,11 +59,13 @@ internal class MotionAnimatorViewContext { ...@@ -56,11 +59,13 @@ internal class MotionAnimatorViewContext {
- Parameter animator: A MotionAnimator. - Parameter animator: A MotionAnimator.
- Parameter snapshot: A UIView. - Parameter snapshot: A UIView.
- Parameter targetState: A MotionTransitionState. - Parameter targetState: A MotionTransitionState.
- Parameter isAppearing: A Boolean.
*/ */
required init(animator: BaseMotionAnimator, snapshot: UIView, targetState: MotionTransitionState) { required init(animator: MotionCoreAnimator, snapshot: UIView, targetState: MotionTransitionState, isAppearing: Bool) {
self.animator = animator self.animator = animator
self.snapshot = snapshot self.snapshot = snapshot
self.targetState = targetState self.targetState = targetState
self.isAppearing = isAppearing
} }
/// Cleans the context. /// Cleans the context.
...@@ -86,8 +91,11 @@ internal class MotionAnimatorViewContext { ...@@ -86,8 +91,11 @@ internal class MotionAnimatorViewContext {
- Parameter at elapsedTime: A TimeInterval. - Parameter at elapsedTime: A TimeInterval.
- Parameter isReversed: A boolean to reverse the animation - Parameter isReversed: A boolean to reverse the animation
or not. or not.
- Returns: A TimeInterval.
*/ */
func resume(at elapsedTime: TimeInterval, isReversed: Bool) {} func resume(at elapsedTime: TimeInterval, isReversed: Bool) -> TimeInterval {
return 0
}
/** /**
Moves the animation to the given elapsed time. Moves the animation to the given elapsed time.
...@@ -106,5 +114,8 @@ internal class MotionAnimatorViewContext { ...@@ -106,5 +114,8 @@ internal class MotionAnimatorViewContext {
- Parameter isAppearing: A boolean value whether the view - Parameter isAppearing: A boolean value whether the view
is appearing or not. is appearing or not.
*/ */
func startAnimations(isAppearing: Bool) {} @discardableResult
func startAnimations() -> TimeInterval {
return 0
}
} }
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
import UIKit import UIKit
class BaseMotionAnimator: MotionAnimator { class MotionCoreAnimator: MotionAnimator {
weak public var motion: Motion! weak public var motion: Motion!
/// A reference to the MotionContext. /// A reference to the MotionContext.
......
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
import UIKit import UIKit
internal class MotionTransitionAnimator<T: MotionAnimatorViewContext>: BaseMotionAnimator, MotionHasInsertOrder { internal class MotionTransitionAnimator<T: MotionAnimatorViewContext>: MotionCoreAnimator, MotionHasInsertOrder {
/// An index of views to their corresponding animator context. /// An index of views to their corresponding animator context.
var viewToContexts = [UIView: T]() var viewToContexts = [UIView: T]()
...@@ -114,8 +114,10 @@ internal class MotionTransitionAnimator<T: MotionAnimatorViewContext>: BaseMotio ...@@ -114,8 +114,10 @@ internal class MotionTransitionAnimator<T: MotionAnimatorViewContext>: BaseMotio
var duration: TimeInterval = 0 var duration: TimeInterval = 0
for (_, v) in viewToContexts { for (_, v) in viewToContexts {
v.resume(at: elapsedTime, isReversed: isReversed) if v.targetState.duration == nil {
duration = max(duration, v.duration) v.duration = max(v.duration, v.snapshot.optimizedDuration(targetState: v.targetState) + elapsedTime)
}
duration = max(duration, v.resume(at: elapsedTime, isReversed: isReversed))
} }
return duration return duration
...@@ -144,11 +146,11 @@ extension MotionTransitionAnimator { ...@@ -144,11 +146,11 @@ extension MotionTransitionAnimator {
*/ */
fileprivate func animate(view: UIView, isAppearing: Bool) { fileprivate func animate(view: UIView, isAppearing: Bool) {
let s = context.snapshotView(for: view) let s = context.snapshotView(for: view)
let v = T(animator: self, snapshot: s, targetState: context[view]!) let v = T(animator: self, snapshot: s, targetState: context[view]!, isAppearing: isAppearing)
viewToContexts[view] = v viewToContexts[view] = v
v.startAnimations(isAppearing: isAppearing) v.startAnimations()
} }
} }
...@@ -29,6 +29,26 @@ import UIKit ...@@ -29,6 +29,26 @@ import UIKit
extension CALayer: CAAnimationDelegate {} extension CALayer: CAAnimationDelegate {}
internal extension CALayer { internal extension CALayer {
internal static var motionAddedAnimations: [(CALayer, String, CAAnimation)]? = {
let swizzling: (AnyClass, Selector, Selector) -> Void = { forClass, originalSelector, swizzledSelector in
if let originalMethod = class_getInstanceMethod(forClass, originalSelector), let swizzledMethod = class_getInstanceMethod(forClass, swizzledSelector) {
method_exchangeImplementations(originalMethod, swizzledMethod)
}
}
swizzling(CALayer.self, #selector(add(_:forKey:)), #selector(motionAdd(anim:forKey:)))
return nil
}()
@objc
dynamic func motionAdd(anim: CAAnimation, forKey: String?) {
let copiedAnim = anim.copy() as! CAAnimation
copiedAnim.delegate = nil // having delegate resulted some weird animation behavior
CALayer.motionAddedAnimations?.append((self, forKey!, copiedAnim))
motionAdd(anim: anim, forKey: forKey)
}
/// Retrieves all currently running animations for the layer. /// Retrieves all currently running animations for the layer.
var animations: [(String, CAAnimation)] { var animations: [(String, CAAnimation)] {
guard let keys = animationKeys() else { guard let keys = animationKeys() else {
......
...@@ -187,6 +187,16 @@ public func /(left: CGPoint, right: CGPoint) -> CGPoint { ...@@ -187,6 +187,16 @@ public func /(left: CGPoint, right: CGPoint) -> CGPoint {
/** /**
A handler for the (/) operator. A handler for the (/) operator.
- Parameter left: A CGPoint.
- Parameter right: A CGSize.
- Returns: A CGPoint.
*/
public func /(left: CGPoint, right: CGSize) -> CGPoint {
return CGPoint(x: left.x / right.width, y: left.y / right.height)
}
/**
A handler for the (/) operator.
- Parameter left: A CGSize. - Parameter left: A CGSize.
- Parameter right: A CGSize. - Parameter right: A CGSize.
- Returns: A CGSize. - Returns: A CGSize.
......
...@@ -284,6 +284,17 @@ internal extension UIView { ...@@ -284,6 +284,17 @@ internal extension UIView {
} }
/** /**
Calculates the optimized duration for a view.
- Parameter targetState: A MotionTransitionState.
- Returns: A TimeInterval.
*/
func optimizedDuration(targetState: MotionTransitionState) -> TimeInterval {
return optimizedDuration(position: targetState.position,
size: targetState.size,
transform: targetState.transform)
}
/**
Takes a snapshot of a view usinag the UI graphics context. Takes a snapshot of a view usinag the UI graphics context.
- Returns: A UIView with an embedded UIImageView. - Returns: A UIView with an embedded UIImageView.
*/ */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment