mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
123 lines
4.4 KiB
Swift
123 lines
4.4 KiB
Swift
//
|
|
// GroupNode.swift
|
|
// lottie-swift
|
|
//
|
|
// Created by Brandon Withrow on 1/18/19.
|
|
//
|
|
|
|
import Foundation
|
|
import QuartzCore
|
|
import CoreGraphics
|
|
|
|
final class GroupNodeProperties: NodePropertyMap {
|
|
|
|
init(transform: ShapeTransform?) {
|
|
if let transform = transform {
|
|
self.anchor = NodeProperty(provider: KeyframeInterpolator(keyframes: transform.anchor.keyframes))
|
|
self.position = NodeProperty(provider: KeyframeInterpolator(keyframes: transform.position.keyframes))
|
|
self.scale = NodeProperty(provider: KeyframeInterpolator(keyframes: transform.scale.keyframes))
|
|
self.rotation = NodeProperty(provider: KeyframeInterpolator(keyframes: transform.rotation.keyframes))
|
|
self.opacity = NodeProperty(provider: KeyframeInterpolator(keyframes: transform.opacity.keyframes))
|
|
self.skew = NodeProperty(provider: KeyframeInterpolator(keyframes: transform.skew.keyframes))
|
|
self.skewAxis = NodeProperty(provider: KeyframeInterpolator(keyframes: transform.skewAxis.keyframes))
|
|
} else {
|
|
/// Transform node missing. Default to empty transform.
|
|
self.anchor = NodeProperty(provider: SingleValueProvider(Vector3D(x: CGFloat(0), y: CGFloat(0), z: CGFloat(0))))
|
|
self.position = NodeProperty(provider: SingleValueProvider(Vector3D(x: CGFloat(0), y: CGFloat(0), z: CGFloat(0))))
|
|
self.scale = NodeProperty(provider: SingleValueProvider(Vector3D(x: CGFloat(1), y: CGFloat(1), z: CGFloat(1))))
|
|
self.rotation = NodeProperty(provider: SingleValueProvider(Vector1D(0)))
|
|
self.opacity = NodeProperty(provider: SingleValueProvider(Vector1D(1)))
|
|
self.skew = NodeProperty(provider: SingleValueProvider(Vector1D(0)))
|
|
self.skewAxis = NodeProperty(provider: SingleValueProvider(Vector1D(0)))
|
|
}
|
|
let keypathProperties: [String : AnyNodeProperty] = [
|
|
"Anchor Point" : anchor,
|
|
"Position" : position,
|
|
"Scale" : scale,
|
|
"Rotation" : rotation,
|
|
"Opacity" : opacity,
|
|
"Skew" : skew,
|
|
"Skew Axis" : skewAxis
|
|
]
|
|
self.properties = Array(keypathProperties.values)
|
|
}
|
|
|
|
let properties: [AnyNodeProperty]
|
|
|
|
let anchor: NodeProperty<Vector3D>
|
|
let position: NodeProperty<Vector3D>
|
|
let scale: NodeProperty<Vector3D>
|
|
let rotation: NodeProperty<Vector1D>
|
|
let opacity: NodeProperty<Vector1D>
|
|
let skew: NodeProperty<Vector1D>
|
|
let skewAxis: NodeProperty<Vector1D>
|
|
|
|
var caTransform: CATransform3D {
|
|
return CATransform3D.makeTransform(anchor: anchor.value.pointValue,
|
|
position: position.value.pointValue,
|
|
scale: scale.value.sizeValue,
|
|
rotation: rotation.value.cgFloatValue,
|
|
skew: skew.value.cgFloatValue,
|
|
skewAxis: skewAxis.value.cgFloatValue)
|
|
}
|
|
}
|
|
|
|
final class GroupNode: AnimatorNode {
|
|
|
|
// MARK: Properties
|
|
let groupOutput: GroupOutputNode
|
|
|
|
let properties: GroupNodeProperties
|
|
|
|
let rootNode: AnimatorNode?
|
|
|
|
var container: ShapeContainerLayer = ShapeContainerLayer()
|
|
|
|
// MARK: Initializer
|
|
init(name: String, parentNode: AnimatorNode?, tree: NodeTree) {
|
|
self.parentNode = parentNode
|
|
self.rootNode = tree.rootNode
|
|
self.properties = GroupNodeProperties(transform: tree.transform)
|
|
self.groupOutput = GroupOutputNode(parent: parentNode?.outputNode, rootNode: rootNode?.outputNode)
|
|
|
|
for childContainer in tree.renderContainers {
|
|
container.insertRenderLayer(childContainer)
|
|
}
|
|
}
|
|
|
|
// MARK: Animator Node Protocol
|
|
|
|
var propertyMap: NodePropertyMap {
|
|
return properties
|
|
}
|
|
|
|
var outputNode: NodeOutput {
|
|
return groupOutput
|
|
}
|
|
|
|
let parentNode: AnimatorNode?
|
|
var hasLocalUpdates: Bool = false
|
|
var hasUpstreamUpdates: Bool = false
|
|
var lastUpdateFrame: CGFloat? = nil
|
|
var isEnabled: Bool = true {
|
|
didSet {
|
|
container.isHidden = !isEnabled
|
|
}
|
|
}
|
|
|
|
func performAdditionalLocalUpdates(frame: CGFloat, forceLocalUpdate: Bool) -> Bool {
|
|
return rootNode?.updateContents(frame, forceLocalUpdate: forceLocalUpdate) ?? false
|
|
}
|
|
|
|
func performAdditionalOutputUpdates(_ frame: CGFloat, forceOutputUpdate: Bool) {
|
|
rootNode?.updateOutputs(frame, forceOutputUpdate: forceOutputUpdate)
|
|
}
|
|
|
|
func rebuildOutputs(frame: CGFloat) {
|
|
container.opacity = Float(properties.opacity.value.cgFloatValue) * 0.01
|
|
container.transform = properties.caTransform
|
|
groupOutput.setTransform(container.transform, forFrame: frame)
|
|
}
|
|
|
|
}
|