Commit 3bc0ad78 by Daniel Dahan

updating can animate checks

parent fdf4c631
...@@ -207,11 +207,11 @@ ...@@ -207,11 +207,11 @@
96E4095D1F24F7370015A2B5 /* Preprocessors */ = { 96E4095D1F24F7370015A2B5 /* Preprocessors */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
96E409621F24F7370015A2B5 /* MotionPreprocessor.swift */,
965FE96A1FDDA4EA0098BDD0 /* MotionCorePreprocessor.swift */, 965FE96A1FDDA4EA0098BDD0 /* MotionCorePreprocessor.swift */,
96E4095E1F24F7370015A2B5 /* CascadePreprocessor.swift */, 96E4095E1F24F7370015A2B5 /* CascadePreprocessor.swift */,
96E409601F24F7370015A2B5 /* IgnoreSubviewModifiersPreprocessor.swift */, 96E409601F24F7370015A2B5 /* IgnoreSubviewModifiersPreprocessor.swift */,
96E409611F24F7370015A2B5 /* MatchPreprocessor.swift */, 96E409611F24F7370015A2B5 /* MatchPreprocessor.swift */,
96E409621F24F7370015A2B5 /* MotionPreprocessor.swift */,
96E409631F24F7370015A2B5 /* SourcePreprocessor.swift */, 96E409631F24F7370015A2B5 /* SourcePreprocessor.swift */,
96E409641F24F7370015A2B5 /* TransitionPreprocessor.swift */, 96E409641F24F7370015A2B5 /* TransitionPreprocessor.swift */,
965FE9761FE0976F0098BDD0 /* ConditionalPreprocessor.swift */, 965FE9761FE0976F0098BDD0 /* ConditionalPreprocessor.swift */,
......
...@@ -123,6 +123,7 @@ internal class MotionTransitionAnimator<T: MotionAnimatorViewContext>: MotionCor ...@@ -123,6 +123,7 @@ internal class MotionTransitionAnimator<T: MotionAnimatorViewContext>: MotionCor
if nil == v.targetState.duration { if nil == v.targetState.duration {
v.duration = max(v.duration, v.snapshot.optimizedDuration(targetState: v.targetState) + elapsedTime) v.duration = max(v.duration, v.snapshot.optimizedDuration(targetState: v.targetState) + elapsedTime)
} }
duration = max(duration, v.resume(at: elapsedTime, isReversed: isReversed)) duration = max(duration, v.resume(at: elapsedTime, isReversed: isReversed))
} }
......
...@@ -126,19 +126,19 @@ extension UIViewController { ...@@ -126,19 +126,19 @@ extension UIViewController {
get { get {
return transitioningDelegate is Motion return transitioningDelegate is Motion
} }
set(value) { set(value) {
guard value != isMotionEnabled else { guard value != isMotionEnabled else {
return return
} }
if value { if value {
transitioningDelegate = Motion.shared transitioningDelegate = Motion.shared
if let v = self as? UINavigationController { if let v = self as? UINavigationController {
previousNavigationDelegate = v.delegate previousNavigationDelegate = v.delegate
v.delegate = Motion.shared v.delegate = Motion.shared
} }
if let v = self as? UITabBarController { if let v = self as? UITabBarController {
previousTabBarDelegate = v.delegate previousTabBarDelegate = v.delegate
v.delegate = Motion.shared v.delegate = Motion.shared
...@@ -146,11 +146,11 @@ extension UIViewController { ...@@ -146,11 +146,11 @@ extension UIViewController {
} else { } else {
transitioningDelegate = nil transitioningDelegate = nil
if let v = self as? UINavigationController, v.delegate is Motion { if let v = self as? UINavigationController, v.delegate is Motion {
v.delegate = previousNavigationDelegate v.delegate = previousNavigationDelegate
} }
if let v = self as? UITabBarController, v.delegate is Motion { if let v = self as? UITabBarController, v.delegate is Motion {
v.delegate = previousTabBarDelegate v.delegate = previousTabBarDelegate
} }
......
...@@ -41,38 +41,33 @@ extension Motion { ...@@ -41,38 +41,33 @@ extension Motion {
context.unhide(view: tv) context.unhide(view: tv)
} }
for (fv, tv) in transitionPairs { for v in animatingFromViews {
for v in fv { context.hide(view: v)
context.hide(view: v) }
}
for v in animatingToViews {
for v in tv { context.hide(view: v)
context.hide(view: v)
}
} }
var t: TimeInterval = 0 var t: TimeInterval = 0
var animatorWantsInteractive = false var animatorWantsInteractive = false
if context.insertToViewFirst { if context.insertToViewFirst {
for (fv, tv) in transitionPairs { for v in animatingToViews {
for v in tv { context.snapshotView(for: v)
context.snapshotView(for: v)
}
for v in fv {
context.snapshotView(for: v)
}
} }
for v in animatingFromViews {
context.snapshotView(for: v)
}
} else { } else {
for (fv, tv) in transitionPairs { for v in animatingFromViews {
for v in fv { context.snapshotView(for: v)
context.snapshotView(for: v) }
}
for v in animatingToViews {
for v in tv { context.snapshotView(for: v)
context.snapshotView(for: v)
}
} }
} }
...@@ -81,18 +76,27 @@ extension Motion { ...@@ -81,18 +76,27 @@ extension Motion {
// Therefore we kick off the layout beforehand // Therefore we kick off the layout beforehand
fromView?.layoutIfNeeded() fromView?.layoutIfNeeded()
for (i, a) in animators.enumerated() { for animator in animators {
let d = a.animate(fromViews: transitionPairs[i].0, toViews: transitionPairs[i].1) let duration = animator.animate(fromViews: animatingFromViews.filter {
print(animator.canAnimate(view: $0, isAppearing: false))
return animator.canAnimate(view: $0, isAppearing: false)
}, toViews: animatingToViews.filter {
print(animator.canAnimate(view: $0, isAppearing: false))
return animator.canAnimate(view: $0, isAppearing: true)
})
if .infinity == d { print("T", t, "DURATION", duration)
if .infinity == duration {
animatorWantsInteractive = true animatorWantsInteractive = true
} else { } else {
t = max(t, d) t = max(t, duration)
} }
} }
totalDuration = t totalDuration = t
print("T", t)
if let forceFinishing = forceFinishing { if let forceFinishing = forceFinishing {
complete(isFinishing: forceFinishing) complete(isFinishing: forceFinishing)
} else if let startingProgress = startingProgress { } else if let startingProgress = startingProgress {
......
...@@ -72,7 +72,8 @@ extension Motion { ...@@ -72,7 +72,8 @@ extension Motion {
isNavigationController = false isNavigationController = false
isTabBarController = false isTabBarController = false
forceNonInteractive = false forceNonInteractive = false
transitionPairs.removeAll() animatingToViews.removeAll()
animatingFromViews.removeAll()
transitionObservers = nil transitionObservers = nil
transitionContainer = nil transitionContainer = nil
completionCallback = nil completionCallback = nil
......
...@@ -37,7 +37,7 @@ extension Motion { ...@@ -37,7 +37,7 @@ extension Motion {
state = .starting state = .starting
prepareToView() prepareViewFrame()
prepareViewControllers() prepareViewControllers()
prepareSnapshotView() prepareSnapshotView()
preparePreprocessors() preparePreprocessors()
...@@ -47,7 +47,8 @@ extension Motion { ...@@ -47,7 +47,8 @@ extension Motion {
prepareContainer() prepareContainer()
prepareContext() prepareContext()
prepareViewHierarchy() prepareViewHierarchy()
prepareTransitionPairs() prepareAnimatingViews()
prepareToView()
processPreprocessors() processPreprocessors()
processAnimation() processAnimation()
...@@ -55,8 +56,8 @@ extension Motion { ...@@ -55,8 +56,8 @@ extension Motion {
} }
fileprivate extension Motion { fileprivate extension Motion {
/// Prepares the toView instance. /// Prepares the views frames.
func prepareToView() { func prepareViewFrame() {
guard let fv = fromView else { guard let fv = fromView else {
return return
} }
...@@ -87,7 +88,7 @@ fileprivate extension Motion { ...@@ -87,7 +88,7 @@ fileprivate extension Motion {
} }
fullScreenSnapshot = v.window?.snapshotView(afterScreenUpdates: false) ?? fromView?.snapshotView(afterScreenUpdates: false) fullScreenSnapshot = v.window?.snapshotView(afterScreenUpdates: false) ?? fromView?.snapshotView(afterScreenUpdates: false)
(v.window ?? transitionContainer)?.addSubview(fullScreenSnapshot) (v.window ?? v)?.addSubview(fullScreenSnapshot)
if let v = fromViewController?.motionStoredSnapshot { if let v = fromViewController?.motionStoredSnapshot {
v.removeFromSuperview() v.removeFromSuperview()
...@@ -212,24 +213,28 @@ fileprivate extension Motion { ...@@ -212,24 +213,28 @@ fileprivate extension Motion {
} }
/// Prepares the transition fromView & toView pairs. /// Prepares the transition fromView & toView pairs.
@objc func prepareAnimatingViews() {
func prepareTransitionPairs() { animatingFromViews = context.fromViews.filter { (view) -> Bool in
guard isTransitioning else { for animator in animators {
return if animator.canAnimate(view: view, isAppearing: false) {
return true
}
}
return false
} }
for a in animators { animatingToViews = context.toViews.filter { (view) -> Bool in
let fv = context.fromViews.filter { (view) -> Bool in for animator in animators {
return a.canAnimate(view: view, isAppearing: false) if animator.canAnimate(view: view, isAppearing: true) {
} return true
}
let tv = context.toViews.filter {
return a.canAnimate(view: $0, isAppearing: true)
} }
return false
transitionPairs.append((fv, tv))
} }
}
/// Prepares the to view.
func prepareToView() {
guard let tv = toView else { guard let tv = toView else {
return return
} }
...@@ -258,6 +263,7 @@ fileprivate extension Motion { ...@@ -258,6 +263,7 @@ fileprivate extension Motion {
Motion.async { [weak self] in Motion.async { [weak self] in
self?.animate() self?.animate()
} }
} else { } else {
animate() animate()
} }
......
...@@ -264,7 +264,8 @@ public class Motion: NSObject, MotionProgressRunnerDelegate { ...@@ -264,7 +264,8 @@ public class Motion: NSObject, MotionProgressRunnerDelegate {
internal lazy var plugins = [MotionPlugin]() internal lazy var plugins = [MotionPlugin]()
/// The matching fromViews to toViews based on the motionIdentifier value. /// The matching fromViews to toViews based on the motionIdentifier value.
internal lazy var transitionPairs = [(fromViews: [UIView], toViews: [UIView])]() internal var animatingFromViews = [UIView]()
internal var animatingToViews = [UIView]()
/// Default animation type. /// Default animation type.
internal var defaultAnimation = MotionTransitionType.auto internal var defaultAnimation = MotionTransitionType.auto
...@@ -363,7 +364,13 @@ public extension Motion { ...@@ -363,7 +364,13 @@ public extension Motion {
- Parameter elapsedTime t: the current progress, must be between -1...1. - Parameter elapsedTime t: the current progress, must be between -1...1.
*/ */
public func update(elapsedTime: TimeInterval) { public func update(elapsedTime: TimeInterval) {
self.elapsedTime = elapsedTime guard .animating == state else {
startingProgress = elapsedTime
return
}
progressRunner.stop()
self.elapsedTime = Double(CGFloat(elapsedTime).clamp(0, 1))
} }
/** /**
...@@ -818,7 +825,7 @@ extension Motion { ...@@ -818,7 +825,7 @@ extension Motion {
- Parameter execute: A block that is executed asynchronously on the main thread. - Parameter execute: A block that is executed asynchronously on the main thread.
*/ */
public class func async(_ execute: @escaping () -> Void) { public class func async(_ execute: @escaping () -> Void) {
Motion.delay(0, execute: execute) DispatchQueue.main.async(execute: execute)
} }
/** /**
...@@ -833,7 +840,7 @@ extension Motion { ...@@ -833,7 +840,7 @@ extension Motion {
let delayed: MotionCancelBlock = { let delayed: MotionCancelBlock = {
if !$0 { if !$0 {
DispatchQueue.main.async(execute: execute) async(execute)
} }
cancelable = nil cancelable = nil
......
...@@ -33,29 +33,41 @@ public enum CascadeDirection { ...@@ -33,29 +33,41 @@ public enum CascadeDirection {
case bottomToTop case bottomToTop
case leftToRight case leftToRight
case rightToLeft case rightToLeft
case radial(center:CGPoint) case radial(center: CGPoint)
case inverseRadial(center:CGPoint) case inverseRadial(center: CGPoint)
/// Based on the cascade direction a comparator is set. /// Based on the cascade direction a comparator is set.
var comparator: (UIView, UIView) -> Bool { var comparator: (UIView, UIView) -> Bool {
switch self { switch self {
case .topToBottom: case .topToBottom:
return { return $0.frame.minY < $1.frame.minY } return {
return $0.frame.minY < $1.frame.minY
}
case .bottomToTop: case .bottomToTop:
return { return $0.frame.maxY == $1.frame.maxY ? $0.frame.maxX > $1.frame.maxX : $0.frame.maxY > $1.frame.maxY } return {
return $0.frame.maxY == $1.frame.maxY ? $0.frame.maxX > $1.frame.maxX : $0.frame.maxY > $1.frame.maxY
}
case .leftToRight: case .leftToRight:
return { return $0.frame.minX < $1.frame.minX } return {
return $0.frame.minX < $1.frame.minX
}
case .rightToLeft: case .rightToLeft:
return { return $0.frame.maxX > $1.frame.maxX } return {
return $0.frame.maxX > $1.frame.maxX
}
case .radial(let center): case .radial(let center):
return { return $0.center.distance(center) < $1.center.distance(center) } return {
return $0.center.distance(center) < $1.center.distance(center)
}
case .inverseRadial(let center): case .inverseRadial(let center):
return { return $0.center.distance(center) > $1.center.distance(center) } return {
return $0.center.distance(center) > $1.center.distance(center)
}
} }
} }
} }
...@@ -76,24 +88,26 @@ class CascadePreprocessor: MotionCorePreprocessor { ...@@ -76,24 +88,26 @@ class CascadePreprocessor: MotionCorePreprocessor {
- Parameter views: An Array of UIViews. - Parameter views: An Array of UIViews.
*/ */
func process(views: [UIView]) { func process(views: [UIView]) {
for v in views { for view in views {
guard let (deltaTime, direction, delayMatchedViews) = context[v]?.cascade else { guard let (deltaTime, direction, delayMatchedViews) = context[view]?.cascade else { continue }
continue
var parentView = view
if view is UITableView, let wrapperView = view.subviews.get(0) {
parentView = wrapperView
} }
let parentView = v is UITableView ? v.subviews.get(0) ?? v : v
let sortedSubviews = parentView.subviews.sorted(by: direction.comparator) let sortedSubviews = parentView.subviews.sorted(by: direction.comparator)
let initialDelay = context[v]!.delay let initialDelay = context[view]!.delay
let finalDelay = TimeInterval(sortedSubviews.count) * deltaTime + initialDelay let finalDelay = TimeInterval(sortedSubviews.count) * deltaTime + initialDelay
for (i, subview) in sortedSubviews.enumerated() { for (i, subview) in sortedSubviews.enumerated() {
let delay = TimeInterval(i) * deltaTime + initialDelay let delay = TimeInterval(i) * deltaTime + initialDelay
func applyDelay(view: UIView) { func applyDelay(view: UIView) {
if context.pairedView(for: view) == nil { if context.pairedView(for: view) == nil {
context[view]?.delay = delay context[view]?.delay = delay
} else if delayMatchedViews, let paired = context.pairedView(for: view) { } else if delayMatchedViews, let paired = context.pairedView(for: view) {
context[view]?.delay = finalDelay context[view]?.delay = finalDelay
context[paired]?.delay = finalDelay context[paired]?.delay = finalDelay
...@@ -103,7 +117,7 @@ class CascadePreprocessor: MotionCorePreprocessor { ...@@ -103,7 +117,7 @@ class CascadePreprocessor: MotionCorePreprocessor {
applyDelay(view: subview) applyDelay(view: subview)
} }
} }
applyDelay(view: subview) applyDelay(view: subview)
} }
} }
......
...@@ -51,7 +51,9 @@ class SourcePreprocessor: MotionCorePreprocessor { ...@@ -51,7 +51,9 @@ class SourcePreprocessor: MotionCorePreprocessor {
prepare(view: tv, for: fv) prepare(view: tv, for: fv)
} }
} }
}
fileprivate extension SourcePreprocessor {
/** /**
Prepares a given view for a target view. Prepares a given view for a target view.
- Parameter view: A UIView. - Parameter view: A UIView.
...@@ -112,7 +114,7 @@ class SourcePreprocessor: MotionCorePreprocessor { ...@@ -112,7 +114,7 @@ class SourcePreprocessor: MotionCorePreprocessor {
if view.layer.contentsScale != targetView.layer.contentsScale { if view.layer.contentsScale != targetView.layer.contentsScale {
state.contentsScale = targetView.layer.contentsScale state.contentsScale = targetView.layer.contentsScale
} }
context[view] = state context[view] = state
} }
} }
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