Skip to content

Commit 59ad972

Browse files
authored
Animation and Haptics: add various ViewController animation protocols
This fleshes out the protocols required for the `ViewController` class interfaces.
1 parent d057368 commit 59ad972

10 files changed

+427
-0
lines changed
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// Copyright © 2021 Saleem Abdulrasool <[email protected]>
2+
// SPDX-License-Identifier: BSD-3-Clause
3+
4+
/// The timing information for animations in the form of a cubic Bézier curve.
5+
public class CubicTimingParameters {
6+
// MARK - Initializing a Cubic Timing Parameters Object
7+
8+
/// Initializes the object with the system’s default timing curve.
9+
public init() {
10+
self.animationCurve = .linear
11+
self.controlPoint1 = .zero
12+
self.controlPoint2 = Point(x: 1, y: 1)
13+
}
14+
15+
/// Initializes the object with the specified builtin timing curve.
16+
public init(animationCurve curve: View.AnimationCurve) {
17+
self.animationCurve = curve
18+
self.controlPoint1 = .zero
19+
self.controlPoint2 = .zero
20+
}
21+
22+
/// Initializes the object with the specified control points for a cubic
23+
/// Bézier curve.
24+
public init(controlPoint1 point1: Point, controlPoint2 point2: Point) {
25+
self.animationCurve = .linear
26+
self.controlPoint1 = point1
27+
self.controlPoint2 = point2
28+
}
29+
30+
// MARK - Getting the Timing Parameters
31+
32+
/// The standard builtin animation curve to use for timing.
33+
public private(set) var animationCurve: View.AnimationCurve
34+
35+
/// The first control point for the cubic Bézier curve.
36+
public private(set) var controlPoint1: Point
37+
38+
/// The second control point of the cubic Bézier curve.
39+
public private(set) var controlPoint2: Point
40+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// Copyright © 2021 Saleem Abdulrasool <[email protected]>
2+
// SPDX-License-Identifier: BSD-3-Clause
3+
4+
/// The timing information for animations that mimics the behavior of a spring.
5+
public class SpringTimingParameters {
6+
// MARK - Initializing a Spring Timing Parameters Object
7+
8+
/// Creates a default timing parameters object.
9+
///
10+
/// This method sets the initial velocity of any animated properties to 0.0
11+
/// and sets the damping ratio to 4.56.
12+
public init() {
13+
self.initialVelocity = .zero
14+
}
15+
16+
/// Creates a timing parameters object with the specified damping ratio.
17+
///
18+
/// This method sets the initial velocity of any animated properties to 0.0.
19+
public convenience init(dampingRatio ratio: Double) {
20+
self.init(dampingRatio: ratio, initialVelocity: .zero)
21+
}
22+
23+
/// Creates a timing parameters object with the specified damping ratio and
24+
/// initial velocity.
25+
public init(dampingRatio ratio: Double, initialVelocity velocity: Vector) {
26+
self.initialVelocity = velocity
27+
}
28+
29+
/// Creates a timing parameters object with the specified spring stiffness,
30+
/// mass, damping coefficient, and initial velocity.
31+
///
32+
/// The damping ratio for the spring is computed from the formula:
33+
/// `damping / (2 * sqrt (stiffness * mass))`.
34+
public init(mass: Double, stiffness: Double, damping: Double,
35+
initialVelocity velocity: Vector) {
36+
self.initialVelocity = velocity
37+
}
38+
39+
// MARK - Getting the Initial Velocity
40+
41+
/// The target property’s rate of change at the start of a spring animation,
42+
/// enabling a smooth transition into the animation.
43+
public private(set) var initialVelocity: Vector
44+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// Copyright © 2021 Saleem Abdulrasool <[email protected]>
2+
// SPDX-License-Identifier: BSD-3-Clause
3+
4+
/// Constants indicating the type of timing information to use.
5+
public enum TimingCurveType: Int {
6+
/// Use the built-in timing curves. Specify this value when you want to use
7+
/// one of the constants in the `View.AnimationCurve` type. Specify the
8+
/// desired curve using the `cubicTimingParameters` property.
9+
case builtin
10+
11+
/// Use a custom cubic Bézier curve. Specify the curve information using the
12+
/// `cubicTimingParameters` property.
13+
case cubic
14+
15+
/// Use a custom spring animation. Specify the desired curve using the
16+
/// `springTimingParameters` property.
17+
case spring
18+
19+
/// Use a combination of timing parameters. This type of curve starts with the
20+
/// curve defined by the `cubicTimingParameters` property and modifies it
21+
/// using the spring information in the `springTimingParameters` property.
22+
case composed
23+
}
24+
25+
/// An interface for providing the timing information needed to perform
26+
/// animations.
27+
public protocol TimingCurveProvider {
28+
// MARK - Getting the Timing Information
29+
30+
/// The type of timing information to use.
31+
var timingCurveType: TimingCurveType { get }
32+
33+
/// The cubic timing parameters to use.
34+
var cubicTimingParameters: CubicTimingParameters? { get }
35+
36+
/// The spring-based timing parameters to use.
37+
var springTimingParameters: SpringTimingParameters? { get }
38+
}

Sources/SwiftWin32/Animation and Haptics/Property-Based Animations/ViewAnimating.swift

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
// Copyright © 2021 Saleem Abdulrasool <[email protected]>
22
// SPDX-License-Identifier: BSD-3-Clause
33

4+
import struct Foundation.TimeInterval
5+
46
/// Constants indicating positions within the animation.
57
public enum ViewAnimatingPosition: Int {
68
/// The end point of the animation. Use this constant when you want the final
@@ -17,3 +19,57 @@ public enum ViewAnimatingPosition: Int {
1719
/// value set by an animator object.
1820
case current
1921
}
22+
23+
/// Constants indicating the current state of the animation.
24+
public enum ViewAnimatingState: Int {
25+
/// The animations have not yet started executing. This is the initial state
26+
/// of the animator object.
27+
case inactive
28+
29+
/// The animator object is active and animations are either running or paused.
30+
/// An animator moves to this state after the first call to `startAnimation()`
31+
/// or `pauseAnimation()`. It stays in the active state until the animations
32+
/// finish naturally or until you call the `stopAnimation(_:)` method.
33+
case active
34+
35+
/// The animation is stopped. Putting an animation into this state ends the
36+
/// animation and leaves any animatable properties at their current values,
37+
/// instead of updating them to their intended final values. An animation
38+
/// cannot be started while in this state.
39+
case stopped
40+
}
41+
42+
/// An interface for implementing custom animator objects.
43+
public protocol ViewAnimating {
44+
// MARK - Starting and Stopping the Animations
45+
46+
/// Starts the animation from its current position.
47+
func startAnimation()
48+
49+
/// Starts the animation after the specified delay.
50+
func startAnimation(afterDelay delay: TimeInterval)
51+
52+
/// Pauses a running animation at its current position.
53+
func pauseAnimation()
54+
55+
/// Stops the animations at their current positions.
56+
func stopAnimation(_ withoutFinishing: Bool)
57+
58+
/// Finishes the animations and returns the animator to the inactive state.
59+
func finishAnimation(at finalPositiong: ViewAnimatingPosition)
60+
61+
// MARK - Getting the Animator's State
62+
63+
/// The completion percentage of the animation.
64+
var fractionComplete: Double { get set }
65+
66+
/// A boolean value indicating whether the animation is running in the reverse
67+
/// direction.
68+
var isReversed: Bool { get set }
69+
70+
/// The current state of the animation.
71+
var state: ViewAnimatingState { get }
72+
73+
/// A boolean value indicating whether the animation is currently running.
74+
var isRunning: Bool { get }
75+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// Copyright © 2021 Saleem Abdulrasool <[email protected]>
2+
// SPDX-License-Identifier: BSD-3-Clause
3+
4+
/// An interface for modifying an animation while it is running.
5+
public protocol ViewImplicitlyAnimating: ViewAnimating {
6+
// MARK - Modifying Animations
7+
8+
/// Adds the specified animation block to the animator.
9+
func addAnimations(_ animation: @escaping () -> Void)
10+
11+
/// Adds the specified animation block to the animator with a delay.
12+
func addAnimations(_ animation: @escaping () -> Void, delayFactor: Double)
13+
14+
/// Adds the specified completion block to the animator.
15+
func addCompletion(_ completion: @escaping (ViewAnimatingPosition) -> Void)
16+
17+
/// Adjusts the final timing and duration of a paused animation.
18+
func continueAnimation(withTimingParameters paramters: TimingCurveProvider?,
19+
durationFactor: Double)
20+
}
21+
22+
extension ViewImplicitlyAnimating {
23+
public func addAnimations(_ animation: @escaping () -> Void) {
24+
self.addAnimations(animation, delayFactor: 0.0)
25+
}
26+
27+
public func addAnimations(_ animation: @escaping () -> Void,
28+
delayFactor: Double) {
29+
}
30+
31+
public func addCompletion(_ completion: @escaping (ViewAnimatingPosition) -> Void) {
32+
}
33+
34+
public func continueAnimation(withTimingParameters paramters: TimingCurveProvider?,
35+
durationFactor: Double) {
36+
}
37+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// Copyright © 2021 Saleem Abdulrasool <[email protected]>
2+
// SPDX-License-Identifier: BSD-3-Clause
3+
4+
import struct Foundation.TimeInterval
5+
6+
/// A set of methods for implementing the animations for a custom view controller
7+
/// transition.
8+
public protocol ViewControllerAnimatedTransitioning {
9+
// MARK - Performing a Transition
10+
11+
/// Tells your animator object to perform the transition animations.
12+
func animateTransition(using transitionContext: ViewControllerContextTransitioning)
13+
14+
/// Tells your animator object that the transition animations have finished.
15+
func animationEnded(_ transitionCompleted: Bool)
16+
17+
// MARK - Reporting Transition Duration
18+
19+
/// Asks your animator object for the duration (in seconds) of the transition
20+
/// animation.
21+
func transitionDuration(using transitionContext: ViewControllerContextTransitioning?)
22+
-> TimeInterval
23+
24+
// MARK - Returning an Interruptible Animator
25+
26+
/// Returns the interruptible animator to use during the transition.
27+
func interruptibleAnimator(using transitionContext: ViewControllerContextTransitioning)
28+
-> ViewImplicitlyAnimating
29+
}
30+
31+
extension ViewControllerAnimatedTransitioning {
32+
public func animationEnded(_ transitionCompleted: Bool) {
33+
}
34+
}
35+
36+
extension ViewControllerAnimatedTransitioning {
37+
func interruptibleAnimator(using transitionContext: ViewControllerContextTransitioning)
38+
-> ViewImplicitlyAnimating {
39+
fatalError("\(#function) not yet implemented")
40+
}
41+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// Copyright © 2021 Saleem Abdulrasool <[email protected]>
2+
// SPDX-License-Identifier: BSD-3-Clause
3+
4+
/// A set of methods that enable an object (such as a navigation controller) to
5+
/// drive a view controller transition.
6+
public protocol ViewControllerInteractiveTransitioning {
7+
// MARK - Starting an Interactive Transition
8+
9+
/// Called when the system needs to set up the interactive portions of a view
10+
/// controller transition and start the animations.
11+
func startInteractiveTransition(_ transitionContext: ViewControllerContextTransitioning)
12+
13+
/// A boolean value indicating whether the transition is interactive when it
14+
/// starts.
15+
///
16+
/// The value of this property is `true` when the transition is interactive
17+
/// from the moment it starts. The property is `false` when the transition
18+
/// starts off as noninteractive. However, even a transition that starts off
19+
/// as noninteractive may become interactive later if it implements the
20+
/// `interruptibleAnimator(using:)` method of the
21+
/// `ViewControllerAnimatedTransitioning` protocol.
22+
var wantsInteractiveStart: Bool { get }
23+
24+
// MARK - Providing a Transition's Completion Characteristics
25+
26+
/// Called when the system needs the animation completion curve for an
27+
/// interactive view controller transition.
28+
var completionCurve: View.AnimationCurve { get }
29+
30+
/// Called when the system needs the speed at which to complete an interactive
31+
/// transition, after the interactive portion is finished.
32+
var completionSpeed: Double { get }
33+
}
34+
35+
extension ViewControllerInteractiveTransitioning {
36+
public var wantsInteractiveStart: Bool { true }
37+
}
38+
39+
extension ViewControllerInteractiveTransitioning {
40+
public var completionCurve: View.AnimationCurve { .easeInOut }
41+
42+
public var completionSpeed: Double { 1.0 }
43+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
// Copyright © 2021 Saleem Abdulrasool <[email protected]>
2+
// SPDX-License-Identifier: BSD-3-Clause
3+
4+
/// A set of methods that vend objects used to manage a fixed-length or
5+
/// interactive transition between view controllers.
6+
public protocol ViewControllerTransitioningDelegate: AnyObject {
7+
// MARK - Getting the Transition Animator Objects
8+
9+
/// Asks your delegate for the transition animator object to use when
10+
/// presenting a view controller.
11+
func animationController(forPresented presented: ViewController,
12+
presenting: ViewController, source: ViewController)
13+
-> ViewControllerAnimatedTransitioning?
14+
15+
/// Asks your delegate for the transition animator object to use when
16+
/// dismissing a view controller.
17+
func animationController(forDismissed dismissed: ViewController)
18+
-> ViewControllerAnimatedTransitioning?
19+
20+
// MARK - Getting the Interactive Animator Objects
21+
22+
/// Asks your delegate for the interactive animator object to use when
23+
/// presenting a view controller.
24+
func interactionControllerForPresentation(using animator: ViewControllerAnimatedTransitioning)
25+
-> ViewControllerInteractiveTransitioning?
26+
27+
/// Asks your delegate for the interactive animator object to use when
28+
/// dismissing a view controller.
29+
func interactionControllerForDismissal(using animator: ViewControllerAnimatedTransitioning)
30+
-> ViewControllerInteractiveTransitioning?
31+
32+
// MARK - Getting the Custom Presentation Controller
33+
34+
/// Asks your delegate for the custom presentation controller to use for
35+
/// managing the view hierarchy when presenting a view controller.
36+
func presentationController(forPresented presented: ViewController,
37+
presenting: ViewController?,
38+
source: ViewController)
39+
-> PresentationController?
40+
}
41+
42+
extension ViewControllerTransitioningDelegate {
43+
public func animationController(forPresented presented: ViewController,
44+
presenting: ViewController, source: ViewController)
45+
-> ViewControllerAnimatedTransitioning? {
46+
return nil
47+
}
48+
49+
public func animationController(forDismissed dismissed: ViewController)
50+
-> ViewControllerAnimatedTransitioning? {
51+
return nil
52+
}
53+
}
54+
55+
extension ViewControllerTransitioningDelegate {
56+
public func interactionControllerForPresentation(using animator: ViewControllerAnimatedTransitioning)
57+
-> ViewControllerInteractiveTransitioning? {
58+
return nil
59+
}
60+
61+
public func interactionControllerForDismissal(using animator: ViewControllerAnimatedTransitioning)
62+
-> ViewControllerInteractiveTransitioning? {
63+
return nil
64+
}
65+
}
66+
67+
extension ViewControllerTransitioningDelegate {
68+
public func presentationController(forPresented presented: ViewController,
69+
presenting: ViewController?,
70+
source: ViewController)
71+
-> PresentationController? {
72+
return nil
73+
}
74+
}

0 commit comments

Comments
 (0)