├── Example ├── StarWarsAnimations │ ├── Assets.xcassets │ │ ├── Contents.json │ │ ├── spark.imageset │ │ │ ├── spark.png │ │ │ └── Contents.json │ │ ├── Knob_ON.imageset │ │ │ ├── Knob_ON.png │ │ │ ├── Knob_ON@2x.png │ │ │ ├── Knob_ON@3x.png │ │ │ └── Contents.json │ │ ├── Knob_OFF.imageset │ │ │ ├── Knob_OFF.png │ │ │ ├── Knob_OFF@2x.png │ │ │ ├── Knob_OFF@3x.png │ │ │ └── Contents.json │ │ ├── Menu_icn.imageset │ │ │ ├── Menu_icn.png │ │ │ ├── Menu_icn@2x.png │ │ │ ├── Menu_icn@3x.png │ │ │ └── Contents.json │ │ ├── Track_ON.imageset │ │ │ ├── Track_ON.png │ │ │ ├── Track_ON@2x.png │ │ │ ├── Track_ON@3x.png │ │ │ └── Contents.json │ │ ├── AppIcon.appiconset │ │ │ ├── Icon-60@2x.png │ │ │ ├── Icon-60@3x.png │ │ │ ├── Icon-Small@2x.png │ │ │ ├── Icon-Small@3x.png │ │ │ ├── Icon-Small-40@2x.png │ │ │ ├── Icon-Small-40@3x.png │ │ │ └── Contents.json │ │ ├── Close_icn.imageset │ │ │ ├── Close_icn.png │ │ │ ├── Close_icn@2x.png │ │ │ ├── Close_icn@3x.png │ │ │ └── Contents.json │ │ ├── Track_OFF.imageset │ │ │ ├── Track_OFF.png │ │ │ ├── Track_OFF@2x.png │ │ │ ├── Track_OFF@3x.png │ │ │ └── Contents.json │ │ ├── Photo_dark.imageset │ │ │ ├── Photo_dark.png │ │ │ ├── Photo_dark@2x.png │ │ │ ├── Photo_dark@3x.png │ │ │ └── Contents.json │ │ ├── Photo_light.imageset │ │ │ ├── Photo_light.png │ │ │ ├── Photo_light@2x.png │ │ │ ├── Photo_light@3x.png │ │ │ └── Contents.json │ │ ├── Separator_dark.imageset │ │ │ ├── Separator_dark.png │ │ │ ├── Separator_dark@2x.png │ │ │ ├── Separator_dark@3x.png │ │ │ └── Contents.json │ │ ├── star_wars_logo.imageset │ │ │ ├── star_wars_logo.png │ │ │ ├── star_wars_logo@2x.png │ │ │ ├── star_wars_logo@3x.png │ │ │ └── Contents.json │ │ ├── Separator_light.imageset │ │ │ ├── Separator_light.png │ │ │ ├── Separator_light@2x.png │ │ │ ├── Separator_light@3x.png │ │ │ └── Contents.json │ │ ├── Radio-dark_Active.imageset │ │ │ ├── Radio-dark_Active.png │ │ │ ├── Radio-dark_Active@2x.png │ │ │ ├── Radio-dark_Active@3x.png │ │ │ └── Contents.json │ │ ├── Radio-light_Active.imageset │ │ │ ├── Radio-light_Active.png │ │ │ ├── Radio-light_Active@2x.png │ │ │ ├── Radio-light_Active@3x.png │ │ │ └── Contents.json │ │ ├── Radio-dark_Inactive.imageset │ │ │ ├── Radio-dark_Inactive.png │ │ │ ├── Radio-dark_Inactive@2x.png │ │ │ ├── Radio-dark_Inactive@3x.png │ │ │ └── Contents.json │ │ └── Radio-light_Inactive.imageset │ │ │ ├── Radio-light_Inactive.png │ │ │ ├── Radio-light_Inactive@2x.png │ │ │ ├── Radio-light_Inactive@3x.png │ │ │ └── Contents.json │ ├── Resources │ │ ├── GothaProReg.otf │ │ └── yalantis_badge.png │ ├── Misc │ │ └── AppDelegate.swift │ ├── Circular │ │ ├── AnimationDelegate.swift │ │ └── CircularRevealAnimator.swift │ ├── Extension │ │ ├── UIView+IBInspectable.swift │ │ ├── UIView+CircularAnimation.swift │ │ └── UIColor+String.swift │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ ├── Info.plist │ ├── View │ │ ├── ProfileButton.swift │ │ └── StarsOverlay.swift │ ├── ViewModel │ │ └── SettingsTheme.swift │ └── Controller │ │ ├── MainSettingsViewController.swift │ │ ├── IntroViewController.swift │ │ └── SettingsViewController.swift ├── StarWarsAnimations.xcodeproj │ ├── project.xcworkspace │ │ └── contents.xcworkspacedata │ └── project.pbxproj └── StarWars │ ├── StarWars.h │ └── Info.plist ├── .gitignore ├── StarWars.podspec ├── LICENSE ├── StarWars ├── StarWarsGLAnimator │ ├── SpriteRender.swift │ ├── Sprite.swift │ ├── ViewTexture.swift │ ├── Vector2.swift │ └── StarWarsGLAnimator.swift ├── StarWarsUIViewAnimator │ └── StarWarsUIViewAnimator.swift └── StarWarsUIDynamicAnimator │ └── StarWarsUIDynamicAnimator.swift └── README.md /Example/StarWarsAnimations/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /Example/StarWarsAnimations/Resources/GothaProReg.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/animations/StarWars.iOS/master/Example/StarWarsAnimations/Resources/GothaProReg.otf -------------------------------------------------------------------------------- /Example/StarWarsAnimations/Resources/yalantis_badge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/animations/StarWars.iOS/master/Example/StarWarsAnimations/Resources/yalantis_badge.png -------------------------------------------------------------------------------- /Example/StarWarsAnimations/Assets.xcassets/spark.imageset/spark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/animations/StarWars.iOS/master/Example/StarWarsAnimations/Assets.xcassets/spark.imageset/spark.png -------------------------------------------------------------------------------- /Example/StarWarsAnimations/Assets.xcassets/Knob_ON.imageset/Knob_ON.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/animations/StarWars.iOS/master/Example/StarWarsAnimations/Assets.xcassets/Knob_ON.imageset/Knob_ON.png -------------------------------------------------------------------------------- /Example/StarWarsAnimations/Assets.xcassets/Knob_OFF.imageset/Knob_OFF.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/animations/StarWars.iOS/master/Example/StarWarsAnimations/Assets.xcassets/Knob_OFF.imageset/Knob_OFF.png -------------------------------------------------------------------------------- /Example/StarWarsAnimations/Assets.xcassets/Menu_icn.imageset/Menu_icn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/animations/StarWars.iOS/master/Example/StarWarsAnimations/Assets.xcassets/Menu_icn.imageset/Menu_icn.png -------------------------------------------------------------------------------- /Example/StarWarsAnimations/Assets.xcassets/Track_ON.imageset/Track_ON.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/animations/StarWars.iOS/master/Example/StarWarsAnimations/Assets.xcassets/Track_ON.imageset/Track_ON.png -------------------------------------------------------------------------------- /Example/StarWarsAnimations/Assets.xcassets/AppIcon.appiconset/Icon-60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/animations/StarWars.iOS/master/Example/StarWarsAnimations/Assets.xcassets/AppIcon.appiconset/Icon-60@2x.png -------------------------------------------------------------------------------- /Example/StarWarsAnimations/Assets.xcassets/AppIcon.appiconset/Icon-60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/animations/StarWars.iOS/master/Example/StarWarsAnimations/Assets.xcassets/AppIcon.appiconset/Icon-60@3x.png -------------------------------------------------------------------------------- /Example/StarWarsAnimations/Assets.xcassets/Close_icn.imageset/Close_icn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/animations/StarWars.iOS/master/Example/StarWarsAnimations/Assets.xcassets/Close_icn.imageset/Close_icn.png -------------------------------------------------------------------------------- /Example/StarWarsAnimations/Assets.xcassets/Knob_OFF.imageset/Knob_OFF@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/animations/StarWars.iOS/master/Example/StarWarsAnimations/Assets.xcassets/Knob_OFF.imageset/Knob_OFF@2x.png -------------------------------------------------------------------------------- /Example/StarWarsAnimations/Assets.xcassets/Knob_OFF.imageset/Knob_OFF@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/animations/StarWars.iOS/master/Example/StarWarsAnimations/Assets.xcassets/Knob_OFF.imageset/Knob_OFF@3x.png -------------------------------------------------------------------------------- /Example/StarWarsAnimations/Assets.xcassets/Knob_ON.imageset/Knob_ON@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/animations/StarWars.iOS/master/Example/StarWarsAnimations/Assets.xcassets/Knob_ON.imageset/Knob_ON@2x.png -------------------------------------------------------------------------------- /Example/StarWarsAnimations/Assets.xcassets/Knob_ON.imageset/Knob_ON@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/animations/StarWars.iOS/master/Example/StarWarsAnimations/Assets.xcassets/Knob_ON.imageset/Knob_ON@3x.png -------------------------------------------------------------------------------- /Example/StarWarsAnimations/Assets.xcassets/Menu_icn.imageset/Menu_icn@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/animations/StarWars.iOS/master/Example/StarWarsAnimations/Assets.xcassets/Menu_icn.imageset/Menu_icn@2x.png -------------------------------------------------------------------------------- /Example/StarWarsAnimations/Assets.xcassets/Menu_icn.imageset/Menu_icn@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/animations/StarWars.iOS/master/Example/StarWarsAnimations/Assets.xcassets/Menu_icn.imageset/Menu_icn@3x.png -------------------------------------------------------------------------------- /Example/StarWarsAnimations/Assets.xcassets/Track_OFF.imageset/Track_OFF.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/animations/StarWars.iOS/master/Example/StarWarsAnimations/Assets.xcassets/Track_OFF.imageset/Track_OFF.png -------------------------------------------------------------------------------- /Example/StarWarsAnimations/Assets.xcassets/Track_ON.imageset/Track_ON@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/animations/StarWars.iOS/master/Example/StarWarsAnimations/Assets.xcassets/Track_ON.imageset/Track_ON@2x.png -------------------------------------------------------------------------------- /Example/StarWarsAnimations/Assets.xcassets/Track_ON.imageset/Track_ON@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/animations/StarWars.iOS/master/Example/StarWarsAnimations/Assets.xcassets/Track_ON.imageset/Track_ON@3x.png -------------------------------------------------------------------------------- /Example/StarWarsAnimations/Assets.xcassets/Close_icn.imageset/Close_icn@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/animations/StarWars.iOS/master/Example/StarWarsAnimations/Assets.xcassets/Close_icn.imageset/Close_icn@2x.png -------------------------------------------------------------------------------- /Example/StarWarsAnimations/Assets.xcassets/Close_icn.imageset/Close_icn@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/animations/StarWars.iOS/master/Example/StarWarsAnimations/Assets.xcassets/Close_icn.imageset/Close_icn@3x.png -------------------------------------------------------------------------------- /Example/StarWarsAnimations/Assets.xcassets/Photo_dark.imageset/Photo_dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/animations/StarWars.iOS/master/Example/StarWarsAnimations/Assets.xcassets/Photo_dark.imageset/Photo_dark.png -------------------------------------------------------------------------------- /Example/StarWarsAnimations/Assets.xcassets/Track_OFF.imageset/Track_OFF@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/animations/StarWars.iOS/master/Example/StarWarsAnimations/Assets.xcassets/Track_OFF.imageset/Track_OFF@2x.png -------------------------------------------------------------------------------- /Example/StarWarsAnimations/Assets.xcassets/Track_OFF.imageset/Track_OFF@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/animations/StarWars.iOS/master/Example/StarWarsAnimations/Assets.xcassets/Track_OFF.imageset/Track_OFF@3x.png -------------------------------------------------------------------------------- /Example/StarWarsAnimations/Assets.xcassets/AppIcon.appiconset/Icon-Small@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/animations/StarWars.iOS/master/Example/StarWarsAnimations/Assets.xcassets/AppIcon.appiconset/Icon-Small@2x.png -------------------------------------------------------------------------------- /Example/StarWarsAnimations/Assets.xcassets/AppIcon.appiconset/Icon-Small@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/animations/StarWars.iOS/master/Example/StarWarsAnimations/Assets.xcassets/AppIcon.appiconset/Icon-Small@3x.png -------------------------------------------------------------------------------- /Example/StarWarsAnimations/Assets.xcassets/Photo_dark.imageset/Photo_dark@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/animations/StarWars.iOS/master/Example/StarWarsAnimations/Assets.xcassets/Photo_dark.imageset/Photo_dark@2x.png -------------------------------------------------------------------------------- /Example/StarWarsAnimations/Assets.xcassets/Photo_dark.imageset/Photo_dark@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/animations/StarWars.iOS/master/Example/StarWarsAnimations/Assets.xcassets/Photo_dark.imageset/Photo_dark@3x.png -------------------------------------------------------------------------------- /Example/StarWarsAnimations/Assets.xcassets/Photo_light.imageset/Photo_light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/animations/StarWars.iOS/master/Example/StarWarsAnimations/Assets.xcassets/Photo_light.imageset/Photo_light.png -------------------------------------------------------------------------------- /Example/StarWarsAnimations/Assets.xcassets/AppIcon.appiconset/Icon-Small-40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/animations/StarWars.iOS/master/Example/StarWarsAnimations/Assets.xcassets/AppIcon.appiconset/Icon-Small-40@2x.png -------------------------------------------------------------------------------- /Example/StarWarsAnimations/Assets.xcassets/AppIcon.appiconset/Icon-Small-40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/animations/StarWars.iOS/master/Example/StarWarsAnimations/Assets.xcassets/AppIcon.appiconset/Icon-Small-40@3x.png -------------------------------------------------------------------------------- /Example/StarWarsAnimations/Assets.xcassets/Photo_light.imageset/Photo_light@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/animations/StarWars.iOS/master/Example/StarWarsAnimations/Assets.xcassets/Photo_light.imageset/Photo_light@2x.png -------------------------------------------------------------------------------- /Example/StarWarsAnimations/Assets.xcassets/Photo_light.imageset/Photo_light@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/animations/StarWars.iOS/master/Example/StarWarsAnimations/Assets.xcassets/Photo_light.imageset/Photo_light@3x.png -------------------------------------------------------------------------------- /Example/StarWarsAnimations/Assets.xcassets/Separator_dark.imageset/Separator_dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/animations/StarWars.iOS/master/Example/StarWarsAnimations/Assets.xcassets/Separator_dark.imageset/Separator_dark.png -------------------------------------------------------------------------------- /Example/StarWarsAnimations/Assets.xcassets/star_wars_logo.imageset/star_wars_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/animations/StarWars.iOS/master/Example/StarWarsAnimations/Assets.xcassets/star_wars_logo.imageset/star_wars_logo.png -------------------------------------------------------------------------------- /Example/StarWarsAnimations/Assets.xcassets/Separator_dark.imageset/Separator_dark@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/animations/StarWars.iOS/master/Example/StarWarsAnimations/Assets.xcassets/Separator_dark.imageset/Separator_dark@2x.png -------------------------------------------------------------------------------- /Example/StarWarsAnimations/Assets.xcassets/Separator_dark.imageset/Separator_dark@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/animations/StarWars.iOS/master/Example/StarWarsAnimations/Assets.xcassets/Separator_dark.imageset/Separator_dark@3x.png -------------------------------------------------------------------------------- /Example/StarWarsAnimations/Assets.xcassets/Separator_light.imageset/Separator_light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/animations/StarWars.iOS/master/Example/StarWarsAnimations/Assets.xcassets/Separator_light.imageset/Separator_light.png -------------------------------------------------------------------------------- /Example/StarWarsAnimations/Assets.xcassets/star_wars_logo.imageset/star_wars_logo@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/animations/StarWars.iOS/master/Example/StarWarsAnimations/Assets.xcassets/star_wars_logo.imageset/star_wars_logo@2x.png -------------------------------------------------------------------------------- /Example/StarWarsAnimations/Assets.xcassets/star_wars_logo.imageset/star_wars_logo@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/animations/StarWars.iOS/master/Example/StarWarsAnimations/Assets.xcassets/star_wars_logo.imageset/star_wars_logo@3x.png -------------------------------------------------------------------------------- /Example/StarWarsAnimations/Assets.xcassets/Radio-dark_Active.imageset/Radio-dark_Active.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/animations/StarWars.iOS/master/Example/StarWarsAnimations/Assets.xcassets/Radio-dark_Active.imageset/Radio-dark_Active.png -------------------------------------------------------------------------------- /Example/StarWarsAnimations/Assets.xcassets/Separator_light.imageset/Separator_light@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/animations/StarWars.iOS/master/Example/StarWarsAnimations/Assets.xcassets/Separator_light.imageset/Separator_light@2x.png -------------------------------------------------------------------------------- /Example/StarWarsAnimations/Assets.xcassets/Separator_light.imageset/Separator_light@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/animations/StarWars.iOS/master/Example/StarWarsAnimations/Assets.xcassets/Separator_light.imageset/Separator_light@3x.png -------------------------------------------------------------------------------- /Example/StarWarsAnimations/Assets.xcassets/Radio-light_Active.imageset/Radio-light_Active.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/animations/StarWars.iOS/master/Example/StarWarsAnimations/Assets.xcassets/Radio-light_Active.imageset/Radio-light_Active.png -------------------------------------------------------------------------------- /Example/StarWarsAnimations/Assets.xcassets/Radio-dark_Active.imageset/Radio-dark_Active@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/animations/StarWars.iOS/master/Example/StarWarsAnimations/Assets.xcassets/Radio-dark_Active.imageset/Radio-dark_Active@2x.png -------------------------------------------------------------------------------- /Example/StarWarsAnimations/Assets.xcassets/Radio-dark_Active.imageset/Radio-dark_Active@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/animations/StarWars.iOS/master/Example/StarWarsAnimations/Assets.xcassets/Radio-dark_Active.imageset/Radio-dark_Active@3x.png -------------------------------------------------------------------------------- /Example/StarWarsAnimations/Assets.xcassets/Radio-dark_Inactive.imageset/Radio-dark_Inactive.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/animations/StarWars.iOS/master/Example/StarWarsAnimations/Assets.xcassets/Radio-dark_Inactive.imageset/Radio-dark_Inactive.png -------------------------------------------------------------------------------- /Example/StarWarsAnimations/Assets.xcassets/Radio-light_Active.imageset/Radio-light_Active@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/animations/StarWars.iOS/master/Example/StarWarsAnimations/Assets.xcassets/Radio-light_Active.imageset/Radio-light_Active@2x.png -------------------------------------------------------------------------------- /Example/StarWarsAnimations/Assets.xcassets/Radio-light_Active.imageset/Radio-light_Active@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/animations/StarWars.iOS/master/Example/StarWarsAnimations/Assets.xcassets/Radio-light_Active.imageset/Radio-light_Active@3x.png -------------------------------------------------------------------------------- /Example/StarWarsAnimations/Assets.xcassets/Radio-dark_Inactive.imageset/Radio-dark_Inactive@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/animations/StarWars.iOS/master/Example/StarWarsAnimations/Assets.xcassets/Radio-dark_Inactive.imageset/Radio-dark_Inactive@2x.png -------------------------------------------------------------------------------- /Example/StarWarsAnimations/Assets.xcassets/Radio-dark_Inactive.imageset/Radio-dark_Inactive@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/animations/StarWars.iOS/master/Example/StarWarsAnimations/Assets.xcassets/Radio-dark_Inactive.imageset/Radio-dark_Inactive@3x.png -------------------------------------------------------------------------------- /Example/StarWarsAnimations/Assets.xcassets/Radio-light_Inactive.imageset/Radio-light_Inactive.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/animations/StarWars.iOS/master/Example/StarWarsAnimations/Assets.xcassets/Radio-light_Inactive.imageset/Radio-light_Inactive.png -------------------------------------------------------------------------------- /Example/StarWarsAnimations/Assets.xcassets/Radio-light_Inactive.imageset/Radio-light_Inactive@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/animations/StarWars.iOS/master/Example/StarWarsAnimations/Assets.xcassets/Radio-light_Inactive.imageset/Radio-light_Inactive@2x.png -------------------------------------------------------------------------------- /Example/StarWarsAnimations/Assets.xcassets/Radio-light_Inactive.imageset/Radio-light_Inactive@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/animations/StarWars.iOS/master/Example/StarWarsAnimations/Assets.xcassets/Radio-light_Inactive.imageset/Radio-light_Inactive@3x.png -------------------------------------------------------------------------------- /Example/StarWarsAnimations.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Example/StarWarsAnimations/Misc/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // StarWarsAnimations 4 | // 5 | // Created by Artem Sidorenko on 9/11/15. 6 | // Copyright © 2015 Yalantis. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | var window: UIWindow? 14 | } 15 | 16 | -------------------------------------------------------------------------------- /Example/StarWarsAnimations/Assets.xcassets/spark.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "spark.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Example/StarWarsAnimations/Circular/AnimationDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2014 Yalantis 3 | // Licensed under the MIT license: http://opensource.org/licenses/MIT 4 | // 5 | 6 | import QuartzCore 7 | 8 | class AnimationDelegate { 9 | private let completion: () -> Void 10 | 11 | init(completion: () -> Void) { 12 | self.completion = completion 13 | } 14 | 15 | dynamic func animationDidStop(_: CAAnimation, finished: Bool) { 16 | completion() 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Example/StarWarsAnimations/Assets.xcassets/Knob_ON.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Knob_ON.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "Knob_ON@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "Knob_ON@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /Example/StarWarsAnimations/Assets.xcassets/Knob_OFF.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Knob_OFF.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "Knob_OFF@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "Knob_OFF@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /Example/StarWarsAnimations/Assets.xcassets/Menu_icn.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Menu_icn.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "Menu_icn@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "Menu_icn@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /Example/StarWarsAnimations/Assets.xcassets/Track_ON.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Track_ON.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "Track_ON@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "Track_ON@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /Example/StarWarsAnimations/Assets.xcassets/Close_icn.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Close_icn.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "Close_icn@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "Close_icn@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /Example/StarWarsAnimations/Assets.xcassets/Track_OFF.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Track_OFF.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "Track_OFF@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "Track_OFF@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /Example/StarWarsAnimations/Assets.xcassets/Photo_dark.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Photo_dark.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "Photo_dark@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "Photo_dark@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /Example/StarWarsAnimations/Assets.xcassets/Photo_light.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Photo_light.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "Photo_light@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "Photo_light@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /Example/StarWarsAnimations/Assets.xcassets/Separator_dark.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Separator_dark.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "Separator_dark@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "Separator_dark@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /Example/StarWarsAnimations/Assets.xcassets/star_wars_logo.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "star_wars_logo.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "star_wars_logo@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "star_wars_logo@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /Example/StarWarsAnimations/Assets.xcassets/Separator_light.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Separator_light.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "Separator_light@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "Separator_light@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /Example/StarWarsAnimations/Assets.xcassets/Radio-dark_Active.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Radio-dark_Active.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "Radio-dark_Active@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "Radio-dark_Active@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /Example/StarWars/StarWars.h: -------------------------------------------------------------------------------- 1 | // 2 | // StarWars.h 3 | // StarWars 4 | // 5 | // Created by Artem Sidorenko on 10/20/15. 6 | // Copyright © 2015 Yalantis. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | //! Project version number for StarWars. 12 | FOUNDATION_EXPORT double StarWarsVersionNumber; 13 | 14 | //! Project version string for StarWars. 15 | FOUNDATION_EXPORT const unsigned char StarWarsVersionString[]; 16 | 17 | // In this header, you should import all the public headers of your framework using statements like #import 18 | 19 | 20 | -------------------------------------------------------------------------------- /Example/StarWarsAnimations/Assets.xcassets/Radio-dark_Inactive.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Radio-dark_Inactive.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "Radio-dark_Inactive@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "Radio-dark_Inactive@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /Example/StarWarsAnimations/Assets.xcassets/Radio-light_Inactive.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Radio-light_Inactive.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "Radio-light_Inactive@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "Radio-light_Inactive@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /Example/StarWarsAnimations/Assets.xcassets/Radio-light_Active.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Radio-light_Active.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "Radio-light_Active@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "Radio-light_Active@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | }, 23 | "properties" : { 24 | "template-rendering-intent" : "template" 25 | } 26 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | build/ 4 | *.pbxuser 5 | !default.pbxuser 6 | *.mode1v3 7 | !default.mode1v3 8 | *.mode2v3 9 | !default.mode2v3 10 | *.perspectivev3 11 | !default.perspectivev3 12 | xcuserdata 13 | *.xccheckout 14 | *.moved-aside 15 | DerivedData 16 | *.hmap 17 | *.ipa 18 | *.xcuserstate 19 | 20 | # CocoaPods 21 | # 22 | # We recommend against adding the Pods directory to your .gitignore. However 23 | # you should judge for yourself, the pros and cons are mentioned at: 24 | # http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control 25 | # 26 | # Pods/ 27 | 28 | # Carthage 29 | # 30 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 31 | # Carthage/Checkouts 32 | 33 | Carthage/Build 34 | -------------------------------------------------------------------------------- /StarWars.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | 3 | s.name = "StarWars" 4 | s.version = "1.0" 5 | s.summary = "This component implements transition animation to crumble view-controller into tiny pieces" 6 | 7 | s.homepage = "https://yalantis.com/blog/uidynamics-uikit-or-opengl-3-types-of-ios-animations-for-the-star-wars/" 8 | 9 | s.license = { :type => "MIT", :file => "LICENSE" } 10 | 11 | s.author = "Yalantis" 12 | s.social_media_url = "https://twitter.com/yalantis" 13 | 14 | s.platform = :ios, "8.0" 15 | s.ios.deployment_target = "8.0" 16 | 17 | 18 | s.source = { :git => "https://github.com/Yalantis/StarWars.iOS.git", :tag => s.version.to_s } 19 | s.source_files = "StarWars/StarWarsGLAnimator/*.swift" 20 | s.module_name = "StarWars" 21 | s.requires_arc = true 22 | 23 | end 24 | -------------------------------------------------------------------------------- /Example/StarWars/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(CURRENT_PROJECT_VERSION) 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Example/StarWarsAnimations/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "29x29", 5 | "idiom" : "iphone", 6 | "filename" : "Icon-Small@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "29x29", 11 | "idiom" : "iphone", 12 | "filename" : "Icon-Small@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "40x40", 17 | "idiom" : "iphone", 18 | "filename" : "Icon-Small-40@2x.png", 19 | "scale" : "2x" 20 | }, 21 | { 22 | "size" : "40x40", 23 | "idiom" : "iphone", 24 | "filename" : "Icon-Small-40@3x.png", 25 | "scale" : "3x" 26 | }, 27 | { 28 | "size" : "60x60", 29 | "idiom" : "iphone", 30 | "filename" : "Icon-60@2x.png", 31 | "scale" : "2x" 32 | }, 33 | { 34 | "size" : "60x60", 35 | "idiom" : "iphone", 36 | "filename" : "Icon-60@3x.png", 37 | "scale" : "3x" 38 | } 39 | ], 40 | "info" : { 41 | "version" : 1, 42 | "author" : "xcode" 43 | } 44 | } -------------------------------------------------------------------------------- /Example/StarWarsAnimations/Extension/UIView+IBInspectable.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+IBInspectable.swift 3 | // StarWarsAnimations 4 | // 5 | // Created by Artem Sidorenko on 10/5/15. 6 | // Copyright © 2015 Yalantis. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | extension UIView { 12 | 13 | @IBInspectable 14 | var cornerRadius: CGFloat { 15 | get { 16 | return layer.cornerRadius 17 | } 18 | set { 19 | layer.cornerRadius = newValue 20 | } 21 | } 22 | 23 | @IBInspectable 24 | var borderWidth: CGFloat { 25 | get { 26 | return layer.borderWidth 27 | } 28 | set { 29 | layer.borderWidth = newValue 30 | } 31 | } 32 | 33 | @IBInspectable 34 | var borderColor: UIColor? { 35 | get { 36 | guard let color = layer.borderColor else { return nil } 37 | return UIColor(CGColor: color) 38 | } 39 | set { 40 | layer.borderColor = newValue?.CGColor 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Yalantis 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /Example/StarWarsAnimations/Extension/UIView+CircularAnimation.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+CircularAnimation.swift 3 | // StarWarsAnimations 4 | // 5 | // Created by Artem Sidorenko on 10/5/15. 6 | // Copyright © 2015 Yalantis. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | extension UIView { 12 | 13 | func animateCircularWithDuration(duration: NSTimeInterval, center: CGPoint, @noescape animations: () -> Void, completion: ((Bool) -> Void)? = nil) { 14 | let snapshot = self.snapshotViewAfterScreenUpdates(false) 15 | snapshot.frame = self.bounds 16 | self.addSubview(snapshot) 17 | 18 | let center = self.convertPoint(center, toView: snapshot) 19 | let radius: CGFloat = { 20 | let x = max(center.x, frame.width - center.x) 21 | let y = max(center.y, frame.height - center.y) 22 | return sqrt(x * x + y * y) 23 | }() 24 | let animation = CircularRevealAnimator(layer: snapshot.layer, center: center, startRadius: 0, endRadius: radius, invert: true) 25 | animation.duration = duration 26 | animation.completion = { 27 | snapshot.removeFromSuperview() 28 | completion?(true) 29 | } 30 | animation.start() 31 | animations() 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Example/StarWarsAnimations/Extension/UIColor+String.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIColor+String.swift 3 | // StarWarsAnimations 4 | // 5 | // Created by Artem Sidorenko on 10/5/15. 6 | // Copyright © 2015 Yalantis. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | 12 | extension UIColor { 13 | convenience init(string: String) { 14 | var string = string.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet()).uppercaseString 15 | 16 | if string.hasPrefix("#") { 17 | string = (string as NSString).substringFromIndex(1) 18 | } 19 | 20 | if string.characters.count != 6 { 21 | fatalError() 22 | } 23 | 24 | let rString = (string as NSString).substringToIndex(2) 25 | let gString = ((string as NSString).substringFromIndex(2) as NSString).substringToIndex(2) 26 | let bString = ((string as NSString).substringFromIndex(4) as NSString).substringToIndex(2) 27 | 28 | var r:CUnsignedInt = 0, g:CUnsignedInt = 0, b:CUnsignedInt = 0; 29 | NSScanner(string: rString).scanHexInt(&r) 30 | NSScanner(string: gString).scanHexInt(&g) 31 | NSScanner(string: bString).scanHexInt(&b) 32 | 33 | self.init(red: CGFloat(r) / 255.0, green: CGFloat(g) / 255.0, blue: CGFloat(b) / 255.0, alpha: CGFloat(1)) 34 | } 35 | } -------------------------------------------------------------------------------- /StarWars/StarWarsGLAnimator/SpriteRender.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Artem Sidorenko on 10/8/15. 3 | // Copyright © 2015 Yalantis. All rights reserved. 4 | // 5 | // Licensed under the MIT license: http://opensource.org/licenses/MIT 6 | // Latest version can be found at https://github.com/Yalantis/StarWars.iOS 7 | // 8 | 9 | import GLKit 10 | 11 | class SpriteRender { 12 | 13 | private let texture: ViewTexture 14 | private let effect: GLKBaseEffect 15 | 16 | init(texture: ViewTexture, effect: GLKBaseEffect) { 17 | self.texture = texture 18 | self.effect = effect 19 | } 20 | 21 | func render(sprites: [Sprite]) { 22 | effect.texture2d0.name = self.texture.name 23 | effect.texture2d0.enabled = 1 24 | 25 | effect.prepareToDraw() 26 | 27 | var vertex = sprites.map { $0.quad } 28 | 29 | glEnableVertexAttribArray(GLuint(GLKVertexAttrib.Position.rawValue)) 30 | glEnableVertexAttribArray(GLuint(GLKVertexAttrib.TexCoord0.rawValue)) 31 | 32 | withUnsafePointer(&vertex[0].bl.geometryVertex) { offset in 33 | glVertexAttribPointer(GLuint(GLKVertexAttrib.Position.rawValue), 2, GLenum(GL_FLOAT), GLboolean(UInt8(GL_FALSE)), GLsizei(sizeof(TexturedVertex)), offset) 34 | } 35 | withUnsafePointer(&vertex[0].bl.textureVertex) { offset in 36 | glVertexAttribPointer(GLuint(GLKVertexAttrib.TexCoord0.rawValue), 2, GLenum(GL_FLOAT), GLboolean(UInt8(GL_FALSE)), GLsizei(sizeof(TexturedVertex)), offset) 37 | } 38 | 39 | glDrawArrays(GLenum(GL_TRIANGLES), 0, GLsizei(vertex.count * 6)) 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /Example/StarWarsAnimations/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /Example/StarWarsAnimations/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UIAppFonts 26 | 27 | GothaProReg.otf 28 | 29 | UILaunchStoryboardName 30 | LaunchScreen 31 | UIMainStoryboardFile 32 | Main 33 | UIRequiredDeviceCapabilities 34 | 35 | armv7 36 | 37 | UIStatusBarHidden 38 | 39 | UISupportedInterfaceOrientations 40 | 41 | UIInterfaceOrientationPortrait 42 | UIInterfaceOrientationLandscapeLeft 43 | UIInterfaceOrientationLandscapeRight 44 | 45 | UISupportedInterfaceOrientations~ipad 46 | 47 | UIInterfaceOrientationPortrait 48 | UIInterfaceOrientationPortraitUpsideDown 49 | UIInterfaceOrientationLandscapeLeft 50 | UIInterfaceOrientationLandscapeRight 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /Example/StarWarsAnimations/View/ProfileButton.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ProfileButton.swift 3 | // StarWarsAnimations 4 | // 5 | // Created by Artem Sidorenko on 10/5/15. 6 | // Copyright © 2015 Yalantis. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | private let buttonPadding: CGFloat = 50 12 | 13 | @IBDesignable 14 | class ProfileButton: UIButton { 15 | 16 | override func intrinsicContentSize() -> CGSize { 17 | let size = super.intrinsicContentSize() 18 | return CGSize(width: size.width + buttonPadding, height: size.height) 19 | } 20 | 21 | func animateTouchUpInside(completion completion: () -> Void) { 22 | userInteractionEnabled = false 23 | layer.masksToBounds = true 24 | 25 | let fillLayer = CALayer() 26 | fillLayer.backgroundColor = self.layer.borderColor 27 | fillLayer.frame = self.layer.bounds 28 | layer.insertSublayer(fillLayer, atIndex: 0) 29 | 30 | let center = CGPoint(x: fillLayer.bounds.midX, y: fillLayer.bounds.midY) 31 | let radius: CGFloat = max(frame.width / 2 , frame.height / 2) 32 | 33 | let circularAnimation = CircularRevealAnimator(layer: fillLayer, center: center, startRadius: 0, endRadius: radius) 34 | circularAnimation.duration = 0.2 35 | circularAnimation.completion = { 36 | fillLayer.opacity = 0 37 | let opacityAnimation = CABasicAnimation(keyPath: "opacity") 38 | opacityAnimation.fromValue = 1 39 | opacityAnimation.toValue = 0 40 | opacityAnimation.duration = 0.2 41 | opacityAnimation.delegate = AnimationDelegate { 42 | fillLayer.removeFromSuperlayer() 43 | self.userInteractionEnabled = true 44 | completion() 45 | } 46 | fillLayer.addAnimation(opacityAnimation, forKey: "opacity") 47 | } 48 | circularAnimation.start() 49 | 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /Example/StarWarsAnimations/ViewModel/SettingsTheme.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SettingsTheme.swift 3 | // StarWarsAnimations 4 | // 5 | // Created by Artem Sidorenko on 10/5/15. 6 | // Copyright © 2015 Yalantis. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class SettingsTheme { 12 | 13 | static var light: SettingsTheme { 14 | return SettingsTheme(darkSide: false) 15 | } 16 | 17 | static var dark: SettingsTheme { 18 | return SettingsTheme(darkSide: true) 19 | } 20 | 21 | 22 | let backgroundColor: UIColor 23 | let separatorColor: UIColor 24 | let topImage: UIImage 25 | 26 | let cellTitleColor: UIColor 27 | let cellSubtitleColor: UIColor 28 | let primaryColor: UIColor 29 | let radioActiveImage: UIImage 30 | let radioInactiveImage: UIImage 31 | 32 | let username: String 33 | 34 | 35 | init(darkSide: Bool) { 36 | if darkSide { 37 | username = "Darth Vader" 38 | backgroundColor = UIColor(string: "#141217") 39 | separatorColor = UIColor(string: "#1f1d22") 40 | topImage = UIImage(named: "Photo_dark")! 41 | cellTitleColor = UIColor(string: "#4f4d51") 42 | cellSubtitleColor = UIColor(string: "#d0d0d1") 43 | primaryColor = UIColor(string: "#ef5350") 44 | radioActiveImage = UIImage(named: "Radio-dark_Active")! 45 | radioInactiveImage = UIImage(named: "Radio-dark_Inactive")! 46 | } else { 47 | username = "Anakin Skywalker" 48 | backgroundColor = UIColor(string: "#f8f8f8") 49 | separatorColor = UIColor(string: "#ededed") 50 | topImage = UIImage(named: "Photo_light")! 51 | cellTitleColor = UIColor(string: "#8e8e8e") 52 | cellSubtitleColor = UIColor(string: "#55606f") 53 | primaryColor = UIColor(string: "#0288d1") 54 | radioActiveImage = UIImage(named: "Radio-light_Active")! 55 | radioInactiveImage = UIImage(named: "Radio-light_Inactive")! 56 | } 57 | } 58 | 59 | } -------------------------------------------------------------------------------- /Example/StarWarsAnimations/Controller/MainSettingsViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MainSettingsViewController.swift 3 | // StarWarsAnimations 4 | // 5 | // Created by Artem Sidorenko on 10/19/15. 6 | // Copyright © 2015 Yalantis. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class MainSettingsViewController: UIViewController { 12 | 13 | @IBOutlet 14 | private weak var saveButton: UIButton! 15 | 16 | var theme: SettingsTheme! { 17 | didSet { 18 | settingsViewController?.theme = theme 19 | saveButton?.backgroundColor = theme.primaryColor 20 | } 21 | } 22 | 23 | override func viewDidLoad() { 24 | super.viewDidLoad() 25 | self.setupNavigationBar() 26 | } 27 | 28 | private func setupNavigationBar() { 29 | navigationController!.navigationBar.setBackgroundImage(UIImage(), forBarMetrics: UIBarMetrics.Default) 30 | navigationController!.navigationBar.shadowImage = UIImage() 31 | navigationController!.navigationBar.translucent = true 32 | navigationController!.navigationBar.titleTextAttributes = [ 33 | NSFontAttributeName: UIFont(name: "GothamPro", size: 20)!, 34 | NSForegroundColorAttributeName: UIColor.whiteColor() 35 | ] 36 | } 37 | 38 | private var settingsViewController: SettingsViewController! 39 | 40 | override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) { 41 | if let settings = segue.destinationViewController as? SettingsViewController { 42 | settingsViewController = settings 43 | settings.themeChanged = { [unowned self, unowned settings] darkside, center in 44 | let center = self.view.convertPoint(center, fromView: settings.view) 45 | self.view.animateCircularWithDuration(0.5, center: center, animations: { 46 | self.theme = darkside ? .dark : .light 47 | }) 48 | } 49 | } 50 | } 51 | 52 | override func prefersStatusBarHidden() -> Bool { 53 | return true 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /Example/StarWarsAnimations/Controller/IntroViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // IntroViewController.swift 3 | // StarWarsAnimations 4 | // 5 | // Created by Artem Sidorenko on 9/11/15. 6 | // Copyright © 2015 Yalantis. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import StarWars 11 | 12 | class IntroViewController: UIViewController { 13 | 14 | @IBOutlet 15 | private var topContraint: NSLayoutConstraint! 16 | 17 | override func viewWillAppear(animated: Bool) { 18 | super.viewWillAppear(animated) 19 | topContraint.active = false 20 | } 21 | 22 | override func viewDidAppear(animated: Bool) { 23 | super.viewDidAppear(animated) 24 | 25 | UIView.animateWithDuration(1, animations: { 26 | self.topContraint.active = true 27 | self.view.layoutIfNeeded() 28 | }) 29 | } 30 | 31 | @IBAction 32 | func backToIntroViewContoller(segue: UIStoryboardSegue) { } 33 | 34 | @IBAction func setupYourProfileTapped(sender: ProfileButton) { 35 | sender.animateTouchUpInside { 36 | self.performSegueWithIdentifier("presentSettings", sender: sender) 37 | } 38 | } 39 | 40 | override func prefersStatusBarHidden() -> Bool { 41 | return true 42 | } 43 | 44 | override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) { 45 | let destination = segue.destinationViewController 46 | destination.transitioningDelegate = self 47 | if let navigation = destination as? UINavigationController, 48 | settings = navigation.topViewController as? MainSettingsViewController { 49 | settings.theme = .light 50 | } 51 | } 52 | } 53 | 54 | extension IntroViewController: UIViewControllerTransitioningDelegate { 55 | 56 | func animationControllerForDismissedController(dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? { 57 | 58 | // return StarWarsUIDynamicAnimator() 59 | // return StarWarsUIViewAnimator() 60 | return StarWarsGLAnimator() 61 | 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /StarWars/StarWarsGLAnimator/Sprite.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Artem Sidorenko on 10/8/15. 3 | // Copyright © 2015 Yalantis. All rights reserved. 4 | // 5 | // Licensed under the MIT license: http://opensource.org/licenses/MIT 6 | // Latest version can be found at https://github.com/Yalantis/StarWars.iOS 7 | // 8 | 9 | import GLKit 10 | 11 | struct TexturedVertex { 12 | var geometryVertex = Vector2() 13 | var textureVertex = Vector2() 14 | } 15 | 16 | struct TexturedQuad { 17 | var bl = TexturedVertex() 18 | var br = TexturedVertex() { didSet { _br = br } } 19 | var tl = TexturedVertex() { didSet { _tl = tl } } 20 | var tr = TexturedVertex() 21 | 22 | // openGL optimization. it uses triangles to draw. 23 | // so we duplicate 2 vertex, so it have 6 vertex to draw two triangles 24 | private var _br = TexturedVertex() 25 | private var _tl = TexturedVertex() 26 | } 27 | 28 | struct Sprite { 29 | var quad = TexturedQuad() 30 | var moveVelocity = Vector2() 31 | 32 | mutating func slice(rect: CGRect, textureSize: CGSize) { 33 | quad.bl.geometryVertex = Vector2(x: 0, y: 0) 34 | quad.br.geometryVertex = Vector2(x: rect.size.width, y: 0) 35 | quad.tl.geometryVertex = Vector2(x: 0, y: rect.size.height) 36 | quad.tr.geometryVertex = Vector2(x: rect.size.width, y: rect.size.height) 37 | 38 | quad.bl.textureVertex = Vector2(x: rect.origin.x / textureSize.width, y: rect.origin.y / textureSize.height) 39 | quad.br.textureVertex = Vector2(x: (rect.origin.x + rect.size.width) / textureSize.width, y: rect.origin.y / textureSize.height) 40 | quad.tl.textureVertex = Vector2(x: rect.origin.x / textureSize.width, y: (rect.origin.y + rect.size.height) / textureSize.height) 41 | quad.tr.textureVertex = Vector2(x: (rect.origin.x + rect.size.width) / textureSize.width, y: (rect.origin.y + rect.size.height) / textureSize.height) 42 | 43 | position += Vector2(rect.origin) 44 | } 45 | 46 | var position = Vector2() { 47 | didSet { 48 | let diff = position - oldValue 49 | quad.bl.geometryVertex += diff 50 | quad.br.geometryVertex += diff 51 | quad.tl.geometryVertex += diff 52 | quad.tr.geometryVertex += diff 53 | } 54 | } 55 | 56 | mutating func update(tick: NSTimeInterval) { 57 | position += moveVelocity * Float32(tick) 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /Example/StarWarsAnimations/Circular/CircularRevealAnimator.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2014 Yalantis 3 | // Licensed under the MIT license: http://opensource.org/licenses/MIT 4 | // 5 | 6 | import QuartzCore 7 | 8 | private func SquareAroundCircle(center: CGPoint, radius: CGFloat) -> CGRect { 9 | assert(0 <= radius, "radius must be a positive value") 10 | return CGRectInset(CGRect(origin: center, size: CGSizeZero), -radius, -radius) 11 | } 12 | 13 | class CircularRevealAnimator { 14 | var completion: () -> Void = {} 15 | 16 | private let layer: CALayer 17 | private let mask: CAShapeLayer 18 | private let animation: CABasicAnimation 19 | 20 | var duration: CFTimeInterval { 21 | get { return animation.duration } 22 | set(value) { animation.duration = value } 23 | } 24 | 25 | var timingFunction: CAMediaTimingFunction! { 26 | get { return animation.timingFunction } 27 | set(value) { animation.timingFunction = value } 28 | } 29 | 30 | init(layer: CALayer, center: CGPoint, startRadius: CGFloat, endRadius: CGFloat, invert: Bool = false) { 31 | let startCirclePath = CGPathCreateWithEllipseInRect(SquareAroundCircle(center, radius: startRadius), UnsafePointer()) 32 | let endCirclePath = CGPathCreateWithEllipseInRect(SquareAroundCircle(center, radius: endRadius), UnsafePointer()) 33 | 34 | var startPath = startCirclePath, endPath = endCirclePath 35 | if invert { 36 | var path = CGPathCreateMutable() 37 | CGPathAddRect(path, nil, layer.bounds) 38 | CGPathAddPath(path, nil, startCirclePath) 39 | startPath = path 40 | path = CGPathCreateMutable() 41 | CGPathAddRect(path, nil, layer.bounds) 42 | CGPathAddPath(path, nil, endCirclePath) 43 | endPath = path 44 | } 45 | self.layer = layer 46 | 47 | mask = CAShapeLayer() 48 | mask.path = endPath 49 | mask.fillRule = kCAFillRuleEvenOdd 50 | 51 | animation = CABasicAnimation(keyPath: "path") 52 | animation.fromValue = startPath 53 | animation.toValue = endPath 54 | animation.delegate = AnimationDelegate { 55 | layer.mask = nil 56 | self.completion() 57 | self.animation.delegate = nil 58 | } 59 | } 60 | 61 | func start() { 62 | layer.mask = mask 63 | mask.frame = layer.bounds 64 | mask.addAnimation(animation, forKey: "reveal") 65 | } 66 | } -------------------------------------------------------------------------------- /StarWars/StarWarsGLAnimator/ViewTexture.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Artem Sidorenko on 10/9/15. 3 | // Copyright © 2015 Yalantis. All rights reserved. 4 | // 5 | // Licensed under the MIT license: http://opensource.org/licenses/MIT 6 | // Latest version can be found at https://github.com/Yalantis/StarWars.iOS 7 | // 8 | 9 | import UIKit 10 | 11 | class ViewTexture { 12 | var name: GLuint = 0 13 | var width: GLsizei = 0 14 | var height: GLsizei = 0 15 | 16 | func setupOpenGL() { 17 | glGenTextures(1, &name) 18 | glBindTexture(GLenum(GL_TEXTURE_2D), name) 19 | 20 | glTexParameteri(GLenum(GL_TEXTURE_2D), GLenum(GL_TEXTURE_MIN_FILTER), GLint(GL_LINEAR)) 21 | glTexParameteri(GLenum(GL_TEXTURE_2D), GLenum(GL_TEXTURE_MAG_FILTER), GLint(GL_LINEAR)) 22 | 23 | glTexParameteri(GLenum(GL_TEXTURE_2D), GLenum(GL_TEXTURE_WRAP_S), GLint(GL_CLAMP_TO_EDGE)) 24 | glTexParameteri(GLenum(GL_TEXTURE_2D), GLenum(GL_TEXTURE_WRAP_T), GLint(GL_CLAMP_TO_EDGE)) 25 | glBindTexture(GLenum(GL_TEXTURE_2D), 0); 26 | } 27 | 28 | deinit { 29 | if name != 0 { 30 | glDeleteTextures(1, &name) 31 | } 32 | } 33 | 34 | func renderView(view: UIView) { 35 | let scale = UIScreen.mainScreen().scale 36 | width = GLsizei(view.layer.bounds.size.width * scale) 37 | height = GLsizei(view.layer.bounds.size.height * scale) 38 | 39 | var texturePixelBuffer = [GLubyte](count: Int(height * width * 4), repeatedValue: 0) 40 | let colorSpace = CGColorSpaceCreateDeviceRGB() 41 | 42 | withUnsafeMutablePointer(&texturePixelBuffer[0]) { texturePixelBuffer in 43 | let context = CGBitmapContextCreate(texturePixelBuffer, 44 | Int(width), Int(height), 8, Int(width * 4), colorSpace, 45 | CGImageAlphaInfo.PremultipliedLast.rawValue | CGBitmapInfo.ByteOrder32Big.rawValue)! 46 | CGContextScaleCTM(context, scale, scale) 47 | 48 | UIGraphicsPushContext(context) 49 | view.drawViewHierarchyInRect(view.layer.bounds, afterScreenUpdates: false) 50 | UIGraphicsPopContext() 51 | 52 | glBindTexture(GLenum(GL_TEXTURE_2D), name); 53 | 54 | glTexImage2D(GLenum(GL_TEXTURE_2D), 0, GLint(GL_RGBA), width, height, 0, GLenum(GL_RGBA), GLenum(GL_UNSIGNED_BYTE), texturePixelBuffer) 55 | glBindTexture(GLenum(GL_TEXTURE_2D), 0); 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /Example/StarWarsAnimations/View/StarsOverlay.swift: -------------------------------------------------------------------------------- 1 | // 2 | // StarsOverlay.swift 3 | // StarWarsAnimations 4 | // 5 | // Created by Artem Sidorenko on 9/11/15. 6 | // Copyright © 2015 Yalantis. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class StarsOverlay: UIView { 12 | 13 | override class func layerClass() -> AnyClass { 14 | return CAEmitterLayer.self 15 | } 16 | 17 | override init(frame: CGRect) { 18 | super.init(frame: frame) 19 | self.setup() 20 | } 21 | 22 | required init?(coder aDecoder: NSCoder) { 23 | super.init(coder: aDecoder) 24 | self.setup() 25 | } 26 | 27 | private var emitter: CAEmitterLayer { 28 | return layer as! CAEmitterLayer 29 | } 30 | 31 | private var particle: CAEmitterCell! 32 | 33 | func setup() { 34 | emitter.emitterMode = kCAEmitterLayerOutline 35 | emitter.emitterShape = kCAEmitterLayerCircle 36 | emitter.renderMode = kCAEmitterLayerOldestFirst 37 | emitter.preservesDepth = true 38 | 39 | particle = CAEmitterCell() 40 | 41 | particle.contents = UIImage(named: "spark")!.CGImage 42 | particle.birthRate = 10 43 | 44 | particle.lifetime = 50 45 | particle.lifetimeRange = 5 46 | 47 | particle.velocity = 20 48 | particle.velocityRange = 10 49 | 50 | particle.scale = 0.02 51 | particle.scaleRange = 0.1 52 | particle.scaleSpeed = 0.02 53 | 54 | emitter.emitterCells = [particle] 55 | } 56 | 57 | var emitterTimer: NSTimer? 58 | 59 | override func didMoveToWindow() { 60 | super.didMoveToWindow() 61 | 62 | if self.window != nil { 63 | if emitterTimer == nil { 64 | emitterTimer = NSTimer.scheduledTimerWithTimeInterval(0.1, target: self, selector: "randomizeEmitterPosition", userInfo: nil, repeats: true) 65 | } 66 | } else if emitterTimer != nil { 67 | emitterTimer?.invalidate() 68 | emitterTimer = nil 69 | } 70 | } 71 | 72 | func randomizeEmitterPosition() { 73 | let sizeWidth = max(bounds.width, bounds.height) 74 | let radius = CGFloat(arc4random()) % sizeWidth 75 | emitter.emitterSize = CGSize(width: radius, height: radius) 76 | particle.birthRate = 10 + sqrt(Float(radius)) 77 | } 78 | 79 | override func layoutSubviews() { 80 | super.layoutSubviews() 81 | emitter.emitterPosition = self.center 82 | emitter.emitterSize = self.bounds.size 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # StarWars Animation 2 | [![Platform](http://img.shields.io/badge/platform-iOS-blue.svg?style=flat)](http://cocoapods.org/?q=YALSideMenu) [![License](http://img.shields.io/badge/license-MIT-green.svg?style=flat)](https://github.com/Yalantis/Side-Menu.iOS/blob/master/LICENSE) 3 | 4 | This component implements transition animation to crumble view-controller into tiny pieces. 5 | 6 | [![Yalantis](https://raw.githubusercontent.com/Yalantis/PullToRefresh/develop/PullToRefreshDemo/Resources/badge_dark.png)](https://yalantis.com/?utm_source=github) 7 | 8 | 9 | Check this project on dribbble. 10 | 11 | Also, read how it was done in [our blog](https://yalantis.com/blog/uidynamics-uikit-or-opengl-3-types-of-ios-animations-for-the-star-wars/) 12 | 13 | ##Requirements 14 | - iOS 8.0+ 15 | - Xcode 7 16 | - Swift 2 17 | 18 | ##Installing with [CocoaPods](https://cocoapods.org) 19 | 20 | ```ruby 21 | use_frameworks! 22 | pod 'StarWars', '~> 1.0' 23 | ``` 24 | 25 | ##Usage 26 | 27 | At first, import StarWars: 28 | ```swift 29 | import StarWars 30 | ``` 31 | 32 | Then just implement class of *UIViewControllerTransitioningDelegate* that will return our animation form method *animationControllerForDismissedController* and assign it to *transitioningDelegate* of viewController that you want to dismiss. 33 | ```swift 34 | override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) { 35 | let destination = segue.destinationViewController 36 | destination.transitioningDelegate = self 37 | } 38 | 39 | func animationControllerForDismissedController(dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? { 40 | return StarWarsGLAnimator() 41 | } 42 | ``` 43 | 44 | There are also two things you can customize in the Star Wars animation: duration and sprite sizes. 45 | Let’s see how you can do this: 46 | 47 | ```swift 48 | let animator = StarWarsGLAnimator() 49 | animator.duration = 2 50 | animator.spriteWidth = 8 51 | ``` 52 | 53 | Have fun! :) 54 | 55 | ## License 56 | 57 | The MIT License (MIT) 58 | 59 | Copyright © 2015 Yalantis 60 | 61 | Permission is hereby granted, free of charge, to any person obtaining a copy 62 | of this software and associated documentation files (the "Software"), to deal 63 | in the Software without restriction, including without limitation the rights 64 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 65 | copies of the Software, and to permit persons to whom the Software is 66 | furnished to do so, subject to the following conditions: 67 | 68 | The above copyright notice and this permission notice shall be included in 69 | all copies or substantial portions of the Software. 70 | 71 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 72 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 73 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 74 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 75 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 76 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 77 | THE SOFTWARE. 78 | 79 | -------------------------------------------------------------------------------- /StarWars/StarWarsUIViewAnimator/StarWarsUIViewAnimator.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Artem Sidorenko on 9/11/15. 3 | // Copyright © 2015 Yalantis. All rights reserved. 4 | // 5 | // Licensed under the MIT license: http://opensource.org/licenses/MIT 6 | // Latest version can be found at https://github.com/Yalantis/StarWars.iOS 7 | // 8 | 9 | import UIKit 10 | 11 | public class StarWarsUIViewAnimator: NSObject, UIViewControllerAnimatedTransitioning { 12 | 13 | public var duration: NSTimeInterval = 2 14 | public var spriteWidth: CGFloat = 10 15 | 16 | 17 | public func transitionDuration(transitionContext: UIViewControllerContextTransitioning?) -> NSTimeInterval { 18 | return self.duration 19 | } 20 | 21 | public func animateTransition(transitionContext: UIViewControllerContextTransitioning) { 22 | 23 | let containerView = transitionContext.containerView()! 24 | let fromView = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey)!.view 25 | let toView = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey)!.view 26 | 27 | containerView.addSubview(toView) 28 | containerView.sendSubviewToBack(toView) 29 | 30 | var snapshots:[UIView] = [] 31 | let size = fromView.frame.size 32 | 33 | func randomFloatBetween(smallNumber: CGFloat, and bigNumber: CGFloat) -> CGFloat { 34 | let diff = bigNumber - smallNumber 35 | return CGFloat(arc4random()) / 100.0 % diff + smallNumber 36 | } 37 | 38 | // snapshot the from view, this makes subsequent snaphots more performant 39 | let fromViewSnapshot = fromView.snapshotViewAfterScreenUpdates(false) 40 | 41 | let width = spriteWidth 42 | let height = width 43 | 44 | for x in CGFloat(0).stride(through: size.width, by: width) { 45 | for y in CGFloat(0).stride(through: size.height, by: height) { 46 | 47 | let snapshotRegion = CGRect(x: x, y: y, width: width, height: height) 48 | 49 | let snapshot = fromViewSnapshot.resizableSnapshotViewFromRect(snapshotRegion, afterScreenUpdates: false, withCapInsets: UIEdgeInsetsZero) 50 | 51 | containerView.addSubview(snapshot) 52 | snapshot.frame = snapshotRegion 53 | snapshots.append(snapshot) 54 | } 55 | } 56 | 57 | print(snapshots.count) 58 | 59 | containerView.sendSubviewToBack(fromView) 60 | 61 | UIView.animateWithDuration(duration, delay: 0, options: UIViewAnimationOptions.CurveLinear, animations: { 62 | for view in snapshots { 63 | 64 | let xOffset: CGFloat = randomFloatBetween(-200 , and: 200) 65 | let yOffset: CGFloat = randomFloatBetween(fromView.frame.height, and: fromView.frame.height * 1.3) 66 | view.frame = view.frame.offsetBy(dx: xOffset, dy: yOffset) 67 | } 68 | }) { finished in 69 | for view in snapshots { 70 | view.removeFromSuperview() 71 | } 72 | transitionContext.completeTransition(!transitionContext.transitionWasCancelled()) 73 | } 74 | } 75 | 76 | } 77 | -------------------------------------------------------------------------------- /StarWars/StarWarsUIDynamicAnimator/StarWarsUIDynamicAnimator.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Artem Sidorenko on 9/11/15. 3 | // Copyright © 2015 Yalantis. All rights reserved. 4 | // 5 | // Licensed under the MIT license: http://opensource.org/licenses/MIT 6 | // Latest version can be found at https://github.com/Yalantis/StarWars.iOS 7 | // 8 | 9 | import UIKit 10 | 11 | public class StarWarsUIDynamicAnimator: NSObject, UIViewControllerAnimatedTransitioning { 12 | 13 | public var duration: NSTimeInterval = 2 14 | public var spriteWidth: CGFloat = 20 15 | 16 | var transitionContext: UIViewControllerContextTransitioning! 17 | 18 | public func transitionDuration(transitionContext: UIViewControllerContextTransitioning?) -> NSTimeInterval { 19 | return self.duration 20 | } 21 | 22 | var animator: UIDynamicAnimator! 23 | 24 | public func animateTransition(transitionContext: UIViewControllerContextTransitioning) { 25 | 26 | let containerView = transitionContext.containerView()! 27 | let fromView = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey)!.view 28 | let toView = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey)!.view 29 | 30 | containerView.addSubview(toView) 31 | containerView.sendSubviewToBack(toView) 32 | 33 | var snapshots:[UIView] = [] 34 | let size = fromView.frame.size 35 | 36 | func randomFloatBetween(smallNumber: CGFloat, and bigNumber: CGFloat) -> CGFloat { 37 | let diff = bigNumber - smallNumber 38 | return CGFloat(arc4random()) / 100.0 % diff + smallNumber 39 | } 40 | 41 | // snapshot the from view, this makes subsequent snaphots more performant 42 | let fromViewSnapshot = fromView.snapshotViewAfterScreenUpdates(false) 43 | 44 | let width = spriteWidth 45 | let height = width 46 | 47 | animator = UIDynamicAnimator(referenceView: containerView) 48 | 49 | for x in CGFloat(0).stride(through: size.width, by: width) { 50 | for y in CGFloat(0).stride(through: size.height, by: height) { 51 | let snapshotRegion = CGRect(x: x, y: y, width: width, height: height) 52 | 53 | let snapshot = fromViewSnapshot.resizableSnapshotViewFromRect(snapshotRegion, afterScreenUpdates: false, withCapInsets: UIEdgeInsetsZero) 54 | 55 | containerView.addSubview(snapshot) 56 | snapshot.frame = snapshotRegion 57 | snapshots.append(snapshot) 58 | 59 | let push = UIPushBehavior(items: [snapshot], mode: .Instantaneous) 60 | push.pushDirection = CGVector(dx: randomFloatBetween(-0.15 , and: 0.15), dy: randomFloatBetween(-0.15 , and: 0)) 61 | push.active = true 62 | animator.addBehavior(push) 63 | } 64 | } 65 | let gravity = UIGravityBehavior(items: snapshots) 66 | animator.addBehavior(gravity) 67 | 68 | print(snapshots.count) 69 | 70 | fromView.removeFromSuperview() 71 | 72 | NSTimer.scheduledTimerWithTimeInterval(duration, target: self, selector: "completeTransition", userInfo: nil, repeats: false) 73 | self.transitionContext = transitionContext 74 | } 75 | 76 | func completeTransition() { 77 | self.transitionContext.completeTransition(!transitionContext.transitionWasCancelled()) 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /Example/StarWarsAnimations/Controller/SettingsViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SettingsViewController.swift 3 | // StarWarsAnimations 4 | // 5 | // Created by Artem Sidorenko on 9/11/15. 6 | // Copyright © 2015 Yalantis. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | private let tableViewOffset: CGFloat = UIScreen.mainScreen().bounds.height < 600 ? 215 : 225 12 | private let beforeAppearOffset: CGFloat = 400 13 | 14 | class SettingsViewController: UITableViewController { 15 | 16 | var themeChanged: ((darkside: Bool, center: CGPoint) -> Void)? 17 | 18 | @IBOutlet 19 | private var backgroundHolder: UIView! 20 | 21 | @IBOutlet 22 | private weak var backgroundImageView: UIImageView! 23 | 24 | @IBOutlet 25 | private weak var backgroundHeightConstraint: NSLayoutConstraint! 26 | 27 | @IBOutlet 28 | private weak var backgroundWidthConstraint: NSLayoutConstraint! 29 | 30 | @IBOutlet 31 | private weak var darkSideSwitch: UISwitch! 32 | 33 | @IBOutlet 34 | private weak var radioInactiveImageView: UIImageView! 35 | @IBOutlet 36 | private weak var radioActiveImageView: UIImageView! 37 | 38 | @IBOutlet 39 | private var cellTitleLabels: [UILabel]! 40 | @IBOutlet 41 | private var cellSubtitleLabels: [UILabel]! 42 | 43 | @IBOutlet 44 | private weak var usernameLabel: UILabel! 45 | 46 | @IBAction 47 | private func darkSideChanged(sender: AnyObject) { 48 | let center = self.tableView.convertPoint(darkSideSwitch.center, fromView: darkSideSwitch.superview) 49 | self.themeChanged?(darkside: darkSideSwitch.on, center: center) 50 | } 51 | 52 | var theme: SettingsTheme! { 53 | didSet { 54 | backgroundImageView.image = theme.topImage 55 | tableView.separatorColor = theme.separatorColor 56 | backgroundHolder.backgroundColor = theme.backgroundColor 57 | for label in cellTitleLabels { label.textColor = theme.cellTitleColor } 58 | for label in cellSubtitleLabels { label.textColor = theme.cellSubtitleColor } 59 | radioInactiveImageView.image = theme.radioInactiveImage 60 | radioActiveImageView.image = theme.radioActiveImage 61 | usernameLabel.text = theme.username 62 | tableView.reloadData() 63 | } 64 | } 65 | 66 | override func viewWillAppear(animated: Bool) { 67 | super.viewWillAppear(animated) 68 | tableView.contentInset = UIEdgeInsets(top: tableViewOffset, left: 0, bottom: 0, right: 0) 69 | tableView.contentOffset = CGPoint(x: 0, y: -beforeAppearOffset) 70 | 71 | UIView.animateWithDuration(0.5, animations: { 72 | self.tableView.contentOffset = CGPoint(x: 0, y: -tableViewOffset) 73 | }) 74 | } 75 | 76 | override func viewDidLoad() { 77 | super.viewDidLoad() 78 | 79 | theme = .light 80 | tableView.backgroundView = backgroundHolder 81 | } 82 | 83 | override func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) { 84 | cell.backgroundColor = theme.backgroundColor 85 | } 86 | 87 | override func scrollViewDidScroll(scrollView: UIScrollView) { 88 | backgroundHeightConstraint.constant = max(navigationController!.navigationBar.bounds.height + scrollView.contentInset.top - scrollView.contentOffset.y, 0) 89 | backgroundWidthConstraint.constant = navigationController!.navigationBar.bounds.height - scrollView.contentInset.top - scrollView.contentOffset.y * 0.8 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /StarWars/StarWarsGLAnimator/Vector2.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Artem Sidorenko on 10/9/15. 3 | // Copyright © 2015 Yalantis. All rights reserved. 4 | // 5 | // Licensed under the MIT license: http://opensource.org/licenses/MIT 6 | // Latest version can be found at https://github.com/Yalantis/StarWars.iOS 7 | // 8 | 9 | import UIKit 10 | 11 | struct Vector2 { 12 | 13 | var x : Float32 = 0.0 14 | var y : Float32 = 0.0 15 | 16 | init() { 17 | 18 | x = 0.0 19 | y = 0.0 20 | } 21 | 22 | init(value: Float32) { 23 | 24 | x = value 25 | y = value 26 | } 27 | 28 | init(x: Float32 ,y: Float32) { 29 | 30 | self.x = x 31 | self.y = y 32 | } 33 | 34 | init(x: CGFloat, y: CGFloat) { 35 | self.init(x: Float32(x), y: Float32(y)) 36 | } 37 | 38 | init(x: Int, y: Int) { 39 | self.init(x: Float32(x), y: Float32(y)) 40 | } 41 | 42 | init(other: Vector2) { 43 | 44 | x = other.x 45 | y = other.y 46 | } 47 | 48 | init(_ other: CGPoint) { 49 | x = Float32(other.x) 50 | y = Float32(other.y) 51 | } 52 | } 53 | 54 | extension Vector2: CustomStringConvertible { 55 | 56 | var description: String { return "[\(x),\(y)]" } 57 | } 58 | 59 | extension Vector2 : Equatable { 60 | 61 | func isFinite() -> Bool { 62 | 63 | return x.isFinite && y.isFinite 64 | } 65 | 66 | func distance(other: Vector2) -> Float32 { 67 | 68 | let result = self - other; 69 | return sqrt( result.dot(result) ) 70 | } 71 | 72 | mutating func normalize() { 73 | 74 | let m = magnitude() 75 | 76 | if m > 0 { 77 | 78 | let il:Float32 = 1.0 / m 79 | 80 | x *= il 81 | y *= il 82 | } 83 | } 84 | 85 | func magnitude() -> Float32 { 86 | 87 | return sqrtf( x*x + y*y ) 88 | } 89 | 90 | func dot( v: Vector2 ) -> Float32 { 91 | 92 | return x * v.x + y * v.y 93 | } 94 | 95 | mutating func lerp( a: Vector2, b: Vector2, coef : Float32) { 96 | 97 | let result = a + ( b - a) * coef 98 | 99 | x = result.x 100 | y = result.y 101 | } 102 | } 103 | 104 | func ==(lhs: Vector2, rhs: Vector2) -> Bool { 105 | 106 | return (lhs.x == rhs.x) && (lhs.y == rhs.y) 107 | } 108 | 109 | func * (left: Vector2, right : Float32) -> Vector2 { 110 | 111 | return Vector2(x:left.x * right, y:left.y * right) 112 | } 113 | 114 | func * (left: Vector2, right : Vector2) -> Vector2 { 115 | 116 | return Vector2(x:left.x * right.x, y:left.y * right.y) 117 | } 118 | 119 | func / (left: Vector2, right : Float32) -> Vector2 { 120 | 121 | return Vector2(x:left.x / right, y:left.y / right) 122 | } 123 | 124 | func / (left: Vector2, right : Vector2) -> Vector2 { 125 | 126 | return Vector2(x:left.x / right.x, y:left.y / right.y) 127 | } 128 | 129 | func + (left: Vector2, right: Vector2) -> Vector2 { 130 | 131 | return Vector2(x:left.x + right.x, y:left.y + right.y) 132 | } 133 | 134 | func - (left: Vector2, right: Vector2) -> Vector2 { 135 | 136 | return Vector2(x:left.x - right.x, y:left.y - right.y) 137 | } 138 | 139 | func + (left: Vector2, right: Float32) -> Vector2 { 140 | 141 | return Vector2(x:left.x + right, y:left.y + right) 142 | } 143 | 144 | func - (left: Vector2, right: Float32) -> Vector2 { 145 | 146 | return Vector2(x:left.x - right, y:left.y - right) 147 | } 148 | 149 | func += (inout left: Vector2, right: Vector2) { 150 | 151 | left = left + right 152 | } 153 | 154 | func -= (inout left: Vector2, right: Vector2) { 155 | 156 | left = left - right 157 | } 158 | 159 | func *= (inout left: Vector2, right: Vector2) { 160 | 161 | left = left * right 162 | } 163 | 164 | func /= (inout left: Vector2, right: Vector2) { 165 | 166 | left = left / right 167 | } 168 | 169 | -------------------------------------------------------------------------------- /StarWars/StarWarsGLAnimator/StarWarsGLAnimator.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Artem Sidorenko on 9/14/15. 3 | // Copyright © 2015 Yalantis. All rights reserved. 4 | // 5 | // Licensed under the MIT license: http://opensource.org/licenses/MIT 6 | // Latest version can be found at https://github.com/Yalantis/StarWars.iOS 7 | // 8 | 9 | import UIKit 10 | import GLKit 11 | 12 | public class StarWarsGLAnimator: NSObject, UIViewControllerAnimatedTransitioning { 13 | 14 | public var duration: NSTimeInterval = 2 15 | public var spriteWidth: CGFloat = 8 16 | 17 | 18 | private var sprites: [Sprite] = [] 19 | private var glContext: EAGLContext! 20 | private var effect: GLKBaseEffect! 21 | private var glView: GLKView! 22 | private var displayLink: CADisplayLink! 23 | private var lastUpdateTime: NSTimeInterval? 24 | private var startTransitionTime: NSTimeInterval! 25 | private var transitionContext: UIViewControllerContextTransitioning! 26 | private var render: SpriteRender! 27 | 28 | public func transitionDuration(transitionContext: UIViewControllerContextTransitioning?) -> NSTimeInterval { 29 | return self.duration 30 | } 31 | 32 | public func animateTransition(transitionContext: UIViewControllerContextTransitioning) { 33 | 34 | let containerView = transitionContext.containerView()! 35 | let fromView = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey)!.view 36 | let toView = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey)!.view 37 | 38 | containerView.addSubview(toView) 39 | containerView.sendSubviewToBack(toView) 40 | 41 | func randomFloatBetween(smallNumber: CGFloat, and bigNumber: CGFloat) -> Float { 42 | let diff = bigNumber - smallNumber 43 | return Float(CGFloat(arc4random()) / 100.0 % diff + smallNumber) 44 | } 45 | 46 | self.glContext = EAGLContext(API: .OpenGLES2) 47 | EAGLContext.setCurrentContext(glContext) 48 | 49 | glView = GLKView(frame: fromView.frame, context: glContext) 50 | glView.enableSetNeedsDisplay = true 51 | glView.delegate = self 52 | glView.opaque = false 53 | containerView.addSubview(glView) 54 | 55 | let texture = ViewTexture() 56 | texture.setupOpenGL() 57 | texture.renderView(fromView) 58 | 59 | effect = GLKBaseEffect() 60 | let projectionMatrix = GLKMatrix4MakeOrtho(0, Float(texture.width), 0, Float(texture.height), -1, 1) 61 | effect.transform.projectionMatrix = projectionMatrix 62 | 63 | render = SpriteRender(texture: texture, effect: effect) 64 | 65 | let size = CGSize(width: CGFloat(texture.width), height: CGFloat(texture.height)) 66 | 67 | let scale = UIScreen.mainScreen().scale 68 | let width = spriteWidth * scale 69 | let height = width 70 | 71 | for x in CGFloat(0).stride(through: size.width, by: width) { 72 | for y in CGFloat(0).stride(through: size.height, by: height) { 73 | let region = CGRect(x: x, y: y, width: width, height: height) 74 | var sprite = Sprite() 75 | sprite.slice(region, textureSize: size) 76 | sprite.moveVelocity = Vector2(x: randomFloatBetween(-100, and: 100), y: randomFloatBetween(-CGFloat(texture.height)*1.3/CGFloat(duration), and: -CGFloat(texture.height)/CGFloat(duration))) 77 | 78 | sprites.append(sprite) 79 | } 80 | } 81 | fromView.removeFromSuperview() 82 | self.transitionContext = transitionContext 83 | 84 | displayLink = CADisplayLink(target: self, selector: "displayLinkTick:") 85 | displayLink.paused = false 86 | displayLink.addToRunLoop(NSRunLoop.mainRunLoop(), forMode: NSRunLoopCommonModes) 87 | 88 | self.startTransitionTime = NSDate.timeIntervalSinceReferenceDate() 89 | } 90 | 91 | public func animationEnded(transitionCompleted: Bool) { 92 | self.displayLink.invalidate() 93 | self.displayLink = nil 94 | } 95 | 96 | func displayLinkTick(displayLink: CADisplayLink) { 97 | if let lastUpdateTime = lastUpdateTime { 98 | let timeSinceLastUpdate = NSDate.timeIntervalSinceReferenceDate() - lastUpdateTime 99 | self.lastUpdateTime = NSDate.timeIntervalSinceReferenceDate() 100 | for index in 0.. self.duration { 108 | self.transitionContext.completeTransition(!transitionContext.transitionWasCancelled()) 109 | } 110 | } 111 | } 112 | 113 | extension StarWarsGLAnimator: GLKViewDelegate { 114 | 115 | public func glkView(view: GLKView, drawInRect rect: CGRect) { 116 | glClearColor(0, 0, 0, 0) 117 | glClear(UInt32(GL_COLOR_BUFFER_BIT)) 118 | glBlendFunc(GLenum(GL_SRC_ALPHA), GLenum(GL_ONE_MINUS_SRC_ALPHA)) 119 | glEnable(GLenum(GL_BLEND)) 120 | 121 | render.render(self.sprites) 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /Example/StarWarsAnimations.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 2A05EF861BD4B9F600BF150F /* MainSettingsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A05EF851BD4B9F600BF150F /* MainSettingsViewController.swift */; settings = {ASSET_TAGS = (); }; }; 11 | 2A6F123B1BD6662F00D12C56 /* GothaProReg.otf in Resources */ = {isa = PBXBuildFile; fileRef = 2A89D8891BD6626D00A2C503 /* GothaProReg.otf */; }; 12 | 2A89D88C1BD6628000A2C503 /* AnimationDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A89D88A1BD6628000A2C503 /* AnimationDelegate.swift */; settings = {ASSET_TAGS = (); }; }; 13 | 2A89D88D1BD6628000A2C503 /* CircularRevealAnimator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A89D88B1BD6628000A2C503 /* CircularRevealAnimator.swift */; settings = {ASSET_TAGS = (); }; }; 14 | 2A89D8981BD6633300A2C503 /* StarWars.h in Headers */ = {isa = PBXBuildFile; fileRef = 2A89D8971BD6633300A2C503 /* StarWars.h */; settings = {ATTRIBUTES = (Public, ); }; }; 15 | 2A89D89C1BD6633300A2C503 /* StarWars.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2A89D8951BD6633300A2C503 /* StarWars.framework */; }; 16 | 2A89D89D1BD6633300A2C503 /* StarWars.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 2A89D8951BD6633300A2C503 /* StarWars.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 17 | 2A89D8A81BD663A000A2C503 /* Sprite.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A89D8A31BD663A000A2C503 /* Sprite.swift */; settings = {ASSET_TAGS = (); }; }; 18 | 2A89D8A91BD663A000A2C503 /* SpriteRender.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A89D8A41BD663A000A2C503 /* SpriteRender.swift */; settings = {ASSET_TAGS = (); }; }; 19 | 2A89D8AA1BD663A000A2C503 /* StarWarsGLAnimator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A89D8A51BD663A000A2C503 /* StarWarsGLAnimator.swift */; settings = {ASSET_TAGS = (); }; }; 20 | 2A89D8AB1BD663A000A2C503 /* Vector2.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A89D8A61BD663A000A2C503 /* Vector2.swift */; settings = {ASSET_TAGS = (); }; }; 21 | 2A89D8AC1BD663A000A2C503 /* ViewTexture.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A89D8A71BD663A000A2C503 /* ViewTexture.swift */; settings = {ASSET_TAGS = (); }; }; 22 | 2A89D8AF1BD663B300A2C503 /* StarWarsUIDynamicAnimator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A89D8AE1BD663B300A2C503 /* StarWarsUIDynamicAnimator.swift */; settings = {ASSET_TAGS = (); }; }; 23 | 2A89D8B21BD663C500A2C503 /* StarWarsUIViewAnimator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A89D8B11BD663C500A2C503 /* StarWarsUIViewAnimator.swift */; settings = {ASSET_TAGS = (); }; }; 24 | 2A977CAE1BC55CF10038BE80 /* IntroViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A977CAC1BC55CF10038BE80 /* IntroViewController.swift */; settings = {ASSET_TAGS = (); }; }; 25 | 2A977CAF1BC55CF10038BE80 /* SettingsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A977CAD1BC55CF10038BE80 /* SettingsViewController.swift */; settings = {ASSET_TAGS = (); }; }; 26 | 2A977CB41BC55D040038BE80 /* UIColor+String.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A977CB11BC55D040038BE80 /* UIColor+String.swift */; settings = {ASSET_TAGS = (); }; }; 27 | 2A977CB51BC55D040038BE80 /* UIView+CircularAnimation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A977CB21BC55D040038BE80 /* UIView+CircularAnimation.swift */; settings = {ASSET_TAGS = (); }; }; 28 | 2A977CB61BC55D040038BE80 /* UIView+IBInspectable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A977CB31BC55D040038BE80 /* UIView+IBInspectable.swift */; settings = {ASSET_TAGS = (); }; }; 29 | 2A977CB91BC55D160038BE80 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A977CB81BC55D160038BE80 /* AppDelegate.swift */; settings = {ASSET_TAGS = (); }; }; 30 | 2A977CBD1BC55D3F0038BE80 /* SettingsTheme.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A977CBC1BC55D3F0038BE80 /* SettingsTheme.swift */; settings = {ASSET_TAGS = (); }; }; 31 | 2A977CC01BC55D740038BE80 /* ProfileButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A977CBE1BC55D740038BE80 /* ProfileButton.swift */; settings = {ASSET_TAGS = (); }; }; 32 | 2A977CC11BC55D740038BE80 /* StarsOverlay.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A977CBF1BC55D740038BE80 /* StarsOverlay.swift */; settings = {ASSET_TAGS = (); }; }; 33 | 2ACECE401BA2BF2E005689AD /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 2ACECE3E1BA2BF2E005689AD /* Main.storyboard */; }; 34 | 2ACECE421BA2BF2E005689AD /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 2ACECE411BA2BF2E005689AD /* Assets.xcassets */; }; 35 | 2ACECE451BA2BF2E005689AD /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 2ACECE431BA2BF2E005689AD /* LaunchScreen.storyboard */; }; 36 | /* End PBXBuildFile section */ 37 | 38 | /* Begin PBXContainerItemProxy section */ 39 | 2A89D89A1BD6633300A2C503 /* PBXContainerItemProxy */ = { 40 | isa = PBXContainerItemProxy; 41 | containerPortal = 2ACECE2F1BA2BF2E005689AD /* Project object */; 42 | proxyType = 1; 43 | remoteGlobalIDString = 2A89D8941BD6633300A2C503; 44 | remoteInfo = StarWars; 45 | }; 46 | /* End PBXContainerItemProxy section */ 47 | 48 | /* Begin PBXCopyFilesBuildPhase section */ 49 | 2A89D8A11BD6633300A2C503 /* Embed Frameworks */ = { 50 | isa = PBXCopyFilesBuildPhase; 51 | buildActionMask = 2147483647; 52 | dstPath = ""; 53 | dstSubfolderSpec = 10; 54 | files = ( 55 | 2A89D89D1BD6633300A2C503 /* StarWars.framework in Embed Frameworks */, 56 | ); 57 | name = "Embed Frameworks"; 58 | runOnlyForDeploymentPostprocessing = 0; 59 | }; 60 | /* End PBXCopyFilesBuildPhase section */ 61 | 62 | /* Begin PBXFileReference section */ 63 | 2A05EF851BD4B9F600BF150F /* MainSettingsViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = MainSettingsViewController.swift; path = Controller/MainSettingsViewController.swift; sourceTree = ""; }; 64 | 2A89D8891BD6626D00A2C503 /* GothaProReg.otf */ = {isa = PBXFileReference; lastKnownFileType = file; name = GothaProReg.otf; path = Resources/GothaProReg.otf; sourceTree = ""; }; 65 | 2A89D88A1BD6628000A2C503 /* AnimationDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = AnimationDelegate.swift; path = Circular/AnimationDelegate.swift; sourceTree = ""; }; 66 | 2A89D88B1BD6628000A2C503 /* CircularRevealAnimator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = CircularRevealAnimator.swift; path = Circular/CircularRevealAnimator.swift; sourceTree = ""; }; 67 | 2A89D8951BD6633300A2C503 /* StarWars.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = StarWars.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 68 | 2A89D8971BD6633300A2C503 /* StarWars.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = StarWars.h; sourceTree = ""; }; 69 | 2A89D8991BD6633300A2C503 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 70 | 2A89D8A31BD663A000A2C503 /* Sprite.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Sprite.swift; path = ../../StarWars/StarWarsGLAnimator/Sprite.swift; sourceTree = ""; }; 71 | 2A89D8A41BD663A000A2C503 /* SpriteRender.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SpriteRender.swift; path = ../../StarWars/StarWarsGLAnimator/SpriteRender.swift; sourceTree = ""; }; 72 | 2A89D8A51BD663A000A2C503 /* StarWarsGLAnimator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = StarWarsGLAnimator.swift; path = ../../StarWars/StarWarsGLAnimator/StarWarsGLAnimator.swift; sourceTree = ""; }; 73 | 2A89D8A61BD663A000A2C503 /* Vector2.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Vector2.swift; path = ../../StarWars/StarWarsGLAnimator/Vector2.swift; sourceTree = ""; }; 74 | 2A89D8A71BD663A000A2C503 /* ViewTexture.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ViewTexture.swift; path = ../../StarWars/StarWarsGLAnimator/ViewTexture.swift; sourceTree = ""; }; 75 | 2A89D8AE1BD663B300A2C503 /* StarWarsUIDynamicAnimator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = StarWarsUIDynamicAnimator.swift; path = ../../StarWars/StarWarsUIDynamicAnimator/StarWarsUIDynamicAnimator.swift; sourceTree = ""; }; 76 | 2A89D8B11BD663C500A2C503 /* StarWarsUIViewAnimator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = StarWarsUIViewAnimator.swift; path = ../../StarWars/StarWarsUIViewAnimator/StarWarsUIViewAnimator.swift; sourceTree = ""; }; 77 | 2A977CAC1BC55CF10038BE80 /* IntroViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = IntroViewController.swift; path = Controller/IntroViewController.swift; sourceTree = ""; }; 78 | 2A977CAD1BC55CF10038BE80 /* SettingsViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SettingsViewController.swift; path = Controller/SettingsViewController.swift; sourceTree = ""; }; 79 | 2A977CB11BC55D040038BE80 /* UIColor+String.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = "UIColor+String.swift"; path = "Extension/UIColor+String.swift"; sourceTree = ""; }; 80 | 2A977CB21BC55D040038BE80 /* UIView+CircularAnimation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = "UIView+CircularAnimation.swift"; path = "Extension/UIView+CircularAnimation.swift"; sourceTree = ""; }; 81 | 2A977CB31BC55D040038BE80 /* UIView+IBInspectable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = "UIView+IBInspectable.swift"; path = "Extension/UIView+IBInspectable.swift"; sourceTree = ""; }; 82 | 2A977CB81BC55D160038BE80 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = AppDelegate.swift; path = Misc/AppDelegate.swift; sourceTree = ""; }; 83 | 2A977CBC1BC55D3F0038BE80 /* SettingsTheme.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SettingsTheme.swift; path = ViewModel/SettingsTheme.swift; sourceTree = ""; }; 84 | 2A977CBE1BC55D740038BE80 /* ProfileButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ProfileButton.swift; path = View/ProfileButton.swift; sourceTree = ""; }; 85 | 2A977CBF1BC55D740038BE80 /* StarsOverlay.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = StarsOverlay.swift; path = View/StarsOverlay.swift; sourceTree = ""; }; 86 | 2ACECE371BA2BF2E005689AD /* StarWarsDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = StarWarsDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; 87 | 2ACECE3F1BA2BF2E005689AD /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 88 | 2ACECE411BA2BF2E005689AD /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 89 | 2ACECE441BA2BF2E005689AD /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 90 | 2ACECE461BA2BF2E005689AD /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 91 | /* End PBXFileReference section */ 92 | 93 | /* Begin PBXFrameworksBuildPhase section */ 94 | 2A89D8911BD6633300A2C503 /* Frameworks */ = { 95 | isa = PBXFrameworksBuildPhase; 96 | buildActionMask = 2147483647; 97 | files = ( 98 | ); 99 | runOnlyForDeploymentPostprocessing = 0; 100 | }; 101 | 2ACECE341BA2BF2E005689AD /* Frameworks */ = { 102 | isa = PBXFrameworksBuildPhase; 103 | buildActionMask = 2147483647; 104 | files = ( 105 | 2A89D89C1BD6633300A2C503 /* StarWars.framework in Frameworks */, 106 | ); 107 | runOnlyForDeploymentPostprocessing = 0; 108 | }; 109 | /* End PBXFrameworksBuildPhase section */ 110 | 111 | /* Begin PBXGroup section */ 112 | 2A6955691BB584EF009AB18A /* Resources */ = { 113 | isa = PBXGroup; 114 | children = ( 115 | 2A89D8891BD6626D00A2C503 /* GothaProReg.otf */, 116 | ); 117 | name = Resources; 118 | sourceTree = ""; 119 | }; 120 | 2A89D8961BD6633300A2C503 /* StarWars */ = { 121 | isa = PBXGroup; 122 | children = ( 123 | 2A89D8A21BD6639700A2C503 /* StarWarsGLAnimator */, 124 | 2A89D8B01BD663BD00A2C503 /* StarWarsUIViewAnimator */, 125 | 2A89D8AD1BD663A600A2C503 /* StarWarsUIDynamicAnimator */, 126 | 2A89D8971BD6633300A2C503 /* StarWars.h */, 127 | 2A89D8991BD6633300A2C503 /* Info.plist */, 128 | ); 129 | path = StarWars; 130 | sourceTree = ""; 131 | }; 132 | 2A89D8A21BD6639700A2C503 /* StarWarsGLAnimator */ = { 133 | isa = PBXGroup; 134 | children = ( 135 | 2A89D8A31BD663A000A2C503 /* Sprite.swift */, 136 | 2A89D8A41BD663A000A2C503 /* SpriteRender.swift */, 137 | 2A89D8A51BD663A000A2C503 /* StarWarsGLAnimator.swift */, 138 | 2A89D8A61BD663A000A2C503 /* Vector2.swift */, 139 | 2A89D8A71BD663A000A2C503 /* ViewTexture.swift */, 140 | ); 141 | name = StarWarsGLAnimator; 142 | sourceTree = ""; 143 | }; 144 | 2A89D8AD1BD663A600A2C503 /* StarWarsUIDynamicAnimator */ = { 145 | isa = PBXGroup; 146 | children = ( 147 | 2A89D8AE1BD663B300A2C503 /* StarWarsUIDynamicAnimator.swift */, 148 | ); 149 | name = StarWarsUIDynamicAnimator; 150 | sourceTree = ""; 151 | }; 152 | 2A89D8B01BD663BD00A2C503 /* StarWarsUIViewAnimator */ = { 153 | isa = PBXGroup; 154 | children = ( 155 | 2A89D8B11BD663C500A2C503 /* StarWarsUIViewAnimator.swift */, 156 | ); 157 | name = StarWarsUIViewAnimator; 158 | sourceTree = ""; 159 | }; 160 | 2A977C981BC55CB20038BE80 /* Circular Animation */ = { 161 | isa = PBXGroup; 162 | children = ( 163 | 2A89D88A1BD6628000A2C503 /* AnimationDelegate.swift */, 164 | 2A89D88B1BD6628000A2C503 /* CircularRevealAnimator.swift */, 165 | ); 166 | name = "Circular Animation"; 167 | sourceTree = ""; 168 | }; 169 | 2A977CAB1BC55CE60038BE80 /* Controller */ = { 170 | isa = PBXGroup; 171 | children = ( 172 | 2A977CAC1BC55CF10038BE80 /* IntroViewController.swift */, 173 | 2A05EF851BD4B9F600BF150F /* MainSettingsViewController.swift */, 174 | 2A977CAD1BC55CF10038BE80 /* SettingsViewController.swift */, 175 | ); 176 | name = Controller; 177 | sourceTree = ""; 178 | }; 179 | 2A977CB01BC55CFA0038BE80 /* Extension */ = { 180 | isa = PBXGroup; 181 | children = ( 182 | 2A977CB11BC55D040038BE80 /* UIColor+String.swift */, 183 | 2A977CB21BC55D040038BE80 /* UIView+CircularAnimation.swift */, 184 | 2A977CB31BC55D040038BE80 /* UIView+IBInspectable.swift */, 185 | ); 186 | name = Extension; 187 | sourceTree = ""; 188 | }; 189 | 2A977CB71BC55D0F0038BE80 /* Misc */ = { 190 | isa = PBXGroup; 191 | children = ( 192 | 2A977CB81BC55D160038BE80 /* AppDelegate.swift */, 193 | ); 194 | name = Misc; 195 | sourceTree = ""; 196 | }; 197 | 2A977CBA1BC55D1C0038BE80 /* View */ = { 198 | isa = PBXGroup; 199 | children = ( 200 | 2A977CBE1BC55D740038BE80 /* ProfileButton.swift */, 201 | 2A977CBF1BC55D740038BE80 /* StarsOverlay.swift */, 202 | ); 203 | name = View; 204 | sourceTree = ""; 205 | }; 206 | 2A977CBB1BC55D380038BE80 /* ViewModel */ = { 207 | isa = PBXGroup; 208 | children = ( 209 | 2A977CBC1BC55D3F0038BE80 /* SettingsTheme.swift */, 210 | ); 211 | name = ViewModel; 212 | sourceTree = ""; 213 | }; 214 | 2ACECE2E1BA2BF2E005689AD = { 215 | isa = PBXGroup; 216 | children = ( 217 | 2ACECE391BA2BF2E005689AD /* StarWarsDemo */, 218 | 2A89D8961BD6633300A2C503 /* StarWars */, 219 | 2ACECE381BA2BF2E005689AD /* Products */, 220 | ); 221 | sourceTree = ""; 222 | }; 223 | 2ACECE381BA2BF2E005689AD /* Products */ = { 224 | isa = PBXGroup; 225 | children = ( 226 | 2ACECE371BA2BF2E005689AD /* StarWarsDemo.app */, 227 | 2A89D8951BD6633300A2C503 /* StarWars.framework */, 228 | ); 229 | name = Products; 230 | sourceTree = ""; 231 | }; 232 | 2ACECE391BA2BF2E005689AD /* StarWarsDemo */ = { 233 | isa = PBXGroup; 234 | children = ( 235 | 2A977CAB1BC55CE60038BE80 /* Controller */, 236 | 2A977CBB1BC55D380038BE80 /* ViewModel */, 237 | 2A977CBA1BC55D1C0038BE80 /* View */, 238 | 2A977CB71BC55D0F0038BE80 /* Misc */, 239 | 2A977CB01BC55CFA0038BE80 /* Extension */, 240 | 2A977C981BC55CB20038BE80 /* Circular Animation */, 241 | 2A6955691BB584EF009AB18A /* Resources */, 242 | 2ACECE3E1BA2BF2E005689AD /* Main.storyboard */, 243 | 2ACECE411BA2BF2E005689AD /* Assets.xcassets */, 244 | 2ACECE431BA2BF2E005689AD /* LaunchScreen.storyboard */, 245 | 2ACECE461BA2BF2E005689AD /* Info.plist */, 246 | ); 247 | name = StarWarsDemo; 248 | path = StarWarsAnimations; 249 | sourceTree = ""; 250 | }; 251 | /* End PBXGroup section */ 252 | 253 | /* Begin PBXHeadersBuildPhase section */ 254 | 2A89D8921BD6633300A2C503 /* Headers */ = { 255 | isa = PBXHeadersBuildPhase; 256 | buildActionMask = 2147483647; 257 | files = ( 258 | 2A89D8981BD6633300A2C503 /* StarWars.h in Headers */, 259 | ); 260 | runOnlyForDeploymentPostprocessing = 0; 261 | }; 262 | /* End PBXHeadersBuildPhase section */ 263 | 264 | /* Begin PBXNativeTarget section */ 265 | 2A89D8941BD6633300A2C503 /* StarWars */ = { 266 | isa = PBXNativeTarget; 267 | buildConfigurationList = 2A89D89E1BD6633300A2C503 /* Build configuration list for PBXNativeTarget "StarWars" */; 268 | buildPhases = ( 269 | 2A89D8901BD6633300A2C503 /* Sources */, 270 | 2A89D8911BD6633300A2C503 /* Frameworks */, 271 | 2A89D8921BD6633300A2C503 /* Headers */, 272 | 2A89D8931BD6633300A2C503 /* Resources */, 273 | ); 274 | buildRules = ( 275 | ); 276 | dependencies = ( 277 | ); 278 | name = StarWars; 279 | productName = StarWars; 280 | productReference = 2A89D8951BD6633300A2C503 /* StarWars.framework */; 281 | productType = "com.apple.product-type.framework"; 282 | }; 283 | 2ACECE361BA2BF2E005689AD /* StarWarsDemo */ = { 284 | isa = PBXNativeTarget; 285 | buildConfigurationList = 2ACECE491BA2BF2E005689AD /* Build configuration list for PBXNativeTarget "StarWarsDemo" */; 286 | buildPhases = ( 287 | 2ACECE331BA2BF2E005689AD /* Sources */, 288 | 2ACECE341BA2BF2E005689AD /* Frameworks */, 289 | 2ACECE351BA2BF2E005689AD /* Resources */, 290 | 2A89D8A11BD6633300A2C503 /* Embed Frameworks */, 291 | ); 292 | buildRules = ( 293 | ); 294 | dependencies = ( 295 | 2A89D89B1BD6633300A2C503 /* PBXTargetDependency */, 296 | ); 297 | name = StarWarsDemo; 298 | productName = StarWarsAnimations; 299 | productReference = 2ACECE371BA2BF2E005689AD /* StarWarsDemo.app */; 300 | productType = "com.apple.product-type.application"; 301 | }; 302 | /* End PBXNativeTarget section */ 303 | 304 | /* Begin PBXProject section */ 305 | 2ACECE2F1BA2BF2E005689AD /* Project object */ = { 306 | isa = PBXProject; 307 | attributes = { 308 | LastSwiftUpdateCheck = 0700; 309 | LastUpgradeCheck = 0700; 310 | ORGANIZATIONNAME = Yalantis; 311 | TargetAttributes = { 312 | 2A89D8941BD6633300A2C503 = { 313 | CreatedOnToolsVersion = 7.0.1; 314 | }; 315 | 2ACECE361BA2BF2E005689AD = { 316 | CreatedOnToolsVersion = 7.0; 317 | }; 318 | }; 319 | }; 320 | buildConfigurationList = 2ACECE321BA2BF2E005689AD /* Build configuration list for PBXProject "StarWarsAnimations" */; 321 | compatibilityVersion = "Xcode 3.2"; 322 | developmentRegion = English; 323 | hasScannedForEncodings = 0; 324 | knownRegions = ( 325 | en, 326 | Base, 327 | ); 328 | mainGroup = 2ACECE2E1BA2BF2E005689AD; 329 | productRefGroup = 2ACECE381BA2BF2E005689AD /* Products */; 330 | projectDirPath = ""; 331 | projectRoot = ""; 332 | targets = ( 333 | 2ACECE361BA2BF2E005689AD /* StarWarsDemo */, 334 | 2A89D8941BD6633300A2C503 /* StarWars */, 335 | ); 336 | }; 337 | /* End PBXProject section */ 338 | 339 | /* Begin PBXResourcesBuildPhase section */ 340 | 2A89D8931BD6633300A2C503 /* Resources */ = { 341 | isa = PBXResourcesBuildPhase; 342 | buildActionMask = 2147483647; 343 | files = ( 344 | ); 345 | runOnlyForDeploymentPostprocessing = 0; 346 | }; 347 | 2ACECE351BA2BF2E005689AD /* Resources */ = { 348 | isa = PBXResourcesBuildPhase; 349 | buildActionMask = 2147483647; 350 | files = ( 351 | 2A6F123B1BD6662F00D12C56 /* GothaProReg.otf in Resources */, 352 | 2ACECE451BA2BF2E005689AD /* LaunchScreen.storyboard in Resources */, 353 | 2ACECE421BA2BF2E005689AD /* Assets.xcassets in Resources */, 354 | 2ACECE401BA2BF2E005689AD /* Main.storyboard in Resources */, 355 | ); 356 | runOnlyForDeploymentPostprocessing = 0; 357 | }; 358 | /* End PBXResourcesBuildPhase section */ 359 | 360 | /* Begin PBXSourcesBuildPhase section */ 361 | 2A89D8901BD6633300A2C503 /* Sources */ = { 362 | isa = PBXSourcesBuildPhase; 363 | buildActionMask = 2147483647; 364 | files = ( 365 | 2A89D8A91BD663A000A2C503 /* SpriteRender.swift in Sources */, 366 | 2A89D8AB1BD663A000A2C503 /* Vector2.swift in Sources */, 367 | 2A89D8AA1BD663A000A2C503 /* StarWarsGLAnimator.swift in Sources */, 368 | 2A89D8AF1BD663B300A2C503 /* StarWarsUIDynamicAnimator.swift in Sources */, 369 | 2A89D8B21BD663C500A2C503 /* StarWarsUIViewAnimator.swift in Sources */, 370 | 2A89D8AC1BD663A000A2C503 /* ViewTexture.swift in Sources */, 371 | 2A89D8A81BD663A000A2C503 /* Sprite.swift in Sources */, 372 | ); 373 | runOnlyForDeploymentPostprocessing = 0; 374 | }; 375 | 2ACECE331BA2BF2E005689AD /* Sources */ = { 376 | isa = PBXSourcesBuildPhase; 377 | buildActionMask = 2147483647; 378 | files = ( 379 | 2A977CAF1BC55CF10038BE80 /* SettingsViewController.swift in Sources */, 380 | 2A977CB61BC55D040038BE80 /* UIView+IBInspectable.swift in Sources */, 381 | 2A89D88C1BD6628000A2C503 /* AnimationDelegate.swift in Sources */, 382 | 2A977CAE1BC55CF10038BE80 /* IntroViewController.swift in Sources */, 383 | 2A977CB41BC55D040038BE80 /* UIColor+String.swift in Sources */, 384 | 2A977CB51BC55D040038BE80 /* UIView+CircularAnimation.swift in Sources */, 385 | 2A977CC11BC55D740038BE80 /* StarsOverlay.swift in Sources */, 386 | 2A977CC01BC55D740038BE80 /* ProfileButton.swift in Sources */, 387 | 2A05EF861BD4B9F600BF150F /* MainSettingsViewController.swift in Sources */, 388 | 2A977CB91BC55D160038BE80 /* AppDelegate.swift in Sources */, 389 | 2A89D88D1BD6628000A2C503 /* CircularRevealAnimator.swift in Sources */, 390 | 2A977CBD1BC55D3F0038BE80 /* SettingsTheme.swift in Sources */, 391 | ); 392 | runOnlyForDeploymentPostprocessing = 0; 393 | }; 394 | /* End PBXSourcesBuildPhase section */ 395 | 396 | /* Begin PBXTargetDependency section */ 397 | 2A89D89B1BD6633300A2C503 /* PBXTargetDependency */ = { 398 | isa = PBXTargetDependency; 399 | target = 2A89D8941BD6633300A2C503 /* StarWars */; 400 | targetProxy = 2A89D89A1BD6633300A2C503 /* PBXContainerItemProxy */; 401 | }; 402 | /* End PBXTargetDependency section */ 403 | 404 | /* Begin PBXVariantGroup section */ 405 | 2ACECE3E1BA2BF2E005689AD /* Main.storyboard */ = { 406 | isa = PBXVariantGroup; 407 | children = ( 408 | 2ACECE3F1BA2BF2E005689AD /* Base */, 409 | ); 410 | name = Main.storyboard; 411 | sourceTree = ""; 412 | }; 413 | 2ACECE431BA2BF2E005689AD /* LaunchScreen.storyboard */ = { 414 | isa = PBXVariantGroup; 415 | children = ( 416 | 2ACECE441BA2BF2E005689AD /* Base */, 417 | ); 418 | name = LaunchScreen.storyboard; 419 | sourceTree = ""; 420 | }; 421 | /* End PBXVariantGroup section */ 422 | 423 | /* Begin XCBuildConfiguration section */ 424 | 2A89D89F1BD6633300A2C503 /* Debug */ = { 425 | isa = XCBuildConfiguration; 426 | buildSettings = { 427 | CLANG_ENABLE_MODULES = YES; 428 | CURRENT_PROJECT_VERSION = 1; 429 | DEFINES_MODULE = YES; 430 | DYLIB_COMPATIBILITY_VERSION = 1; 431 | DYLIB_CURRENT_VERSION = 1; 432 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 433 | INFOPLIST_FILE = StarWars/Info.plist; 434 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 435 | IPHONEOS_DEPLOYMENT_TARGET = 8.4; 436 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 437 | PRODUCT_BUNDLE_IDENTIFIER = com.Yalantis.StarWars.Animation; 438 | PRODUCT_NAME = "$(TARGET_NAME)"; 439 | SKIP_INSTALL = YES; 440 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 441 | VERSIONING_SYSTEM = "apple-generic"; 442 | VERSION_INFO_PREFIX = ""; 443 | }; 444 | name = Debug; 445 | }; 446 | 2A89D8A01BD6633300A2C503 /* Release */ = { 447 | isa = XCBuildConfiguration; 448 | buildSettings = { 449 | CLANG_ENABLE_MODULES = YES; 450 | CURRENT_PROJECT_VERSION = 1; 451 | DEFINES_MODULE = YES; 452 | DYLIB_COMPATIBILITY_VERSION = 1; 453 | DYLIB_CURRENT_VERSION = 1; 454 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 455 | INFOPLIST_FILE = StarWars/Info.plist; 456 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 457 | IPHONEOS_DEPLOYMENT_TARGET = 8.4; 458 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 459 | PRODUCT_BUNDLE_IDENTIFIER = com.Yalantis.StarWars.Animation; 460 | PRODUCT_NAME = "$(TARGET_NAME)"; 461 | SKIP_INSTALL = YES; 462 | VERSIONING_SYSTEM = "apple-generic"; 463 | VERSION_INFO_PREFIX = ""; 464 | }; 465 | name = Release; 466 | }; 467 | 2ACECE471BA2BF2E005689AD /* Debug */ = { 468 | isa = XCBuildConfiguration; 469 | buildSettings = { 470 | ALWAYS_SEARCH_USER_PATHS = NO; 471 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 472 | CLANG_CXX_LIBRARY = "libc++"; 473 | CLANG_ENABLE_MODULES = YES; 474 | CLANG_ENABLE_OBJC_ARC = YES; 475 | CLANG_WARN_BOOL_CONVERSION = YES; 476 | CLANG_WARN_CONSTANT_CONVERSION = YES; 477 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 478 | CLANG_WARN_EMPTY_BODY = YES; 479 | CLANG_WARN_ENUM_CONVERSION = YES; 480 | CLANG_WARN_INT_CONVERSION = YES; 481 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 482 | CLANG_WARN_UNREACHABLE_CODE = YES; 483 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 484 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 485 | COPY_PHASE_STRIP = NO; 486 | DEBUG_INFORMATION_FORMAT = dwarf; 487 | ENABLE_STRICT_OBJC_MSGSEND = YES; 488 | ENABLE_TESTABILITY = YES; 489 | GCC_C_LANGUAGE_STANDARD = gnu99; 490 | GCC_DYNAMIC_NO_PIC = NO; 491 | GCC_NO_COMMON_BLOCKS = YES; 492 | GCC_OPTIMIZATION_LEVEL = 0; 493 | GCC_PREPROCESSOR_DEFINITIONS = ( 494 | "DEBUG=1", 495 | "$(inherited)", 496 | ); 497 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 498 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 499 | GCC_WARN_UNDECLARED_SELECTOR = YES; 500 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 501 | GCC_WARN_UNUSED_FUNCTION = YES; 502 | GCC_WARN_UNUSED_VARIABLE = YES; 503 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 504 | MTL_ENABLE_DEBUG_INFO = YES; 505 | ONLY_ACTIVE_ARCH = YES; 506 | SDKROOT = iphoneos; 507 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 508 | TARGETED_DEVICE_FAMILY = "1,2"; 509 | }; 510 | name = Debug; 511 | }; 512 | 2ACECE481BA2BF2E005689AD /* Release */ = { 513 | isa = XCBuildConfiguration; 514 | buildSettings = { 515 | ALWAYS_SEARCH_USER_PATHS = NO; 516 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 517 | CLANG_CXX_LIBRARY = "libc++"; 518 | CLANG_ENABLE_MODULES = YES; 519 | CLANG_ENABLE_OBJC_ARC = YES; 520 | CLANG_WARN_BOOL_CONVERSION = YES; 521 | CLANG_WARN_CONSTANT_CONVERSION = YES; 522 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 523 | CLANG_WARN_EMPTY_BODY = YES; 524 | CLANG_WARN_ENUM_CONVERSION = YES; 525 | CLANG_WARN_INT_CONVERSION = YES; 526 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 527 | CLANG_WARN_UNREACHABLE_CODE = YES; 528 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 529 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 530 | COPY_PHASE_STRIP = NO; 531 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 532 | ENABLE_NS_ASSERTIONS = NO; 533 | ENABLE_STRICT_OBJC_MSGSEND = YES; 534 | GCC_C_LANGUAGE_STANDARD = gnu99; 535 | GCC_NO_COMMON_BLOCKS = YES; 536 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 537 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 538 | GCC_WARN_UNDECLARED_SELECTOR = YES; 539 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 540 | GCC_WARN_UNUSED_FUNCTION = YES; 541 | GCC_WARN_UNUSED_VARIABLE = YES; 542 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 543 | MTL_ENABLE_DEBUG_INFO = NO; 544 | SDKROOT = iphoneos; 545 | TARGETED_DEVICE_FAMILY = "1,2"; 546 | VALIDATE_PRODUCT = YES; 547 | }; 548 | name = Release; 549 | }; 550 | 2ACECE4A1BA2BF2E005689AD /* Debug */ = { 551 | isa = XCBuildConfiguration; 552 | buildSettings = { 553 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 554 | CLANG_ENABLE_MODULES = YES; 555 | EMBEDDED_CONTENT_CONTAINS_SWIFT = YES; 556 | INFOPLIST_FILE = StarWarsAnimations/Info.plist; 557 | IPHONEOS_DEPLOYMENT_TARGET = 8.4; 558 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 559 | PRODUCT_BUNDLE_IDENTIFIER = com.Yalantis.StarWars; 560 | PRODUCT_NAME = "$(TARGET_NAME)"; 561 | }; 562 | name = Debug; 563 | }; 564 | 2ACECE4B1BA2BF2E005689AD /* Release */ = { 565 | isa = XCBuildConfiguration; 566 | buildSettings = { 567 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 568 | CLANG_ENABLE_MODULES = YES; 569 | EMBEDDED_CONTENT_CONTAINS_SWIFT = YES; 570 | INFOPLIST_FILE = StarWarsAnimations/Info.plist; 571 | IPHONEOS_DEPLOYMENT_TARGET = 8.4; 572 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 573 | PRODUCT_BUNDLE_IDENTIFIER = com.Yalantis.StarWars; 574 | PRODUCT_NAME = "$(TARGET_NAME)"; 575 | }; 576 | name = Release; 577 | }; 578 | /* End XCBuildConfiguration section */ 579 | 580 | /* Begin XCConfigurationList section */ 581 | 2A89D89E1BD6633300A2C503 /* Build configuration list for PBXNativeTarget "StarWars" */ = { 582 | isa = XCConfigurationList; 583 | buildConfigurations = ( 584 | 2A89D89F1BD6633300A2C503 /* Debug */, 585 | 2A89D8A01BD6633300A2C503 /* Release */, 586 | ); 587 | defaultConfigurationIsVisible = 0; 588 | defaultConfigurationName = Release; 589 | }; 590 | 2ACECE321BA2BF2E005689AD /* Build configuration list for PBXProject "StarWarsAnimations" */ = { 591 | isa = XCConfigurationList; 592 | buildConfigurations = ( 593 | 2ACECE471BA2BF2E005689AD /* Debug */, 594 | 2ACECE481BA2BF2E005689AD /* Release */, 595 | ); 596 | defaultConfigurationIsVisible = 0; 597 | defaultConfigurationName = Release; 598 | }; 599 | 2ACECE491BA2BF2E005689AD /* Build configuration list for PBXNativeTarget "StarWarsDemo" */ = { 600 | isa = XCConfigurationList; 601 | buildConfigurations = ( 602 | 2ACECE4A1BA2BF2E005689AD /* Debug */, 603 | 2ACECE4B1BA2BF2E005689AD /* Release */, 604 | ); 605 | defaultConfigurationIsVisible = 0; 606 | defaultConfigurationName = Release; 607 | }; 608 | /* End XCConfigurationList section */ 609 | }; 610 | rootObject = 2ACECE2F1BA2BF2E005689AD /* Project object */; 611 | } 612 | -------------------------------------------------------------------------------- /Example/StarWarsAnimations/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | GothamPro 11 | GothamPro 12 | GothamPro 13 | GothamPro 14 | GothamPro 15 | GothamPro 16 | GothamPro 17 | GothamPro 18 | GothamPro 19 | GothamPro 20 | GothamPro 21 | GothamPro 22 | GothamPro 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 48 | 73 | 74 | 75 | 76 | 77 | 82 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 258 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 293 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 328 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 378 | 385 | 386 | 387 | 388 | 389 | 390 | 391 | 392 | 393 | 394 | 395 | 396 | 397 | 398 | 399 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 419 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 427 | 428 | 429 | 430 | 431 | 432 | 433 | 434 | 435 | 436 | 437 | 438 | 439 | 440 | 441 | 442 | 443 | 444 | 445 | 446 | 447 | 448 | 449 | 450 | 451 | 452 | 453 | 454 | 455 | 456 | 457 | 458 | 459 | 460 | 461 | 462 | 463 | 464 | 465 | 466 | 467 | 468 | 469 | 470 | 471 | 472 | 473 | 474 | 475 | 476 | 477 | 478 | 479 | 480 | 481 | 482 | 483 | 484 | 485 | 486 | 487 | 488 | 489 | 490 | 491 | 492 | 493 | 494 | 495 | 496 | 497 | 498 | 499 | 500 | --------------------------------------------------------------------------------