Commit 320db704 authored by toby's avatar toby

mostly working state machine

parent cf9ed1e4
......@@ -8,6 +8,14 @@
import UIKit
struct BGTransition {
let duration: Double
let startColor: UIColor
let endColor: UIColor
}
extension UIView {
func pause() -> Void {
let pausedTime = self.layer.convertTime(CACurrentMediaTime(), fromLayer: nil)
......@@ -25,6 +33,7 @@ extension UIView {
}
}
func degreesToRadians(degrees: CGFloat) -> CGFloat {
return degrees * (3.1415926 / 180)
}
......
......@@ -13,6 +13,7 @@
DA376F141AAD1C4B0071423A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = DA376F131AAD1C4B0071423A /* Images.xcassets */; };
DA376F171AAD1C4B0071423A /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = DA376F151AAD1C4B0071423A /* LaunchScreen.xib */; };
DA376F231AAD1C4B0071423A /* loboTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA376F221AAD1C4B0071423A /* loboTests.swift */; };
DA6CF1091ABF865500270C05 /* StateMachine.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA6CF1081ABF865500270C05 /* StateMachine.swift */; };
DAAE8A531ABE313400DDFA37 /* Utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAAE8A521ABE313400DDFA37 /* Utils.swift */; };
/* End PBXBuildFile section */
......@@ -37,6 +38,7 @@
DA376F1C1AAD1C4B0071423A /* loboTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = loboTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
DA376F211AAD1C4B0071423A /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
DA376F221AAD1C4B0071423A /* loboTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = loboTests.swift; sourceTree = "<group>"; };
DA6CF1081ABF865500270C05 /* StateMachine.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StateMachine.swift; sourceTree = "<group>"; };
DAAE8A521ABE313400DDFA37 /* Utils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Utils.swift; path = ../Utils.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */
......@@ -79,8 +81,9 @@
DA376F091AAD1C4B0071423A /* lobo */ = {
isa = PBXGroup;
children = (
DAAE8A521ABE313400DDFA37 /* Utils.swift */,
DA376F0C1AAD1C4B0071423A /* AppDelegate.swift */,
DA6CF1081ABF865500270C05 /* StateMachine.swift */,
DAAE8A521ABE313400DDFA37 /* Utils.swift */,
DA376F0E1AAD1C4B0071423A /* ViewController.swift */,
DA376F101AAD1C4B0071423A /* Main.storyboard */,
DA376F131AAD1C4B0071423A /* Images.xcassets */,
......@@ -219,6 +222,7 @@
DA376F0F1AAD1C4B0071423A /* ViewController.swift in Sources */,
DA376F0D1AAD1C4B0071423A /* AppDelegate.swift in Sources */,
DAAE8A531ABE313400DDFA37 /* Utils.swift in Sources */,
DA6CF1091ABF865500270C05 /* StateMachine.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
......
//
// StateMachine.swift
// lobo
//
// Created by Toby Padilla on 3/22/15.
// Copyright (c) 2015 Toby Padilla. All rights reserved.
//
import Foundation
protocol StateMachineDelegate: class{
typealias StateType:StateMachineDataSource
func didTransitionFrom(from:StateType, to:StateType)
}
protocol StateMachineDataSource{
func shouldTransitionFrom(from:Self, to:Self)->Should<Self>
}
enum Should<T>{
case Continue, Abort, Redirect(T)
}
class StateMachine<P:StateMachineDelegate>{
private var _state:P.StateType{
didSet{
delegate.didTransitionFrom(oldValue, to: _state)
}
}
unowned let delegate:P
var state:P.StateType{
get{
return _state
}
set{
switch _state.shouldTransitionFrom(_state, to:newValue){
case .Continue:
_state = newValue
case .Redirect(let redirectState):
_state = newValue
self.state = redirectState
case .Abort:
break;
}
}
}
init(initialState:P.StateType, delegate:P){
_state = initialState //set the primitive to avoid calling the delegate.
self.delegate = delegate
}
}
\ No newline at end of file
......@@ -8,52 +8,84 @@
import UIKit
struct BGTransition {
let duration: Double
let startColor: UIColor
let endColor: UIColor
enum BackgroundState:StateMachineDataSource{
case Ready, Animating, Paused, Finished
func shouldTransitionFrom(from:BackgroundState, to: BackgroundState) -> Should<BackgroundState>{
switch (from, to){
case (.Ready, .Animating), (.Paused, .Animating), (.Animating, .Paused), (.Animating, .Finished), (.Paused, .Finished), (.Finished, .Animating):
return .Continue
default:
return .Abort
}
}
}
struct AppState {
var paused: Bool = false
var animating: Bool = false
extension ViewController: StateMachineDelegate {
typealias StateType = BackgroundState
func didTransitionFrom(from: StateType, to: StateType) {
switch (from, to){
case (.Ready, .Animating), (.Finished, .Animating):
animateBackground()
case (.Animating, .Paused):
view.pause()
case (.Paused, .Animating), (.Paused, .Finished):
view.unpause()
case (.Animating, .Finished):
machine.state = .Animating
default:
break
}
}
}
class ViewController: UIViewController {
var animator: UIDynamicAnimator!
var gravity: UIGravityBehavior!
var collision: UICollisionBehavior!
var machine: StateMachine<ViewController>!
var backgroundTransition: BGTransition!
var appState = AppState()
override func viewDidLoad() {
super.viewDidLoad()
// Setup background transition
backgroundTransition = randomTransition()
// backgroundTransition = BGTransition(duration: 5.0, startColor: UIColor.blackColor(), endColor: UIColor.whiteColor())
view.backgroundColor = backgroundTransition.startColor
// Setup barrier
let barrier = UIView(frame: CGRectFromOrigin(view, 0, 40, 130, 20))
barrier.backgroundColor = randomColor()
view.addSubview(barrier)
// Setup gravity
gravity = UIGravityBehavior()
gravity.angle = degreesToRadians(90)
gravity.magnitude = CGFloat(0.1)
// Setup collisions
collision = UICollisionBehavior()
collision.translatesReferenceBoundsIntoBoundary = true
collision.addBoundaryWithIdentifier("barrier", forPath: UIBezierPath(rect: barrier.frame))
// Setup animator
animator = UIDynamicAnimator(referenceView: view)
animator.addBehavior(gravity)
animator.addBehavior(collision)
// Setup gestures
let hold = UILongPressGestureRecognizer(target: self, action: Selector("backgroundHeld:"))
view.addGestureRecognizer(hold)
// Setup state machine
machine = StateMachine(initialState: .Ready, delegate: self)
}
override func didReceiveMemoryWarning() {
......@@ -61,8 +93,8 @@ class ViewController: UIViewController {
// Dispose of any resources that can be recreated.
}
func animateBackground() -> Void {
self.appState.animating = true
private func animateBackground() -> Void {
println("animate background")
UIView.animateWithDuration(
self.backgroundTransition.duration,
delay: 0.0,
......@@ -72,13 +104,10 @@ class ViewController: UIViewController {
},
completion: {
(finished: Bool) -> Void in
self.appState.animating = false
self.backgroundTransition = randomTransition()
UIView.animateWithDuration(
0.25,
delay: 0.0,
options: UIViewAnimationOptions.CurveEaseInOut | UIViewAnimationOptions.AllowUserInteraction,
options: UIViewAnimationOptions.CurveEaseInOut,
animations: {
self.view!.backgroundColor = UIColor.whiteColor()
......@@ -89,16 +118,14 @@ class ViewController: UIViewController {
UIView.animateWithDuration(
0.25,
delay: 0.0,
options: UIViewAnimationOptions.CurveEaseInOut | UIViewAnimationOptions.AllowUserInteraction,
options: UIViewAnimationOptions.CurveEaseInOut,
animations: {
self.view!.backgroundColor = self.backgroundTransition.startColor
},
completion: {
(finished: Bool) -> Void in
if(!self.appState.paused && !self.appState.animating) {
self.animateBackground()
}
self.machine.state = .Finished
})
}
)
......@@ -109,20 +136,10 @@ class ViewController: UIViewController {
@IBAction func backgroundHeld(hold: UILongPressGestureRecognizer) {
switch hold.state {
case UIGestureRecognizerState.Began:
if(!self.appState.paused){
self.animateBackground()
} else {
self.appState.animating = true
self.appState.paused = false
self.view.unpause()
}
machine.state = .Animating
case UIGestureRecognizerState.Ended:
if(self.appState.animating == true) {
self.appState.paused = true
self.appState.animating = false
self.view.pause()
}
machine.state = .Paused
default:
break
......
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