Commit 53088a53 by Daniel Dahan

rework of Motion+CG

parent 1dfc3fb8
/* /*
* Copyright (C) 2015 - 2017, Daniel Dahan and CosmicMind, Inc. <http://cosmicmind.com>. * The MIT License (MIT)
* All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Copyright (C) 2017, Daniel Dahan and CosmicMind, Inc. <http://cosmicmind.com>.
* modification, are permitted provided that the following conditions are met: * All rights reserved.
* *
* * Redistributions of source code must retain the above copyright notice, this * Original Inspiration & Author
* list of conditions and the following disclaimer. * Copyright (c) 2016 Luke Zhao <me@lkzhao.com>
* *
* * Redistributions in binary form must reproduce the above copyright notice, * Permission is hereby granted, free of charge, to any person obtaining a copy
* this list of conditions and the following disclaimer in the documentation * of this software and associated documentation files (the "Software"), to deal
* and/or other materials provided with the distribution. * in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
* *
* * Neither the name of CosmicMind nor the names of its * The above copyright notice and this permission notice shall be included in
* contributors may be used to endorse or promote products derived from * all copies or substantial portions of the Software.
* this software without specific prior written permission.
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * THE SOFTWARE.
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
import MetalKit import MetalKit
internal struct KeySet<Key: Hashable, Value: Hashable> { extension CGSize {
/// A reference to the dictionary storing the key / Set pairs. /// THe center point based on width and height.
fileprivate var dictionary = [Key: Set<Value>]() var center: CGPoint {
return CGPoint(x: width / 2, y: height / 2)
/**
Subscript for matching keys and returning the corresponding set.
- Parameter key: A Key type.
- Returns: A Set<Value> type.
*/
subscript(key: Key) -> Set<Value> {
mutating get {
if nil == dictionary[key] {
dictionary[key] = Set<Value>()
} }
return dictionary[key]! /// Top left point based on the size.
} var topLeft: CGPoint {
set(value) { return .zero
dictionary[key] = value
} }
/// Top right point based on the size.
var topRight: CGPoint {
return CGPoint(x: width, y: 0)
} }
}
internal extension CGSize { /// Bottom left point based on the size.
internal var center: CGPoint { var bottomLeftPoint: CGPoint {
return CGPoint(x: width / 2, y: height / 2) return CGPoint(x: 0, y: height)
} }
internal var point: CGPoint { /// Bottom right point based on the size.
var bottomRight: CGPoint {
return CGPoint(x: width, y: height) return CGPoint(x: width, y: height)
} }
internal func transform(_ t: CGAffineTransform) -> CGSize { /**
Retrieves the size based on a given CGAffineTransform.
- Parameter _ t: A CGAffineTransform.
- Returns: A CGSize.
*/
func transform(_ t: CGAffineTransform) -> CGSize {
return applying(t) return applying(t)
} }
internal func transform(_ t: CATransform3D) -> CGSize { /**
Retrieves the size based on a given CATransform3D.
- Parameter _ t: A CGAffineTransform.
- Returns: A CGSize.
*/
func transform(_ t: CATransform3D) -> CGSize {
return applying(CATransform3DGetAffineTransform(t)) return applying(CATransform3DGetAffineTransform(t))
} }
} }
internal extension CGRect { extension CGRect {
/// A center point based on the origin and size values.
var center: CGPoint { var center: CGPoint {
return CGPoint(x: origin.x + size.width / 2, y: origin.y + size.height / 2) return CGPoint(x: origin.x + size.width / 2, y: origin.y + size.height / 2)
} }
/// The bounding box size based from from the frame's rect.
var bounds: CGRect { var bounds: CGRect {
return CGRect(origin: CGPoint.zero, size: size) return CGRect(origin: .zero, size: size)
} }
/**
An initializer with a given point and size.
- Parameter center: A CGPoint.
- Parameter size: A CGSize.
*/
init(center: CGPoint, size: CGSize) { init(center: CGPoint, size: CGSize) {
self.init(x: center.x - size.width / 2, y: center.y - size.height / 2, width: size.width, height: size.height) self.init(x: center.x - size.width / 2, y: center.y - size.height / 2, width: size.width, height: size.height)
} }
} }
internal extension CGFloat { extension CGFloat {
/**
Calculates the limiting position to an area.
- Parameter _ a: A CGFloat.
- Parameter _ b: A CGFloat.
- Returns: A CGFloat.
*/
func clamp(_ a: CGFloat, _ b: CGFloat) -> CGFloat { func clamp(_ a: CGFloat, _ b: CGFloat) -> CGFloat {
return self < a ? a : self > b ? b : self return self < a ? a : self > b ? b : self
} }
} }
internal extension CGPoint { extension CGPoint {
/**
Calculates a translation point based on the origin value.
- Parameter _ dx: A CGFloat.
- Parameter _ dy: A CGFloat.
- Returns: A CGPoint.
*/
func translate(_ dx: CGFloat, dy: CGFloat) -> CGPoint { func translate(_ dx: CGFloat, dy: CGFloat) -> CGPoint {
return CGPoint(x: x + dx, y: y + dy) return CGPoint(x: x + dx, y: y + dy)
} }
/**
Calculates a transform point based on a given CGAffineTransform.
- Parameter _ t: CGAffineTransform.
- Returns: A CGPoint.
*/
func transform(_ t: CGAffineTransform) -> CGPoint { func transform(_ t: CGAffineTransform) -> CGPoint {
return applying(t) return applying(t)
} }
/**
Calculates a transform point based on a given CATransform3D.
- Parameter _ t: CATransform3D.
- Returns: A CGPoint.
*/
func transform(_ t: CATransform3D) -> CGPoint { func transform(_ t: CATransform3D) -> CGPoint {
return applying(CATransform3DGetAffineTransform(t)) return applying(CATransform3DGetAffineTransform(t))
} }
/**
Calculates the distance between the CGPoint and given CGPoint.
- Parameter _ b: A CGPoint.
- Returns: A CGFloat.
*/
func distance(_ b: CGPoint) -> CGFloat { func distance(_ b: CGPoint) -> CGFloat {
return sqrt(pow(x - b.x, 2) + pow(y - b.y, 2)) return sqrt(pow(x - b.x, 2) + pow(y - b.y, 2))
} }
} }
internal func +(left: CGPoint, right: CGPoint) -> CGPoint { /**
A handler for the (+) operator.
- Parameter left: A CGPoint.
- Parameter right: A CGPoint.
- Returns: A CGPoint.
*/
func +(left: CGPoint, right: CGPoint) -> CGPoint {
return CGPoint(x: left.x + right.x, y: left.y + right.y) return CGPoint(x: left.x + right.x, y: left.y + right.y)
} }
internal func -(left: CGPoint, right: CGPoint) -> CGPoint { /**
A handler for the (-) operator.
- Parameter left: A CGPoint.
- Parameter right: A CGPoint.
- Returns: A CGPoint.
*/
func -(left: CGPoint, right: CGPoint) -> CGPoint {
return CGPoint(x: left.x - right.x, y: left.y - right.y) return CGPoint(x: left.x - right.x, y: left.y - right.y)
} }
internal func /(left: CGPoint, right: CGFloat) -> CGPoint { /**
A handler for the (/) operator.
- Parameter left: A CGPoint.
- Parameter right: A CGFloat.
- Returns: A CGPoint.
*/
func /(left: CGPoint, right: CGFloat) -> CGPoint {
return CGPoint(x: left.x / right, y: left.y / right) return CGPoint(x: left.x / right, y: left.y / right)
} }
internal func /(left: CGPoint, right: CGPoint) -> CGPoint { /**
A handler for the (/) operator.
- Parameter left: A CGPoint.
- Parameter right: A CGPoint.
- Returns: A CGPoint.
*/
func /(left: CGPoint, right: CGPoint) -> CGPoint {
return CGPoint(x: left.x / right.x, y: left.y / right.y) return CGPoint(x: left.x / right.x, y: left.y / right.y)
} }
internal func *(left: CGPoint, right: CGFloat) -> CGPoint { /**
A handler for the (/) operator.
- Parameter left: A CGSize.
- Parameter right: A CGSize.
- Returns: A CGSize.
*/
func /(left: CGSize, right: CGSize) -> CGSize {
return CGSize(width: left.width / right.width, height: left.height / right.height)
}
/**
A handler for the (*) operator.
- Parameter left: A CGPoint.
- Parameter right: A CGFloat.
- Returns: A CGPoint.
*/
func *(left: CGPoint, right: CGFloat) -> CGPoint {
return CGPoint(x: left.x * right, y: left.y * right) return CGPoint(x: left.x * right, y: left.y * right)
} }
internal func *(left: CGPoint, right: CGSize) -> CGPoint { /**
A handler for the (*) operator.
- Parameter left: A CGPoint.
- Parameter right: A CGSize.
- Returns: A CGPoint.
*/
func *(left: CGPoint, right: CGSize) -> CGPoint {
return CGPoint(x: left.x * right.width, y: left.y * right.width) return CGPoint(x: left.x * right.width, y: left.y * right.width)
} }
internal func *(left: CGFloat, right: CGPoint) -> CGPoint { /**
A handler for the (*) operator.
- Parameter left: A CGFloat.
- Parameter right: A CGPoint.
- Returns: A CGPoint.
*/
func *(left: CGFloat, right: CGPoint) -> CGPoint {
return right * left return right * left
} }
internal func *(left: CGPoint, right: CGPoint) -> CGPoint { /**
A handler for the (*) operator.
- Parameter left: A CGPoint.
- Parameter right: A CGPoint.
- Returns: A CGPoint.
*/
func *(left: CGPoint, right: CGPoint) -> CGPoint {
return CGPoint(x: left.x * right.x, y: left.y * right.y) return CGPoint(x: left.x * right.x, y: left.y * right.y)
} }
internal prefix func -(point: CGPoint) -> CGPoint { /**
return CGPoint.zero - point A handler for the (*) prefix.
} - Parameter left: A CGSize.
- Parameter right: A CGFloat.
internal func abs(_ p: CGPoint) -> CGPoint { - Returns: A CGSize.
return CGPoint(x: abs(p.x), y: abs(p.y)) */
} func *(left: CGSize, right: CGFloat) -> CGSize {
internal func *(left: CGSize, right: CGFloat) -> CGSize {
return CGSize(width: left.width * right, height: left.height * right) return CGSize(width: left.width * right, height: left.height * right)
} }
internal func *(left: CGSize, right: CGSize) -> CGSize { /**
A handler for the (*) prefix.
- Parameter left: A CGSize.
- Parameter right: A CGSize.
- Returns: A CGSize.
*/
func *(left: CGSize, right: CGSize) -> CGSize {
return CGSize(width: left.width * right.width, height: left.height * right.width) return CGSize(width: left.width * right.width, height: left.height * right.width)
} }
internal func /(left: CGSize, right: CGSize) -> CGSize { /**
return CGSize(width: left.width / right.width, height: left.height / right.height) A handler for the (==) operator.
} - Parameter lhs: A CATransform3D.
- Parameter rhs: A CATransform3D.
internal func == (lhs: CATransform3D, rhs: CATransform3D) -> Bool { - Returns: A Bool.
*/
func ==(lhs: CATransform3D, rhs: CATransform3D) -> Bool {
var lhs = lhs var lhs = lhs
var rhs = rhs var rhs = rhs
return memcmp(&lhs, &rhs, MemoryLayout<CATransform3D>.size) == 0 return memcmp(&lhs, &rhs, MemoryLayout<CATransform3D>.size) == 0
} }
internal func != (lhs: CATransform3D, rhs: CATransform3D) -> Bool { /**
A handler for the (!=) operator.
- Parameter lhs: A CATransform3D.
- Parameter rhs: A CATransform3D.
- Returns: A Bool.
*/
func !=(lhs: CATransform3D, rhs: CATransform3D) -> Bool {
return !(lhs == rhs) return !(lhs == rhs)
} }
/**
A handler for the (-) prefix.
- Parameter point: A CGPoint.
- Returns: A CGPoint.
*/
prefix func -(point: CGPoint) -> CGPoint {
return CGPoint.zero - point
}
/**
A handler for the (abs) function.
- Parameter _ p: A CGPoint.
- Returns: A CGPoint.
*/
func abs(_ p: CGPoint) -> CGPoint {
return CGPoint(x: abs(p.x), y: abs(p.y))
}
...@@ -30,24 +30,22 @@ import UIKit ...@@ -30,24 +30,22 @@ import UIKit
internal extension UIView { internal extension UIView {
func optimizedDuration(fromPosition: CGPoint, toPosition: CGPoint?, size: CGSize?, transform: CATransform3D?) -> TimeInterval { func optimizedDuration(fromPosition: CGPoint, toPosition: CGPoint?, size: CGSize?, transform: CATransform3D?) -> TimeInterval {
let fromPos = fromPosition let toPos = toPosition ?? fromPosition
let toPos = toPosition ?? fromPos
let fromSize = (layer.presentation() ?? layer).bounds.size let fromSize = (layer.presentation() ?? layer).bounds.size
let toSize = size ?? fromSize let toSize = size ?? fromSize
let fromTransform = (layer.presentation() ?? layer).transform let fromTransform = (layer.presentation() ?? layer).transform
let toTransform = transform ?? fromTransform let toTransform = transform ?? fromTransform
let realFromPos = CGPoint.zero.transform(fromTransform) + fromPos let realFromPos = CGPoint.zero.transform(fromTransform) + fromPosition
let realToPos = CGPoint.zero.transform(toTransform) + toPos let realToPos = CGPoint.zero.transform(toTransform) + toPos
let realFromSize = fromSize.transform(fromTransform) let realFromSize = fromSize.transform(fromTransform)
let realToSize = toSize.transform(toTransform) let realToSize = toSize.transform(toTransform)
let movePoints = (realFromPos.distance(realToPos) + realFromSize.point.distance(realToSize.point)) let movePoints = realFromPos.distance(realToPos) + realFromSize.bottomRight.distance(realToSize.bottomRight)
// duration is 0.2 @ 0 to 0.375 @ 500 // duration is 0.2 @ 0 to 0.375 @ 500
let duration = 0.208 + Double(movePoints.clamp(0, 500)) / 3000 return 0.208 + Double(movePoints.clamp(0, 500)) / 3000
return duration
} }
} }
......
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