├── .gitignore
├── Examples
└── TweenApp
│ ├── Podfile
│ ├── Podfile.lock
│ ├── Pods
│ ├── Local Podspecs
│ │ └── Ubergang.podspec.json
│ ├── Manifest.lock
│ ├── Pods.xcodeproj
│ │ └── project.pbxproj
│ ├── Target Support Files
│ │ ├── Pods-TweenApp
│ │ │ ├── Info.plist
│ │ │ ├── Pods-TweenApp-Info.plist
│ │ │ ├── Pods-TweenApp-acknowledgements.markdown
│ │ │ ├── Pods-TweenApp-acknowledgements.plist
│ │ │ ├── Pods-TweenApp-dummy.m
│ │ │ ├── Pods-TweenApp-frameworks.sh
│ │ │ ├── Pods-TweenApp-resources.sh
│ │ │ ├── Pods-TweenApp-umbrella.h
│ │ │ ├── Pods-TweenApp.debug.xcconfig
│ │ │ ├── Pods-TweenApp.modulemap
│ │ │ └── Pods-TweenApp.release.xcconfig
│ │ └── Ubergang
│ │ │ ├── Info.plist
│ │ │ ├── Ubergang-Info.plist
│ │ │ ├── Ubergang-dummy.m
│ │ │ ├── Ubergang-prefix.pch
│ │ │ ├── Ubergang-umbrella.h
│ │ │ ├── Ubergang.modulemap
│ │ │ └── Ubergang.xcconfig
│ └── Ubergang
│ │ ├── LICENSE
│ │ ├── README.md
│ │ └── Ubergang
│ │ ├── Core
│ │ ├── Engine.swift
│ │ ├── Timer.swift
│ │ └── UTweenSetup.swift
│ │ ├── Data
│ │ ├── TweenDirection.swift
│ │ ├── TweenMemoryReference.swift
│ │ └── TweenOptions.swift
│ │ ├── Ease
│ │ ├── Back.swift
│ │ ├── Bounce.swift
│ │ ├── Circ.swift
│ │ ├── Cubic.swift
│ │ ├── Ease.swift
│ │ ├── Elastic.swift
│ │ ├── Expo.swift
│ │ ├── Linear.swift
│ │ ├── Quad.swift
│ │ ├── Quart.swift
│ │ ├── Quint.swift
│ │ └── Sine.swift
│ │ ├── Extension
│ │ ├── CGPath.swift
│ │ ├── CGPointExtension.h
│ │ ├── CGPointExtension.m
│ │ ├── UIBezierPath+Interpolation.h
│ │ └── UIBezierPath+Interpolation.m
│ │ ├── Protocols
│ │ ├── Numeric.swift
│ │ ├── Tweenable.swift
│ │ ├── TypeTweenable.swift
│ │ ├── UTweenLoggable.swift
│ │ └── WeaklyLoopable.swift
│ │ ├── Tween
│ │ ├── BezierPathTween.swift
│ │ ├── CGPointTween.swift
│ │ ├── ColorTween.swift
│ │ ├── NumericTween.swift
│ │ ├── TransformTween.swift
│ │ ├── UTimeline.swift
│ │ ├── UTween.h
│ │ ├── UTween.swift
│ │ └── UTweenBase.swift
│ │ ├── UTweenBuilder.swift
│ │ └── Util
│ │ ├── Bezier.swift
│ │ └── Math.swift
│ ├── TweenApp.xcodeproj
│ ├── project.pbxproj
│ └── project.xcworkspace
│ │ └── contents.xcworkspacedata
│ ├── TweenApp.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ ├── IDEWorkspaceChecks.plist
│ │ └── WorkspaceSettings.xcsettings
│ └── TweenApp
│ ├── AdditiveAnimationViewController.swift
│ ├── AppDelegate.swift
│ ├── Assets.xcassets
│ ├── AppIcon.appiconset
│ │ ├── Contents.json
│ │ ├── Icon-40.png
│ │ ├── Icon-40@2x.png
│ │ ├── Icon-40@3x.png
│ │ ├── Icon-60@2x.png
│ │ ├── Icon-60@3x.png
│ │ ├── Icon-72.png
│ │ ├── Icon-72@2x.png
│ │ ├── Icon-76.png
│ │ ├── Icon-76@2x.png
│ │ ├── Icon-83.5@2x.png
│ │ ├── Icon-Small-50.png
│ │ ├── Icon-Small-50@2x.png
│ │ ├── Icon-Small.png
│ │ ├── Icon-Small@2x.png
│ │ ├── Icon-Small@3x.png
│ │ ├── Icon.png
│ │ └── Icon@2x.png
│ ├── CircleBG.imageset
│ │ ├── Contents.json
│ │ └── circleBG.png
│ ├── CircleOutline.imageset
│ │ ├── CircleOutline.png
│ │ └── Contents.json
│ ├── Contents.json
│ ├── Dot.imageset
│ │ ├── Contents.json
│ │ └── dot.png
│ ├── PauseIcon.imageset
│ │ ├── Contents.json
│ │ └── PauseIcon.png
│ ├── PlayIcon.imageset
│ │ ├── Contents.json
│ │ └── PlayIcon.png
│ ├── ReverseIcon.imageset
│ │ ├── Contents.json
│ │ └── ReverseIcon.png
│ ├── SliderThumb.imageset
│ │ ├── Contents.json
│ │ └── SliderThumb.png
│ └── StopIcon.imageset
│ │ ├── Contents.json
│ │ └── StopIcon.png
│ ├── Base.lproj
│ ├── LaunchScreen.storyboard
│ └── Main.storyboard
│ ├── BezierPathViewController.swift
│ ├── ColorViewController.swift
│ ├── ConstraintViewController.swift
│ ├── CurveThroughViewController.swift
│ ├── DynamicViewController.swift
│ ├── ExampleViewController.swift
│ ├── Info.plist
│ ├── InsertTimelineViewController.swift
│ ├── MainTableViewController.swift
│ ├── NumericViewController.swift
│ ├── ParticleViewController.swift
│ ├── ProgressViewController.swift
│ ├── TimelinesViewController.swift
│ ├── TransformViewController.swift
│ ├── Ubergang-Bridging-Header.h
│ └── Views
│ ├── CircularProgressBar.swift
│ ├── ReverseButton.swift
│ ├── TitleIconTableViewCell.swift
│ ├── TweenControlButton.swift
│ ├── TweenControls.xib
│ ├── TweenControlsView.swift
│ └── TweenStatusView.swift
├── Framework
└── Ubergang.framework
│ ├── Headers
│ └── Ubergang-Swift.h
│ ├── Info.plist
│ ├── Modules
│ ├── Ubergang.swiftmodule
│ │ ├── x86_64.swiftdoc
│ │ └── x86_64.swiftmodule
│ └── module.modulemap
│ └── Ubergang
├── LICENSE
├── Movies
├── exampleConstraints.gif
├── exampleConstraints.mov
├── exampleDynamic.mov
├── examplePath.gif
├── examplePath.mov
├── exampleTimeline.gif
└── exampleTimeline.mov
├── README.md
├── Ubergang-Bridging-Header.h
├── Ubergang.png
├── Ubergang.podspec
├── Ubergang.xcodeproj
├── project.pbxproj
└── project.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ └── IDEWorkspaceChecks.plist
├── Ubergang.xcworkspace
├── contents.xcworkspacedata
└── xcshareddata
│ ├── IDEWorkspaceChecks.plist
│ └── WorkspaceSettings.xcsettings
└── Ubergang
├── Core
├── Engine.swift
├── Timer.swift
└── UTweenSetup.swift
├── Data
├── TweenDirection.swift
├── TweenMemoryReference.swift
└── TweenOptions.swift
├── Ease
├── Back.swift
├── Bounce.swift
├── Circ.swift
├── Cubic.swift
├── Ease.swift
├── Elastic.swift
├── Expo.swift
├── Linear.swift
├── Quad.swift
├── Quart.swift
├── Quint.swift
└── Sine.swift
├── Extension
├── CGPath.swift
├── CGPointExtension.h
├── CGPointExtension.m
├── UIBezierPath+Interpolation.h
└── UIBezierPath+Interpolation.m
├── Info.plist
├── Protocols
├── Numeric.swift
├── Tweenable.swift
├── TypeTweenable.swift
├── UTweenLoggable.swift
└── WeaklyLoopable.swift
├── Tween
├── BezierPathTween.swift
├── CGPointTween.swift
├── ColorTween.swift
├── NumericTween.swift
├── TransformTween.swift
├── UTimeline.swift
├── UTween.h
├── UTween.swift
└── UTweenBase.swift
├── UTweenBuilder.swift
└── Util
├── Bezier.swift
└── Math.swift
/.gitignore:
--------------------------------------------------------------------------------
1 | # Xcode
2 | #
3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
4 |
5 | ## Build generated
6 | build/
7 | DerivedData
8 |
9 | ## Various settings
10 | *.pbxuser
11 | !default.pbxuser
12 | *.mode1v3
13 | !default.mode1v3
14 | *.mode2v3
15 | !default.mode2v3
16 | *.perspectivev3
17 | !default.perspectivev3
18 | xcuserdata
19 |
20 | ## Other
21 | *.xccheckout
22 | *.moved-aside
23 | *.xcuserstate
24 | *.xcscmblueprint
25 |
26 | ## Obj-C/Swift specific
27 | *.hmap
28 | *.ipa
29 |
30 | ## Playgrounds
31 | timeline.xctimeline
32 | playground.xcworkspace
33 |
34 | # Swift Package Manager
35 | #
36 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
37 | # Packages/
38 | .build/
39 |
40 | # CocoaPods
41 | #
42 | # We recommend against adding the Pods directory to your .gitignore. However
43 | # you should judge for yourself, the pros and cons are mentioned at:
44 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
45 | #
46 | # Pods/
47 |
48 | # Carthage
49 | #
50 | # Add this line if you want to avoid checking in source code from Carthage dependencies.
51 | # Carthage/Checkouts
52 |
53 | Carthage/Build
54 |
55 | # fastlane
56 | #
57 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
58 | # screenshots whenever they are needed.
59 | # For more information about the recommended setup visit:
60 | # https://github.com/fastlane/fastlane/blob/master/docs/Gitignore.md
61 |
62 | fastlane/report.xml
63 | fastlane/screenshots
64 | Output
65 |
--------------------------------------------------------------------------------
/Examples/TweenApp/Podfile:
--------------------------------------------------------------------------------
1 | # Uncomment this line to define a global platform for your project
2 | platform :ios, '8.2'
3 | # Uncomment this line if you're using Swift
4 | use_frameworks!
5 |
6 | #pod 'Ubergang'
7 | pod 'Ubergang', :path => '~/Workspace/mobile/Ubergang'
8 |
9 | target 'TweenApp' do
10 |
11 | end
12 |
--------------------------------------------------------------------------------
/Examples/TweenApp/Podfile.lock:
--------------------------------------------------------------------------------
1 | PODS:
2 | - Ubergang (1.2.0)
3 |
4 | DEPENDENCIES:
5 | - Ubergang (from `~/Workspace/mobile/Ubergang`)
6 |
7 | EXTERNAL SOURCES:
8 | Ubergang:
9 | :path: "~/Workspace/mobile/Ubergang"
10 |
11 | SPEC CHECKSUMS:
12 | Ubergang: b5db74966f6fabcab09c4fbc207d316aa9469b06
13 |
14 | PODFILE CHECKSUM: f0dbfb25a7fe3142bfc0573ae587a9b44a3f0491
15 |
16 | COCOAPODS: 1.7.2
17 |
--------------------------------------------------------------------------------
/Examples/TweenApp/Pods/Local Podspecs/Ubergang.podspec.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Ubergang",
3 | "version": "1.2.0",
4 | "summary": "A tweening engine written in Swift.",
5 | "homepage": "https://github.com/RobinFalko/Ubergang",
6 | "license": {
7 | "type": "Apache",
8 | "file": "LICENSE"
9 | },
10 | "authors": {
11 | "Robin Frielingsdorf": "mail@robinfalko.com"
12 | },
13 | "source": {
14 | "git": "https://github.com/RobinFalko/Ubergang.git",
15 | "tag": "1.2.0"
16 | },
17 | "source_files": "Ubergang/**/*.{h,m,swift}",
18 | "module_name": "Ubergang",
19 | "swift_versions": "5.0",
20 | "platforms": {
21 | "ios": "8.0"
22 | },
23 | "swift_version": "5.0"
24 | }
25 |
--------------------------------------------------------------------------------
/Examples/TweenApp/Pods/Manifest.lock:
--------------------------------------------------------------------------------
1 | PODS:
2 | - Ubergang (1.2.0)
3 |
4 | DEPENDENCIES:
5 | - Ubergang (from `~/Workspace/mobile/Ubergang`)
6 |
7 | EXTERNAL SOURCES:
8 | Ubergang:
9 | :path: "~/Workspace/mobile/Ubergang"
10 |
11 | SPEC CHECKSUMS:
12 | Ubergang: b5db74966f6fabcab09c4fbc207d316aa9469b06
13 |
14 | PODFILE CHECKSUM: f0dbfb25a7fe3142bfc0573ae587a9b44a3f0491
15 |
16 | COCOAPODS: 1.7.2
17 |
--------------------------------------------------------------------------------
/Examples/TweenApp/Pods/Target Support Files/Pods-TweenApp/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.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | ${CURRENT_PROJECT_VERSION}
23 | NSPrincipalClass
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/Examples/TweenApp/Pods/Target Support Files/Pods-TweenApp/Pods-TweenApp-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.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | ${CURRENT_PROJECT_VERSION}
23 | NSPrincipalClass
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/Examples/TweenApp/Pods/Target Support Files/Pods-TweenApp/Pods-TweenApp-dummy.m:
--------------------------------------------------------------------------------
1 | #import
2 | @interface PodsDummy_Pods_TweenApp : NSObject
3 | @end
4 | @implementation PodsDummy_Pods_TweenApp
5 | @end
6 |
--------------------------------------------------------------------------------
/Examples/TweenApp/Pods/Target Support Files/Pods-TweenApp/Pods-TweenApp-umbrella.h:
--------------------------------------------------------------------------------
1 | #ifdef __OBJC__
2 | #import
3 | #else
4 | #ifndef FOUNDATION_EXPORT
5 | #if defined(__cplusplus)
6 | #define FOUNDATION_EXPORT extern "C"
7 | #else
8 | #define FOUNDATION_EXPORT extern
9 | #endif
10 | #endif
11 | #endif
12 |
13 |
14 | FOUNDATION_EXPORT double Pods_TweenAppVersionNumber;
15 | FOUNDATION_EXPORT const unsigned char Pods_TweenAppVersionString[];
16 |
17 |
--------------------------------------------------------------------------------
/Examples/TweenApp/Pods/Target Support Files/Pods-TweenApp/Pods-TweenApp.debug.xcconfig:
--------------------------------------------------------------------------------
1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES
2 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Ubergang"
3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
4 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Ubergang/Ubergang.framework/Headers"
5 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks'
6 | OTHER_LDFLAGS = $(inherited) -framework "Ubergang"
7 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS
8 | PODS_BUILD_DIR = ${BUILD_DIR}
9 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
10 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/.
11 | PODS_ROOT = ${SRCROOT}/Pods
12 |
--------------------------------------------------------------------------------
/Examples/TweenApp/Pods/Target Support Files/Pods-TweenApp/Pods-TweenApp.modulemap:
--------------------------------------------------------------------------------
1 | framework module Pods_TweenApp {
2 | umbrella header "Pods-TweenApp-umbrella.h"
3 |
4 | export *
5 | module * { export * }
6 | }
7 |
--------------------------------------------------------------------------------
/Examples/TweenApp/Pods/Target Support Files/Pods-TweenApp/Pods-TweenApp.release.xcconfig:
--------------------------------------------------------------------------------
1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES
2 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Ubergang"
3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
4 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Ubergang/Ubergang.framework/Headers"
5 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks'
6 | OTHER_LDFLAGS = $(inherited) -framework "Ubergang"
7 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS
8 | PODS_BUILD_DIR = ${BUILD_DIR}
9 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
10 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/.
11 | PODS_ROOT = ${SRCROOT}/Pods
12 |
--------------------------------------------------------------------------------
/Examples/TweenApp/Pods/Target Support Files/Ubergang/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.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | ${CURRENT_PROJECT_VERSION}
23 | NSPrincipalClass
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/Examples/TweenApp/Pods/Target Support Files/Ubergang/Ubergang-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.2.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | ${CURRENT_PROJECT_VERSION}
23 | NSPrincipalClass
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/Examples/TweenApp/Pods/Target Support Files/Ubergang/Ubergang-dummy.m:
--------------------------------------------------------------------------------
1 | #import
2 | @interface PodsDummy_Ubergang : NSObject
3 | @end
4 | @implementation PodsDummy_Ubergang
5 | @end
6 |
--------------------------------------------------------------------------------
/Examples/TweenApp/Pods/Target Support Files/Ubergang/Ubergang-prefix.pch:
--------------------------------------------------------------------------------
1 | #ifdef __OBJC__
2 | #import
3 | #else
4 | #ifndef FOUNDATION_EXPORT
5 | #if defined(__cplusplus)
6 | #define FOUNDATION_EXPORT extern "C"
7 | #else
8 | #define FOUNDATION_EXPORT extern
9 | #endif
10 | #endif
11 | #endif
12 |
13 |
--------------------------------------------------------------------------------
/Examples/TweenApp/Pods/Target Support Files/Ubergang/Ubergang-umbrella.h:
--------------------------------------------------------------------------------
1 | #ifdef __OBJC__
2 | #import
3 | #else
4 | #ifndef FOUNDATION_EXPORT
5 | #if defined(__cplusplus)
6 | #define FOUNDATION_EXPORT extern "C"
7 | #else
8 | #define FOUNDATION_EXPORT extern
9 | #endif
10 | #endif
11 | #endif
12 |
13 | #import "CGPointExtension.h"
14 | #import "UIBezierPath+Interpolation.h"
15 | #import "UTween.h"
16 |
17 | FOUNDATION_EXPORT double UbergangVersionNumber;
18 | FOUNDATION_EXPORT const unsigned char UbergangVersionString[];
19 |
20 |
--------------------------------------------------------------------------------
/Examples/TweenApp/Pods/Target Support Files/Ubergang/Ubergang.modulemap:
--------------------------------------------------------------------------------
1 | framework module Ubergang {
2 | umbrella header "Ubergang-umbrella.h"
3 |
4 | export *
5 | module * { export * }
6 | }
7 |
--------------------------------------------------------------------------------
/Examples/TweenApp/Pods/Target Support Files/Ubergang/Ubergang.xcconfig:
--------------------------------------------------------------------------------
1 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/Ubergang
2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
3 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS
4 | PODS_BUILD_DIR = ${BUILD_DIR}
5 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
6 | PODS_ROOT = ${SRCROOT}
7 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/../../..
8 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
9 | SKIP_INSTALL = YES
10 |
--------------------------------------------------------------------------------
/Examples/TweenApp/Pods/Ubergang/Ubergang/Core/Engine.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Engine.swift
3 | // Ubergang
4 | //
5 | // Created by Robin Frielingsdorf on 09/01/16.
6 | // Copyright © 2016 Robin Falko. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import UIKit
11 |
12 | open class Engine: NSObject {
13 | public typealias Closure = () -> Void
14 |
15 | fileprivate var displayLink: CADisplayLink?
16 |
17 | var closures = [String : Closure]()
18 |
19 | var mapTable = NSMapTable(keyOptions: NSPointerFunctions.Options.strongMemory, valueOptions: NSPointerFunctions.Options.weakMemory)
20 |
21 | open static var instance: Engine = {
22 | let engine = Engine()
23 | engine.start()
24 | return engine
25 | }()
26 |
27 | func start() {
28 | if displayLink == nil {
29 | displayLink = CADisplayLink(target: self, selector: #selector(Engine.update))
30 | displayLink!.add(to: RunLoop.current, forMode: RunLoopMode.commonModes)
31 | }
32 | }
33 |
34 | func stop() {
35 | displayLink?.remove(from: RunLoop.current, forMode: RunLoopMode.commonModes)
36 | displayLink = nil
37 | }
38 |
39 | @objc func update() {
40 | let enumerator = mapTable.objectEnumerator()
41 | while let any: AnyObject = enumerator?.nextObject() as AnyObject! {
42 | if let loopable = any as? WeaklyLoopable {
43 | loopable.loopWeakly()
44 | }
45 | }
46 |
47 | for (_, closure) in closures {
48 | closure()
49 | }
50 | }
51 |
52 |
53 | func register(_ closure: @escaping Closure, forKey key: String) {
54 | closures[key] = closure
55 |
56 | start()
57 | }
58 |
59 |
60 | func register(_ loopable: WeaklyLoopable, forKey key: String) {
61 | mapTable.setObject(loopable as AnyObject?, forKey: key as AnyObject?)
62 |
63 | start()
64 | }
65 |
66 |
67 | func unregister(_ key: String) {
68 | mapTable.removeObject(forKey: key as AnyObject?)
69 |
70 | closures.removeValue(forKey: key)
71 |
72 | if mapTable.count == 0 && closures.isEmpty {
73 | stop()
74 | }
75 | }
76 |
77 |
78 | func contains(_ key: String) -> Bool {
79 | return mapTable.object(forKey: key as AnyObject?) != nil || closures[key] != nil
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/Examples/TweenApp/Pods/Ubergang/Ubergang/Core/Timer.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Timer.swift
3 | // Ubergang
4 | //
5 | // Created by Robin Frielingsdorf on 07/01/16.
6 | // Copyright © 2016 Robin Falko. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | open class Timer {
12 | open static let instance = Timer()
13 |
14 | fileprivate let id = "\(#file)_update"
15 |
16 | open static var delta:TimeInterval = TimeInterval(0)
17 | open static var time:TimeInterval = TimeInterval(0)
18 | fileprivate var lastUpdateTime:TimeInterval = TimeInterval(0)
19 |
20 | fileprivate init() {}
21 |
22 | func start() {
23 | self.lastUpdateTime = Date().timeIntervalSince1970
24 |
25 | Engine.instance.register(update, forKey: id)
26 | }
27 |
28 |
29 | func stop() {
30 | Engine.instance.unregister(id)
31 | }
32 |
33 |
34 | func update() {
35 | tick(Date().timeIntervalSince1970)
36 | }
37 |
38 |
39 | func tick(_ currentTime: TimeInterval) {
40 | if lastUpdateTime == 0.0 {
41 | Timer.delta = 0
42 | } else {
43 | Timer.delta = currentTime - self.lastUpdateTime
44 | }
45 |
46 | self.lastUpdateTime = Date().timeIntervalSince1970
47 |
48 | Timer.time += Timer.delta
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/Examples/TweenApp/Pods/Ubergang/Ubergang/Core/UTweenSetup.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UTweenSetup.swift
3 | // Ubergang
4 | //
5 | // Created by RF on 11/07/16.
6 | // Copyright © 2016 Robin Falko. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | open class UTweenSetup {
12 | open static let instance = UTweenSetup()
13 |
14 | fileprivate var isLoggingEnabled = false
15 |
16 | internal lazy var logger: UTweenLoggable? = {
17 | guard UTweenSetup.instance.isLoggingEnabled else { return nil }
18 | return UTweenLogger()
19 | }()
20 |
21 | fileprivate init() {}
22 |
23 | open func enableLogging(_ enabled: Bool) {
24 | isLoggingEnabled = enabled
25 | }
26 |
27 | open func enableLogging(_ enabled: Bool, withLogger logger: UTweenLoggable) {
28 | enableLogging(enabled)
29 | self.logger = logger
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/Examples/TweenApp/Pods/Ubergang/Ubergang/Data/TweenDirection.swift:
--------------------------------------------------------------------------------
1 | //
2 | // TweenDirection.swift
3 | // Ubergang
4 | //
5 | // Created by Robin Frielingsdorf on 10/04/16.
6 | // Copyright © 2016 Robin Falko. All rights reserved.
7 | //
8 |
9 | public enum TweenDirection {
10 | case forward, reverse
11 | }
12 |
--------------------------------------------------------------------------------
/Examples/TweenApp/Pods/Ubergang/Ubergang/Data/TweenMemoryReference.swift:
--------------------------------------------------------------------------------
1 | //
2 | // TweenMemoryReference.swift
3 | // Ubergang
4 | //
5 | // Created by Robin Frielingsdorf on 14/02/16.
6 | // Copyright © 2016 Robin Falko. All rights reserved.
7 | //
8 |
9 | public enum TweenMemoryReference {
10 | case weak, strong
11 | }
12 |
--------------------------------------------------------------------------------
/Examples/TweenApp/Pods/Ubergang/Ubergang/Data/TweenOptions.swift:
--------------------------------------------------------------------------------
1 | //
2 | // TweenOptions.swift
3 | // Ubergang
4 | //
5 | // Created by Robin Frielingsdorf on 20/01/16.
6 | // Copyright © 2016 Robin Falko. All rights reserved.
7 | //
8 |
9 | public func ==(a: TweenOptions, b: TweenOptions) -> Bool {
10 | switch (a, b) {
11 | case (.yoyo, .yoyo): return true
12 | case (.repeat(let l), .repeat(let r)) where l == r: return true
13 | default: return false
14 | }
15 | }
16 |
17 | internal extension Sequence where Iterator.Element == TweenOptions {
18 | func repeatCount() -> Int {
19 | var repeatCount = 0
20 | self.forEach {
21 | if case .repeat(let count) = $0 {
22 | repeatCount = count
23 | }
24 | }
25 |
26 | return repeatCount
27 | }
28 |
29 | func containsRepeat() -> Bool {
30 | return repeatCount() > 0
31 | }
32 |
33 | func containsYoyo() -> Bool {
34 | return self.contains(.yoyo)
35 | }
36 | }
37 |
38 | public enum TweenOptions: Equatable {
39 | case yoyo
40 | case `repeat`(Int)
41 | }
42 |
--------------------------------------------------------------------------------
/Examples/TweenApp/Pods/Ubergang/Ubergang/Ease/Back.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Back.swift
3 | // Ubergang
4 | //
5 | // Created by Robin Frielingsdorf on 07/01/16.
6 | // Copyright © 2016 Robin Falko. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | open class Back: Ease {
12 | /**
13 | Back ease in.
14 |
15 | - Parameter t: The value to be mapped going from 0 to `d`
16 | - Parameter b: The mapped start value
17 | - Parameter c: The mapped end value
18 | - Parameter d: The end value
19 | - Returns: The mapped result
20 | */
21 | open class func easeIn(t: Double, b: Double, c: Double, d: Double) -> Double {
22 | var t = t
23 | let s = 1.70158
24 | t/=d
25 | let postFix = t
26 | return c*(postFix)*t*((s+1)*t - s) + b
27 | }
28 |
29 | /**
30 | Back ease out.
31 |
32 | - Parameter t: The value to be mapped going from 0 to `d`
33 | - Parameter b: The mapped start value
34 | - Parameter c: The mapped end value
35 | - Parameter d: The end value
36 | - Returns: The mapped result
37 | */
38 | open class func easeOut(t: Double, b: Double, c: Double, d: Double) -> Double {
39 | var t = t
40 | let s = 1.70158
41 | t=t/d-1
42 | let f = (s+1)*t + s
43 | return c*(t*t*f + 1) + b
44 | }
45 |
46 | /**
47 | Back ease in out.
48 |
49 | - Parameter t: The value to be mapped going from 0 to `d`
50 | - Parameter b: The mapped start value
51 | - Parameter c: The mapped end value
52 | - Parameter d: The end value
53 | - Returns: The mapped result
54 | */
55 | open class func easeInOut(t: Double, b: Double, c: Double, d: Double) -> Double {
56 | var t = t
57 | var s = 1.70158
58 | t/=d/2
59 | if (t < 1) { s*=(1.525); return c/2*(t*t*(((s)+1)*t - s)) + b }
60 | t-=2
61 | let postFix = t
62 | s*=(1.525)
63 | let f = (s+1)*t + s
64 | return c/2*(postFix*t*f + 2) + b
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/Examples/TweenApp/Pods/Ubergang/Ubergang/Ease/Bounce.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Bounce.swift
3 | // Ubergang
4 | //
5 | // Created by Robin Frielingsdorf on 07/01/16.
6 | // Copyright © 2016 Robin Falko. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | open class Bounce: Ease {
12 |
13 | /**
14 | Bounce ease in.
15 |
16 | - Parameter t: The value to be mapped going from 0 to `d`
17 | - Parameter b: The mapped start value
18 | - Parameter c: The mapped end value
19 | - Parameter d: The end value
20 | - Returns: The mapped result
21 | */
22 | open class func easeIn(t: Double, b: Double, c: Double, d: Double) -> Double {
23 | return c - easeOut (t: d-t, b: 0, c: c, d: d) + b
24 | }
25 |
26 | /**
27 | Bounce ease out.
28 |
29 | - Parameter t: The value to be mapped going from 0 to `d`
30 | - Parameter b: The mapped start value
31 | - Parameter c: The mapped end value
32 | - Parameter d: The end value
33 | - Returns: The mapped result
34 | */
35 | open class func easeOut(t: Double, b: Double, c: Double, d: Double) -> Double {
36 | var t = t
37 | t/=d
38 | if t < (1/2.75) {
39 | return c*(7.5625*t*t) + b
40 | } else if (t < (2/2.75)) {
41 | t-=(1.5/2.75)
42 | let postFix = t
43 | return c*(7.5625*(postFix)*t + 0.75) + b
44 | } else if (t < (2.5/2.75)) {
45 | t-=(2.25/2.75)
46 | let postFix = t
47 | return c*(7.5625*(postFix)*t + 0.9375) + b
48 | } else {
49 | t-=(2.625/2.75)
50 | let postFix = t
51 | return c*(7.5625*(postFix)*t + 0.984375) + b
52 | }
53 | }
54 |
55 | /**
56 | Bounce ease in out.
57 |
58 | - Parameter t: The value to be mapped going from 0 to `d`
59 | - Parameter b: The mapped start value
60 | - Parameter c: The mapped end value
61 | - Parameter d: The end value
62 | - Returns: The mapped result
63 | */
64 | open class func easeInOut(t: Double, b: Double, c: Double, d: Double) -> Double {
65 | if (t < d/2) { return easeIn (t: t*2, b: 0, c: c, d: d) * 0.5 + b }
66 | else { return easeOut (t: t*2-d, b: 0, c: c, d: d) * 0.5 + c*0.5 + b }
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/Examples/TweenApp/Pods/Ubergang/Ubergang/Ease/Circ.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Circ.swift
3 | // Ubergang
4 | //
5 | // Created by Robin Frielingsdorf on 07/01/16.
6 | // Copyright © 2016 Robin Falko. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | open class Circ: Ease {
12 |
13 | /**
14 | Circ ease in.
15 |
16 | - Parameter t: The value to be mapped going from 0 to `d`
17 | - Parameter b: The mapped start value
18 | - Parameter c: The mapped end value
19 | - Parameter d: The end value
20 | - Returns: The mapped result
21 | */
22 | open class func easeIn(t: Double, b: Double, c: Double, d: Double) -> Double {
23 | var t = t
24 | t/=d
25 | return -c * (sqrt(1 - (t)*t) - 1) + b
26 | }
27 |
28 | /**
29 | Circ ease out.
30 |
31 | - Parameter t: The value to be mapped going from 0 to `d`
32 | - Parameter b: The mapped start value
33 | - Parameter c: The mapped end value
34 | - Parameter d: The end value
35 | - Returns: The mapped result
36 | */
37 | open class func easeOut(t: Double, b: Double, c: Double, d: Double) -> Double {
38 | var t = t
39 | t=t/d-1
40 | return c * sqrt(1 - (t)*t) + b
41 | }
42 |
43 | /**
44 | Circ ease in out.
45 |
46 | - Parameter t: The value to be mapped going from 0 to `d`
47 | - Parameter b: The mapped start value
48 | - Parameter c: The mapped end value
49 | - Parameter d: The end value
50 | - Returns: The mapped result
51 | */
52 | open class func easeInOut(t: Double, b: Double, c: Double, d: Double) -> Double {
53 | var t = t
54 | t/=d/2
55 | if ((t) < 1) { return -c/2 * (sqrt(1 - t*t) - 1) + b }
56 | t-=2
57 | return c/2 * (sqrt(1 - t*(t)) + 1) + b
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/Examples/TweenApp/Pods/Ubergang/Ubergang/Ease/Cubic.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Cubic.swift
3 | // Ubergang
4 | //
5 | // Created by Robin Frielingsdorf on 07/01/16.
6 | // Copyright © 2016 Robin Falko. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | open class Cubic: Ease {
12 |
13 | /**
14 | Cubic ease in.
15 |
16 | - Parameter t: The value to be mapped going from 0 to `d`
17 | - Parameter b: The mapped start value
18 | - Parameter c: The mapped end value
19 | - Parameter d: The end value
20 | - Returns: The mapped result
21 | */
22 | open class func easeIn(t: Double, b: Double, c: Double, d: Double) -> Double {
23 | var t = t
24 | t = t/d
25 | return c*t*t*t + b
26 | }
27 |
28 | /**
29 | Cubic ease out.
30 |
31 | - Parameter t: The value to be mapped going from 0 to `d`
32 | - Parameter b: The mapped start value
33 | - Parameter c: The mapped end value
34 | - Parameter d: The end value
35 | - Returns: The mapped result
36 | */
37 | open class func easeOut(t: Double, b: Double, c: Double, d: Double) -> Double {
38 | var t = t
39 | t = t/d-1
40 | return c*(t*t*t + 1) + b
41 | }
42 |
43 | /**
44 | Cubic ease in out.
45 |
46 | - Parameter t: The value to be mapped going from 0 to `d`
47 | - Parameter b: The mapped start value
48 | - Parameter c: The mapped end value
49 | - Parameter d: The end value
50 | - Returns: The mapped result
51 | */
52 | open class func easeInOut(t: Double, b: Double, c: Double, d: Double) -> Double {
53 | var t = t
54 | t = t/(d/2)
55 | if t < 1 {
56 | return c/2*t*t*t + b
57 | }
58 |
59 | t = t-2
60 | return c/2*(t*t*t + 2) + b;
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/Examples/TweenApp/Pods/Ubergang/Ubergang/Ease/Ease.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Ease.swift
3 | // Ubergang
4 | //
5 | // Created by Robin Frielingsdorf on 14/01/16.
6 | // Copyright © 2016 Robin Falko. All rights reserved.
7 | //
8 |
9 | public typealias Easing = (_ t: Double, _ b: Double, _ c: Double, _ d: Double) -> Double
10 |
11 | open class Ease {}
12 |
--------------------------------------------------------------------------------
/Examples/TweenApp/Pods/Ubergang/Ubergang/Ease/Elastic.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Elastic.swift
3 | // Ubergang
4 | //
5 | // Created by Robin Frielingsdorf on 10/01/16.
6 | // Copyright © 2016 Robin Falko. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | open class Elastic: Ease {
12 |
13 | /**
14 | Elastic ease in.
15 |
16 | - Parameter t: The value to be mapped going from 0 to `d`
17 | - Parameter b: The mapped start value
18 | - Parameter c: The mapped end value
19 | - Parameter d: The end value
20 | - Returns: The mapped result
21 | */
22 | open class func easeIn(t: Double, b: Double, c: Double, d: Double) -> Double {
23 | var t = t
24 | if t == 0 {
25 | return b
26 | }
27 |
28 | t = t / d
29 | if t == 1 {
30 | return b+c
31 | }
32 |
33 | let p = d * 0.3
34 | let a = c
35 | let s = p / 4
36 | t = t - 1
37 |
38 | let postFix = a * pow(2.0, 10.0 * t) // this is a fix, again, with post-increment operators
39 |
40 | return -(postFix * sin((t*d-s) * (2 * .pi)/p )) + b
41 | }
42 |
43 | /**
44 | Elastic ease out.
45 |
46 | - Parameter t: The value to be mapped going from 0 to `d`
47 | - Parameter b: The mapped start value
48 | - Parameter c: The mapped end value
49 | - Parameter d: The end value
50 | - Returns: The mapped result
51 | */
52 | open class func easeOut(t: Double, b: Double, c: Double, d: Double) -> Double {
53 | var t = t
54 | if t == 0 {
55 | return b
56 | }
57 |
58 | t = t / d
59 | if t == 1 {
60 | return b+c
61 | }
62 |
63 | let p = d * 0.3
64 | let a = c
65 | let s = p / 4
66 |
67 | return (a * pow(2, -10 * t) * sin( (t*d-s) * (2 * .pi)/p ) + c + b)
68 | }
69 |
70 | /**
71 | Elastic ease in out.
72 |
73 | - Parameter t: The value to be mapped going from 0 to `d`
74 | - Parameter b: The mapped start value
75 | - Parameter c: The mapped end value
76 | - Parameter d: The end value
77 | - Returns: The mapped result
78 | */
79 | open class func easeInOut(t: Double, b: Double, c: Double, d: Double) -> Double {
80 | var t = t
81 | if t == 0 {
82 | return b
83 | }
84 |
85 | t = t / (d / 2)
86 | if t == 2 {
87 | return b+c
88 | }
89 |
90 | let p = d * (0.3*1.5)
91 | let a = c
92 | let s = p / 4
93 |
94 | t = t - 1
95 |
96 | if (t < 1) {
97 | let postFix = a * pow(2.0, 10.0 * t) // postIncrement is evil
98 | return -0.5 * (postFix * sin((t*d-s) * (2 * .pi)/p)) + b
99 | }
100 |
101 | let postFix = a * pow(2.0, -10.0 * t) // postIncrement is evil
102 | return postFix * sin((t*d-s) * (2 * .pi) / p) * 0.5 + c + b
103 | }
104 | }
105 |
--------------------------------------------------------------------------------
/Examples/TweenApp/Pods/Ubergang/Ubergang/Ease/Expo.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Expo.swift
3 | // Ubergang
4 | //
5 | // Created by Robin Frielingsdorf on 07/01/16.
6 | // Copyright © 2016 Robin Falko. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | open class Expo: Ease {
12 |
13 | /**
14 | Expo ease in.
15 |
16 | - Parameter t: The value to be mapped going from 0 to `d`
17 | - Parameter b: The mapped start value
18 | - Parameter c: The mapped end value
19 | - Parameter d: The end value
20 | - Returns: The mapped result
21 | */
22 | open class func easeIn(t: Double, b: Double, c: Double, d: Double) -> Double {
23 | return (t==0) ? b : c * pow(2, 10 * (t/d - 1)) + b
24 | }
25 |
26 | /**
27 | Circ ease out.
28 |
29 | - Parameter t: The value to be mapped going from 0 to `d`
30 | - Parameter b: The mapped start value
31 | - Parameter c: The mapped end value
32 | - Parameter d: The end value
33 | - Returns: The mapped result
34 | */
35 | open class func easeOut(t: Double, b: Double, c: Double, d: Double) -> Double {
36 | return (t==d) ? b+c : c * (-pow(2, -10 * t/d) + 1) + b
37 | }
38 |
39 | /**
40 | Circ ease in out.
41 |
42 | - Parameter t: The value to be mapped going from 0 to `d`
43 | - Parameter b: The mapped start value
44 | - Parameter c: The mapped end value
45 | - Parameter d: The end value
46 | - Returns: The mapped result
47 | */
48 | open class func easeInOut(t: Double, b: Double, c: Double, d: Double) -> Double {
49 | var t = t
50 | if (t==0) { return b }
51 | if (t==d) { return b+c }
52 | t/=d/2
53 | if ((t) < 1) { return c/2 * pow(2, 10 * (t - 1)) + b }
54 | t-=1
55 | return c/2 * (-pow(2, -10 * t) + 2) + b
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/Examples/TweenApp/Pods/Ubergang/Ubergang/Ease/Linear.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Linear.swift
3 | // Ubergang
4 | //
5 | // Created by Robin Frielingsdorf on 07/01/16.
6 | // Copyright © 2016 Robin Falko. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | open class Linear: Ease {
12 |
13 | /**
14 | Linear ease.
15 |
16 | - Parameter t: The value to be mapped going from 0 to `d`
17 | - Parameter b: The mapped start value
18 | - Parameter c: The mapped end value
19 | - Parameter d: The end value
20 | - Returns: The mapped result
21 | */
22 | open class func ease(t: Double, b: Double, c: Double, d: Double) -> Double {
23 | return c * t / d + b
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/Examples/TweenApp/Pods/Ubergang/Ubergang/Ease/Quad.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Quad.swift
3 | // Ubergang
4 | //
5 | // Created by Robin Frielingsdorf on 07/01/16.
6 | // Copyright © 2016 Robin Falko. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | open class Quad: Ease {
12 |
13 | /**
14 | Quad ease in.
15 |
16 | - Parameter t: The value to be mapped going from 0 to `d`
17 | - Parameter b: The mapped start value
18 | - Parameter c: The mapped end value
19 | - Parameter d: The end value
20 | - Returns: The mapped result
21 | */
22 | open class func easeIn(t: Double, b: Double, c: Double, d: Double) -> Double {
23 | var t = t
24 | t/=d
25 | return c*(t)*t + b
26 | }
27 |
28 | /**
29 | Quad ease out.
30 |
31 | - Parameter t: The value to be mapped going from 0 to `d`
32 | - Parameter b: The mapped start value
33 | - Parameter c: The mapped end value
34 | - Parameter d: The end value
35 | - Returns: The mapped result
36 | */
37 | open class func easeOut(t: Double, b: Double, c: Double, d: Double) -> Double {
38 | var t = t
39 | t/=d
40 | return -c*(t)*(t-2) + b
41 | }
42 |
43 | /**
44 | Quad ease in out.
45 |
46 | - Parameter t: The value to be mapped going from 0 to `d`
47 | - Parameter b: The mapped start value
48 | - Parameter c: The mapped end value
49 | - Parameter d: The end value
50 | - Returns: The mapped result
51 | */
52 | open class func easeInOut(t: Double, b: Double, c: Double, d: Double) -> Double {
53 | var t = t
54 | t/=d/2
55 | if ((t) < 1) { return ((c/2)*(t*t)) + b }
56 | let t2 = t-1
57 | return -c/2 * (((t-2)*(t2)) - 1) + b
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/Examples/TweenApp/Pods/Ubergang/Ubergang/Ease/Quart.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Quart.swift
3 | // Ubergang
4 | //
5 | // Created by Robin Frielingsdorf on 07/01/16.
6 | // Copyright © 2016 Robin Falko. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | open class Quart: Ease {
12 |
13 | /**
14 | Quart ease in.
15 |
16 | - Parameter t: The value to be mapped going from 0 to `d`
17 | - Parameter b: The mapped start value
18 | - Parameter c: The mapped end value
19 | - Parameter d: The end value
20 | - Returns: The mapped result
21 | */
22 | open class func easeIn(t: Double, b: Double, c: Double, d: Double) -> Double {
23 | var t = t
24 | t/=d
25 | return c*(t)*t*t*t + b
26 | }
27 |
28 | /**
29 | Quart ease out.
30 |
31 | - Parameter t: The value to be mapped going from 0 to `d`
32 | - Parameter b: The mapped start value
33 | - Parameter c: The mapped end value
34 | - Parameter d: The end value
35 | - Returns: The mapped result
36 | */
37 | open class func easeOut(t: Double, b: Double, c: Double, d: Double) -> Double {
38 | var t = t
39 | t=t/d-1
40 | return -c * ((t)*t*t*t - 1) + b
41 | }
42 |
43 | /**
44 | Quart ease in out.
45 |
46 | - Parameter t: The value to be mapped going from 0 to `d`
47 | - Parameter b: The mapped start value
48 | - Parameter c: The mapped end value
49 | - Parameter d: The end value
50 | - Returns: The mapped result
51 | */
52 | open class func easeInOut(t: Double, b: Double, c: Double, d: Double) -> Double {
53 | var t = t
54 | t/=d/2
55 | if ((t) < 1) { return c/2*t*t*t*t + b }
56 | t-=2
57 | return -c/2 * ((t)*t*t*t - 2) + b
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/Examples/TweenApp/Pods/Ubergang/Ubergang/Ease/Quint.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Quint.swift
3 | // Ubergang
4 | //
5 | // Created by Robin Frielingsdorf on 07/01/16.
6 | // Copyright © 2016 Robin Falko. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | open class Quint: Ease {
12 |
13 | /**
14 | Quint ease in.
15 |
16 | - Parameter t: The value to be mapped going from 0 to `d`
17 | - Parameter b: The mapped start value
18 | - Parameter c: The mapped end value
19 | - Parameter d: The end value
20 | - Returns: The mapped result
21 | */
22 | open class func easeIn(t: Double, b: Double, c: Double, d: Double) -> Double {
23 | var t = t
24 | t/=d
25 | return c*(t)*t*t*t*t + b
26 | }
27 |
28 | /**
29 | Quint ease out.
30 |
31 | - Parameter t: The value to be mapped going from 0 to `d`
32 | - Parameter b: The mapped start value
33 | - Parameter c: The mapped end value
34 | - Parameter d: The end value
35 | - Returns: The mapped result
36 | */
37 | open class func easeOut(t: Double, b: Double, c: Double, d: Double) -> Double {
38 | var t = t
39 | t=t/d-1
40 | return c*((t)*t*t*t*t + 1) + b
41 | }
42 |
43 | /**
44 | Quint ease in out.
45 |
46 | - Parameter t: The value to be mapped going from 0 to `d`
47 | - Parameter b: The mapped start value
48 | - Parameter c: The mapped end value
49 | - Parameter d: The end value
50 | - Returns: The mapped result
51 | */
52 | open class func easeInOut(t: Double, b: Double, c: Double, d: Double) -> Double {
53 | var t = t
54 | t/=d/2
55 | if ((t) < 1) { return c/2*t*t*t*t*t + b }
56 | t-=2
57 | return c/2*((t)*t*t*t*t + 2) + b
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/Examples/TweenApp/Pods/Ubergang/Ubergang/Ease/Sine.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Sine.swift
3 | // Ubergang
4 | //
5 | // Created by Robin Frielingsdorf on 07/01/16.
6 | // Copyright © 2016 Robin Falko. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | open class Sine: Ease {
12 |
13 | /**
14 | Sine ease in.
15 |
16 | - Parameter t: The value to be mapped going from 0 to `d`
17 | - Parameter b: The mapped start value
18 | - Parameter c: The mapped end value
19 | - Parameter d: The end value
20 | - Returns: The mapped result
21 | */
22 | open class func easeIn(t: Double, b: Double, c: Double, d: Double) -> Double {
23 | return -c * cos(t/d * (.pi/2)) + c + b
24 | }
25 |
26 | /**
27 | Sine ease out.
28 |
29 | - Parameter t: The value to be mapped going from 0 to `d`
30 | - Parameter b: The mapped start value
31 | - Parameter c: The mapped end value
32 | - Parameter d: The end value
33 | - Returns: The mapped result
34 | */
35 | open class func easeOut(t: Double, b: Double, c: Double, d: Double) -> Double {
36 | return c * sin(t/d * (.pi/2)) + b
37 | }
38 |
39 | /**
40 | Sine ease in out.
41 |
42 | - Parameter t: The value to be mapped going from 0 to `d`
43 | - Parameter b: The mapped start value
44 | - Parameter c: The mapped end value
45 | - Parameter d: The end value
46 | - Returns: The mapped result
47 | */
48 | open class func easeInOut(t: Double, b: Double, c: Double, d: Double) -> Double {
49 | return -c/2 * (cos(.pi*t/d) - 1) + b
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/Examples/TweenApp/Pods/Ubergang/Ubergang/Extension/CGPath.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CGPath.swift
3 | // Ubergang
4 | //
5 | // Created by Robin Frielingsdorf on 19/05/16.
6 | // Copyright © 2016 Robin Falko. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | extension CGPath {
12 | func forEach(_ body: @convention(block) (CGPathElement) -> Void) {
13 | typealias Body = @convention(block) (CGPathElement) -> Void
14 | func callback(_ info: UnsafeMutableRawPointer, element: UnsafePointer) {
15 | let body = unsafeBitCast(info, to: Body.self)
16 | body(element.pointee)
17 | }
18 | let unsafeBody = unsafeBitCast(body, to: UnsafeMutableRawPointer.self)
19 | self.apply(info: unsafeBody, function: callback as! CGPathApplierFunction)
20 | }
21 |
22 | func getElements() -> [(type: CGPathElementType, points: [CGPoint])] {
23 | var result = [(type: CGPathElementType, points: [CGPoint])]()
24 | var elementType: CGPathElementType!
25 | var points: [CGPoint]!
26 | var firstPoint: CGPoint!
27 | var previousLastPoint: CGPoint!
28 | forEach { element in
29 | switch (element.type) {
30 | case CGPathElementType.moveToPoint:
31 | firstPoint = element.points[0]
32 | previousLastPoint = firstPoint
33 | case .addLineToPoint:
34 | points = [CGPoint]()
35 | elementType = element.type
36 | points.append(previousLastPoint)
37 | points.append(element.points[0])
38 | result.append((elementType, points))
39 |
40 | previousLastPoint = element.points[0]
41 | case .addQuadCurveToPoint:
42 | points = [CGPoint]()
43 | elementType = element.type
44 | points.append(previousLastPoint)
45 | points.append(element.points[0])
46 | points.append(element.points[1])
47 | result.append((elementType, points))
48 |
49 | previousLastPoint = element.points[1]
50 | case .addCurveToPoint:
51 | points = [CGPoint]()
52 | elementType = element.type
53 | points.append(previousLastPoint)
54 | points.append(element.points[0])
55 | points.append(element.points[1])
56 | points.append(element.points[2])
57 | result.append((elementType, points))
58 |
59 | previousLastPoint = element.points[2]
60 | case .closeSubpath:
61 | points = [CGPoint]()
62 | elementType = element.type
63 | points.append(previousLastPoint)
64 | points.append(firstPoint)
65 | result.append((elementType, points))
66 | }
67 | }
68 |
69 | return result
70 | }
71 |
72 | func getElement(_ index: Int) -> (type: CGPathElementType, points: [CGPoint])? {
73 | let elements = getElements()
74 | if index >= elements.count {
75 | return nil
76 | }
77 | return elements[index]
78 | }
79 |
80 | func elementCount() -> Int {
81 | var count = 0
82 | self.forEach { element in
83 | if element.type != .moveToPoint && element.type != .closeSubpath {
84 | count += 1
85 | }
86 | }
87 | return count
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/Examples/TweenApp/Pods/Ubergang/Ubergang/Extension/UIBezierPath+Interpolation.h:
--------------------------------------------------------------------------------
1 | //
2 | // UIBezierPath+Interpolation.h
3 | // Curve Interpolation
4 | //
5 | // Created by John Fisher on 4/26/14.
6 | // Copyright (c) 2014 John Fisher. All rights reserved.
7 | //
8 | // Source: https://github.com/jnfisher/ios-curve-interpolation
9 |
10 | #import
11 |
12 | @interface UIBezierPath (Interpolation)
13 |
14 | // pointsAsNSValues must be NSValue objects containing CGPoints.
15 | //
16 | // ex:
17 | // const char *encoding = @encode(CGPoint);
18 | // NSValue *pointAsValue = [NSValue valueWithBytes:&cgPoint objCType:encoding];
19 |
20 | // 0.0 <= alpha <= 1.0
21 | +(UIBezierPath *)interpolateCGPointsWithCatmullRom:(NSArray *)pointsAsNSValues closed:(BOOL)closed alpha:(float)alpha;
22 | +(UIBezierPath *)interpolateCGPointsWithHermite:(NSArray *)pointsAsNSValues closed:(BOOL)closed;
23 | @end
--------------------------------------------------------------------------------
/Examples/TweenApp/Pods/Ubergang/Ubergang/Extension/UIBezierPath+Interpolation.m:
--------------------------------------------------------------------------------
1 | //
2 | // UIBezierPath+Interpolation.m
3 | // Curve Interpolation
4 | //
5 | // Created by John Fisher on 4/26/14.
6 | // Copyright (c) 2014 John Fisher. All rights reserved.
7 | //
8 | // Source: https://github.com/jnfisher/ios-curve-interpolation
9 |
10 | #import "UIBezierPath+Interpolation.h"
11 | #import "CGPointExtension.h"
12 |
13 | #define kEPSILON 1.0e-5
14 |
15 | @implementation UIBezierPath (Interpolation)
16 |
17 | +(UIBezierPath *)interpolateCGPointsWithCatmullRom:(NSArray *)pointsAsNSValues closed:(BOOL)closed alpha:(float)alpha {
18 | if ([pointsAsNSValues count] < 4)
19 | return nil;
20 |
21 | NSInteger endIndex = (closed ? [pointsAsNSValues count] : [pointsAsNSValues count]-2);
22 | NSAssert(alpha >= 0.0 && alpha <= 1.0, @"alpha value is between 0.0 and 1.0, inclusive");
23 |
24 | UIBezierPath *path = [UIBezierPath bezierPath];
25 | NSInteger startIndex = (closed ? 0 : 1);
26 | for (NSInteger ii=startIndex; ii < endIndex; ++ii) {
27 | CGPoint p0, p1, p2, p3;
28 | NSInteger nextii = (ii+1)%[pointsAsNSValues count];
29 | NSInteger nextnextii = (nextii+1)%[pointsAsNSValues count];
30 | NSInteger previi = (ii-1 < 0 ? [pointsAsNSValues count]-1 : ii-1);
31 |
32 | [pointsAsNSValues[ii] getValue:&p1];
33 | [pointsAsNSValues[previi] getValue:&p0];
34 | [pointsAsNSValues[nextii] getValue:&p2];
35 | [pointsAsNSValues[nextnextii] getValue:&p3];
36 |
37 | CGFloat d1 = ccpLength(ccpSub(p1, p0));
38 | CGFloat d2 = ccpLength(ccpSub(p2, p1));
39 | CGFloat d3 = ccpLength(ccpSub(p3, p2));
40 |
41 | CGPoint b1, b2;
42 | if (fabs(d1) < kEPSILON) {
43 | b1 = p1;
44 | }
45 | else {
46 | b1 = ccpMult(p2, powf(d1, 2*alpha));
47 | b1 = ccpSub(b1, ccpMult(p0, powf(d2, 2*alpha)));
48 | b1 = ccpAdd(b1, ccpMult(p1,(2*powf(d1, 2*alpha) + 3*powf(d1, alpha)*powf(d2, alpha) + powf(d2, 2*alpha))));
49 | b1 = ccpMult(b1, 1.0 / (3*powf(d1, alpha)*(powf(d1, alpha)+powf(d2, alpha))));
50 | }
51 |
52 | if (fabs(d3) < kEPSILON) {
53 | b2 = p2;
54 | }
55 | else {
56 | b2 = ccpMult(p1, powf(d3, 2*alpha));
57 | b2 = ccpSub(b2, ccpMult(p3, powf(d2, 2*alpha)));
58 | b2 = ccpAdd(b2, ccpMult(p2,(2*powf(d3, 2*alpha) + 3*powf(d3, alpha)*powf(d2, alpha) + powf(d2, 2*alpha))));
59 | b2 = ccpMult(b2, 1.0 / (3*powf(d3, alpha)*(powf(d3, alpha)+powf(d2, alpha))));
60 | }
61 |
62 | if (ii==startIndex)
63 | [path moveToPoint:p1];
64 |
65 | [path addCurveToPoint:p2 controlPoint1:b1 controlPoint2:b2];
66 | }
67 |
68 | if (closed)
69 | [path closePath];
70 |
71 | return path;
72 | }
73 |
74 | +(UIBezierPath *)interpolateCGPointsWithHermite:(NSArray *)pointsAsNSValues closed:(BOOL)closed {
75 | if ([pointsAsNSValues count] < 2)
76 | return nil;
77 |
78 | NSInteger nCurves = (closed ? [pointsAsNSValues count] : [pointsAsNSValues count]-1);
79 |
80 | UIBezierPath *path = [UIBezierPath bezierPath];
81 | for (NSInteger ii=0; ii < nCurves; ++ii) {
82 | NSValue *value = pointsAsNSValues[ii];
83 |
84 | CGPoint curPt, prevPt, nextPt, endPt;
85 | [value getValue:&curPt];
86 | if (ii==0)
87 | [path moveToPoint:curPt];
88 |
89 | NSInteger nextii = (ii+1)%[pointsAsNSValues count];
90 | NSInteger previi = (ii-1 < 0 ? [pointsAsNSValues count]-1 : ii-1);
91 |
92 | [pointsAsNSValues[previi] getValue:&prevPt];
93 | [pointsAsNSValues[nextii] getValue:&nextPt];
94 | endPt = nextPt;
95 |
96 | CGFloat mx, my;
97 | if (closed || ii > 0) {
98 | mx = (nextPt.x - curPt.x)*0.5 + (curPt.x - prevPt.x)*0.5;
99 | my = (nextPt.y - curPt.y)*0.5 + (curPt.y - prevPt.y)*0.5;
100 | }
101 | else {
102 | mx = (nextPt.x - curPt.x)*0.5;
103 | my = (nextPt.y - curPt.y)*0.5;
104 | }
105 |
106 | CGPoint ctrlPt1;
107 | ctrlPt1.x = curPt.x + mx / 3.0;
108 | ctrlPt1.y = curPt.y + my / 3.0;
109 |
110 | [pointsAsNSValues[nextii] getValue:&curPt];
111 |
112 | nextii = (nextii+1)%[pointsAsNSValues count];
113 | previi = ii;
114 |
115 | [pointsAsNSValues[previi] getValue:&prevPt];
116 | [pointsAsNSValues[nextii] getValue:&nextPt];
117 |
118 | if (closed || ii < nCurves-1) {
119 | mx = (nextPt.x - curPt.x)*0.5 + (curPt.x - prevPt.x)*0.5;
120 | my = (nextPt.y - curPt.y)*0.5 + (curPt.y - prevPt.y)*0.5;
121 | }
122 | else {
123 | mx = (curPt.x - prevPt.x)*0.5;
124 | my = (curPt.y - prevPt.y)*0.5;
125 | }
126 |
127 | CGPoint ctrlPt2;
128 | ctrlPt2.x = curPt.x - mx / 3.0;
129 | ctrlPt2.y = curPt.y - my / 3.0;
130 |
131 | [path addCurveToPoint:endPt controlPoint1:ctrlPt1 controlPoint2:ctrlPt2];
132 | }
133 |
134 | if (closed)
135 | [path closePath];
136 |
137 | return path;
138 | }
139 |
140 |
141 | @end
--------------------------------------------------------------------------------
/Examples/TweenApp/Pods/Ubergang/Ubergang/Protocols/Numeric.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Computable.swift
3 | // Ubergang
4 | //
5 | // Created by Robin Frielingsdorf on 14/01/16.
6 | // Copyright © 2016 Robin Falko. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | public protocol Numeric {
12 | init()
13 | init(_ value: Int)
14 | init(_ value: Double)
15 | init(_ value: Float)
16 |
17 | static func + (lhs: Self, rhs: Self) -> Self
18 | static func - (lhs: Self, rhs: Self) -> Self
19 | static func * (lhs: Self, rhs: Self) -> Self
20 | static func / (lhs: Self, rhs: Self) -> Self
21 | }
22 |
23 | extension Double : Numeric {
24 | public init?(_ value: T) {
25 | switch (value) {
26 | case is Int:
27 | self.init(Double(value as! Int))
28 | break
29 | case is Int8:
30 | self.init(Double(value as! Int8))
31 | break
32 | case is Int16:
33 | self.init(Double(value as! Int16))
34 | break
35 | case is Int32:
36 | self.init(Double(value as! Int32))
37 | break
38 | case is Int64:
39 | self.init(Double(value as! Int64))
40 | break
41 | case is Float:
42 | self.init(Double(value as! Float))
43 | break
44 | case is CGFloat:
45 | self.init(Double(value as! CGFloat))
46 | break
47 | case is Double:
48 | fallthrough
49 | default:
50 | return nil
51 | }
52 | }
53 | }
54 | extension Float : Numeric {}
55 | extension Int : Numeric {}
56 | extension Int8 : Numeric {}
57 | extension Int16 : Numeric {}
58 | extension Int32 : Numeric {}
59 | extension Int64 : Numeric {}
60 | extension UInt : Numeric {}
61 | extension UInt8 : Numeric {}
62 | extension UInt16 : Numeric {}
63 | extension UInt32 : Numeric {}
64 | extension UInt64 : Numeric {}
65 | extension CGFloat: Numeric {}
66 |
--------------------------------------------------------------------------------
/Examples/TweenApp/Pods/Ubergang/Ubergang/Protocols/Tweenable.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Tweenable.swift
3 | // Ubergang
4 | //
5 | // Created by Robin Frielingsdorf on 05/04/16.
6 | // Copyright © 2016 Robin Falko. All rights reserved.
7 | //
8 |
9 | public protocol Tweenable {
10 | var id: String { get }
11 | var duration: Double { get set }
12 | var progress: Double { get set }
13 |
14 | func start() -> Self
15 | func stop()
16 | func pause()
17 | func resume()
18 | func kill()
19 | }
--------------------------------------------------------------------------------
/Examples/TweenApp/Pods/Ubergang/Ubergang/Protocols/TypeTweenable.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Tween.swift
3 | // Ubergang
4 | //
5 | // Created by RF on 06.08.17.
6 | // Copyright © 2017 Robin Falko. All rights reserved.
7 | //
8 |
9 | // Not sure why this won't work.
10 | // Use repetitive code in extensions instead
11 | //public protocol GenericTweenable {
12 | // associatedtype TweenType: UTween
13 | // func tween(to: Self) -> TweenType
14 | //}
15 | //
16 | //public extension GenericTweenable {
17 | // func tween(to: Self) -> TweenType {
18 | // return TweenType().tween(from: self, to: to)
19 | // }
20 | //}
21 | //extension CGPoint: GenericTweenable {typealias TweenType = CGPointTween}
22 | //extension UIColor: GenericTweenable {typealias TweenType = ColorTween}
23 | //extension CGAffineTransform: Generic Tweenable {typealias TweenType = TransformTween}
24 |
25 | public extension CGPoint {
26 | func tween(to: CGPoint) -> CGPointTween {
27 | return CGPointTween().from(self, to: to)
28 | }
29 | }
30 |
31 | public extension UIColor {
32 | func tween(to: UIColor) -> ColorTween {
33 | return ColorTween().from(self, to: to)
34 | }
35 | }
36 |
37 | public extension CGAffineTransform {
38 | func tween(to: CGAffineTransform) -> TransformTween {
39 | return TransformTween().from(self, to: to)
40 | }
41 | }
42 |
43 | public protocol NumericTweenable: Numeric {
44 | func tween(to: Self) -> NumericTween
45 | }
46 |
47 | public extension NumericTweenable {
48 | func tween(to: Self) -> NumericTween {
49 | return NumericTween().from(self, to: to)
50 | }
51 | }
52 |
53 | extension Double : NumericTweenable {}
54 | extension Float : NumericTweenable {}
55 | extension Int : NumericTweenable {}
56 | extension Int8 : NumericTweenable {}
57 | extension Int16 : NumericTweenable {}
58 | extension Int32 : NumericTweenable {}
59 | extension Int64 : NumericTweenable {}
60 | extension UInt : NumericTweenable {}
61 | extension UInt8 : NumericTweenable {}
62 | extension UInt16 : NumericTweenable {}
63 | extension UInt32 : NumericTweenable {}
64 | extension UInt64 : NumericTweenable {}
65 | extension CGFloat: NumericTweenable {}
66 |
--------------------------------------------------------------------------------
/Examples/TweenApp/Pods/Ubergang/Ubergang/Protocols/UTweenLoggable.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UTweenLoggable.swift
3 | // Ubergang
4 | //
5 | // Created by RF on 18/07/16.
6 | // Copyright © 2016 Robin Falko. All rights reserved.
7 | //
8 |
9 | public protocol UTweenLoggable {
10 | func verbose(_ msg: String, function: String, file: String, line: Int)
11 | func debug(_ msg: String, function: String, file: String, line: Int)
12 | func info(_ msg: String, function: String, file: String, line: Int)
13 | func warning(_ msg: String, function: String, file: String, line: Int)
14 | func error(_ msg: String, function: String, file: String, line: Int)
15 | }
16 |
17 |
18 | extension UTweenLoggable {
19 | func verbose(_ msg: String, function: String = #function, file: String = #file, line: Int = #line) {
20 | print("[\(file) - \(function)->\(line)]:\(msg)")
21 | }
22 |
23 | func debug(_ msg: String, function: String = #function, file: String = #file, line: Int = #line) {
24 | print("[\(file) - \(function)->\(line)]:\(msg)")
25 | }
26 |
27 | func info(_ msg: String, function: String = #function, file: String = #file, line: Int = #line) {
28 | print("[\(file) - \(function)->\(line)]:\(msg)")
29 | }
30 |
31 | func warning(_ msg: String, function: String = #function, file: String = #file, line: Int = #line) {
32 | print("[\(file) - \(function)->\(line)]:\(msg)")
33 | }
34 |
35 | func error(_ msg: String, function: String = #function, file: String = #file, line: Int = #line) {
36 | print("[\(file) - \(function)->\(line)]:\(msg)")
37 | }
38 | }
39 |
40 |
41 | class UTweenLogger: UTweenLoggable {}
42 |
--------------------------------------------------------------------------------
/Examples/TweenApp/Pods/Ubergang/Ubergang/Protocols/WeaklyLoopable.swift:
--------------------------------------------------------------------------------
1 | //
2 | // WeaklyLoopable.swift
3 | // Ubergang
4 | //
5 | // Created by Robin Frielingsdorf on 10/04/16.
6 | // Copyright © 2016 Robin Falko. All rights reserved.
7 | //
8 |
9 | protocol WeaklyLoopable {
10 | func loopWeakly()
11 | }
--------------------------------------------------------------------------------
/Examples/TweenApp/Pods/Ubergang/Ubergang/Tween/CGPointTween.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CGPointTween.swift
3 | // Ubergang
4 | //
5 | // Created by Robin Frielingsdorf on 14/01/16.
6 | // Copyright © 2016 Robin Falko. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | open class CGPointTween: UTween {
12 |
13 | var currentValue = CGPoint()
14 |
15 | override func compute(_ value: Double) -> CGPoint {
16 | _ = super.compute(value)
17 |
18 | let from = self.fromC()
19 | let to = self.toC()
20 |
21 | currentValue.x = from.x + (to.x - from.x) * CGFloat(value)
22 | currentValue.y = from.y + (to.y - from.y) * CGFloat(value)
23 |
24 | return currentValue
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/Examples/TweenApp/Pods/Ubergang/Ubergang/Tween/ColorTween.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ColorTween.swift
3 | // Ubergang
4 | //
5 | // Created by Robin Frielingsdorf on 14/01/16.
6 | // Copyright © 2016 Robin Falko. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import UIKit
11 |
12 | open class ColorTween: UTween {
13 | override func compute(_ value: Double) -> UIColor {
14 | _ = super.compute(value)
15 |
16 | let from = self.fromC()
17 | let to = self.toC()
18 |
19 | var rFrom: CGFloat = 0
20 | var gFrom: CGFloat = 0
21 | var bFrom: CGFloat = 0
22 | var aFrom: CGFloat = 0
23 |
24 | var rTo: CGFloat = 0
25 | var gTo: CGFloat = 0
26 | var bTo: CGFloat = 0
27 | var aTo: CGFloat = 0
28 |
29 | from.getRed(&rFrom, green: &gFrom, blue: &bFrom, alpha: &aFrom)
30 | to.getRed(&rTo, green: &gTo, blue: &bTo, alpha: &aTo)
31 |
32 | let r = rFrom + (rTo - rFrom) * CGFloat(value)
33 | let g = gFrom + (gTo - gFrom) * CGFloat(value)
34 | let b = bFrom + (bTo - bFrom) * CGFloat(value)
35 | let a = aFrom + (aTo - aFrom) * CGFloat(value)
36 |
37 | return UIColor(red: r, green: g, blue: b, alpha: a)
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/Examples/TweenApp/Pods/Ubergang/Ubergang/Tween/NumericTween.swift:
--------------------------------------------------------------------------------
1 | //
2 | // NumericTween.swift
3 | // Ubergang
4 | //
5 | // Created by Robin Frielingsdorf on 14/01/16.
6 | // Copyright © 2016 Robin Falko. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | open class NumericTween: UTween {
12 | override func compute(_ value: Double) -> T {
13 | _ = super.compute(value)
14 |
15 | let from = self.fromC()
16 | let to = self.toC()
17 |
18 | let distance = to - from
19 | var parsedDistance: Double
20 | if distance is Double {
21 | parsedDistance = distance as! Double
22 | }
23 | else {
24 | parsedDistance = Double(distance)!
25 | }
26 |
27 | let total = T( parsedDistance * value )
28 |
29 | return from + total
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/Examples/TweenApp/Pods/Ubergang/Ubergang/Tween/TransformTween.swift:
--------------------------------------------------------------------------------
1 | //
2 | // TransformTween.swift
3 | // Ubergang
4 | //
5 | // Created by Robin Frielingsdorf on 14/01/16.
6 | // Copyright © 2016 Robin Falko. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import UIKit
11 |
12 | open class TransformTween: UTween {
13 | override func compute(_ value: Double) -> CGAffineTransform {
14 | _ = super.compute(value)
15 |
16 | let from = self.fromC()
17 | let to = self.toC()
18 |
19 | var currentValue = CGAffineTransform.identity
20 | currentValue.tx = from.tx + (to.tx - from.tx) * CGFloat(value)
21 | currentValue.ty = from.ty + (to.ty - from.ty) * CGFloat(value)
22 |
23 | currentValue.a = from.a + (to.a - from.a) * CGFloat(value)
24 | currentValue.b = from.b + (to.b - from.b) * CGFloat(value)
25 | currentValue.c = from.c + (to.c - from.c) * CGFloat(value)
26 | currentValue.d = from.d + (to.d - from.d) * CGFloat(value)
27 |
28 | return currentValue
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/Examples/TweenApp/Pods/Ubergang/Ubergang/Tween/UTimeline.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UTimeline.swift
3 | // Ubergang
4 | //
5 | // Created by Robin Frielingsdorf on 05/04/16.
6 | // Copyright © 2016 Robin Falko. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | open class UTimeline: UTweenBase {
12 | var tweens: [UTweenBase] = []
13 | var startTimeForTweenId: [String : Double] = [:]
14 |
15 | open var count: Int { return tweens.count }
16 |
17 | /**
18 | Initialize a `UTimeline` with a random id.
19 |
20 | Tweens all containing elements from start to end.
21 | */
22 | public convenience init() {
23 | let id = "\(#file)_\(arc4random())_update"
24 | self.init(id: id)
25 | }
26 |
27 | /**
28 | Initialize a `UTimeline`.
29 |
30 | Tweens all containing elements from start to end.
31 |
32 | - Parameter id: The unique id of the Tween
33 | */
34 | public override init(id: String) {
35 | super.init(id: id)
36 |
37 | initialDuration = 0
38 | duration = 0
39 | durationTotal = 0
40 | }
41 |
42 | open func append(_ tween: UTweenBase) {
43 | // tween.computeConfigs()
44 | //
45 | // tweens.append(tween)
46 | //
47 | // startTimeForTweenId[tween.id] = initialDuration
48 | //
49 | // initialDuration += tween.durationTotal
50 | //
51 | // computeConfigs()
52 |
53 | insert(tween, at: durationTotal)
54 | }
55 |
56 | open func insert(_ tween: UTweenBase, at time: Double) {
57 | tween.computeConfigs()
58 |
59 | tweens.append(tween)
60 |
61 | startTimeForTweenId[tween.id] = time
62 | duration = max(duration, time + tween.durationTotal)
63 | initialDuration = duration
64 |
65 | tweens.sort(by: {
66 | startTimeForTweenId[$0.id] ?? 0 < startTimeForTweenId[$1.id] ?? 0
67 | })
68 | computeConfigs()
69 | }
70 |
71 | override open var progress: Double {
72 | set {
73 | time = newValue * duration
74 |
75 | for (i, tween) in tweens.enumerated() {
76 | let repeatCount = tweenOptions.repeatCount()
77 | var cycles = Double(repeatCount + 1)
78 |
79 | if tweenOptions.contains(.yoyo) && !tweenOptions.containsRepeat() {
80 | cycles *= 2.0
81 | }
82 |
83 | let startTime = startTimeForTweenId[tween.id]! / cycles
84 |
85 | let mapped = Math.mapValueInRange(time,
86 | fromLower: startTime, fromUpper: startTime + tween.durationTotal / cycles,
87 | toLower: 0.0, toUpper: 1.0)
88 |
89 | let value = tween.direction == .forward ? mapped : 1 - mapped
90 |
91 | let clamped = Math.clamp(value, lower: 0.0, upper: 1.0)
92 | if i == 0 || clamped > 0 {
93 | tween.progressTotal = clamped
94 | }
95 | }
96 |
97 | super.progress = newValue
98 | }
99 | get {
100 | return time / duration
101 | }
102 | }
103 |
104 |
105 | @discardableResult
106 | override open func reference(_ value: TweenMemoryReference) -> Self {
107 | reference = value
108 |
109 | return self
110 | }
111 | }
112 |
--------------------------------------------------------------------------------
/Examples/TweenApp/Pods/Ubergang/Ubergang/Tween/UTween.h:
--------------------------------------------------------------------------------
1 | //
2 | // UTween.h
3 | // UTween
4 | //
5 | // Created by Robin Frielingsdorf on 07/01/16.
6 | // Copyright © 2016 Robin Falko. All rights reserved.
7 | //
8 |
9 | #import
10 | #import
11 |
12 | //! Project version number for Tween.
13 | FOUNDATION_EXPORT double TweenVersionNumber;
14 |
15 | //! Project version string for Tween.
16 | FOUNDATION_EXPORT const unsigned char TweenVersionString[];
17 |
18 | // In this header, you should import all the public headers of your framework using statements like #import
19 |
20 |
21 |
--------------------------------------------------------------------------------
/Examples/TweenApp/Pods/Ubergang/Ubergang/Tween/UTween.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UTween.swift
3 | // UTween
4 | //
5 | // Created by Robin Frielingsdorf on 07/01/16.
6 | // Copyright © 2016 Robin Falko. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import UIKit
11 |
12 | open class UTween: UTweenBase {
13 |
14 | var start: T!
15 | var end: T!
16 |
17 | internal var fromC: (() -> T)!
18 | internal var toC: (() -> T)!
19 |
20 | var updateValue: ((_ value: T) -> Void)!
21 | var updateValueAndProgress: ((_ value: T, _ progress: Double) -> Void)!
22 |
23 | var offset: Double?
24 |
25 | /**
26 | Initialize a generic `UTween` with a random id.
27 |
28 | Tweens any value with type T from start to end.
29 |
30 | This object needs to know how to compute interpolations from start to end, that for
31 | `func compute(value: Double) -> T` must be overriden.
32 | */
33 | public convenience init() {
34 | let id = "\(#file)_\(arc4random())_update"
35 | self.init(id: id)
36 | }
37 |
38 | /**
39 | Initialize a generic `UTween`.
40 |
41 | Tweens any value with type T from start to end.
42 |
43 | This object needs to know how to compute interpolations from start to end, that for
44 | `func compute(value: Double) -> T` must be overriden.
45 |
46 | - Parameter id: The unique id of the Tween
47 | */
48 | public override init(id: String) {
49 | super.init(id: id)
50 | }
51 |
52 | override open var progress: Double {
53 | set {
54 | time = newValue * duration
55 |
56 | easeValue = ease(time, 0.0, 1.0, duration)
57 |
58 | if let offset = offset {
59 | easeValue = fmod(easeValue + offset, 1.0)
60 | }
61 |
62 | let computedValue = compute(easeValue)
63 |
64 | updateValue?( computedValue)
65 | updateValueAndProgress?( computedValue, newValue )
66 |
67 | super.progress = newValue
68 | }
69 | get {
70 | return time / duration
71 | }
72 | }
73 |
74 | func compute(_ value: Double) -> T {
75 | //should be overriden
76 |
77 | return fromC()
78 | }
79 |
80 | //override Tweenable methods
81 | override open func kill() {
82 | super.kill()
83 |
84 | fromC = nil
85 | updateValue = nil
86 | updateValueAndProgress = nil
87 | complete = nil
88 | }
89 |
90 | @discardableResult
91 | override open func reference(_ value: TweenMemoryReference) -> Self {
92 | reference = value
93 |
94 | return self
95 | }
96 | }
97 |
98 |
99 | extension UTween {
100 | // -
101 | public func from(_ from: T, to: T) -> Self {
102 | self.fromC = {from}
103 | self.toC = {to}
104 |
105 | return self.duration(duration)
106 | }
107 |
108 | public func from(_ from: @escaping () -> T, to: @escaping () -> T) -> Self {
109 | self.fromC = from
110 | self.toC = to
111 |
112 | return self.duration(duration)
113 | }
114 |
115 | public func from(_ from: @escaping () -> T, to: T) -> Self {
116 | self.fromC = from
117 | self.toC = {to}
118 |
119 | return self.duration(duration)
120 | }
121 |
122 | public func from(_ from: T, to: @escaping () -> T) -> Self {
123 | self.fromC = {from}
124 | self.toC = to
125 |
126 | return self.duration(duration)
127 | }
128 |
129 |
130 | @discardableResult
131 | public func update(_ value: @escaping (T) -> Void) -> Self {
132 | updateValue = value
133 |
134 | return self
135 | }
136 |
137 |
138 | @discardableResult
139 | public func update(_ value: @escaping (T, Double) -> Void) -> Self {
140 | updateValueAndProgress = value
141 |
142 | return self
143 | }
144 |
145 | @discardableResult
146 | public func ease(_ ease: @escaping Easing) -> Self {
147 | self.ease = ease
148 | return self
149 | }
150 |
151 | @discardableResult
152 | public func offset(_ value: Double) -> Self {
153 | self.offset = value
154 | return self
155 | }
156 | }
157 |
--------------------------------------------------------------------------------
/Examples/TweenApp/Pods/Ubergang/Ubergang/Util/Bezier.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Bezier.swift
3 | // Ubergang
4 | //
5 | // Created by Robin Frielingsdorf on 17/05/16.
6 | // Copyright © 2016 Robin Falko. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import GLKit
11 |
12 | //see https://en.wikipedia.org/wiki/B%C3%A9zier_curve
13 |
14 | class Bezier {
15 | static func linear(t _t: CGFloat, p0: CGPoint, p1: CGPoint) -> CGPoint {
16 |
17 | let v0 = GLKVector2(v: (Float(p0.x), Float(p0.y)))
18 | let v1 = GLKVector2(v: (Float(p1.x), Float(p1.y)))
19 |
20 | let t = Float(_t)
21 |
22 | let v0r = GLKVector2MultiplyScalar(v0, 1-t)
23 | let v1r = GLKVector2MultiplyScalar(v1, t)
24 |
25 | let vResult = GLKVector2Add(v0r, v1r)
26 |
27 | return CGPoint(x: CGFloat(vResult.x), y: CGFloat(vResult.y))
28 | }
29 |
30 | static func quad(t _t: CGFloat, p0: CGPoint, p1: CGPoint, p2: CGPoint) -> CGPoint {
31 |
32 | let v0 = GLKVector2(v: (Float(p0.x), Float(p0.y)))
33 | let v1 = GLKVector2(v: (Float(p1.x), Float(p1.y)))
34 | let v2 = GLKVector2(v: (Float(p2.x), Float(p2.y)))
35 |
36 | let t = Float(_t)
37 |
38 | let v0r = GLKVector2MultiplyScalar(v0, pow(1-t, 2))
39 | let v1r = GLKVector2MultiplyScalar(v1, 2*t*(1-t))
40 | let v2r = GLKVector2MultiplyScalar(v2, t*t)
41 |
42 | var vResult = GLKVector2Add(v0r, v1r)
43 | vResult = GLKVector2Add(vResult, v2r)
44 |
45 | return CGPoint(x: CGFloat(vResult.x), y: CGFloat(vResult.y))
46 | }
47 |
48 | static func cubic(t _t: CGFloat, p0: CGPoint, p1: CGPoint, p2: CGPoint, p3: CGPoint) -> CGPoint {
49 | let v0 = GLKVector2(v: (Float(p0.x), Float(p0.y)))
50 | let v1 = GLKVector2(v: (Float(p1.x), Float(p1.y)))
51 | let v2 = GLKVector2(v: (Float(p2.x), Float(p2.y)))
52 | let v3 = GLKVector2(v: (Float(p3.x), Float(p3.y)))
53 |
54 | let t = Float(_t)
55 |
56 | let v0r = GLKVector2MultiplyScalar(v0, pow(1-t, 3))
57 | let v1r = GLKVector2MultiplyScalar(v1, 3 * t * pow(1-t, 2))
58 | let v2r = GLKVector2MultiplyScalar(v2, 3 * pow(t, 2) * (1-t))
59 | let v3r = GLKVector2MultiplyScalar(v3, pow(t, 3))
60 |
61 | var vResult = GLKVector2Add(v0r, v1r)
62 | vResult = GLKVector2Add(vResult, v2r)
63 | vResult = GLKVector2Add(vResult, v3r)
64 |
65 | return CGPoint(x: CGFloat(vResult.x), y: CGFloat(vResult.y))
66 | }
67 | }
--------------------------------------------------------------------------------
/Examples/TweenApp/Pods/Ubergang/Ubergang/Util/Math.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Math.swift
3 | // Ubergang
4 | //
5 | // Created by Robin Frielingsdorf on 15/05/16.
6 | // Copyright © 2016 Robin Falko. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | class Math {
12 | class func clamp(_ value: T, lower: T, upper: T) -> T {
13 | return max(lower, min(value, upper))
14 | }
15 |
16 | class func mapValueInRange(_ value: Double, fromLower: Double, fromUpper: Double, toLower: Double, toUpper: Double) -> Double {
17 | let fromRangeSize = fromUpper - fromLower
18 | let toRangeSize = toUpper - toLower
19 | let valueScale = (value - fromLower) / fromRangeSize
20 | return toLower + (valueScale * toRangeSize)
21 | }
22 |
23 | class func zigZag(_ x: Double) -> Double {
24 | return 1 / .pi * asin(cos(Double.pi * (x + 1))) + 0.5
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/Examples/TweenApp/TweenApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Examples/TweenApp/TweenApp.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/Examples/TweenApp/TweenApp.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Examples/TweenApp/TweenApp.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/Examples/TweenApp/TweenApp/AdditiveAnimationViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.swift
3 | // TweenApp
4 | //
5 | // Created by RF on 07/01/16.
6 | // Copyright © 2016 Robin Falko. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import Foundation
11 | import Ubergang
12 |
13 | class AdditiveAnimationViewController: ExampleViewController {
14 |
15 |
16 | @IBOutlet var views: [UIImageView]!
17 |
18 | @IBOutlet var targetView: UIImageView!
19 |
20 | var tween: CGPointTween!
21 |
22 | override func viewDidLoad() {
23 | super.viewDidLoad()
24 |
25 | views.forEach {
26 | $0.image = $0.image!.withRenderingMode(UIImage.RenderingMode.alwaysTemplate);
27 | $0.translatesAutoresizingMaskIntoConstraints = true
28 | }
29 | }
30 |
31 | override func setupTween() -> UTweenBase {
32 | return CGPointTween(id: "pointTween")
33 | .from({ [unowned self] in
34 | self.views[0].center
35 | }, to:{ [unowned self] in
36 | self.views[1].center
37 | })
38 | .update { [unowned self] (value:CGPoint, progress: Double) in
39 | self.targetView.center = value
40 | }
41 | .updateTotal { [unowned self] progressTotal in
42 | self.tweenControls.progress(progressTotal)
43 | }
44 | .complete { [unowned self] in
45 | self.tweenControls.stop()
46 | }
47 | .duration(5)
48 | .ease(.cubic(.out))
49 | }
50 |
51 | var selectedView: UIView?
52 | override func touchesBegan(_ touches: Set, with event: UIEvent?) {
53 | let touch = touches.first!
54 | let position = touch.location(in: view)
55 |
56 | selectedView = view.hitTest(position, with: nil)
57 | if selectedView == view {
58 | selectedView = nil
59 | }
60 | if selectedView != nil {
61 | view.bringSubviewToFront(selectedView!)
62 | }
63 | }
64 |
65 |
66 | override func touchesMoved(_ touches: Set, with event: UIEvent?) {
67 | let touch = touches.first!
68 | let position = touch.location(in: view)
69 |
70 | selectedView?.center.x = position.x
71 | selectedView?.center.y = position.y
72 | }
73 |
74 | override func touchesEnded(_ touches: Set, with event: UIEvent?) {
75 | selectedView = nil
76 | }
77 | }
78 |
79 |
--------------------------------------------------------------------------------
/Examples/TweenApp/TweenApp/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // TweenApp
4 | //
5 | // Created by RF on 07/01/16.
6 | // Copyright © 2016 Robin Falko. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import Ubergang
11 |
12 | @UIApplicationMain
13 | class AppDelegate: UIResponder, UIApplicationDelegate {
14 |
15 | var window: UIWindow?
16 |
17 |
18 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
19 |
20 | UserDefaults.standard.setValue(false, forKey: "_UIConstraintBasedLayoutLogUnsatisfiable")
21 |
22 | UTweenSetup.instance.enableLogging(true)
23 |
24 | return true
25 | }
26 |
27 | func applicationWillResignActive(_ application: UIApplication) {
28 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
29 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
30 | }
31 |
32 | func applicationDidEnterBackground(_ application: UIApplication) {
33 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
34 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
35 | }
36 |
37 | func applicationWillEnterForeground(_ application: UIApplication) {
38 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
39 | }
40 |
41 | func applicationDidBecomeActive(_ application: UIApplication) {
42 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
43 | }
44 |
45 | func applicationWillTerminate(_ application: UIApplication) {
46 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
47 | }
48 |
49 |
50 | }
51 |
52 |
--------------------------------------------------------------------------------
/Examples/TweenApp/TweenApp/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "20x20",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "20x20",
11 | "scale" : "3x"
12 | },
13 | {
14 | "size" : "29x29",
15 | "idiom" : "iphone",
16 | "filename" : "Icon-Small.png",
17 | "scale" : "1x"
18 | },
19 | {
20 | "size" : "29x29",
21 | "idiom" : "iphone",
22 | "filename" : "Icon-Small@2x.png",
23 | "scale" : "2x"
24 | },
25 | {
26 | "size" : "29x29",
27 | "idiom" : "iphone",
28 | "filename" : "Icon-Small@3x.png",
29 | "scale" : "3x"
30 | },
31 | {
32 | "size" : "40x40",
33 | "idiom" : "iphone",
34 | "filename" : "Icon-40@2x.png",
35 | "scale" : "2x"
36 | },
37 | {
38 | "size" : "40x40",
39 | "idiom" : "iphone",
40 | "filename" : "Icon-40@3x.png",
41 | "scale" : "3x"
42 | },
43 | {
44 | "size" : "57x57",
45 | "idiom" : "iphone",
46 | "filename" : "Icon.png",
47 | "scale" : "1x"
48 | },
49 | {
50 | "size" : "57x57",
51 | "idiom" : "iphone",
52 | "filename" : "Icon@2x.png",
53 | "scale" : "2x"
54 | },
55 | {
56 | "size" : "60x60",
57 | "idiom" : "iphone",
58 | "filename" : "Icon-60@2x.png",
59 | "scale" : "2x"
60 | },
61 | {
62 | "size" : "60x60",
63 | "idiom" : "iphone",
64 | "filename" : "Icon-60@3x.png",
65 | "scale" : "3x"
66 | },
67 | {
68 | "idiom" : "ipad",
69 | "size" : "20x20",
70 | "scale" : "1x"
71 | },
72 | {
73 | "idiom" : "ipad",
74 | "size" : "20x20",
75 | "scale" : "2x"
76 | },
77 | {
78 | "size" : "29x29",
79 | "idiom" : "ipad",
80 | "filename" : "Icon-Small.png",
81 | "scale" : "1x"
82 | },
83 | {
84 | "size" : "29x29",
85 | "idiom" : "ipad",
86 | "filename" : "Icon-Small@2x.png",
87 | "scale" : "2x"
88 | },
89 | {
90 | "size" : "40x40",
91 | "idiom" : "ipad",
92 | "filename" : "Icon-40.png",
93 | "scale" : "1x"
94 | },
95 | {
96 | "size" : "40x40",
97 | "idiom" : "ipad",
98 | "filename" : "Icon-40@2x.png",
99 | "scale" : "2x"
100 | },
101 | {
102 | "size" : "50x50",
103 | "idiom" : "ipad",
104 | "filename" : "Icon-Small-50.png",
105 | "scale" : "1x"
106 | },
107 | {
108 | "size" : "50x50",
109 | "idiom" : "ipad",
110 | "filename" : "Icon-Small-50@2x.png",
111 | "scale" : "2x"
112 | },
113 | {
114 | "size" : "72x72",
115 | "idiom" : "ipad",
116 | "filename" : "Icon-72.png",
117 | "scale" : "1x"
118 | },
119 | {
120 | "size" : "72x72",
121 | "idiom" : "ipad",
122 | "filename" : "Icon-72@2x.png",
123 | "scale" : "2x"
124 | },
125 | {
126 | "size" : "76x76",
127 | "idiom" : "ipad",
128 | "filename" : "Icon-76.png",
129 | "scale" : "1x"
130 | },
131 | {
132 | "size" : "76x76",
133 | "idiom" : "ipad",
134 | "filename" : "Icon-76@2x.png",
135 | "scale" : "2x"
136 | },
137 | {
138 | "size" : "83.5x83.5",
139 | "idiom" : "ipad",
140 | "filename" : "Icon-83.5@2x.png",
141 | "scale" : "2x"
142 | },
143 | {
144 | "idiom" : "ios-marketing",
145 | "size" : "1024x1024",
146 | "scale" : "1x"
147 | }
148 | ],
149 | "info" : {
150 | "version" : 1,
151 | "author" : "xcode"
152 | }
153 | }
--------------------------------------------------------------------------------
/Examples/TweenApp/TweenApp/Assets.xcassets/AppIcon.appiconset/Icon-40.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RobinFalko/Ubergang/4f61d0677e96dcd724f06f5765816bbfc2732ece/Examples/TweenApp/TweenApp/Assets.xcassets/AppIcon.appiconset/Icon-40.png
--------------------------------------------------------------------------------
/Examples/TweenApp/TweenApp/Assets.xcassets/AppIcon.appiconset/Icon-40@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RobinFalko/Ubergang/4f61d0677e96dcd724f06f5765816bbfc2732ece/Examples/TweenApp/TweenApp/Assets.xcassets/AppIcon.appiconset/Icon-40@2x.png
--------------------------------------------------------------------------------
/Examples/TweenApp/TweenApp/Assets.xcassets/AppIcon.appiconset/Icon-40@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RobinFalko/Ubergang/4f61d0677e96dcd724f06f5765816bbfc2732ece/Examples/TweenApp/TweenApp/Assets.xcassets/AppIcon.appiconset/Icon-40@3x.png
--------------------------------------------------------------------------------
/Examples/TweenApp/TweenApp/Assets.xcassets/AppIcon.appiconset/Icon-60@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RobinFalko/Ubergang/4f61d0677e96dcd724f06f5765816bbfc2732ece/Examples/TweenApp/TweenApp/Assets.xcassets/AppIcon.appiconset/Icon-60@2x.png
--------------------------------------------------------------------------------
/Examples/TweenApp/TweenApp/Assets.xcassets/AppIcon.appiconset/Icon-60@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RobinFalko/Ubergang/4f61d0677e96dcd724f06f5765816bbfc2732ece/Examples/TweenApp/TweenApp/Assets.xcassets/AppIcon.appiconset/Icon-60@3x.png
--------------------------------------------------------------------------------
/Examples/TweenApp/TweenApp/Assets.xcassets/AppIcon.appiconset/Icon-72.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RobinFalko/Ubergang/4f61d0677e96dcd724f06f5765816bbfc2732ece/Examples/TweenApp/TweenApp/Assets.xcassets/AppIcon.appiconset/Icon-72.png
--------------------------------------------------------------------------------
/Examples/TweenApp/TweenApp/Assets.xcassets/AppIcon.appiconset/Icon-72@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RobinFalko/Ubergang/4f61d0677e96dcd724f06f5765816bbfc2732ece/Examples/TweenApp/TweenApp/Assets.xcassets/AppIcon.appiconset/Icon-72@2x.png
--------------------------------------------------------------------------------
/Examples/TweenApp/TweenApp/Assets.xcassets/AppIcon.appiconset/Icon-76.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RobinFalko/Ubergang/4f61d0677e96dcd724f06f5765816bbfc2732ece/Examples/TweenApp/TweenApp/Assets.xcassets/AppIcon.appiconset/Icon-76.png
--------------------------------------------------------------------------------
/Examples/TweenApp/TweenApp/Assets.xcassets/AppIcon.appiconset/Icon-76@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RobinFalko/Ubergang/4f61d0677e96dcd724f06f5765816bbfc2732ece/Examples/TweenApp/TweenApp/Assets.xcassets/AppIcon.appiconset/Icon-76@2x.png
--------------------------------------------------------------------------------
/Examples/TweenApp/TweenApp/Assets.xcassets/AppIcon.appiconset/Icon-83.5@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RobinFalko/Ubergang/4f61d0677e96dcd724f06f5765816bbfc2732ece/Examples/TweenApp/TweenApp/Assets.xcassets/AppIcon.appiconset/Icon-83.5@2x.png
--------------------------------------------------------------------------------
/Examples/TweenApp/TweenApp/Assets.xcassets/AppIcon.appiconset/Icon-Small-50.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RobinFalko/Ubergang/4f61d0677e96dcd724f06f5765816bbfc2732ece/Examples/TweenApp/TweenApp/Assets.xcassets/AppIcon.appiconset/Icon-Small-50.png
--------------------------------------------------------------------------------
/Examples/TweenApp/TweenApp/Assets.xcassets/AppIcon.appiconset/Icon-Small-50@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RobinFalko/Ubergang/4f61d0677e96dcd724f06f5765816bbfc2732ece/Examples/TweenApp/TweenApp/Assets.xcassets/AppIcon.appiconset/Icon-Small-50@2x.png
--------------------------------------------------------------------------------
/Examples/TweenApp/TweenApp/Assets.xcassets/AppIcon.appiconset/Icon-Small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RobinFalko/Ubergang/4f61d0677e96dcd724f06f5765816bbfc2732ece/Examples/TweenApp/TweenApp/Assets.xcassets/AppIcon.appiconset/Icon-Small.png
--------------------------------------------------------------------------------
/Examples/TweenApp/TweenApp/Assets.xcassets/AppIcon.appiconset/Icon-Small@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RobinFalko/Ubergang/4f61d0677e96dcd724f06f5765816bbfc2732ece/Examples/TweenApp/TweenApp/Assets.xcassets/AppIcon.appiconset/Icon-Small@2x.png
--------------------------------------------------------------------------------
/Examples/TweenApp/TweenApp/Assets.xcassets/AppIcon.appiconset/Icon-Small@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RobinFalko/Ubergang/4f61d0677e96dcd724f06f5765816bbfc2732ece/Examples/TweenApp/TweenApp/Assets.xcassets/AppIcon.appiconset/Icon-Small@3x.png
--------------------------------------------------------------------------------
/Examples/TweenApp/TweenApp/Assets.xcassets/AppIcon.appiconset/Icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RobinFalko/Ubergang/4f61d0677e96dcd724f06f5765816bbfc2732ece/Examples/TweenApp/TweenApp/Assets.xcassets/AppIcon.appiconset/Icon.png
--------------------------------------------------------------------------------
/Examples/TweenApp/TweenApp/Assets.xcassets/AppIcon.appiconset/Icon@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RobinFalko/Ubergang/4f61d0677e96dcd724f06f5765816bbfc2732ece/Examples/TweenApp/TweenApp/Assets.xcassets/AppIcon.appiconset/Icon@2x.png
--------------------------------------------------------------------------------
/Examples/TweenApp/TweenApp/Assets.xcassets/CircleBG.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "circleBG.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/Examples/TweenApp/TweenApp/Assets.xcassets/CircleBG.imageset/circleBG.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RobinFalko/Ubergang/4f61d0677e96dcd724f06f5765816bbfc2732ece/Examples/TweenApp/TweenApp/Assets.xcassets/CircleBG.imageset/circleBG.png
--------------------------------------------------------------------------------
/Examples/TweenApp/TweenApp/Assets.xcassets/CircleOutline.imageset/CircleOutline.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RobinFalko/Ubergang/4f61d0677e96dcd724f06f5765816bbfc2732ece/Examples/TweenApp/TweenApp/Assets.xcassets/CircleOutline.imageset/CircleOutline.png
--------------------------------------------------------------------------------
/Examples/TweenApp/TweenApp/Assets.xcassets/CircleOutline.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "CircleOutline.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/Examples/TweenApp/TweenApp/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/Examples/TweenApp/TweenApp/Assets.xcassets/Dot.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "dot.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/Examples/TweenApp/TweenApp/Assets.xcassets/Dot.imageset/dot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RobinFalko/Ubergang/4f61d0677e96dcd724f06f5765816bbfc2732ece/Examples/TweenApp/TweenApp/Assets.xcassets/Dot.imageset/dot.png
--------------------------------------------------------------------------------
/Examples/TweenApp/TweenApp/Assets.xcassets/PauseIcon.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "PauseIcon.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/Examples/TweenApp/TweenApp/Assets.xcassets/PauseIcon.imageset/PauseIcon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RobinFalko/Ubergang/4f61d0677e96dcd724f06f5765816bbfc2732ece/Examples/TweenApp/TweenApp/Assets.xcassets/PauseIcon.imageset/PauseIcon.png
--------------------------------------------------------------------------------
/Examples/TweenApp/TweenApp/Assets.xcassets/PlayIcon.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "PlayIcon.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/Examples/TweenApp/TweenApp/Assets.xcassets/PlayIcon.imageset/PlayIcon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RobinFalko/Ubergang/4f61d0677e96dcd724f06f5765816bbfc2732ece/Examples/TweenApp/TweenApp/Assets.xcassets/PlayIcon.imageset/PlayIcon.png
--------------------------------------------------------------------------------
/Examples/TweenApp/TweenApp/Assets.xcassets/ReverseIcon.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "ReverseIcon.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | },
21 | "properties" : {
22 | "template-rendering-intent" : "template"
23 | }
24 | }
--------------------------------------------------------------------------------
/Examples/TweenApp/TweenApp/Assets.xcassets/ReverseIcon.imageset/ReverseIcon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RobinFalko/Ubergang/4f61d0677e96dcd724f06f5765816bbfc2732ece/Examples/TweenApp/TweenApp/Assets.xcassets/ReverseIcon.imageset/ReverseIcon.png
--------------------------------------------------------------------------------
/Examples/TweenApp/TweenApp/Assets.xcassets/SliderThumb.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "SliderThumb.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/Examples/TweenApp/TweenApp/Assets.xcassets/SliderThumb.imageset/SliderThumb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RobinFalko/Ubergang/4f61d0677e96dcd724f06f5765816bbfc2732ece/Examples/TweenApp/TweenApp/Assets.xcassets/SliderThumb.imageset/SliderThumb.png
--------------------------------------------------------------------------------
/Examples/TweenApp/TweenApp/Assets.xcassets/StopIcon.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "StopIcon.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/Examples/TweenApp/TweenApp/Assets.xcassets/StopIcon.imageset/StopIcon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RobinFalko/Ubergang/4f61d0677e96dcd724f06f5765816bbfc2732ece/Examples/TweenApp/TweenApp/Assets.xcassets/StopIcon.imageset/StopIcon.png
--------------------------------------------------------------------------------
/Examples/TweenApp/TweenApp/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 |
--------------------------------------------------------------------------------
/Examples/TweenApp/TweenApp/BezierPathViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.swift
3 | // TweenApp
4 | //
5 | // Created by RF on 07/01/16.
6 | // Copyright © 2016 Robin Falko. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import Foundation
11 | import Ubergang
12 |
13 | class BezierPathViewController: ExampleViewController {
14 |
15 | var targetView: UIImageView!
16 |
17 | var random: CGFloat {
18 | return CGFloat(Double(arc4random_uniform(255)) / 255.0)
19 | }
20 |
21 | override func loadView() {
22 | super.loadView()
23 |
24 | targetView = UIImageView(image: UIImage(named: "SliderThumb"))
25 | view.addSubview(targetView)
26 | }
27 |
28 | override func setupTween() -> UTweenBase {
29 | let rectWidth = CGFloat(130)
30 | let centerX = (UIScreen.main.bounds.width - rectWidth) * 0.5
31 | let path = heartInRect(CGRect(x: centerX, y: 100, width: rectWidth, height: 260))
32 | // let path = randomPath()
33 |
34 | drawPath(path)
35 |
36 | return BezierPathTween(id: "bezierTween")
37 | .along(path)
38 | .update { [weak self] in
39 | self?.targetView.center = $0
40 | }
41 | .duration(15)
42 | .ease(.linear)
43 | .options(.repeat(1))
44 | .updateTotal { [weak self] value in
45 | self?.tweenControls.progress(value)
46 | }
47 | .complete { [weak self] in
48 | self?.tweenControls.stop()
49 | }
50 | }
51 |
52 | func drawPath(_ path: UIBezierPath) {
53 | let shape = CAShapeLayer()
54 | shape.path = path.cgPath
55 | shape.strokeColor = UIColor.red.cgColor
56 | shape.lineWidth = 5
57 | shape.fillColor = UIColor.clear.cgColor
58 | view.layer.addSublayer(shape)
59 | }
60 |
61 | func heartInRect(_ rect:CGRect) -> UIBezierPath {
62 | let path = UIBezierPath()
63 |
64 | let center = rect.minX + rect.width * 0.5
65 | let bottom = rect.maxY
66 |
67 | let startPoint = CGPoint(x: center, y: bottom)
68 | self.targetView.center = startPoint
69 | path.move(to: startPoint)
70 |
71 | var p1 = CGPoint(x: center, y: bottom - 60)
72 | var p2 = CGPoint(x: center - 160, y: bottom - 116)
73 | var p3 = CGPoint(x: center - 130, y: bottom - 200)
74 | path.addCurve(to: p3, controlPoint1: p1, controlPoint2: p2)
75 |
76 | p1 = CGPoint(x: center - 100, y: bottom - 280)
77 | p2 = CGPoint(x: center - 15, y: bottom - 255)
78 | p3 = CGPoint(x: center, y: bottom - 225)
79 | path.addCurve(to: p3, controlPoint1: p1, controlPoint2: p2)
80 |
81 | p1 = CGPoint(x: center + 15, y: bottom - 255)
82 | p2 = CGPoint(x: center + 100, y: bottom - 280)
83 | p3 = CGPoint(x: center + 130, y: bottom - 200)
84 | path.addCurve(to: p3, controlPoint1: p1, controlPoint2: p2)
85 |
86 | p1 = CGPoint(x: center + 160, y: bottom - 116)
87 | p2 = CGPoint(x: center, y: bottom - 60)
88 | p3 = CGPoint(x: center, y: bottom)
89 | path.addCurve(to: p3, controlPoint1: p1, controlPoint2: p2)
90 |
91 | return path
92 | }
93 |
94 | func randomPath() -> UIBezierPath {
95 | let path = UIBezierPath()
96 |
97 | let startPoint = CGPoint(x: 20, y: 100)
98 | self.targetView.center = startPoint
99 | path.move(to: startPoint)
100 |
101 | for _ in 0...3 {
102 | print("\(arc4random_uniform(2))")
103 | let rnd = arc4random_uniform(3)
104 | switch rnd {
105 | case 0:
106 | path.addLine(to: getRndPointOnScreen())
107 | case 1:
108 | let p1 = getRndPointOnScreen()
109 | let p2 = getRndPointOnScreen()
110 | path.addQuadCurve(to: p2, controlPoint: p1)
111 | default:
112 | let p1 = getRndPointOnScreen()
113 | let p2 = getRndPointOnScreen()
114 | let p3 = getRndPointOnScreen()
115 | path.addCurve(to: p3, controlPoint1: p1, controlPoint2: p2)
116 | }
117 | }
118 |
119 | path.close()
120 |
121 | let shape = CAShapeLayer()
122 | shape.path = path.cgPath
123 | shape.strokeColor = UIColor.red.cgColor
124 | shape.fillColor = UIColor.clear.cgColor
125 | view.layer.addSublayer(shape)
126 |
127 | return path
128 | }
129 |
130 | func getRndPointOnScreen() -> CGPoint {
131 | let width = UInt32(UIScreen.main.bounds.width - 40)
132 | let height = UInt32(UIScreen.main.bounds.height - 200)
133 |
134 | let rndWidth = CGFloat(arc4random_uniform(width))
135 | let rndHeight = CGFloat(arc4random_uniform(height))
136 |
137 | return CGPoint(x: rndWidth + 20, y: rndHeight + 100)
138 | }
139 | }
140 |
141 |
--------------------------------------------------------------------------------
/Examples/TweenApp/TweenApp/ColorViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.swift
3 | // TweenApp
4 | //
5 | // Created by RF on 07/01/16.
6 | // Copyright © 2016 Robin Falko. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import Foundation
11 | import Ubergang
12 |
13 | class ColorViewController: ExampleViewController {
14 |
15 | @IBOutlet var targetView: UIView!
16 |
17 | var random: CGFloat {
18 | return CGFloat(Double(arc4random_uniform(255)) / 255.0)
19 | }
20 |
21 | override func setupTween() -> UTweenBase {
22 | let colorTo = UIColor(red: random, green: random, blue: random, alpha: 1.0)
23 | let colorFrom = UIColor(red: random, green: random, blue: random, alpha: 1.0)
24 |
25 | self.targetView.backgroundColor = colorFrom
26 |
27 | return colorFrom.tween(to: colorTo)
28 | .duration(1)
29 | .update { [unowned self] (value:UIColor, progress: Double) in
30 | self.targetView.backgroundColor = value
31 | self.tweenControls.progress(progress)
32 | }
33 | .complete { [unowned self] in
34 | self.tweenControls.stop()
35 | }
36 | }
37 | }
38 |
39 |
--------------------------------------------------------------------------------
/Examples/TweenApp/TweenApp/ConstraintViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ConstraintViewController.swift
3 | // TweenApp
4 | //
5 | // Created by RF on 07/01/16.
6 | // Copyright © 2016 Robin Falko. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import Ubergang
11 |
12 | class ConstraintViewController: ExampleViewController {
13 | @IBOutlet var redViewHeight: NSLayoutConstraint!
14 | @IBOutlet var grayViewWidth: NSLayoutConstraint!
15 | @IBOutlet var greenViewBottom: NSLayoutConstraint!
16 |
17 | var defaultRedViewHeight: CGFloat!
18 | var defaultGrayViewWidth: CGFloat!
19 | var defaultGreenViewBottom: CGFloat!
20 |
21 | override func loadView() {
22 | super.loadView()
23 |
24 | defaultRedViewHeight = redViewHeight.constant
25 | defaultGrayViewWidth = grayViewWidth.constant
26 | defaultGreenViewBottom = greenViewBottom.constant
27 | }
28 |
29 | override func setupTween() -> UTweenBase {
30 | let timeline = UTimeline()
31 | .reference(.weak)
32 | .updateTotal { [unowned self] (progressTotal) in
33 | self.tweenControls.progress(progressTotal)
34 | }
35 | .complete { [unowned self] in
36 | self.tweenControls.stop()
37 | }
38 |
39 | let tween1 = defaultRedViewHeight!.tween(to: 50)
40 | .update { [unowned self] in
41 | self.redViewHeight.constant = $0
42 | }
43 | .duration(1)
44 | .ease(.quint(.inOut))
45 |
46 | let tween2 = defaultGrayViewWidth!.tween(to: 150)
47 | .update { [unowned self] in
48 | self.grayViewWidth.constant = $0
49 | }
50 | .duration(2)
51 | .ease(.bounce(.out))
52 |
53 | let tween3 = defaultGreenViewBottom!.tween(to: 100)
54 | .update { [unowned self] in
55 | self.greenViewBottom.constant = $0
56 | }
57 | .duration(3)
58 | .options(.repeat(1), .yoyo)
59 | .ease(.expo(.inOut))
60 |
61 | timeline.append(tween1)
62 | timeline.append(tween2)
63 | timeline.append(tween3)
64 |
65 | return timeline
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/Examples/TweenApp/TweenApp/CurveThroughViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.swift
3 | // TweenApp
4 | //
5 | // Created by RF on 07/01/16.
6 | // Copyright © 2016 Robin Falko. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import Foundation
11 | import Ubergang
12 |
13 | class CurveThroughViewController: ExampleViewController {
14 |
15 | var targetView: UIImageView!
16 |
17 | override func loadView() {
18 | super.loadView()
19 |
20 | targetView = UIImageView(image: UIImage(named: "PlayIcon")?.withRenderingMode(.alwaysTemplate))
21 | targetView.tintColor = UIColor(red: 73 / 255, green: 205 / 255, blue: 6 / 255, alpha: 0.75)
22 | view.addSubview(targetView)
23 | }
24 |
25 | override func setupTween() -> UTweenBase {
26 | let rectWidth = CGFloat(130)
27 | let centerX = (UIScreen.main.bounds.width - rectWidth) * 0.5
28 | let points = raceTrack(CGRect(x: centerX, y: 100, width: rectWidth, height: 260))
29 |
30 | let numbers = points.map { NSValue(cgPoint: $0) }
31 | let path = UIBezierPath.interpolateCGPoints(withCatmullRom: numbers, closed: true, alpha: 1.0)
32 |
33 | drawPath(path!)
34 |
35 | return BezierPathTween(id: "bezierTween")
36 | .along(points, closed: true)
37 | .update { [weak self] (value:CGPoint, progress: Double, orientation: CGPoint) in
38 | self?.targetView.center = value
39 |
40 | let angle = atan2(orientation.y, orientation.x)
41 | let transform = CGAffineTransform.identity.rotated(by: angle)
42 | self?.targetView.transform = transform
43 | }
44 | .duration(10)
45 | .ease(.linear)
46 | .options(.repeat(1))
47 | .updateTotal { [weak self] value in
48 | self?.tweenControls.progress(value)
49 | }
50 | .complete { [weak self] in
51 | self?.tweenControls.stop()
52 | }
53 | }
54 |
55 | func drawPath(_ path: UIBezierPath) {
56 | let shape = CAShapeLayer()
57 | shape.path = path.cgPath
58 | shape.strokeColor = UIColor.red.cgColor
59 | shape.fillColor = UIColor.clear.cgColor
60 | view.layer.addSublayer(shape)
61 | }
62 |
63 | func raceTrack(_ rect:CGRect) -> [CGPoint] {
64 |
65 | let startPoint = CGPoint(x: rect.minX, y: rect.minY)
66 | self.targetView.center = startPoint
67 |
68 | var points = [CGPoint]()
69 | points.append(startPoint)
70 | points.append(CGPoint(x: rect.midX, y: rect.midY))
71 | points.append(CGPoint(x: rect.minX, y: rect.maxY))
72 | points.append(CGPoint(x: rect.maxX, y: rect.maxY))
73 | points.append(CGPoint(x: rect.maxX, y: rect.minY))
74 |
75 | return points
76 | }
77 | }
78 |
79 |
--------------------------------------------------------------------------------
/Examples/TweenApp/TweenApp/ExampleViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ExampleViewController.swift
3 | // TweenApp
4 | //
5 | // Created by RF on 15/05/16.
6 | // Copyright © 2016 Robin Falko. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import Ubergang
11 |
12 | class ExampleViewController: UIViewController {
13 |
14 | var tweenControls: TweenControlsView!
15 |
16 | override func viewDidLoad() {
17 | super.viewDidLoad()
18 |
19 | addTweenControls(setupTween())
20 | }
21 |
22 | deinit {
23 | print("deinit \(type(of: self))")
24 | }
25 |
26 | func setupTween() -> UTweenBase {
27 | //override
28 | return UTween()
29 | }
30 |
31 | func addTweenControls(_ tween: UTweenBase) {
32 | tweenControls = TweenControlsView.instanceFromNib()
33 | tweenControls.progress(0.0)
34 | tweenControls.onPlay = {
35 | tween.start()
36 | }
37 | tweenControls.onStop = {
38 | tween.stop()
39 | }
40 | tweenControls.onPause = {
41 | tween.pause()
42 | }
43 | tweenControls.onResume = {
44 | tween.resume()
45 | }
46 | tweenControls.onDirection = { value in
47 | tween.direction(value)
48 | }
49 | tweenControls.onProgress = { value in
50 | tween.progressTotal = value
51 | }
52 | view.addSubview(tweenControls)
53 |
54 | tween.progressTotal = 0
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/Examples/TweenApp/TweenApp/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 | UILaunchStoryboardName
26 | LaunchScreen
27 | UIMainStoryboardFile
28 | Main
29 | UIRequiredDeviceCapabilities
30 |
31 | armv7
32 |
33 | UISupportedInterfaceOrientations
34 |
35 | UIInterfaceOrientationPortrait
36 | UIInterfaceOrientationLandscapeLeft
37 | UIInterfaceOrientationLandscapeRight
38 |
39 | UISupportedInterfaceOrientations~ipad
40 |
41 | UIInterfaceOrientationPortrait
42 | UIInterfaceOrientationPortraitUpsideDown
43 | UIInterfaceOrientationLandscapeLeft
44 | UIInterfaceOrientationLandscapeRight
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/Examples/TweenApp/TweenApp/InsertTimelineViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // InsertTimelineViewController.swift
3 | // TweenApp
4 | //
5 | // Created by RF on 05.08.17.
6 | // Copyright © 2017 Robin Falko. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import Ubergang
11 |
12 | class InsertTimelineViewController: ExampleViewController {
13 |
14 | @IBOutlet var viewCenterY: NSLayoutConstraint!
15 | @IBOutlet var viewCenterX: NSLayoutConstraint!
16 |
17 | override func setupTween() -> UTweenBase {
18 | let timeline = UTimeline()
19 | .reference(.weak)
20 | .options(.repeat(1))
21 | .updateTotal { [unowned self] in
22 | self.tweenControls.progress($0)
23 | }
24 | .complete { [unowned self] in
25 | self.tweenControls.stop()
26 | }
27 |
28 | //time 0 to 0.5
29 | timeline.append(CGFloat(0).tween(to: 100).update({ [unowned self] (value: CGFloat) in
30 | self.viewCenterY.constant = value
31 | })
32 | )
33 |
34 | //time 4 to 4.5
35 | timeline.insert(CGFloat(0).tween(to: 100).update({ [unowned self] in
36 | self.viewCenterX.constant = $0
37 | }), at: 4)
38 |
39 | //time 5 to 7
40 | timeline.insert(CGFloat(100).tween(to: -100).update({ [unowned self] (value: CGFloat) in
41 | self.viewCenterX.constant = value
42 | self.viewCenterY.constant = value
43 | })
44 | .duration(2)
45 | , at: 5)
46 |
47 | //time 7 to 9
48 | timeline.insert(CGFloat(-100).tween(to: 0).update({ [unowned self] (value: CGFloat) in
49 | self.viewCenterX.constant = value
50 | })
51 | .duration(2)
52 | , at: 7)
53 |
54 | //time 9.5 to 10
55 | timeline.insert(CGFloat(-100).tween(to: 0).update({ [unowned self] in
56 | self.viewCenterY.constant = $0
57 | }), at: 9.5)
58 |
59 | return timeline
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/Examples/TweenApp/TweenApp/MainTableViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MainTableViewController.swift
3 | // TweenApp
4 | //
5 | // Created by RF on 08/04/16.
6 | // Copyright © 2016 Robin Falko. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class MainTableViewController: UITableViewController {
12 | override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
13 | if let cell = cell as? TitleIconTableViewCell {
14 | cell.animateIn()
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/Examples/TweenApp/TweenApp/NumericViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.swift
3 | // TweenApp
4 | //
5 | // Created by RF on 07/01/16.
6 | // Copyright © 2016 Robin Falko. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import Ubergang
11 |
12 | class NumericViewController: ExampleViewController {
13 | @IBOutlet var numberLabel: UILabel!
14 |
15 | override func setupTween() -> UTweenBase {
16 | return 0.tween(to:100)
17 | .update { [unowned self] (value:Int, progress: Double) in
18 | self.numberLabel.text = "\(value)"
19 | self.tweenControls.progress(progress)
20 | }
21 | .complete { [unowned self] in
22 | self.tweenControls.stop()
23 | }
24 | }
25 | }
26 |
27 |
--------------------------------------------------------------------------------
/Examples/TweenApp/TweenApp/ParticleViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ParticleViewController.swift
3 | // TweenApp
4 | //
5 | // Created by RF on 07/01/16.
6 | // Copyright © 2016 Robin Falko. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import Ubergang
11 |
12 | class ParticleViewController: ExampleViewController {
13 | var numTweens: UInt32 = 500
14 |
15 | var particles = [UIView]()
16 |
17 | override func loadView() {
18 | super.loadView()
19 |
20 | createViews()
21 | }
22 |
23 | func createViews() {
24 | let bounds = UIScreen.main.bounds
25 |
26 | for _: UInt32 in 0.. UTweenBase {
39 | let timeline = UTimeline(id: "particleTimeline")
40 | .reference(.weak)
41 | .updateTotal { [unowned self] (progressTotal) in
42 | self.tweenControls.progress(progressTotal)
43 | }
44 | .complete { [unowned self] in
45 | self.tweenControls.stop()
46 | }
47 |
48 | for i in 0.. UTweenBase {
21 | return 0.0.tween(to: 10)
22 | .id("progressTween")
23 | .duration(5)
24 | .ease(.cubic(.out))
25 | .options(.repeat(1), .yoyo)
26 | .reference(.weak)
27 | .update { [unowned self] (value, progress) in
28 | self.progressBar.progress = Float(progress)
29 | self.tweenLabel.text = "\(round(value * 10.0) / 10.0)"
30 | }
31 | .updateTotal { [unowned self] (progressTotal) in
32 | self.tweenControls.progress(progressTotal)
33 | self.progressBarTotal.progress = Float(progressTotal)
34 | }
35 | .repeatCycleChange { [unowned self] cycle in
36 | self.repeatCycleLabel.text = "\(cycle)"
37 | }
38 | .complete { [unowned self] in
39 | self.tweenControls.stop()
40 | }
41 | }
42 | }
43 |
44 |
--------------------------------------------------------------------------------
/Examples/TweenApp/TweenApp/TimelinesViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.swift
3 | // TweenApp
4 | //
5 | // Created by RF on 07/01/16.
6 | // Copyright © 2016 Robin Falko. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import Ubergang
11 |
12 | class TimelinesViewController: ExampleViewController {
13 | @IBOutlet weak var tweenStatusView0: TweenStatusView!
14 | @IBOutlet weak var tweenStatusView1: TweenStatusView!
15 | @IBOutlet weak var tweenStatusView2: TweenStatusView!
16 | @IBOutlet weak var tweenStatusView3: TweenStatusView!
17 | @IBOutlet var numberLabel: UILabel!
18 | @IBOutlet var progressBar: CircularProgressBar!
19 |
20 | override func setupTween() -> UTweenBase {
21 | let timeline = UTimeline(id: "timeline")
22 | .options(.repeat(9))
23 | .repeatCycleChange { [unowned self] repeatCycle in
24 | self.tweenStatusView2.repeatCount = repeatCycle
25 | }
26 | .update { [unowned self] progress in
27 | self.tweenStatusView2.progress = Float(progress)
28 | }
29 | .updateTotal { [unowned self] progressTotal in
30 | self.tweenStatusView2.progressTotal = Float(progressTotal)
31 | self.tweenControls.progress(progressTotal)
32 | }
33 |
34 | //closing arc
35 | let tween0 = NumericTween(id: "arcIncreaseTween")
36 | .from(-360.0, to: -0.1)
37 | .duration(5)
38 | .ease(.cubic(.inOut))
39 | .update { [unowned self] (value: CGFloat, progress: Double) in
40 | self.tweenStatusView0.progress = Float(progress)
41 | self.progressBar.endAngle = value
42 | }
43 | .updateTotal { [unowned self] progress in
44 | self.tweenStatusView0.progressTotal = Float(progress)
45 | }
46 | timeline.append(tween0)
47 |
48 | let tween1 = NumericTween(id: "arcDecreaseTween")
49 | .from(-360, to: -0.1)
50 | .duration(5)
51 | .ease(.cubic(.inOut))
52 | .update { [unowned self] (value: CGFloat, progress: Double) in
53 | self.tweenStatusView1.progress = Float(progress)
54 | self.progressBar.startAngle = value
55 | }
56 | .updateTotal { [unowned self] progress in
57 | self.tweenStatusView1.progressTotal = Float(progress)
58 | }
59 | //opening arc
60 | timeline.append(tween1)
61 |
62 |
63 | let timelineContainer = UTimeline(id: "timelineContainer")
64 | .reference(.weak)
65 | .repeatCycleChange { [unowned self] repeatCycle in
66 | self.tweenStatusView3.repeatCount = repeatCycle
67 | }
68 | .update { [unowned self] progress in
69 | self.tweenStatusView3.progress = Float(progress)
70 | }
71 | .updateTotal { [unowned self] progressTotal in
72 | self.tweenStatusView3.progressTotal = Float(progressTotal)
73 | }
74 | .complete { [unowned self] in
75 | self.tweenControls.stop()
76 | }
77 |
78 | //timeline arcs
79 | timelineContainer.insert(timeline, at: 0)
80 |
81 | //countdown
82 | timelineContainer.insert( 10.tween(to: 0)
83 | .id("countTween")
84 | .duration(10)
85 | .ease(.linear)
86 | .reference(.weak)
87 | .update { [unowned self] (value: Int) in
88 | self.numberLabel.text = String(value)
89 | }, at: 0)
90 |
91 | self.tweenStatusView0.title = "\(tween0.id)"
92 | self.tweenStatusView1.title = "\(tween1.id)"
93 | self.tweenStatusView2.title = "\(timeline.id)"
94 | self.tweenStatusView3.title = "\(timelineContainer.id)"
95 |
96 | return timelineContainer
97 | }
98 | }
99 |
100 |
--------------------------------------------------------------------------------
/Examples/TweenApp/TweenApp/TransformViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // TransformViewController.swift
3 | // TweenApp
4 | //
5 | // Created by RF on 07/01/16.
6 | // Copyright © 2016 Robin Falko. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import Ubergang
11 |
12 | class TransformViewController: ExampleViewController {
13 | @IBOutlet var testView: UIView!
14 | @IBOutlet var slider: UISlider!
15 |
16 | override func setupTween() -> UTweenBase {
17 | testView.transform = CGAffineTransform.identity
18 |
19 | var to = CGAffineTransform(scaleX: 2, y: 2)
20 | to = to.rotated(by: CGFloat(Double.pi / 2))
21 |
22 | return TransformTween(id: "transformTween")
23 | .from(testView.transform, to: to)
24 | .update { [unowned self] (value, progress) in
25 | self.testView.transform = value
26 | }
27 | .duration(4)
28 | .ease(.elastic(.out))
29 | .reference(.weak)
30 | .updateTotal { [unowned self] (progressTotal) in
31 | self.tweenControls.progress(progressTotal)
32 | }
33 | .complete { [unowned self] in
34 | self.tweenControls.stop()
35 | }
36 | }
37 | }
38 |
39 |
--------------------------------------------------------------------------------
/Examples/TweenApp/TweenApp/Ubergang-Bridging-Header.h:
--------------------------------------------------------------------------------
1 | //
2 | // Ubergang-Bridging-Header.h
3 | // Ubergang
4 | //
5 | // Created by RF on 23/05/16.
6 | // Copyright © 2016 Robin Falko. All rights reserved.
7 | //
8 |
9 | #ifndef Ubergang_Bridging_Header_h
10 | #define Ubergang_Bridging_Header_h
11 |
12 | #import "UIBezierPath+Interpolation.h"
13 |
14 | #endif /* Ubergang_Bridging_Header_h */
15 |
--------------------------------------------------------------------------------
/Examples/TweenApp/TweenApp/Views/CircularProgressBar.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CircularProgressBar.swift
3 | // TweenApp
4 | //
5 | // Created by RF on 09/04/16.
6 | // Copyright © 2016 Robin Falko. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class CircularProgressBar: UIView {
12 | let degToRad = CGFloat(.pi / 180.0)
13 |
14 | var shapeLayer:CAShapeLayer!
15 |
16 | var _startAngle: CGFloat = -90.0
17 | var startAngle: CGFloat {
18 | get {
19 | return _startAngle
20 | }
21 | set {
22 | _startAngle = newValue - 90
23 | update()
24 | }
25 | }
26 | var _endAngle: CGFloat = -90.0
27 | var endAngle: CGFloat {
28 | get {
29 | return _endAngle
30 | }
31 | set {
32 | _endAngle = newValue - 90
33 | update()
34 | }
35 | }
36 |
37 | override init(frame: CGRect) {
38 | super.init(frame: frame)
39 | setup()
40 | }
41 |
42 | required init?(coder aDecoder: NSCoder) {
43 | super.init(coder: aDecoder)
44 | setup()
45 | }
46 |
47 | func setup() {
48 | shapeLayer = CAShapeLayer()
49 |
50 | update()
51 |
52 | shapeLayer.strokeColor = UIColor.black.cgColor
53 | shapeLayer.fillColor = UIColor.clear.cgColor
54 | shapeLayer.lineWidth = 10.0
55 |
56 | self.layer.addSublayer(shapeLayer)
57 | }
58 |
59 | func update() {
60 | shapeLayer.path = arcPath().cgPath
61 | }
62 |
63 | func arcPath() -> UIBezierPath {
64 | let radius = frame.size.width * 0.5
65 | let path = UIBezierPath(arcCenter: CGPoint(x: radius, y: radius),
66 | radius: radius,
67 | startAngle: startAngle * degToRad,
68 | endAngle: endAngle * degToRad,
69 | clockwise: true)
70 |
71 | return path
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/Examples/TweenApp/TweenApp/Views/ReverseButton.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ReverseButton.swift
3 | // TweenApp
4 | //
5 | // Created by RF on 16/05/16.
6 | // Copyright © 2016 Robin Falko. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import Ubergang
11 |
12 | class ReverseButtton: TweenControlButton {
13 |
14 | var numericTween: NumericTween!
15 |
16 | override var isSelected: Bool {
17 | get {
18 | return super.isSelected
19 | }
20 | set {
21 | if newValue {
22 | numericTween.direction(.forward).start()
23 | } else {
24 | numericTween.direction(.reverse).start()
25 | }
26 | super.isSelected = newValue
27 | }
28 | }
29 |
30 |
31 | override func setupTween() {
32 | super.setupTween()
33 |
34 | let degToRad = .pi / 180.0
35 |
36 | numericTween = NumericTween(id: "transform_\(arc4random())")
37 | .from(0, to: CGFloat(180 * degToRad))
38 | .update { [unowned self] value in
39 | self.imageView!.layer.transform = CATransform3DRotate(CATransform3DIdentity, value, 0.0, 1.0, 0.0)
40 | }
41 | .duration(0.5)
42 | .ease(.cubic(.inOut))
43 | .reference(.weak)
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/Examples/TweenApp/TweenApp/Views/TitleIconTableViewCell.swift:
--------------------------------------------------------------------------------
1 | //
2 | // TitleIconTableViewCell.swift
3 | // TweenApp
4 | //
5 | // Created by RF on 08/04/16.
6 | // Copyright © 2016 Robin Falko. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import Ubergang
11 |
12 | class TitleIconTableViewCell: UITableViewCell {
13 |
14 | @IBOutlet var titleLabelConstraints: NSLayoutConstraint!
15 | @IBOutlet var iconViewConstraints: NSLayoutConstraint!
16 |
17 | @IBOutlet var iconView: UIImageView!
18 |
19 | var timeline: UTimeline!
20 |
21 | override func awakeFromNib() {
22 | iconView.image = iconView.image?.withRenderingMode(.alwaysTemplate)
23 |
24 | var color: UIColor?
25 | if isUserInteractionEnabled {
26 | color = UIColor(red: 77.0 / 255.0, green: 209.0 / 255.0, blue: 0.0, alpha: 0.75)
27 | } else {
28 | color = UIColor(red: 0.0, green: 148.0 / 255.0, blue: 209.0 / 255.0, alpha: 0.75)
29 | }
30 | iconView.tintColor = color
31 |
32 | setup()
33 | }
34 |
35 |
36 | func animateIn() {
37 | _ = timeline.start()
38 | }
39 |
40 | func setup() {
41 | timeline = UTimeline(id: "timeline \(arc4random())")
42 |
43 | let from = CGFloat(120)
44 | var to = titleLabelConstraints.constant
45 | let duration = 0.4
46 |
47 | let labelTween = NumericTween(id: "titleLabelTween")
48 | .from(from, to: to)
49 | .update { [unowned self] value in
50 | self.titleLabelConstraints.constant = value
51 | }
52 | .duration(duration)
53 | .ease(.cubic(.out))
54 |
55 | to = titleLabelConstraints.constant
56 | let dotTween = NumericTween(id: "iconViewTween")
57 | .from(from, to: to)
58 | .update { [unowned self] value in
59 | self.iconViewConstraints.constant = value
60 | }
61 | .duration(duration)
62 | .ease(.cubic(.out))
63 |
64 | timeline.insert(labelTween, at: 0)
65 | timeline.insert(dotTween, at: 0)
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/Examples/TweenApp/TweenApp/Views/TweenControlButton.swift:
--------------------------------------------------------------------------------
1 | //
2 | // TweenControlButton.swift
3 | // TweenApp
4 | //
5 | // Created by RF on 16/05/16.
6 | // Copyright © 2016 Robin Falko. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import Ubergang
11 |
12 | class TweenControlButton: UIButton {
13 | var timeline: UTimeline!
14 |
15 | var tintNormal: UIColor!
16 | var tintSelected: UIColor?
17 |
18 | override func awakeFromNib() {
19 | super.awakeFromNib()
20 |
21 | addTarget(self, action: #selector(touchDown), for: .touchDown)
22 | addTarget(self, action: #selector(touchUp), for: .touchDragExit)
23 | addTarget(self, action: #selector(touchUp), for: .touchUpInside)
24 |
25 |
26 | var image = self.image(for: UIControl.State())?.withRenderingMode(.alwaysTemplate)
27 | setImage(image, for: UIControl.State())
28 |
29 | image = self.image(for: .selected)?.withRenderingMode(.alwaysTemplate)
30 | setImage(image, for: .selected)
31 |
32 | tintColor = tintNormal
33 |
34 | setupTween()
35 | }
36 |
37 | override var isSelected: Bool {
38 | get {
39 | return super.isSelected
40 | }
41 | set {
42 | tintColor = !newValue ? tintNormal : tintSelected
43 | super.isSelected = newValue
44 | }
45 | }
46 |
47 |
48 | func setupTween() {
49 | let tween = NumericTween(id: "alpha_\(arc4random())")
50 | .from(1.0, to: 0.5)
51 | .update { [unowned self] (value) in
52 | self.alpha = value
53 | }
54 | .duration(0.2)
55 | .ease(.cubic(.out))
56 |
57 | let transform = CGAffineTransform(scaleX: 0.9, y: 0.9)
58 | let transformTween = TransformTween(id: "transform_\(arc4random())")
59 | .from(CGAffineTransform.identity, to: transform)
60 | .update { [unowned self] value in
61 | self.transform = value
62 | }
63 | .duration(0.2)
64 |
65 | _ = transformTween.ease(.cubic(.out))
66 |
67 | timeline = UTimeline(id: "timeline_\(arc4random())")
68 | _ = timeline.reference(.weak)
69 | timeline.insert(tween, at: 0)
70 | timeline.insert(transformTween, at: 0)
71 | }
72 |
73 | @objc func touchDown() {
74 | timeline.direction(.forward).start()
75 |
76 | tweenOutline()
77 | }
78 |
79 | @objc func touchUp() {
80 | timeline.direction(.reverse).start()
81 | }
82 |
83 | func tweenOutline() {
84 | let imageView = UIImageView(image: UIImage(named: "CircleOutline")!.withRenderingMode(.alwaysTemplate))
85 | imageView.tintColor = tintColor
86 | imageView.frame = frame
87 | superview!.addSubview(imageView)
88 |
89 | let transform = CGAffineTransform(scaleX: 1.3, y: 1.3)
90 | TransformTween(id: "outline_\(arc4random())")
91 | .from(CGAffineTransform(scaleX: 1.0, y: 1.0), to: transform)
92 | .update { (value, progress) in
93 | imageView.alpha = 1 - CGFloat(progress)
94 | imageView.transform = value
95 | }
96 | .duration(0.5)
97 | .ease(.cubic(.out))
98 | .complete {
99 | imageView.removeFromSuperview()
100 | }
101 | .start()
102 | }
103 | }
104 |
--------------------------------------------------------------------------------
/Examples/TweenApp/TweenApp/Views/TweenControlsView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // TweenControlsView.swift
3 | // TweenApp
4 | //
5 | // Created by RF on 10/04/16.
6 | // Copyright © 2016 Robin Falko. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import Ubergang
11 |
12 | class TweenControlsView: UIView {
13 | enum PlayState {
14 | case stopped
15 | case playing
16 | case pausing
17 | }
18 |
19 | class func instanceFromNib() -> TweenControlsView {
20 | return UINib(nibName: "TweenControls", bundle: nil).instantiate(withOwner: self, options: nil)[0] as! TweenControlsView
21 | }
22 | @IBOutlet var playPauseButton: UIButton!
23 |
24 | @IBOutlet var stopButton: UIButton!
25 |
26 | @IBOutlet var directionButton: UIButton!
27 |
28 | @IBOutlet var progressSlider: UISlider!
29 |
30 | var onPlay: (() -> Void)?
31 | var onStop: (() -> Void)?
32 | var onPause: (() -> Void)?
33 | var onResume: (() -> Void)?
34 | var onDirection: ((_ direction: TweenDirection) -> Void)?
35 | var onProgress: ((_ value: Double) -> Void)?
36 |
37 | var playState: PlayState = .stopped
38 |
39 | var currentDerection: TweenDirection = .forward
40 |
41 | override func awakeFromNib() {
42 | setup()
43 | }
44 |
45 | func setup() {
46 | playPauseButton.addTarget(self, action: #selector(TweenControlsView.playPauseResume), for: .touchUpInside)
47 | stopButton.addTarget(self, action: #selector(TweenControlsView.stop), for: .touchUpInside)
48 | directionButton.addTarget(self, action: #selector(TweenControlsView.toggleDirection), for: .touchUpInside)
49 |
50 | progressSlider.addTarget(self, action: #selector(TweenControlsView.sliderValueChanged(_:)), for: .valueChanged)
51 |
52 | progressSlider.setThumbImage(UIImage(named: "SliderThumb"), for: UIControl.State())
53 | progressSlider.setThumbImage(UIImage(named: "SliderThumb"), for: .highlighted)
54 |
55 | progress(0)
56 | }
57 |
58 | override func didMoveToSuperview() {
59 | guard let _ = superview else {
60 | return
61 | }
62 |
63 | translatesAutoresizingMaskIntoConstraints = false
64 | var constraints = [NSLayoutConstraint]()
65 |
66 | let views = ["v": self]
67 |
68 | let horizontalConstraints = NSLayoutConstraint.constraints(withVisualFormat: "H:|-0-[v]-0-|", options: [], metrics: nil, views: views)
69 | constraints.append(contentsOf: horizontalConstraints)
70 |
71 | let verticalConstraints = NSLayoutConstraint.constraints(withVisualFormat: "V:[v(64)]-16-|", options: [], metrics: nil, views: views)
72 | constraints.append(contentsOf: verticalConstraints)
73 |
74 | NSLayoutConstraint.activate(constraints)
75 | }
76 |
77 | @objc func playPauseResume() {
78 | switch playState {
79 | case .stopped:
80 | playState = .playing
81 | playPauseButton.isSelected = true
82 |
83 | onPlay?()
84 | break
85 | case .playing:
86 | playState = .pausing
87 | playPauseButton.isSelected = false
88 |
89 | onPause?()
90 | break
91 | case .pausing:
92 | playState = .playing
93 | playPauseButton.isSelected = true
94 |
95 | onResume?()
96 | break
97 | }
98 | }
99 |
100 | @objc func stop() {
101 | playState = .stopped
102 | playPauseButton.isSelected = false
103 |
104 | onStop?()
105 | }
106 |
107 | func pause() {
108 | onPause?()
109 | }
110 |
111 | func resume() {
112 | onResume?()
113 | }
114 |
115 | @objc func toggleDirection() {
116 | switch currentDerection {
117 | case .forward:
118 | currentDerection = .reverse
119 | directionButton.isSelected = true
120 | case .reverse:
121 | currentDerection = .forward
122 | directionButton.isSelected = false
123 | default: break
124 | }
125 |
126 | onDirection?(currentDerection)
127 | }
128 |
129 | @objc func sliderValueChanged(_ sender: UISlider?) {
130 | onProgress?(Double(sender!.value))
131 | }
132 |
133 | func progress(_ value: Double) {
134 | progressSlider.value = Float(value)
135 | }
136 | }
137 |
--------------------------------------------------------------------------------
/Examples/TweenApp/TweenApp/Views/TweenStatusView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // TweenStatusView.swift
3 | // TweenApp
4 | //
5 | // Created by Robin Frielingsdorf on 17/05/16.
6 | // Copyright © 2016 Robin Falko. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class TweenStatusView: UIView {
12 |
13 | @IBOutlet var titleLabel: UILabel!
14 | @IBOutlet var progressBar: UIProgressView!
15 | @IBOutlet var progressBarTotal: UIProgressView!
16 | @IBOutlet var repeatCountLabel: UILabel!
17 |
18 | var title: String = "Tween" {
19 | didSet {
20 | titleLabel.text = title
21 | }
22 | }
23 |
24 | var progress: Float = 0 {
25 | didSet {
26 | progressBar.progress = progress
27 | }
28 | }
29 |
30 | var progressTotal: Float = 0 {
31 | didSet {
32 | progressBarTotal.progress = progressTotal
33 | }
34 | }
35 |
36 | var repeatCount: Int = 0 {
37 | didSet {
38 | repeatCountLabel.text = "\(repeatCount)"
39 | }
40 | }
41 |
42 |
43 | init() {
44 | super.init(frame: CGRect.zero)
45 | setup()
46 | }
47 |
48 | required init?(coder aDecoder: NSCoder) {
49 | super.init(coder: aDecoder)
50 | setup()
51 | }
52 |
53 | fileprivate func setup() {
54 |
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/Framework/Ubergang.framework/Headers/Ubergang-Swift.h:
--------------------------------------------------------------------------------
1 | // Generated by Apple Swift version 2.2 (swiftlang-703.0.18.1 clang-703.0.29)
2 | #pragma clang diagnostic push
3 |
4 | #if defined(__has_include) && __has_include()
5 | # include
6 | #endif
7 |
8 | #pragma clang diagnostic ignored "-Wauto-import"
9 | #include
10 | #include
11 | #include
12 | #include
13 |
14 | #if !defined(SWIFT_TYPEDEFS)
15 | # define SWIFT_TYPEDEFS 1
16 | # if defined(__has_include) && __has_include()
17 | # include
18 | # elif !defined(__cplusplus) || __cplusplus < 201103L
19 | typedef uint_least16_t char16_t;
20 | typedef uint_least32_t char32_t;
21 | # endif
22 | typedef float swift_float2 __attribute__((__ext_vector_type__(2)));
23 | typedef float swift_float3 __attribute__((__ext_vector_type__(3)));
24 | typedef float swift_float4 __attribute__((__ext_vector_type__(4)));
25 | typedef double swift_double2 __attribute__((__ext_vector_type__(2)));
26 | typedef double swift_double3 __attribute__((__ext_vector_type__(3)));
27 | typedef double swift_double4 __attribute__((__ext_vector_type__(4)));
28 | typedef int swift_int2 __attribute__((__ext_vector_type__(2)));
29 | typedef int swift_int3 __attribute__((__ext_vector_type__(3)));
30 | typedef int swift_int4 __attribute__((__ext_vector_type__(4)));
31 | #endif
32 |
33 | #if !defined(SWIFT_PASTE)
34 | # define SWIFT_PASTE_HELPER(x, y) x##y
35 | # define SWIFT_PASTE(x, y) SWIFT_PASTE_HELPER(x, y)
36 | #endif
37 | #if !defined(SWIFT_METATYPE)
38 | # define SWIFT_METATYPE(X) Class
39 | #endif
40 |
41 | #if defined(__has_attribute) && __has_attribute(objc_runtime_name)
42 | # define SWIFT_RUNTIME_NAME(X) __attribute__((objc_runtime_name(X)))
43 | #else
44 | # define SWIFT_RUNTIME_NAME(X)
45 | #endif
46 | #if defined(__has_attribute) && __has_attribute(swift_name)
47 | # define SWIFT_COMPILE_NAME(X) __attribute__((swift_name(X)))
48 | #else
49 | # define SWIFT_COMPILE_NAME(X)
50 | #endif
51 | #if !defined(SWIFT_CLASS_EXTRA)
52 | # define SWIFT_CLASS_EXTRA
53 | #endif
54 | #if !defined(SWIFT_PROTOCOL_EXTRA)
55 | # define SWIFT_PROTOCOL_EXTRA
56 | #endif
57 | #if !defined(SWIFT_ENUM_EXTRA)
58 | # define SWIFT_ENUM_EXTRA
59 | #endif
60 | #if !defined(SWIFT_CLASS)
61 | # if defined(__has_attribute) && __has_attribute(objc_subclassing_restricted)
62 | # define SWIFT_CLASS(SWIFT_NAME) SWIFT_RUNTIME_NAME(SWIFT_NAME) __attribute__((objc_subclassing_restricted)) SWIFT_CLASS_EXTRA
63 | # define SWIFT_CLASS_NAMED(SWIFT_NAME) __attribute__((objc_subclassing_restricted)) SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_CLASS_EXTRA
64 | # else
65 | # define SWIFT_CLASS(SWIFT_NAME) SWIFT_RUNTIME_NAME(SWIFT_NAME) SWIFT_CLASS_EXTRA
66 | # define SWIFT_CLASS_NAMED(SWIFT_NAME) SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_CLASS_EXTRA
67 | # endif
68 | #endif
69 |
70 | #if !defined(SWIFT_PROTOCOL)
71 | # define SWIFT_PROTOCOL(SWIFT_NAME) SWIFT_RUNTIME_NAME(SWIFT_NAME) SWIFT_PROTOCOL_EXTRA
72 | # define SWIFT_PROTOCOL_NAMED(SWIFT_NAME) SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_PROTOCOL_EXTRA
73 | #endif
74 |
75 | #if !defined(SWIFT_EXTENSION)
76 | # define SWIFT_EXTENSION(M) SWIFT_PASTE(M##_Swift_, __LINE__)
77 | #endif
78 |
79 | #if !defined(OBJC_DESIGNATED_INITIALIZER)
80 | # if defined(__has_attribute) && __has_attribute(objc_designated_initializer)
81 | # define OBJC_DESIGNATED_INITIALIZER __attribute__((objc_designated_initializer))
82 | # else
83 | # define OBJC_DESIGNATED_INITIALIZER
84 | # endif
85 | #endif
86 | #if !defined(SWIFT_ENUM)
87 | # define SWIFT_ENUM(_type, _name) enum _name : _type _name; enum SWIFT_ENUM_EXTRA _name : _type
88 | # if defined(__has_feature) && __has_feature(generalized_swift_name)
89 | # define SWIFT_ENUM_NAMED(_type, _name, SWIFT_NAME) enum _name : _type _name SWIFT_COMPILE_NAME(SWIFT_NAME); enum SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_ENUM_EXTRA _name : _type
90 | # else
91 | # define SWIFT_ENUM_NAMED(_type, _name, SWIFT_NAME) SWIFT_ENUM(_type, _name)
92 | # endif
93 | #endif
94 | #if defined(__has_feature) && __has_feature(modules)
95 | @import ObjectiveC;
96 | #endif
97 |
98 | #pragma clang diagnostic ignored "-Wproperty-attribute-mismatch"
99 | #pragma clang diagnostic ignored "-Wduplicate-method-arg"
100 |
101 | SWIFT_CLASS("_TtC8Ubergang6Engine")
102 | @interface Engine : NSObject
103 | + (Engine * _Nonnull)instance;
104 | + (void)setInstance:(Engine * _Nonnull)value;
105 | - (nonnull instancetype)init OBJC_DESIGNATED_INITIALIZER;
106 | @end
107 |
108 | #pragma clang diagnostic pop
109 |
--------------------------------------------------------------------------------
/Framework/Ubergang.framework/Info.plist:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RobinFalko/Ubergang/4f61d0677e96dcd724f06f5765816bbfc2732ece/Framework/Ubergang.framework/Info.plist
--------------------------------------------------------------------------------
/Framework/Ubergang.framework/Modules/Ubergang.swiftmodule/x86_64.swiftdoc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RobinFalko/Ubergang/4f61d0677e96dcd724f06f5765816bbfc2732ece/Framework/Ubergang.framework/Modules/Ubergang.swiftmodule/x86_64.swiftdoc
--------------------------------------------------------------------------------
/Framework/Ubergang.framework/Modules/Ubergang.swiftmodule/x86_64.swiftmodule:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RobinFalko/Ubergang/4f61d0677e96dcd724f06f5765816bbfc2732ece/Framework/Ubergang.framework/Modules/Ubergang.swiftmodule/x86_64.swiftmodule
--------------------------------------------------------------------------------
/Framework/Ubergang.framework/Modules/module.modulemap:
--------------------------------------------------------------------------------
1 | framework module Ubergang {
2 | header "Ubergang-Swift.h"
3 | }
4 |
--------------------------------------------------------------------------------
/Framework/Ubergang.framework/Ubergang:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RobinFalko/Ubergang/4f61d0677e96dcd724f06f5765816bbfc2732ece/Framework/Ubergang.framework/Ubergang
--------------------------------------------------------------------------------
/Movies/exampleConstraints.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RobinFalko/Ubergang/4f61d0677e96dcd724f06f5765816bbfc2732ece/Movies/exampleConstraints.gif
--------------------------------------------------------------------------------
/Movies/exampleConstraints.mov:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RobinFalko/Ubergang/4f61d0677e96dcd724f06f5765816bbfc2732ece/Movies/exampleConstraints.mov
--------------------------------------------------------------------------------
/Movies/exampleDynamic.mov:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RobinFalko/Ubergang/4f61d0677e96dcd724f06f5765816bbfc2732ece/Movies/exampleDynamic.mov
--------------------------------------------------------------------------------
/Movies/examplePath.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RobinFalko/Ubergang/4f61d0677e96dcd724f06f5765816bbfc2732ece/Movies/examplePath.gif
--------------------------------------------------------------------------------
/Movies/examplePath.mov:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RobinFalko/Ubergang/4f61d0677e96dcd724f06f5765816bbfc2732ece/Movies/examplePath.mov
--------------------------------------------------------------------------------
/Movies/exampleTimeline.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RobinFalko/Ubergang/4f61d0677e96dcd724f06f5765816bbfc2732ece/Movies/exampleTimeline.gif
--------------------------------------------------------------------------------
/Movies/exampleTimeline.mov:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RobinFalko/Ubergang/4f61d0677e96dcd724f06f5765816bbfc2732ece/Movies/exampleTimeline.mov
--------------------------------------------------------------------------------
/Ubergang-Bridging-Header.h:
--------------------------------------------------------------------------------
1 | //
2 | // Ubergang-Bridging-Header.h
3 | // Ubergang
4 | //
5 | // Created by RF on 23/05/16.
6 | // Copyright © 2016 Robin Falko. All rights reserved.
7 | //
8 |
9 | #ifndef Ubergang_Bridging_Header_h
10 | #define Ubergang_Bridging_Header_h
11 |
12 | #import "UIBezierPath+Interpolation.h"
13 |
14 | #endif /* Ubergang_Bridging_Header_h */
15 |
--------------------------------------------------------------------------------
/Ubergang.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RobinFalko/Ubergang/4f61d0677e96dcd724f06f5765816bbfc2732ece/Ubergang.png
--------------------------------------------------------------------------------
/Ubergang.podspec:
--------------------------------------------------------------------------------
1 | Pod::Spec.new do |s|
2 | s.name = 'Ubergang'
3 | s.version = '1.2.0'
4 | s.summary = 'A tweening engine written in Swift.'
5 | s.homepage = 'https://github.com/RobinFalko/Ubergang'
6 | s.license = { type: 'Apache', file: 'LICENSE' }
7 | s.authors = { 'Robin Frielingsdorf' => 'mail@robinfalko.com' }
8 |
9 | s.source = { :git => 'https://github.com/RobinFalko/Ubergang.git', :tag => s.version.to_s }
10 | s.source_files = 'Ubergang/**/*.{h,m,swift}'
11 | s.module_name = 'Ubergang'
12 |
13 | s.swift_version = '5.0'
14 | s.platform = :ios, '8.0'
15 | s.ios.deployment_target = '8.0'
16 | end
17 |
--------------------------------------------------------------------------------
/Ubergang.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Ubergang.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Ubergang.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Ubergang.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Ubergang.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/Ubergang/Core/Engine.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Engine.swift
3 | // Ubergang
4 | //
5 | // Created by Robin Frielingsdorf on 09/01/16.
6 | // Copyright © 2016 Robin Falko. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import UIKit
11 |
12 | open class Engine: NSObject {
13 | public typealias Closure = () -> Void
14 |
15 | fileprivate var displayLink: CADisplayLink?
16 |
17 | var closures = [String : Closure]()
18 |
19 | var mapTable = NSMapTable(keyOptions: NSPointerFunctions.Options.strongMemory, valueOptions: NSPointerFunctions.Options.weakMemory)
20 |
21 | public static var instance: Engine = {
22 | let engine = Engine()
23 | engine.start()
24 | return engine
25 | }()
26 |
27 | func start() {
28 | if displayLink == nil {
29 | displayLink = CADisplayLink(target: self, selector: #selector(Engine.update))
30 | displayLink!.add(to: .current, forMode: .common)
31 | }
32 | }
33 |
34 | func stop() {
35 | displayLink?.remove(from: .current, forMode: .common)
36 | displayLink = nil
37 | }
38 |
39 | @objc func update() {
40 | let enumerator = mapTable.objectEnumerator()
41 | while let any: AnyObject = enumerator?.nextObject() as AnyObject? {
42 | if let loopable = any as? WeaklyLoopable {
43 | loopable.loopWeakly()
44 | }
45 | }
46 |
47 | for (_, closure) in closures {
48 | closure()
49 | }
50 | }
51 |
52 |
53 | func register(_ closure: @escaping Closure, forKey key: String) {
54 | closures[key] = closure
55 |
56 | start()
57 | }
58 |
59 |
60 | func register(_ loopable: WeaklyLoopable, forKey key: String) {
61 | mapTable.setObject(loopable as AnyObject?, forKey: key as AnyObject?)
62 |
63 | start()
64 | }
65 |
66 |
67 | func unregister(_ key: String) {
68 | mapTable.removeObject(forKey: key as AnyObject?)
69 |
70 | closures.removeValue(forKey: key)
71 |
72 | if mapTable.count == 0 && closures.isEmpty {
73 | stop()
74 | }
75 | }
76 |
77 |
78 | func contains(_ key: String) -> Bool {
79 | return mapTable.object(forKey: key as AnyObject?) != nil || closures[key] != nil
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/Ubergang/Core/Timer.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Timer.swift
3 | // Ubergang
4 | //
5 | // Created by Robin Frielingsdorf on 07/01/16.
6 | // Copyright © 2016 Robin Falko. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | open class Timer {
12 | public static let instance = Timer()
13 |
14 | fileprivate let id = "\(#file)_update"
15 |
16 | public static var delta:TimeInterval = TimeInterval(0)
17 | public static var time:TimeInterval = TimeInterval(0)
18 | fileprivate var lastUpdateTime:TimeInterval = TimeInterval(0)
19 |
20 | fileprivate init() {}
21 |
22 | func start() {
23 | self.lastUpdateTime = Date().timeIntervalSince1970
24 |
25 | Engine.instance.register(update, forKey: id)
26 | }
27 |
28 |
29 | func stop() {
30 | Engine.instance.unregister(id)
31 | }
32 |
33 |
34 | func update() {
35 | tick(Date().timeIntervalSince1970)
36 | }
37 |
38 |
39 | func tick(_ currentTime: TimeInterval) {
40 | if lastUpdateTime == 0.0 {
41 | Timer.delta = 0
42 | } else {
43 | Timer.delta = currentTime - self.lastUpdateTime
44 | }
45 |
46 | self.lastUpdateTime = Date().timeIntervalSince1970
47 |
48 | Timer.time += Timer.delta
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/Ubergang/Core/UTweenSetup.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UTweenSetup.swift
3 | // Ubergang
4 | //
5 | // Created by RF on 11/07/16.
6 | // Copyright © 2016 Robin Falko. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | open class UTweenSetup {
12 | public static let instance = UTweenSetup()
13 |
14 | fileprivate var isLoggingEnabled = false
15 |
16 | internal lazy var logger: UTweenLoggable? = {
17 | guard UTweenSetup.instance.isLoggingEnabled else { return nil }
18 | return UTweenLogger()
19 | }()
20 |
21 | fileprivate init() {}
22 |
23 | open func enableLogging(_ enabled: Bool) {
24 | isLoggingEnabled = enabled
25 | }
26 |
27 | open func enableLogging(_ enabled: Bool, withLogger logger: UTweenLoggable) {
28 | enableLogging(enabled)
29 | self.logger = logger
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/Ubergang/Data/TweenDirection.swift:
--------------------------------------------------------------------------------
1 | //
2 | // TweenDirection.swift
3 | // Ubergang
4 | //
5 | // Created by Robin Frielingsdorf on 10/04/16.
6 | // Copyright © 2016 Robin Falko. All rights reserved.
7 | //
8 |
9 | // Picture: Timeline containing 3 tweens
10 | /*
11 | forward -->
12 | t0: |-----------------------|
13 | t1: |----------------------|
14 | t2: |--------|
15 | */
16 |
17 | /*
18 | <-- reverse
19 | t0: |-----------------------|
20 | t1: |----------------------|
21 | t2: |--------|
22 | */
23 |
24 | /*
25 | <-- backward
26 | t0: |-----------------------|
27 | t1: |----------------------|
28 | t2: |--------|
29 | */
30 |
31 | public enum TweenDirection {
32 | case forward //play the tween from 0 to 1
33 | case reverse //play the tween from 1 to 0 without adjustments
34 | case backward //play the tween from 1 to 0, inverse easings, and tween start times
35 | }
36 |
37 |
38 |
--------------------------------------------------------------------------------
/Ubergang/Data/TweenMemoryReference.swift:
--------------------------------------------------------------------------------
1 | //
2 | // TweenMemoryReference.swift
3 | // Ubergang
4 | //
5 | // Created by Robin Frielingsdorf on 14/02/16.
6 | // Copyright © 2016 Robin Falko. All rights reserved.
7 | //
8 |
9 | public enum TweenMemoryReference {
10 | case weak, strong
11 | }
12 |
--------------------------------------------------------------------------------
/Ubergang/Data/TweenOptions.swift:
--------------------------------------------------------------------------------
1 | //
2 | // TweenOptions.swift
3 | // Ubergang
4 | //
5 | // Created by Robin Frielingsdorf on 20/01/16.
6 | // Copyright © 2016 Robin Falko. All rights reserved.
7 | //
8 |
9 | public func ==(a: TweenOptions, b: TweenOptions) -> Bool {
10 | switch (a, b) {
11 | case (.yoyo, .yoyo): return true
12 | case (.repeat(let l), .repeat(let r)) where l == r: return true
13 | default: return false
14 | }
15 | }
16 |
17 | internal extension Sequence where Iterator.Element == TweenOptions {
18 | func repeatCount() -> Int {
19 | var repeatCount = 0
20 | self.forEach {
21 | if case .repeat(let count) = $0 {
22 | repeatCount = count
23 | }
24 | }
25 |
26 | return repeatCount
27 | }
28 |
29 | func containsRepeat() -> Bool {
30 | return repeatCount() > 0
31 | }
32 |
33 | func containsYoyo() -> Bool {
34 | return self.contains(.yoyo)
35 | }
36 | }
37 |
38 | public enum TweenOptions: Equatable {
39 | case yoyo
40 | case `repeat`(Int)
41 | }
42 |
--------------------------------------------------------------------------------
/Ubergang/Ease/Back.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Back.swift
3 | // Ubergang
4 | //
5 | // Created by Robin Frielingsdorf on 07/01/16.
6 | // Copyright © 2016 Robin Falko. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | open class Back: Easing, CurveEasing {
12 | /**
13 | Back ease in.
14 |
15 | - Parameter t: The value to be mapped going from 0 to `d`
16 | - Parameter b: The mapped start value
17 | - Parameter c: The mapped end value
18 | - Parameter d: The end value
19 | - Returns: The mapped result
20 | */
21 | open class func easeIn(t: Double, b: Double, c: Double, d: Double) -> Double {
22 | var t = t
23 | let s = 1.70158
24 | t/=d
25 | let postFix = t
26 | return c*(postFix)*t*((s+1)*t - s) + b
27 | }
28 |
29 | /**
30 | Back ease out.
31 |
32 | - Parameter t: The value to be mapped going from 0 to `d`
33 | - Parameter b: The mapped start value
34 | - Parameter c: The mapped end value
35 | - Parameter d: The end value
36 | - Returns: The mapped result
37 | */
38 | open class func easeOut(t: Double, b: Double, c: Double, d: Double) -> Double {
39 | var t = t
40 | let s = 1.70158
41 | t=t/d-1
42 | let f = (s+1)*t + s
43 | return c*(t*t*f + 1) + b
44 | }
45 |
46 | /**
47 | Back ease in out.
48 |
49 | - Parameter t: The value to be mapped going from 0 to `d`
50 | - Parameter b: The mapped start value
51 | - Parameter c: The mapped end value
52 | - Parameter d: The end value
53 | - Returns: The mapped result
54 | */
55 | open class func easeInOut(t: Double, b: Double, c: Double, d: Double) -> Double {
56 | var t = t
57 | var s = 1.70158
58 | t/=d/2
59 | if (t < 1) { s*=(1.525); return c/2*(t*t*(((s)+1)*t - s)) + b }
60 | t-=2
61 | let postFix = t
62 | s*=(1.525)
63 | let f = (s+1)*t + s
64 | return c/2*(postFix*t*f + 2) + b
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/Ubergang/Ease/Bounce.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Bounce.swift
3 | // Ubergang
4 | //
5 | // Created by Robin Frielingsdorf on 07/01/16.
6 | // Copyright © 2016 Robin Falko. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | open class Bounce: Easing, CurveEasing {
12 |
13 | /**
14 | Bounce ease in.
15 |
16 | - Parameter t: The value to be mapped going from 0 to `d`
17 | - Parameter b: The mapped start value
18 | - Parameter c: The mapped end value
19 | - Parameter d: The end value
20 | - Returns: The mapped result
21 | */
22 | open class func easeIn(t: Double, b: Double, c: Double, d: Double) -> Double {
23 | return c - easeOut (t: d-t, b: 0, c: c, d: d) + b
24 | }
25 |
26 | /**
27 | Bounce ease out.
28 |
29 | - Parameter t: The value to be mapped going from 0 to `d`
30 | - Parameter b: The mapped start value
31 | - Parameter c: The mapped end value
32 | - Parameter d: The end value
33 | - Returns: The mapped result
34 | */
35 | open class func easeOut(t: Double, b: Double, c: Double, d: Double) -> Double {
36 | var t = t
37 | t/=d
38 | if t < (1/2.75) {
39 | return c*(7.5625*t*t) + b
40 | } else if (t < (2/2.75)) {
41 | t-=(1.5/2.75)
42 | let postFix = t
43 | return c*(7.5625*(postFix)*t + 0.75) + b
44 | } else if (t < (2.5/2.75)) {
45 | t-=(2.25/2.75)
46 | let postFix = t
47 | return c*(7.5625*(postFix)*t + 0.9375) + b
48 | } else {
49 | t-=(2.625/2.75)
50 | let postFix = t
51 | return c*(7.5625*(postFix)*t + 0.984375) + b
52 | }
53 | }
54 |
55 | /**
56 | Bounce ease in out.
57 |
58 | - Parameter t: The value to be mapped going from 0 to `d`
59 | - Parameter b: The mapped start value
60 | - Parameter c: The mapped end value
61 | - Parameter d: The end value
62 | - Returns: The mapped result
63 | */
64 | open class func easeInOut(t: Double, b: Double, c: Double, d: Double) -> Double {
65 | if (t < d/2) { return easeIn (t: t*2, b: 0, c: c, d: d) * 0.5 + b }
66 | else { return easeOut (t: t*2-d, b: 0, c: c, d: d) * 0.5 + c*0.5 + b }
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/Ubergang/Ease/Circ.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Circ.swift
3 | // Ubergang
4 | //
5 | // Created by Robin Frielingsdorf on 07/01/16.
6 | // Copyright © 2016 Robin Falko. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | open class Circ: Easing, CurveEasing {
12 |
13 | /**
14 | Circ ease in.
15 |
16 | - Parameter t: The value to be mapped going from 0 to `d`
17 | - Parameter b: The mapped start value
18 | - Parameter c: The mapped end value
19 | - Parameter d: The end value
20 | - Returns: The mapped result
21 | */
22 | open class func easeIn(t: Double, b: Double, c: Double, d: Double) -> Double {
23 | var t = t
24 | t/=d
25 | return -c * (sqrt(1 - (t)*t) - 1) + b
26 | }
27 |
28 | /**
29 | Circ ease out.
30 |
31 | - Parameter t: The value to be mapped going from 0 to `d`
32 | - Parameter b: The mapped start value
33 | - Parameter c: The mapped end value
34 | - Parameter d: The end value
35 | - Returns: The mapped result
36 | */
37 | open class func easeOut(t: Double, b: Double, c: Double, d: Double) -> Double {
38 | var t = t
39 | t=t/d-1
40 | return c * sqrt(1 - (t)*t) + b
41 | }
42 |
43 | /**
44 | Circ ease in out.
45 |
46 | - Parameter t: The value to be mapped going from 0 to `d`
47 | - Parameter b: The mapped start value
48 | - Parameter c: The mapped end value
49 | - Parameter d: The end value
50 | - Returns: The mapped result
51 | */
52 | open class func easeInOut(t: Double, b: Double, c: Double, d: Double) -> Double {
53 | var t = t
54 | t/=d/2
55 | if ((t) < 1) { return -c/2 * (sqrt(1 - t*t) - 1) + b }
56 | t-=2
57 | return c/2 * (sqrt(1 - t*(t)) + 1) + b
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/Ubergang/Ease/Cubic.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Cubic.swift
3 | // Ubergang
4 | //
5 | // Created by Robin Frielingsdorf on 07/01/16.
6 | // Copyright © 2016 Robin Falko. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | open class Cubic: Easing, CurveEasing {
12 |
13 | /**
14 | Cubic ease in.
15 |
16 | - Parameter t: The value to be mapped going from 0 to `d`
17 | - Parameter b: The mapped start value
18 | - Parameter c: The mapped end value
19 | - Parameter d: The end value
20 | - Returns: The mapped result
21 | */
22 | open class func easeIn(t: Double, b: Double, c: Double, d: Double) -> Double {
23 | var t = t
24 | t = t/d
25 | return c*t*t*t + b
26 | }
27 |
28 | /**
29 | Cubic ease out.
30 |
31 | - Parameter t: The value to be mapped going from 0 to `d`
32 | - Parameter b: The mapped start value
33 | - Parameter c: The mapped end value
34 | - Parameter d: The end value
35 | - Returns: The mapped result
36 | */
37 | open class func easeOut(t: Double, b: Double, c: Double, d: Double) -> Double {
38 | var t = t
39 | t = t/d-1
40 | return c*(t*t*t + 1) + b
41 | }
42 |
43 | /**
44 | Cubic ease in out.
45 |
46 | - Parameter t: The value to be mapped going from 0 to `d`
47 | - Parameter b: The mapped start value
48 | - Parameter c: The mapped end value
49 | - Parameter d: The end value
50 | - Returns: The mapped result
51 | */
52 | open class func easeInOut(t: Double, b: Double, c: Double, d: Double) -> Double {
53 | var t = t
54 | t = t/(d/2)
55 | if t < 1 {
56 | return c/2*t*t*t + b
57 | }
58 |
59 | t = t-2
60 | return c/2*(t*t*t + 2) + b;
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/Ubergang/Ease/Ease.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Ease.swift
3 | // Ubergang
4 | //
5 | // Created by Robin Frielingsdorf on 14/01/16.
6 | // Copyright © 2016 Robin Falko. All rights reserved.
7 | //
8 |
9 | public enum Ease {
10 | case linear
11 | case back(_ type: EaseType)
12 | case bounce(_ type: EaseType)
13 | case circ(_ type: EaseType)
14 | case cubic(_ type: EaseType)
15 | case elastic(_ type: EaseType)
16 | case expo(_ type: EaseType)
17 | case quad(_ type: EaseType)
18 | case quart(_ type: EaseType)
19 | case quint(_ type: EaseType)
20 | case sine(_ type: EaseType)
21 |
22 | var function: (_ t: Double, _ b: Double, _ c: Double, _ d: Double) -> Double {
23 | switch self {
24 | case .linear: return Linear.ease
25 | case let .back(type): return type.function(for: Back.self)
26 | case let .bounce(type): return type.function(for: Bounce.self)
27 | case let .circ(type): return type.function(for: Circ.self)
28 | case let .cubic(type): return type.function(for: Cubic.self)
29 | case let .elastic(type): return type.function(for: Elastic.self)
30 | case let .expo(type): return type.function(for: Expo.self)
31 | case let .quad(type): return type.function(for: Quad.self)
32 | case let .quart(type): return type.function(for: Quart.self)
33 | case let .quint(type): return type.function(for: Quint.self)
34 | case let .sine(type): return type.function(for: Sine.self)
35 | }
36 | }
37 |
38 | var opposite: Ease {
39 | switch self {
40 | case .linear: return self
41 | case let .back(type): return .back(type.opposite())
42 | case let .bounce(type): return .bounce(type.opposite())
43 | case let .circ(type): return .circ(type.opposite())
44 | case let .cubic(type): return .cubic(type.opposite())
45 | case let .elastic(type): return .elastic(type.opposite())
46 | case let .expo(type): return .expo(type.opposite())
47 | case let .quad(type): return .quad(type.opposite())
48 | case let .quart(type): return .quart(type.opposite())
49 | case let .quint(type): return .quint(type.opposite())
50 | case let .sine(type): return .sine(type.opposite())
51 | }
52 | }
53 | }
54 |
55 | public enum EaseType {
56 | case `in`, out, inOut
57 |
58 | internal func function(for easing: CurveEasing.Type) -> (_ t: Double, _ b: Double, _ c: Double, _ d: Double) -> Double {
59 | switch self {
60 | case .in: return easing.easeIn
61 | case .out: return easing.easeOut
62 | case .inOut: return easing.easeInOut
63 | }
64 | }
65 |
66 | internal func opposite() -> EaseType {
67 | switch self {
68 | case .in: return .out
69 | case .out: return .in
70 | case .inOut: return self
71 | }
72 | }
73 | }
74 |
75 | public protocol CurveEasing {
76 | static func easeIn(t: Double, b: Double, c: Double, d: Double) -> Double
77 | static func easeOut(t: Double, b: Double, c: Double, d: Double) -> Double
78 | static func easeInOut(t: Double, b: Double, c: Double, d: Double) -> Double
79 | }
80 |
81 | open class Easing {}
82 |
--------------------------------------------------------------------------------
/Ubergang/Ease/Elastic.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Elastic.swift
3 | // Ubergang
4 | //
5 | // Created by Robin Frielingsdorf on 10/01/16.
6 | // Copyright © 2016 Robin Falko. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | open class Elastic: Easing, CurveEasing {
12 |
13 | /**
14 | Elastic ease in.
15 |
16 | - Parameter t: The value to be mapped going from 0 to `d`
17 | - Parameter b: The mapped start value
18 | - Parameter c: The mapped end value
19 | - Parameter d: The end value
20 | - Returns: The mapped result
21 | */
22 | open class func easeIn(t: Double, b: Double, c: Double, d: Double) -> Double {
23 | var t = t
24 | if t == 0 {
25 | return b
26 | }
27 |
28 | t = t / d
29 | if t == 1 {
30 | return b+c
31 | }
32 |
33 | let p = d * 0.3
34 | let a = c
35 | let s = p / 4
36 | t = t - 1
37 |
38 | let postFix = a * pow(2.0, 10.0 * t) // this is a fix, again, with post-increment operators
39 |
40 | return -(postFix * sin((t*d-s) * (2 * .pi)/p )) + b
41 | }
42 |
43 | /**
44 | Elastic ease out.
45 |
46 | - Parameter t: The value to be mapped going from 0 to `d`
47 | - Parameter b: The mapped start value
48 | - Parameter c: The mapped end value
49 | - Parameter d: The end value
50 | - Returns: The mapped result
51 | */
52 | open class func easeOut(t: Double, b: Double, c: Double, d: Double) -> Double {
53 | var t = t
54 | if t == 0 {
55 | return b
56 | }
57 |
58 | t = t / d
59 | if t == 1 {
60 | return b+c
61 | }
62 |
63 | let p = d * 0.3
64 | let a = c
65 | let s = p / 4
66 |
67 | return (a * pow(2, -10 * t) * sin( (t*d-s) * (2 * .pi)/p ) + c + b)
68 | }
69 |
70 | /**
71 | Elastic ease in out.
72 |
73 | - Parameter t: The value to be mapped going from 0 to `d`
74 | - Parameter b: The mapped start value
75 | - Parameter c: The mapped end value
76 | - Parameter d: The end value
77 | - Returns: The mapped result
78 | */
79 | open class func easeInOut(t: Double, b: Double, c: Double, d: Double) -> Double {
80 | var t = t
81 | if t == 0 {
82 | return b
83 | }
84 |
85 | t = t / (d / 2)
86 | if t == 2 {
87 | return b+c
88 | }
89 |
90 | let p = d * (0.3*1.5)
91 | let a = c
92 | let s = p / 4
93 |
94 | t = t - 1
95 |
96 | if (t < 1) {
97 | let postFix = a * pow(2.0, 10.0 * t) // postIncrement is evil
98 | return -0.5 * (postFix * sin((t*d-s) * (2 * .pi)/p)) + b
99 | }
100 |
101 | let postFix = a * pow(2.0, -10.0 * t) // postIncrement is evil
102 | return postFix * sin((t*d-s) * (2 * .pi) / p) * 0.5 + c + b
103 | }
104 | }
105 |
--------------------------------------------------------------------------------
/Ubergang/Ease/Expo.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Expo.swift
3 | // Ubergang
4 | //
5 | // Created by Robin Frielingsdorf on 07/01/16.
6 | // Copyright © 2016 Robin Falko. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | open class Expo: Easing, CurveEasing {
12 |
13 | /**
14 | Expo ease in.
15 |
16 | - Parameter t: The value to be mapped going from 0 to `d`
17 | - Parameter b: The mapped start value
18 | - Parameter c: The mapped end value
19 | - Parameter d: The end value
20 | - Returns: The mapped result
21 | */
22 | open class func easeIn(t: Double, b: Double, c: Double, d: Double) -> Double {
23 | return (t==0) ? b : c * pow(2, 10 * (t/d - 1)) + b
24 | }
25 |
26 | /**
27 | Circ ease out.
28 |
29 | - Parameter t: The value to be mapped going from 0 to `d`
30 | - Parameter b: The mapped start value
31 | - Parameter c: The mapped end value
32 | - Parameter d: The end value
33 | - Returns: The mapped result
34 | */
35 | open class func easeOut(t: Double, b: Double, c: Double, d: Double) -> Double {
36 | return (t==d) ? b+c : c * (-pow(2, -10 * t/d) + 1) + b
37 | }
38 |
39 | /**
40 | Circ ease in out.
41 |
42 | - Parameter t: The value to be mapped going from 0 to `d`
43 | - Parameter b: The mapped start value
44 | - Parameter c: The mapped end value
45 | - Parameter d: The end value
46 | - Returns: The mapped result
47 | */
48 | open class func easeInOut(t: Double, b: Double, c: Double, d: Double) -> Double {
49 | var t = t
50 | if (t==0) { return b }
51 | if (t==d) { return b+c }
52 | t/=d/2
53 | if ((t) < 1) { return c/2 * pow(2, 10 * (t - 1)) + b }
54 | t-=1
55 | return c/2 * (-pow(2, -10 * t) + 2) + b
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/Ubergang/Ease/Linear.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Linear.swift
3 | // Ubergang
4 | //
5 | // Created by Robin Frielingsdorf on 07/01/16.
6 | // Copyright © 2016 Robin Falko. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | open class Linear: Easing {
12 |
13 | /**
14 | Linear ease.
15 |
16 | - Parameter t: The value to be mapped going from 0 to `d`
17 | - Parameter b: The mapped start value
18 | - Parameter c: The mapped end value
19 | - Parameter d: The end value
20 | - Returns: The mapped result
21 | */
22 | open class func ease(t: Double, b: Double, c: Double, d: Double) -> Double {
23 | return c * t / d + b
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/Ubergang/Ease/Quad.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Quad.swift
3 | // Ubergang
4 | //
5 | // Created by Robin Frielingsdorf on 07/01/16.
6 | // Copyright © 2016 Robin Falko. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | open class Quad: Easing, CurveEasing {
12 |
13 | /**
14 | Quad ease in.
15 |
16 | - Parameter t: The value to be mapped going from 0 to `d`
17 | - Parameter b: The mapped start value
18 | - Parameter c: The mapped end value
19 | - Parameter d: The end value
20 | - Returns: The mapped result
21 | */
22 | open class func easeIn(t: Double, b: Double, c: Double, d: Double) -> Double {
23 | var t = t
24 | t/=d
25 | return c*(t)*t + b
26 | }
27 |
28 | /**
29 | Quad ease out.
30 |
31 | - Parameter t: The value to be mapped going from 0 to `d`
32 | - Parameter b: The mapped start value
33 | - Parameter c: The mapped end value
34 | - Parameter d: The end value
35 | - Returns: The mapped result
36 | */
37 | open class func easeOut(t: Double, b: Double, c: Double, d: Double) -> Double {
38 | var t = t
39 | t/=d
40 | return -c*(t)*(t-2) + b
41 | }
42 |
43 | /**
44 | Quad ease in out.
45 |
46 | - Parameter t: The value to be mapped going from 0 to `d`
47 | - Parameter b: The mapped start value
48 | - Parameter c: The mapped end value
49 | - Parameter d: The end value
50 | - Returns: The mapped result
51 | */
52 | open class func easeInOut(t: Double, b: Double, c: Double, d: Double) -> Double {
53 | var t = t
54 | t/=d/2
55 | if ((t) < 1) { return ((c/2)*(t*t)) + b }
56 | let t2 = t-1
57 | return -c/2 * (((t-2)*(t2)) - 1) + b
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/Ubergang/Ease/Quart.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Quart.swift
3 | // Ubergang
4 | //
5 | // Created by Robin Frielingsdorf on 07/01/16.
6 | // Copyright © 2016 Robin Falko. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | open class Quart: Easing, CurveEasing {
12 |
13 | /**
14 | Quart ease in.
15 |
16 | - Parameter t: The value to be mapped going from 0 to `d`
17 | - Parameter b: The mapped start value
18 | - Parameter c: The mapped end value
19 | - Parameter d: The end value
20 | - Returns: The mapped result
21 | */
22 | open class func easeIn(t: Double, b: Double, c: Double, d: Double) -> Double {
23 | var t = t
24 | t/=d
25 | return c*(t)*t*t*t + b
26 | }
27 |
28 | /**
29 | Quart ease out.
30 |
31 | - Parameter t: The value to be mapped going from 0 to `d`
32 | - Parameter b: The mapped start value
33 | - Parameter c: The mapped end value
34 | - Parameter d: The end value
35 | - Returns: The mapped result
36 | */
37 | open class func easeOut(t: Double, b: Double, c: Double, d: Double) -> Double {
38 | var t = t
39 | t=t/d-1
40 | return -c * ((t)*t*t*t - 1) + b
41 | }
42 |
43 | /**
44 | Quart ease in out.
45 |
46 | - Parameter t: The value to be mapped going from 0 to `d`
47 | - Parameter b: The mapped start value
48 | - Parameter c: The mapped end value
49 | - Parameter d: The end value
50 | - Returns: The mapped result
51 | */
52 | open class func easeInOut(t: Double, b: Double, c: Double, d: Double) -> Double {
53 | var t = t
54 | t/=d/2
55 | if ((t) < 1) { return c/2*t*t*t*t + b }
56 | t-=2
57 | return -c/2 * ((t)*t*t*t - 2) + b
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/Ubergang/Ease/Quint.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Quint.swift
3 | // Ubergang
4 | //
5 | // Created by Robin Frielingsdorf on 07/01/16.
6 | // Copyright © 2016 Robin Falko. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | open class Quint: Easing, CurveEasing {
12 |
13 | /**
14 | Quint ease in.
15 |
16 | - Parameter t: The value to be mapped going from 0 to `d`
17 | - Parameter b: The mapped start value
18 | - Parameter c: The mapped end value
19 | - Parameter d: The end value
20 | - Returns: The mapped result
21 | */
22 | open class func easeIn(t: Double, b: Double, c: Double, d: Double) -> Double {
23 | var t = t
24 | t/=d
25 | return c*(t)*t*t*t*t + b
26 | }
27 |
28 | /**
29 | Quint ease out.
30 |
31 | - Parameter t: The value to be mapped going from 0 to `d`
32 | - Parameter b: The mapped start value
33 | - Parameter c: The mapped end value
34 | - Parameter d: The end value
35 | - Returns: The mapped result
36 | */
37 | open class func easeOut(t: Double, b: Double, c: Double, d: Double) -> Double {
38 | var t = t
39 | t=t/d-1
40 | return c*((t)*t*t*t*t + 1) + b
41 | }
42 |
43 | /**
44 | Quint ease in out.
45 |
46 | - Parameter t: The value to be mapped going from 0 to `d`
47 | - Parameter b: The mapped start value
48 | - Parameter c: The mapped end value
49 | - Parameter d: The end value
50 | - Returns: The mapped result
51 | */
52 | open class func easeInOut(t: Double, b: Double, c: Double, d: Double) -> Double {
53 | var t = t
54 | t/=d/2
55 | if ((t) < 1) { return c/2*t*t*t*t*t + b }
56 | t-=2
57 | return c/2*((t)*t*t*t*t + 2) + b
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/Ubergang/Ease/Sine.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Sine.swift
3 | // Ubergang
4 | //
5 | // Created by Robin Frielingsdorf on 07/01/16.
6 | // Copyright © 2016 Robin Falko. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | open class Sine: Easing, CurveEasing {
12 |
13 | /**
14 | Sine ease in.
15 |
16 | - Parameter t: The value to be mapped going from 0 to `d`
17 | - Parameter b: The mapped start value
18 | - Parameter c: The mapped end value
19 | - Parameter d: The end value
20 | - Returns: The mapped result
21 | */
22 | open class func easeIn(t: Double, b: Double, c: Double, d: Double) -> Double {
23 | return -c * cos(t/d * (.pi/2)) + c + b
24 | }
25 |
26 | /**
27 | Sine ease out.
28 |
29 | - Parameter t: The value to be mapped going from 0 to `d`
30 | - Parameter b: The mapped start value
31 | - Parameter c: The mapped end value
32 | - Parameter d: The end value
33 | - Returns: The mapped result
34 | */
35 | open class func easeOut(t: Double, b: Double, c: Double, d: Double) -> Double {
36 | return c * sin(t/d * (.pi/2)) + b
37 | }
38 |
39 | /**
40 | Sine ease in out.
41 |
42 | - Parameter t: The value to be mapped going from 0 to `d`
43 | - Parameter b: The mapped start value
44 | - Parameter c: The mapped end value
45 | - Parameter d: The end value
46 | - Returns: The mapped result
47 | */
48 | open class func easeInOut(t: Double, b: Double, c: Double, d: Double) -> Double {
49 | return -c/2 * (cos(.pi*t/d) - 1) + b
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/Ubergang/Extension/CGPath.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CGPath.swift
3 | // Ubergang
4 | //
5 | // Created by Robin Frielingsdorf on 19/05/16.
6 | // Copyright © 2016 Robin Falko. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | extension CGPath {
12 | func forEach(_ body: @escaping @convention(block) (CGPathElement) -> Void) {
13 | typealias Body = @convention(block) (CGPathElement) -> Void
14 | func callback(_ info: UnsafeMutableRawPointer?, element: UnsafePointer) {
15 | let body = unsafeBitCast(info, to: Body.self)
16 | body(element.pointee)
17 | }
18 | let unsafeBody = unsafeBitCast(body, to: UnsafeMutableRawPointer.self)
19 | self.apply(info: unsafeBody, function: callback)
20 | }
21 |
22 | func getElements() -> [(type: CGPathElementType, points: [CGPoint])] {
23 | var result = [(type: CGPathElementType, points: [CGPoint])]()
24 | var elementType: CGPathElementType!
25 | var points: [CGPoint]!
26 | var firstPoint: CGPoint!
27 | var previousLastPoint: CGPoint!
28 | forEach { element in
29 | switch (element.type) {
30 | case CGPathElementType.moveToPoint:
31 | firstPoint = element.points[0]
32 | previousLastPoint = firstPoint
33 | case .addLineToPoint:
34 | points = [CGPoint]()
35 | elementType = element.type
36 | points.append(previousLastPoint)
37 | points.append(element.points[0])
38 | result.append((elementType, points))
39 |
40 | previousLastPoint = element.points[0]
41 | case .addQuadCurveToPoint:
42 | points = [CGPoint]()
43 | elementType = element.type
44 | points.append(previousLastPoint)
45 | points.append(element.points[0])
46 | points.append(element.points[1])
47 | result.append((elementType, points))
48 |
49 | previousLastPoint = element.points[1]
50 | case .addCurveToPoint:
51 | points = [CGPoint]()
52 | elementType = element.type
53 | points.append(previousLastPoint)
54 | points.append(element.points[0])
55 | points.append(element.points[1])
56 | points.append(element.points[2])
57 | result.append((elementType, points))
58 |
59 | previousLastPoint = element.points[2]
60 | case .closeSubpath:
61 | points = [CGPoint]()
62 | elementType = element.type
63 | points.append(previousLastPoint)
64 | points.append(firstPoint)
65 | result.append((elementType, points))
66 | @unknown default:
67 | break
68 | }
69 | }
70 |
71 | return result
72 | }
73 |
74 | func getElement(_ index: Int) -> (type: CGPathElementType, points: [CGPoint])? {
75 | let elements = getElements()
76 | if index >= elements.count {
77 | return nil
78 | }
79 | return elements[index]
80 | }
81 |
82 | func elementCount() -> Int {
83 | var count = 0
84 | self.forEach { element in
85 | if element.type != .moveToPoint && element.type != .closeSubpath {
86 | count += 1
87 | }
88 | }
89 | return count
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/Ubergang/Extension/UIBezierPath+Interpolation.h:
--------------------------------------------------------------------------------
1 | //
2 | // UIBezierPath+Interpolation.h
3 | // Curve Interpolation
4 | //
5 | // Created by John Fisher on 4/26/14.
6 | // Copyright (c) 2014 John Fisher. All rights reserved.
7 | //
8 | // Source: https://github.com/jnfisher/ios-curve-interpolation
9 |
10 | #import
11 |
12 | @interface UIBezierPath (Interpolation)
13 |
14 | // pointsAsNSValues must be NSValue objects containing CGPoints.
15 | //
16 | // ex:
17 | // const char *encoding = @encode(CGPoint);
18 | // NSValue *pointAsValue = [NSValue valueWithBytes:&cgPoint objCType:encoding];
19 |
20 | // 0.0 <= alpha <= 1.0
21 | +(UIBezierPath *)interpolateCGPointsWithCatmullRom:(NSArray *)pointsAsNSValues closed:(BOOL)closed alpha:(float)alpha;
22 | +(UIBezierPath *)interpolateCGPointsWithHermite:(NSArray *)pointsAsNSValues closed:(BOOL)closed;
23 | @end
--------------------------------------------------------------------------------
/Ubergang/Extension/UIBezierPath+Interpolation.m:
--------------------------------------------------------------------------------
1 | //
2 | // UIBezierPath+Interpolation.m
3 | // Curve Interpolation
4 | //
5 | // Created by John Fisher on 4/26/14.
6 | // Copyright (c) 2014 John Fisher. All rights reserved.
7 | //
8 | // Source: https://github.com/jnfisher/ios-curve-interpolation
9 |
10 | #import "UIBezierPath+Interpolation.h"
11 | #import "CGPointExtension.h"
12 |
13 | #define kEPSILON 1.0e-5
14 |
15 | @implementation UIBezierPath (Interpolation)
16 |
17 | +(UIBezierPath *)interpolateCGPointsWithCatmullRom:(NSArray *)pointsAsNSValues closed:(BOOL)closed alpha:(float)alpha {
18 | if ([pointsAsNSValues count] < 4)
19 | return nil;
20 |
21 | NSInteger endIndex = (closed ? [pointsAsNSValues count] : [pointsAsNSValues count]-2);
22 | NSAssert(alpha >= 0.0 && alpha <= 1.0, @"alpha value is between 0.0 and 1.0, inclusive");
23 |
24 | UIBezierPath *path = [UIBezierPath bezierPath];
25 | NSInteger startIndex = (closed ? 0 : 1);
26 | for (NSInteger ii=startIndex; ii < endIndex; ++ii) {
27 | CGPoint p0, p1, p2, p3;
28 | NSInteger nextii = (ii+1)%[pointsAsNSValues count];
29 | NSInteger nextnextii = (nextii+1)%[pointsAsNSValues count];
30 | NSInteger previi = (ii-1 < 0 ? [pointsAsNSValues count]-1 : ii-1);
31 |
32 | [pointsAsNSValues[ii] getValue:&p1];
33 | [pointsAsNSValues[previi] getValue:&p0];
34 | [pointsAsNSValues[nextii] getValue:&p2];
35 | [pointsAsNSValues[nextnextii] getValue:&p3];
36 |
37 | CGFloat d1 = ccpLength(ccpSub(p1, p0));
38 | CGFloat d2 = ccpLength(ccpSub(p2, p1));
39 | CGFloat d3 = ccpLength(ccpSub(p3, p2));
40 |
41 | CGPoint b1, b2;
42 | if (fabs(d1) < kEPSILON) {
43 | b1 = p1;
44 | }
45 | else {
46 | b1 = ccpMult(p2, powf(d1, 2*alpha));
47 | b1 = ccpSub(b1, ccpMult(p0, powf(d2, 2*alpha)));
48 | b1 = ccpAdd(b1, ccpMult(p1,(2*powf(d1, 2*alpha) + 3*powf(d1, alpha)*powf(d2, alpha) + powf(d2, 2*alpha))));
49 | b1 = ccpMult(b1, 1.0 / (3*powf(d1, alpha)*(powf(d1, alpha)+powf(d2, alpha))));
50 | }
51 |
52 | if (fabs(d3) < kEPSILON) {
53 | b2 = p2;
54 | }
55 | else {
56 | b2 = ccpMult(p1, powf(d3, 2*alpha));
57 | b2 = ccpSub(b2, ccpMult(p3, powf(d2, 2*alpha)));
58 | b2 = ccpAdd(b2, ccpMult(p2,(2*powf(d3, 2*alpha) + 3*powf(d3, alpha)*powf(d2, alpha) + powf(d2, 2*alpha))));
59 | b2 = ccpMult(b2, 1.0 / (3*powf(d3, alpha)*(powf(d3, alpha)+powf(d2, alpha))));
60 | }
61 |
62 | if (ii==startIndex)
63 | [path moveToPoint:p1];
64 |
65 | [path addCurveToPoint:p2 controlPoint1:b1 controlPoint2:b2];
66 | }
67 |
68 | if (closed)
69 | [path closePath];
70 |
71 | return path;
72 | }
73 |
74 | +(UIBezierPath *)interpolateCGPointsWithHermite:(NSArray *)pointsAsNSValues closed:(BOOL)closed {
75 | if ([pointsAsNSValues count] < 2)
76 | return nil;
77 |
78 | NSInteger nCurves = (closed ? [pointsAsNSValues count] : [pointsAsNSValues count]-1);
79 |
80 | UIBezierPath *path = [UIBezierPath bezierPath];
81 | for (NSInteger ii=0; ii < nCurves; ++ii) {
82 | NSValue *value = pointsAsNSValues[ii];
83 |
84 | CGPoint curPt, prevPt, nextPt, endPt;
85 | [value getValue:&curPt];
86 | if (ii==0)
87 | [path moveToPoint:curPt];
88 |
89 | NSInteger nextii = (ii+1)%[pointsAsNSValues count];
90 | NSInteger previi = (ii-1 < 0 ? [pointsAsNSValues count]-1 : ii-1);
91 |
92 | [pointsAsNSValues[previi] getValue:&prevPt];
93 | [pointsAsNSValues[nextii] getValue:&nextPt];
94 | endPt = nextPt;
95 |
96 | CGFloat mx, my;
97 | if (closed || ii > 0) {
98 | mx = (nextPt.x - curPt.x)*0.5 + (curPt.x - prevPt.x)*0.5;
99 | my = (nextPt.y - curPt.y)*0.5 + (curPt.y - prevPt.y)*0.5;
100 | }
101 | else {
102 | mx = (nextPt.x - curPt.x)*0.5;
103 | my = (nextPt.y - curPt.y)*0.5;
104 | }
105 |
106 | CGPoint ctrlPt1;
107 | ctrlPt1.x = curPt.x + mx / 3.0;
108 | ctrlPt1.y = curPt.y + my / 3.0;
109 |
110 | [pointsAsNSValues[nextii] getValue:&curPt];
111 |
112 | nextii = (nextii+1)%[pointsAsNSValues count];
113 | previi = ii;
114 |
115 | [pointsAsNSValues[previi] getValue:&prevPt];
116 | [pointsAsNSValues[nextii] getValue:&nextPt];
117 |
118 | if (closed || ii < nCurves-1) {
119 | mx = (nextPt.x - curPt.x)*0.5 + (curPt.x - prevPt.x)*0.5;
120 | my = (nextPt.y - curPt.y)*0.5 + (curPt.y - prevPt.y)*0.5;
121 | }
122 | else {
123 | mx = (curPt.x - prevPt.x)*0.5;
124 | my = (curPt.y - prevPt.y)*0.5;
125 | }
126 |
127 | CGPoint ctrlPt2;
128 | ctrlPt2.x = curPt.x - mx / 3.0;
129 | ctrlPt2.y = curPt.y - my / 3.0;
130 |
131 | [path addCurveToPoint:endPt controlPoint1:ctrlPt1 controlPoint2:ctrlPt2];
132 | }
133 |
134 | if (closed)
135 | [path closePath];
136 |
137 | return path;
138 | }
139 |
140 |
141 | @end
--------------------------------------------------------------------------------
/Ubergang/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.1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | $(CURRENT_PROJECT_VERSION)
23 | NSPrincipalClass
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/Ubergang/Protocols/Numeric.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Computable.swift
3 | // Ubergang
4 | //
5 | // Created by Robin Frielingsdorf on 14/01/16.
6 | // Copyright © 2016 Robin Falko. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | public protocol Numeric {
12 | init()
13 | init(_ value: Int)
14 | init(_ value: Double)
15 | init(_ value: Float)
16 |
17 | static func + (lhs: Self, rhs: Self) -> Self
18 | static func - (lhs: Self, rhs: Self) -> Self
19 | static func * (lhs: Self, rhs: Self) -> Self
20 | static func / (lhs: Self, rhs: Self) -> Self
21 | }
22 |
23 | extension Double : Numeric {
24 | public init?(_ value: T) {
25 | switch (value) {
26 | case is Int:
27 | self.init(Double(value as! Int))
28 | break
29 | case is Int8:
30 | self.init(Double(value as! Int8))
31 | break
32 | case is Int16:
33 | self.init(Double(value as! Int16))
34 | break
35 | case is Int32:
36 | self.init(Double(value as! Int32))
37 | break
38 | case is Int64:
39 | self.init(Double(value as! Int64))
40 | break
41 | case is Float:
42 | self.init(Double(value as! Float))
43 | break
44 | case is CGFloat:
45 | self.init(Double(value as! CGFloat))
46 | break
47 | case is Double:
48 | fallthrough
49 | default:
50 | return nil
51 | }
52 | }
53 | }
54 | extension Float : Numeric {}
55 | extension Int : Numeric {}
56 | extension Int8 : Numeric {}
57 | extension Int16 : Numeric {}
58 | extension Int32 : Numeric {}
59 | extension Int64 : Numeric {}
60 | extension UInt : Numeric {}
61 | extension UInt8 : Numeric {}
62 | extension UInt16 : Numeric {}
63 | extension UInt32 : Numeric {}
64 | extension UInt64 : Numeric {}
65 | extension CGFloat: Numeric {}
66 |
--------------------------------------------------------------------------------
/Ubergang/Protocols/Tweenable.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Tweenable.swift
3 | // Ubergang
4 | //
5 | // Created by Robin Frielingsdorf on 05/04/16.
6 | // Copyright © 2016 Robin Falko. All rights reserved.
7 | //
8 |
9 | public protocol Tweenable {
10 | var id: String { get }
11 | var duration: Double { get set }
12 | var progress: Double { get set }
13 |
14 | func start() -> Self
15 | func stop()
16 | func pause()
17 | func resume()
18 | func kill()
19 | }
--------------------------------------------------------------------------------
/Ubergang/Protocols/TypeTweenable.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Tween.swift
3 | // Ubergang
4 | //
5 | // Created by RF on 06.08.17.
6 | // Copyright © 2017 Robin Falko. All rights reserved.
7 | //
8 |
9 | // Not sure why this won't work.
10 | // Use repetitive code in extensions instead
11 | //public protocol GenericTweenable {
12 | // associatedtype TweenType: UTween
13 | // func tween(to: Self) -> TweenType
14 | //}
15 | //
16 | //public extension GenericTweenable {
17 | // func tween(to: Self) -> TweenType {
18 | // return TweenType().tween(from: self, to: to)
19 | // }
20 | //}
21 | //extension CGPoint: GenericTweenable {typealias TweenType = CGPointTween}
22 | //extension UIColor: GenericTweenable {typealias TweenType = ColorTween}
23 | //extension CGAffineTransform: Generic Tweenable {typealias TweenType = TransformTween}
24 |
25 | public extension CGPoint {
26 | func tween(to: CGPoint) -> CGPointTween {
27 | return CGPointTween().from(self, to: to)
28 | }
29 | }
30 |
31 | public extension UIColor {
32 | func tween(to: UIColor) -> ColorTween {
33 | return ColorTween().from(self, to: to)
34 | }
35 | }
36 |
37 | public extension CGAffineTransform {
38 | func tween(to: CGAffineTransform) -> TransformTween {
39 | return TransformTween().from(self, to: to)
40 | }
41 | }
42 |
43 | public protocol NumericTweenable: Numeric {
44 | func tween(to: Self) -> NumericTween
45 | }
46 |
47 | public extension NumericTweenable {
48 | func tween(to: Self) -> NumericTween {
49 | return NumericTween().from(self, to: to)
50 | }
51 | }
52 |
53 | extension Double : NumericTweenable {}
54 | extension Float : NumericTweenable {}
55 | extension Int : NumericTweenable {}
56 | extension Int8 : NumericTweenable {}
57 | extension Int16 : NumericTweenable {}
58 | extension Int32 : NumericTweenable {}
59 | extension Int64 : NumericTweenable {}
60 | extension UInt : NumericTweenable {}
61 | extension UInt8 : NumericTweenable {}
62 | extension UInt16 : NumericTweenable {}
63 | extension UInt32 : NumericTweenable {}
64 | extension UInt64 : NumericTweenable {}
65 | extension CGFloat: NumericTweenable {}
66 |
--------------------------------------------------------------------------------
/Ubergang/Protocols/UTweenLoggable.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UTweenLoggable.swift
3 | // Ubergang
4 | //
5 | // Created by RF on 18/07/16.
6 | // Copyright © 2016 Robin Falko. All rights reserved.
7 | //
8 |
9 | public protocol UTweenLoggable {
10 | func verbose(_ msg: String, function: String, file: String, line: Int)
11 | func debug(_ msg: String, function: String, file: String, line: Int)
12 | func info(_ msg: String, function: String, file: String, line: Int)
13 | func warning(_ msg: String, function: String, file: String, line: Int)
14 | func error(_ msg: String, function: String, file: String, line: Int)
15 | }
16 |
17 |
18 | extension UTweenLoggable {
19 | func verbose(_ msg: String, function: String = #function, file: String = #file, line: Int = #line) {
20 | print("[\(file) - \(function)->\(line)]:\(msg)")
21 | }
22 |
23 | func debug(_ msg: String, function: String = #function, file: String = #file, line: Int = #line) {
24 | print("[\(file) - \(function)->\(line)]:\(msg)")
25 | }
26 |
27 | func info(_ msg: String, function: String = #function, file: String = #file, line: Int = #line) {
28 | print("[\(file) - \(function)->\(line)]:\(msg)")
29 | }
30 |
31 | func warning(_ msg: String, function: String = #function, file: String = #file, line: Int = #line) {
32 | print("[\(file) - \(function)->\(line)]:\(msg)")
33 | }
34 |
35 | func error(_ msg: String, function: String = #function, file: String = #file, line: Int = #line) {
36 | print("[\(file) - \(function)->\(line)]:\(msg)")
37 | }
38 | }
39 |
40 |
41 | class UTweenLogger: UTweenLoggable {}
42 |
--------------------------------------------------------------------------------
/Ubergang/Protocols/WeaklyLoopable.swift:
--------------------------------------------------------------------------------
1 | //
2 | // WeaklyLoopable.swift
3 | // Ubergang
4 | //
5 | // Created by Robin Frielingsdorf on 10/04/16.
6 | // Copyright © 2016 Robin Falko. All rights reserved.
7 | //
8 |
9 | protocol WeaklyLoopable {
10 | func loopWeakly()
11 | }
--------------------------------------------------------------------------------
/Ubergang/Tween/CGPointTween.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CGPointTween.swift
3 | // Ubergang
4 | //
5 | // Created by Robin Frielingsdorf on 14/01/16.
6 | // Copyright © 2016 Robin Falko. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | open class CGPointTween: UTween {
12 |
13 | var currentValue = CGPoint()
14 |
15 | override func compute(_ value: Double) -> CGPoint {
16 | _ = super.compute(value)
17 |
18 | let from = self.fromC()
19 | let to = self.toC()
20 |
21 | currentValue.x = from.x + (to.x - from.x) * CGFloat(value)
22 | currentValue.y = from.y + (to.y - from.y) * CGFloat(value)
23 |
24 | return currentValue
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/Ubergang/Tween/ColorTween.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ColorTween.swift
3 | // Ubergang
4 | //
5 | // Created by Robin Frielingsdorf on 14/01/16.
6 | // Copyright © 2016 Robin Falko. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import UIKit
11 |
12 | open class ColorTween: UTween {
13 | override func compute(_ value: Double) -> UIColor {
14 | _ = super.compute(value)
15 |
16 | let from = self.fromC()
17 | let to = self.toC()
18 |
19 | var rFrom: CGFloat = 0
20 | var gFrom: CGFloat = 0
21 | var bFrom: CGFloat = 0
22 | var aFrom: CGFloat = 0
23 |
24 | var rTo: CGFloat = 0
25 | var gTo: CGFloat = 0
26 | var bTo: CGFloat = 0
27 | var aTo: CGFloat = 0
28 |
29 | from.getRed(&rFrom, green: &gFrom, blue: &bFrom, alpha: &aFrom)
30 | to.getRed(&rTo, green: &gTo, blue: &bTo, alpha: &aTo)
31 |
32 | let r = rFrom + (rTo - rFrom) * CGFloat(value)
33 | let g = gFrom + (gTo - gFrom) * CGFloat(value)
34 | let b = bFrom + (bTo - bFrom) * CGFloat(value)
35 | let a = aFrom + (aTo - aFrom) * CGFloat(value)
36 |
37 | return UIColor(red: r, green: g, blue: b, alpha: a)
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/Ubergang/Tween/NumericTween.swift:
--------------------------------------------------------------------------------
1 | //
2 | // NumericTween.swift
3 | // Ubergang
4 | //
5 | // Created by Robin Frielingsdorf on 14/01/16.
6 | // Copyright © 2016 Robin Falko. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | open class NumericTween: UTween {
12 | override func compute(_ value: Double) -> T {
13 | _ = super.compute(value)
14 |
15 | let from = self.fromC()
16 | let to = self.toC()
17 |
18 | let distance = to - from
19 | var parsedDistance: Double
20 | if distance is Double {
21 | parsedDistance = distance as! Double
22 | }
23 | else {
24 | parsedDistance = Double(distance)!
25 | }
26 |
27 | let total = T( parsedDistance * value )
28 |
29 | return from + total
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/Ubergang/Tween/TransformTween.swift:
--------------------------------------------------------------------------------
1 | //
2 | // TransformTween.swift
3 | // Ubergang
4 | //
5 | // Created by Robin Frielingsdorf on 14/01/16.
6 | // Copyright © 2016 Robin Falko. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import UIKit
11 |
12 | open class TransformTween: UTween {
13 | override func compute(_ value: Double) -> CGAffineTransform {
14 | _ = super.compute(value)
15 |
16 | let from = self.fromC()
17 | let to = self.toC()
18 |
19 | var currentValue = CGAffineTransform.identity
20 | currentValue.tx = from.tx + (to.tx - from.tx) * CGFloat(value)
21 | currentValue.ty = from.ty + (to.ty - from.ty) * CGFloat(value)
22 |
23 | currentValue.a = from.a + (to.a - from.a) * CGFloat(value)
24 | currentValue.b = from.b + (to.b - from.b) * CGFloat(value)
25 | currentValue.c = from.c + (to.c - from.c) * CGFloat(value)
26 | currentValue.d = from.d + (to.d - from.d) * CGFloat(value)
27 |
28 | return currentValue
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/Ubergang/Tween/UTimeline.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UTimeline.swift
3 | // Ubergang
4 | //
5 | // Created by Robin Frielingsdorf on 05/04/16.
6 | // Copyright © 2016 Robin Falko. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | open class UTimeline: UTweenBase {
12 | var tweens: [UTweenBase] = []
13 | var startTimeForTweenId: [String : Double] = [:]
14 |
15 | open var count: Int { return tweens.count }
16 |
17 | /**
18 | Initialize a `UTimeline` with a random id.
19 |
20 | Tweens all containing elements from start to end.
21 | */
22 | public convenience init() {
23 | let id = "\(#file)_\(arc4random())_update"
24 | self.init(id: id)
25 | }
26 |
27 | /**
28 | Initialize a `UTimeline`.
29 |
30 | Tweens all containing elements from start to end.
31 |
32 | - Parameter id: The unique id of the Tween
33 | */
34 | public override init(id: String) {
35 | super.init(id: id)
36 |
37 | initialDuration = 0
38 | duration = 0
39 | durationTotal = 0
40 | }
41 |
42 | override func computeConfigs() {
43 | super.computeConfigs()
44 |
45 | for tween in tweens {
46 | switch direction {
47 | case .forward: tween.currentEase = tween.ease
48 | case .reverse: tween.currentEase = tween.ease
49 | case .backward: tween.currentEase = tween.ease.opposite
50 | }
51 | }
52 | }
53 |
54 | open func append(_ tween: UTweenBase) {
55 | // tween.computeConfigs()
56 | //
57 | // tweens.append(tween)
58 | //
59 | // startTimeForTweenId[tween.id] = initialDuration
60 | //
61 | // initialDuration += tween.durationTotal
62 | //
63 | // computeConfigs()
64 |
65 | insert(tween, at: durationTotal)
66 | }
67 |
68 | open func insert(_ tween: UTweenBase, at time: Double) {
69 | tween.computeConfigs()
70 |
71 | tweens.append(tween)
72 |
73 | startTimeForTweenId[tween.id] = time
74 | duration = max(duration, time + tween.durationTotal)
75 | initialDuration = duration
76 |
77 | tweens.sort(by: {
78 | startTimeForTweenId[$0.id] ?? 0 < startTimeForTweenId[$1.id] ?? 0
79 | })
80 | computeConfigs()
81 | }
82 |
83 | override open var progress: Double {
84 | set {
85 | time = newValue * duration
86 |
87 | for tween in tweens {
88 | let repeatCount = tweenOptions.repeatCount()
89 | var cycles = Double(repeatCount + 1)
90 |
91 | if tweenOptions.contains(.yoyo) && !tweenOptions.containsRepeat() {
92 | cycles *= 2.0
93 | }
94 |
95 | var startTime = startTimeForTweenId[tween.id]! / cycles
96 |
97 | if direction == .backward {
98 | startTime = durationTotal - tween.durationTotal - startTime
99 | }
100 |
101 | let mapped = Math.mapValueInRange(time,
102 | fromLower: startTime, fromUpper: startTime + tween.durationTotal / cycles,
103 | toLower: 0.0, toUpper: 1.0)
104 |
105 | let value = tween.direction == .forward ? mapped : 1 - mapped
106 |
107 | let clamped = Math.clamp(value, lower: 0.0, upper: 1.0)
108 | tween.progressTotal = clamped
109 | }
110 |
111 | super.progress = newValue
112 | }
113 | get {
114 | return time / duration
115 | }
116 | }
117 |
118 |
119 | @discardableResult
120 | override open func reference(_ value: TweenMemoryReference) -> Self {
121 | reference = value
122 |
123 | return self
124 | }
125 | }
126 |
--------------------------------------------------------------------------------
/Ubergang/Tween/UTween.h:
--------------------------------------------------------------------------------
1 | //
2 | // UTween.h
3 | // UTween
4 | //
5 | // Created by Robin Frielingsdorf on 07/01/16.
6 | // Copyright © 2016 Robin Falko. All rights reserved.
7 | //
8 |
9 | #import
10 | #import
11 |
12 | //! Project version number for Tween.
13 | FOUNDATION_EXPORT double TweenVersionNumber;
14 |
15 | //! Project version string for Tween.
16 | FOUNDATION_EXPORT const unsigned char TweenVersionString[];
17 |
18 | // In this header, you should import all the public headers of your framework using statements like #import
19 |
20 |
21 |
--------------------------------------------------------------------------------
/Ubergang/Tween/UTween.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UTween.swift
3 | // UTween
4 | //
5 | // Created by Robin Frielingsdorf on 07/01/16.
6 | // Copyright © 2016 Robin Falko. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import UIKit
11 |
12 | open class UTween: UTweenBase {
13 |
14 | var start: T!
15 | var end: T!
16 |
17 | internal var fromC: (() -> T)!
18 | internal var toC: (() -> T)!
19 |
20 | var updateValue: ((_ value: T) -> Void)!
21 | var updateValueAndProgress: ((_ value: T, _ progress: Double) -> Void)!
22 |
23 | var offset: Double?
24 |
25 | /**
26 | Initialize a generic `UTween` with a random id.
27 |
28 | Tweens any value with type T from start to end.
29 |
30 | This object needs to know how to compute interpolations from start to end, that for
31 | `func compute(value: Double) -> T` must be overriden.
32 | */
33 | public convenience init() {
34 | let id = "\(#file)_\(arc4random())_update"
35 | self.init(id: id)
36 | }
37 |
38 | /**
39 | Initialize a generic `UTween`.
40 |
41 | Tweens any value with type T from start to end.
42 |
43 | This object needs to know how to compute interpolations from start to end, that for
44 | `func compute(value: Double) -> T` must be overriden.
45 |
46 | - Parameter id: The unique id of the Tween
47 | */
48 | public override init(id: String) {
49 | super.init(id: id)
50 | }
51 |
52 | override open var progress: Double {
53 | set {
54 | time = newValue * duration
55 |
56 | easeValue = currentEase.function(time, 0.0, 1.0, duration)
57 |
58 | if let offset = offset {
59 | easeValue = fmod(easeValue + offset, 1.0)
60 | }
61 |
62 | let computedValue = compute(easeValue)
63 |
64 | updateValue?( computedValue)
65 | updateValueAndProgress?( computedValue, newValue )
66 |
67 | super.progress = newValue
68 | }
69 | get {
70 | return time / duration
71 | }
72 | }
73 |
74 | func compute(_ value: Double) -> T {
75 | //should be overriden
76 |
77 | return fromC()
78 | }
79 |
80 | //override Tweenable methods
81 | override open func kill() {
82 | super.kill()
83 |
84 | fromC = nil
85 | updateValue = nil
86 | updateValueAndProgress = nil
87 | complete = nil
88 | }
89 |
90 | @discardableResult
91 | override open func reference(_ value: TweenMemoryReference) -> Self {
92 | reference = value
93 |
94 | return self
95 | }
96 | }
97 |
98 |
99 | extension UTween {
100 | // -
101 | public func from(_ from: T, to: T) -> Self {
102 | self.fromC = {from}
103 | self.toC = {to}
104 |
105 | return self.duration(duration)
106 | }
107 |
108 | public func from(_ from: @escaping () -> T, to: @escaping () -> T) -> Self {
109 | self.fromC = from
110 | self.toC = to
111 |
112 | return self.duration(duration)
113 | }
114 |
115 | public func from(_ from: @escaping () -> T, to: T) -> Self {
116 | self.fromC = from
117 | self.toC = {to}
118 |
119 | return self.duration(duration)
120 | }
121 |
122 | public func from(_ from: T, to: @escaping () -> T) -> Self {
123 | self.fromC = {from}
124 | self.toC = to
125 |
126 | return self.duration(duration)
127 | }
128 |
129 |
130 | @discardableResult
131 | public func update(_ value: @escaping (T) -> Void) -> Self {
132 | updateValue = value
133 |
134 | return self
135 | }
136 |
137 |
138 | @discardableResult
139 | public func update(_ value: @escaping (T, Double) -> Void) -> Self {
140 | updateValueAndProgress = value
141 |
142 | return self
143 | }
144 |
145 | @discardableResult
146 | public func ease(_ ease: Ease) -> Self {
147 | self.ease = ease
148 | self.currentEase = ease
149 | return self
150 | }
151 |
152 | @discardableResult
153 | public func offset(_ value: Double) -> Self {
154 | self.offset = value
155 | return self
156 | }
157 | }
158 |
--------------------------------------------------------------------------------
/Ubergang/Util/Bezier.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Bezier.swift
3 | // Ubergang
4 | //
5 | // Created by Robin Frielingsdorf on 17/05/16.
6 | // Copyright © 2016 Robin Falko. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import GLKit
11 |
12 | //see https://en.wikipedia.org/wiki/B%C3%A9zier_curve
13 |
14 | class Bezier {
15 | static func linear(t _t: CGFloat, p0: CGPoint, p1: CGPoint) -> CGPoint {
16 |
17 | let v0 = GLKVector2(v: (Float(p0.x), Float(p0.y)))
18 | let v1 = GLKVector2(v: (Float(p1.x), Float(p1.y)))
19 |
20 | let t = Float(_t)
21 |
22 | let v0r = GLKVector2MultiplyScalar(v0, 1-t)
23 | let v1r = GLKVector2MultiplyScalar(v1, t)
24 |
25 | let vResult = GLKVector2Add(v0r, v1r)
26 |
27 | return CGPoint(x: CGFloat(vResult.x), y: CGFloat(vResult.y))
28 | }
29 |
30 | static func quad(t _t: CGFloat, p0: CGPoint, p1: CGPoint, p2: CGPoint) -> CGPoint {
31 |
32 | let v0 = GLKVector2(v: (Float(p0.x), Float(p0.y)))
33 | let v1 = GLKVector2(v: (Float(p1.x), Float(p1.y)))
34 | let v2 = GLKVector2(v: (Float(p2.x), Float(p2.y)))
35 |
36 | let t = Float(_t)
37 |
38 | let v0r = GLKVector2MultiplyScalar(v0, pow(1-t, 2))
39 | let v1r = GLKVector2MultiplyScalar(v1, 2*t*(1-t))
40 | let v2r = GLKVector2MultiplyScalar(v2, t*t)
41 |
42 | var vResult = GLKVector2Add(v0r, v1r)
43 | vResult = GLKVector2Add(vResult, v2r)
44 |
45 | return CGPoint(x: CGFloat(vResult.x), y: CGFloat(vResult.y))
46 | }
47 |
48 | static func cubic(t _t: CGFloat, p0: CGPoint, p1: CGPoint, p2: CGPoint, p3: CGPoint) -> CGPoint {
49 | let v0 = GLKVector2(v: (Float(p0.x), Float(p0.y)))
50 | let v1 = GLKVector2(v: (Float(p1.x), Float(p1.y)))
51 | let v2 = GLKVector2(v: (Float(p2.x), Float(p2.y)))
52 | let v3 = GLKVector2(v: (Float(p3.x), Float(p3.y)))
53 |
54 | let t = Float(_t)
55 |
56 | let v0r = GLKVector2MultiplyScalar(v0, pow(1-t, 3))
57 | let v1r = GLKVector2MultiplyScalar(v1, 3 * t * pow(1-t, 2))
58 | let v2r = GLKVector2MultiplyScalar(v2, 3 * pow(t, 2) * (1-t))
59 | let v3r = GLKVector2MultiplyScalar(v3, pow(t, 3))
60 |
61 | var vResult = GLKVector2Add(v0r, v1r)
62 | vResult = GLKVector2Add(vResult, v2r)
63 | vResult = GLKVector2Add(vResult, v3r)
64 |
65 | return CGPoint(x: CGFloat(vResult.x), y: CGFloat(vResult.y))
66 | }
67 | }
--------------------------------------------------------------------------------
/Ubergang/Util/Math.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Math.swift
3 | // Ubergang
4 | //
5 | // Created by Robin Frielingsdorf on 15/05/16.
6 | // Copyright © 2016 Robin Falko. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | class Math {
12 | class func clamp(_ value: T, lower: T, upper: T) -> T {
13 | return max(lower, min(value, upper))
14 | }
15 |
16 | class func mapValueInRange(_ value: Double, fromLower: Double, fromUpper: Double, toLower: Double, toUpper: Double) -> Double {
17 | let fromRangeSize = fromUpper - fromLower
18 | let toRangeSize = toUpper - toLower
19 | let valueScale = (value - fromLower) / fromRangeSize
20 | return toLower + (valueScale * toRangeSize)
21 | }
22 |
23 | class func zigZag(_ x: Double) -> Double {
24 | return 1 / .pi * asin(cos(Double.pi * (x + 1))) + 0.5
25 | }
26 | }
27 |
--------------------------------------------------------------------------------