├── .clang-format
├── .codecov.yml
├── .gitignore
├── .jazzy.yaml
├── .kokoro
├── .travis.yml
├── AUTHORS
├── CHANGELOG.md
├── CONTRIBUTING.md
├── Info.plist
├── LICENSE
├── MotionInterchange.podspec
├── MotionInterchange.xcodeproj
├── project.pbxproj
└── xcshareddata
│ └── xcschemes
│ └── MotionInterchange.xcscheme
├── Podfile
├── Podfile.lock
├── README.md
├── examples
├── apps
│ └── Catalog
│ │ ├── Catalog
│ │ ├── AppDelegate.swift
│ │ ├── Assets.xcassets
│ │ │ └── AppIcon.appiconset
│ │ │ │ └── Contents.json
│ │ ├── Base.lproj
│ │ │ └── LaunchScreen.storyboard
│ │ └── Info.plist
│ │ ├── MotionInterchangeCatalog.xcodeproj
│ │ ├── project.pbxproj
│ │ └── xcshareddata
│ │ │ └── xcschemes
│ │ │ ├── MotionInterchangeCatalog.xcscheme
│ │ │ └── UnitTests.xcscheme
│ │ ├── TableOfContents.swift
│ │ ├── TestHarness
│ │ ├── AppDelegate.swift
│ │ ├── Assets.xcassets
│ │ │ └── AppIcon.appiconset
│ │ │ │ └── Contents.json
│ │ ├── Base.lproj
│ │ │ └── LaunchScreen.storyboard
│ │ └── Info.plist
│ │ └── UnitTests
│ │ └── Info.plist
└── supplemental
│ ├── ExampleViewController.swift
│ ├── ExampleViews.swift
│ ├── HexColor.swift
│ ├── Layout.swift
│ └── ModalViewController.swift
├── img
└── motion-interchange-banner.gif
├── resources
└── Info.plist
├── scripts
└── v1_to_v2.sh
├── src
├── CAMediaTimingFunction+MDMTimingCurve.h
├── CAMediaTimingFunction+MDMTimingCurve.m
├── MDMAnimationTraits.h
├── MDMAnimationTraits.m
├── MDMMotionCurve.h
├── MDMMotionCurve.m
├── MDMMotionRepetition.h
├── MDMMotionTiming.h
├── MDMRepetition.h
├── MDMRepetition.m
├── MDMRepetitionOverTime.h
├── MDMRepetitionOverTime.m
├── MDMRepetitionTraits.h
├── MDMSpringTimingCurve.h
├── MDMSpringTimingCurve.m
├── MDMSpringTimingCurveGenerator.h
├── MDMSpringTimingCurveGenerator.m
├── MDMSubclassingRestricted.h
├── MDMTimingCurve.h
└── MotionInterchange.h
└── tests
└── unit
├── CAMediaTimingFunctionTests.swift
├── MDMAnimationTraitsTests.swift
├── MDMLegacyAPITests.swift
├── MDMModalMovementTimingTests.m
├── MDMMotionCurveTests.m
├── MDMMotionCurveTests.swift
├── MDMRepetitionOverTimeTests.swift
├── MDMRepetitionTests.swift
└── MDMSpringTimingCurve.swift
/.clang-format:
--------------------------------------------------------------------------------
1 | BasedOnStyle: Google
2 |
3 | AllowShortFunctionsOnASingleLine: Inline
4 | AllowShortIfStatementsOnASingleLine: false
5 | AllowShortLoopsOnASingleLine: false
6 | AlwaysBreakBeforeMultilineStrings: false
7 | BinPackParameters: false
8 | ColumnLimit: 0
9 | IndentWrappedFunctionNames: true
10 | ObjCSpaceBeforeProtocolList: true
11 | PointerBindsToType: false
12 | SortIncludes: true
13 |
--------------------------------------------------------------------------------
/.codecov.yml:
--------------------------------------------------------------------------------
1 | coverage:
2 | ignore:
3 | - "examples/"
4 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | bazel-*
2 | .kokoro-ios-runner
3 |
4 | # Jazzy
5 | docs/
6 |
7 | # Xcode
8 | #
9 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
10 |
11 | ## Build generated
12 | build/
13 | DerivedData/
14 |
15 | ## Various settings
16 | *.pbxuser
17 | !default.pbxuser
18 | *.mode1v3
19 | !default.mode1v3
20 | *.mode2v3
21 | !default.mode2v3
22 | *.perspectivev3
23 | !default.perspectivev3
24 | xcuserdata/
25 |
26 | ## Other
27 | *.moved-aside
28 | *.xcuserstate
29 |
30 | ## Obj-C/Swift specific
31 | *.hmap
32 | *.ipa
33 | *.dSYM.zip
34 | *.dSYM
35 |
36 | ## Playgrounds
37 | timeline.xctimeline
38 | playground.xcworkspace
39 |
40 | # Swift Package Manager
41 | #
42 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
43 | # Packages/
44 | .build/
45 |
46 | # CocoaPods
47 | #
48 | # We recommend against adding the Pods directory to your .gitignore. However
49 | # you should judge for yourself, the pros and cons are mentioned at:
50 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
51 | #
52 | Pods/
53 | *.xcworkspace
54 |
55 | # Carthage
56 | #
57 | # Add this line if you want to avoid checking in source code from Carthage dependencies.
58 | # Carthage/Checkouts
59 |
60 | Carthage/Build
61 |
62 | # fastlane
63 | #
64 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
65 | # screenshots whenever they are needed.
66 | # For more information about the recommended setup visit:
67 | # https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Gitignore.md
68 |
69 | fastlane/report.xml
70 | fastlane/Preview.html
71 | fastlane/screenshots
72 | fastlane/test_output
73 | .DS_Store
74 |
--------------------------------------------------------------------------------
/.jazzy.yaml:
--------------------------------------------------------------------------------
1 | module: MotionInterchange
2 | module_version: 3.0.0
3 | sdk: iphonesimulator
4 | umbrella_header: src/MotionInterchange.h
5 | objc: true
6 | github_url: https://github.com/material-motion/motion-interchange-objc
7 | github_file_prefix: https://github.com/material-motion/motion-interchange-objc/tree/v3.0.0
8 |
9 |
--------------------------------------------------------------------------------
/.kokoro:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | #
3 | # Copyright 2017-present The Material Motion Authors. All Rights Reserved.
4 | #
5 | # Licensed under the Apache License, Version 2.0 (the "License");
6 | # you may not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing, software
12 | # distributed under the License is distributed on an "AS IS" BASIS,
13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | # See the License for the specific language governing permissions and
15 | # limitations under the License.
16 |
17 | # Fail on any error.
18 | set -e
19 |
20 | # Display commands to stderr.
21 | set -x
22 |
23 | BAZEL_VERSION="0.20.0"
24 |
25 | fix_bazel_imports() {
26 | if [ -z "$KOKORO_BUILD_NUMBER" ]; then
27 | repo_prefix=""
28 | else
29 | repo_prefix="github/repo/"
30 | fi
31 |
32 | # Fixes a bug in bazel where objc_library targets have a _ prefix.
33 | find "${repo_prefix}tests/unit" -type f -name '*.swift' -exec sed -i '' -E "s/import Motion(.+)/import _Motion\1/" {} + || true
34 | stashed_dir=$(pwd)
35 | reset_imports() {
36 | # Undoes our source changes from above.
37 | find "${stashed_dir}/${tests_dir_prefix}tests/unit" -type f -name '*.swift' -exec sed -i '' -E "s/import _Motion(.+)/import Motion\1/" {} + || true
38 | }
39 | trap reset_imports EXIT
40 | }
41 |
42 | run_bazel() {
43 | echo "Running bazel builds..."
44 |
45 | fix_bazel_imports
46 |
47 | if [ -n "$KOKORO_BUILD_NUMBER" ]; then
48 | bazel version
49 | use_bazel.sh "$BAZEL_VERSION"
50 | bazel version
51 |
52 | # Move into our cloned repo
53 | cd github/repo
54 | fi
55 |
56 | # Run against whichever Xcode is currently selected.
57 | selected_xcode_developer_path=$(xcode-select -p)
58 | selected_xcode_contents_path=$(dirname "$selected_xcode_developer_path")
59 |
60 | xcode_version=$(cat "$selected_xcode_contents_path/version.plist" \
61 | | grep "CFBundleShortVersionString" -A1 \
62 | | grep string \
63 | | cut -d'>' -f2 \
64 | | cut -d'<' -f1)
65 |
66 | bazel clean
67 | bazel test //... --xcode_version $xcode_version --ios_minimum_os=9.0 --ios_multi_cpus=i386,x86_64 --test_output=all
68 | }
69 |
70 | run_bazel
71 |
72 | echo "Success!"
73 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: objective-c
2 | sudo: false
3 | env:
4 | global:
5 | - LC_CTYPE=en_US.UTF-8
6 | - LANG=en_US.UTF-8
7 | - LANGUAGE=en_US.UTF-8
8 | matrix:
9 | include:
10 | - osx_image: xcode12.2
11 | env: COVERAGE=code_coverage SDK="iphonesimulator14.2" DESTINATION="name=iPhone 6s,OS=11.4"
12 | - osx_image: xcode12.2
13 | env: SDK="iphonesimulator14.2" DESTINATION="name=iPhone 6s,OS=10.3.1"
14 | before_install:
15 | - gem install cocoapods --no-document --quiet
16 | - pod install --repo-update
17 | script:
18 | - set -o pipefail
19 | - xcodebuild test -workspace MotionInterchange.xcworkspace -scheme MotionInterchangeCatalog -sdk "$SDK" -destination "$DESTINATION" -enableCodeCoverage YES ONLY_ACTIVE_ARCH=YES | xcpretty -c;
20 | after_success:
21 | - if [ "$COVERAGE" == "code_coverage" ]; then
22 | bash <(curl -s https://codecov.io/bash);
23 | fi
24 | - bash <(curl -s https://codecov.io/bash)
25 |
--------------------------------------------------------------------------------
/AUTHORS:
--------------------------------------------------------------------------------
1 | # This is the list of Motion Timing authors for copyright purposes.
2 | #
3 | # This does not necessarily list everyone who has contributed code, since in
4 | # some cases, their employer may be the copyright holder. To see the full list
5 | # of contributors, see the revision history with git log.
6 |
7 | Google Inc.
8 | and other contributors
9 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # 4.0.1
2 |
3 | This patch release resolves some missed warnings in 4.0.0 and fixes a broken test on iOS 13+14.
4 |
5 | # 4.0.0
6 |
7 | This major release drops official support for Bazel and iOS 9.
8 |
9 | # 3.0.0
10 |
11 | This major release drops official support for iOS 8.
12 |
13 | ## Non-source changes
14 |
15 | * [Drop support for iOS 8 (#43)](https://github.com/material-motion/motion-interchange-objc/commit/31a6c576f752a132206c7b09412bd6a390052b88) (featherless)
16 | * [Remove the xcode_select logic. (#42)](https://github.com/material-motion/motion-interchange-objc/commit/9cd51bc492174aabfa99cd2d4d802f8f58a3239c) (featherless)
17 |
18 | # 2.0.0
19 |
20 | This major release upgrades the bazel dependencies and workspace. This change is breaking for anyone
21 | using bazel to build this library. In order to use this library with bazel, you will also need to
22 | upgrade your workspace versions to match the ones now used in this library's `WORKSPACE` file.
23 |
24 | ## Source changes
25 |
26 | * [Update .travis.yml (#35)](https://github.com/material-motion/motion-interchange-objc/commit/f9891a24b843edc004f86ee86f7477d6327957b1) (featherless)
27 |
28 | ## Non-source changes
29 |
30 | * [Update bazel workspace to latest versions. (#40)](https://github.com/material-motion/motion-interchange-objc/commit/a9a1cab4354ce45d8a4548b28c708455ce93885a) (featherless)
31 | * [Update .kokoro](https://github.com/material-motion/motion-interchange-objc/commit/cfbd73021314ce24b0e0f2d37906b58b128e416c) (featherless)
32 | * [Update .kokoro](https://github.com/material-motion/motion-interchange-objc/commit/7e3af4ac83426ea8da8283211e09c0458ff24b81) (featherless)
33 | * [Update bazel workspace and version to latest (#38)](https://github.com/material-motion/motion-interchange-objc/commit/71aa2e4393574d2b4b5cf55695787b9a662165d1) (featherless)
34 | * [Update .kokoro to build against Xcode 9.1](https://github.com/material-motion/motion-interchange-objc/commit/816f52f4600b311f50dae7ef9aa3b9f9f1fb1b0e) (featherless)
35 | * [Update .travis.yml](https://github.com/material-motion/motion-interchange-objc/commit/ba7e0f0015b83eda35edf0144fb6fa3ebb52a81a) (featherless)
36 |
37 | # 1.6.0
38 |
39 | This patch release introduces a compatibility initializer for creating Objective-C animation traits from C-style motion timings.
40 |
41 | ## Source changes
42 |
43 | * [Add a legacy initializer for animation traits. (#34)](https://github.com/material-motion/motion-interchange-objc/commit/e3321d0e4081de1f3d8edee115af0a9ea2142c48) (featherless)
44 |
45 | ## API changes
46 |
47 | Auto-generated by running:
48 |
49 | apidiff origin/stable release-candidate objc src/MotionInterchange.h
50 |
51 | #### MDMAnimationTraits(Legacy)
52 |
53 | *new* method: `-initWithMotionTiming:` in `MDMAnimationTraits(Legacy)`
54 |
55 | *new* category: `MDMAnimationTraits(Legacy)`
56 |
57 | # 1.5.0
58 |
59 | This minor release introduces new Objective-C APIs for creating and storing animation traits.
60 |
61 | ## New deprecations
62 |
63 | All of the original C-style APIs for animation timing are now informally deprecated. We will remove these APIs in the future.
64 |
65 | ## New features
66 |
67 | New Objective-C APIs for storing animation traits.
68 |
69 | | Old API | New API | Rationale |
70 | |:------- |:-------- |:-----------|
71 | | MotionTiming | AnimationTraits | This structure is intended to describe animations only, not motion in general. |
72 | | MotionCurve | TimingCurve | This brings the API name closer to the similarly-purposed `CAMediaTimingFunction`. MotionCurve could also be easily confused with motion through x/y space rather than through time (e.g. ArcMove), which will be problematic as we start defining paths of motion through space. |
73 | | MotionRepetition | RepetitionTraits | This aligns the naming with AnimationTraits. |
74 |
75 | ## Source changes
76 |
77 | * [Restrict subclassing on all types. (#32)](https://github.com/material-motion/motion-interchange-objc/commit/0530ba355d8af640fd9fd51df137c6aed494f63c) (featherless)
78 | * [Re-introduce v1 APIs. (#33)](https://github.com/material-motion/motion-interchange-objc/commit/4a857a0393d55e01d1b282d12a814cec197111c0) (featherless)
79 | * [Extract the UIKit damping ratio APIs to their own class. (#31)](https://github.com/material-motion/motion-interchange-objc/commit/e9226a45892cf1a3f783232e6e7fc81751aaeb1d) (featherless)
80 | * [Add support for copying animation traits. (#30)](https://github.com/material-motion/motion-interchange-objc/commit/f7fb09546d034fcdf8e57509aa157a760aebd398) (featherless)
81 | * [Allow writing of all properties. (#26)](https://github.com/material-motion/motion-interchange-objc/commit/4f74d24b6d66503fed71af36482665814e10a3a4) (featherless)
82 | * [Add support for damping ratio initializers on the spring timing curve. (#27)](https://github.com/material-motion/motion-interchange-objc/commit/9d7352cec750b8c00fe300708647ebb01189b6c2) (featherless)
83 | * [Use UIViewAnimationCurve instead of NSString as the easing curve type. (#28)](https://github.com/material-motion/motion-interchange-objc/commit/d94246c2b5286d20f92dfc7569b39798394d9422) (featherless)
84 | * [Add APIs for initializing an animation trait with a named timing function. (#25)](https://github.com/material-motion/motion-interchange-objc/commit/72e75e44a940e815a06ee516237451be0646b688) (featherless)
85 | * [Implement v2 APIs (#22)](https://github.com/material-motion/motion-interchange-objc/commit/3a28e221cfe9fccc2c46523adbb817334e7e918a) (featherless)
86 | * [Standardize the timing curve creation methods on CGFloat. (#21)](https://github.com/material-motion/motion-interchange-objc/commit/75f0d3515bda6cb9770c96ddb787a3da50a2b7c6) (featherless)
87 |
88 | ## API changes
89 |
90 | Auto-generated by running:
91 |
92 | apidiff origin/stable release-candidate objc src/MotionInterchange.h
93 |
94 | #### MDMRepetitionOverTime
95 |
96 | *new* class: `MDMRepetitionOverTime`
97 |
98 | *new* method: `-initWithDuration:autoreverses:` in `MDMRepetitionOverTime`
99 |
100 | *new* method: `-init` in `MDMRepetitionOverTime`
101 |
102 | *new* property: `duration` in `MDMRepetitionOverTime`
103 |
104 | *new* method: `-initWithDuration:` in `MDMRepetitionOverTime`
105 |
106 | #### MDMTimingCurve
107 |
108 | *new* protocol: `MDMTimingCurve`
109 |
110 | #### CAMediaTimingFunction()
111 |
112 | *new* category: `CAMediaTimingFunction()`
113 |
114 | #### MDMRepetitionTraits
115 |
116 | *new* property: `autoreverses` in `MDMRepetitionTraits`
117 |
118 | *new* protocol: `MDMRepetitionTraits`
119 |
120 | #### MDMMotionCurveMakeSpringWithInitialVelocity
121 |
122 | *modified* function: `MDMMotionCurveMakeSpringWithInitialVelocity`
123 |
124 | | Type of change: | Swift declaration |
125 | |---|---|
126 | | From: | `func MotionCurveMakeSpring(mass: Float, tension: Float, friction: Float, initialVelocity: Float) -> MotionCurve` |
127 | | To: | `func MotionCurveMakeSpring(mass: CGFloat, tension: CGFloat, friction: CGFloat, initialVelocity: CGFloat) -> MotionCurve` |
128 |
129 | *modified* function: `MDMMotionCurveMakeSpringWithInitialVelocity`
130 |
131 | | Type of change: | Declaration |
132 | |---|---|
133 | | From: | `extern MDMMotionCurve MDMMotionCurveMakeSpringWithInitialVelocity( float mass, float tension, float friction, float initialVelocity)` |
134 | | To: | `extern MDMMotionCurve MDMMotionCurveMakeSpringWithInitialVelocity( CGFloat mass, CGFloat tension, CGFloat friction, CGFloat initialVelocity)` |
135 |
136 | #### MDMSpringTimingCurve
137 |
138 | *new* property: `tension` in `MDMSpringTimingCurve`
139 |
140 | *new* method: `-init` in `MDMSpringTimingCurve`
141 |
142 | *new* property: `friction` in `MDMSpringTimingCurve`
143 |
144 | *new* property: `initialVelocity` in `MDMSpringTimingCurve`
145 |
146 | *new* property: `mass` in `MDMSpringTimingCurve`
147 |
148 | *new* class: `MDMSpringTimingCurve`
149 |
150 | *new* method: `-initWithMass:tension:friction:` in `MDMSpringTimingCurve`
151 |
152 | *new* method: `-initWithMass:tension:friction:initialVelocity:` in `MDMSpringTimingCurve`
153 |
154 | #### MDMAnimationTraits
155 |
156 | *new* class: `MDMAnimationTraits`
157 |
158 | *new* property: `repetition` in `MDMAnimationTraits`
159 |
160 | *new* property: `delay` in `MDMAnimationTraits`
161 |
162 | *new* property: `duration` in `MDMAnimationTraits`
163 |
164 | *new* method: `-initWithDelay:duration:animationCurve:` in `MDMAnimationTraits`
165 |
166 | *new* method: `-initWithDelay:duration:timingCurve:repetition:` in `MDMAnimationTraits`
167 |
168 | *new* method: `-initWithDuration:animationCurve:` in `MDMAnimationTraits`
169 |
170 | *new* method: `-initWithDelay:duration:` in `MDMAnimationTraits`
171 |
172 | *new* method: `-init` in `MDMAnimationTraits`
173 |
174 | *new* method: `-initWithDelay:duration:timingCurve:` in `MDMAnimationTraits`
175 |
176 | *new* method: `-initWithDuration:` in `MDMAnimationTraits`
177 |
178 | *new* property: `timingCurve` in `MDMAnimationTraits`
179 |
180 | #### CAMediaTimingFunction(MotionInterchangeExtension)
181 |
182 | *new* method: `-mdm_reversed` in `CAMediaTimingFunction(MotionInterchangeExtension)`
183 |
184 | *new* property: `mdm_point1` in `CAMediaTimingFunction(MotionInterchangeExtension)`
185 |
186 | *new* category: `CAMediaTimingFunction(MotionInterchangeExtension)`
187 |
188 | *new* property: `mdm_point2` in `CAMediaTimingFunction(MotionInterchangeExtension)`
189 |
190 | #### MDMMotionCurveMakeSpring
191 |
192 | *modified* function: `MDMMotionCurveMakeSpring`
193 |
194 | | Type of change: | Swift declaration |
195 | |---|---|
196 | | From: | `func MotionCurveMakeSpring(mass: Float, tension: Float, friction: Float) -> MotionCurve` |
197 | | To: | `func MotionCurveMakeSpring(mass: CGFloat, tension: CGFloat, friction: CGFloat) -> MotionCurve` |
198 |
199 | *modified* function: `MDMMotionCurveMakeSpring`
200 |
201 | | Type of change: | Declaration |
202 | |---|---|
203 | | From: | `extern MDMMotionCurve MDMMotionCurveMakeSpring(float mass, float tension, float friction)` |
204 | | To: | `extern MDMMotionCurve MDMMotionCurveMakeSpring(CGFloat mass, CGFloat tension, CGFloat friction)` |
205 |
206 | #### MDMAnimationTraits(SystemTraits)
207 |
208 | *new* category: `MDMAnimationTraits(SystemTraits)`
209 |
210 | *new* property: `systemModalMovement` in `MDMAnimationTraits(SystemTraits)`
211 |
212 | #### MDMSpringTimingCurveGenerator
213 |
214 | *new* property: `initialVelocity` in `MDMSpringTimingCurveGenerator`
215 |
216 | *new* class: `MDMSpringTimingCurveGenerator`
217 |
218 | *new* method: `-init` in `MDMSpringTimingCurveGenerator`
219 |
220 | *new* method: `-initWithDuration:dampingRatio:initialVelocity:` in `MDMSpringTimingCurveGenerator`
221 |
222 | *new* property: `dampingRatio` in `MDMSpringTimingCurveGenerator`
223 |
224 | *new* method: `-springTimingCurve` in `MDMSpringTimingCurveGenerator`
225 |
226 | *new* method: `-initWithDuration:dampingRatio:` in `MDMSpringTimingCurveGenerator`
227 |
228 | *new* property: `duration` in `MDMSpringTimingCurveGenerator`
229 |
230 | #### MDMMotionCurveMakeBezier
231 |
232 | *modified* function: `MDMMotionCurveMakeBezier`
233 |
234 | | Type of change: | Swift declaration |
235 | |---|---|
236 | | From: | `func MotionCurveMakeBezier(p1x: Float, p1y: Float, p2x: Float, p2y: Float) -> MotionCurve` |
237 | | To: | `func MotionCurveMakeBezier(p1x: CGFloat, p1y: CGFloat, p2x: CGFloat, p2y: CGFloat) -> MotionCurve` |
238 |
239 | *modified* function: `MDMMotionCurveMakeBezier`
240 |
241 | | Type of change: | Declaration |
242 | |---|---|
243 | | From: | `extern MDMMotionCurve MDMMotionCurveMakeBezier(float p1x, float p1y, float p2x, float p2y)` |
244 | | To: | `extern MDMMotionCurve MDMMotionCurveMakeBezier(CGFloat p1x, CGFloat p1y, CGFloat p2x, CGFloat p2y)` |
245 |
246 | #### MDMRepetition
247 |
248 | *new* method: `-initWithNumberOfRepetitions:autoreverses:` in `MDMRepetition`
249 |
250 | *new* method: `-initWithNumberOfRepetitions:` in `MDMRepetition`
251 |
252 | *new* class: `MDMRepetition`
253 |
254 | *new* property: `numberOfRepetitions` in `MDMRepetition`
255 |
256 | *new* method: `-init` in `MDMRepetition`
257 |
258 | ## Non-source changes
259 |
260 | * [Update docs with new API.](https://github.com/material-motion/motion-interchange-objc/commit/c30d90457c7bf6901e684ba932a5dd3b8ecd5fe5) (Jeff Verkoeyen)
261 | * [Fixing travis builds.](https://github.com/material-motion/motion-interchange-objc/commit/a4301e2eb55594408452446b37dec9a13d93ca53) (Jeff Verkoeyen)
262 | * [Use http_archive instead of git_respository as per the bazel team's recommendations. (#29)](https://github.com/material-motion/motion-interchange-objc/commit/0730f1a905421f9a5d75e6015e1bf4d242a76988) (featherless)
263 | * [Remove unused header.](https://github.com/material-motion/motion-interchange-objc/commit/e8af0592da1aa244867089532381f6dbdd801a77) (Jeff Verkoeyen)
264 | * [Iterating on the usage docs.](https://github.com/material-motion/motion-interchange-objc/commit/dcca85ea152d83cbdcf88d74916a228f40c8c2e1) (Jeff Verkoeyen)
265 | * [Revert "Add todo configuration"](https://github.com/material-motion/motion-interchange-objc/commit/41588742c057d79a3a3a7338f867a9622d84e143) (Jeff Verkoeyen)
266 | * [Add todo configuration](https://github.com/material-motion/motion-interchange-objc/commit/d2e1450ac327ebfba49c7489375bd635e9cfc1bb) (featherless)
267 | * [Enable code coverage on travis](https://github.com/material-motion/motion-interchange-objc/commit/111d91ea2da6ee2a8acd73c89664f4b10b6232c1) (featherless)
268 | * [Run tests on Travis.](https://github.com/material-motion/motion-interchange-objc/commit/f56f8a7a75e93a087aadc0f0d5759be13fd43cb7) (Jeff Verkoeyen)
269 | * [Update README.md](https://github.com/material-motion/motion-interchange-objc/commit/3f9405eac1445d0f12cb4fad4ad0a89631ded920) (featherless)
270 | * [Fix minor typo.](https://github.com/material-motion/motion-interchange-objc/commit/671ab1d579fd1d1c228ec266396145bbaf70f996) (Jeff Verkoeyen)
271 | * [Initial pass at fleshing out the readme (#24)](https://github.com/material-motion/motion-interchange-objc/commit/4e0a2e7ad5f258bc450a9dde3281fa7c3752bae6) (featherless)
272 | * [Fix travis.](https://github.com/material-motion/motion-interchange-objc/commit/866ec18cf2353c2682f89d1350af57c05ce25839) (Jeff Verkoeyen)
273 | * [Add missing Info.plist. (#20)](https://github.com/material-motion/motion-interchange-objc/commit/0080128a6846d2eda8538cab260cbecbbe32b9a1) (Sylvain Defresne)
274 |
275 | # 1.4.0
276 |
277 | This minor release introduces new APIs for creating springs that have an initial velocity.
278 |
279 | ## New features
280 |
281 | Added new APIs for creating springs with initial velocity:
282 | `MDMMotionCurveMakeSpringWithInitialVelocity` and `_MDMSpringWithInitialVelocity`.
283 |
284 | ## Source changes
285 |
286 | * [Add new APIs for creating springs with initial velocity. (#19)](https://github.com/material-motion/motion-interchange-objc/commit/326180f9f5f99e7d5e9e23131de8c24abe2e1dbf) (featherless)
287 |
288 | ## API changes
289 |
290 | ### MDMMotionCurveMakeSpringWithInitialVelocity
291 |
292 | **new** function: `MDMMotionCurveMakeSpringWithInitialVelocity`
293 |
294 | ### _MDMSpringWithInitialVelocity
295 |
296 | **new** macro: `_MDMSpringWithInitialVelocity`
297 |
298 | ## Non-source changes
299 |
300 | * [Add sdk_frameworks dependencies to the BUILD file. (#18)](https://github.com/material-motion/motion-interchange-objc/commit/a601fb65166426bc708d84c0e29d89913c445d04) (featherless)
301 | * [Add jazzy yaml.](https://github.com/material-motion/motion-interchange-objc/commit/130e9760bbb8c0e2179f820cc14f1278c9465b84) (Jeff Verkoeyen)
302 |
303 | # 1.3.0
304 |
305 | This minor releases introduces new APIs for defining motion curves.
306 |
307 | ## New deprecations
308 |
309 | `MDMMotionCurveTypeDefault` is now deprecated. Use `MDMMotionCurveTypeBezier` instead.
310 |
311 | ## New features
312 |
313 | The new `MDMLinearMotionCurve` macro allows you to define linear easing curves in specs.
314 |
315 | Spring curve specs can now define initial velocity. This value can be read using the new
316 | `MDMSpringMotionCurveDataIndexInitialVelocity` enum value for `MDMSpringMotionCurveDataIndex`.
317 |
318 | ## Source changes
319 |
320 | * [Document and define the initial velocity parameter of spring curves (#17)](https://github.com/material-motion/motion-interchange-objc/commit/7eb5e2f79229c3b7cdada7b8df3e1e66b7e229e5) (featherless)
321 | * [Add a linear curve constant. (#16)](https://github.com/material-motion/motion-interchange-objc/commit/0aa4f8caff7314310c3cbd721814305ee6f53601) (featherless)
322 | * [Deprecate MDMMotionCurveTypeDefault in favor of MDMMotionCurveTypeBezier. (#15)](https://github.com/material-motion/motion-interchange-objc/commit/f5a7f3b4a63d4643700403930e2cafd7d4482013) (featherless)
323 |
324 | ## API changes
325 |
326 | ### MDMSpringMotionCurveDataIndexInitialVelocity
327 |
328 | **new** enum: `MDMSpringMotionCurveDataIndexInitialVelocity`.
329 |
330 | ### MDMLinearMotionCurve
331 |
332 | **new** constant/macro: `MDMLinearMotionCurve`.
333 |
334 | # 1.2.0
335 |
336 | This minor release introduces a new API for reversing cubic beziers and a unit test for
337 | `MDMModalMovementTiming`.
338 |
339 | ## New features
340 |
341 | `MDMMotionCurveReversedBezier` reverses cubic bezier curves. Intended for use when building mirrored
342 | bi-directional transitions.
343 |
344 | ## Source changes
345 |
346 | * [Add a unit test for MDMModalMovementTiming. (#12)](https://github.com/material-motion/motion-interchange-objc/commit/a0c3566ad52a45365657e0591701afa7989eb822) (featherless)
347 | * [Add MDMMotionCurveReversed for reversing timing curves. (#11)](https://github.com/material-motion/motion-interchange-objc/commit/a54a5ffa49052a198b4bb5beedce737bb61ebc91) (featherless)
348 |
349 | ## API changes
350 |
351 | ### MDMMotionCurveReversedBezier
352 |
353 | **new** function: `MDMMotionCurveReversedBezier`.
354 |
355 | ## Non-source changes
356 |
357 | * [Standardize the kokoro and bazel files. (#13)](https://github.com/material-motion/motion-interchange-objc/commit/a009d3f7d08d8b2d087891a86eb1e298714198b4) (featherless)
358 | * [Use the v1.0.0 tag for bazel_ios_warnings. (#10)](https://github.com/material-motion/motion-interchange-objc/commit/545b6a448ddb235279318dc262f051d653a48ed4) (featherless)
359 |
360 | # 1.1.1
361 |
362 | This patch release migrates the project's continuous integration pipeline from arc to bazel and
363 | kokoro.
364 |
365 | ## New features
366 |
367 | Continuous integration can now be run locally by executing `./.kokoro` from the root of the git
368 | repo. Requires [bazel](http://bazel.io/).
369 |
370 | ## Source changes
371 |
372 | * [Replace arc with bazel and Kokoro continuous integration. (#9)](https://github.com/material-motion/motion-interchange-objc/commit/2ef4dfbf95a7beb3f0e323e259576b6797420202) (featherless)
373 | * [Fix warning in unit tests. (#8)](https://github.com/material-motion/motion-interchange-objc/commit/d3203a2857648f74d478525514c0f10cb6552b19) (featherless)
374 | * [Add missing import.](https://github.com/material-motion/motion-interchange-objc/commit/445091dbbd68cd0a75e4dd86195cb431b0717e71) (Jeff Verkoeyen)
375 |
376 | # 1.1.0
377 |
378 | This minor release introduces two new APIs for working with timing curves.
379 |
380 | ## New features
381 |
382 | - `MDMMotionCurveFromTimingFunction` can create a timing curve from a `CAMediaTimingFunction`.
383 | - `MDMModalMovementTiming` is the iOS timing curve for modal presentation movement.
384 |
385 | ## Source changes
386 |
387 | * [Add MDMMotionCurveFromTimingFunction for creating motion curves from timing functions. (#7)](https://github.com/material-motion/motion-interchange-objc/commit/5e9837cb453f354609f574e42c3c7cf69d4e2796) (featherless)
388 | * [Add system timing constant for movement during modal presentation. (#4)](https://github.com/material-motion/motion-interchange-objc/commit/bf757fe5dac65f9e76778d57988689b908a6c69b) (featherless)
389 |
390 | ## API changes
391 |
392 | *new* function: `MDMMotionCurveFromTimingFunction`.
393 |
394 | *new* macro: `MDMModalMovementTiming`.
395 |
396 | ## Non-source changes
397 |
398 | * [Update Xcode project settings.](https://github.com/material-motion/motion-interchange-objc/commit/d932efd547276084a09334f38595a3f8da28205d) (Jeff Verkoeyen)
399 | * [Update Podfile.lock.](https://github.com/material-motion/motion-interchange-objc/commit/07f701eb6918752c29f381a028080c5c12511474) (Jeff Verkoeyen)
400 |
401 | # 1.0.1
402 |
403 | Added a missing framework header for Objective-C support.
404 |
405 | ## Source changes
406 |
407 | * [Add missing framework header.](https://github.com/material-motion/motion-interchange-objc/commit/03a9b2592e805f06eb622238d7ce8ad7e6f56e90) (Jeff Verkoeyen)
408 |
409 | ## Non-source changes
410 |
411 | * [Fix links in readme.](https://github.com/material-motion/motion-interchange-objc/commit/a438194edb51214fca13955fc2badcd93f587ec5) (Jeff Verkoeyen)
412 |
413 | # 1.0.0
414 |
415 | Initial release.
416 |
417 | Includes MotionTiming structure for representing cubic bezier and spring animations.
418 |
419 | ## Source changes
420 |
421 | * [Initial commit of motion interchange format. (#1)](https://github.com/material-motion/motion-interchange-objc/commit/e1d882b11f1ecdd3edf5c8746c8d243939ea097a) (featherless)
422 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | Want to contribute? Great! First, read this page (including the small print at
2 | the end).
3 |
4 | ### Before you contribute
5 |
6 | Before we can use your code, you must sign the
7 | [Google Individual Contributor License Agreement]
8 | (https://cla.developers.google.com/about/google-individual)
9 | (CLA), which you can do online. The CLA is necessary mainly because you own the
10 | copyright to your changes, even after your contribution becomes part of our
11 | codebase, so we need your permission to use and distribute your code. We also
12 | need to be sure of various other things—for instance that you'll tell us if you
13 | know that your code infringes on other people's patents. You don't have to sign
14 | the CLA until after you've submitted your code for review and a member has
15 | approved it, but you must do it before we can put your code into our codebase.
16 | Before you start working on a larger contribution, you should get in touch with
17 | us first through the issue tracker with your idea so that we can help out and
18 | possibly guide you. Coordinating up front makes it much easier to avoid
19 | frustration later on.
20 |
21 | ### Code reviews
22 |
23 | All submissions, including submissions by project members, require review.
24 | We use GitHub pull requests for this purpose.
25 |
26 | ### The small print
27 |
28 | Contributions made by corporations are covered by a different agreement than
29 | the one above, the
30 | [Software Grant and Corporate Contributor License Agreement]
31 | (https://cla.developers.google.com/about/google-corporate).
32 |
--------------------------------------------------------------------------------
/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
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 | 3.0.0
19 | CFBundleVersion
20 | $(CURRENT_PROJECT_VERSION)
21 |
22 |
23 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 |
2 | Apache License
3 | Version 2.0, January 2004
4 | http://www.apache.org/licenses/
5 |
6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7 |
8 | 1. Definitions.
9 |
10 | "License" shall mean the terms and conditions for use, reproduction,
11 | and distribution as defined by Sections 1 through 9 of this document.
12 |
13 | "Licensor" shall mean the copyright owner or entity authorized by
14 | the copyright owner that is granting the License.
15 |
16 | "Legal Entity" shall mean the union of the acting entity and all
17 | other entities that control, are controlled by, or are under common
18 | control with that entity. For the purposes of this definition,
19 | "control" means (i) the power, direct or indirect, to cause the
20 | direction or management of such entity, whether by contract or
21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
22 | outstanding shares, or (iii) beneficial ownership of such entity.
23 |
24 | "You" (or "Your") shall mean an individual or Legal Entity
25 | exercising permissions granted by this License.
26 |
27 | "Source" form shall mean the preferred form for making modifications,
28 | including but not limited to software source code, documentation
29 | source, and configuration files.
30 |
31 | "Object" form shall mean any form resulting from mechanical
32 | transformation or translation of a Source form, including but
33 | not limited to compiled object code, generated documentation,
34 | and conversions to other media types.
35 |
36 | "Work" shall mean the work of authorship, whether in Source or
37 | Object form, made available under the License, as indicated by a
38 | copyright notice that is included in or attached to the work
39 | (an example is provided in the Appendix below).
40 |
41 | "Derivative Works" shall mean any work, whether in Source or Object
42 | form, that is based on (or derived from) the Work and for which the
43 | editorial revisions, annotations, elaborations, or other modifications
44 | represent, as a whole, an original work of authorship. For the purposes
45 | of this License, Derivative Works shall not include works that remain
46 | separable from, or merely link (or bind by name) to the interfaces of,
47 | the Work and Derivative Works thereof.
48 |
49 | "Contribution" shall mean any work of authorship, including
50 | the original version of the Work and any modifications or additions
51 | to that Work or Derivative Works thereof, that is intentionally
52 | submitted to Licensor for inclusion in the Work by the copyright owner
53 | or by an individual or Legal Entity authorized to submit on behalf of
54 | the copyright owner. For the purposes of this definition, "submitted"
55 | means any form of electronic, verbal, or written communication sent
56 | to the Licensor or its representatives, including but not limited to
57 | communication on electronic mailing lists, source code control systems,
58 | and issue tracking systems that are managed by, or on behalf of, the
59 | Licensor for the purpose of discussing and improving the Work, but
60 | excluding communication that is conspicuously marked or otherwise
61 | designated in writing by the copyright owner as "Not a Contribution."
62 |
63 | "Contributor" shall mean Licensor and any individual or Legal Entity
64 | on behalf of whom a Contribution has been received by Licensor and
65 | subsequently incorporated within the Work.
66 |
67 | 2. Grant of Copyright License. Subject to the terms and conditions of
68 | this License, each Contributor hereby grants to You a perpetual,
69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70 | copyright license to reproduce, prepare Derivative Works of,
71 | publicly display, publicly perform, sublicense, and distribute the
72 | Work and such Derivative Works in Source or Object form.
73 |
74 | 3. Grant of Patent License. Subject to the terms and conditions of
75 | this License, each Contributor hereby grants to You a perpetual,
76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77 | (except as stated in this section) patent license to make, have made,
78 | use, offer to sell, sell, import, and otherwise transfer the Work,
79 | where such license applies only to those patent claims licensable
80 | by such Contributor that are necessarily infringed by their
81 | Contribution(s) alone or by combination of their Contribution(s)
82 | with the Work to which such Contribution(s) was submitted. If You
83 | institute patent litigation against any entity (including a
84 | cross-claim or counterclaim in a lawsuit) alleging that the Work
85 | or a Contribution incorporated within the Work constitutes direct
86 | or contributory patent infringement, then any patent licenses
87 | granted to You under this License for that Work shall terminate
88 | as of the date such litigation is filed.
89 |
90 | 4. Redistribution. You may reproduce and distribute copies of the
91 | Work or Derivative Works thereof in any medium, with or without
92 | modifications, and in Source or Object form, provided that You
93 | meet the following conditions:
94 |
95 | (a) You must give any other recipients of the Work or
96 | Derivative Works a copy of this License; and
97 |
98 | (b) You must cause any modified files to carry prominent notices
99 | stating that You changed the files; and
100 |
101 | (c) You must retain, in the Source form of any Derivative Works
102 | that You distribute, all copyright, patent, trademark, and
103 | attribution notices from the Source form of the Work,
104 | excluding those notices that do not pertain to any part of
105 | the Derivative Works; and
106 |
107 | (d) If the Work includes a "NOTICE" text file as part of its
108 | distribution, then any Derivative Works that You distribute must
109 | include a readable copy of the attribution notices contained
110 | within such NOTICE file, excluding those notices that do not
111 | pertain to any part of the Derivative Works, in at least one
112 | of the following places: within a NOTICE text file distributed
113 | as part of the Derivative Works; within the Source form or
114 | documentation, if provided along with the Derivative Works; or,
115 | within a display generated by the Derivative Works, if and
116 | wherever such third-party notices normally appear. The contents
117 | of the NOTICE file are for informational purposes only and
118 | do not modify the License. You may add Your own attribution
119 | notices within Derivative Works that You distribute, alongside
120 | or as an addendum to the NOTICE text from the Work, provided
121 | that such additional attribution notices cannot be construed
122 | as modifying the License.
123 |
124 | You may add Your own copyright statement to Your modifications and
125 | may provide additional or different license terms and conditions
126 | for use, reproduction, or distribution of Your modifications, or
127 | for any such Derivative Works as a whole, provided Your use,
128 | reproduction, and distribution of the Work otherwise complies with
129 | the conditions stated in this License.
130 |
131 | 5. Submission of Contributions. Unless You explicitly state otherwise,
132 | any Contribution intentionally submitted for inclusion in the Work
133 | by You to the Licensor shall be under the terms and conditions of
134 | this License, without any additional terms or conditions.
135 | Notwithstanding the above, nothing herein shall supersede or modify
136 | the terms of any separate license agreement you may have executed
137 | with Licensor regarding such Contributions.
138 |
139 | 6. Trademarks. This License does not grant permission to use the trade
140 | names, trademarks, service marks, or product names of the Licensor,
141 | except as required for reasonable and customary use in describing the
142 | origin of the Work and reproducing the content of the NOTICE file.
143 |
144 | 7. Disclaimer of Warranty. Unless required by applicable law or
145 | agreed to in writing, Licensor provides the Work (and each
146 | Contributor provides its Contributions) on an "AS IS" BASIS,
147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148 | implied, including, without limitation, any warranties or conditions
149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150 | PARTICULAR PURPOSE. You are solely responsible for determining the
151 | appropriateness of using or redistributing the Work and assume any
152 | risks associated with Your exercise of permissions under this License.
153 |
154 | 8. Limitation of Liability. In no event and under no legal theory,
155 | whether in tort (including negligence), contract, or otherwise,
156 | unless required by applicable law (such as deliberate and grossly
157 | negligent acts) or agreed to in writing, shall any Contributor be
158 | liable to You for damages, including any direct, indirect, special,
159 | incidental, or consequential damages of any character arising as a
160 | result of this License or out of the use or inability to use the
161 | Work (including but not limited to damages for loss of goodwill,
162 | work stoppage, computer failure or malfunction, or any and all
163 | other commercial damages or losses), even if such Contributor
164 | has been advised of the possibility of such damages.
165 |
166 | 9. Accepting Warranty or Additional Liability. While redistributing
167 | the Work or Derivative Works thereof, You may choose to offer,
168 | and charge a fee for, acceptance of support, warranty, indemnity,
169 | or other liability obligations and/or rights consistent with this
170 | License. However, in accepting such obligations, You may act only
171 | on Your own behalf and on Your sole responsibility, not on behalf
172 | of any other Contributor, and only if You agree to indemnify,
173 | defend, and hold each Contributor harmless for any liability
174 | incurred by, or claims asserted against, such Contributor by reason
175 | of your accepting any such warranty or additional liability.
176 |
177 | END OF TERMS AND CONDITIONS
178 |
179 | APPENDIX: How to apply the Apache License to your work.
180 |
181 | To apply the Apache License to your work, attach the following
182 | boilerplate notice, with the fields enclosed by brackets "[]"
183 | replaced with your own identifying information. (Don't include
184 | the brackets!) The text should be enclosed in the appropriate
185 | comment syntax for the file format. We also recommend that a
186 | file or class name and description of purpose be included on the
187 | same "printed page" as the copyright notice for easier
188 | identification within third-party archives.
189 |
190 | Copyright [yyyy] [name of copyright owner]
191 |
192 | Licensed under the Apache License, Version 2.0 (the "License");
193 | you may not use this file except in compliance with the License.
194 | You may obtain a copy of the License at
195 |
196 | http://www.apache.org/licenses/LICENSE-2.0
197 |
198 | Unless required by applicable law or agreed to in writing, software
199 | distributed under the License is distributed on an "AS IS" BASIS,
200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201 | See the License for the specific language governing permissions and
202 | limitations under the License.
203 |
--------------------------------------------------------------------------------
/MotionInterchange.podspec:
--------------------------------------------------------------------------------
1 | Pod::Spec.new do |s|
2 | s.name = "MotionInterchange"
3 | s.summary = "Motion interchange format."
4 | s.version = "4.0.1"
5 | s.authors = "The Material Motion Authors"
6 | s.license = "Apache 2.0"
7 | s.homepage = "https://github.com/material-motion/motion-interchange-objc"
8 | s.source = { :git => "https://github.com/material-motion/motion-interchange-objc.git", :tag => "v" + s.version.to_s }
9 | s.platform = :ios, "10.0"
10 | s.requires_arc = true
11 |
12 | s.public_header_files = "src/*.h"
13 | s.source_files = "src/*.{h,m,mm}", "src/private/*.{h,m,mm}"
14 | end
15 |
--------------------------------------------------------------------------------
/MotionInterchange.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 50;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 6DC6507322388CE7003DBBF5 /* MDMRepetitionTraits.h in Headers */ = {isa = PBXBuildFile; fileRef = 6DC6505F22388CE7003DBBF5 /* MDMRepetitionTraits.h */; settings = {ATTRIBUTES = (Public, ); }; };
11 | 6DC6507422388CE7003DBBF5 /* MDMRepetitionOverTime.m in Sources */ = {isa = PBXBuildFile; fileRef = 6DC6506022388CE7003DBBF5 /* MDMRepetitionOverTime.m */; };
12 | 6DC6507522388CE7003DBBF5 /* MDMMotionCurve.m in Sources */ = {isa = PBXBuildFile; fileRef = 6DC6506122388CE7003DBBF5 /* MDMMotionCurve.m */; };
13 | 6DC6507622388CE7003DBBF5 /* CAMediaTimingFunction+MDMTimingCurve.m in Sources */ = {isa = PBXBuildFile; fileRef = 6DC6506222388CE7003DBBF5 /* CAMediaTimingFunction+MDMTimingCurve.m */; };
14 | 6DC6507722388CE7003DBBF5 /* MotionInterchange.h in Headers */ = {isa = PBXBuildFile; fileRef = 6DC6506322388CE7003DBBF5 /* MotionInterchange.h */; settings = {ATTRIBUTES = (Public, ); }; };
15 | 6DC6507822388CE7003DBBF5 /* MDMSpringTimingCurveGenerator.m in Sources */ = {isa = PBXBuildFile; fileRef = 6DC6506422388CE7003DBBF5 /* MDMSpringTimingCurveGenerator.m */; };
16 | 6DC6507922388CE7003DBBF5 /* MDMSubclassingRestricted.h in Headers */ = {isa = PBXBuildFile; fileRef = 6DC6506522388CE7003DBBF5 /* MDMSubclassingRestricted.h */; settings = {ATTRIBUTES = (Public, ); }; };
17 | 6DC6507A22388CE7003DBBF5 /* MDMRepetition.m in Sources */ = {isa = PBXBuildFile; fileRef = 6DC6506622388CE7003DBBF5 /* MDMRepetition.m */; };
18 | 6DC6507B22388CE7003DBBF5 /* MDMAnimationTraits.m in Sources */ = {isa = PBXBuildFile; fileRef = 6DC6506722388CE7003DBBF5 /* MDMAnimationTraits.m */; };
19 | 6DC6507C22388CE7003DBBF5 /* MDMSpringTimingCurve.m in Sources */ = {isa = PBXBuildFile; fileRef = 6DC6506822388CE7003DBBF5 /* MDMSpringTimingCurve.m */; };
20 | 6DC6507D22388CE7003DBBF5 /* MDMMotionTiming.h in Headers */ = {isa = PBXBuildFile; fileRef = 6DC6506922388CE7003DBBF5 /* MDMMotionTiming.h */; settings = {ATTRIBUTES = (Public, ); }; };
21 | 6DC6507E22388CE7003DBBF5 /* MDMRepetitionOverTime.h in Headers */ = {isa = PBXBuildFile; fileRef = 6DC6506A22388CE7003DBBF5 /* MDMRepetitionOverTime.h */; settings = {ATTRIBUTES = (Public, ); }; };
22 | 6DC6507F22388CE7003DBBF5 /* MDMMotionCurve.h in Headers */ = {isa = PBXBuildFile; fileRef = 6DC6506B22388CE7003DBBF5 /* MDMMotionCurve.h */; settings = {ATTRIBUTES = (Public, ); }; };
23 | 6DC6508022388CE7003DBBF5 /* MDMTimingCurve.h in Headers */ = {isa = PBXBuildFile; fileRef = 6DC6506C22388CE7003DBBF5 /* MDMTimingCurve.h */; settings = {ATTRIBUTES = (Public, ); }; };
24 | 6DC6508122388CE7003DBBF5 /* MDMSpringTimingCurveGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = 6DC6506D22388CE7003DBBF5 /* MDMSpringTimingCurveGenerator.h */; settings = {ATTRIBUTES = (Public, ); }; };
25 | 6DC6508222388CE7003DBBF5 /* CAMediaTimingFunction+MDMTimingCurve.h in Headers */ = {isa = PBXBuildFile; fileRef = 6DC6506E22388CE7003DBBF5 /* CAMediaTimingFunction+MDMTimingCurve.h */; settings = {ATTRIBUTES = (Public, ); }; };
26 | 6DC6508322388CE7003DBBF5 /* MDMSpringTimingCurve.h in Headers */ = {isa = PBXBuildFile; fileRef = 6DC6506F22388CE7003DBBF5 /* MDMSpringTimingCurve.h */; settings = {ATTRIBUTES = (Public, ); }; };
27 | 6DC6508422388CE7003DBBF5 /* MDMAnimationTraits.h in Headers */ = {isa = PBXBuildFile; fileRef = 6DC6507022388CE7003DBBF5 /* MDMAnimationTraits.h */; settings = {ATTRIBUTES = (Public, ); }; };
28 | 6DC6508522388CE7003DBBF5 /* MDMRepetition.h in Headers */ = {isa = PBXBuildFile; fileRef = 6DC6507122388CE7003DBBF5 /* MDMRepetition.h */; settings = {ATTRIBUTES = (Public, ); }; };
29 | 6DC6508622388CE7003DBBF5 /* MDMMotionRepetition.h in Headers */ = {isa = PBXBuildFile; fileRef = 6DC6507222388CE7003DBBF5 /* MDMMotionRepetition.h */; settings = {ATTRIBUTES = (Public, ); }; };
30 | /* End PBXBuildFile section */
31 |
32 | /* Begin PBXFileReference section */
33 | 6DC6505322388CA7003DBBF5 /* MotionInterchange.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = MotionInterchange.framework; sourceTree = BUILT_PRODUCTS_DIR; };
34 | 6DC6505F22388CE7003DBBF5 /* MDMRepetitionTraits.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MDMRepetitionTraits.h; sourceTree = ""; };
35 | 6DC6506022388CE7003DBBF5 /* MDMRepetitionOverTime.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MDMRepetitionOverTime.m; sourceTree = ""; };
36 | 6DC6506122388CE7003DBBF5 /* MDMMotionCurve.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MDMMotionCurve.m; sourceTree = ""; };
37 | 6DC6506222388CE7003DBBF5 /* CAMediaTimingFunction+MDMTimingCurve.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "CAMediaTimingFunction+MDMTimingCurve.m"; sourceTree = ""; };
38 | 6DC6506322388CE7003DBBF5 /* MotionInterchange.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MotionInterchange.h; sourceTree = ""; };
39 | 6DC6506422388CE7003DBBF5 /* MDMSpringTimingCurveGenerator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MDMSpringTimingCurveGenerator.m; sourceTree = ""; };
40 | 6DC6506522388CE7003DBBF5 /* MDMSubclassingRestricted.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MDMSubclassingRestricted.h; sourceTree = ""; };
41 | 6DC6506622388CE7003DBBF5 /* MDMRepetition.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MDMRepetition.m; sourceTree = ""; };
42 | 6DC6506722388CE7003DBBF5 /* MDMAnimationTraits.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MDMAnimationTraits.m; sourceTree = ""; };
43 | 6DC6506822388CE7003DBBF5 /* MDMSpringTimingCurve.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MDMSpringTimingCurve.m; sourceTree = ""; };
44 | 6DC6506922388CE7003DBBF5 /* MDMMotionTiming.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MDMMotionTiming.h; sourceTree = ""; };
45 | 6DC6506A22388CE7003DBBF5 /* MDMRepetitionOverTime.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MDMRepetitionOverTime.h; sourceTree = ""; };
46 | 6DC6506B22388CE7003DBBF5 /* MDMMotionCurve.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MDMMotionCurve.h; sourceTree = ""; };
47 | 6DC6506C22388CE7003DBBF5 /* MDMTimingCurve.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MDMTimingCurve.h; sourceTree = ""; };
48 | 6DC6506D22388CE7003DBBF5 /* MDMSpringTimingCurveGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MDMSpringTimingCurveGenerator.h; sourceTree = ""; };
49 | 6DC6506E22388CE7003DBBF5 /* CAMediaTimingFunction+MDMTimingCurve.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "CAMediaTimingFunction+MDMTimingCurve.h"; sourceTree = ""; };
50 | 6DC6506F22388CE7003DBBF5 /* MDMSpringTimingCurve.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MDMSpringTimingCurve.h; sourceTree = ""; };
51 | 6DC6507022388CE7003DBBF5 /* MDMAnimationTraits.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MDMAnimationTraits.h; sourceTree = ""; };
52 | 6DC6507122388CE7003DBBF5 /* MDMRepetition.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MDMRepetition.h; sourceTree = ""; };
53 | 6DC6507222388CE7003DBBF5 /* MDMMotionRepetition.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MDMMotionRepetition.h; sourceTree = ""; };
54 | 6DC6508722388CFA003DBBF5 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = SOURCE_ROOT; };
55 | /* End PBXFileReference section */
56 |
57 | /* Begin PBXFrameworksBuildPhase section */
58 | 6DC6505022388CA7003DBBF5 /* Frameworks */ = {
59 | isa = PBXFrameworksBuildPhase;
60 | buildActionMask = 2147483647;
61 | files = (
62 | );
63 | runOnlyForDeploymentPostprocessing = 0;
64 | };
65 | /* End PBXFrameworksBuildPhase section */
66 |
67 | /* Begin PBXGroup section */
68 | 6DC6504922388CA7003DBBF5 = {
69 | isa = PBXGroup;
70 | children = (
71 | 6DC6505E22388CE7003DBBF5 /* src */,
72 | 6DC6505422388CA7003DBBF5 /* Products */,
73 | );
74 | sourceTree = "";
75 | };
76 | 6DC6505422388CA7003DBBF5 /* Products */ = {
77 | isa = PBXGroup;
78 | children = (
79 | 6DC6505322388CA7003DBBF5 /* MotionInterchange.framework */,
80 | );
81 | name = Products;
82 | sourceTree = "";
83 | };
84 | 6DC6505E22388CE7003DBBF5 /* src */ = {
85 | isa = PBXGroup;
86 | children = (
87 | 6DC6508722388CFA003DBBF5 /* Info.plist */,
88 | 6DC6506E22388CE7003DBBF5 /* CAMediaTimingFunction+MDMTimingCurve.h */,
89 | 6DC6506222388CE7003DBBF5 /* CAMediaTimingFunction+MDMTimingCurve.m */,
90 | 6DC6507022388CE7003DBBF5 /* MDMAnimationTraits.h */,
91 | 6DC6506722388CE7003DBBF5 /* MDMAnimationTraits.m */,
92 | 6DC6506B22388CE7003DBBF5 /* MDMMotionCurve.h */,
93 | 6DC6506122388CE7003DBBF5 /* MDMMotionCurve.m */,
94 | 6DC6507222388CE7003DBBF5 /* MDMMotionRepetition.h */,
95 | 6DC6506922388CE7003DBBF5 /* MDMMotionTiming.h */,
96 | 6DC6507122388CE7003DBBF5 /* MDMRepetition.h */,
97 | 6DC6506622388CE7003DBBF5 /* MDMRepetition.m */,
98 | 6DC6506A22388CE7003DBBF5 /* MDMRepetitionOverTime.h */,
99 | 6DC6506022388CE7003DBBF5 /* MDMRepetitionOverTime.m */,
100 | 6DC6505F22388CE7003DBBF5 /* MDMRepetitionTraits.h */,
101 | 6DC6506F22388CE7003DBBF5 /* MDMSpringTimingCurve.h */,
102 | 6DC6506822388CE7003DBBF5 /* MDMSpringTimingCurve.m */,
103 | 6DC6506D22388CE7003DBBF5 /* MDMSpringTimingCurveGenerator.h */,
104 | 6DC6506422388CE7003DBBF5 /* MDMSpringTimingCurveGenerator.m */,
105 | 6DC6506522388CE7003DBBF5 /* MDMSubclassingRestricted.h */,
106 | 6DC6506C22388CE7003DBBF5 /* MDMTimingCurve.h */,
107 | 6DC6506322388CE7003DBBF5 /* MotionInterchange.h */,
108 | );
109 | path = src;
110 | sourceTree = "";
111 | };
112 | /* End PBXGroup section */
113 |
114 | /* Begin PBXHeadersBuildPhase section */
115 | 6DC6504E22388CA7003DBBF5 /* Headers */ = {
116 | isa = PBXHeadersBuildPhase;
117 | buildActionMask = 2147483647;
118 | files = (
119 | 6DC6508322388CE7003DBBF5 /* MDMSpringTimingCurve.h in Headers */,
120 | 6DC6507322388CE7003DBBF5 /* MDMRepetitionTraits.h in Headers */,
121 | 6DC6508522388CE7003DBBF5 /* MDMRepetition.h in Headers */,
122 | 6DC6508022388CE7003DBBF5 /* MDMTimingCurve.h in Headers */,
123 | 6DC6508122388CE7003DBBF5 /* MDMSpringTimingCurveGenerator.h in Headers */,
124 | 6DC6508622388CE7003DBBF5 /* MDMMotionRepetition.h in Headers */,
125 | 6DC6507F22388CE7003DBBF5 /* MDMMotionCurve.h in Headers */,
126 | 6DC6508222388CE7003DBBF5 /* CAMediaTimingFunction+MDMTimingCurve.h in Headers */,
127 | 6DC6507722388CE7003DBBF5 /* MotionInterchange.h in Headers */,
128 | 6DC6507922388CE7003DBBF5 /* MDMSubclassingRestricted.h in Headers */,
129 | 6DC6507E22388CE7003DBBF5 /* MDMRepetitionOverTime.h in Headers */,
130 | 6DC6507D22388CE7003DBBF5 /* MDMMotionTiming.h in Headers */,
131 | 6DC6508422388CE7003DBBF5 /* MDMAnimationTraits.h in Headers */,
132 | );
133 | runOnlyForDeploymentPostprocessing = 0;
134 | };
135 | /* End PBXHeadersBuildPhase section */
136 |
137 | /* Begin PBXNativeTarget section */
138 | 6DC6505222388CA7003DBBF5 /* MotionInterchange */ = {
139 | isa = PBXNativeTarget;
140 | buildConfigurationList = 6DC6505B22388CA7003DBBF5 /* Build configuration list for PBXNativeTarget "MotionInterchange" */;
141 | buildPhases = (
142 | 6DC6504E22388CA7003DBBF5 /* Headers */,
143 | 6DC6504F22388CA7003DBBF5 /* Sources */,
144 | 6DC6505022388CA7003DBBF5 /* Frameworks */,
145 | 6DC6505122388CA7003DBBF5 /* Resources */,
146 | );
147 | buildRules = (
148 | );
149 | dependencies = (
150 | );
151 | name = MotionInterchange;
152 | productName = MotionInterchange;
153 | productReference = 6DC6505322388CA7003DBBF5 /* MotionInterchange.framework */;
154 | productType = "com.apple.product-type.framework";
155 | };
156 | /* End PBXNativeTarget section */
157 |
158 | /* Begin PBXProject section */
159 | 6DC6504A22388CA7003DBBF5 /* Project object */ = {
160 | isa = PBXProject;
161 | attributes = {
162 | LastUpgradeCheck = 1010;
163 | ORGANIZATIONNAME = "The Material Motion Authors";
164 | TargetAttributes = {
165 | 6DC6505222388CA7003DBBF5 = {
166 | CreatedOnToolsVersion = 10.1;
167 | };
168 | };
169 | };
170 | buildConfigurationList = 6DC6504D22388CA7003DBBF5 /* Build configuration list for PBXProject "MotionInterchange" */;
171 | compatibilityVersion = "Xcode 9.3";
172 | developmentRegion = en;
173 | hasScannedForEncodings = 0;
174 | knownRegions = (
175 | en,
176 | );
177 | mainGroup = 6DC6504922388CA7003DBBF5;
178 | productRefGroup = 6DC6505422388CA7003DBBF5 /* Products */;
179 | projectDirPath = "";
180 | projectRoot = "";
181 | targets = (
182 | 6DC6505222388CA7003DBBF5 /* MotionInterchange */,
183 | );
184 | };
185 | /* End PBXProject section */
186 |
187 | /* Begin PBXResourcesBuildPhase section */
188 | 6DC6505122388CA7003DBBF5 /* Resources */ = {
189 | isa = PBXResourcesBuildPhase;
190 | buildActionMask = 2147483647;
191 | files = (
192 | );
193 | runOnlyForDeploymentPostprocessing = 0;
194 | };
195 | /* End PBXResourcesBuildPhase section */
196 |
197 | /* Begin PBXSourcesBuildPhase section */
198 | 6DC6504F22388CA7003DBBF5 /* Sources */ = {
199 | isa = PBXSourcesBuildPhase;
200 | buildActionMask = 2147483647;
201 | files = (
202 | 6DC6507B22388CE7003DBBF5 /* MDMAnimationTraits.m in Sources */,
203 | 6DC6507522388CE7003DBBF5 /* MDMMotionCurve.m in Sources */,
204 | 6DC6507422388CE7003DBBF5 /* MDMRepetitionOverTime.m in Sources */,
205 | 6DC6507C22388CE7003DBBF5 /* MDMSpringTimingCurve.m in Sources */,
206 | 6DC6507622388CE7003DBBF5 /* CAMediaTimingFunction+MDMTimingCurve.m in Sources */,
207 | 6DC6507822388CE7003DBBF5 /* MDMSpringTimingCurveGenerator.m in Sources */,
208 | 6DC6507A22388CE7003DBBF5 /* MDMRepetition.m in Sources */,
209 | );
210 | runOnlyForDeploymentPostprocessing = 0;
211 | };
212 | /* End PBXSourcesBuildPhase section */
213 |
214 | /* Begin XCBuildConfiguration section */
215 | 6DC6505922388CA7003DBBF5 /* Debug */ = {
216 | isa = XCBuildConfiguration;
217 | buildSettings = {
218 | ALWAYS_SEARCH_USER_PATHS = NO;
219 | CLANG_ANALYZER_NONNULL = YES;
220 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
221 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
222 | CLANG_CXX_LIBRARY = "libc++";
223 | CLANG_ENABLE_MODULES = YES;
224 | CLANG_ENABLE_OBJC_ARC = YES;
225 | CLANG_ENABLE_OBJC_WEAK = YES;
226 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
227 | CLANG_WARN_BOOL_CONVERSION = YES;
228 | CLANG_WARN_COMMA = YES;
229 | CLANG_WARN_CONSTANT_CONVERSION = YES;
230 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
231 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
232 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
233 | CLANG_WARN_EMPTY_BODY = YES;
234 | CLANG_WARN_ENUM_CONVERSION = YES;
235 | CLANG_WARN_INFINITE_RECURSION = YES;
236 | CLANG_WARN_INT_CONVERSION = YES;
237 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
238 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
239 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
240 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
241 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
242 | CLANG_WARN_STRICT_PROTOTYPES = YES;
243 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
244 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
245 | CLANG_WARN_UNREACHABLE_CODE = YES;
246 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
247 | CODE_SIGN_IDENTITY = "iPhone Developer";
248 | COPY_PHASE_STRIP = NO;
249 | CURRENT_PROJECT_VERSION = 1;
250 | DEBUG_INFORMATION_FORMAT = dwarf;
251 | ENABLE_STRICT_OBJC_MSGSEND = YES;
252 | ENABLE_TESTABILITY = YES;
253 | GCC_C_LANGUAGE_STANDARD = gnu11;
254 | GCC_DYNAMIC_NO_PIC = NO;
255 | GCC_NO_COMMON_BLOCKS = YES;
256 | GCC_OPTIMIZATION_LEVEL = 0;
257 | GCC_PREPROCESSOR_DEFINITIONS = (
258 | "DEBUG=1",
259 | "$(inherited)",
260 | );
261 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
262 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
263 | GCC_WARN_UNDECLARED_SELECTOR = YES;
264 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
265 | GCC_WARN_UNUSED_FUNCTION = YES;
266 | GCC_WARN_UNUSED_VARIABLE = YES;
267 | IPHONEOS_DEPLOYMENT_TARGET = 9.0;
268 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
269 | MTL_FAST_MATH = YES;
270 | ONLY_ACTIVE_ARCH = YES;
271 | SDKROOT = iphoneos;
272 | VERSIONING_SYSTEM = "apple-generic";
273 | VERSION_INFO_PREFIX = "";
274 | };
275 | name = Debug;
276 | };
277 | 6DC6505A22388CA7003DBBF5 /* Release */ = {
278 | isa = XCBuildConfiguration;
279 | buildSettings = {
280 | ALWAYS_SEARCH_USER_PATHS = NO;
281 | CLANG_ANALYZER_NONNULL = YES;
282 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
283 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
284 | CLANG_CXX_LIBRARY = "libc++";
285 | CLANG_ENABLE_MODULES = YES;
286 | CLANG_ENABLE_OBJC_ARC = YES;
287 | CLANG_ENABLE_OBJC_WEAK = YES;
288 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
289 | CLANG_WARN_BOOL_CONVERSION = YES;
290 | CLANG_WARN_COMMA = YES;
291 | CLANG_WARN_CONSTANT_CONVERSION = YES;
292 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
293 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
294 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
295 | CLANG_WARN_EMPTY_BODY = YES;
296 | CLANG_WARN_ENUM_CONVERSION = YES;
297 | CLANG_WARN_INFINITE_RECURSION = YES;
298 | CLANG_WARN_INT_CONVERSION = YES;
299 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
300 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
301 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
302 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
303 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
304 | CLANG_WARN_STRICT_PROTOTYPES = YES;
305 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
306 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
307 | CLANG_WARN_UNREACHABLE_CODE = YES;
308 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
309 | CODE_SIGN_IDENTITY = "iPhone Developer";
310 | COPY_PHASE_STRIP = NO;
311 | CURRENT_PROJECT_VERSION = 1;
312 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
313 | ENABLE_NS_ASSERTIONS = NO;
314 | ENABLE_STRICT_OBJC_MSGSEND = YES;
315 | GCC_C_LANGUAGE_STANDARD = gnu11;
316 | GCC_NO_COMMON_BLOCKS = YES;
317 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
318 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
319 | GCC_WARN_UNDECLARED_SELECTOR = YES;
320 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
321 | GCC_WARN_UNUSED_FUNCTION = YES;
322 | GCC_WARN_UNUSED_VARIABLE = YES;
323 | IPHONEOS_DEPLOYMENT_TARGET = 9.0;
324 | MTL_ENABLE_DEBUG_INFO = NO;
325 | MTL_FAST_MATH = YES;
326 | SDKROOT = iphoneos;
327 | VALIDATE_PRODUCT = YES;
328 | VERSIONING_SYSTEM = "apple-generic";
329 | VERSION_INFO_PREFIX = "";
330 | };
331 | name = Release;
332 | };
333 | 6DC6505C22388CA7003DBBF5 /* Debug */ = {
334 | isa = XCBuildConfiguration;
335 | buildSettings = {
336 | CODE_SIGN_IDENTITY = "";
337 | CODE_SIGN_STYLE = Automatic;
338 | DEFINES_MODULE = YES;
339 | DYLIB_COMPATIBILITY_VERSION = 1;
340 | DYLIB_CURRENT_VERSION = 1;
341 | DYLIB_INSTALL_NAME_BASE = "@rpath";
342 | INFOPLIST_FILE = "$(SRCROOT)/Info.plist";
343 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
344 | LD_RUNPATH_SEARCH_PATHS = (
345 | "$(inherited)",
346 | "@executable_path/Frameworks",
347 | "@loader_path/Frameworks",
348 | );
349 | PRODUCT_BUNDLE_IDENTIFIER = "com.material-motion.MotionInterchange";
350 | PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
351 | SKIP_INSTALL = YES;
352 | TARGETED_DEVICE_FAMILY = "1,2";
353 | };
354 | name = Debug;
355 | };
356 | 6DC6505D22388CA7003DBBF5 /* Release */ = {
357 | isa = XCBuildConfiguration;
358 | buildSettings = {
359 | CODE_SIGN_IDENTITY = "";
360 | CODE_SIGN_STYLE = Automatic;
361 | DEFINES_MODULE = YES;
362 | DYLIB_COMPATIBILITY_VERSION = 1;
363 | DYLIB_CURRENT_VERSION = 1;
364 | DYLIB_INSTALL_NAME_BASE = "@rpath";
365 | INFOPLIST_FILE = "$(SRCROOT)/Info.plist";
366 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
367 | LD_RUNPATH_SEARCH_PATHS = (
368 | "$(inherited)",
369 | "@executable_path/Frameworks",
370 | "@loader_path/Frameworks",
371 | );
372 | PRODUCT_BUNDLE_IDENTIFIER = "com.material-motion.MotionInterchange";
373 | PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
374 | SKIP_INSTALL = YES;
375 | TARGETED_DEVICE_FAMILY = "1,2";
376 | };
377 | name = Release;
378 | };
379 | /* End XCBuildConfiguration section */
380 |
381 | /* Begin XCConfigurationList section */
382 | 6DC6504D22388CA7003DBBF5 /* Build configuration list for PBXProject "MotionInterchange" */ = {
383 | isa = XCConfigurationList;
384 | buildConfigurations = (
385 | 6DC6505922388CA7003DBBF5 /* Debug */,
386 | 6DC6505A22388CA7003DBBF5 /* Release */,
387 | );
388 | defaultConfigurationIsVisible = 0;
389 | defaultConfigurationName = Release;
390 | };
391 | 6DC6505B22388CA7003DBBF5 /* Build configuration list for PBXNativeTarget "MotionInterchange" */ = {
392 | isa = XCConfigurationList;
393 | buildConfigurations = (
394 | 6DC6505C22388CA7003DBBF5 /* Debug */,
395 | 6DC6505D22388CA7003DBBF5 /* Release */,
396 | );
397 | defaultConfigurationIsVisible = 0;
398 | defaultConfigurationName = Release;
399 | };
400 | /* End XCConfigurationList section */
401 | };
402 | rootObject = 6DC6504A22388CA7003DBBF5 /* Project object */;
403 | }
404 |
--------------------------------------------------------------------------------
/MotionInterchange.xcodeproj/xcshareddata/xcschemes/MotionInterchange.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
34 |
35 |
45 |
46 |
52 |
53 |
54 |
55 |
56 |
57 |
63 |
64 |
70 |
71 |
72 |
73 |
75 |
76 |
79 |
80 |
81 |
--------------------------------------------------------------------------------
/Podfile:
--------------------------------------------------------------------------------
1 | workspace 'MotionInterchange.xcworkspace'
2 | use_frameworks!
3 | platform :ios, '10.0'
4 |
5 | target "MotionInterchangeCatalog" do
6 | pod 'CatalogByConvention'
7 | pod 'MotionInterchange', :path => './'
8 |
9 | project 'examples/apps/Catalog/MotionInterchangeCatalog.xcodeproj'
10 | end
11 |
12 | target "UnitTests" do
13 | pod 'MotionInterchange', :path => './'
14 |
15 | project 'examples/apps/Catalog/MotionInterchangeCatalog.xcodeproj'
16 | end
17 |
18 | post_install do |installer|
19 | installer.pods_project.targets.each do |target|
20 | target.build_configurations.each do |configuration|
21 | configuration.build_settings['SWIFT_VERSION'] = "3.0"
22 | if target.name.start_with?("MotionInterchange")
23 | configuration.build_settings['WARNING_CFLAGS'] ="$(inherited) -Wall -Wcast-align -Wconversion -Werror -Wextra -Wimplicit-atomic-properties -Wmissing-prototypes -Wno-sign-conversion -Wno-unused-parameter -Woverlength-strings -Wshadow -Wstrict-selector-match -Wundeclared-selector -Wunreachable-code"
24 | end
25 | end
26 | end
27 | end
28 |
--------------------------------------------------------------------------------
/Podfile.lock:
--------------------------------------------------------------------------------
1 | PODS:
2 | - CatalogByConvention (2.5.2)
3 | - MotionInterchange (4.0.1)
4 |
5 | DEPENDENCIES:
6 | - CatalogByConvention
7 | - MotionInterchange (from `./`)
8 |
9 | SPEC REPOS:
10 | trunk:
11 | - CatalogByConvention
12 |
13 | EXTERNAL SOURCES:
14 | MotionInterchange:
15 | :path: "./"
16 |
17 | SPEC CHECKSUMS:
18 | CatalogByConvention: ef713654160053be026fa4648dd28caf6b5ca4e1
19 | MotionInterchange: d58704efd5dcd62c6535bc1081df832533a8e9b9
20 |
21 | PODFILE CHECKSUM: aea7b8b75a397821880e2ba54fc4cf979d21cd99
22 |
23 | COCOAPODS: 1.10.1
24 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 
2 |
3 | > A standard format for representing animation traits in Objective-C and Swift.
4 |
5 | [](https://travis-ci.org/material-motion/motion-interchange-objc)
6 | [](https://codecov.io/gh/material-motion/motion-interchange-objc)
7 | [](https://cocoapods.org/pods/MotionInterchange)
8 | [](http://cocoadocs.org/docsets/MotionInterchange)
9 |
10 | "Magic numbers" — those lonely, abandoned values without a home — are often one of the first things
11 | targeted in code review for cleanup. And yet, numbers related to animations may go unnoticed and
12 | left behind, scattered throughout a code base with little to no organizational diligence. These
13 | forgotten metrics form the backbone of mobile interactions and are often the ones needing the most
14 | care - so why are we ok leaving them scattered throughout a code base?
15 |
16 | ```objc
17 | // Let's play "find the magic number": how many magic numbers are hidden in this code?
18 | [UIView animateWithDuration:0.230
19 | delay:0
20 | options:UIViewAnimationOptionCurveEaseOut
21 | animations:^{
22 | myButton.position = updatedPosition;
23 | }
24 | completion:nil];
25 | // Hint: the answer is not "one, the number 0.230".
26 | ```
27 |
28 | The challenge with extracting animation magic numbers is that we often don't have a clear
29 | definition of *what an animation is composed of*. An animation is not simply determined by its
30 | duration, in the same way that a color is not simply determined by how red it is.
31 |
32 | The traits of an animation — like the red, green, and blue components of a color — include the
33 | following:
34 |
35 | - Delay.
36 | - Duration.
37 | - Timing curve.
38 | - Repetition.
39 |
40 | Within this library you will find simple data types for storing and representing animation
41 | traits so that the magic numbers that define your animations can find a place to call home.
42 |
43 | Welcome home, lost numbers.
44 |
45 | ## Sibling library: Motion Animator
46 |
47 | While it is possible to use the Motion Interchange as a standalone library, the Motion Animator
48 | is designed to be the primary consumer of Motion Interchange data types. Consider using these
49 | libraries together, with MotionAnimator as your primary dependency.
50 |
51 | ```objc
52 | MDMAnimationTraits *animationTraits =
53 | [[MDMAnimationTraits alloc] initWithDuration:0.230
54 | timingFunctionName:kCAMediaTimingFunctionEaseInEaseOut];
55 |
56 | MDMMotionAnimator *animator = [[MDMMotionAnimator alloc] init];
57 | [animator animateWithTraits:animationTraits animations:^{
58 | view.alpha = 0;
59 | }];
60 | ```
61 |
62 | To learn more, visit the MotionAnimator GitHub page:
63 |
64 | https://github.com/material-motion/motion-animator-objc
65 |
66 | ## Installation
67 |
68 | ### Installation with CocoaPods
69 |
70 | > CocoaPods is a dependency manager for Objective-C and Swift libraries. CocoaPods automates the
71 | > process of using third-party libraries in your projects. See
72 | > [the Getting Started guide](https://guides.cocoapods.org/using/getting-started.html) for more
73 | > information. You can install it with the following command:
74 | >
75 | > gem install cocoapods
76 |
77 | Add `MotionInterchange` to your `Podfile`:
78 |
79 | pod 'MotionInterchange'
80 |
81 | Then run the following command:
82 |
83 | pod install
84 |
85 | ### Usage
86 |
87 | Import the framework:
88 |
89 | @import MotionInterchange;
90 |
91 | You will now have access to all of the APIs.
92 |
93 | ## Example apps/unit tests
94 |
95 | Check out a local copy of the repo to access the Catalog application by running the following
96 | commands:
97 |
98 | git clone https://github.com/material-motion/motion-interchange-objc.git
99 | cd motion-interchange-objc
100 | pod install
101 | open MotionInterchange.xcworkspace
102 |
103 | ## Guides
104 |
105 | 1. [Animation traits](#animation-traits)
106 | 2. [Timing curves](#timing-curves)
107 |
108 | ### Animation traits
109 |
110 | The primary data type you'll make use of is `MDMAnimationTraits`. This class can store all of
111 | the necessary traits that make up an animation, including:
112 |
113 | - Delay.
114 | - Duration.
115 | - Timing curve.
116 | - Repetition.
117 |
118 | In Objective-C, you initialize a simple ease in/out cubic bezier instance like so:
119 |
120 | ```objc
121 | MDMAnimationTraits *traits = [[MDMAnimationTraits alloc] initWithDuration:0.5];
122 | ```
123 |
124 | And in Swift:
125 |
126 | ```swift
127 | let traits = MDMAnimationTraits(duration: 0.5)
128 | ```
129 |
130 | There are many more ways to initialize animation traits. Read the
131 | [header documentation](src/MDMAnimationTraits.h) to see all of the available initializers.
132 |
133 | ### Timing curves
134 |
135 | A timing curve describes how quickly an animation progresses over time. Two types of timing
136 | curves are supported by Core Animation, and therefore by the MotionInterchange:
137 |
138 | - Cubic bezier
139 | - Spring
140 |
141 | **Cubic beziers** are represented by the CAMediaTimingFunction object. To define an
142 | animation trait with a cubic bezier curve in Objective-C:
143 |
144 | ```objc
145 | CAMediaTimingFunction *timingCurve =
146 | [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
147 | MDMAnimationTraits *traits =
148 | [[MDMAnimationTraits alloc] initWithDelay:0 duration:0.5 timingCurve:timingCurve];
149 | ```
150 |
151 | And in Swift:
152 |
153 | ```swift
154 | let timingCurve = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
155 | let traits = MDMAnimationTraits(delay: 0, duration: 0.5, timingCurve: timingCurve)
156 | ```
157 |
158 | You can also use the UIViewAnimationCurve type to initialize a timing curve in Objective-C:
159 |
160 | ```objc
161 | MDMAnimationTraits *traits =
162 | [[MDMAnimationTraits alloc] initWithDuration:0.5 animationCurve:UIViewAnimationCurveEaseIn];
163 | ```
164 |
165 | And in Swift:
166 |
167 | ```swift
168 | let traits = MDMAnimationTraits(duration: 0.5, animationCurve: .easeIn)
169 | ```
170 |
171 | **Springs** are represented with the custom `MDMSpringTimingCurve` type. To define an
172 | animation trait with a spring curve in Objective-C:
173 |
174 | ```objc
175 | MDMSpringTimingCurve *timingCurve =
176 | [[MDMSpringTimingCurve alloc] initWithMass:1 tension:100 friction:10];
177 | MDMAnimationTraits *traits =
178 | [[MDMAnimationTraits alloc] initWithDelay:0 duration:0.5 timingCurve:timingCurve];
179 | ```
180 |
181 | And in Swift:
182 |
183 | ```swift
184 | let timingCurve = MDMSpringTimingCurve(mass: 1, tension: 100, friction: 10)
185 | let traits = MDMAnimationTraits(delay: 0, duration: 0.5, timingCurve: timingCurve)
186 | ```
187 |
188 | Springs can also be initialized using UIKit's [damping ratio concept](https://developer.apple.com/documentation/uikit/uiview/1622594-animatewithduration). The `MDMSpringTimingCurveGenerator` type generates `MDMSpringTimingCurve` instances when needed. A spring timing curve generator can be stored as the `timingCurve` of an `MDMAnimationTraits` instance.
189 |
190 | ```objc
191 | MDMSpringTimingCurveGenerator *timingCurve =
192 | [[MDMSpringTimingCurveGenerator alloc] initWithDuration:<#(NSTimeInterval)#> dampingRatio:<#(CGFloat)#>];
193 | MDMAnimationTraits *traits =
194 | [[MDMAnimationTraits alloc] initWithDelay:0 duration:0.5 timingCurve:timingCurve];
195 | ```
196 |
197 | And in Swift:
198 |
199 | ```swift
200 | let timingCurve = MDMSpringTimingCurveGenerator(duration: 0.5, dampingRatio: 0.5)
201 | let traits = MDMAnimationTraits(delay: 0, duration: 0.5, timingCurve: timingCurve)
202 | ```
203 |
204 | ## Contributing
205 |
206 | We welcome contributions!
207 |
208 | Check out our [upcoming milestones](https://github.com/material-motion/motion-interchange-objc/milestones).
209 |
210 | Learn more about [our team](https://material-motion.github.io/material-motion/team/),
211 | [our community](https://material-motion.github.io/material-motion/team/community/), and
212 | our [contributor essentials](https://material-motion.github.io/material-motion/team/essentials/).
213 |
214 | ## License
215 |
216 | Licensed under the Apache 2.0 license. See LICENSE for details.
217 |
--------------------------------------------------------------------------------
/examples/apps/Catalog/Catalog/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2017-present The Material Motion Authors. All Rights Reserved.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | import UIKit
18 | import CatalogByConvention
19 |
20 | @UIApplicationMain
21 | class AppDelegate: UIResponder, UIApplicationDelegate {
22 |
23 | var window: UIWindow?
24 |
25 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
26 | let window = UIWindow(frame: UIScreen.main.bounds)
27 | self.window = window
28 |
29 | let rootViewController = CBCNodeListViewController(node: CBCCreateNavigationTree())
30 | rootViewController.title = "Motion Interchange"
31 | window.rootViewController = UINavigationController(rootViewController: rootViewController)
32 |
33 | window.makeKeyAndVisible()
34 | return true
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/examples/apps/Catalog/Catalog/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "29x29",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "29x29",
11 | "scale" : "3x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "40x40",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "40x40",
21 | "scale" : "3x"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "size" : "60x60",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "size" : "60x60",
31 | "scale" : "3x"
32 | },
33 | {
34 | "idiom" : "ipad",
35 | "size" : "29x29",
36 | "scale" : "1x"
37 | },
38 | {
39 | "idiom" : "ipad",
40 | "size" : "29x29",
41 | "scale" : "2x"
42 | },
43 | {
44 | "idiom" : "ipad",
45 | "size" : "40x40",
46 | "scale" : "1x"
47 | },
48 | {
49 | "idiom" : "ipad",
50 | "size" : "40x40",
51 | "scale" : "2x"
52 | },
53 | {
54 | "idiom" : "ipad",
55 | "size" : "76x76",
56 | "scale" : "1x"
57 | },
58 | {
59 | "idiom" : "ipad",
60 | "size" : "76x76",
61 | "scale" : "2x"
62 | },
63 | {
64 | "idiom" : "ipad",
65 | "size" : "83.5x83.5",
66 | "scale" : "2x"
67 | }
68 | ],
69 | "info" : {
70 | "version" : 1,
71 | "author" : "xcode"
72 | }
73 | }
--------------------------------------------------------------------------------
/examples/apps/Catalog/Catalog/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/apps/Catalog/Catalog/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 | UIRequiredDeviceCapabilities
28 |
29 | armv7
30 |
31 | UISupportedInterfaceOrientations
32 |
33 | UIInterfaceOrientationPortrait
34 | UIInterfaceOrientationLandscapeLeft
35 | UIInterfaceOrientationLandscapeRight
36 |
37 | UISupportedInterfaceOrientations~ipad
38 |
39 | UIInterfaceOrientationPortrait
40 | UIInterfaceOrientationPortraitUpsideDown
41 | UIInterfaceOrientationLandscapeLeft
42 | UIInterfaceOrientationLandscapeRight
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/examples/apps/Catalog/MotionInterchangeCatalog.xcodeproj/xcshareddata/xcschemes/MotionInterchangeCatalog.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
31 |
32 |
34 |
40 |
41 |
42 |
43 |
44 |
50 |
51 |
52 |
53 |
54 |
55 |
66 |
68 |
74 |
75 |
76 |
77 |
78 |
79 |
85 |
87 |
93 |
94 |
95 |
96 |
98 |
99 |
102 |
103 |
104 |
--------------------------------------------------------------------------------
/examples/apps/Catalog/MotionInterchangeCatalog.xcodeproj/xcshareddata/xcschemes/UnitTests.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
16 |
18 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
41 |
42 |
43 |
44 |
50 |
51 |
53 |
54 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/examples/apps/Catalog/TableOfContents.swift:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2017-present The Material Motion Authors. All Rights Reserved.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | // MARK: Catalog by convention
18 |
19 | // Note: this library does not include examples because it is solely a data format.
20 |
--------------------------------------------------------------------------------
/examples/apps/Catalog/TestHarness/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2016-present The Material Motion Authors. All Rights Reserved.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | import UIKit
18 |
19 | @UIApplicationMain
20 | class AppDelegate: UIResponder, UIApplicationDelegate {
21 |
22 | var window: UIWindow?
23 |
24 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
25 | let window = UIWindow(frame: UIScreen.main.bounds)
26 | self.window = window
27 | window.rootViewController = UINavigationController(rootViewController: UIViewController())
28 | window.makeKeyAndVisible()
29 | return true
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/examples/apps/Catalog/TestHarness/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "29x29",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "29x29",
11 | "scale" : "3x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "40x40",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "40x40",
21 | "scale" : "3x"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "size" : "60x60",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "size" : "60x60",
31 | "scale" : "3x"
32 | },
33 | {
34 | "idiom" : "ipad",
35 | "size" : "29x29",
36 | "scale" : "1x"
37 | },
38 | {
39 | "idiom" : "ipad",
40 | "size" : "29x29",
41 | "scale" : "2x"
42 | },
43 | {
44 | "idiom" : "ipad",
45 | "size" : "40x40",
46 | "scale" : "1x"
47 | },
48 | {
49 | "idiom" : "ipad",
50 | "size" : "40x40",
51 | "scale" : "2x"
52 | },
53 | {
54 | "idiom" : "ipad",
55 | "size" : "76x76",
56 | "scale" : "1x"
57 | },
58 | {
59 | "idiom" : "ipad",
60 | "size" : "76x76",
61 | "scale" : "2x"
62 | }
63 | ],
64 | "info" : {
65 | "version" : 1,
66 | "author" : "xcode"
67 | }
68 | }
--------------------------------------------------------------------------------
/examples/apps/Catalog/TestHarness/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/apps/Catalog/TestHarness/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 | CFBundleVersion
20 | 1
21 | LSRequiresIPhoneOS
22 |
23 | UILaunchStoryboardName
24 | LaunchScreen
25 | UIRequiredDeviceCapabilities
26 |
27 | armv7
28 |
29 | UISupportedInterfaceOrientations
30 |
31 | UIInterfaceOrientationPortrait
32 | UIInterfaceOrientationLandscapeLeft
33 | UIInterfaceOrientationLandscapeRight
34 |
35 | UISupportedInterfaceOrientations~ipad
36 |
37 | UIInterfaceOrientationPortrait
38 | UIInterfaceOrientationPortraitUpsideDown
39 | UIInterfaceOrientationLandscapeLeft
40 | UIInterfaceOrientationLandscapeRight
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/examples/apps/Catalog/UnitTests/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 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 |
24 |
25 |
--------------------------------------------------------------------------------
/examples/supplemental/ExampleViewController.swift:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2017-present The Material Motion Authors. All Rights Reserved.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | import UIKit
18 |
19 | struct ExampleInfo {
20 | let title: String
21 | let instructions: String
22 | }
23 |
24 | class ExampleViewController: UIViewController {
25 |
26 | override func viewDidLoad() {
27 | super.viewDidLoad()
28 | view.backgroundColor = .backgroundColor
29 | }
30 |
31 | func exampleInformation() -> ExampleInfo {
32 | return ExampleInfo(title: "Uninitialized", instructions: "")
33 | }
34 |
35 | override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
36 | super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
37 |
38 | self.title = exampleInformation().title
39 | }
40 |
41 | required init?(coder aDecoder: NSCoder) {
42 | fatalError("init(coder:) has not been implemented")
43 | }
44 | }
45 |
46 | class ExampleTableViewController: UITableViewController {
47 |
48 | func exampleInformation() -> ExampleInfo {
49 | return ExampleInfo(title: "Uninitialized", instructions: "")
50 | }
51 |
52 | convenience init() {
53 | self.init(style: .plain)
54 | }
55 |
56 | override init(style: UITableView.Style) {
57 | super.init(style: style)
58 |
59 | self.title = exampleInformation().title
60 | }
61 |
62 | override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
63 | super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
64 |
65 | self.title = exampleInformation().title
66 | }
67 |
68 | required init?(coder aDecoder: NSCoder) {
69 | fatalError("init(coder:) has not been implemented")
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/examples/supplemental/ExampleViews.swift:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2017-present The Material Motion Authors. All Rights Reserved.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | import UIKit
18 |
19 | func createExampleView() -> UIView {
20 | let view = UIView(frame: .init(x: 0, y: 0, width: 128, height: 128))
21 | view.backgroundColor = .primaryColor
22 | view.layer.cornerRadius = view.bounds.width / 2
23 | return view
24 | }
25 |
26 | func createExampleSquareView() -> UIView {
27 | let view = UIView(frame: .init(x: 0, y: 0, width: 128, height: 128))
28 | view.backgroundColor = .primaryColor
29 | return view
30 | }
31 |
--------------------------------------------------------------------------------
/examples/supplemental/HexColor.swift:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2017-present The Material Motion Authors. All Rights Reserved.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | import Foundation
18 | import UIKit
19 |
20 | extension UIColor {
21 | private convenience init(red: Int, green: Int, blue: Int) {
22 | assert(red >= 0 && red <= 255, "Invalid red component")
23 | assert(green >= 0 && green <= 255, "Invalid green component")
24 | assert(blue >= 0 && blue <= 255, "Invalid blue component")
25 |
26 | self.init(red: CGFloat(red) / 255.0, green: CGFloat(green) / 255.0, blue: CGFloat(blue) / 255.0, alpha: 1.0)
27 | }
28 |
29 | convenience init(hexColor: Int) {
30 | self.init(red: (hexColor >> 16) & 0xff, green: (hexColor >> 8) & 0xff, blue: hexColor & 0xff)
31 | }
32 |
33 | static var primaryColor: UIColor {
34 | return UIColor(hexColor: 0xFF80AB)
35 | }
36 |
37 | static var secondaryColor: UIColor {
38 | return UIColor(hexColor: 0xC51162)
39 | }
40 |
41 | static var backgroundColor: UIColor {
42 | return UIColor(hexColor: 0x212121)
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/examples/supplemental/Layout.swift:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2017-present The Material Motion Authors. All Rights Reserved.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | import UIKit
18 |
19 | func center(_ view: UIView, within containerView: UIView) -> UIView {
20 | let x = (containerView.bounds.width - view.bounds.width) / 2
21 | let y = (containerView.bounds.height - view.bounds.height) / 2
22 | view.frame = .init(origin: .init(x: x, y: y), size: view.bounds.size)
23 | view.autoresizingMask = [.flexibleTopMargin, .flexibleRightMargin, .flexibleBottomMargin, .flexibleLeftMargin]
24 | return view
25 | }
26 |
--------------------------------------------------------------------------------
/examples/supplemental/ModalViewController.swift:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2017-present The Material Motion Authors. All Rights Reserved.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | import Foundation
18 | import UIKit
19 |
20 | class ModalViewController: ExampleViewController {
21 |
22 | override func viewDidLoad() {
23 | super.viewDidLoad()
24 |
25 | view.backgroundColor = .primaryColor
26 |
27 | view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(didTap)))
28 |
29 | let label = UILabel(frame: view.bounds)
30 | label.numberOfLines = 0
31 | label.lineBreakMode = .byWordWrapping
32 | label.text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. In aliquam dolor eget orci condimentum, eu blandit metus dictum. Suspendisse vitae metus pellentesque, sagittis massa vel, sodales velit. Aliquam placerat nibh et posuere interdum. Etiam fermentum purus vel turpis lobortis auctor. Curabitur auctor maximus purus, ac iaculis mi. In ac hendrerit sapien, eget porttitor risus. Integer placerat cursus viverra. Proin mollis nulla vitae nisi posuere, eu rutrum mauris condimentum. Nullam in faucibus nulla, non tincidunt lectus. Maecenas mollis massa purus, in viverra elit molestie eu. Nunc volutpat magna eget mi vestibulum pharetra. Suspendisse nulla ligula, laoreet non ante quis, vehicula facilisis libero. Morbi faucibus, sapien a convallis sodales, leo quam scelerisque leo, ut tincidunt diam velit laoreet nulla. Proin at quam vel nibh varius ultrices porta id diam. Pellentesque pretium consequat neque volutpat tristique. Sed placerat a purus ut molestie. Nullam laoreet venenatis urna non pulvinar. Proin a vestibulum nulla, eu placerat est. Morbi molestie aliquam justo, ut aliquet neque tristique consectetur. In hac habitasse platea dictumst. Fusce vehicula justo in euismod elementum. Ut vel malesuada est. Aliquam mattis, ex vel viverra eleifend, mauris nibh faucibus nibh, in fringilla sem purus vitae elit. Donec sed dapibus orci, ut vulputate sapien. Integer eu magna efficitur est pellentesque tempor. Sed ac imperdiet ex. Maecenas congue quis lacus vel dictum. Phasellus dictum mi at sollicitudin euismod. Mauris laoreet, eros vitae euismod commodo, libero ligula pretium massa, in scelerisque eros dui eu metus. Fusce elementum mauris velit, eu tempor nulla congue ut. In at tellus id quam feugiat semper eget ut felis. Nulla quis varius quam. Nullam tincidunt laoreet risus, ut aliquet nisl gravida id. Nulla iaculis mauris velit, vitae feugiat nunc scelerisque ac. Vivamus eget ligula porta, pulvinar ex vitae, sollicitudin erat. Maecenas semper ornare suscipit. Ut et neque condimentum lectus pulvinar maximus in sit amet odio. Aliquam congue purus erat, eu rutrum risus placerat a."
33 | label.autoresizingMask = [.flexibleWidth, .flexibleHeight]
34 | view.addSubview(label)
35 | }
36 |
37 | override var preferredStatusBarStyle: UIStatusBarStyle {
38 | return .lightContent
39 | }
40 |
41 | @objc func didTap() {
42 | dismiss(animated: true)
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/img/motion-interchange-banner.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/material-motion/motion-interchange-objc/835474053336d2004c079f7d6580f582a7a2b85a/img/motion-interchange-banner.gif
--------------------------------------------------------------------------------
/resources/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.2
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | $(CURRENT_PROJECT_VERSION)
23 | NSPrincipalClass
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/scripts/v1_to_v2.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | #
3 | # Copyright 2017-present The Material Motion Authors. All Rights Reserved.
4 | #
5 | # Licensed under the Apache License, Version 2.0 (the "License");
6 | # you may not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing, software
12 | # distributed under the License is distributed on an "AS IS" BASIS,
13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | # See the License for the specific language governing permissions and
15 | # limitations under the License.
16 |
17 | # Migration script from v1 to v2 interchange APIs.
18 |
19 | if [ "$#" -ne 1 ]; then
20 | echo "Usage: $(basename $0) "
21 | exit 1
22 | fi
23 |
24 | search_path="$1"
25 |
26 | replace_objc() {
27 | find "$search_path" -type f -name "*.h" | xargs sed -i '' "$1"
28 | find "$search_path" -type f -name "*.m" | xargs sed -i '' "$1"
29 | }
30 |
31 | replace_swift() {
32 | find "$search_path" -type f -name "*.swift" | xargs sed -i '' "$1"
33 | }
34 |
35 | replace_all() {
36 | replace_objc "$1"
37 | replace_swift "$1"
38 | }
39 |
40 | replace_all "s/timing.curve/traits.timingCurve/g"
41 | replace_all "s/traits.curve/traits.timingCurve/g"
42 | replace_objc "s/MDMMotionTiming/MDMAnimationTraits */g"
43 | replace_swift "s/MotionTiming/MDMAnimationTraits/g"
44 |
--------------------------------------------------------------------------------
/src/CAMediaTimingFunction+MDMTimingCurve.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2017-present The Material Motion Authors. All Rights Reserved.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | #import
18 | #import
19 |
20 | #import "MDMTimingCurve.h"
21 |
22 | API_DEPRECATED_BEGIN("Use standard UIKit/CALayer animation APIs instead.",
23 | ios(12, API_TO_BE_DEPRECATED))
24 |
25 | // A CAMediaTimingFunction is a timing curve - we simply define its conformity to our protocol here.
26 | @interface CAMediaTimingFunction ()
27 | @end
28 |
29 | @interface CAMediaTimingFunction (MotionInterchangeExtension)
30 |
31 | /**
32 | Returns a instance of the timing function with its control points reversed.
33 | */
34 | - (nonnull CAMediaTimingFunction *)mdm_reversed;
35 |
36 | /**
37 | Returns the first control point of the timing function.
38 | */
39 | @property(nonatomic, assign, readonly) CGPoint mdm_point1;
40 |
41 | /**
42 | Returns the second control point of the timing function.
43 | */
44 | @property(nonatomic, assign, readonly) CGPoint mdm_point2;
45 |
46 | @end
47 |
48 | API_DEPRECATED_END
49 |
--------------------------------------------------------------------------------
/src/CAMediaTimingFunction+MDMTimingCurve.m:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2017-present The Material Motion Authors. All Rights Reserved.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | #import "CAMediaTimingFunction+MDMTimingCurve.h"
18 |
19 | @implementation CAMediaTimingFunction (MotionInterchangeExtension)
20 |
21 | - (CAMediaTimingFunction *)mdm_reversed {
22 | float pt1[2];
23 | float pt2[2];
24 | [self getControlPointAtIndex:1 values:pt1];
25 | [self getControlPointAtIndex:2 values:pt2];
26 |
27 | float reversedPt1[2];
28 | float reversedPt2[2];
29 | reversedPt1[0] = 1 - pt2[0];
30 | reversedPt1[1] = 1 - pt2[1];
31 | reversedPt2[0] = 1 - pt1[0];
32 | reversedPt2[1] = 1 - pt1[1];
33 | return [CAMediaTimingFunction functionWithControlPoints:reversedPt1[0] :reversedPt1[1]
34 | :reversedPt2[0] :reversedPt2[1]];
35 | }
36 |
37 | - (CGPoint)mdm_point1 {
38 | float point[2];
39 | [self getControlPointAtIndex:1 values:point];
40 | return CGPointMake(point[0], point[1]);
41 | }
42 |
43 | - (CGPoint)mdm_point2 {
44 | float point[2];
45 | [self getControlPointAtIndex:2 values:point];
46 | return CGPointMake(point[0], point[1]);
47 | }
48 |
49 | @end
50 |
--------------------------------------------------------------------------------
/src/MDMAnimationTraits.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2017-present The Material Motion Authors. All Rights Reserved.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | #import
18 | #import
19 | #import
20 |
21 | #import "MDMMotionTiming.h"
22 | #import "MDMRepetitionTraits.h"
23 | #import "MDMSubclassingRestricted.h"
24 | #import "MDMTimingCurve.h"
25 |
26 | API_DEPRECATED_BEGIN("Use standard UIKit/CALayer animation APIs instead.",
27 | ios(12, API_TO_BE_DEPRECATED))
28 |
29 | /**
30 | A generic representation of animation traits.
31 | */
32 | MDM_SUBCLASSING_RESTRICTED
33 | @interface MDMAnimationTraits: NSObject
34 |
35 | /**
36 | Initializes the instance with the provided duration and kCAMediaTimingFunctionEaseInEaseOut timing
37 | curve.
38 |
39 | @param duration The animation will occur over this length of time, in seconds.
40 | */
41 | - (nonnull instancetype)initWithDuration:(NSTimeInterval)duration;
42 |
43 | /**
44 | Initializes the instance with the provided duration and named bezier timing curve.
45 |
46 | @param duration The animation will occur over this length of time, in seconds.
47 | @param animationCurve A UIKit bezier animation curve type.
48 | */
49 | - (nonnull instancetype)initWithDuration:(NSTimeInterval)duration
50 | animationCurve:(UIViewAnimationCurve)animationCurve;
51 |
52 | /**
53 | Initializes the instance with the provided duration, delay, and
54 | kCAMediaTimingFunctionEaseInEaseOut timing curve.
55 |
56 | @param delay The amount of time, in seconds, to wait before starting the animation.
57 | @param duration The animation will occur over this length of time, in seconds, after the delay time
58 | has passed.
59 | */
60 | - (nonnull instancetype)initWithDelay:(NSTimeInterval)delay duration:(NSTimeInterval)duration;
61 |
62 | /**
63 | Initializes the instance with the provided duration, delay, and named bezier timing curve.
64 |
65 | This is a convenience API for defining a timing curve using the Core Animation timing function
66 | names. See the documentation for CAMediaTimingFunction for more details.
67 |
68 | @param delay The amount of time, in seconds, to wait before starting the animation.
69 | @param duration The animation will occur over this length of time, in seconds, after the delay time
70 | has passed.
71 | @param animationCurve A UIKit bezier animation curve type.
72 | */
73 | - (nonnull instancetype)initWithDelay:(NSTimeInterval)delay
74 | duration:(NSTimeInterval)duration
75 | animationCurve:(UIViewAnimationCurve)animationCurve;
76 |
77 | /**
78 | Initializes the instance with the provided duration, delay, and timing curve.
79 |
80 | @param delay The amount of time, in seconds, to wait before starting the animation.
81 | @param duration The animation will occur over this length of time, in seconds, after the delay time
82 | has passed.
83 | @param timingCurve If provided, defines the acceleration timing for the animation. If nil, the
84 | animation will be treated as instant and the duration/delay will be ignored.
85 | */
86 | - (nonnull instancetype)initWithDelay:(NSTimeInterval)delay
87 | duration:(NSTimeInterval)duration
88 | timingCurve:(nullable id)timingCurve;
89 |
90 | /**
91 | Initializes an animation trait with the provided timing curve, duration, delay, and repetition.
92 |
93 | @param duration The animation will occur over this length of time, in seconds, after the delay time
94 | has passed.
95 | @param delay The amount of time, in seconds, to wait before starting the animation.
96 | @param timingCurve If provided, defines the acceleration timing for the animation. If nil, the
97 | animation will be treated as instant and the duration/delay will be ignored.
98 | @param repetition The repetition traits of the animation. Most often an instance of MDMRepetition
99 | or MDMRepetitionOverTime. If nil, the animation will not repeat.
100 | */
101 | - (nonnull instancetype)initWithDelay:(NSTimeInterval)delay
102 | duration:(NSTimeInterval)duration
103 | timingCurve:(nullable id)timingCurve
104 | repetition:(nullable id)repetition
105 | NS_DESIGNATED_INITIALIZER;
106 |
107 | #pragma mark - Traits
108 |
109 | /**
110 | The amount of time, in seconds, before this animation's value interpolation should begin.
111 | */
112 | @property(nonatomic, assign) NSTimeInterval delay;
113 |
114 | /**
115 | The amount of time, in seconds, over which this animation should interpolate between its values.
116 | */
117 | @property(nonatomic, assign) NSTimeInterval duration;
118 |
119 | /**
120 | The velocity and acceleration of the animation over time.
121 |
122 | If the timing curve is nil then the timing is assumed to be "instant", regardless of duration and
123 | delay.
124 | */
125 | @property(nonatomic, strong, nullable) id timingCurve;
126 |
127 | /**
128 | The repetition characteristics of the animation.
129 |
130 | If the repetition is nil then no repetition should occur.
131 | */
132 | @property(nonatomic, strong, nullable) id repetition;
133 |
134 | #pragma mark - Unavailable
135 |
136 | /**
137 | Unavailable.
138 | */
139 | - (nonnull instancetype)init NS_UNAVAILABLE;
140 |
141 | @end
142 |
143 | @interface MDMAnimationTraits (SystemTraits)
144 |
145 | /**
146 | Animation traits for an iOS modal presentation slide animation.
147 | */
148 | @property(nonatomic, class, strong, nonnull, readonly) MDMAnimationTraits *systemModalMovement;
149 |
150 | @end
151 |
152 | @interface MDMAnimationTraits (Legacy)
153 |
154 | /**
155 | Initializes the instance with the provided legacy C-style animation trait structure.
156 |
157 | @param timing A legacy C-style representation of animation traits.
158 | */
159 | - (nonnull instancetype)initWithMotionTiming:(MDMMotionTiming)timing;
160 |
161 | @end
162 |
163 | API_DEPRECATED_END
164 |
--------------------------------------------------------------------------------
/src/MDMAnimationTraits.m:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2017-present The Material Motion Authors. All Rights Reserved.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | #import "MDMAnimationTraits.h"
18 |
19 | #import "CAMediaTimingFunction+MDMTimingCurve.h"
20 | #import "MDMRepetition.h"
21 | #import "MDMRepetitionOverTime.h"
22 | #import "MDMSpringTimingCurve.h"
23 |
24 | @implementation MDMAnimationTraits
25 |
26 | - (instancetype)init {
27 | [self doesNotRecognizeSelector:_cmd];
28 | return nil;
29 | }
30 |
31 | - (nonnull instancetype)initWithDuration:(NSTimeInterval)duration {
32 | return [self initWithDelay:0 duration:duration];
33 | }
34 |
35 | - (instancetype)initWithDuration:(NSTimeInterval)duration
36 | animationCurve:(UIViewAnimationCurve)animationCurve {
37 | return [self initWithDelay:0 duration:duration animationCurve:animationCurve];
38 | }
39 |
40 | - (instancetype)initWithDelay:(NSTimeInterval)delay duration:(NSTimeInterval)duration {
41 | return [self initWithDelay:delay duration:duration animationCurve:UIViewAnimationCurveEaseInOut];
42 | }
43 |
44 | - (instancetype)initWithDelay:(NSTimeInterval)delay
45 | duration:(NSTimeInterval)duration
46 | animationCurve:(UIViewAnimationCurve)animationCurve {
47 | CAMediaTimingFunction *timingCurve;
48 | switch (animationCurve) {
49 | case UIViewAnimationCurveEaseInOut:
50 | timingCurve = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
51 | break;
52 | case UIViewAnimationCurveEaseIn:
53 | timingCurve = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];
54 | break;
55 | case UIViewAnimationCurveEaseOut:
56 | timingCurve = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
57 | break;
58 | case UIViewAnimationCurveLinear:
59 | timingCurve = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
60 | break;
61 | }
62 | return [self initWithDelay:delay duration:duration timingCurve:timingCurve];
63 | }
64 |
65 | - (instancetype)initWithDelay:(NSTimeInterval)delay
66 | duration:(NSTimeInterval)duration
67 | timingCurve:(id)timingCurve {
68 | return [self initWithDelay:delay duration:duration timingCurve:timingCurve repetition:nil];
69 | }
70 |
71 | - (instancetype)initWithDelay:(NSTimeInterval)delay
72 | duration:(NSTimeInterval)duration
73 | timingCurve:(id)timingCurve
74 | repetition:(id)repetition {
75 | self = [super init];
76 | if (self) {
77 | _duration = duration;
78 | _delay = delay;
79 | _timingCurve = timingCurve;
80 | _repetition = repetition;
81 | }
82 | return self;
83 | }
84 |
85 | - (nonnull instancetype)initWithMotionTiming:(MDMMotionTiming)timing {
86 | id timingCurve;
87 | switch (timing.curve.type) {
88 | case MDMMotionCurveTypeInstant:
89 | timingCurve = nil;
90 | break;
91 | #pragma clang diagnostic push
92 | #pragma clang diagnostic ignored "-Wdeprecated-declarations"
93 | case MDMMotionCurveTypeDefault:
94 | #pragma clang diagnostic pop
95 | case MDMMotionCurveTypeBezier:
96 | timingCurve = [CAMediaTimingFunction functionWithControlPoints:(float)timing.curve.data[0]
97 | :(float)timing.curve.data[1]
98 | :(float)timing.curve.data[2]
99 | :(float)timing.curve.data[3]];
100 | break;
101 | case MDMMotionCurveTypeSpring: {
102 | CGFloat *data = timing.curve.data;
103 | timingCurve =
104 | [[MDMSpringTimingCurve alloc] initWithMass:data[MDMSpringMotionCurveDataIndexMass]
105 | tension:data[MDMSpringMotionCurveDataIndexTension]
106 | friction:data[MDMSpringMotionCurveDataIndexFriction]
107 | initialVelocity:data[MDMSpringMotionCurveDataIndexInitialVelocity]];
108 | break;
109 | }
110 | }
111 | id repetition;
112 | switch (timing.repetition.type) {
113 | case MDMMotionRepetitionTypeNone:
114 | repetition = nil;
115 | break;
116 |
117 | case MDMMotionRepetitionTypeCount:
118 | repetition = [[MDMRepetition alloc] initWithNumberOfRepetitions:timing.repetition.amount
119 | autoreverses:timing.repetition.autoreverses];
120 | break;
121 | case MDMMotionRepetitionTypeDuration:
122 | repetition = [[MDMRepetitionOverTime alloc] initWithDuration:timing.repetition.amount
123 | autoreverses:timing.repetition.autoreverses];
124 | break;
125 | }
126 | return [self initWithDelay:timing.delay
127 | duration:timing.duration
128 | timingCurve:timingCurve
129 | repetition:repetition];
130 | }
131 |
132 | #pragma mark - NSCopying
133 |
134 | - (id)copyWithZone:(NSZone *)zone {
135 | return [[[self class] alloc] initWithDelay:self.delay
136 | duration:self.duration
137 | timingCurve:[self.timingCurve copyWithZone:zone]
138 | repetition:[self.repetition copyWithZone:zone]];
139 | }
140 |
141 | @end
142 |
143 | @implementation MDMAnimationTraits (SystemTraits)
144 |
145 | + (MDMAnimationTraits *)systemModalMovement {
146 | MDMSpringTimingCurve *timingCurve = [[MDMSpringTimingCurve alloc] initWithMass:3
147 | tension:1000
148 | friction:500];
149 | return [[MDMAnimationTraits alloc] initWithDelay:0 duration:0.500 timingCurve:timingCurve];
150 | }
151 |
152 | @end
153 |
154 |
--------------------------------------------------------------------------------
/src/MDMMotionCurve.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2017-present The Material Motion Authors. All Rights Reserved.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | #import
18 | #import
19 | #import
20 |
21 | API_DEPRECATED_BEGIN("Use standard UIKit/CALayer animation APIs instead.",
22 | ios(12, API_TO_BE_DEPRECATED))
23 |
24 | /** The possible kinds of motion curves that can be used to describe an animation. */
25 | typedef NS_ENUM(NSUInteger, MDMMotionCurveType) {
26 | /** The value will be instantly set with no animation. */
27 | MDMMotionCurveTypeInstant,
28 |
29 | /** The value will be animated using a cubic bezier curve to model its velocity. */
30 | MDMMotionCurveTypeBezier,
31 |
32 | /**
33 | The value will be animated using a spring simulation.
34 |
35 | A spring will treat the duration property of the motion timing as a suggestion and may choose to
36 | ignore it altogether.
37 | */
38 | MDMMotionCurveTypeSpring,
39 |
40 | /** The default curve will be used. */
41 | MDMMotionCurveTypeDefault __deprecated_enum_msg("Use MDMMotionCurveTypeBezier instead."),
42 |
43 | } NS_SWIFT_NAME(MotionCurveType);
44 |
45 | /**
46 | A generalized representation of a motion curve.
47 | */
48 | struct MDMMotionCurve {
49 | /**
50 | The type defines how to interpret the data values.
51 | */
52 | MDMMotionCurveType type;
53 |
54 | /**
55 | The data values corresponding with this curve.
56 | */
57 | CGFloat data[4];
58 | } NS_SWIFT_NAME(MotionCurve);
59 | typedef struct MDMMotionCurve MDMMotionCurve;
60 |
61 | /**
62 | Creates a bezier motion curve with the provided control points.
63 |
64 | A cubic bezier has four control points in total. We assume that the first control point is 0, 0 and
65 | the last control point is 1, 1. This method requires that you provide the second and third control
66 | points.
67 |
68 | See the documentation for CAMediaTimingFunction for more information.
69 | */
70 | // clang-format off
71 | FOUNDATION_EXTERN
72 | MDMMotionCurve MDMMotionCurveMakeBezier(CGFloat p1x, CGFloat p1y, CGFloat p2x, CGFloat p2y)
73 | NS_SWIFT_NAME(MotionCurveMakeBezier(p1x:p1y:p2x:p2y:));
74 | // clang-format on
75 |
76 | // clang-format off
77 | FOUNDATION_EXTERN
78 | MDMMotionCurve MDMMotionCurveFromTimingFunction(CAMediaTimingFunction * _Nonnull timingFunction)
79 | NS_SWIFT_NAME(MotionCurve(fromTimingFunction:));
80 | // clang-format on
81 |
82 | /**
83 | Creates a spring curve with the provided configuration.
84 |
85 | Tension and friction map to Core Animation's stiffness and damping, respectively.
86 |
87 | See the documentation for CASpringAnimation for more information.
88 | */
89 | // clang-format off
90 | FOUNDATION_EXTERN MDMMotionCurve MDMMotionCurveMakeSpring(CGFloat mass,
91 | CGFloat tension,
92 | CGFloat friction)
93 | NS_SWIFT_NAME(MotionCurveMakeSpring(mass:tension:friction:));
94 | // clang-format on
95 |
96 | /**
97 | Creates a spring curve with the provided configuration.
98 |
99 | Tension and friction map to Core Animation's stiffness and damping, respectively.
100 |
101 | See the documentation for CASpringAnimation for more information.
102 | */
103 | // clang-format off
104 | FOUNDATION_EXTERN
105 | MDMMotionCurve MDMMotionCurveMakeSpringWithInitialVelocity(CGFloat mass,
106 | CGFloat tension,
107 | CGFloat friction,
108 | CGFloat initialVelocity)
109 | NS_SWIFT_NAME(MotionCurveMakeSpring(mass:tension:friction:initialVelocity:));
110 | // clang-format on
111 |
112 | /**
113 | For cubic bezier curves, returns a reversed cubic bezier curve. For all other curve types, a copy
114 | of the original curve is returned.
115 | */
116 | // clang-format off
117 | FOUNDATION_EXTERN MDMMotionCurve MDMMotionCurveReversedBezier(MDMMotionCurve motionCurve)
118 | NS_SWIFT_NAME(MotionCurveReversedBezier(fromMotionCurve:));
119 | // clang-format on
120 |
121 | /**
122 | Named indices for the bezier motion curve's data array.
123 | */
124 | typedef NS_ENUM(NSUInteger, MDMBezierMotionCurveDataIndex) {
125 | MDMBezierMotionCurveDataIndexP1X,
126 | MDMBezierMotionCurveDataIndexP1Y,
127 | MDMBezierMotionCurveDataIndexP2X,
128 | MDMBezierMotionCurveDataIndexP2Y
129 | } NS_SWIFT_NAME(BezierMotionCurveDataIndex);
130 |
131 | /**
132 | Named indices for the spring motion curve's data array.
133 | */
134 | typedef NS_ENUM(NSUInteger, MDMSpringMotionCurveDataIndex) {
135 | MDMSpringMotionCurveDataIndexMass,
136 | MDMSpringMotionCurveDataIndexTension,
137 | MDMSpringMotionCurveDataIndexFriction,
138 |
139 | /**
140 | The initial velocity of the animation.
141 |
142 | A value of zero indicates no initial velocity.
143 | A positive value indicates movement toward the destination.
144 | A negative value indicates movement away from the destination.
145 |
146 | The value's units are dependent on the context and the value being animated.
147 | */
148 | MDMSpringMotionCurveDataIndexInitialVelocity
149 | } NS_SWIFT_NAME(SpringMotionCurveDataIndex);
150 |
151 | // Objective-C-specific macros
152 |
153 | #define _MDMBezier(p1x, p1y, p2x, p2y) \
154 | ((MDMMotionCurve) { \
155 | .type = MDMMotionCurveTypeBezier, \
156 | .data = { p1x, \
157 | p1y, \
158 | p2x, \
159 | p2y } \
160 | })
161 |
162 | #define _MDMSpring(mass, tension, friction) \
163 | ((MDMMotionCurve) { \
164 | .type = MDMMotionCurveTypeSpring, \
165 | .data = { mass, \
166 | tension, \
167 | friction } \
168 | })
169 |
170 | #define _MDMSpringWithInitialVelocity(mass, tension, friction, initialVelocity) \
171 | ((MDMMotionCurve) { \
172 | .type = MDMMotionCurveTypeSpring, \
173 | .data = { mass, \
174 | tension, \
175 | friction, \
176 | initialVelocity } \
177 | })
178 |
179 | /**
180 | A linear bezier motion curve.
181 | */
182 | #define MDMLinearMotionCurve _MDMBezier(0, 0, 1, 1)
183 |
184 | /**
185 | Timing information for an iOS modal presentation slide animation.
186 | */
187 | #define MDMModalMovementTiming { \
188 | .delay = 0.000, .duration = 0.500, .curve = _MDMSpring(3, 1000, 500) \
189 | }
190 |
191 | API_DEPRECATED_END
192 |
--------------------------------------------------------------------------------
/src/MDMMotionCurve.m:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2017-present The Material Motion Authors. All Rights Reserved.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | #import "MDMMotionCurve.h"
18 |
19 | MDMMotionCurve MDMMotionCurveMakeBezier(CGFloat p1x, CGFloat p1y, CGFloat p2x, CGFloat p2y) {
20 | return _MDMBezier(p1x, p1y, p2x, p2y);
21 | }
22 |
23 | MDMMotionCurve MDMMotionCurveMakeSpring(CGFloat mass, CGFloat tension, CGFloat friction) {
24 | return MDMMotionCurveMakeSpringWithInitialVelocity(mass, tension, friction, 0);
25 | }
26 |
27 | MDMMotionCurve MDMMotionCurveMakeSpringWithInitialVelocity(CGFloat mass,
28 | CGFloat tension,
29 | CGFloat friction,
30 | CGFloat initialVelocity) {
31 | return _MDMSpringWithInitialVelocity(mass, tension, friction, initialVelocity);
32 | }
33 |
34 | MDMMotionCurve MDMMotionCurveFromTimingFunction(CAMediaTimingFunction *timingFunction) {
35 | float pt1[2];
36 | float pt2[2];
37 | [timingFunction getControlPointAtIndex:1 values:pt1];
38 | [timingFunction getControlPointAtIndex:2 values:pt2];
39 | return MDMMotionCurveMakeBezier(pt1[0], pt1[1], pt2[0], pt2[1]);
40 | }
41 |
42 | MDMMotionCurve MDMMotionCurveReversedBezier(MDMMotionCurve motionCurve) {
43 | MDMMotionCurve reversed = motionCurve;
44 | if (motionCurve.type == MDMMotionCurveTypeBezier) {
45 | reversed.data[0] = 1 - motionCurve.data[2];
46 | reversed.data[1] = 1 - motionCurve.data[3];
47 | reversed.data[2] = 1 - motionCurve.data[0];
48 | reversed.data[3] = 1 - motionCurve.data[1];
49 | }
50 | return reversed;
51 | }
52 |
--------------------------------------------------------------------------------
/src/MDMMotionRepetition.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2017-present The Material Motion Authors. All Rights Reserved.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | #import
18 | #import
19 |
20 | API_DEPRECATED_BEGIN("Use standard UIKit/CALayer animation APIs instead.",
21 | ios(12, API_TO_BE_DEPRECATED))
22 |
23 | /**
24 | The possible kinds of repetition that can be used to describe an animation.
25 | */
26 | typedef NS_ENUM(NSUInteger, MDMMotionRepetitionType) {
27 | /**
28 | The animation will be not be repeated.
29 | */
30 | MDMMotionRepetitionTypeNone,
31 |
32 | /**
33 | The animation will be repeated a given number of times.
34 | */
35 | MDMMotionRepetitionTypeCount,
36 |
37 | /**
38 | The animation will be repeated for a given number of seconds.
39 | */
40 | MDMMotionRepetitionTypeDuration,
41 |
42 | } NS_SWIFT_NAME(MotionReptitionType);
43 |
44 | /**
45 | A generalized representation of a motion curve.
46 | */
47 | struct MDMMotionRepetition {
48 | /**
49 | The type defines how to interpret the amount.
50 | */
51 | MDMMotionRepetitionType type;
52 |
53 | /**
54 | The amount of repetition.
55 | */
56 | double amount;
57 |
58 | /**
59 | Whether the animation should animate backwards after animating forwards.
60 | */
61 | BOOL autoreverses;
62 |
63 | } NS_SWIFT_NAME(MotionRepetition);
64 | typedef struct MDMMotionRepetition MDMMotionRepetition;
65 |
66 | // Objective-C-specific macros
67 |
68 | #define _MDMNoRepetition \
69 | (MDMMotionRepetition) { \
70 | .type = MDMMotionRepetitionTypeNone, \
71 | .amount = 0, \
72 | .autoreverses = false \
73 | }
74 |
75 | API_DEPRECATED_END
76 |
--------------------------------------------------------------------------------
/src/MDMMotionTiming.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2017-present The Material Motion Authors. All Rights Reserved.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | #import
18 | #import
19 |
20 | #import "MDMMotionCurve.h"
21 | #import "MDMMotionRepetition.h"
22 |
23 | API_DEPRECATED_BEGIN("Use standard UIKit/CALayer animation APIs instead.",
24 | ios(12, API_TO_BE_DEPRECATED))
25 |
26 | /**
27 | A representation of timing for an animation.
28 | */
29 | struct MDMMotionTiming {
30 | /**
31 | The amount of time, in seconds, before this animation's value interpolation should begin.
32 | */
33 | CFTimeInterval delay;
34 |
35 | /**
36 | The amount of time, in seconds, over which this animation should interpolate between its values.
37 | */
38 | CFTimeInterval duration;
39 |
40 | /**
41 | The velocity and acceleration of the animation over time.
42 | */
43 | MDMMotionCurve curve;
44 |
45 | /**
46 | The repetition characteristics of the animation.
47 | */
48 | MDMMotionRepetition repetition;
49 |
50 | } NS_SWIFT_NAME(MotionTiming);
51 | typedef struct MDMMotionTiming MDMMotionTiming;
52 |
53 | API_DEPRECATED_END
54 |
--------------------------------------------------------------------------------
/src/MDMRepetition.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2017-present The Material Motion Authors. All Rights Reserved.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | #import
18 |
19 | #import "MDMRepetitionTraits.h"
20 | #import "MDMSubclassingRestricted.h"
21 |
22 | API_DEPRECATED_BEGIN("Use standard UIKit/CALayer animation APIs instead.",
23 | ios(12, API_TO_BE_DEPRECATED))
24 |
25 | /**
26 | Represents repetition that repeats a specific number of times.
27 | */
28 | MDM_SUBCLASSING_RESTRICTED
29 | @interface MDMRepetition: NSObject
30 |
31 | /**
32 | Initializes the instance with the given number of repetitions.
33 |
34 | Autoreversing is disabled.
35 |
36 | @param numberOfRepetitions May be fractional. Initializing with greatestFiniteMagnitude will cause
37 | the animation to repeat forever.
38 | */
39 | - (nonnull instancetype)initWithNumberOfRepetitions:(double)numberOfRepetitions;
40 |
41 | /**
42 | Initializes the instance with the given number of repetitions and autoreversal behavior.
43 |
44 | @param numberOfRepetitions May be fractional. Initializing with greatestFiniteMagnitude will cause
45 | the animation to repeat forever.
46 | @param autoreverses Whether the animation should animate backwards after animating forwards.
47 | */
48 | - (nonnull instancetype)initWithNumberOfRepetitions:(double)numberOfRepetitions
49 | autoreverses:(BOOL)autoreverses
50 | NS_DESIGNATED_INITIALIZER;
51 |
52 | #pragma mark - Traits
53 |
54 | /**
55 | The number of repetitions that will occur before this animation stops repeating.
56 | */
57 | @property(nonatomic, assign) double numberOfRepetitions;
58 |
59 | /**
60 | Unavailable.
61 | */
62 | - (nonnull instancetype)init NS_UNAVAILABLE;
63 |
64 | @end
65 |
66 | API_DEPRECATED_END
67 |
--------------------------------------------------------------------------------
/src/MDMRepetition.m:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2017-present The Material Motion Authors. All Rights Reserved.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | #import "MDMRepetition.h"
18 |
19 | @implementation MDMRepetition
20 |
21 | @synthesize autoreverses = _autoreverses;
22 |
23 | - (instancetype)init {
24 | [self doesNotRecognizeSelector:_cmd];
25 | return nil;
26 | }
27 |
28 | - (instancetype)initWithNumberOfRepetitions:(double)numberOfRepetitions {
29 | return [self initWithNumberOfRepetitions:numberOfRepetitions autoreverses:NO];
30 | }
31 |
32 | - (instancetype)initWithNumberOfRepetitions:(double)numberOfRepetitions
33 | autoreverses:(BOOL)autoreverses {
34 | self = [super init];
35 | if (self) {
36 | _numberOfRepetitions = numberOfRepetitions;
37 | _autoreverses = autoreverses;
38 | }
39 | return self;
40 | }
41 |
42 | #pragma mark - NSCopying
43 |
44 | - (id)copyWithZone:(__unused NSZone *)zone {
45 | return [[[self class] alloc] initWithNumberOfRepetitions:self.numberOfRepetitions
46 | autoreverses:self.autoreverses];
47 | }
48 |
49 | @end
50 |
51 |
--------------------------------------------------------------------------------
/src/MDMRepetitionOverTime.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2017-present The Material Motion Authors. All Rights Reserved.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | #import
18 |
19 | #import "MDMRepetitionTraits.h"
20 | #import "MDMSubclassingRestricted.h"
21 |
22 | API_DEPRECATED_BEGIN("Use standard UIKit/CALayer animation APIs instead.",
23 | ios(12, API_TO_BE_DEPRECATED))
24 |
25 | /**
26 | Represents repetition that repeats until a specific duration has passed.
27 | */
28 | MDM_SUBCLASSING_RESTRICTED
29 | @interface MDMRepetitionOverTime: NSObject
30 |
31 | /**
32 | Initializes the instance with the given duration.
33 |
34 | @param duration The amount of time, in seconds, over which the animation will repeat.
35 | */
36 | - (nonnull instancetype)initWithDuration:(double)duration;
37 |
38 | /**
39 | Initializes the instance with the given duration and autoreversal behavior.
40 |
41 | @param duration The amount of time, in seconds, over which the animation will repeat.
42 | @param autoreverses Whether the animation should animate backwards after animating forwards.
43 | */
44 | - (nonnull instancetype)initWithDuration:(double)duration autoreverses:(BOOL)autoreverses
45 | NS_DESIGNATED_INITIALIZER;
46 |
47 | #pragma mark - Traits
48 |
49 | /**
50 | The amount of time, in seconds, that will pass before this animation stops repeating.
51 | */
52 | @property(nonatomic, assign) double duration;
53 |
54 | /**
55 | Unavailable.
56 | */
57 | - (nonnull instancetype)init NS_UNAVAILABLE;
58 |
59 | @end
60 |
61 | API_DEPRECATED_END
62 |
--------------------------------------------------------------------------------
/src/MDMRepetitionOverTime.m:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2017-present The Material Motion Authors. All Rights Reserved.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | #import "MDMRepetitionOverTime.h"
18 |
19 | @implementation MDMRepetitionOverTime
20 |
21 | @synthesize autoreverses = _autoreverses;
22 |
23 | - (instancetype)init {
24 | [self doesNotRecognizeSelector:_cmd];
25 | return nil;
26 | }
27 |
28 | - (instancetype)initWithDuration:(double)duration {
29 | return [self initWithDuration:duration autoreverses:NO];
30 | }
31 |
32 | - (instancetype)initWithDuration:(double)duration autoreverses:(BOOL)autoreverses {
33 | self = [super init];
34 | if (self) {
35 | _duration = duration;
36 | _autoreverses = autoreverses;
37 | }
38 | return self;
39 | }
40 |
41 | #pragma mark - NSCopying
42 |
43 | - (id)copyWithZone:(__unused NSZone *)zone {
44 | return [[[self class] alloc] initWithDuration:self.duration autoreverses:self.autoreverses];
45 | }
46 |
47 | @end
48 |
49 |
--------------------------------------------------------------------------------
/src/MDMRepetitionTraits.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2017-present The Material Motion Authors. All Rights Reserved.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | #import
18 |
19 | API_DEPRECATED_BEGIN("Use standard UIKit/CALayer animation APIs instead.",
20 | ios(12, API_TO_BE_DEPRECATED))
21 |
22 | /**
23 | A generalized representation of a repetition traits.
24 | */
25 | @protocol MDMRepetitionTraits
26 |
27 | /**
28 | Whether the animation should animate backwards after animating forwards.
29 | */
30 | @property(nonatomic, assign) BOOL autoreverses;
31 |
32 | @end
33 |
34 | API_DEPRECATED_END
35 |
--------------------------------------------------------------------------------
/src/MDMSpringTimingCurve.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2017-present The Material Motion Authors. All Rights Reserved.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | #import
18 | #import
19 |
20 | #import "MDMSubclassingRestricted.h"
21 | #import "MDMTimingCurve.h"
22 |
23 | API_DEPRECATED_BEGIN("Use standard UIKit/CALayer animation APIs instead.",
24 | ios(12, API_TO_BE_DEPRECATED))
25 |
26 | /**
27 | A timing curve that represents the motion of a single-dimensional attached spring.
28 | */
29 | MDM_SUBCLASSING_RESTRICTED
30 | @interface MDMSpringTimingCurve: NSObject
31 |
32 | /**
33 | Initializes the timing curve with the given parameters and an initial velocity of zero.
34 |
35 | @param mass The mass of the spring simulation. Affects the animation's momentum.
36 | @param tension The tension of the spring simulation. Affects how quickly the animation moves
37 | toward its destination.
38 | @param friction The friction of the spring simulation. Affects how quickly the animation starts
39 | and stops.
40 | */
41 | - (nonnull instancetype)initWithMass:(CGFloat)mass
42 | tension:(CGFloat)tension
43 | friction:(CGFloat)friction;
44 |
45 | /**
46 | Initializes the timing curve with the given parameters.
47 |
48 | @param mass The mass of the spring simulation. Affects the animation's momentum.
49 | @param tension The tension of the spring simulation. Affects how quickly the animation moves
50 | toward its destination.
51 | @param friction The friction of the spring simulation. Affects how quickly the animation starts
52 | and stops.
53 | @param initialVelocity The initial velocity of the spring simulation. Measured in units of
54 | translation per second. For example, if the property being animated is positional, then this value
55 | is in screen units per second.
56 | */
57 | - (nonnull instancetype)initWithMass:(CGFloat)mass
58 | tension:(CGFloat)tension
59 | friction:(CGFloat)friction
60 | initialVelocity:(CGFloat)initialVelocity
61 | NS_DESIGNATED_INITIALIZER;
62 |
63 | #pragma mark - Traits
64 |
65 | /**
66 | The mass of the spring simulation.
67 |
68 | Affects the animation's momentum. This is usually 1.
69 | */
70 | @property(nonatomic, assign) CGFloat mass;
71 |
72 | /**
73 | The tension of the spring simulation.
74 |
75 | Affects how quickly the animation moves toward its destination.
76 | */
77 | @property(nonatomic, assign) CGFloat tension;
78 |
79 | /**
80 | The friction of the spring simulation.
81 |
82 | Affects how quickly the animation starts and stops.
83 | */
84 | @property(nonatomic, assign) CGFloat friction;
85 |
86 | /**
87 | The initial velocity of the spring simulation.
88 |
89 | Measured in units of translation per second.
90 |
91 | If this timing curve was initialized using a damping ratio then setting a new initial velocity
92 | will also change the the mass/tension/friction values according to the new UIKit damping
93 | coefficient calculation.
94 | */
95 | @property(nonatomic, assign) CGFloat initialVelocity;
96 |
97 | /** Unavailable. */
98 | - (nonnull instancetype)init NS_UNAVAILABLE;
99 |
100 | @end
101 |
102 | API_DEPRECATED_END
103 |
--------------------------------------------------------------------------------
/src/MDMSpringTimingCurve.m:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2017-present The Material Motion Authors. All Rights Reserved.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | #import "MDMSpringTimingCurve.h"
18 |
19 | @implementation MDMSpringTimingCurve
20 |
21 | - (instancetype)init {
22 | [self doesNotRecognizeSelector:_cmd];
23 | return nil;
24 | }
25 |
26 | - (instancetype)initWithMass:(CGFloat)mass tension:(CGFloat)tension friction:(CGFloat)friction {
27 | return [self initWithMass:mass tension:tension friction:friction initialVelocity:0];
28 | }
29 |
30 | - (instancetype)initWithMass:(CGFloat)mass
31 | tension:(CGFloat)tension
32 | friction:(CGFloat)friction
33 | initialVelocity:(CGFloat)initialVelocity {
34 | self = [super init];
35 | if (self) {
36 | _mass = mass;
37 | _tension = tension;
38 | _friction = friction;
39 | _initialVelocity = initialVelocity;
40 | }
41 | return self;
42 | }
43 |
44 | #pragma mark - NSCopying
45 |
46 | - (id)copyWithZone:(NSZone *)zone {
47 | return [[[self class] allocWithZone:zone] initWithMass:self.mass
48 | tension:self.tension
49 | friction:self.friction
50 | initialVelocity:self.initialVelocity];;
51 | }
52 |
53 | #pragma mark - Private
54 |
55 | @end
56 |
57 |
--------------------------------------------------------------------------------
/src/MDMSpringTimingCurveGenerator.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2017-present The Material Motion Authors. All Rights Reserved.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | #import
18 | #import
19 |
20 | #import "MDMSubclassingRestricted.h"
21 | #import "MDMTimingCurve.h"
22 |
23 | API_DEPRECATED_BEGIN("Use standard UIKit/CALayer animation APIs instead.",
24 | ios(12, API_TO_BE_DEPRECATED))
25 |
26 | @class MDMSpringTimingCurve;
27 |
28 | /**
29 | A spring timing curve generator based on UIKit duration/dampingRatio-based coefficients.
30 | */
31 | MDM_SUBCLASSING_RESTRICTED
32 | @interface MDMSpringTimingCurveGenerator : NSObject
33 |
34 | /**
35 | Initializes the timing curve with the given UIKit spring damping ratio.
36 |
37 | @param duration The desired duration of the spring animation.
38 | @param dampingRatio From the UIKit documentation: "When `dampingRatio` is 1, the animation will
39 | smoothly decelerate to its final model values without oscillating. Damping ratios less than 1 will
40 | oscillate more and more before coming to a complete stop."
41 | */
42 | - (nonnull instancetype)initWithDuration:(NSTimeInterval)duration
43 | dampingRatio:(CGFloat)dampingRatio;
44 |
45 | /**
46 | Initializes the timing curve with the given UIKit spring damping ratio and initial velocity.
47 |
48 | @param duration The desired duration of the spring animation.
49 | @param dampingRatio From the UIKit documentation: "When `dampingRatio` is 1, the animation will
50 | smoothly decelerate to its final model values without oscillating. Damping ratios less than 1 will
51 | oscillate more and more before coming to a complete stop."
52 | @param initialVelocity From the UIKit documentation: "You can use the initial spring velocity to
53 | specify how fast the object at the end of the simulated spring was moving before it was attached.
54 | It's a unit coordinate system, where 1 is defined as travelling the total animation distance in a
55 | second. So if you're changing an object's position by 200pt in this animation, and you want the
56 | animation to behave as if the object was moving at 100pt/s before the animation started, you'd
57 | pass 0.5. You'll typically want to pass 0 for the velocity."
58 | */
59 | - (nonnull instancetype)initWithDuration:(NSTimeInterval)duration
60 | dampingRatio:(CGFloat)dampingRatio
61 | initialVelocity:(CGFloat)initialVelocity
62 | NS_DESIGNATED_INITIALIZER;
63 |
64 | #pragma mark - Traits
65 |
66 | /**
67 | The desired duration of the spring animation.
68 | */
69 | @property(nonatomic, assign) NSTimeInterval duration;
70 |
71 | /**
72 | From the UIKit documentation: "When `dampingRatio` is 1, the animation will
73 | smoothly decelerate to its final model values without oscillating. Damping ratios less than 1 will
74 | oscillate more and more before coming to a complete stop."
75 | */
76 | @property(nonatomic, assign) CGFloat dampingRatio;
77 |
78 | /**
79 | From the UIKit documentation: "You can use the initial spring velocity to
80 | specify how fast the object at the end of the simulated spring was moving before it was attached.
81 | It's a unit coordinate system, where 1 is defined as travelling the total animation distance in a
82 | second. So if you're changing an object's position by 200pt in this animation, and you want the
83 | animation to behave as if the object was moving at 100pt/s before the animation started, you'd
84 | pass 0.5. You'll typically want to pass 0 for the velocity."
85 | */
86 | @property(nonatomic, assign) CGFloat initialVelocity;
87 |
88 | /**
89 | Creates and returns a new spring timing curve instance with the current configuration.
90 | */
91 | - (nonnull MDMSpringTimingCurve *)springTimingCurve;
92 |
93 | /** Unavailable. */
94 | - (nonnull instancetype)init NS_UNAVAILABLE;
95 |
96 | @end
97 |
98 | API_DEPRECATED_END
99 |
--------------------------------------------------------------------------------
/src/MDMSpringTimingCurveGenerator.m:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2017-present The Material Motion Authors. All Rights Reserved.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | #import "MDMSpringTimingCurveGenerator.h"
18 |
19 | #import "MDMSpringTimingCurve.h"
20 |
21 | #import
22 |
23 | @implementation MDMSpringTimingCurveGenerator
24 |
25 | - (instancetype)initWithDuration:(NSTimeInterval)duration dampingRatio:(CGFloat)dampingRatio {
26 | return [self initWithDuration:duration dampingRatio:dampingRatio initialVelocity:0];
27 | }
28 |
29 | - (nonnull instancetype)initWithDuration:(NSTimeInterval)duration
30 | dampingRatio:(CGFloat)dampingRatio
31 | initialVelocity:(CGFloat)initialVelocity {
32 | self = [super init];
33 | if (self) {
34 | _duration = duration;
35 | _dampingRatio = dampingRatio;
36 | _initialVelocity = initialVelocity;
37 | }
38 | return self;
39 | }
40 |
41 | #pragma mark - NSCopying
42 |
43 | - (id)copyWithZone:(NSZone *)zone {
44 | return [[[self class] allocWithZone:zone] initWithDuration:self.duration
45 | dampingRatio:self.dampingRatio
46 | initialVelocity:self.initialVelocity];
47 | }
48 |
49 | - (MDMSpringTimingCurve *)springTimingCurve {
50 | UIView *view = [[UIView alloc] init];
51 | [UIView animateWithDuration:self.duration
52 | delay:0
53 | usingSpringWithDamping:self.dampingRatio
54 | initialSpringVelocity:self.initialVelocity
55 | options:0
56 | animations:^{
57 | view.center = CGPointMake(100, 100);
58 | } completion:nil];
59 |
60 | NSString *animationKey = [view.layer.animationKeys firstObject];
61 | NSAssert(animationKey != nil, @"Unable to extract animation timing curve: no animation found.");
62 | #pragma clang diagnostic push
63 | // CASpringAnimation is a private API on iOS 8 - we're able to make use of it because we're
64 | // linking against the public API on iOS 9+.
65 | #pragma clang diagnostic ignored "-Wpartial-availability"
66 | CASpringAnimation *springAnimation =
67 | (CASpringAnimation *)[view.layer animationForKey:animationKey];
68 | NSAssert([springAnimation isKindOfClass:[CASpringAnimation class]],
69 | @"Unable to extract animation timing curve: unexpected animation type.");
70 | #pragma clang diagnostic pop
71 |
72 | return [[MDMSpringTimingCurve alloc] initWithMass:springAnimation.mass
73 | tension:springAnimation.stiffness
74 | friction:springAnimation.damping
75 | initialVelocity:self.initialVelocity];
76 | }
77 |
78 | @end
79 |
--------------------------------------------------------------------------------
/src/MDMSubclassingRestricted.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2017-present The Material Motion Authors. All Rights Reserved.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | #import
18 |
19 | #ifndef MDM_SUBCLASSING_RESTRICTED
20 | #if defined(__has_attribute) && __has_attribute(objc_subclassing_restricted)
21 | #define MDM_SUBCLASSING_RESTRICTED __attribute__((objc_subclassing_restricted))
22 | #else
23 | #define MDM_SUBCLASSING_RESTRICTED
24 | #endif
25 | #endif // #ifndef MDM_SUBCLASSING_RESTRICTED
26 |
27 |
--------------------------------------------------------------------------------
/src/MDMTimingCurve.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2017-present The Material Motion Authors. All Rights Reserved.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | #import
18 | #import
19 |
20 | API_DEPRECATED_BEGIN("Use standard UIKit/CALayer animation APIs instead.",
21 | ios(12, API_TO_BE_DEPRECATED))
22 |
23 | /**
24 | A generalized representation of a timing curve.
25 | */
26 | @protocol MDMTimingCurve
27 | @end
28 |
29 | API_DEPRECATED_END
30 |
--------------------------------------------------------------------------------
/src/MotionInterchange.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2017-present The Material Motion Authors. All Rights Reserved.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | // V2 APIs
18 | #import "CAMediaTimingFunction+MDMTimingCurve.h"
19 | #import "MDMAnimationTraits.h"
20 | #import "MDMRepetitionTraits.h"
21 | #import "MDMRepetition.h"
22 | #import "MDMRepetitionOverTime.h"
23 | #import "MDMTimingCurve.h"
24 | #import "MDMSpringTimingCurve.h"
25 | #import "MDMSpringTimingCurveGenerator.h"
26 |
27 | // V1 APIs
28 | #import "MDMMotionCurve.h"
29 | #import "MDMMotionRepetition.h"
30 | #import "MDMMotionTiming.h"
31 |
--------------------------------------------------------------------------------
/tests/unit/CAMediaTimingFunctionTests.swift:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2017-present The Material Motion Authors. All Rights Reserved.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | import XCTest
18 | import MotionInterchange
19 |
20 | class CAMediaTimingFunctionTests: XCTestCase {
21 | func testReversalAlgorithm() {
22 | let curve = CAMediaTimingFunction(controlPoints: 0.1, 0.2, 0.3, 0.4)
23 | let reversed = curve.mdm_reversed()
24 | XCTAssertEqual(curve.mdm_point1.x, 1 - reversed.mdm_point2.x, accuracy: 0.001)
25 | XCTAssertEqual(curve.mdm_point1.y, 1 - reversed.mdm_point2.y, accuracy: 0.001)
26 | XCTAssertEqual(curve.mdm_point2.x, 1 - reversed.mdm_point1.x, accuracy: 0.001)
27 | XCTAssertEqual(curve.mdm_point2.y, 1 - reversed.mdm_point1.y, accuracy: 0.001)
28 | }
29 |
30 | func testReversingBezierCurveTwiceGivesSameResult() {
31 | let curve = CAMediaTimingFunction(controlPoints: 0.1, 0.2, 0.3, 0.4)
32 | let reversed = curve.mdm_reversed()
33 | let reversedAgain = reversed.mdm_reversed()
34 | XCTAssertEqual(curve.mdm_point1.x, reversedAgain.mdm_point1.x, accuracy: 0.001)
35 | XCTAssertEqual(curve.mdm_point1.y, reversedAgain.mdm_point1.y, accuracy: 0.001)
36 | XCTAssertEqual(curve.mdm_point2.x, reversedAgain.mdm_point2.x, accuracy: 0.001)
37 | XCTAssertEqual(curve.mdm_point2.y, reversedAgain.mdm_point2.y, accuracy: 0.001)
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/tests/unit/MDMAnimationTraitsTests.swift:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2017-present The Material Motion Authors. All Rights Reserved.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | import XCTest
18 | import MotionInterchange
19 |
20 | class MDMAnimationTraitsTests: XCTestCase {
21 |
22 | func testInitializerValuesWithDuration() {
23 | let traits = MDMAnimationTraits(duration: 0.5)
24 |
25 | XCTAssertEqual(traits.duration, 0.5, accuracy: 0.001)
26 | XCTAssertEqual(traits.delay, 0, accuracy: 0.001)
27 | XCTAssertTrue(traits.timingCurve is CAMediaTimingFunction)
28 | if let timingCurve = traits.timingCurve as? CAMediaTimingFunction {
29 | let easeInOut = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut)
30 | XCTAssertEqual(timingCurve.mdm_point1.x, easeInOut.mdm_point1.x, accuracy: 0.001)
31 | XCTAssertEqual(timingCurve.mdm_point1.y, easeInOut.mdm_point1.y, accuracy: 0.001)
32 | XCTAssertEqual(timingCurve.mdm_point2.x, easeInOut.mdm_point2.x, accuracy: 0.001)
33 | XCTAssertEqual(timingCurve.mdm_point2.y, easeInOut.mdm_point2.y, accuracy: 0.001)
34 | }
35 | XCTAssertNil(traits.repetition)
36 | }
37 |
38 | func testInitializerValuesWithDurationAndEaseInCurve() {
39 | let traits = MDMAnimationTraits(duration: 0.5, animationCurve: .easeIn)
40 |
41 | XCTAssertEqual(traits.duration, 0.5, accuracy: 0.001)
42 | XCTAssertEqual(traits.delay, 0, accuracy: 0.001)
43 | XCTAssertTrue(traits.timingCurve is CAMediaTimingFunction)
44 | if let timingCurve = traits.timingCurve as? CAMediaTimingFunction {
45 | let easeInOut = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeIn)
46 | XCTAssertEqual(timingCurve.mdm_point1.x, easeInOut.mdm_point1.x, accuracy: 0.001)
47 | XCTAssertEqual(timingCurve.mdm_point1.y, easeInOut.mdm_point1.y, accuracy: 0.001)
48 | XCTAssertEqual(timingCurve.mdm_point2.x, easeInOut.mdm_point2.x, accuracy: 0.001)
49 | XCTAssertEqual(timingCurve.mdm_point2.y, easeInOut.mdm_point2.y, accuracy: 0.001)
50 | }
51 | XCTAssertNil(traits.repetition)
52 | }
53 |
54 | func testInitializerValuesWithDurationDelay() {
55 | let traits = MDMAnimationTraits(delay: 0.2, duration: 0.5)
56 |
57 | XCTAssertEqual(traits.duration, 0.5, accuracy: 0.001)
58 | XCTAssertEqual(traits.delay, 0.2, accuracy: 0.001)
59 | XCTAssertTrue(traits.timingCurve is CAMediaTimingFunction)
60 | if let timingCurve = traits.timingCurve as? CAMediaTimingFunction {
61 | let easeInOut = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut)
62 | XCTAssertEqual(timingCurve.mdm_point1.x, easeInOut.mdm_point1.x, accuracy: 0.001)
63 | XCTAssertEqual(timingCurve.mdm_point1.y, easeInOut.mdm_point1.y, accuracy: 0.001)
64 | XCTAssertEqual(timingCurve.mdm_point2.x, easeInOut.mdm_point2.x, accuracy: 0.001)
65 | XCTAssertEqual(timingCurve.mdm_point2.y, easeInOut.mdm_point2.y, accuracy: 0.001)
66 | }
67 | XCTAssertNil(traits.repetition)
68 | }
69 |
70 | func testInitializerValuesWithDurationDelayNilTimingCurve() {
71 | let traits = MDMAnimationTraits(delay: 0.2, duration: 0.5, timingCurve: nil)
72 |
73 | XCTAssertEqual(traits.duration, 0.5, accuracy: 0.001)
74 | XCTAssertEqual(traits.delay, 0.2, accuracy: 0.001)
75 | XCTAssertNil(traits.timingCurve)
76 | XCTAssertNil(traits.repetition)
77 | }
78 |
79 | func testInitializerValuesWithDurationDelayLinearTimingCurve() {
80 | let linear = CAMediaTimingFunction(name: CAMediaTimingFunctionName.linear)
81 | let traits = MDMAnimationTraits(delay: 0.2, duration: 0.5, timingCurve: linear)
82 |
83 | XCTAssertEqual(traits.duration, 0.5, accuracy: 0.001)
84 | XCTAssertEqual(traits.delay, 0.2, accuracy: 0.001)
85 | XCTAssertTrue(traits.timingCurve is CAMediaTimingFunction)
86 | if let timingCurve = traits.timingCurve as? CAMediaTimingFunction {
87 | XCTAssertEqual(timingCurve.mdm_point1.x, linear.mdm_point1.x, accuracy: 0.001)
88 | XCTAssertEqual(timingCurve.mdm_point1.y, linear.mdm_point1.y, accuracy: 0.001)
89 | XCTAssertEqual(timingCurve.mdm_point2.x, linear.mdm_point2.x, accuracy: 0.001)
90 | XCTAssertEqual(timingCurve.mdm_point2.y, linear.mdm_point2.y, accuracy: 0.001)
91 | }
92 | XCTAssertNil(traits.repetition)
93 | }
94 |
95 | func testInitializerValuesWithDurationDelaySpringTimingCurve() {
96 | let spring = MDMSpringTimingCurve(mass: 0.7, tension: 0.8, friction: 0.9)
97 | let traits = MDMAnimationTraits(delay: 0.2, duration: 0.5, timingCurve: spring)
98 |
99 | XCTAssertEqual(traits.duration, 0.5, accuracy: 0.001)
100 | XCTAssertEqual(traits.delay, 0.2, accuracy: 0.001)
101 | XCTAssertTrue(traits.timingCurve is MDMSpringTimingCurve)
102 | if let timingCurve = traits.timingCurve as? MDMSpringTimingCurve {
103 | XCTAssertEqual(timingCurve.mass, spring.mass, accuracy: 0.001)
104 | XCTAssertEqual(timingCurve.friction, spring.friction, accuracy: 0.001)
105 | XCTAssertEqual(timingCurve.tension, spring.tension, accuracy: 0.001)
106 | XCTAssertEqual(timingCurve.initialVelocity, spring.initialVelocity,
107 | accuracy: 0.001)
108 | }
109 | XCTAssertNil(traits.repetition)
110 | }
111 |
112 | func testInitializerValuesWithDurationDelayNilTimingCurveRepetition() {
113 | let repetition = MDMRepetition(numberOfRepetitions: 5)
114 | let traits = MDMAnimationTraits(delay: 0.2,
115 | duration: 0.5,
116 | timingCurve: nil,
117 | repetition: repetition)
118 |
119 | XCTAssertEqual(traits.duration, 0.5, accuracy: 0.001)
120 | XCTAssertEqual(traits.delay, 0.2, accuracy: 0.001)
121 | XCTAssertNil(traits.timingCurve)
122 | XCTAssertTrue(traits.repetition is MDMRepetition)
123 | if let setRepetition = traits.repetition as? MDMRepetition {
124 | XCTAssertEqual(setRepetition.numberOfRepetitions, repetition.numberOfRepetitions,
125 | accuracy: 0.001)
126 | XCTAssertEqual(setRepetition.autoreverses, repetition.autoreverses)
127 | }
128 | }
129 |
130 | func testModifyingACopyDoesNotModifyTheOriginal() {
131 | let spring = MDMSpringTimingCurve(mass: 0.7, tension: 0.8, friction: 0.9)
132 | let repetition = MDMRepetition(numberOfRepetitions: 5)
133 | let traits = MDMAnimationTraits(delay: 0.2,
134 | duration: 0.5,
135 | timingCurve: spring,
136 | repetition: repetition)
137 |
138 | let copy = traits.copy() as! MDMAnimationTraits
139 | copy.delay = copy.delay + 1
140 | copy.duration = copy.duration + 1
141 | if let springCopy = copy.timingCurve as? MDMSpringTimingCurve {
142 | springCopy.friction = springCopy.friction + 1
143 | springCopy.tension = springCopy.tension + 1
144 | springCopy.mass = springCopy.mass + 1
145 | springCopy.initialVelocity = springCopy.initialVelocity + 1
146 |
147 | XCTAssertNotEqual(springCopy.friction, spring.friction, accuracy: 0.001)
148 | XCTAssertNotEqual(springCopy.tension, spring.tension, accuracy: 0.001)
149 | XCTAssertNotEqual(springCopy.mass, spring.mass, accuracy: 0.001)
150 | XCTAssertNotEqual(springCopy.initialVelocity, spring.initialVelocity, accuracy: 0.001)
151 | }
152 | if let repetitionCopy = copy.repetition as? MDMRepetition {
153 | repetitionCopy.autoreverses = !repetitionCopy.autoreverses
154 | repetitionCopy.numberOfRepetitions = repetitionCopy.numberOfRepetitions + 1
155 |
156 | XCTAssertNotEqual(repetitionCopy.autoreverses, repetition.autoreverses)
157 | XCTAssertNotEqual(repetitionCopy.numberOfRepetitions, repetition.numberOfRepetitions)
158 | }
159 |
160 | XCTAssertNotEqual(copy.duration, traits.duration, accuracy: 0.001)
161 | XCTAssertNotEqual(copy.delay, traits.delay, accuracy: 0.001)
162 | }
163 | }
164 |
--------------------------------------------------------------------------------
/tests/unit/MDMLegacyAPITests.swift:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2017-present The Material Motion Authors. All Rights Reserved.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | import XCTest
18 | import MotionInterchange
19 |
20 | class MDMLegacyAPITests: XCTestCase {
21 |
22 | func testTimingValuesMatchTraitValues() {
23 | let timing = MotionTiming(delay: 0.1,
24 | duration: 0.2,
25 | curve: MotionCurveMakeBezier(p1x: 0.3, p1y: 0.4, p2x: 0.5, p2y: 0.6),
26 | repetition: .init(type: .duration, amount: 0.7, autoreverses: true))
27 |
28 | let traits = MDMAnimationTraits(motionTiming: timing)
29 |
30 | XCTAssertEqual(traits.duration, timing.duration, accuracy: 0.001)
31 | XCTAssertEqual(traits.delay, timing.delay, accuracy: 0.001)
32 | XCTAssertTrue(traits.timingCurve is CAMediaTimingFunction)
33 | if let timingCurve = traits.timingCurve as? CAMediaTimingFunction {
34 | XCTAssertEqual(timingCurve.mdm_point1.x, timing.curve.data.0, accuracy: 0.001)
35 | XCTAssertEqual(timingCurve.mdm_point1.y, timing.curve.data.1, accuracy: 0.001)
36 | XCTAssertEqual(timingCurve.mdm_point2.x, timing.curve.data.2, accuracy: 0.001)
37 | XCTAssertEqual(timingCurve.mdm_point2.y, timing.curve.data.3, accuracy: 0.001)
38 | }
39 | XCTAssertTrue(traits.repetition is MDMRepetitionOverTime)
40 | if let repetition = traits.repetition as? MDMRepetitionOverTime {
41 | XCTAssertEqual(repetition.duration, timing.repetition.amount, accuracy: 0.001)
42 | XCTAssertEqual(repetition.autoreverses, timing.repetition.autoreverses.boolValue)
43 | }
44 | }
45 |
46 | }
47 |
48 |
--------------------------------------------------------------------------------
/tests/unit/MDMModalMovementTimingTests.m:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2017-present The Material Motion Authors. All Rights Reserved.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | #import
18 |
19 | #import "MotionInterchange.h"
20 |
21 | @interface MDMAnimationTraitsSystemModalMovementTests : XCTestCase
22 | @property(nonatomic, strong) UIWindow *window;
23 | @end
24 |
25 | @interface ModalPresentationExtractionViewController : UIViewController
26 | @property(nonatomic, strong) CAAnimation *presentationPositionAnimation;
27 | @end
28 |
29 | @implementation ModalPresentationExtractionViewController
30 |
31 | - (void)viewDidLayoutSubviews {
32 | [super viewDidLayoutSubviews];
33 |
34 | // We just want the first position key path animation that affects this view controller.
35 | if (!self.presentationPositionAnimation) {
36 | UIView *iterator = self.view;
37 | while (iterator != nil && self.presentationPositionAnimation == nil) {
38 | self.presentationPositionAnimation = [iterator.layer animationForKey:@"position"];
39 | iterator = iterator.superview;
40 | }
41 | }
42 | }
43 |
44 | @end
45 |
46 | @implementation MDMAnimationTraitsSystemModalMovementTests
47 |
48 | - (void)setUp {
49 | [super setUp];
50 |
51 | self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
52 | self.window.rootViewController = [[UIViewController alloc] initWithNibName:nil bundle:nil];
53 | [self.window makeKeyAndVisible];
54 | }
55 |
56 | - (void)tearDown {
57 | self.window = nil;
58 |
59 | [super tearDown];
60 | }
61 |
62 | - (void)testSystemModalMovementTimingCurveMatchesModalMovementTiming {
63 | ModalPresentationExtractionViewController *presentedViewController =
64 | [[ModalPresentationExtractionViewController alloc] initWithNibName:nil bundle:nil];
65 | XCTestExpectation *didComplete = [self expectationWithDescription:@"Animation completed"];
66 | [self.window.rootViewController presentViewController:presentedViewController
67 | animated:YES
68 | completion:^{
69 | [didComplete fulfill];
70 | }];
71 |
72 | [self waitForExpectationsWithTimeout:1 handler:nil];
73 |
74 | XCTAssertTrue([presentedViewController.presentationPositionAnimation
75 | isKindOfClass:[CASpringAnimation class]]);
76 | CASpringAnimation *springAnimation =
77 | (CASpringAnimation *)presentedViewController.presentationPositionAnimation;
78 |
79 | MDMAnimationTraits *traits = [MDMAnimationTraits systemModalMovement];
80 | XCTAssertTrue([traits.timingCurve isKindOfClass:[MDMSpringTimingCurve class]],
81 | @"Expected the system timing curve to be a %@ type, but it was '%@' instead.",
82 | NSStringFromClass([MDMSpringTimingCurve class]),
83 | NSStringFromClass([traits.timingCurve class]));
84 | if ([traits.timingCurve isKindOfClass:[MDMSpringTimingCurve class]]) {
85 | MDMSpringTimingCurve *spring = (MDMSpringTimingCurve *)traits.timingCurve;
86 |
87 | XCTAssertEqualWithAccuracy(spring.mass, springAnimation.mass, 0.001);
88 | XCTAssertEqualWithAccuracy(spring.tension, springAnimation.stiffness, 0.001);
89 | XCTAssertEqualWithAccuracy(spring.friction, springAnimation.damping, 0.001);
90 | if ([springAnimation respondsToSelector:@selector(initialVelocity)]) {
91 | XCTAssertEqualWithAccuracy(spring.initialVelocity, springAnimation.initialVelocity, 0.001);
92 | }
93 | }
94 | }
95 |
96 | @end
97 |
--------------------------------------------------------------------------------
/tests/unit/MDMMotionCurveTests.m:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2017-present The Material Motion Authors. All Rights Reserved.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | #import
18 |
19 | #import "MotionInterchange.h"
20 |
21 | @interface MDMMotionCurveTests : XCTestCase
22 | @end
23 |
24 | @implementation MDMMotionCurveTests
25 |
26 | - (void)testLinearCurveConstantMatchesSystemLinearCurve {
27 | MDMMotionCurve curve = MDMLinearMotionCurve;
28 | CAMediaTimingFunction *linearTimingFunction =
29 | [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
30 | MDMMotionCurve systemLinearCurve = MDMMotionCurveFromTimingFunction(linearTimingFunction);
31 | XCTAssertEqualWithAccuracy(curve.data[MDMBezierMotionCurveDataIndexP1X],
32 | systemLinearCurve.data[MDMBezierMotionCurveDataIndexP1X],
33 | 0.001);
34 | XCTAssertEqualWithAccuracy(curve.data[MDMBezierMotionCurveDataIndexP1Y],
35 | systemLinearCurve.data[MDMBezierMotionCurveDataIndexP1Y],
36 | 0.001);
37 | XCTAssertEqualWithAccuracy(curve.data[MDMBezierMotionCurveDataIndexP2X],
38 | systemLinearCurve.data[MDMBezierMotionCurveDataIndexP2X],
39 | 0.001);
40 | XCTAssertEqualWithAccuracy(curve.data[MDMBezierMotionCurveDataIndexP2Y],
41 | systemLinearCurve.data[MDMBezierMotionCurveDataIndexP2Y],
42 | 0.001);
43 | }
44 |
45 | - (void)testBezierCurveData {
46 | MDMMotionCurve curve = MDMMotionCurveMakeBezier(0.1f, 0.2f, 0.3f, 0.4f);
47 | XCTAssertEqualWithAccuracy(curve.data[MDMBezierMotionCurveDataIndexP1X], 0.1, 0.001);
48 | XCTAssertEqualWithAccuracy(curve.data[MDMBezierMotionCurveDataIndexP1Y], 0.2, 0.001);
49 | XCTAssertEqualWithAccuracy(curve.data[MDMBezierMotionCurveDataIndexP2X], 0.3, 0.001);
50 | XCTAssertEqualWithAccuracy(curve.data[MDMBezierMotionCurveDataIndexP2Y], 0.4, 0.001);
51 | }
52 |
53 | - (void)testSpringCurveData {
54 | MDMMotionCurve curve = MDMMotionCurveMakeSpring(0.1f, 0.2f, 0.3f);
55 | XCTAssertEqualWithAccuracy(curve.data[MDMSpringMotionCurveDataIndexMass], 0.1, 0.001);
56 | XCTAssertEqualWithAccuracy(curve.data[MDMSpringMotionCurveDataIndexTension], 0.2, 0.001);
57 | XCTAssertEqualWithAccuracy(curve.data[MDMSpringMotionCurveDataIndexFriction], 0.3, 0.001);
58 | }
59 |
60 | - (void)testBezierCurveDataWithMacro {
61 | MDMMotionCurve curve = _MDMBezier(0.1, 0.2, 0.3, 0.4);
62 | XCTAssertEqualWithAccuracy(curve.data[MDMBezierMotionCurveDataIndexP1X], 0.1, 0.001);
63 | XCTAssertEqualWithAccuracy(curve.data[MDMBezierMotionCurveDataIndexP1Y], 0.2, 0.001);
64 | XCTAssertEqualWithAccuracy(curve.data[MDMBezierMotionCurveDataIndexP2X], 0.3, 0.001);
65 | XCTAssertEqualWithAccuracy(curve.data[MDMBezierMotionCurveDataIndexP2Y], 0.4, 0.001);
66 | }
67 |
68 | - (void)testSpringCurveDataWithMacro {
69 | MDMMotionCurve curve = _MDMSpring(0.1, 0.2, 0.3);
70 | XCTAssertEqualWithAccuracy(curve.data[MDMSpringMotionCurveDataIndexMass], 0.1, 0.001);
71 | XCTAssertEqualWithAccuracy(curve.data[MDMSpringMotionCurveDataIndexTension], 0.2, 0.001);
72 | XCTAssertEqualWithAccuracy(curve.data[MDMSpringMotionCurveDataIndexFriction], 0.3, 0.001);
73 | }
74 |
75 | @end
76 |
--------------------------------------------------------------------------------
/tests/unit/MDMMotionCurveTests.swift:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2017-present The Material Motion Authors. All Rights Reserved.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | import XCTest
18 | import MotionInterchange
19 |
20 | class MDMMotionCurveTests: XCTestCase {
21 |
22 | func testBezierCurveData() {
23 | let curve = MotionCurveMakeBezier(p1x: 0.1, p1y: 0.2, p2x: 0.3, p2y: 0.4)
24 | XCTAssertEqual(curve.data.0, 0.1, accuracy: 0.001)
25 | XCTAssertEqual(curve.data.1, 0.2, accuracy: 0.001)
26 | XCTAssertEqual(curve.data.2, 0.3, accuracy: 0.001)
27 | XCTAssertEqual(curve.data.3, 0.4, accuracy: 0.001)
28 | }
29 |
30 | func testBezierCurveFromTimingFunction() {
31 | let timingFunction = CAMediaTimingFunction(controlPoints: 0.1, 0.2, 0.3, 0.4)
32 | let curve = MotionCurve(fromTimingFunction: timingFunction)
33 | XCTAssertEqual(curve.data.0, 0.1, accuracy: 0.001)
34 | XCTAssertEqual(curve.data.1, 0.2, accuracy: 0.001)
35 | XCTAssertEqual(curve.data.2, 0.3, accuracy: 0.001)
36 | XCTAssertEqual(curve.data.3, 0.4, accuracy: 0.001)
37 | }
38 |
39 | func testSpringCurveData() {
40 | let curve = MotionCurveMakeSpring(mass: 0.1, tension: 0.2, friction: 0.3)
41 | XCTAssertEqual(curve.data.0, 0.1, accuracy: 0.001) // mass
42 | XCTAssertEqual(curve.data.1, 0.2, accuracy: 0.001) // tension
43 | XCTAssertEqual(curve.data.2, 0.3, accuracy: 0.001) // friction
44 | XCTAssertEqual(curve.data.3, 0.0, accuracy: 0.001)
45 | }
46 |
47 | func testReversedBezierCurve() {
48 | let curve = MotionCurveMakeBezier(p1x: 0.1, p1y: 0.2, p2x: 0.3, p2y: 0.4)
49 | let reversed = MotionCurveReversedBezier(fromMotionCurve: curve)
50 | XCTAssertEqual(curve.data.0, 1 - reversed.data.2, accuracy: 0.001)
51 | XCTAssertEqual(curve.data.1, 1 - reversed.data.3, accuracy: 0.001)
52 | XCTAssertEqual(curve.data.2, 1 - reversed.data.0, accuracy: 0.001)
53 | XCTAssertEqual(curve.data.3, 1 - reversed.data.1, accuracy: 0.001)
54 | }
55 |
56 | func testReversingBezierCurveTwiceGivesSameResult() {
57 | let curve = MotionCurveMakeBezier(p1x: 0.1, p1y: 0.2, p2x: 0.3, p2y: 0.4)
58 | let reversed = MotionCurveReversedBezier(fromMotionCurve: curve)
59 | let reversedAgain = MotionCurveReversedBezier(fromMotionCurve: reversed)
60 | XCTAssertEqual(curve.data.0, reversedAgain.data.0, accuracy: 0.001)
61 | XCTAssertEqual(curve.data.1, reversedAgain.data.1, accuracy: 0.001)
62 | XCTAssertEqual(curve.data.2, reversedAgain.data.2, accuracy: 0.001)
63 | XCTAssertEqual(curve.data.3, reversedAgain.data.3, accuracy: 0.001)
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/tests/unit/MDMRepetitionOverTimeTests.swift:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2017-present The Material Motion Authors. All Rights Reserved.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | import XCTest
18 | import MotionInterchange
19 |
20 | class MDMRepetitionOverTimeTests: XCTestCase {
21 |
22 | func testInitializationWithDuration() {
23 | let repetition = MDMRepetitionOverTime(duration: 5.5)
24 | XCTAssertEqual(repetition.duration, 5.5, accuracy: 0.001)
25 | XCTAssertFalse(repetition.autoreverses)
26 | }
27 |
28 | func testInitializationWithDurationAndAutoreversed() {
29 | let repetition = MDMRepetitionOverTime(duration: 5.5, autoreverses: true)
30 | XCTAssertEqual(repetition.duration, 5.5, accuracy: 0.001)
31 | XCTAssertTrue(repetition.autoreverses)
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/tests/unit/MDMRepetitionTests.swift:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2017-present The Material Motion Authors. All Rights Reserved.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | import XCTest
18 | import MotionInterchange
19 |
20 | class MDMRepetitionTests: XCTestCase {
21 |
22 | func testInitializationWithNumberOfRepetitions() {
23 | let repetition = MDMRepetition(numberOfRepetitions: 5.5)
24 | XCTAssertEqual(repetition.numberOfRepetitions, 5.5, accuracy: 0.001)
25 | XCTAssertFalse(repetition.autoreverses)
26 | }
27 |
28 | func testInitializationWithNumberOfRepetitionsAndAutoreversed() {
29 | let repetition = MDMRepetition(numberOfRepetitions: 5.5, autoreverses: true)
30 | XCTAssertEqual(repetition.numberOfRepetitions, 5.5, accuracy: 0.001)
31 | XCTAssertTrue(repetition.autoreverses)
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/tests/unit/MDMSpringTimingCurve.swift:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2017-present The Material Motion Authors. All Rights Reserved.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | import XCTest
18 | import MotionInterchange
19 |
20 | class MDMTimingCurveTests: XCTestCase {
21 |
22 | func testInitializerValuesWithNoInitialVelocity() {
23 | let curve = MDMSpringTimingCurve(mass: 0.1, tension: 0.2, friction: 0.3)
24 | XCTAssertEqual(curve.mass, 0.1, accuracy: 0.001)
25 | XCTAssertEqual(curve.tension, 0.2, accuracy: 0.001)
26 | XCTAssertEqual(curve.friction, 0.3, accuracy: 0.001)
27 | XCTAssertEqual(curve.initialVelocity, 0.0, accuracy: 0.001)
28 | }
29 |
30 | func testInitializerValuesWithInitialVelocity() {
31 | let curve = MDMSpringTimingCurve(mass: 0.1, tension: 0.2, friction: 0.3, initialVelocity: 0.4)
32 | XCTAssertEqual(curve.mass, 0.1, accuracy: 0.001)
33 | XCTAssertEqual(curve.tension, 0.2, accuracy: 0.001)
34 | XCTAssertEqual(curve.friction, 0.3, accuracy: 0.001)
35 | XCTAssertEqual(curve.initialVelocity, 0.4, accuracy: 0.001)
36 | }
37 |
38 | @available(iOS 9.0, *)
39 | func testInitializerValuesWithDampingCoefficient() {
40 | for duration in stride(from: TimeInterval(0.1), to: TimeInterval(3), by: TimeInterval(0.5)) {
41 | for dampingRatio in stride(from: CGFloat(0.1), to: CGFloat(2), by: CGFloat(0.4)) {
42 | for initialVel in stride(from: CGFloat(-2), to: CGFloat(2), by: CGFloat(0.8)) {
43 | let generator = MDMSpringTimingCurveGenerator(duration: duration,
44 | dampingRatio: dampingRatio,
45 | initialVelocity: initialVel)
46 | let view = UIView()
47 |
48 | UIView.animate(withDuration: duration,
49 | delay: 0,
50 | usingSpringWithDamping: dampingRatio,
51 | initialSpringVelocity: initialVel,
52 | options: [],
53 | animations: {
54 | view.center = CGPoint(x: initialVel * 5, y: dampingRatio * 10)
55 | }, completion: nil)
56 |
57 | if let animationKey = view.layer.animationKeys()?.first,
58 | let animation = view.layer.animation(forKey: animationKey) as? CASpringAnimation {
59 |
60 | let curve = generator.springTimingCurve()
61 | XCTAssertEqual(curve.mass, animation.mass, accuracy: 0.001)
62 | XCTAssertEqual(curve.tension, animation.stiffness, accuracy: 0.001)
63 | XCTAssertEqual(curve.friction, animation.damping, accuracy: 0.001)
64 | if animation.responds(to: #selector(initialVelocity)) {
65 | XCTAssertEqual(curve.initialVelocity, animation.initialVelocity, accuracy: 0.001)
66 | }
67 | }
68 | }
69 | }
70 | }
71 | }
72 |
73 | // Dummy getter for #selector(initialVelocity) reference.
74 | func initialVelocity() {
75 | }
76 | }
77 |
--------------------------------------------------------------------------------