Skip to content

Instantly share code, notes, and snippets.

@ryanlintott
Last active September 8, 2023 14:31
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Embed
What would you like to do?
A parameter pack implementation of `AnimatablePair`. Started off as a weird idea but I think this version works. Now included in my ShapeUp SPM. https://github.com/ryanlintott/ShapeUp
//
// AnimatablePack.swift
// ShapeUp
//
// Created by Ryan Lintott on 2023-08-02.
//
import Foundation
import SwiftUI
@available(iOS 17, macOS 14, *)
fileprivate extension VectorArithmetic {
func addingMagnitudeSquared(to value: inout Double) {
value += magnitudeSquared
}
}
/**
A parameter pack implementation of `AnimatablePair`
Conforming to Animatable with AnimatablePair:
```swift
struct MyShape: Animatable {
var animatableData: AnimatablePair<CGFloat, AnimatablePair<RelatableValue, Double>> {
get { AnimatablePair(insetAmount, AnimatablePair(cornerRadius, rotation)) }
set {
insetAmount = newValue.first
cornerRadius = newValue.second.first
rotation = newValue.second.second
}
}
}
```
Conforming to Animatable with AnimatablePack:
```swift
struct MyShape: Animatable {
var animatableData: AnimatablePack<CGFloat, RelatableValue, Double> {
get { AnimatablePack(insetAmount, cornerRadius, rotation) }
set { (insetAmount, cornerRadius, rotation) = newValue() }
}
}
```
*/
@available(iOS 17, macOS 14, *)
public struct AnimatablePack<each Item: VectorArithmetic>: VectorArithmetic {
public var item: (repeat each Item)
public init(_ item: repeat each Item) {
self.item = (repeat each item)
}
public func callAsFunction() -> (repeat each Item) {
item
}
}
@available(iOS 17, macOS 14, *)
public extension AnimatablePack {
static var zero: Self {
.init(repeat (each Item).zero)
}
static func + (lhs: Self, rhs: Self) -> Self {
.init(repeat (each lhs.item) + (each rhs.item))
}
static func - (lhs: Self, rhs: Self) -> Self {
.init(repeat (each lhs.item) - (each rhs.item))
}
mutating func scale(by rhs: Double) {
item = (repeat (each item).scaled(by: rhs))
}
static func == (lhs: Self, rhs: Self) -> Bool {
(lhs - rhs).magnitudeSquared == .zero
}
var magnitudeSquared: Double {
var value = 0.0
_ = (repeat (each item).addingMagnitudeSquared(to: &value))
return value
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment