Keyframe.swift 2.7 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
// Created by Cal Stephens on 1/24/22.
// Copyright © 2022 Airbnb Inc. All rights reserved.

import CoreFoundation

// MARK: - Keyframe

/// A keyframe with a single value, and timing information
/// about when the value should be displayed and how it
/// should be interpolated.
public final class Keyframe<T> {

  // MARK: Lifecycle

  /// Initialize a value-only keyframe with no time data.
  public init(
    _ value: T,
    spatialInTangent: LottieVector3D? = nil,
    spatialOutTangent: LottieVector3D? = nil)
  {
    self.value = value
    time = 0
    isHold = true
    inTangent = nil
    outTangent = nil
    self.spatialInTangent = spatialInTangent
    self.spatialOutTangent = spatialOutTangent
  }

  /// Initialize a keyframe
  public init(
    value: T,
    time: AnimationFrameTime,
    isHold: Bool = false,
    inTangent: LottieVector2D? = nil,
    outTangent: LottieVector2D? = nil,
    spatialInTangent: LottieVector3D? = nil,
    spatialOutTangent: LottieVector3D? = nil)
  {
    self.value = value
    self.time = time
    self.isHold = isHold
    self.outTangent = outTangent
    self.inTangent = inTangent
    self.spatialInTangent = spatialInTangent
    self.spatialOutTangent = spatialOutTangent
  }

  // MARK: Public

  /// The value of the keyframe
  public let value: T
  /// The time in frames of the keyframe.
  public let time: AnimationFrameTime
  /// A hold keyframe freezes interpolation until the next keyframe that is not a hold.
  public let isHold: Bool
  /// The in tangent for the time interpolation curve.
  public let inTangent: LottieVector2D?
  /// The out tangent for the time interpolation curve.
  public let outTangent: LottieVector2D?

  /// The spatial in tangent of the vector.
  public let spatialInTangent: LottieVector3D?
  /// The spatial out tangent of the vector.
  public let spatialOutTangent: LottieVector3D?
}

// MARK: Equatable

extension Keyframe: Equatable where T: Equatable {
  public static func == (lhs: Keyframe<T>, rhs: Keyframe<T>) -> Bool {
    lhs.value == rhs.value
      && lhs.time == rhs.time
      && lhs.isHold == rhs.isHold
      && lhs.inTangent == rhs.inTangent
      && lhs.outTangent == rhs.outTangent
      && lhs.spatialInTangent == rhs.spatialOutTangent
      && lhs.spatialOutTangent == rhs.spatialOutTangent
  }
}

// MARK: Hashable

extension Keyframe: Hashable where T: Hashable {
  public func hash(into hasher: inout Hasher) {
    hasher.combine(value)
    hasher.combine(time)
    hasher.combine(isHold)
    hasher.combine(inTangent)
    hasher.combine(outTangent)
    hasher.combine(spatialInTangent)
    hasher.combine(spatialOutTangent)
  }
}

// MARK: Sendable

extension Keyframe: Sendable where T: Sendable { }