You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
179 lines
6.2 KiB
179 lines
6.2 KiB
// The MIT License (MIT)
|
|
//
|
|
// Copyright (c) 2016 Luke Zhao <me@lkzhao.com>
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
// of this software and associated documentation files (the "Software"), to deal
|
|
// 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:
|
|
//
|
|
// The above copyright notice and this permission notice shall be included in
|
|
// all copies or substantial portions of the Software.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
// THE SOFTWARE.
|
|
|
|
import UIKit
|
|
|
|
#if os(iOS)
|
|
public class HeroDebugPlugin: HeroPlugin {
|
|
public static var showOnTop: Bool = false
|
|
|
|
var debugView: HeroDebugView?
|
|
var zPositionMap = [UIView: CGFloat]()
|
|
var addedLayers: [CALayer] = []
|
|
var updating = false
|
|
|
|
override public func animate(fromViews: [UIView], toViews: [UIView]) -> TimeInterval {
|
|
if hero.forceNotInteractive { return 0 }
|
|
var hasArc = false
|
|
for v in context.fromViews + context.toViews where context[v]?.arc != nil && context[v]?.position != nil {
|
|
hasArc = true
|
|
break
|
|
}
|
|
let debugView = HeroDebugView(initialProcess: hero.isPresenting ? 0.0 : 1.0, showCurveButton: hasArc, showOnTop: HeroDebugPlugin.showOnTop)
|
|
debugView.frame = hero.container.bounds
|
|
debugView.delegate = self
|
|
hero.container.window?.addSubview(debugView)
|
|
|
|
debugView.layoutSubviews()
|
|
self.debugView = debugView
|
|
|
|
UIView.animate(withDuration: 0.4) {
|
|
debugView.showControls = true
|
|
}
|
|
|
|
return .infinity
|
|
}
|
|
|
|
public override func resume(timePassed: TimeInterval, reverse: Bool) -> TimeInterval {
|
|
guard let debugView = debugView else { return 0.4 }
|
|
debugView.delegate = nil
|
|
|
|
UIView.animate(withDuration: 0.4) {
|
|
debugView.showControls = false
|
|
debugView.debugSlider.setValue(roundf(debugView.progress), animated: true)
|
|
}
|
|
|
|
on3D(wants3D: false)
|
|
return 0.4
|
|
}
|
|
|
|
public override func clean() {
|
|
debugView?.removeFromSuperview()
|
|
debugView = nil
|
|
}
|
|
}
|
|
|
|
extension HeroDebugPlugin: HeroDebugViewDelegate {
|
|
public func onDone() {
|
|
guard let debugView = debugView else { return }
|
|
let seekValue = hero.isPresenting ? debugView.progress : 1.0 - debugView.progress
|
|
if seekValue > 0.5 {
|
|
hero.finish()
|
|
} else {
|
|
hero.cancel()
|
|
}
|
|
}
|
|
|
|
public func onProcessSliderChanged(progress: Float) {
|
|
let seekValue = hero.isPresenting ? progress : 1.0 - progress
|
|
hero.update(CGFloat(seekValue))
|
|
}
|
|
|
|
func onPerspectiveChanged(translation: CGPoint, rotation: CGFloat, scale: CGFloat) {
|
|
var t = CATransform3DIdentity
|
|
t.m34 = -1 / 4000
|
|
t = CATransform3DTranslate(t, translation.x, translation.y, 0)
|
|
t = CATransform3DScale(t, scale, scale, 1)
|
|
t = CATransform3DRotate(t, rotation, 0, 1, 0)
|
|
hero.container.layer.sublayerTransform = t
|
|
}
|
|
|
|
func animateZPosition(view: UIView, to: CGFloat) {
|
|
let a = CABasicAnimation(keyPath: "zPosition")
|
|
a.fromValue = view.layer.value(forKeyPath: "zPosition")
|
|
a.toValue = NSNumber(value: Double(to))
|
|
a.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut)
|
|
a.duration = 0.4
|
|
view.layer.add(a, forKey: "zPosition")
|
|
view.layer.zPosition = to
|
|
}
|
|
|
|
func onDisplayArcCurve(wantsCurve: Bool) {
|
|
for layer in addedLayers {
|
|
layer.removeFromSuperlayer()
|
|
addedLayers.removeAll()
|
|
}
|
|
if wantsCurve {
|
|
for layer in hero.container.layer.sublayers! {
|
|
for (_, anim) in layer.animations {
|
|
if let keyframeAnim = anim as? CAKeyframeAnimation, let path = keyframeAnim.path {
|
|
let s = CAShapeLayer()
|
|
s.zPosition = layer.zPosition + 10
|
|
s.path = path
|
|
s.strokeColor = UIColor.blue.cgColor
|
|
s.fillColor = UIColor.clear.cgColor
|
|
hero.container.layer.addSublayer(s)
|
|
addedLayers.append(s)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func on3D(wants3D: Bool) {
|
|
var t = CATransform3DIdentity
|
|
if wants3D {
|
|
var viewsWithZPosition = Set<UIView>()
|
|
for view in hero.container.subviews where view.layer.zPosition != 0 {
|
|
viewsWithZPosition.insert(view)
|
|
zPositionMap[view] = view.layer.zPosition
|
|
}
|
|
|
|
let viewsWithoutZPosition = hero.container.subviews.filter { return !viewsWithZPosition.contains($0) }
|
|
let viewsWithPositiveZPosition = viewsWithZPosition.filter { return $0.layer.zPosition > 0 }
|
|
|
|
for (i, v) in viewsWithoutZPosition.enumerated() {
|
|
animateZPosition(view: v, to: CGFloat(i * 10))
|
|
}
|
|
|
|
var maxZPosition: CGFloat = 0
|
|
for v in viewsWithPositiveZPosition {
|
|
maxZPosition = max(maxZPosition, v.layer.zPosition)
|
|
animateZPosition(view: v, to: v.layer.zPosition + CGFloat(viewsWithoutZPosition.count * 10))
|
|
}
|
|
|
|
t.m34 = -1 / 4000
|
|
t = CATransform3DTranslate(t, debugView!.translation.x, debugView!.translation.y, 0)
|
|
t = CATransform3DScale(t, debugView!.scale, debugView!.scale, 1)
|
|
t = CATransform3DRotate(t, debugView!.rotation, 0, 1, 0)
|
|
} else {
|
|
for v in hero.container.subviews {
|
|
animateZPosition(view: v, to: self.zPositionMap[v] ?? 0)
|
|
}
|
|
self.zPositionMap.removeAll()
|
|
}
|
|
|
|
let a = CABasicAnimation(keyPath: "sublayerTransform")
|
|
a.fromValue = hero.container.layer.value(forKeyPath: "sublayerTransform")
|
|
a.toValue = NSValue(caTransform3D: t)
|
|
a.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut)
|
|
a.duration = 0.4
|
|
|
|
UIView.animate(withDuration: 0.4) {
|
|
self.context.container.backgroundColor = UIColor(white: 0.85, alpha: 1.0)
|
|
}
|
|
|
|
hero.container.layer.add(a, forKey: "debug")
|
|
hero.container.layer.sublayerTransform = t
|
|
}
|
|
}
|
|
#endif
|