From 0f6bf48522cee1894fcdadfab3f6a0e13cc7086a Mon Sep 17 00:00:00 2001 From: Jeff Verkoeyen Date: Fri, 1 Dec 2017 15:14:18 -0500 Subject: [PATCH 01/13] Add v2 apis. --- .../project.pbxproj | 8 + scripts/v1_to_v2.sh | 40 ++++ src/CFEnumType.h | 25 +++ ...MDMMotionTiming.h => MDMAnimationTraits.h} | 20 +- src/MDMAnimationTraits.m | 23 +++ src/MDMMotionCurve.h | 194 ------------------ ...tionRepetition.h => MDMRepetitionTraits.h} | 29 +-- src/MDMTimingCurve.h | 152 ++++++++++++++ src/{MDMMotionCurve.m => MDMTimingCurve.m} | 36 ++-- src/MotionInterchange.h | 6 +- tests/unit/MDMModalMovementTimingTests.m | 31 ++- tests/unit/MDMTimingCurveTests.m | 60 ++++++ tests/unit/MDMTimingCurveTests.swift | 65 ++++++ 13 files changed, 450 insertions(+), 239 deletions(-) create mode 100755 scripts/v1_to_v2.sh create mode 100644 src/CFEnumType.h rename src/{MDMMotionTiming.h => MDMAnimationTraits.h} (72%) create mode 100644 src/MDMAnimationTraits.m delete mode 100644 src/MDMMotionCurve.h rename src/{MDMMotionRepetition.h => MDMRepetitionTraits.h} (61%) create mode 100644 src/MDMTimingCurve.h rename src/{MDMMotionCurve.m => MDMTimingCurve.m} (53%) create mode 100644 tests/unit/MDMTimingCurveTests.m create mode 100644 tests/unit/MDMTimingCurveTests.swift diff --git a/examples/apps/Catalog/MotionInterchangeCatalog.xcodeproj/project.pbxproj b/examples/apps/Catalog/MotionInterchangeCatalog.xcodeproj/project.pbxproj index c0139ca..321abb6 100644 --- a/examples/apps/Catalog/MotionInterchangeCatalog.xcodeproj/project.pbxproj +++ b/examples/apps/Catalog/MotionInterchangeCatalog.xcodeproj/project.pbxproj @@ -7,6 +7,8 @@ objects = { /* Begin PBXBuildFile section */ + 660248AE1FD1EE78004C0147 /* MDMTimingCurveTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 660248AC1FD1EE78004C0147 /* MDMTimingCurveTests.swift */; }; + 660248AF1FD1EE78004C0147 /* MDMTimingCurveTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 660248AD1FD1EE78004C0147 /* MDMTimingCurveTests.m */; }; 6619E1D91FA0ED0300F3AB25 /* MDMModalMovementTimingTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 6619E1D81FA0ED0300F3AB25 /* MDMModalMovementTimingTests.m */; }; 663ED7C51EDF1F0C0096B2A9 /* ExampleViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 663ED7C01EDF1F0C0096B2A9 /* ExampleViewController.swift */; }; 663ED7C61EDF1F0C0096B2A9 /* ExampleViews.swift in Sources */ = {isa = PBXBuildFile; fileRef = 663ED7C11EDF1F0C0096B2A9 /* ExampleViews.swift */; }; @@ -47,6 +49,8 @@ 09CEA5DEA01BA723D08D84E6 /* Pods-UnitTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-UnitTests.release.xcconfig"; path = "../../../Pods/Target Support Files/Pods-UnitTests/Pods-UnitTests.release.xcconfig"; sourceTree = ""; }; 2DE76D4D35953D836F578CDE /* Pods-MotionInterchangeCatalog.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MotionInterchangeCatalog.debug.xcconfig"; path = "../../../Pods/Target Support Files/Pods-MotionInterchangeCatalog/Pods-MotionInterchangeCatalog.debug.xcconfig"; sourceTree = ""; }; 4AAB8EBB088513D48896641A /* Pods-MotionInterchangeCatalog.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MotionInterchangeCatalog.release.xcconfig"; path = "../../../Pods/Target Support Files/Pods-MotionInterchangeCatalog/Pods-MotionInterchangeCatalog.release.xcconfig"; sourceTree = ""; }; + 660248AC1FD1EE78004C0147 /* MDMTimingCurveTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MDMTimingCurveTests.swift; sourceTree = ""; }; + 660248AD1FD1EE78004C0147 /* MDMTimingCurveTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MDMTimingCurveTests.m; sourceTree = ""; }; 6619E1D81FA0ED0300F3AB25 /* MDMModalMovementTimingTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MDMModalMovementTimingTests.m; sourceTree = ""; }; 663ED7C01EDF1F0C0096B2A9 /* ExampleViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExampleViewController.swift; sourceTree = ""; }; 663ED7C11EDF1F0C0096B2A9 /* ExampleViews.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExampleViews.swift; sourceTree = ""; }; @@ -165,6 +169,8 @@ 663ED8001EE628BA0096B2A9 /* MDMMotionCurveTests.swift */, 663ED8021EE6299A0096B2A9 /* MDMMotionCurveTests.m */, 6619E1D81FA0ED0300F3AB25 /* MDMModalMovementTimingTests.m */, + 660248AD1FD1EE78004C0147 /* MDMTimingCurveTests.m */, + 660248AC1FD1EE78004C0147 /* MDMTimingCurveTests.swift */, ); name = tests; path = ../../../tests/unit; @@ -480,6 +486,8 @@ files = ( 663ED8031EE6299A0096B2A9 /* MDMMotionCurveTests.m in Sources */, 663ED8011EE628BA0096B2A9 /* MDMMotionCurveTests.swift in Sources */, + 660248AE1FD1EE78004C0147 /* MDMTimingCurveTests.swift in Sources */, + 660248AF1FD1EE78004C0147 /* MDMTimingCurveTests.m in Sources */, 6619E1D91FA0ED0300F3AB25 /* MDMModalMovementTimingTests.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/scripts/v1_to_v2.sh b/scripts/v1_to_v2.sh new file mode 100755 index 0000000..6131995 --- /dev/null +++ b/scripts/v1_to_v2.sh @@ -0,0 +1,40 @@ +#!/bin/bash +# +# Copyright 2017-present The Material Motion Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Migration script from v1 to v2 interchange APIs. + +if [ "$#" -ne 1 ]; then + echo "Usage: $(basename $0) " + exit 1 +fi + +search_path="$1" + +replace_all() { + find "$search_path" -type f -name "*.h" | xargs sed -i '' "$1" + find "$search_path" -type f -name "*.m" | xargs sed -i '' "$1" + find "$search_path" -type f -name "*.swift" | xargs sed -i '' "$1" +} + +replace_all "s/MDMBezierTimingCurveDataIndex/MDMTimingCurveBezierDataIndex/g" +replace_all "s/MDMSpringTimingCurveDataIndex/MDMTimingCurveSpringDataIndex/g" +replace_all "s/MotionCurveMakeSpring(mass/TimingCurve(springWithMass/g" +replace_all "s/MDMLinearTimingCurve/MDMTimingCurveLinear/g" +replace_all "s/timing.curve/traits.timingCurve/g" +replace_all "s/.curve/.timingCurve/g" +replace_all "s/MotionCurve/TimingCurve/g" +replace_all "s/MotionTiming timing/AnimationTraits traits/g" +replace_all "s/MotionTiming/AnimationTraits/g" diff --git a/src/CFEnumType.h b/src/CFEnumType.h new file mode 100644 index 0000000..8be62b7 --- /dev/null +++ b/src/CFEnumType.h @@ -0,0 +1,25 @@ +/* + Copyright 2017-present The Material Motion Authors. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +// This macro is introduced in Xcode 9. +#ifndef CF_TYPED_ENUM // What follows is backwards compat for Xcode 8 and below. +#if __has_attribute(swift_wrapper) +#define CF_TYPED_ENUM __attribute__((swift_wrapper(enum))) +#else +#define CF_TYPED_ENUM +#endif +#endif + diff --git a/src/MDMMotionTiming.h b/src/MDMAnimationTraits.h similarity index 72% rename from src/MDMMotionTiming.h rename to src/MDMAnimationTraits.h index b225570..25d3cbe 100644 --- a/src/MDMMotionTiming.h +++ b/src/MDMAnimationTraits.h @@ -17,13 +17,13 @@ #import #import -#import "MDMMotionCurve.h" -#import "MDMMotionRepetition.h" +#import "MDMRepetitionTraits.h" +#import "MDMTimingCurve.h" /** - A representation of timing for an animation. + A generic representation of animation traits. */ -struct MDMMotionTiming { +typedef struct MDMAnimationTraits { /** The amount of time, in seconds, before this animation's value interpolation should begin. */ @@ -37,12 +37,16 @@ struct MDMMotionTiming { /** The velocity and acceleration of the animation over time. */ - MDMMotionCurve curve; + MDMTimingCurve timingCurve; /** The repetition characteristics of the animation. */ - MDMMotionRepetition repetition; + MDMRepetitionTraits repetition; -} NS_SWIFT_NAME(MotionTiming); -typedef struct MDMMotionTiming MDMMotionTiming; +} NS_SWIFT_NAME(AnimationTraits) MDMAnimationTraits; + +/** + Animation traits for an iOS modal presentation slide animation. + */ +FOUNDATION_EXPORT const MDMAnimationTraits MDMAnimationTraitsSystemModalMovement; diff --git a/src/MDMAnimationTraits.m b/src/MDMAnimationTraits.m new file mode 100644 index 0000000..964139c --- /dev/null +++ b/src/MDMAnimationTraits.m @@ -0,0 +1,23 @@ +/* + Copyright 2017-present The Material Motion Authors. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "MDMAnimationTraits.h" + +const MDMAnimationTraits MDMAnimationTraitsSystemModalMovement = { + .duration = 0.500, .timingCurve = { + .type = MDMTimingCurveTypeSpring, .data = { 3, 1000, 500, 0 } + } +}; diff --git a/src/MDMMotionCurve.h b/src/MDMMotionCurve.h deleted file mode 100644 index 0b233eb..0000000 --- a/src/MDMMotionCurve.h +++ /dev/null @@ -1,194 +0,0 @@ -/* - Copyright 2017-present The Material Motion Authors. All Rights Reserved. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - */ - -#import -#import -#import - -/** - The possible kinds of motion curves that can be used to describe an animation. - */ -typedef NS_ENUM(NSUInteger, MDMMotionCurveType) { - /** - The value will be instantly set with no animation. - */ - MDMMotionCurveTypeInstant, - - /** - The value will be animated using a cubic bezier curve to model its velocity. - */ - MDMMotionCurveTypeBezier, - - /** - The value will be animated using a spring simulation. - - A spring will treat the duration property of the motion timing as a suggestion and may choose to - ignore it altogether. - */ - MDMMotionCurveTypeSpring, - - /** - The default curve will be used. - */ - MDMMotionCurveTypeDefault __deprecated_enum_msg("Use MDMMotionCurveTypeBezier instead."), - -} NS_SWIFT_NAME(MotionCurveType); - -/** - A generalized representation of a motion curve. - */ -struct MDMMotionCurve { - /** - The type defines how to interpret the data values. - */ - MDMMotionCurveType type; - - /** - The data values corresponding with this curve. - */ - CGFloat data[4]; -} NS_SWIFT_NAME(MotionCurve); -typedef struct MDMMotionCurve MDMMotionCurve; - -/** - Creates a bezier motion curve with the provided control points. - - A cubic bezier has four control points in total. We assume that the first control point is 0, 0 and - the last control point is 1, 1. This method requires that you provide the second and third control - points. - - See the documentation for CAMediaTimingFunction for more information. - */ -// clang-format off -FOUNDATION_EXTERN -MDMMotionCurve MDMMotionCurveMakeBezier(CGFloat p1x, CGFloat p1y, CGFloat p2x, CGFloat p2y) - NS_SWIFT_NAME(MotionCurveMakeBezier(p1x:p1y:p2x:p2y:)); -// clang-format on - -// clang-format off -FOUNDATION_EXTERN -MDMMotionCurve MDMMotionCurveFromTimingFunction(CAMediaTimingFunction * _Nonnull timingFunction) - NS_SWIFT_NAME(MotionCurve(fromTimingFunction:)); -// clang-format on - -/** - Creates a spring curve with the provided configuration. - - Tension and friction map to Core Animation's stiffness and damping, respectively. - - See the documentation for CASpringAnimation for more information. - */ -// clang-format off -FOUNDATION_EXTERN MDMMotionCurve MDMMotionCurveMakeSpring(CGFloat mass, - CGFloat tension, - CGFloat friction) - NS_SWIFT_NAME(MotionCurveMakeSpring(mass:tension:friction:)); -// clang-format on - -/** - Creates a spring curve with the provided configuration. - - Tension and friction map to Core Animation's stiffness and damping, respectively. - - See the documentation for CASpringAnimation for more information. - */ -// clang-format off -FOUNDATION_EXTERN -MDMMotionCurve MDMMotionCurveMakeSpringWithInitialVelocity(CGFloat mass, - CGFloat tension, - CGFloat friction, - CGFloat initialVelocity) - NS_SWIFT_NAME(MotionCurveMakeSpring(mass:tension:friction:initialVelocity:)); -// clang-format on - -/** - For cubic bezier curves, returns a reversed cubic bezier curve. For all other curve types, a copy - of the original curve is returned. - */ -// clang-format off -FOUNDATION_EXTERN MDMMotionCurve MDMMotionCurveReversedBezier(MDMMotionCurve motionCurve) - NS_SWIFT_NAME(MotionCurveReversedBezier(fromMotionCurve:)); -// clang-format on - -/** - Named indices for the bezier motion curve's data array. - */ -typedef NS_ENUM(NSUInteger, MDMBezierMotionCurveDataIndex) { - MDMBezierMotionCurveDataIndexP1X, - MDMBezierMotionCurveDataIndexP1Y, - MDMBezierMotionCurveDataIndexP2X, - MDMBezierMotionCurveDataIndexP2Y -} NS_SWIFT_NAME(BezierMotionCurveDataIndex); - -/** - Named indices for the spring motion curve's data array. - */ -typedef NS_ENUM(NSUInteger, MDMSpringMotionCurveDataIndex) { - MDMSpringMotionCurveDataIndexMass, - MDMSpringMotionCurveDataIndexTension, - MDMSpringMotionCurveDataIndexFriction, - - /** - The initial velocity of the animation. - - A value of zero indicates no initial velocity. - A positive value indicates movement toward the destination. - A negative value indicates movement away from the destination. - - The value's units are dependent on the context and the value being animated. - */ - MDMSpringMotionCurveDataIndexInitialVelocity -} NS_SWIFT_NAME(SpringMotionCurveDataIndex); - -// Objective-C-specific macros - -#define _MDMBezier(p1x, p1y, p2x, p2y) \ - ((MDMMotionCurve) { \ - .type = MDMMotionCurveTypeBezier, \ - .data = { p1x, \ - p1y, \ - p2x, \ - p2y } \ - }) - -#define _MDMSpring(mass, tension, friction) \ - ((MDMMotionCurve) { \ - .type = MDMMotionCurveTypeSpring, \ - .data = { mass, \ - tension, \ - friction } \ - }) - -#define _MDMSpringWithInitialVelocity(mass, tension, friction, initialVelocity) \ - ((MDMMotionCurve) { \ - .type = MDMMotionCurveTypeSpring, \ - .data = { mass, \ - tension, \ - friction, \ - initialVelocity } \ - }) - -/** - A linear bezier motion curve. - */ -#define MDMLinearMotionCurve _MDMBezier(0, 0, 1, 1) - -/** - Timing information for an iOS modal presentation slide animation. - */ -#define MDMModalMovementTiming { \ - .delay = 0.000, .duration = 0.500, .curve = _MDMSpring(3, 1000, 500) \ -} diff --git a/src/MDMMotionRepetition.h b/src/MDMRepetitionTraits.h similarity index 61% rename from src/MDMMotionRepetition.h rename to src/MDMRepetitionTraits.h index 94fc266..820e542 100644 --- a/src/MDMMotionRepetition.h +++ b/src/MDMRepetitionTraits.h @@ -18,34 +18,34 @@ #import /** - The possible kinds of repetition that can be used to describe an animation. + The possible repetition types that can be used to describe an animation. */ -typedef NS_ENUM(NSUInteger, MDMMotionRepetitionType) { +typedef NS_ENUM(NSUInteger, MDMRepetitionType) { /** The animation will be not be repeated. */ - MDMMotionRepetitionTypeNone, + MDMRepetitionTypeNone, /** The animation will be repeated a given number of times. */ - MDMMotionRepetitionTypeCount, + MDMRepetitionTypeCount, /** The animation will be repeated for a given number of seconds. */ - MDMMotionRepetitionTypeDuration, + MDMRepetitionTypeDuration, -} NS_SWIFT_NAME(MotionReptitionType); +} NS_SWIFT_NAME(RepetitionType); /** - A generalized representation of a motion curve. + A generalized representation of a repetition traits. */ -struct MDMMotionRepetition { +typedef struct MDMRepetitionTraits { /** The type defines how to interpret the amount. */ - MDMMotionRepetitionType type; + MDMRepetitionType type; /** The amount of repetition. @@ -57,14 +57,5 @@ struct MDMMotionRepetition { */ BOOL autoreverses; -} NS_SWIFT_NAME(MotionRepetition); -typedef struct MDMMotionRepetition MDMMotionRepetition; +} NS_SWIFT_NAME(RepetitionTraits) MDMRepetitionTraits; -// Objective-C-specific macros - -#define _MDMNoRepetition \ - (MDMMotionRepetition) { \ - .type = MDMMotionRepetitionTypeNone, \ - .amount = 0, \ - .autoreverses = false \ - } diff --git a/src/MDMTimingCurve.h b/src/MDMTimingCurve.h new file mode 100644 index 0000000..9e054c9 --- /dev/null +++ b/src/MDMTimingCurve.h @@ -0,0 +1,152 @@ +/* + Copyright 2017-present The Material Motion Authors. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import +#import +#import + +/** + The possible kinds of traits curves that can be used to describe an animation. + */ +typedef NS_ENUM(NSUInteger, MDMTimingCurveType) { + /** + The value will be instantly set with no animation. + */ + MDMTimingCurveTypeInstant, + + /** + The value will be animated using a cubic bezier curve to model its velocity. + */ + MDMTimingCurveTypeBezier, + + /** + The value will be animated using a spring simulation. + + A spring will treat the duration property of the traits as a suggestion and may choose to + ignore it altogether. + */ + MDMTimingCurveTypeSpring, + +} NS_SWIFT_NAME(TimingCurveType); + +/** + A generalized representation of a traits curve. + */ +typedef struct MDMTimingCurve { + /** + The type defines how to interpret the data values. + */ + MDMTimingCurveType type; + + /** + The data values corresponding with this curve. + */ + CGFloat data[4]; +} NS_SWIFT_NAME(TimingCurve) MDMTimingCurve; + +/** + Creates a bezier traits curve with the provided control points. + + A cubic bezier has four control points in total. We assume that the first control point is 0, 0 and + the last control point is 1, 1. This method requires that you provide the second and third control + points. + + See the documentation for CAMediaTimingFunction for more information. + */ +// clang-format off +FOUNDATION_EXTERN +MDMTimingCurve MDMTimingCurveMakeBezier(CGFloat p1x, CGFloat p1y, CGFloat p2x, CGFloat p2y) + NS_SWIFT_NAME(TimingCurve(bezierWithP1x:p1y:p2x:p2y:)); +// clang-format on + +// clang-format off +FOUNDATION_EXTERN +MDMTimingCurve MDMTimingCurveFromTimingFunction(CAMediaTimingFunction * _Nonnull traitsFunction) + NS_SWIFT_NAME(TimingCurve(fromTimingFunction:)); +// clang-format on + +/** + Creates a spring curve with the provided configuration. + + Tension and friction map to Core Animation's stiffness and damping, respectively. + + See the documentation for CASpringAnimation for more information. + */ +// clang-format off +FOUNDATION_EXTERN +MDMTimingCurve MDMTimingCurveMakeSpring(CGFloat mass, CGFloat tension, CGFloat friction) + NS_SWIFT_NAME(TimingCurve(springWithMass:tension:friction:)); +// clang-format on + +/** + Creates a spring curve with the provided configuration. + + Tension and friction map to Core Animation's stiffness and damping, respectively. + + See the documentation for CASpringAnimation for more information. + */ +// clang-format off +FOUNDATION_EXTERN +MDMTimingCurve MDMTimingCurveMakeSpringWithInitialVelocity(CGFloat mass, + CGFloat tension, + CGFloat friction, + CGFloat initialVelocity) + NS_SWIFT_NAME(TimingCurve(springWithMass:tension:friction:initialVelocity:)); +// clang-format on + +/** + For cubic bezier curves, returns a reversed cubic bezier curve. For all other curve types, a copy + of the original curve is returned. + */ +// clang-format off +FOUNDATION_EXTERN MDMTimingCurve MDMTimingCurveReversedBezier(MDMTimingCurve traitsCurve) + NS_SWIFT_NAME(TimingCurve(reversedFromTimingCurve:)); +// clang-format on + +/** + Named indices for the bezier traits curve's data array. + */ +typedef NS_ENUM(NSUInteger, MDMTimingCurveBezierDataIndex) { + MDMTimingCurveBezierDataIndexP1X, + MDMTimingCurveBezierDataIndexP1Y, + MDMTimingCurveBezierDataIndexP2X, + MDMTimingCurveBezierDataIndexP2Y +} NS_SWIFT_NAME(TimingCurveBezierDataIndex); + +/** + Named indices for the spring traits curve's data array. + */ +typedef NS_ENUM(NSUInteger, MDMTimingCurveSpringDataIndex) { + MDMTimingCurveSpringDataIndexMass, + MDMTimingCurveSpringDataIndexTension, + MDMTimingCurveSpringDataIndexFriction, + + /** + The initial velocity of the animation. + + A value of zero indicates no initial velocity. + A positive value indicates movement toward the destination. + A negative value indicates movement away from the destination. + + The value's units are dependent on the context and the value being animated. + */ + MDMTimingCurveSpringDataIndexInitialVelocity +} NS_SWIFT_NAME(TimingCurveSpringDataIndex); + +/** + A linear bezier traits curve. + */ +FOUNDATION_EXPORT const MDMTimingCurve MDMTimingCurveLinear; diff --git a/src/MDMMotionCurve.m b/src/MDMTimingCurve.m similarity index 53% rename from src/MDMMotionCurve.m rename to src/MDMTimingCurve.m index 2cc57c8..2dd03ee 100644 --- a/src/MDMMotionCurve.m +++ b/src/MDMTimingCurve.m @@ -14,34 +14,42 @@ limitations under the License. */ -#import "MDMMotionCurve.h" +#import "MDMTimingCurve.h" -MDMMotionCurve MDMMotionCurveMakeBezier(CGFloat p1x, CGFloat p1y, CGFloat p2x, CGFloat p2y) { - return _MDMBezier(p1x, p1y, p2x, p2y); +const MDMTimingCurve MDMTimingCurveLinear = { + .type = MDMTimingCurveTypeBezier, .data = { 0, 0, 1, 1 } +}; + +MDMTimingCurve MDMTimingCurveMakeBezier(CGFloat p1x, CGFloat p1y, CGFloat p2x, CGFloat p2y) { + return (MDMTimingCurve){ + .type = MDMTimingCurveTypeBezier, .data = { p1x, p1y, p2x, p2y } + }; } -MDMMotionCurve MDMMotionCurveMakeSpring(CGFloat mass, CGFloat tension, CGFloat friction) { - return MDMMotionCurveMakeSpringWithInitialVelocity(mass, tension, friction, 0); +MDMTimingCurve MDMTimingCurveMakeSpring(CGFloat mass, CGFloat tension, CGFloat friction) { + return MDMTimingCurveMakeSpringWithInitialVelocity(mass, tension, friction, 0); } -MDMMotionCurve MDMMotionCurveMakeSpringWithInitialVelocity(CGFloat mass, +MDMTimingCurve MDMTimingCurveMakeSpringWithInitialVelocity(CGFloat mass, CGFloat tension, CGFloat friction, CGFloat initialVelocity) { - return _MDMSpringWithInitialVelocity(mass, tension, friction, initialVelocity); + return (MDMTimingCurve){ + .type = MDMTimingCurveTypeSpring, .data = { mass, tension, friction, initialVelocity } + }; } -MDMMotionCurve MDMMotionCurveFromTimingFunction(CAMediaTimingFunction *timingFunction) { +MDMTimingCurve MDMTimingCurveFromTimingFunction(CAMediaTimingFunction *traitsFunction) { float pt1[2]; float pt2[2]; - [timingFunction getControlPointAtIndex:1 values:pt1]; - [timingFunction getControlPointAtIndex:2 values:pt2]; - return MDMMotionCurveMakeBezier(pt1[0], pt1[1], pt2[0], pt2[1]); + [traitsFunction getControlPointAtIndex:1 values:pt1]; + [traitsFunction getControlPointAtIndex:2 values:pt2]; + return MDMTimingCurveMakeBezier(pt1[0], pt1[1], pt2[0], pt2[1]); } -MDMMotionCurve MDMMotionCurveReversedBezier(MDMMotionCurve motionCurve) { - MDMMotionCurve reversed = motionCurve; - if (motionCurve.type == MDMMotionCurveTypeBezier) { +MDMTimingCurve MDMTimingCurveReversedBezier(MDMTimingCurve motionCurve) { + MDMTimingCurve reversed = motionCurve; + if (motionCurve.type == MDMTimingCurveTypeBezier) { reversed.data[0] = 1 - motionCurve.data[2]; reversed.data[1] = 1 - motionCurve.data[3]; reversed.data[2] = 1 - motionCurve.data[0]; diff --git a/src/MotionInterchange.h b/src/MotionInterchange.h index 33e8de8..dd6d8ef 100644 --- a/src/MotionInterchange.h +++ b/src/MotionInterchange.h @@ -14,6 +14,6 @@ limitations under the License. */ -#import "MDMMotionCurve.h" -#import "MDMMotionRepetition.h" -#import "MDMMotionTiming.h" +#import "MDMAnimationTraits.h" +#import "MDMRepetitionTraits.h" +#import "MDMTimingCurve.h" diff --git a/tests/unit/MDMModalMovementTimingTests.m b/tests/unit/MDMModalMovementTimingTests.m index f955a9a..a20b08a 100644 --- a/tests/unit/MDMModalMovementTimingTests.m +++ b/tests/unit/MDMModalMovementTimingTests.m @@ -55,7 +55,7 @@ - (void)tearDown { [super tearDown]; } -- (void)testSystemModalMovementTimingCurveMatchesModalMovementTiming { +- (void)testSystemModalMovementTimingCurveMatchesModalMovementTimingOldAPI { ModalPresentationExtractionViewController *presentedViewController = [[ModalPresentationExtractionViewController alloc] initWithNibName:nil bundle:nil]; XCTestExpectation *didComplete = [self expectationWithDescription:@"Animation completed"]; @@ -84,4 +84,33 @@ - (void)testSystemModalMovementTimingCurveMatchesModalMovementTiming { 0.001); } +- (void)testSystemModalMovementTimingCurveMatchesModalMovementTiming { + ModalPresentationExtractionViewController *presentedViewController = + [[ModalPresentationExtractionViewController alloc] initWithNibName:nil bundle:nil]; + XCTestExpectation *didComplete = [self expectationWithDescription:@"Animation completed"]; + [self.window.rootViewController presentViewController:presentedViewController + animated:YES + completion:^{ + [didComplete fulfill]; + }]; + + [self waitForExpectationsWithTimeout:1 handler:nil]; + + XCTAssertTrue([presentedViewController.presentationPositionAnimation + isKindOfClass:[CASpringAnimation class]]); + CASpringAnimation *springAnimation = + (CASpringAnimation *)presentedViewController.presentationPositionAnimation; + + MDMAnimationTraits traits = MDMAnimationTraitsSystemModalMovement; + XCTAssertEqualWithAccuracy(traits.curve.data[MDMSpringMotionCurveDataIndexMass], + springAnimation.mass, + 0.001); + XCTAssertEqualWithAccuracy(traits.curve.data[MDMSpringMotionCurveDataIndexTension], + springAnimation.stiffness, + 0.001); + XCTAssertEqualWithAccuracy(traits.curve.data[MDMSpringMotionCurveDataIndexFriction], + springAnimation.damping, + 0.001); +} + @end diff --git a/tests/unit/MDMTimingCurveTests.m b/tests/unit/MDMTimingCurveTests.m new file mode 100644 index 0000000..c5882de --- /dev/null +++ b/tests/unit/MDMTimingCurveTests.m @@ -0,0 +1,60 @@ +/* + Copyright 2017-present The Material Motion Authors. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import + +#import "MotionInterchange.h" + +@interface MDMTimingCurveTests : XCTestCase +@end + +@implementation MDMTimingCurveTests + +- (void)testLinearCurveConstantMatchesSystemLinearCurve { + MDMTimingCurve curve = MDMTimingCurveLinear; + CAMediaTimingFunction *linearTimingFunction = + [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]; + MDMTimingCurve systemLinearCurve = MDMTimingCurveFromTimingFunction(linearTimingFunction); + XCTAssertEqualWithAccuracy(curve.data[MDMTimingCurveBezierDataIndexP1X], + systemLinearCurve.data[MDMTimingCurveBezierDataIndexP1X], + 0.001); + XCTAssertEqualWithAccuracy(curve.data[MDMTimingCurveBezierDataIndexP1Y], + systemLinearCurve.data[MDMTimingCurveBezierDataIndexP1Y], + 0.001); + XCTAssertEqualWithAccuracy(curve.data[MDMTimingCurveBezierDataIndexP2X], + systemLinearCurve.data[MDMTimingCurveBezierDataIndexP2X], + 0.001); + XCTAssertEqualWithAccuracy(curve.data[MDMTimingCurveBezierDataIndexP2Y], + systemLinearCurve.data[MDMTimingCurveBezierDataIndexP2Y], + 0.001); +} + +- (void)testBezierCurveData { + MDMTimingCurve curve = MDMTimingCurveMakeBezier(0.1f, 0.2f, 0.3f, 0.4f); + XCTAssertEqualWithAccuracy(curve.data[MDMTimingCurveBezierDataIndexP1X], 0.1, 0.001); + XCTAssertEqualWithAccuracy(curve.data[MDMTimingCurveBezierDataIndexP1Y], 0.2, 0.001); + XCTAssertEqualWithAccuracy(curve.data[MDMTimingCurveBezierDataIndexP2X], 0.3, 0.001); + XCTAssertEqualWithAccuracy(curve.data[MDMTimingCurveBezierDataIndexP2Y], 0.4, 0.001); +} + +- (void)testSpringCurveData { + MDMTimingCurve curve = MDMTimingCurveMakeSpring(0.1f, 0.2f, 0.3f); + XCTAssertEqualWithAccuracy(curve.data[MDMTimingCurveSpringDataIndexMass], 0.1, 0.001); + XCTAssertEqualWithAccuracy(curve.data[MDMTimingCurveSpringDataIndexTension], 0.2, 0.001); + XCTAssertEqualWithAccuracy(curve.data[MDMTimingCurveSpringDataIndexFriction], 0.3, 0.001); +} + +@end diff --git a/tests/unit/MDMTimingCurveTests.swift b/tests/unit/MDMTimingCurveTests.swift new file mode 100644 index 0000000..e6ad038 --- /dev/null +++ b/tests/unit/MDMTimingCurveTests.swift @@ -0,0 +1,65 @@ +/* + Copyright 2017-present The Material Motion Authors. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +import XCTest +import MotionInterchange + +class MDMTimingCurveTests: XCTestCase { + + func testBezierCurveData() { + let curve = TimingCurve(bezierWithP1x: 0.1, p1y: 0.2, p2x: 0.3, p2y: 0.4) + XCTAssertEqualWithAccuracy(curve.data.0, 0.1, accuracy: 0.001) + XCTAssertEqualWithAccuracy(curve.data.1, 0.2, accuracy: 0.001) + XCTAssertEqualWithAccuracy(curve.data.2, 0.3, accuracy: 0.001) + XCTAssertEqualWithAccuracy(curve.data.3, 0.4, accuracy: 0.001) + } + + func testBezierCurveFromTimingFunction() { + let timingFunction = CAMediaTimingFunction(controlPoints: 0.1, 0.2, 0.3, 0.4) + let curve = TimingCurve(fromTimingFunction: timingFunction) + XCTAssertEqualWithAccuracy(curve.data.0, 0.1, accuracy: 0.001) + XCTAssertEqualWithAccuracy(curve.data.1, 0.2, accuracy: 0.001) + XCTAssertEqualWithAccuracy(curve.data.2, 0.3, accuracy: 0.001) + XCTAssertEqualWithAccuracy(curve.data.3, 0.4, accuracy: 0.001) + } + + func testSpringCurveData() { + let curve = TimingCurve(springWithMass: 0.1, tension: 0.2, friction: 0.3) + XCTAssertEqualWithAccuracy(curve.data.0, 0.1, accuracy: 0.001) // mass + XCTAssertEqualWithAccuracy(curve.data.1, 0.2, accuracy: 0.001) // tension + XCTAssertEqualWithAccuracy(curve.data.2, 0.3, accuracy: 0.001) // friction + XCTAssertEqualWithAccuracy(curve.data.3, 0.0, accuracy: 0.001) + } + + func testReversedBezierCurve() { + let curve = TimingCurve(bezierWithP1x: 0.1, p1y: 0.2, p2x: 0.3, p2y: 0.4) + let reversed = TimingCurve(reversedFromTimingCurve: curve) + XCTAssertEqualWithAccuracy(curve.data.0, 1 - reversed.data.2, accuracy: 0.001) + XCTAssertEqualWithAccuracy(curve.data.1, 1 - reversed.data.3, accuracy: 0.001) + XCTAssertEqualWithAccuracy(curve.data.2, 1 - reversed.data.0, accuracy: 0.001) + XCTAssertEqualWithAccuracy(curve.data.3, 1 - reversed.data.1, accuracy: 0.001) + } + + func testReversingBezierCurveTwiceGivesSameResult() { + let curve = TimingCurve(bezierWithP1x: 0.1, p1y: 0.2, p2x: 0.3, p2y: 0.4) + let reversed = TimingCurve(reversedFromTimingCurve: curve) + let reversedAgain = TimingCurve(reversedFromTimingCurve: reversed) + XCTAssertEqualWithAccuracy(curve.data.0, reversedAgain.data.0, accuracy: 0.001) + XCTAssertEqualWithAccuracy(curve.data.1, reversedAgain.data.1, accuracy: 0.001) + XCTAssertEqualWithAccuracy(curve.data.2, reversedAgain.data.2, accuracy: 0.001) + XCTAssertEqualWithAccuracy(curve.data.3, reversedAgain.data.3, accuracy: 0.001) + } +} From a334d4decf044fb990ad679e972fa1d0a2d860f9 Mon Sep 17 00:00:00 2001 From: Jeff Verkoeyen Date: Fri, 1 Dec 2017 15:56:03 -0500 Subject: [PATCH 02/13] Add repetition renaming. --- scripts/v1_to_v2.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/v1_to_v2.sh b/scripts/v1_to_v2.sh index 6131995..0a90d0a 100755 --- a/scripts/v1_to_v2.sh +++ b/scripts/v1_to_v2.sh @@ -36,5 +36,6 @@ replace_all "s/MDMLinearTimingCurve/MDMTimingCurveLinear/g" replace_all "s/timing.curve/traits.timingCurve/g" replace_all "s/.curve/.timingCurve/g" replace_all "s/MotionCurve/TimingCurve/g" +replace_all "s/MotionRepetition/RepetitionTraits/g" replace_all "s/MotionTiming timing/AnimationTraits traits/g" replace_all "s/MotionTiming/AnimationTraits/g" From 18650875dc1144d0a1fc2adf6d75872b5d0731da Mon Sep 17 00:00:00 2001 From: Jeff Verkoeyen Date: Fri, 1 Dec 2017 16:01:35 -0500 Subject: [PATCH 03/13] Fix more tests. --- .../project.pbxproj | 8 -- scripts/v1_to_v2.sh | 3 +- tests/unit/MDMModalMovementTimingTests.m | 18 ++--- tests/unit/MDMMotionCurveTests.m | 75 ------------------- tests/unit/MDMMotionCurveTests.swift | 65 ---------------- 5 files changed, 11 insertions(+), 158 deletions(-) delete mode 100644 tests/unit/MDMMotionCurveTests.m delete mode 100644 tests/unit/MDMMotionCurveTests.swift diff --git a/examples/apps/Catalog/MotionInterchangeCatalog.xcodeproj/project.pbxproj b/examples/apps/Catalog/MotionInterchangeCatalog.xcodeproj/project.pbxproj index 321abb6..9523a51 100644 --- a/examples/apps/Catalog/MotionInterchangeCatalog.xcodeproj/project.pbxproj +++ b/examples/apps/Catalog/MotionInterchangeCatalog.xcodeproj/project.pbxproj @@ -15,8 +15,6 @@ 663ED7C71EDF1F0C0096B2A9 /* HexColor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 663ED7C21EDF1F0C0096B2A9 /* HexColor.swift */; }; 663ED7C81EDF1F0C0096B2A9 /* Layout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 663ED7C31EDF1F0C0096B2A9 /* Layout.swift */; }; 663ED7C91EDF1F0C0096B2A9 /* ModalViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 663ED7C41EDF1F0C0096B2A9 /* ModalViewController.swift */; }; - 663ED8011EE628BA0096B2A9 /* MDMMotionCurveTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 663ED8001EE628BA0096B2A9 /* MDMMotionCurveTests.swift */; }; - 663ED8031EE6299A0096B2A9 /* MDMMotionCurveTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 663ED8021EE6299A0096B2A9 /* MDMMotionCurveTests.m */; }; 666FAA841D384A6B000363DA /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 666FAA831D384A6B000363DA /* AppDelegate.swift */; }; 666FAA8B1D384A6B000363DA /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 666FAA8A1D384A6B000363DA /* Assets.xcassets */; }; 666FAA8E1D384A6B000363DA /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 666FAA8C1D384A6B000363DA /* LaunchScreen.storyboard */; }; @@ -57,8 +55,6 @@ 663ED7C21EDF1F0C0096B2A9 /* HexColor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HexColor.swift; sourceTree = ""; }; 663ED7C31EDF1F0C0096B2A9 /* Layout.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Layout.swift; sourceTree = ""; }; 663ED7C41EDF1F0C0096B2A9 /* ModalViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ModalViewController.swift; sourceTree = ""; }; - 663ED8001EE628BA0096B2A9 /* MDMMotionCurveTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MDMMotionCurveTests.swift; sourceTree = ""; }; - 663ED8021EE6299A0096B2A9 /* MDMMotionCurveTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MDMMotionCurveTests.m; sourceTree = ""; }; 666FAA801D384A6B000363DA /* MotionInterchangeCatalog.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MotionInterchangeCatalog.app; sourceTree = BUILT_PRODUCTS_DIR; }; 666FAA831D384A6B000363DA /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = AppDelegate.swift; path = Catalog/AppDelegate.swift; sourceTree = ""; }; 666FAA8A1D384A6B000363DA /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; @@ -166,8 +162,6 @@ 666FAA971D384A6B000363DA /* tests */ = { isa = PBXGroup; children = ( - 663ED8001EE628BA0096B2A9 /* MDMMotionCurveTests.swift */, - 663ED8021EE6299A0096B2A9 /* MDMMotionCurveTests.m */, 6619E1D81FA0ED0300F3AB25 /* MDMModalMovementTimingTests.m */, 660248AD1FD1EE78004C0147 /* MDMTimingCurveTests.m */, 660248AC1FD1EE78004C0147 /* MDMTimingCurveTests.swift */, @@ -484,8 +478,6 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 663ED8031EE6299A0096B2A9 /* MDMMotionCurveTests.m in Sources */, - 663ED8011EE628BA0096B2A9 /* MDMMotionCurveTests.swift in Sources */, 660248AE1FD1EE78004C0147 /* MDMTimingCurveTests.swift in Sources */, 660248AF1FD1EE78004C0147 /* MDMTimingCurveTests.m in Sources */, 6619E1D91FA0ED0300F3AB25 /* MDMModalMovementTimingTests.m in Sources */, diff --git a/scripts/v1_to_v2.sh b/scripts/v1_to_v2.sh index 0a90d0a..00e2f6c 100755 --- a/scripts/v1_to_v2.sh +++ b/scripts/v1_to_v2.sh @@ -33,8 +33,9 @@ replace_all "s/MDMBezierTimingCurveDataIndex/MDMTimingCurveBezierDataIndex/g" replace_all "s/MDMSpringTimingCurveDataIndex/MDMTimingCurveSpringDataIndex/g" replace_all "s/MotionCurveMakeSpring(mass/TimingCurve(springWithMass/g" replace_all "s/MDMLinearTimingCurve/MDMTimingCurveLinear/g" +replace_all "s/MDMModalMovementTiming/MDMAnimationTraitsSystemModalMovement/g" replace_all "s/timing.curve/traits.timingCurve/g" -replace_all "s/.curve/.timingCurve/g" +replace_all "s/\.curve/.timingCurve/g" replace_all "s/MotionCurve/TimingCurve/g" replace_all "s/MotionRepetition/RepetitionTraits/g" replace_all "s/MotionTiming timing/AnimationTraits traits/g" diff --git a/tests/unit/MDMModalMovementTimingTests.m b/tests/unit/MDMModalMovementTimingTests.m index a20b08a..e8856dc 100644 --- a/tests/unit/MDMModalMovementTimingTests.m +++ b/tests/unit/MDMModalMovementTimingTests.m @@ -18,7 +18,7 @@ #import "MotionInterchange.h" -@interface MDMModalMovementTimingTests : XCTestCase +@interface MDMAnimationTraitsSystemModalMovementTests : XCTestCase @property(nonatomic, strong) UIWindow *window; @end @@ -39,7 +39,7 @@ - (void)viewDidLayoutSubviews { @end -@implementation MDMModalMovementTimingTests +@implementation MDMAnimationTraitsSystemModalMovementTests - (void)setUp { [super setUp]; @@ -72,14 +72,14 @@ - (void)testSystemModalMovementTimingCurveMatchesModalMovementTimingOldAPI { CASpringAnimation *springAnimation = (CASpringAnimation *)presentedViewController.presentationPositionAnimation; - MDMMotionTiming timing = MDMModalMovementTiming; - XCTAssertEqualWithAccuracy(timing.curve.data[MDMSpringMotionCurveDataIndexMass], + MDMAnimationTraits traits = MDMAnimationTraitsSystemModalMovement; + XCTAssertEqualWithAccuracy(traits.timingCurve.data[MDMTimingCurveSpringDataIndexMass], springAnimation.mass, 0.001); - XCTAssertEqualWithAccuracy(timing.curve.data[MDMSpringMotionCurveDataIndexTension], + XCTAssertEqualWithAccuracy(traits.timingCurve.data[MDMTimingCurveSpringDataIndexTension], springAnimation.stiffness, 0.001); - XCTAssertEqualWithAccuracy(timing.curve.data[MDMSpringMotionCurveDataIndexFriction], + XCTAssertEqualWithAccuracy(traits.timingCurve.data[MDMTimingCurveSpringDataIndexFriction], springAnimation.damping, 0.001); } @@ -102,13 +102,13 @@ - (void)testSystemModalMovementTimingCurveMatchesModalMovementTiming { (CASpringAnimation *)presentedViewController.presentationPositionAnimation; MDMAnimationTraits traits = MDMAnimationTraitsSystemModalMovement; - XCTAssertEqualWithAccuracy(traits.curve.data[MDMSpringMotionCurveDataIndexMass], + XCTAssertEqualWithAccuracy(traits.timingCurve.data[MDMTimingCurveSpringDataIndexMass], springAnimation.mass, 0.001); - XCTAssertEqualWithAccuracy(traits.curve.data[MDMSpringMotionCurveDataIndexTension], + XCTAssertEqualWithAccuracy(traits.timingCurve.data[MDMTimingCurveSpringDataIndexTension], springAnimation.stiffness, 0.001); - XCTAssertEqualWithAccuracy(traits.curve.data[MDMSpringMotionCurveDataIndexFriction], + XCTAssertEqualWithAccuracy(traits.timingCurve.data[MDMTimingCurveSpringDataIndexFriction], springAnimation.damping, 0.001); } diff --git a/tests/unit/MDMMotionCurveTests.m b/tests/unit/MDMMotionCurveTests.m deleted file mode 100644 index 0cf4941..0000000 --- a/tests/unit/MDMMotionCurveTests.m +++ /dev/null @@ -1,75 +0,0 @@ -/* - Copyright 2017-present The Material Motion Authors. All Rights Reserved. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - */ - -#import - -#import "MotionInterchange.h" - -@interface MDMMotionCurveTests : XCTestCase -@end - -@implementation MDMMotionCurveTests - -- (void)testLinearCurveConstantMatchesSystemLinearCurve { - MDMMotionCurve curve = MDMLinearMotionCurve; - CAMediaTimingFunction *linearTimingFunction = - [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]; - MDMMotionCurve systemLinearCurve = MDMMotionCurveFromTimingFunction(linearTimingFunction); - XCTAssertEqualWithAccuracy(curve.data[MDMBezierMotionCurveDataIndexP1X], - systemLinearCurve.data[MDMBezierMotionCurveDataIndexP1X], - 0.001); - XCTAssertEqualWithAccuracy(curve.data[MDMBezierMotionCurveDataIndexP1Y], - systemLinearCurve.data[MDMBezierMotionCurveDataIndexP1Y], - 0.001); - XCTAssertEqualWithAccuracy(curve.data[MDMBezierMotionCurveDataIndexP2X], - systemLinearCurve.data[MDMBezierMotionCurveDataIndexP2X], - 0.001); - XCTAssertEqualWithAccuracy(curve.data[MDMBezierMotionCurveDataIndexP2Y], - systemLinearCurve.data[MDMBezierMotionCurveDataIndexP2Y], - 0.001); -} - -- (void)testBezierCurveData { - MDMMotionCurve curve = MDMMotionCurveMakeBezier(0.1f, 0.2f, 0.3f, 0.4f); - XCTAssertEqualWithAccuracy(curve.data[MDMBezierMotionCurveDataIndexP1X], 0.1, 0.001); - XCTAssertEqualWithAccuracy(curve.data[MDMBezierMotionCurveDataIndexP1Y], 0.2, 0.001); - XCTAssertEqualWithAccuracy(curve.data[MDMBezierMotionCurveDataIndexP2X], 0.3, 0.001); - XCTAssertEqualWithAccuracy(curve.data[MDMBezierMotionCurveDataIndexP2Y], 0.4, 0.001); -} - -- (void)testSpringCurveData { - MDMMotionCurve curve = MDMMotionCurveMakeSpring(0.1f, 0.2f, 0.3f); - XCTAssertEqualWithAccuracy(curve.data[MDMSpringMotionCurveDataIndexMass], 0.1, 0.001); - XCTAssertEqualWithAccuracy(curve.data[MDMSpringMotionCurveDataIndexTension], 0.2, 0.001); - XCTAssertEqualWithAccuracy(curve.data[MDMSpringMotionCurveDataIndexFriction], 0.3, 0.001); -} - -- (void)testBezierCurveDataWithMacro { - MDMMotionCurve curve = _MDMBezier(0.1, 0.2, 0.3, 0.4); - XCTAssertEqualWithAccuracy(curve.data[MDMBezierMotionCurveDataIndexP1X], 0.1, 0.001); - XCTAssertEqualWithAccuracy(curve.data[MDMBezierMotionCurveDataIndexP1Y], 0.2, 0.001); - XCTAssertEqualWithAccuracy(curve.data[MDMBezierMotionCurveDataIndexP2X], 0.3, 0.001); - XCTAssertEqualWithAccuracy(curve.data[MDMBezierMotionCurveDataIndexP2Y], 0.4, 0.001); -} - -- (void)testSpringCurveDataWithMacro { - MDMMotionCurve curve = _MDMSpring(0.1, 0.2, 0.3); - XCTAssertEqualWithAccuracy(curve.data[MDMSpringMotionCurveDataIndexMass], 0.1, 0.001); - XCTAssertEqualWithAccuracy(curve.data[MDMSpringMotionCurveDataIndexTension], 0.2, 0.001); - XCTAssertEqualWithAccuracy(curve.data[MDMSpringMotionCurveDataIndexFriction], 0.3, 0.001); -} - -@end diff --git a/tests/unit/MDMMotionCurveTests.swift b/tests/unit/MDMMotionCurveTests.swift deleted file mode 100644 index 0f1fb27..0000000 --- a/tests/unit/MDMMotionCurveTests.swift +++ /dev/null @@ -1,65 +0,0 @@ -/* - Copyright 2017-present The Material Motion Authors. All Rights Reserved. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - */ - -import XCTest -import MotionInterchange - -class MDMMotionCurveTests: XCTestCase { - - func testBezierCurveData() { - let curve = MotionCurveMakeBezier(p1x: 0.1, p1y: 0.2, p2x: 0.3, p2y: 0.4) - XCTAssertEqualWithAccuracy(curve.data.0, 0.1, accuracy: 0.001) - XCTAssertEqualWithAccuracy(curve.data.1, 0.2, accuracy: 0.001) - XCTAssertEqualWithAccuracy(curve.data.2, 0.3, accuracy: 0.001) - XCTAssertEqualWithAccuracy(curve.data.3, 0.4, accuracy: 0.001) - } - - func testBezierCurveFromTimingFunction() { - let timingFunction = CAMediaTimingFunction(controlPoints: 0.1, 0.2, 0.3, 0.4) - let curve = MotionCurve(fromTimingFunction: timingFunction) - XCTAssertEqualWithAccuracy(curve.data.0, 0.1, accuracy: 0.001) - XCTAssertEqualWithAccuracy(curve.data.1, 0.2, accuracy: 0.001) - XCTAssertEqualWithAccuracy(curve.data.2, 0.3, accuracy: 0.001) - XCTAssertEqualWithAccuracy(curve.data.3, 0.4, accuracy: 0.001) - } - - func testSpringCurveData() { - let curve = MotionCurveMakeSpring(mass: 0.1, tension: 0.2, friction: 0.3) - XCTAssertEqualWithAccuracy(curve.data.0, 0.1, accuracy: 0.001) // mass - XCTAssertEqualWithAccuracy(curve.data.1, 0.2, accuracy: 0.001) // tension - XCTAssertEqualWithAccuracy(curve.data.2, 0.3, accuracy: 0.001) // friction - XCTAssertEqualWithAccuracy(curve.data.3, 0.0, accuracy: 0.001) - } - - func testReversedBezierCurve() { - let curve = MotionCurveMakeBezier(p1x: 0.1, p1y: 0.2, p2x: 0.3, p2y: 0.4) - let reversed = MotionCurveReversedBezier(fromMotionCurve: curve) - XCTAssertEqualWithAccuracy(curve.data.0, 1 - reversed.data.2, accuracy: 0.001) - XCTAssertEqualWithAccuracy(curve.data.1, 1 - reversed.data.3, accuracy: 0.001) - XCTAssertEqualWithAccuracy(curve.data.2, 1 - reversed.data.0, accuracy: 0.001) - XCTAssertEqualWithAccuracy(curve.data.3, 1 - reversed.data.1, accuracy: 0.001) - } - - func testReversingBezierCurveTwiceGivesSameResult() { - let curve = MotionCurveMakeBezier(p1x: 0.1, p1y: 0.2, p2x: 0.3, p2y: 0.4) - let reversed = MotionCurveReversedBezier(fromMotionCurve: curve) - let reversedAgain = MotionCurveReversedBezier(fromMotionCurve: reversed) - XCTAssertEqualWithAccuracy(curve.data.0, reversedAgain.data.0, accuracy: 0.001) - XCTAssertEqualWithAccuracy(curve.data.1, reversedAgain.data.1, accuracy: 0.001) - XCTAssertEqualWithAccuracy(curve.data.2, reversedAgain.data.2, accuracy: 0.001) - XCTAssertEqualWithAccuracy(curve.data.3, reversedAgain.data.3, accuracy: 0.001) - } -} From 66300612e665b0ae7050314097770bb61d219dca Mon Sep 17 00:00:00 2001 From: Jeff Verkoeyen Date: Fri, 1 Dec 2017 16:04:11 -0500 Subject: [PATCH 04/13] Delete unused header. --- src/CFEnumType.h | 25 ------------------------- 1 file changed, 25 deletions(-) delete mode 100644 src/CFEnumType.h diff --git a/src/CFEnumType.h b/src/CFEnumType.h deleted file mode 100644 index 8be62b7..0000000 --- a/src/CFEnumType.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - Copyright 2017-present The Material Motion Authors. All Rights Reserved. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - */ - -// This macro is introduced in Xcode 9. -#ifndef CF_TYPED_ENUM // What follows is backwards compat for Xcode 8 and below. -#if __has_attribute(swift_wrapper) -#define CF_TYPED_ENUM __attribute__((swift_wrapper(enum))) -#else -#define CF_TYPED_ENUM -#endif -#endif - From 55001b439c6b0130f38ee88ca0eced08999cd8a8 Mon Sep 17 00:00:00 2001 From: Jeff Verkoeyen Date: Fri, 1 Dec 2017 16:09:21 -0500 Subject: [PATCH 05/13] More to script. --- scripts/v1_to_v2.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/v1_to_v2.sh b/scripts/v1_to_v2.sh index 00e2f6c..582175e 100755 --- a/scripts/v1_to_v2.sh +++ b/scripts/v1_to_v2.sh @@ -32,6 +32,7 @@ replace_all() { replace_all "s/MDMBezierTimingCurveDataIndex/MDMTimingCurveBezierDataIndex/g" replace_all "s/MDMSpringTimingCurveDataIndex/MDMTimingCurveSpringDataIndex/g" replace_all "s/MotionCurveMakeSpring(mass/TimingCurve(springWithMass/g" +replace_all "s/TimingCurveMakeBezier(p1x/TimingCurve(bezierWithP1x/g" replace_all "s/MDMLinearTimingCurve/MDMTimingCurveLinear/g" replace_all "s/MDMModalMovementTiming/MDMAnimationTraitsSystemModalMovement/g" replace_all "s/timing.curve/traits.timingCurve/g" From 151d00c8b741f11157360e009e4a295815167248 Mon Sep 17 00:00:00 2001 From: Jeff Verkoeyen Date: Sun, 3 Dec 2017 10:24:05 -0500 Subject: [PATCH 06/13] Review feedback. --- src/MDMRepetitionTraits.h | 6 +++--- src/MDMTimingCurve.h | 27 ++++++++++++++------------- 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/src/MDMRepetitionTraits.h b/src/MDMRepetitionTraits.h index 820e542..a3ef5f4 100644 --- a/src/MDMRepetitionTraits.h +++ b/src/MDMRepetitionTraits.h @@ -24,17 +24,17 @@ typedef NS_ENUM(NSUInteger, MDMRepetitionType) { /** The animation will be not be repeated. */ - MDMRepetitionTypeNone, + MDMRepetitionTypeNone = 0, /** The animation will be repeated a given number of times. */ - MDMRepetitionTypeCount, + MDMRepetitionTypeCount = 1, /** The animation will be repeated for a given number of seconds. */ - MDMRepetitionTypeDuration, + MDMRepetitionTypeDuration = 2, } NS_SWIFT_NAME(RepetitionType); diff --git a/src/MDMTimingCurve.h b/src/MDMTimingCurve.h index 9e054c9..20aabce 100644 --- a/src/MDMTimingCurve.h +++ b/src/MDMTimingCurve.h @@ -25,12 +25,12 @@ typedef NS_ENUM(NSUInteger, MDMTimingCurveType) { /** The value will be instantly set with no animation. */ - MDMTimingCurveTypeInstant, + MDMTimingCurveTypeInstant = 0, /** The value will be animated using a cubic bezier curve to model its velocity. */ - MDMTimingCurveTypeBezier, + MDMTimingCurveTypeBezier = 1, /** The value will be animated using a spring simulation. @@ -38,7 +38,7 @@ typedef NS_ENUM(NSUInteger, MDMTimingCurveType) { A spring will treat the duration property of the traits as a suggestion and may choose to ignore it altogether. */ - MDMTimingCurveTypeSpring, + MDMTimingCurveTypeSpring = 2, } NS_SWIFT_NAME(TimingCurveType); @@ -60,9 +60,10 @@ typedef struct MDMTimingCurve { /** Creates a bezier traits curve with the provided control points. - A cubic bezier has four control points in total. We assume that the first control point is 0, 0 and - the last control point is 1, 1. This method requires that you provide the second and third control - points. + A cubic bezier has four control points in total. We assume that the first control point (p0) is + 0, 0 and the last control point (p3) is 1, 1. This method requires that you provide the second (p1) + and third (p2) control points, resulting in the following cubic bezier points: + `[(0, 0), p1, p2, (1, 1)]`. See the documentation for CAMediaTimingFunction for more information. */ @@ -120,19 +121,19 @@ FOUNDATION_EXTERN MDMTimingCurve MDMTimingCurveReversedBezier(MDMTimingCurve tra Named indices for the bezier traits curve's data array. */ typedef NS_ENUM(NSUInteger, MDMTimingCurveBezierDataIndex) { - MDMTimingCurveBezierDataIndexP1X, - MDMTimingCurveBezierDataIndexP1Y, - MDMTimingCurveBezierDataIndexP2X, - MDMTimingCurveBezierDataIndexP2Y + MDMTimingCurveBezierDataIndexP1X = 0, + MDMTimingCurveBezierDataIndexP1Y = 1, + MDMTimingCurveBezierDataIndexP2X = 2, + MDMTimingCurveBezierDataIndexP2Y = 3 } NS_SWIFT_NAME(TimingCurveBezierDataIndex); /** Named indices for the spring traits curve's data array. */ typedef NS_ENUM(NSUInteger, MDMTimingCurveSpringDataIndex) { - MDMTimingCurveSpringDataIndexMass, - MDMTimingCurveSpringDataIndexTension, - MDMTimingCurveSpringDataIndexFriction, + MDMTimingCurveSpringDataIndexMass = 0, + MDMTimingCurveSpringDataIndexTension = 1, + MDMTimingCurveSpringDataIndexFriction = 2, /** The initial velocity of the animation. From b0c260b6d9c2a93cd5e31623653e2b050b97cd8c Mon Sep 17 00:00:00 2001 From: Jeff Verkoeyen Date: Sun, 3 Dec 2017 10:38:11 -0500 Subject: [PATCH 07/13] API name. --- src/MDMAnimationTraits.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/MDMAnimationTraits.h b/src/MDMAnimationTraits.h index 25d3cbe..d7c2279 100644 --- a/src/MDMAnimationTraits.h +++ b/src/MDMAnimationTraits.h @@ -49,4 +49,6 @@ typedef struct MDMAnimationTraits { /** Animation traits for an iOS modal presentation slide animation. */ -FOUNDATION_EXPORT const MDMAnimationTraits MDMAnimationTraitsSystemModalMovement; +FOUNDATION_EXPORT +const MDMAnimationTraits MDMAnimationTraitsSystemModalMovement + NS_SWIFT_NAME(AnimationTraitsSystemModalMovement); From 8c32394a85b43d23ae39b86e9a2b61b71d21085d Mon Sep 17 00:00:00 2001 From: Jeff Verkoeyen Date: Mon, 4 Dec 2017 09:03:00 -0500 Subject: [PATCH 08/13] Docs. --- src/MDMAnimationTraits.m | 13 ++++++++++++- src/MDMTimingCurve.h | 17 +++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/src/MDMAnimationTraits.m b/src/MDMAnimationTraits.m index 964139c..72c10b2 100644 --- a/src/MDMAnimationTraits.m +++ b/src/MDMAnimationTraits.m @@ -16,8 +16,19 @@ #import "MDMAnimationTraits.h" +static const CGFloat MDMAnimationTraitsSystemModalMovementMass = 3; +static const CGFloat MDMAnimationTraitsSystemModalMovementTension = 1000; +static const CGFloat MDMAnimationTraitsSystemModalMovementFriction = 500; +static const CGFloat MDMAnimationTraitsSystemModalMovementInitialVelocity = 0; + const MDMAnimationTraits MDMAnimationTraitsSystemModalMovement = { .duration = 0.500, .timingCurve = { - .type = MDMTimingCurveTypeSpring, .data = { 3, 1000, 500, 0 } + .type = MDMTimingCurveTypeSpring, + .data = { + MDMAnimationTraitsSystemModalMovementMass, + MDMAnimationTraitsSystemModalMovementTension, + MDMAnimationTraitsSystemModalMovementFriction, + MDMAnimationTraitsSystemModalMovementInitialVelocity, + } } }; diff --git a/src/MDMTimingCurve.h b/src/MDMTimingCurve.h index 20aabce..79643bd 100644 --- a/src/MDMTimingCurve.h +++ b/src/MDMTimingCurve.h @@ -29,6 +29,16 @@ typedef NS_ENUM(NSUInteger, MDMTimingCurveType) { /** The value will be animated using a cubic bezier curve to model its velocity. + + The associated data values are interpreted as follows: + + data[0] = p1.x + data[1] = p1.y + data[2] = p2.x + data[3] = p2.y + + as part of a four point cubic bezier where the first point is (0, 0) and the last is (1, 1): + [(0, 0), p1, p2, (1, 1)] */ MDMTimingCurveTypeBezier = 1, @@ -37,6 +47,13 @@ typedef NS_ENUM(NSUInteger, MDMTimingCurveType) { A spring will treat the duration property of the traits as a suggestion and may choose to ignore it altogether. + + The associated data values are interpreted as follows: + + data[0] = mass + data[1] = tension + data[2] = friction + data[3] = initial velocity */ MDMTimingCurveTypeSpring = 2, From 4aceb00b2976e837e9ab7f3f7aee23b72287ca58 Mon Sep 17 00:00:00 2001 From: Jeff Verkoeyen Date: Mon, 4 Dec 2017 11:11:19 -0500 Subject: [PATCH 09/13] Implement the APIs in Objective-C. Increase testing coverage. --- .../project.pbxproj | 28 +++- src/CAMediaTimingFunction+MDMTimingCurve.h | 44 +++++ src/CAMediaTimingFunction+MDMTimingCurve.m | 49 ++++++ src/MDMAnimationTraits.h | 102 +++++++++--- src/MDMAnimationTraits.m | 67 ++++++-- src/MDMRepetition.h | 60 +++++++ src/MDMRepetition.m | 43 +++++ src/MDMRepetitionOverTime.h | 55 +++++++ src/MDMRepetitionOverTime.m | 42 +++++ src/MDMRepetitionTraits.h | 43 +---- src/MDMSpringTimingCurve.h | 95 +++++++++++ src/MDMSpringTimingCurve.m | 45 ++++++ src/MDMTimingCurve.h | 152 +----------------- src/MDMTimingCurve.m | 59 ------- src/MotionInterchange.h | 4 + tests/unit/CAMediaTimingFunctionTests.swift | 39 +++++ tests/unit/MDMAnimationTraitsTests.swift | 113 +++++++++++++ tests/unit/MDMModalMovementTimingTests.m | 54 ++----- tests/unit/MDMRepetitionOverTimeTests.swift | 33 ++++ tests/unit/MDMRepetitionTests.swift | 33 ++++ tests/unit/MDMSpringTimingCurve.swift | 37 +++++ tests/unit/MDMTimingCurveTests.m | 60 ------- tests/unit/MDMTimingCurveTests.swift | 65 -------- 23 files changed, 868 insertions(+), 454 deletions(-) create mode 100644 src/CAMediaTimingFunction+MDMTimingCurve.h create mode 100644 src/CAMediaTimingFunction+MDMTimingCurve.m create mode 100644 src/MDMRepetition.h create mode 100644 src/MDMRepetition.m create mode 100644 src/MDMRepetitionOverTime.h create mode 100644 src/MDMRepetitionOverTime.m create mode 100644 src/MDMSpringTimingCurve.h create mode 100644 src/MDMSpringTimingCurve.m delete mode 100644 src/MDMTimingCurve.m create mode 100644 tests/unit/CAMediaTimingFunctionTests.swift create mode 100644 tests/unit/MDMAnimationTraitsTests.swift create mode 100644 tests/unit/MDMRepetitionOverTimeTests.swift create mode 100644 tests/unit/MDMRepetitionTests.swift create mode 100644 tests/unit/MDMSpringTimingCurve.swift delete mode 100644 tests/unit/MDMTimingCurveTests.m delete mode 100644 tests/unit/MDMTimingCurveTests.swift diff --git a/examples/apps/Catalog/MotionInterchangeCatalog.xcodeproj/project.pbxproj b/examples/apps/Catalog/MotionInterchangeCatalog.xcodeproj/project.pbxproj index 9523a51..899b7e7 100644 --- a/examples/apps/Catalog/MotionInterchangeCatalog.xcodeproj/project.pbxproj +++ b/examples/apps/Catalog/MotionInterchangeCatalog.xcodeproj/project.pbxproj @@ -7,14 +7,17 @@ objects = { /* Begin PBXBuildFile section */ - 660248AE1FD1EE78004C0147 /* MDMTimingCurveTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 660248AC1FD1EE78004C0147 /* MDMTimingCurveTests.swift */; }; - 660248AF1FD1EE78004C0147 /* MDMTimingCurveTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 660248AD1FD1EE78004C0147 /* MDMTimingCurveTests.m */; }; + 660248AE1FD1EE78004C0147 /* MDMSpringTimingCurve.swift in Sources */ = {isa = PBXBuildFile; fileRef = 660248AC1FD1EE78004C0147 /* MDMSpringTimingCurve.swift */; }; 6619E1D91FA0ED0300F3AB25 /* MDMModalMovementTimingTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 6619E1D81FA0ED0300F3AB25 /* MDMModalMovementTimingTests.m */; }; 663ED7C51EDF1F0C0096B2A9 /* ExampleViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 663ED7C01EDF1F0C0096B2A9 /* ExampleViewController.swift */; }; 663ED7C61EDF1F0C0096B2A9 /* ExampleViews.swift in Sources */ = {isa = PBXBuildFile; fileRef = 663ED7C11EDF1F0C0096B2A9 /* ExampleViews.swift */; }; 663ED7C71EDF1F0C0096B2A9 /* HexColor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 663ED7C21EDF1F0C0096B2A9 /* HexColor.swift */; }; 663ED7C81EDF1F0C0096B2A9 /* Layout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 663ED7C31EDF1F0C0096B2A9 /* Layout.swift */; }; 663ED7C91EDF1F0C0096B2A9 /* ModalViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 663ED7C41EDF1F0C0096B2A9 /* ModalViewController.swift */; }; + 664C8C531FD5A555004ED471 /* CAMediaTimingFunctionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 664C8C521FD5A555004ED471 /* CAMediaTimingFunctionTests.swift */; }; + 664C8C551FD5A7B7004ED471 /* MDMRepetitionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 664C8C541FD5A7B7004ED471 /* MDMRepetitionTests.swift */; }; + 664C8C571FD5A831004ED471 /* MDMRepetitionOverTimeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 664C8C561FD5A831004ED471 /* MDMRepetitionOverTimeTests.swift */; }; + 664C8C591FD5A8AC004ED471 /* MDMAnimationTraitsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 664C8C581FD5A8AC004ED471 /* MDMAnimationTraitsTests.swift */; }; 666FAA841D384A6B000363DA /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 666FAA831D384A6B000363DA /* AppDelegate.swift */; }; 666FAA8B1D384A6B000363DA /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 666FAA8A1D384A6B000363DA /* Assets.xcassets */; }; 666FAA8E1D384A6B000363DA /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 666FAA8C1D384A6B000363DA /* LaunchScreen.storyboard */; }; @@ -47,14 +50,17 @@ 09CEA5DEA01BA723D08D84E6 /* Pods-UnitTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-UnitTests.release.xcconfig"; path = "../../../Pods/Target Support Files/Pods-UnitTests/Pods-UnitTests.release.xcconfig"; sourceTree = ""; }; 2DE76D4D35953D836F578CDE /* Pods-MotionInterchangeCatalog.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MotionInterchangeCatalog.debug.xcconfig"; path = "../../../Pods/Target Support Files/Pods-MotionInterchangeCatalog/Pods-MotionInterchangeCatalog.debug.xcconfig"; sourceTree = ""; }; 4AAB8EBB088513D48896641A /* Pods-MotionInterchangeCatalog.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MotionInterchangeCatalog.release.xcconfig"; path = "../../../Pods/Target Support Files/Pods-MotionInterchangeCatalog/Pods-MotionInterchangeCatalog.release.xcconfig"; sourceTree = ""; }; - 660248AC1FD1EE78004C0147 /* MDMTimingCurveTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MDMTimingCurveTests.swift; sourceTree = ""; }; - 660248AD1FD1EE78004C0147 /* MDMTimingCurveTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MDMTimingCurveTests.m; sourceTree = ""; }; + 660248AC1FD1EE78004C0147 /* MDMSpringTimingCurve.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MDMSpringTimingCurve.swift; sourceTree = ""; }; 6619E1D81FA0ED0300F3AB25 /* MDMModalMovementTimingTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MDMModalMovementTimingTests.m; sourceTree = ""; }; 663ED7C01EDF1F0C0096B2A9 /* ExampleViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExampleViewController.swift; sourceTree = ""; }; 663ED7C11EDF1F0C0096B2A9 /* ExampleViews.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExampleViews.swift; sourceTree = ""; }; 663ED7C21EDF1F0C0096B2A9 /* HexColor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HexColor.swift; sourceTree = ""; }; 663ED7C31EDF1F0C0096B2A9 /* Layout.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Layout.swift; sourceTree = ""; }; 663ED7C41EDF1F0C0096B2A9 /* ModalViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ModalViewController.swift; sourceTree = ""; }; + 664C8C521FD5A555004ED471 /* CAMediaTimingFunctionTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CAMediaTimingFunctionTests.swift; sourceTree = ""; }; + 664C8C541FD5A7B7004ED471 /* MDMRepetitionTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MDMRepetitionTests.swift; sourceTree = ""; }; + 664C8C561FD5A831004ED471 /* MDMRepetitionOverTimeTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MDMRepetitionOverTimeTests.swift; sourceTree = ""; }; + 664C8C581FD5A8AC004ED471 /* MDMAnimationTraitsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MDMAnimationTraitsTests.swift; sourceTree = ""; }; 666FAA801D384A6B000363DA /* MotionInterchangeCatalog.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MotionInterchangeCatalog.app; sourceTree = BUILT_PRODUCTS_DIR; }; 666FAA831D384A6B000363DA /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = AppDelegate.swift; path = Catalog/AppDelegate.swift; sourceTree = ""; }; 666FAA8A1D384A6B000363DA /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; @@ -162,9 +168,12 @@ 666FAA971D384A6B000363DA /* tests */ = { isa = PBXGroup; children = ( + 664C8C521FD5A555004ED471 /* CAMediaTimingFunctionTests.swift */, + 664C8C581FD5A8AC004ED471 /* MDMAnimationTraitsTests.swift */, 6619E1D81FA0ED0300F3AB25 /* MDMModalMovementTimingTests.m */, - 660248AD1FD1EE78004C0147 /* MDMTimingCurveTests.m */, - 660248AC1FD1EE78004C0147 /* MDMTimingCurveTests.swift */, + 664C8C541FD5A7B7004ED471 /* MDMRepetitionTests.swift */, + 664C8C561FD5A831004ED471 /* MDMRepetitionOverTimeTests.swift */, + 660248AC1FD1EE78004C0147 /* MDMSpringTimingCurve.swift */, ); name = tests; path = ../../../tests/unit; @@ -478,9 +487,12 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 660248AE1FD1EE78004C0147 /* MDMTimingCurveTests.swift in Sources */, - 660248AF1FD1EE78004C0147 /* MDMTimingCurveTests.m in Sources */, + 664C8C531FD5A555004ED471 /* CAMediaTimingFunctionTests.swift in Sources */, + 660248AE1FD1EE78004C0147 /* MDMSpringTimingCurve.swift in Sources */, 6619E1D91FA0ED0300F3AB25 /* MDMModalMovementTimingTests.m in Sources */, + 664C8C571FD5A831004ED471 /* MDMRepetitionOverTimeTests.swift in Sources */, + 664C8C591FD5A8AC004ED471 /* MDMAnimationTraitsTests.swift in Sources */, + 664C8C551FD5A7B7004ED471 /* MDMRepetitionTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/src/CAMediaTimingFunction+MDMTimingCurve.h b/src/CAMediaTimingFunction+MDMTimingCurve.h new file mode 100644 index 0000000..e140d0b --- /dev/null +++ b/src/CAMediaTimingFunction+MDMTimingCurve.h @@ -0,0 +1,44 @@ +/* + Copyright 2017-present The Material Motion Authors. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import +#import + +#import "MDMTimingCurve.h" + +// A CAMediaTimingFunction is a timing curve - we simply define its conformity to our protocol here. +@interface CAMediaTimingFunction () +@end + +@interface CAMediaTimingFunction (MotionInterchangeExtension) + +/** + Returns a instance of the timing function with its control points reversed. + */ +- (nonnull CAMediaTimingFunction *)mdm_reversed; + +/** + Returns the first control point of the timing function. + */ +@property(nonatomic, assign, readonly) CGPoint mdm_point1; + +/** + Returns the second control point of the timing function. + */ +@property(nonatomic, assign, readonly) CGPoint mdm_point2; + +@end + diff --git a/src/CAMediaTimingFunction+MDMTimingCurve.m b/src/CAMediaTimingFunction+MDMTimingCurve.m new file mode 100644 index 0000000..f344f17 --- /dev/null +++ b/src/CAMediaTimingFunction+MDMTimingCurve.m @@ -0,0 +1,49 @@ +/* + Copyright 2017-present The Material Motion Authors. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "CAMediaTimingFunction+MDMTimingCurve.h" + +@implementation CAMediaTimingFunction (MotionInterchangeExtension) + +- (CAMediaTimingFunction *)mdm_reversed { + float pt1[2]; + float pt2[2]; + [self getControlPointAtIndex:1 values:pt1]; + [self getControlPointAtIndex:2 values:pt2]; + + float reversedPt1[2]; + float reversedPt2[2]; + reversedPt1[0] = 1 - pt2[0]; + reversedPt1[1] = 1 - pt2[1]; + reversedPt2[0] = 1 - pt1[0]; + reversedPt2[1] = 1 - pt1[1]; + return [CAMediaTimingFunction functionWithControlPoints:reversedPt1[0] :reversedPt1[1] + :reversedPt2[0] :reversedPt2[1]]; +} + +- (CGPoint)mdm_point1 { + float point[2]; + [self getControlPointAtIndex:1 values:point]; + return CGPointMake(point[0], point[1]); +} + +- (CGPoint)mdm_point2 { + float point[2]; + [self getControlPointAtIndex:2 values:point]; + return CGPointMake(point[0], point[1]); +} + +@end diff --git a/src/MDMAnimationTraits.h b/src/MDMAnimationTraits.h index d7c2279..a9426ce 100644 --- a/src/MDMAnimationTraits.h +++ b/src/MDMAnimationTraits.h @@ -23,32 +23,92 @@ /** A generic representation of animation traits. */ -typedef struct MDMAnimationTraits { - /** - The amount of time, in seconds, before this animation's value interpolation should begin. - */ - CFTimeInterval delay; +@interface MDMAnimationTraits: NSObject - /** - The amount of time, in seconds, over which this animation should interpolate between its values. - */ - CFTimeInterval duration; +/** + Initializes the instance with the provided duration and default iOS ease in/out cubic bezier. - /** - The velocity and acceleration of the animation over time. - */ - MDMTimingCurve timingCurve; + @param duration The animation will occur over this length of time, in seconds. + */ +- (nonnull instancetype)initWithDuration:(NSTimeInterval)duration; - /** - The repetition characteristics of the animation. - */ - MDMRepetitionTraits repetition; +/** + Initializes the instance with the provided duration, delay, and default iOS ease in/out cubic + bezier. -} NS_SWIFT_NAME(AnimationTraits) MDMAnimationTraits; + @param duration The animation will occur over this length of time, in seconds, after the delay time + has passed. + @param delay The amount of time, in seconds, to wait before starting the animation. + */ +- (nonnull instancetype)initWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay; + +/** + Initializes the instance with the provided duration, delay, and timing curve. + + @param duration The animation will occur over this length of time, in seconds, after the delay time + has passed. + @param delay The amount of time, in seconds, to wait before starting the animation. + @param timingCurve If provided, defines the acceleration timing for the animation. If nil, the + animation will be treated as instant and the duration/delay will be ignored. + */ +- (nonnull instancetype)initWithDuration:(NSTimeInterval)duration + delay:(NSTimeInterval)delay + timingCurve:(nullable id)timingCurve; + +/** + Initializes an animation trait with the provided timing curve, duration, delay, and repetition. + + @param duration The animation will occur over this length of time, in seconds, after the delay time + has passed. + @param delay The amount of time, in seconds, to wait before starting the animation. + @param timingCurve If provided, defines the acceleration timing for the animation. If nil, the + animation will be treated as instant and the duration/delay will be ignored. + @param repetition The repetition traits of the animation. Most often an instance of MDMRepetition + or MDMRepetitionOverTime. If nil, the animation will not repeat. + */ +- (nonnull instancetype)initWithDuration:(NSTimeInterval)duration + delay:(NSTimeInterval)delay + timingCurve:(nullable id)timingCurve + repetition:(nullable id)repetition + NS_DESIGNATED_INITIALIZER; + +#pragma mark - Traits + +/** + The amount of time, in seconds, before this animation's value interpolation should begin. + */ +@property(nonatomic, assign, readonly) NSTimeInterval delay; + +/** + The amount of time, in seconds, over which this animation should interpolate between its values. + */ +@property(nonatomic, assign, readonly) NSTimeInterval duration; + +/** + The velocity and acceleration of the animation over time. + */ +@property(nonatomic, strong, nullable, readonly) id timingCurve; + +/** + The repetition characteristics of the animation. + */ +@property(nonatomic, strong, nullable, readonly) id repetition; + +#pragma mark - Unavailable + +/** + Unavailable. + */ +- (nonnull instancetype)init NS_UNAVAILABLE; + +@end + +@interface MDMAnimationTraits (SystemTraits) /** Animation traits for an iOS modal presentation slide animation. */ -FOUNDATION_EXPORT -const MDMAnimationTraits MDMAnimationTraitsSystemModalMovement - NS_SWIFT_NAME(AnimationTraitsSystemModalMovement); +@property(nonatomic, class, strong, nonnull, readonly) MDMAnimationTraits *systemModalMovement; + +@end + diff --git a/src/MDMAnimationTraits.m b/src/MDMAnimationTraits.m index 72c10b2..15816b1 100644 --- a/src/MDMAnimationTraits.m +++ b/src/MDMAnimationTraits.m @@ -16,19 +16,56 @@ #import "MDMAnimationTraits.h" -static const CGFloat MDMAnimationTraitsSystemModalMovementMass = 3; -static const CGFloat MDMAnimationTraitsSystemModalMovementTension = 1000; -static const CGFloat MDMAnimationTraitsSystemModalMovementFriction = 500; -static const CGFloat MDMAnimationTraitsSystemModalMovementInitialVelocity = 0; - -const MDMAnimationTraits MDMAnimationTraitsSystemModalMovement = { - .duration = 0.500, .timingCurve = { - .type = MDMTimingCurveTypeSpring, - .data = { - MDMAnimationTraitsSystemModalMovementMass, - MDMAnimationTraitsSystemModalMovementTension, - MDMAnimationTraitsSystemModalMovementFriction, - MDMAnimationTraitsSystemModalMovementInitialVelocity, - } +#import "CAMediaTimingFunction+MDMTimingCurve.h" +#import "MDMSpringTimingCurve.h" + +@implementation MDMAnimationTraits + +- (instancetype)init { + [self doesNotRecognizeSelector:_cmd]; + return nil; +} + +- (nonnull instancetype)initWithDuration:(NSTimeInterval)duration { + return [self initWithDuration:duration delay:0]; +} + +- (instancetype)initWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay { + CAMediaTimingFunction *easeInOut = + [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; + return [self initWithDuration:duration delay:delay timingCurve:easeInOut]; +} + +- (instancetype)initWithDuration:(NSTimeInterval)duration + delay:(NSTimeInterval)delay + timingCurve:(id)timingCurve { + return [self initWithDuration:duration delay:delay timingCurve:timingCurve repetition:nil]; +} + +- (instancetype)initWithDuration:(NSTimeInterval)duration + delay:(NSTimeInterval)delay + timingCurve:(id)timingCurve + repetition:(id)repetition { + self = [super init]; + if (self) { + _duration = duration; + _delay = delay; + _timingCurve = timingCurve; + _repetition = repetition; } -}; + return self; +} + +@end + +@implementation MDMAnimationTraits (SystemTraits) + ++ (MDMAnimationTraits *)systemModalMovement { + MDMSpringTimingCurve *timingCurve = [[MDMSpringTimingCurve alloc] initWithMass:3 + tension:1000 + friction:500]; + return [[MDMAnimationTraits alloc] initWithDuration:0.500 delay:0 timingCurve:timingCurve]; +} + +@end + diff --git a/src/MDMRepetition.h b/src/MDMRepetition.h new file mode 100644 index 0000000..523082f --- /dev/null +++ b/src/MDMRepetition.h @@ -0,0 +1,60 @@ +/* + Copyright 2017-present The Material Motion Authors. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import + +#import "MDMRepetitionTraits.h" + +/** + Represents repetition that repeats a specific number of times. + */ +@interface MDMRepetition: NSObject + +/** + Initializes the instance with the given number of repetitions. + + Autoreversing is disabled. + + @param numberOfRepetitions May be fractional. Initializing with greatestFiniteMagnitude will cause + the animation to repeat forever. + */ +- (nonnull instancetype)initWithNumberOfRepetitions:(double)numberOfRepetitions; + +/** + Initializes the instance with the given number of repetitions and autoreversal behavior. + + @param numberOfRepetitions May be fractional. Initializing with greatestFiniteMagnitude will cause + the animation to repeat forever. + @param autoreverses Whether the animation should animate backwards after animating forwards. + */ +- (nonnull instancetype)initWithNumberOfRepetitions:(double)numberOfRepetitions + autoreverses:(BOOL)autoreverses + NS_DESIGNATED_INITIALIZER; + +#pragma mark - Traits + +/** + The number of repetitions that will occur before this animation stops repeating. + */ +@property(nonatomic, assign, readonly) double numberOfRepetitions; + +/** + Unavailable. + */ +- (nonnull instancetype)init NS_UNAVAILABLE; + +@end + diff --git a/src/MDMRepetition.m b/src/MDMRepetition.m new file mode 100644 index 0000000..e3d5a1c --- /dev/null +++ b/src/MDMRepetition.m @@ -0,0 +1,43 @@ +/* + Copyright 2017-present The Material Motion Authors. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "MDMRepetition.h" + +@implementation MDMRepetition + +@synthesize autoreverses = _autoreverses; + +- (instancetype)init { + [self doesNotRecognizeSelector:_cmd]; + return nil; +} + +- (instancetype)initWithNumberOfRepetitions:(double)numberOfRepetitions { + return [self initWithNumberOfRepetitions:numberOfRepetitions autoreverses:NO]; +} + +- (instancetype)initWithNumberOfRepetitions:(double)numberOfRepetitions + autoreverses:(BOOL)autoreverses { + self = [super init]; + if (self) { + _numberOfRepetitions = numberOfRepetitions; + _autoreverses = autoreverses; + } + return self; +} + +@end + diff --git a/src/MDMRepetitionOverTime.h b/src/MDMRepetitionOverTime.h new file mode 100644 index 0000000..507b422 --- /dev/null +++ b/src/MDMRepetitionOverTime.h @@ -0,0 +1,55 @@ +/* + Copyright 2017-present The Material Motion Authors. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import + +#import "MDMRepetitionTraits.h" + +/** + Represents repetition that repeats until a specific duration has passed. + */ +@interface MDMRepetitionOverTime: NSObject + +/** + Initializes the instance with the given duration. + + @param duration The amount of time, in seconds, over which the animation will repeat. + */ +- (nonnull instancetype)initWithDuration:(double)duration; + +/** + Initializes the instance with the given duration and autoreversal behavior. + + @param duration The amount of time, in seconds, over which the animation will repeat. + @param autoreverses Whether the animation should animate backwards after animating forwards. + */ +- (nonnull instancetype)initWithDuration:(double)duration autoreverses:(BOOL)autoreverses + NS_DESIGNATED_INITIALIZER; + +#pragma mark - Traits + +/** + The amount of time, in seconds, that will pass before this animation stops repeating. + */ +@property(nonatomic, assign, readonly) double duration; + +/** + Unavailable. + */ +- (nonnull instancetype)init NS_UNAVAILABLE; + +@end + diff --git a/src/MDMRepetitionOverTime.m b/src/MDMRepetitionOverTime.m new file mode 100644 index 0000000..55cdcab --- /dev/null +++ b/src/MDMRepetitionOverTime.m @@ -0,0 +1,42 @@ +/* + Copyright 2017-present The Material Motion Authors. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "MDMRepetitionOverTime.h" + +@implementation MDMRepetitionOverTime + +@synthesize autoreverses = _autoreverses; + +- (instancetype)init { + [self doesNotRecognizeSelector:_cmd]; + return nil; +} + +- (instancetype)initWithDuration:(double)duration { + return [self initWithDuration:duration autoreverses:NO]; +} + +- (instancetype)initWithDuration:(double)duration autoreverses:(BOOL)autoreverses { + self = [super init]; + if (self) { + _duration = duration; + _autoreverses = autoreverses; + } + return self; +} + +@end + diff --git a/src/MDMRepetitionTraits.h b/src/MDMRepetitionTraits.h index a3ef5f4..211f227 100644 --- a/src/MDMRepetitionTraits.h +++ b/src/MDMRepetitionTraits.h @@ -14,48 +14,17 @@ limitations under the License. */ -#import #import /** - The possible repetition types that can be used to describe an animation. + A generalized representation of a repetition traits. */ -typedef NS_ENUM(NSUInteger, MDMRepetitionType) { - /** - The animation will be not be repeated. - */ - MDMRepetitionTypeNone = 0, - - /** - The animation will be repeated a given number of times. - */ - MDMRepetitionTypeCount = 1, - - /** - The animation will be repeated for a given number of seconds. - */ - MDMRepetitionTypeDuration = 2, - -} NS_SWIFT_NAME(RepetitionType); +@protocol MDMRepetitionTraits /** - A generalized representation of a repetition traits. + Whether the animation should animate backwards after animating forwards. */ -typedef struct MDMRepetitionTraits { - /** - The type defines how to interpret the amount. - */ - MDMRepetitionType type; - - /** - The amount of repetition. - */ - double amount; - - /** - Whether the animation should animate backwards after animating forwards. - */ - BOOL autoreverses; - -} NS_SWIFT_NAME(RepetitionTraits) MDMRepetitionTraits; +@property(nonatomic, assign, readonly) BOOL autoreverses; + +@end diff --git a/src/MDMSpringTimingCurve.h b/src/MDMSpringTimingCurve.h new file mode 100644 index 0000000..30f7ca9 --- /dev/null +++ b/src/MDMSpringTimingCurve.h @@ -0,0 +1,95 @@ +/* + Copyright 2017-present The Material Motion Authors. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import +#import + +#import "MDMTimingCurve.h" + +/** + A timing curve that represents the motion of a single-dimensional attached spring. + */ +@interface MDMSpringTimingCurve: NSObject + +/** + Initializes the timing curve with the given parameters and an initial velocity of zero. + + @param mass The mass of the spring simulation. Affects the animation's momentum. + @param tension The tension of the spring simulation. Affects how quickly the animation moves + toward its destination. + @param friction The friction of the spring simulation. Affects how quickly the animation starts + and stops. + */ +- (nonnull instancetype)initWithMass:(CGFloat)mass + tension:(CGFloat)tension + friction:(CGFloat)friction; + +/** + Initializes the timing curve with the given parameters. + + @param mass The mass of the spring simulation. Affects the animation's momentum. + @param tension The tension of the spring simulation. Affects how quickly the animation moves + toward its destination. + @param friction The friction of the spring simulation. Affects how quickly the animation starts + and stops. + @param initialVelocity The initial velocity of the spring simulation. Measured in units of + translation per second. For example, if the property being animated is positional, then this value + is in screen units per second. + */ +- (nonnull instancetype)initWithMass:(CGFloat)mass + tension:(CGFloat)tension + friction:(CGFloat)friction + initialVelocity:(CGFloat)initialVelocity + NS_DESIGNATED_INITIALIZER; + +#pragma mark - Traits + +/** + The mass of the spring simulation. + + Affects the animation's momentum. This is usually 1. + */ +@property(nonatomic, assign, readonly) CGFloat mass; + +/** + The tension of the spring simulation. + + Affects how quickly the animation moves toward its destination. + */ +@property(nonatomic, assign, readonly) CGFloat tension; + +/** + The friction of the spring simulation. + + Affects how quickly the animation starts and stops. + */ +@property(nonatomic, assign, readonly) CGFloat friction; + +/** + The initial velocity of the spring simulation. + + Measured in units of translation per second. + */ +@property(nonatomic, assign, readonly) CGFloat initialVelocity; + +/** + Unavailable. + */ +- (nonnull instancetype)init NS_UNAVAILABLE; + +@end + + diff --git a/src/MDMSpringTimingCurve.m b/src/MDMSpringTimingCurve.m new file mode 100644 index 0000000..138a556 --- /dev/null +++ b/src/MDMSpringTimingCurve.m @@ -0,0 +1,45 @@ +/* + Copyright 2017-present The Material Motion Authors. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "MDMSpringTimingCurve.h" + +@implementation MDMSpringTimingCurve + +- (instancetype)init { + [self doesNotRecognizeSelector:_cmd]; + return nil; +} + +- (instancetype)initWithMass:(CGFloat)mass tension:(CGFloat)tension friction:(CGFloat)friction { + return [self initWithMass:mass tension:tension friction:friction initialVelocity:0]; +} + +- (instancetype)initWithMass:(CGFloat)mass + tension:(CGFloat)tension + friction:(CGFloat)friction + initialVelocity:(CGFloat)initialVelocity { + self = [super init]; + if (self) { + _mass = mass; + _tension = tension; + _friction = friction; + _initialVelocity = initialVelocity; + } + return self; +} + +@end + diff --git a/src/MDMTimingCurve.h b/src/MDMTimingCurve.h index 79643bd..3a628ec 100644 --- a/src/MDMTimingCurve.h +++ b/src/MDMTimingCurve.h @@ -14,157 +14,11 @@ limitations under the License. */ -#import #import #import /** - The possible kinds of traits curves that can be used to describe an animation. + A generalized representation of a timing curve. */ -typedef NS_ENUM(NSUInteger, MDMTimingCurveType) { - /** - The value will be instantly set with no animation. - */ - MDMTimingCurveTypeInstant = 0, - - /** - The value will be animated using a cubic bezier curve to model its velocity. - - The associated data values are interpreted as follows: - - data[0] = p1.x - data[1] = p1.y - data[2] = p2.x - data[3] = p2.y - - as part of a four point cubic bezier where the first point is (0, 0) and the last is (1, 1): - [(0, 0), p1, p2, (1, 1)] - */ - MDMTimingCurveTypeBezier = 1, - - /** - The value will be animated using a spring simulation. - - A spring will treat the duration property of the traits as a suggestion and may choose to - ignore it altogether. - - The associated data values are interpreted as follows: - - data[0] = mass - data[1] = tension - data[2] = friction - data[3] = initial velocity - */ - MDMTimingCurveTypeSpring = 2, - -} NS_SWIFT_NAME(TimingCurveType); - -/** - A generalized representation of a traits curve. - */ -typedef struct MDMTimingCurve { - /** - The type defines how to interpret the data values. - */ - MDMTimingCurveType type; - - /** - The data values corresponding with this curve. - */ - CGFloat data[4]; -} NS_SWIFT_NAME(TimingCurve) MDMTimingCurve; - -/** - Creates a bezier traits curve with the provided control points. - - A cubic bezier has four control points in total. We assume that the first control point (p0) is - 0, 0 and the last control point (p3) is 1, 1. This method requires that you provide the second (p1) - and third (p2) control points, resulting in the following cubic bezier points: - `[(0, 0), p1, p2, (1, 1)]`. - - See the documentation for CAMediaTimingFunction for more information. - */ -// clang-format off -FOUNDATION_EXTERN -MDMTimingCurve MDMTimingCurveMakeBezier(CGFloat p1x, CGFloat p1y, CGFloat p2x, CGFloat p2y) - NS_SWIFT_NAME(TimingCurve(bezierWithP1x:p1y:p2x:p2y:)); -// clang-format on - -// clang-format off -FOUNDATION_EXTERN -MDMTimingCurve MDMTimingCurveFromTimingFunction(CAMediaTimingFunction * _Nonnull traitsFunction) - NS_SWIFT_NAME(TimingCurve(fromTimingFunction:)); -// clang-format on - -/** - Creates a spring curve with the provided configuration. - - Tension and friction map to Core Animation's stiffness and damping, respectively. - - See the documentation for CASpringAnimation for more information. - */ -// clang-format off -FOUNDATION_EXTERN -MDMTimingCurve MDMTimingCurveMakeSpring(CGFloat mass, CGFloat tension, CGFloat friction) - NS_SWIFT_NAME(TimingCurve(springWithMass:tension:friction:)); -// clang-format on - -/** - Creates a spring curve with the provided configuration. - - Tension and friction map to Core Animation's stiffness and damping, respectively. - - See the documentation for CASpringAnimation for more information. - */ -// clang-format off -FOUNDATION_EXTERN -MDMTimingCurve MDMTimingCurveMakeSpringWithInitialVelocity(CGFloat mass, - CGFloat tension, - CGFloat friction, - CGFloat initialVelocity) - NS_SWIFT_NAME(TimingCurve(springWithMass:tension:friction:initialVelocity:)); -// clang-format on - -/** - For cubic bezier curves, returns a reversed cubic bezier curve. For all other curve types, a copy - of the original curve is returned. - */ -// clang-format off -FOUNDATION_EXTERN MDMTimingCurve MDMTimingCurveReversedBezier(MDMTimingCurve traitsCurve) - NS_SWIFT_NAME(TimingCurve(reversedFromTimingCurve:)); -// clang-format on - -/** - Named indices for the bezier traits curve's data array. - */ -typedef NS_ENUM(NSUInteger, MDMTimingCurveBezierDataIndex) { - MDMTimingCurveBezierDataIndexP1X = 0, - MDMTimingCurveBezierDataIndexP1Y = 1, - MDMTimingCurveBezierDataIndexP2X = 2, - MDMTimingCurveBezierDataIndexP2Y = 3 -} NS_SWIFT_NAME(TimingCurveBezierDataIndex); - -/** - Named indices for the spring traits curve's data array. - */ -typedef NS_ENUM(NSUInteger, MDMTimingCurveSpringDataIndex) { - MDMTimingCurveSpringDataIndexMass = 0, - MDMTimingCurveSpringDataIndexTension = 1, - MDMTimingCurveSpringDataIndexFriction = 2, - - /** - The initial velocity of the animation. - - A value of zero indicates no initial velocity. - A positive value indicates movement toward the destination. - A negative value indicates movement away from the destination. - - The value's units are dependent on the context and the value being animated. - */ - MDMTimingCurveSpringDataIndexInitialVelocity -} NS_SWIFT_NAME(TimingCurveSpringDataIndex); - -/** - A linear bezier traits curve. - */ -FOUNDATION_EXPORT const MDMTimingCurve MDMTimingCurveLinear; +@protocol MDMTimingCurve +@end diff --git a/src/MDMTimingCurve.m b/src/MDMTimingCurve.m deleted file mode 100644 index 2dd03ee..0000000 --- a/src/MDMTimingCurve.m +++ /dev/null @@ -1,59 +0,0 @@ -/* - Copyright 2017-present The Material Motion Authors. All Rights Reserved. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - */ - -#import "MDMTimingCurve.h" - -const MDMTimingCurve MDMTimingCurveLinear = { - .type = MDMTimingCurveTypeBezier, .data = { 0, 0, 1, 1 } -}; - -MDMTimingCurve MDMTimingCurveMakeBezier(CGFloat p1x, CGFloat p1y, CGFloat p2x, CGFloat p2y) { - return (MDMTimingCurve){ - .type = MDMTimingCurveTypeBezier, .data = { p1x, p1y, p2x, p2y } - }; -} - -MDMTimingCurve MDMTimingCurveMakeSpring(CGFloat mass, CGFloat tension, CGFloat friction) { - return MDMTimingCurveMakeSpringWithInitialVelocity(mass, tension, friction, 0); -} - -MDMTimingCurve MDMTimingCurveMakeSpringWithInitialVelocity(CGFloat mass, - CGFloat tension, - CGFloat friction, - CGFloat initialVelocity) { - return (MDMTimingCurve){ - .type = MDMTimingCurveTypeSpring, .data = { mass, tension, friction, initialVelocity } - }; -} - -MDMTimingCurve MDMTimingCurveFromTimingFunction(CAMediaTimingFunction *traitsFunction) { - float pt1[2]; - float pt2[2]; - [traitsFunction getControlPointAtIndex:1 values:pt1]; - [traitsFunction getControlPointAtIndex:2 values:pt2]; - return MDMTimingCurveMakeBezier(pt1[0], pt1[1], pt2[0], pt2[1]); -} - -MDMTimingCurve MDMTimingCurveReversedBezier(MDMTimingCurve motionCurve) { - MDMTimingCurve reversed = motionCurve; - if (motionCurve.type == MDMTimingCurveTypeBezier) { - reversed.data[0] = 1 - motionCurve.data[2]; - reversed.data[1] = 1 - motionCurve.data[3]; - reversed.data[2] = 1 - motionCurve.data[0]; - reversed.data[3] = 1 - motionCurve.data[1]; - } - return reversed; -} diff --git a/src/MotionInterchange.h b/src/MotionInterchange.h index dd6d8ef..540e559 100644 --- a/src/MotionInterchange.h +++ b/src/MotionInterchange.h @@ -14,6 +14,10 @@ limitations under the License. */ +#import "CAMediaTimingFunction+MDMTimingCurve.h" #import "MDMAnimationTraits.h" #import "MDMRepetitionTraits.h" +#import "MDMRepetition.h" +#import "MDMRepetitionOverTime.h" #import "MDMTimingCurve.h" +#import "MDMSpringTimingCurve.h" diff --git a/tests/unit/CAMediaTimingFunctionTests.swift b/tests/unit/CAMediaTimingFunctionTests.swift new file mode 100644 index 0000000..ae953ec --- /dev/null +++ b/tests/unit/CAMediaTimingFunctionTests.swift @@ -0,0 +1,39 @@ +/* + Copyright 2017-present The Material Motion Authors. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +import XCTest +import MotionInterchange + +class CAMediaTimingFunctionTests: XCTestCase { + func testReversalAlgorithm() { + let curve = CAMediaTimingFunction(controlPoints: 0.1, 0.2, 0.3, 0.4) + let reversed = curve.mdm_reversed() + XCTAssertEqualWithAccuracy(curve.mdm_point1.x, 1 - reversed.mdm_point2.x, accuracy: 0.001) + XCTAssertEqualWithAccuracy(curve.mdm_point1.y, 1 - reversed.mdm_point2.y, accuracy: 0.001) + XCTAssertEqualWithAccuracy(curve.mdm_point2.x, 1 - reversed.mdm_point1.x, accuracy: 0.001) + XCTAssertEqualWithAccuracy(curve.mdm_point2.y, 1 - reversed.mdm_point1.y, accuracy: 0.001) + } + + func testReversingBezierCurveTwiceGivesSameResult() { + let curve = CAMediaTimingFunction(controlPoints: 0.1, 0.2, 0.3, 0.4) + let reversed = curve.mdm_reversed() + let reversedAgain = reversed.mdm_reversed() + XCTAssertEqualWithAccuracy(curve.mdm_point1.x, reversedAgain.mdm_point1.x, accuracy: 0.001) + XCTAssertEqualWithAccuracy(curve.mdm_point1.y, reversedAgain.mdm_point1.y, accuracy: 0.001) + XCTAssertEqualWithAccuracy(curve.mdm_point2.x, reversedAgain.mdm_point2.x, accuracy: 0.001) + XCTAssertEqualWithAccuracy(curve.mdm_point2.y, reversedAgain.mdm_point2.y, accuracy: 0.001) + } +} diff --git a/tests/unit/MDMAnimationTraitsTests.swift b/tests/unit/MDMAnimationTraitsTests.swift new file mode 100644 index 0000000..d5cc806 --- /dev/null +++ b/tests/unit/MDMAnimationTraitsTests.swift @@ -0,0 +1,113 @@ +/* + Copyright 2017-present The Material Motion Authors. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +import XCTest +import MotionInterchange + +class MDMAnimationTraitsTests: XCTestCase { + + func testInitializerValuesWithDuration() { + let traits = MDMAnimationTraits(duration: 0.5) + + XCTAssertEqualWithAccuracy(traits.duration, 0.5, accuracy: 0.001) + XCTAssertEqualWithAccuracy(traits.delay, 0, accuracy: 0.001) + XCTAssertTrue(traits.timingCurve is CAMediaTimingFunction) + if let timingCurve = traits.timingCurve as? CAMediaTimingFunction { + let easeInOut = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut) + XCTAssertEqualWithAccuracy(timingCurve.mdm_point1.x, easeInOut.mdm_point1.x, accuracy: 0.001) + XCTAssertEqualWithAccuracy(timingCurve.mdm_point1.y, easeInOut.mdm_point1.y, accuracy: 0.001) + XCTAssertEqualWithAccuracy(timingCurve.mdm_point2.x, easeInOut.mdm_point2.x, accuracy: 0.001) + XCTAssertEqualWithAccuracy(timingCurve.mdm_point2.y, easeInOut.mdm_point2.y, accuracy: 0.001) + } + XCTAssertNil(traits.repetition) + } + + func testInitializerValuesWithDurationDelay() { + let traits = MDMAnimationTraits(duration: 0.5, delay: 0.2) + + XCTAssertEqualWithAccuracy(traits.duration, 0.5, accuracy: 0.001) + XCTAssertEqualWithAccuracy(traits.delay, 0.2, accuracy: 0.001) + XCTAssertTrue(traits.timingCurve is CAMediaTimingFunction) + if let timingCurve = traits.timingCurve as? CAMediaTimingFunction { + let easeInOut = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut) + XCTAssertEqualWithAccuracy(timingCurve.mdm_point1.x, easeInOut.mdm_point1.x, accuracy: 0.001) + XCTAssertEqualWithAccuracy(timingCurve.mdm_point1.y, easeInOut.mdm_point1.y, accuracy: 0.001) + XCTAssertEqualWithAccuracy(timingCurve.mdm_point2.x, easeInOut.mdm_point2.x, accuracy: 0.001) + XCTAssertEqualWithAccuracy(timingCurve.mdm_point2.y, easeInOut.mdm_point2.y, accuracy: 0.001) + } + XCTAssertNil(traits.repetition) + } + + func testInitializerValuesWithDurationDelayNilTimingCurve() { + let traits = MDMAnimationTraits(duration: 0.5, delay: 0.2, timingCurve: nil) + + XCTAssertEqualWithAccuracy(traits.duration, 0.5, accuracy: 0.001) + XCTAssertEqualWithAccuracy(traits.delay, 0.2, accuracy: 0.001) + XCTAssertNil(traits.timingCurve) + XCTAssertNil(traits.repetition) + } + + func testInitializerValuesWithDurationDelayLinearTimingCurve() { + let linear = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear) + let traits = MDMAnimationTraits(duration: 0.5, delay: 0.2, timingCurve: linear) + + XCTAssertEqualWithAccuracy(traits.duration, 0.5, accuracy: 0.001) + XCTAssertEqualWithAccuracy(traits.delay, 0.2, accuracy: 0.001) + XCTAssertTrue(traits.timingCurve is CAMediaTimingFunction) + if let timingCurve = traits.timingCurve as? CAMediaTimingFunction { + XCTAssertEqualWithAccuracy(timingCurve.mdm_point1.x, linear.mdm_point1.x, accuracy: 0.001) + XCTAssertEqualWithAccuracy(timingCurve.mdm_point1.y, linear.mdm_point1.y, accuracy: 0.001) + XCTAssertEqualWithAccuracy(timingCurve.mdm_point2.x, linear.mdm_point2.x, accuracy: 0.001) + XCTAssertEqualWithAccuracy(timingCurve.mdm_point2.y, linear.mdm_point2.y, accuracy: 0.001) + } + XCTAssertNil(traits.repetition) + } + + func testInitializerValuesWithDurationDelaySpringTimingCurve() { + let spring = MDMSpringTimingCurve(mass: 0.7, tension: 0.8, friction: 0.9) + let traits = MDMAnimationTraits(duration: 0.5, delay: 0.2, timingCurve: spring) + + XCTAssertEqualWithAccuracy(traits.duration, 0.5, accuracy: 0.001) + XCTAssertEqualWithAccuracy(traits.delay, 0.2, accuracy: 0.001) + XCTAssertTrue(traits.timingCurve is MDMSpringTimingCurve) + if let timingCurve = traits.timingCurve as? MDMSpringTimingCurve { + XCTAssertEqualWithAccuracy(timingCurve.mass, spring.mass, accuracy: 0.001) + XCTAssertEqualWithAccuracy(timingCurve.friction, spring.friction, accuracy: 0.001) + XCTAssertEqualWithAccuracy(timingCurve.tension, spring.tension, accuracy: 0.001) + XCTAssertEqualWithAccuracy(timingCurve.initialVelocity, spring.initialVelocity, + accuracy: 0.001) + } + XCTAssertNil(traits.repetition) + } + + func testInitializerValuesWithDurationDelayNilTimingCurveRepetition() { + let repetition = MDMRepetition(numberOfRepetitions: 5) + let traits = MDMAnimationTraits(duration: 0.5, + delay: 0.2, + timingCurve: nil, + repetition: repetition) + + XCTAssertEqualWithAccuracy(traits.duration, 0.5, accuracy: 0.001) + XCTAssertEqualWithAccuracy(traits.delay, 0.2, accuracy: 0.001) + XCTAssertNil(traits.timingCurve) + XCTAssertTrue(traits.repetition is MDMRepetition) + if let setRepetition = traits.repetition as? MDMRepetition { + XCTAssertEqualWithAccuracy(setRepetition.numberOfRepetitions, repetition.numberOfRepetitions, + accuracy: 0.001) + XCTAssertEqual(setRepetition.autoreverses, repetition.autoreverses) + } + } +} diff --git a/tests/unit/MDMModalMovementTimingTests.m b/tests/unit/MDMModalMovementTimingTests.m index e8856dc..d5aa2b2 100644 --- a/tests/unit/MDMModalMovementTimingTests.m +++ b/tests/unit/MDMModalMovementTimingTests.m @@ -55,7 +55,7 @@ - (void)tearDown { [super tearDown]; } -- (void)testSystemModalMovementTimingCurveMatchesModalMovementTimingOldAPI { +- (void)testSystemModalMovementTimingCurveMatchesModalMovementTiming { ModalPresentationExtractionViewController *presentedViewController = [[ModalPresentationExtractionViewController alloc] initWithNibName:nil bundle:nil]; XCTestExpectation *didComplete = [self expectationWithDescription:@"Animation completed"]; @@ -72,45 +72,19 @@ - (void)testSystemModalMovementTimingCurveMatchesModalMovementTimingOldAPI { CASpringAnimation *springAnimation = (CASpringAnimation *)presentedViewController.presentationPositionAnimation; - MDMAnimationTraits traits = MDMAnimationTraitsSystemModalMovement; - XCTAssertEqualWithAccuracy(traits.timingCurve.data[MDMTimingCurveSpringDataIndexMass], - springAnimation.mass, - 0.001); - XCTAssertEqualWithAccuracy(traits.timingCurve.data[MDMTimingCurveSpringDataIndexTension], - springAnimation.stiffness, - 0.001); - XCTAssertEqualWithAccuracy(traits.timingCurve.data[MDMTimingCurveSpringDataIndexFriction], - springAnimation.damping, - 0.001); -} - -- (void)testSystemModalMovementTimingCurveMatchesModalMovementTiming { - ModalPresentationExtractionViewController *presentedViewController = - [[ModalPresentationExtractionViewController alloc] initWithNibName:nil bundle:nil]; - XCTestExpectation *didComplete = [self expectationWithDescription:@"Animation completed"]; - [self.window.rootViewController presentViewController:presentedViewController - animated:YES - completion:^{ - [didComplete fulfill]; - }]; - - [self waitForExpectationsWithTimeout:1 handler:nil]; - - XCTAssertTrue([presentedViewController.presentationPositionAnimation - isKindOfClass:[CASpringAnimation class]]); - CASpringAnimation *springAnimation = - (CASpringAnimation *)presentedViewController.presentationPositionAnimation; - - MDMAnimationTraits traits = MDMAnimationTraitsSystemModalMovement; - XCTAssertEqualWithAccuracy(traits.timingCurve.data[MDMTimingCurveSpringDataIndexMass], - springAnimation.mass, - 0.001); - XCTAssertEqualWithAccuracy(traits.timingCurve.data[MDMTimingCurveSpringDataIndexTension], - springAnimation.stiffness, - 0.001); - XCTAssertEqualWithAccuracy(traits.timingCurve.data[MDMTimingCurveSpringDataIndexFriction], - springAnimation.damping, - 0.001); + MDMAnimationTraits *traits = [MDMAnimationTraits systemModalMovement]; + XCTAssertTrue([traits.timingCurve isKindOfClass:[MDMSpringTimingCurve class]], + @"Expected the system timing curve to be a %@ type, but it was '%@' instead.", + NSStringFromClass([MDMSpringTimingCurve class]), + NSStringFromClass([traits.timingCurve class])); + if ([traits.timingCurve isKindOfClass:[MDMSpringTimingCurve class]]) { + MDMSpringTimingCurve *spring = (MDMSpringTimingCurve *)traits.timingCurve; + + XCTAssertEqualWithAccuracy(spring.mass, springAnimation.mass, 0.001); + XCTAssertEqualWithAccuracy(spring.tension, springAnimation.stiffness, 0.001); + XCTAssertEqualWithAccuracy(spring.friction, springAnimation.damping, 0.001); + XCTAssertEqualWithAccuracy(spring.initialVelocity, springAnimation.initialVelocity, 0.001); + } } @end diff --git a/tests/unit/MDMRepetitionOverTimeTests.swift b/tests/unit/MDMRepetitionOverTimeTests.swift new file mode 100644 index 0000000..9b43a40 --- /dev/null +++ b/tests/unit/MDMRepetitionOverTimeTests.swift @@ -0,0 +1,33 @@ +/* + Copyright 2017-present The Material Motion Authors. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +import XCTest +import MotionInterchange + +class MDMRepetitionOverTimeTests: XCTestCase { + + func testInitializationWithDuration() { + let repetition = MDMRepetitionOverTime(duration: 5.5) + XCTAssertEqualWithAccuracy(repetition.duration, 5.5, accuracy: 0.001) + XCTAssertFalse(repetition.autoreverses) + } + + func testInitializationWithNumberOfRepetitionsAndAutoreversed() { + let repetition = MDMRepetitionOverTime(duration: 5.5, autoreverses: true) + XCTAssertEqualWithAccuracy(repetition.duration, 5.5, accuracy: 0.001) + XCTAssertTrue(repetition.autoreverses) + } +} diff --git a/tests/unit/MDMRepetitionTests.swift b/tests/unit/MDMRepetitionTests.swift new file mode 100644 index 0000000..e90f2bb --- /dev/null +++ b/tests/unit/MDMRepetitionTests.swift @@ -0,0 +1,33 @@ +/* + Copyright 2017-present The Material Motion Authors. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +import XCTest +import MotionInterchange + +class MDMRepetitionTests: XCTestCase { + + func testInitializationWithNumberOfRepetitions() { + let repetition = MDMRepetition(numberOfRepetitions: 5.5) + XCTAssertEqualWithAccuracy(repetition.numberOfRepetitions, 5.5, accuracy: 0.001) + XCTAssertFalse(repetition.autoreverses) + } + + func testInitializationWithNumberOfRepetitionsAndAutoreversed() { + let repetition = MDMRepetition(numberOfRepetitions: 5.5, autoreverses: true) + XCTAssertEqualWithAccuracy(repetition.numberOfRepetitions, 5.5, accuracy: 0.001) + XCTAssertTrue(repetition.autoreverses) + } +} diff --git a/tests/unit/MDMSpringTimingCurve.swift b/tests/unit/MDMSpringTimingCurve.swift new file mode 100644 index 0000000..d0115c6 --- /dev/null +++ b/tests/unit/MDMSpringTimingCurve.swift @@ -0,0 +1,37 @@ +/* + Copyright 2017-present The Material Motion Authors. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +import XCTest +import MotionInterchange + +class MDMTimingCurveTests: XCTestCase { + + func testInitializerValuesWithNoInitialVelocity() { + let curve = MDMSpringTimingCurve(mass: 0.1, tension: 0.2, friction: 0.3) + XCTAssertEqualWithAccuracy(curve.mass, 0.1, accuracy: 0.001) + XCTAssertEqualWithAccuracy(curve.tension, 0.2, accuracy: 0.001) + XCTAssertEqualWithAccuracy(curve.friction, 0.3, accuracy: 0.001) + XCTAssertEqualWithAccuracy(curve.initialVelocity, 0.0, accuracy: 0.001) + } + + func testInitializerValuesWithInitialVelocity() { + let curve = MDMSpringTimingCurve(mass: 0.1, tension: 0.2, friction: 0.3, initialVelocity: 0.4) + XCTAssertEqualWithAccuracy(curve.mass, 0.1, accuracy: 0.001) + XCTAssertEqualWithAccuracy(curve.tension, 0.2, accuracy: 0.001) + XCTAssertEqualWithAccuracy(curve.friction, 0.3, accuracy: 0.001) + XCTAssertEqualWithAccuracy(curve.initialVelocity, 0.4, accuracy: 0.001) + } +} diff --git a/tests/unit/MDMTimingCurveTests.m b/tests/unit/MDMTimingCurveTests.m deleted file mode 100644 index c5882de..0000000 --- a/tests/unit/MDMTimingCurveTests.m +++ /dev/null @@ -1,60 +0,0 @@ -/* - Copyright 2017-present The Material Motion Authors. All Rights Reserved. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - */ - -#import - -#import "MotionInterchange.h" - -@interface MDMTimingCurveTests : XCTestCase -@end - -@implementation MDMTimingCurveTests - -- (void)testLinearCurveConstantMatchesSystemLinearCurve { - MDMTimingCurve curve = MDMTimingCurveLinear; - CAMediaTimingFunction *linearTimingFunction = - [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]; - MDMTimingCurve systemLinearCurve = MDMTimingCurveFromTimingFunction(linearTimingFunction); - XCTAssertEqualWithAccuracy(curve.data[MDMTimingCurveBezierDataIndexP1X], - systemLinearCurve.data[MDMTimingCurveBezierDataIndexP1X], - 0.001); - XCTAssertEqualWithAccuracy(curve.data[MDMTimingCurveBezierDataIndexP1Y], - systemLinearCurve.data[MDMTimingCurveBezierDataIndexP1Y], - 0.001); - XCTAssertEqualWithAccuracy(curve.data[MDMTimingCurveBezierDataIndexP2X], - systemLinearCurve.data[MDMTimingCurveBezierDataIndexP2X], - 0.001); - XCTAssertEqualWithAccuracy(curve.data[MDMTimingCurveBezierDataIndexP2Y], - systemLinearCurve.data[MDMTimingCurveBezierDataIndexP2Y], - 0.001); -} - -- (void)testBezierCurveData { - MDMTimingCurve curve = MDMTimingCurveMakeBezier(0.1f, 0.2f, 0.3f, 0.4f); - XCTAssertEqualWithAccuracy(curve.data[MDMTimingCurveBezierDataIndexP1X], 0.1, 0.001); - XCTAssertEqualWithAccuracy(curve.data[MDMTimingCurveBezierDataIndexP1Y], 0.2, 0.001); - XCTAssertEqualWithAccuracy(curve.data[MDMTimingCurveBezierDataIndexP2X], 0.3, 0.001); - XCTAssertEqualWithAccuracy(curve.data[MDMTimingCurveBezierDataIndexP2Y], 0.4, 0.001); -} - -- (void)testSpringCurveData { - MDMTimingCurve curve = MDMTimingCurveMakeSpring(0.1f, 0.2f, 0.3f); - XCTAssertEqualWithAccuracy(curve.data[MDMTimingCurveSpringDataIndexMass], 0.1, 0.001); - XCTAssertEqualWithAccuracy(curve.data[MDMTimingCurveSpringDataIndexTension], 0.2, 0.001); - XCTAssertEqualWithAccuracy(curve.data[MDMTimingCurveSpringDataIndexFriction], 0.3, 0.001); -} - -@end diff --git a/tests/unit/MDMTimingCurveTests.swift b/tests/unit/MDMTimingCurveTests.swift deleted file mode 100644 index e6ad038..0000000 --- a/tests/unit/MDMTimingCurveTests.swift +++ /dev/null @@ -1,65 +0,0 @@ -/* - Copyright 2017-present The Material Motion Authors. All Rights Reserved. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - */ - -import XCTest -import MotionInterchange - -class MDMTimingCurveTests: XCTestCase { - - func testBezierCurveData() { - let curve = TimingCurve(bezierWithP1x: 0.1, p1y: 0.2, p2x: 0.3, p2y: 0.4) - XCTAssertEqualWithAccuracy(curve.data.0, 0.1, accuracy: 0.001) - XCTAssertEqualWithAccuracy(curve.data.1, 0.2, accuracy: 0.001) - XCTAssertEqualWithAccuracy(curve.data.2, 0.3, accuracy: 0.001) - XCTAssertEqualWithAccuracy(curve.data.3, 0.4, accuracy: 0.001) - } - - func testBezierCurveFromTimingFunction() { - let timingFunction = CAMediaTimingFunction(controlPoints: 0.1, 0.2, 0.3, 0.4) - let curve = TimingCurve(fromTimingFunction: timingFunction) - XCTAssertEqualWithAccuracy(curve.data.0, 0.1, accuracy: 0.001) - XCTAssertEqualWithAccuracy(curve.data.1, 0.2, accuracy: 0.001) - XCTAssertEqualWithAccuracy(curve.data.2, 0.3, accuracy: 0.001) - XCTAssertEqualWithAccuracy(curve.data.3, 0.4, accuracy: 0.001) - } - - func testSpringCurveData() { - let curve = TimingCurve(springWithMass: 0.1, tension: 0.2, friction: 0.3) - XCTAssertEqualWithAccuracy(curve.data.0, 0.1, accuracy: 0.001) // mass - XCTAssertEqualWithAccuracy(curve.data.1, 0.2, accuracy: 0.001) // tension - XCTAssertEqualWithAccuracy(curve.data.2, 0.3, accuracy: 0.001) // friction - XCTAssertEqualWithAccuracy(curve.data.3, 0.0, accuracy: 0.001) - } - - func testReversedBezierCurve() { - let curve = TimingCurve(bezierWithP1x: 0.1, p1y: 0.2, p2x: 0.3, p2y: 0.4) - let reversed = TimingCurve(reversedFromTimingCurve: curve) - XCTAssertEqualWithAccuracy(curve.data.0, 1 - reversed.data.2, accuracy: 0.001) - XCTAssertEqualWithAccuracy(curve.data.1, 1 - reversed.data.3, accuracy: 0.001) - XCTAssertEqualWithAccuracy(curve.data.2, 1 - reversed.data.0, accuracy: 0.001) - XCTAssertEqualWithAccuracy(curve.data.3, 1 - reversed.data.1, accuracy: 0.001) - } - - func testReversingBezierCurveTwiceGivesSameResult() { - let curve = TimingCurve(bezierWithP1x: 0.1, p1y: 0.2, p2x: 0.3, p2y: 0.4) - let reversed = TimingCurve(reversedFromTimingCurve: curve) - let reversedAgain = TimingCurve(reversedFromTimingCurve: reversed) - XCTAssertEqualWithAccuracy(curve.data.0, reversedAgain.data.0, accuracy: 0.001) - XCTAssertEqualWithAccuracy(curve.data.1, reversedAgain.data.1, accuracy: 0.001) - XCTAssertEqualWithAccuracy(curve.data.2, reversedAgain.data.2, accuracy: 0.001) - XCTAssertEqualWithAccuracy(curve.data.3, reversedAgain.data.3, accuracy: 0.001) - } -} From a400a253b8c13717384f6d588cf1572323a6ac7b Mon Sep 17 00:00:00 2001 From: Jeff Verkoeyen Date: Mon, 4 Dec 2017 13:13:59 -0500 Subject: [PATCH 10/13] Reordering. --- scripts/v1_to_v2.sh | 32 ++++++++++++++++++++------------ src/MDMAnimationTraits.h | 20 ++++++++++---------- src/MDMAnimationTraits.m | 26 +++++++++++++------------- 3 files changed, 43 insertions(+), 35 deletions(-) diff --git a/scripts/v1_to_v2.sh b/scripts/v1_to_v2.sh index 582175e..0b95bc9 100755 --- a/scripts/v1_to_v2.sh +++ b/scripts/v1_to_v2.sh @@ -23,21 +23,29 @@ fi search_path="$1" -replace_all() { +replace_objc() { find "$search_path" -type f -name "*.h" | xargs sed -i '' "$1" find "$search_path" -type f -name "*.m" | xargs sed -i '' "$1" +} + +replace_swift() { find "$search_path" -type f -name "*.swift" | xargs sed -i '' "$1" } -replace_all "s/MDMBezierTimingCurveDataIndex/MDMTimingCurveBezierDataIndex/g" -replace_all "s/MDMSpringTimingCurveDataIndex/MDMTimingCurveSpringDataIndex/g" -replace_all "s/MotionCurveMakeSpring(mass/TimingCurve(springWithMass/g" -replace_all "s/TimingCurveMakeBezier(p1x/TimingCurve(bezierWithP1x/g" -replace_all "s/MDMLinearTimingCurve/MDMTimingCurveLinear/g" -replace_all "s/MDMModalMovementTiming/MDMAnimationTraitsSystemModalMovement/g" +replace_all() { + replace_objc $1 + replace_swift $1 +} + +# replace_all "s/MotionCurveMakeSpring(mass/TimingCurve(springWithMass/g" +# replace_all "s/TimingCurveMakeBezier(p1x/TimingCurve(bezierWithP1x/g" +# replace_all "s/MDMLinearTimingCurve/MDMTimingCurveLinear/g" +# replace_all "s/MDMModalMovementTiming/MDMAnimationTraitsSystemModalMovement/g" replace_all "s/timing.curve/traits.timingCurve/g" -replace_all "s/\.curve/.timingCurve/g" -replace_all "s/MotionCurve/TimingCurve/g" -replace_all "s/MotionRepetition/RepetitionTraits/g" -replace_all "s/MotionTiming timing/AnimationTraits traits/g" -replace_all "s/MotionTiming/AnimationTraits/g" +replace_all "s/traits.curve/traits.timingCurve/g" +# replace_all "s/\.curve/.timingCurve/g" +# replace_all "s/MotionCurve/TimingCurve/g" +# replace_all "s/MotionRepetition/RepetitionTraits/g" +# replace_all "s/MotionTiming timing/AnimationTraits traits/g" +replace_objc "s/MDMMotionTiming/MDMAnimationTraits */g" +replace_swift "s/MotionTiming/MDMAnimationTraits/g" diff --git a/src/MDMAnimationTraits.h b/src/MDMAnimationTraits.h index a9426ce..212355c 100644 --- a/src/MDMAnimationTraits.h +++ b/src/MDMAnimationTraits.h @@ -36,24 +36,24 @@ Initializes the instance with the provided duration, delay, and default iOS ease in/out cubic bezier. + @param delay The amount of time, in seconds, to wait before starting the animation. @param duration The animation will occur over this length of time, in seconds, after the delay time has passed. - @param delay The amount of time, in seconds, to wait before starting the animation. */ -- (nonnull instancetype)initWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay; +- (nonnull instancetype)initWithDelay:(NSTimeInterval)delay duration:(NSTimeInterval)duration; /** Initializes the instance with the provided duration, delay, and timing curve. + @param delay The amount of time, in seconds, to wait before starting the animation. @param duration The animation will occur over this length of time, in seconds, after the delay time has passed. - @param delay The amount of time, in seconds, to wait before starting the animation. @param timingCurve If provided, defines the acceleration timing for the animation. If nil, the animation will be treated as instant and the duration/delay will be ignored. */ -- (nonnull instancetype)initWithDuration:(NSTimeInterval)duration - delay:(NSTimeInterval)delay - timingCurve:(nullable id)timingCurve; +- (nonnull instancetype)initWithDelay:(NSTimeInterval)delay + duration:(NSTimeInterval)duration + timingCurve:(nullable id)timingCurve; /** Initializes an animation trait with the provided timing curve, duration, delay, and repetition. @@ -66,10 +66,10 @@ @param repetition The repetition traits of the animation. Most often an instance of MDMRepetition or MDMRepetitionOverTime. If nil, the animation will not repeat. */ -- (nonnull instancetype)initWithDuration:(NSTimeInterval)duration - delay:(NSTimeInterval)delay - timingCurve:(nullable id)timingCurve - repetition:(nullable id)repetition +- (nonnull instancetype)initWithDelay:(NSTimeInterval)delay + duration:(NSTimeInterval)duration + timingCurve:(nullable id)timingCurve + repetition:(nullable id)repetition NS_DESIGNATED_INITIALIZER; #pragma mark - Traits diff --git a/src/MDMAnimationTraits.m b/src/MDMAnimationTraits.m index 15816b1..3bfa441 100644 --- a/src/MDMAnimationTraits.m +++ b/src/MDMAnimationTraits.m @@ -27,25 +27,25 @@ - (instancetype)init { } - (nonnull instancetype)initWithDuration:(NSTimeInterval)duration { - return [self initWithDuration:duration delay:0]; + return [self initWithDelay:0 duration:duration]; } -- (instancetype)initWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay { +- (instancetype)initWithDelay:(NSTimeInterval)delay duration:(NSTimeInterval)duration { CAMediaTimingFunction *easeInOut = - [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; - return [self initWithDuration:duration delay:delay timingCurve:easeInOut]; + [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; + return [self initWithDelay:delay duration:duration timingCurve:easeInOut]; } -- (instancetype)initWithDuration:(NSTimeInterval)duration - delay:(NSTimeInterval)delay - timingCurve:(id)timingCurve { - return [self initWithDuration:duration delay:delay timingCurve:timingCurve repetition:nil]; +- (instancetype)initWithDelay:(NSTimeInterval)delay + duration:(NSTimeInterval)duration + timingCurve:(id)timingCurve { + return [self initWithDelay:delay duration:duration timingCurve:timingCurve repetition:nil]; } -- (instancetype)initWithDuration:(NSTimeInterval)duration - delay:(NSTimeInterval)delay - timingCurve:(id)timingCurve - repetition:(id)repetition { +- (instancetype)initWithDelay:(NSTimeInterval)delay + duration:(NSTimeInterval)duration + timingCurve:(id)timingCurve + repetition:(id)repetition { self = [super init]; if (self) { _duration = duration; @@ -64,7 +64,7 @@ + (MDMAnimationTraits *)systemModalMovement { MDMSpringTimingCurve *timingCurve = [[MDMSpringTimingCurve alloc] initWithMass:3 tension:1000 friction:500]; - return [[MDMAnimationTraits alloc] initWithDuration:0.500 delay:0 timingCurve:timingCurve]; + return [[MDMAnimationTraits alloc] initWithDelay:0 duration:0.500 timingCurve:timingCurve]; } @end From 771d7123b63bb9e71b8f8b84fbd3ea22fc7a4d4f Mon Sep 17 00:00:00 2001 From: Jeff Verkoeyen Date: Mon, 4 Dec 2017 13:32:51 -0500 Subject: [PATCH 11/13] Fix tests. --- tests/unit/MDMAnimationTraitsTests.swift | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/unit/MDMAnimationTraitsTests.swift b/tests/unit/MDMAnimationTraitsTests.swift index d5cc806..8755967 100644 --- a/tests/unit/MDMAnimationTraitsTests.swift +++ b/tests/unit/MDMAnimationTraitsTests.swift @@ -36,7 +36,7 @@ class MDMAnimationTraitsTests: XCTestCase { } func testInitializerValuesWithDurationDelay() { - let traits = MDMAnimationTraits(duration: 0.5, delay: 0.2) + let traits = MDMAnimationTraits(delay: 0.2, duration: 0.5) XCTAssertEqualWithAccuracy(traits.duration, 0.5, accuracy: 0.001) XCTAssertEqualWithAccuracy(traits.delay, 0.2, accuracy: 0.001) @@ -52,7 +52,7 @@ class MDMAnimationTraitsTests: XCTestCase { } func testInitializerValuesWithDurationDelayNilTimingCurve() { - let traits = MDMAnimationTraits(duration: 0.5, delay: 0.2, timingCurve: nil) + let traits = MDMAnimationTraits(delay: 0.2, duration: 0.5, timingCurve: nil) XCTAssertEqualWithAccuracy(traits.duration, 0.5, accuracy: 0.001) XCTAssertEqualWithAccuracy(traits.delay, 0.2, accuracy: 0.001) @@ -62,7 +62,7 @@ class MDMAnimationTraitsTests: XCTestCase { func testInitializerValuesWithDurationDelayLinearTimingCurve() { let linear = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear) - let traits = MDMAnimationTraits(duration: 0.5, delay: 0.2, timingCurve: linear) + let traits = MDMAnimationTraits(delay: 0.2, duration: 0.5, timingCurve: linear) XCTAssertEqualWithAccuracy(traits.duration, 0.5, accuracy: 0.001) XCTAssertEqualWithAccuracy(traits.delay, 0.2, accuracy: 0.001) @@ -78,7 +78,7 @@ class MDMAnimationTraitsTests: XCTestCase { func testInitializerValuesWithDurationDelaySpringTimingCurve() { let spring = MDMSpringTimingCurve(mass: 0.7, tension: 0.8, friction: 0.9) - let traits = MDMAnimationTraits(duration: 0.5, delay: 0.2, timingCurve: spring) + let traits = MDMAnimationTraits(delay: 0.2, duration: 0.5, timingCurve: spring) XCTAssertEqualWithAccuracy(traits.duration, 0.5, accuracy: 0.001) XCTAssertEqualWithAccuracy(traits.delay, 0.2, accuracy: 0.001) @@ -95,8 +95,8 @@ class MDMAnimationTraitsTests: XCTestCase { func testInitializerValuesWithDurationDelayNilTimingCurveRepetition() { let repetition = MDMRepetition(numberOfRepetitions: 5) - let traits = MDMAnimationTraits(duration: 0.5, - delay: 0.2, + let traits = MDMAnimationTraits(delay: 0.2, + duration: 0.5, timingCurve: nil, repetition: repetition) From c4a4cc2b54d834e9f86c438996bd00297713808f Mon Sep 17 00:00:00 2001 From: Jeff Verkoeyen Date: Mon, 4 Dec 2017 14:30:11 -0500 Subject: [PATCH 12/13] Quotes. --- scripts/v1_to_v2.sh | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/scripts/v1_to_v2.sh b/scripts/v1_to_v2.sh index 0b95bc9..b601faa 100755 --- a/scripts/v1_to_v2.sh +++ b/scripts/v1_to_v2.sh @@ -33,19 +33,11 @@ replace_swift() { } replace_all() { - replace_objc $1 - replace_swift $1 + replace_objc "$1" + replace_swift "$1" } -# replace_all "s/MotionCurveMakeSpring(mass/TimingCurve(springWithMass/g" -# replace_all "s/TimingCurveMakeBezier(p1x/TimingCurve(bezierWithP1x/g" -# replace_all "s/MDMLinearTimingCurve/MDMTimingCurveLinear/g" -# replace_all "s/MDMModalMovementTiming/MDMAnimationTraitsSystemModalMovement/g" replace_all "s/timing.curve/traits.timingCurve/g" replace_all "s/traits.curve/traits.timingCurve/g" -# replace_all "s/\.curve/.timingCurve/g" -# replace_all "s/MotionCurve/TimingCurve/g" -# replace_all "s/MotionRepetition/RepetitionTraits/g" -# replace_all "s/MotionTiming timing/AnimationTraits traits/g" replace_objc "s/MDMMotionTiming/MDMAnimationTraits */g" replace_swift "s/MotionTiming/MDMAnimationTraits/g" From 6898bac6df56fc2587967374b6262cd7b55be773 Mon Sep 17 00:00:00 2001 From: Jeff Verkoeyen Date: Mon, 4 Dec 2017 14:38:27 -0500 Subject: [PATCH 13/13] Review feedback. --- src/MDMAnimationTraits.h | 7 ++++--- src/MDMAnimationTraits.m | 2 +- tests/unit/MDMRepetitionOverTimeTests.swift | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/MDMAnimationTraits.h b/src/MDMAnimationTraits.h index 212355c..3eefaac 100644 --- a/src/MDMAnimationTraits.h +++ b/src/MDMAnimationTraits.h @@ -26,15 +26,16 @@ @interface MDMAnimationTraits: NSObject /** - Initializes the instance with the provided duration and default iOS ease in/out cubic bezier. + Initializes the instance with the provided duration and kCAMediaTimingFunctionEaseInEaseOut timing + curve. @param duration The animation will occur over this length of time, in seconds. */ - (nonnull instancetype)initWithDuration:(NSTimeInterval)duration; /** - Initializes the instance with the provided duration, delay, and default iOS ease in/out cubic - bezier. + Initializes the instance with the provided duration, delay, and + kCAMediaTimingFunctionEaseInEaseOut timing curve. @param delay The amount of time, in seconds, to wait before starting the animation. @param duration The animation will occur over this length of time, in seconds, after the delay time diff --git a/src/MDMAnimationTraits.m b/src/MDMAnimationTraits.m index 3bfa441..99bf382 100644 --- a/src/MDMAnimationTraits.m +++ b/src/MDMAnimationTraits.m @@ -32,7 +32,7 @@ - (nonnull instancetype)initWithDuration:(NSTimeInterval)duration { - (instancetype)initWithDelay:(NSTimeInterval)delay duration:(NSTimeInterval)duration { CAMediaTimingFunction *easeInOut = - [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; + [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; return [self initWithDelay:delay duration:duration timingCurve:easeInOut]; } diff --git a/tests/unit/MDMRepetitionOverTimeTests.swift b/tests/unit/MDMRepetitionOverTimeTests.swift index 9b43a40..f571d07 100644 --- a/tests/unit/MDMRepetitionOverTimeTests.swift +++ b/tests/unit/MDMRepetitionOverTimeTests.swift @@ -25,7 +25,7 @@ class MDMRepetitionOverTimeTests: XCTestCase { XCTAssertFalse(repetition.autoreverses) } - func testInitializationWithNumberOfRepetitionsAndAutoreversed() { + func testInitializationWithDurationAndAutoreversed() { let repetition = MDMRepetitionOverTime(duration: 5.5, autoreverses: true) XCTAssertEqualWithAccuracy(repetition.duration, 5.5, accuracy: 0.001) XCTAssertTrue(repetition.autoreverses)