import Foundation import UIKit import SceneKit import Display import AppBundle import LegacyComponents import PremiumStarComponent private let sceneVersion: Int = 1 final class FasterStarsView: UIView, PhoneDemoDecorationView { private let sceneView: SCNView private var particles: SCNNode? override init(frame: CGRect) { self.sceneView = SCNView(frame: CGRect(origin: .zero, size: frame.size)) self.sceneView.backgroundColor = .clear if let scene = loadCompressedScene(name: "lightspeed", version: sceneVersion) { self.sceneView.scene = scene } self.sceneView.isUserInteractionEnabled = false self.sceneView.preferredFramesPerSecond = 60 super.init(frame: frame) self.alpha = 0.0 self.addSubview(self.sceneView) self.particles = self.sceneView.scene?.rootNode.childNode(withName: "particles", recursively: false) } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } deinit { self.particles = nil } func setVisible(_ visible: Bool) { if visible, let particles = self.particles, particles.parent == nil { self.sceneView.scene?.rootNode.addChildNode(particles) } let transition = ContainedViewLayoutTransition.animated(duration: 0.3, curve: .linear) transition.updateAlpha(layer: self.layer, alpha: visible ? 0.4 : 0.0, completion: { [weak self] finished in if let strongSelf = self, finished && !visible && strongSelf.particles?.parent != nil { strongSelf.particles?.removeFromParentNode() } }) } private var playing = false func startAnimation() { guard !self.playing, let scene = self.sceneView.scene, let node = scene.rootNode.childNode(withName: "particles", recursively: false), let particles = node.particleSystems?.first else { return } self.playing = true let speedAnimation = POPBasicAnimation() speedAnimation.property = (POPAnimatableProperty.property(withName: "speedFactor", initializer: { property in property?.readBlock = { particleSystem, values in values?.pointee = (particleSystem as! SCNParticleSystem).speedFactor } property?.writeBlock = { particleSystem, values in (particleSystem as! SCNParticleSystem).speedFactor = values!.pointee } property?.threshold = 0.01 }) as! POPAnimatableProperty) speedAnimation.fromValue = 1.0 as NSNumber speedAnimation.toValue = 3.0 as NSNumber speedAnimation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.linear) speedAnimation.duration = 0.8 particles.pop_add(speedAnimation, forKey: "speedFactor") let stretchAnimation = POPBasicAnimation() stretchAnimation.property = (POPAnimatableProperty.property(withName: "stretchFactor", initializer: { property in property?.readBlock = { particleSystem, values in values?.pointee = (particleSystem as! SCNParticleSystem).stretchFactor } property?.writeBlock = { particleSystem, values in (particleSystem as! SCNParticleSystem).stretchFactor = values!.pointee } property?.threshold = 0.01 }) as! POPAnimatableProperty) stretchAnimation.fromValue = 0.05 as NSNumber stretchAnimation.toValue = 0.3 as NSNumber stretchAnimation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.linear) stretchAnimation.duration = 0.8 particles.pop_add(stretchAnimation, forKey: "stretchFactor") } func resetAnimation() { guard self.playing, let scene = self.sceneView.scene, let node = scene.rootNode.childNode(withName: "particles", recursively: false), let particles = node.particleSystems?.first else { return } self.playing = false let speedAnimation = POPBasicAnimation() speedAnimation.property = (POPAnimatableProperty.property(withName: "speedFactor", initializer: { property in property?.readBlock = { particleSystem, values in values?.pointee = (particleSystem as! SCNParticleSystem).speedFactor } property?.writeBlock = { particleSystem, values in (particleSystem as! SCNParticleSystem).speedFactor = values!.pointee } property?.threshold = 0.01 }) as! POPAnimatableProperty) speedAnimation.fromValue = 3.0 as NSNumber speedAnimation.toValue = 1.0 as NSNumber speedAnimation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.linear) speedAnimation.duration = 0.35 particles.pop_add(speedAnimation, forKey: "speedFactor") let stretchAnimation = POPBasicAnimation() stretchAnimation.property = (POPAnimatableProperty.property(withName: "stretchFactor", initializer: { property in property?.readBlock = { particleSystem, values in values?.pointee = (particleSystem as! SCNParticleSystem).stretchFactor } property?.writeBlock = { particleSystem, values in (particleSystem as! SCNParticleSystem).stretchFactor = values!.pointee } property?.threshold = 0.01 }) as! POPAnimatableProperty) stretchAnimation.fromValue = 0.3 as NSNumber stretchAnimation.toValue = 0.05 as NSNumber stretchAnimation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.linear) stretchAnimation.duration = 0.35 particles.pop_add(stretchAnimation, forKey: "stretchFactor") } override func layoutSubviews() { super.layoutSubviews() self.sceneView.frame = CGRect(origin: .zero, size: frame.size) } }