Commit 3bc0ad78 by Daniel Dahan

updating can animate checks

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