@@ -18,34 +18,85 @@ class ViewController: UIViewController, MetaballDataSource {
1818 override func viewDidLoad() {
1919 super.viewDidLoad()
2020
21+ view.backgroundColor = UIColor.whiteColor()
22+
2123 let recognizer = UIPanGestureRecognizer(target: self, action: "handlePan:")
2224 view.addGestureRecognizer(recognizer)
2325
24− let metaballs = [CGPoint(x: 70, y: 70), CGPoint(x: 270, y: 70), CGPoint(x: 270, y: 470), CGPoint(x: 70, y: 470)].map {
25− Metaball(position: $0)
26+ var positions = [CGPoint]()
27+ positions.append(CGPoint(x: Double(screenWidth) / 2, y: Double(screenHeight) / 2))
28+ for i in 1...5 {
29+ let sine = sin(Double(i) * 2 * M_PI / 5)
30+ let cosine = cos(Double(i) * 2 * M_PI / 5)
31+ let radius: Double = 150
32+ let x = Double(screenWidth) / 2 + sine * radius
33+ let y = Double(screenHeight) / 2 + cosine * radius
34+ positions.append(CGPoint(x: x, y: y))
2635 }
36+
37+ let colors =
38+ [UIColor(red255: 110, green: 220, blue: 220, alpha: 1.0),
39+ UIColor(red255: 250, green: 235, blue: 50, alpha: 1.0),
40+ UIColor(red255: 110, green: 220, blue: 220, alpha: 1.0),
41+ UIColor(red255: 90, green: 170, blue: 170, alpha: 1.0),
42+ UIColor(red255: 90, green: 170, blue: 170, alpha: 1.0),
43+ UIColor(red255: 110, green: 220, blue: 220, alpha: 1.0)]
44+ let metaballs = zip(positions, colors).map { Metaball(position: $0.0, color: $0.1) }
45+
2746 metaballGraph = Graph(vertices: metaballs)
28− metaballGraph.addEdge(0, 1)
29− metaballGraph.addEdge(0, 3)
30− metaballGraph.addEdge(1, 2)
31− metaballGraph.addEdge(1, 3)
32− metaballGraph.addEdge(2, 3)
33−
34− let border = 20
35− let metaballViewFrame = CGRect(x: border / 2, y: border / 2, width: width, height: height)
47+
48+ let metaballViewFrame = screenRect
3649 renderer = MetalMetaballRenderer(dataSource: self, frame: metaballViewFrame)
3750 metaballView = renderer.targetView
38−
39− let bigView = UIView(frame: CGRect(x: 10, y: 70, width: width + border, height: height + border))
40− bigView.backgroundColor = UIColor.redColor()
41− bigView.addSubview(metaballView)
42− view.addSubview(bigView)
51+ view.addSubview(metaballView)
4352
4453 for metaball in metaballs {
4554 metaballView.addSubview(metaball)
4655 }
4756
48− addEdge(0, 2)
57+ delay(1.0) {
58+ self.addEdge(0, 1)
59+ self.addEdge(0, 2)
60+ self.addEdge(0, 3)
61+ self.addEdge(0, 4)
62+ self.addEdge(0, 5)
63+ }
64+
65+ delay(2.3) {
66+ self.removeEdge(0, 1)
67+ self.removeEdge(0, 2)
68+ self.removeEdge(0, 3)
69+ self.removeEdge(0, 4)
70+ self.removeEdge(0, 5)
71+ }
72+
73+ delay(4) {
74+ for i in 1...5 {
75+ UIView.animateWithDuration(1.0, delay: 0, options: UIViewAnimationOptions.CurveEaseInOut, animations: { () -> Void in
76+ let sine = sin(Double(i) * 2 * M_PI / 5)
77+ let cosine = cos(Double(i) * 2 * M_PI / 5)
78+ let radius: Double = 85
79+ let x = Double(screenWidth) / 2 + sine * radius
80+ let y = Double(screenHeight) / 2 + cosine * radius
81+ let metaball = metaballs[i]
82+ self.animateMetaball(metaball, toPoint: CGPoint(x: x, y: y))
83+ }, completion: nil)
84+ }
85+ }
86+
87+ delay(6) { () -> () in
88+ for i in 1...5 {
89+ UIView.animateWithDuration(1.0, delay: 0, usingSpringWithDamping: 0.5, initialSpringVelocity: 0, options: UIViewAnimationOptions.CurveEaseInOut, animations: { () -> Void in
90+ let sine = sin(Double(i) * 2 * M_PI / 5)
91+ let cosine = cos(Double(i) * 2 * M_PI / 5)
92+ let radius: Double = 150
93+ let x = Double(screenWidth) / 2 + sine * radius
94+ let y = Double(screenHeight) / 2 + cosine * radius
95+ let metaball = metaballs[i]
96+ self.animateMetaball(metaball, toPoint: CGPoint(x: x, y: y))
97+ }, completion: nil)
98+ }
99+ }
49100
50101 renderer.state = .Running
51102 }
@@ -58,6 +109,33 @@ class ViewController: UIViewController, MetaballDataSource {
58109 animateEdge(i, j, fadeIn: false)
59110 }
60111
112+ func animateMetaball(metaball: Metaball, toPoint destination: CGPoint) {
113+ let parameters = VertexAnimationParameters(startDate: NSDate(), duration: 1.0, origin: metaball.center, destination: destination, metaball: metaball)
114+ NSTimer.scheduledTimerWithTimeInterval(1.0 / 60.0, target: self, selector: "animateMetaballWithTimer:", userInfo: parameters, repeats: true)
115+ }
116+
117+ func animateMetaball(withTimer timer: NSTimer) {
118+ guard let userInfo = timer.userInfo as? VertexAnimationParameters else { preconditionFailure() }
119+ let (animationStart, duration, origin, destination, metaball) = (userInfo).unpack()
120+
121+ let now = NSDate()
122+ var timeElapsed = Float(now.timeIntervalSinceDate(animationStart))
123+
124+ if timeElapsed > duration {
125+ timer.invalidate()
126+ timeElapsed = duration
127+ }
128+
129+ let linearValue = timeElapsed / duration
130+ let interpolatedValue = interpolateSmooth(linearValue)
131+ print(interpolatedValue)
132+
133+ let position = origin + ((destination - origin) * interpolatedValue)
134+ metaball.center = position
135+
136+ renderer.state = .Running
137+ }
138+
61139 func animateEdge(i: Int, _ j: Int, fadeIn: Bool) {
62140 let parameters = EdgeAnimationParameters(startDate: NSDate(), duration: edgeAnimationDuration, fadeIn: fadeIn, i: i, j: j)
63141 NSTimer.scheduledTimerWithTimeInterval(1.0 / 60.0, target: self, selector: "animateEdgeWithTimer:", userInfo: parameters, repeats: true)
@@ -107,18 +185,3 @@ class ViewController: UIViewController, MetaballDataSource {
107185 }
108186
109187}
110−
111−class Metaball: UIView {
112−
113− init(position: CGPoint) {
114− super.init(frame: CGRect.zero)
115−
116− size = CGSize(50)
117− middle = position
118− backgroundColor = UIColor(randomFlatColorOfShadeStyle: .Light)
119− }
120−
121− required init?(coder aDecoder: NSCoder) {
122− super.init(coder: aDecoder)
123− }
124−}