From 7e3417d2bdf60376b371406309c506aebd62e9f0 Mon Sep 17 00:00:00 2001 From: Brett Walker Date: Mon, 19 Mar 2018 00:06:51 -0700 Subject: [PATCH] 1.3.0 update - Refactored the "finalState" convenience initializer for the Motion class to now take an Array of PropertyStates objects. This allows you to provide both starting and ending representational value objects for easy animation properties creation. Most of the ValueAssistant objects had significant updates to support this. - A new "buildPropertyData(fromObject: AnyObject, propertyStates: [PropertyStates])" public method has been added to the Motion class, which creates and returns an array of PropertyData objects. This method is used in conjunction with the above convenience initializer, but can be called ad hoc to generate PropertyData objects from a set of state objects you pass in. - Bugfix: ValueAssistants now won't exclude properties from being created when the ending value is the same as the object's original value, but the specified starting value is different. - Minor updates for Swift 4 compatibility. The Examples and Tests projects now target Swift 4. - Updated tests, and additional test coverage for ValueAssistant classes. --- CHANGELOG.md | 7 + Classes/CATempo.swift | 2 +- Classes/EasingTypes/EasingBack.swift | 2 +- Classes/EasingTypes/EasingBounce.swift | 2 +- Classes/EasingTypes/EasingCircular.swift | 2 +- Classes/EasingTypes/EasingCubic.swift | 2 +- Classes/EasingTypes/EasingElastic.swift | 2 +- Classes/EasingTypes/EasingExpo.swift | 2 +- Classes/EasingTypes/EasingLinear.swift | 2 +- Classes/EasingTypes/EasingQuadratic.swift | 2 +- Classes/EasingTypes/EasingQuartic.swift | 2 +- Classes/EasingTypes/EasingQuintic.swift | 2 +- Classes/EasingTypes/EasingSine.swift | 2 +- Classes/Motion.swift | 116 +++-- Classes/MotionGroup.swift | 2 +- Classes/MotionMachine.swift | 6 +- Classes/MotionSequence.swift | 2 +- Classes/MotionSupport.swift | 2 +- Classes/PhysicsMotion.swift | 2 +- Classes/PhysicsSystem.swift | 2 +- Classes/PropertyData.swift | 4 +- Classes/PropertyStates.swift | 83 ++++ Classes/Tempo.swift | 2 +- Classes/TimerTempo.swift | 2 +- .../ValueAssistants/CGStructAssistant.swift | 403 ++++++++++++++---- .../ValueAssistants/CIColorAssistant.swift | 57 ++- .../ValueAssistants/UIColorAssistant.swift | 52 ++- .../UIKitStructAssistant.swift | 103 +++-- .../ValueAssistants/ValueAssistantGroup.swift | 19 +- .../MotionExamples.xcodeproj/project.pbxproj | 279 ++++++------ .../Assets.xcassets/Contents.json | 6 + .../SequenceContiguousViewController.swift | 2 +- .../Classes/SequenceViewController.swift | 2 +- Guides/MoveableClasses.md | 12 +- MotionMachine.podspec | 2 +- README.md | 2 +- .../project.pbxproj | 305 +++++++------ Tests/Tests/EasingTests.swift | 22 +- Tests/Tests/Helpers/Tester.swift | 4 + Tests/Tests/MotionGroupTests.swift | 2 +- Tests/Tests/MotionSequenceTests.swift | 18 +- Tests/Tests/MotionTests.swift | 32 +- Tests/Tests/PhysicsMotionTests.swift | 4 +- .../CGStructAssistantTests.swift | 167 +++++++- .../CIColorAssistantTests.swift | 34 +- .../UIColorAssistantTests.swift | 37 +- .../UIKitStructAssistantTests.swift | 110 ++++- .../ValueAssistantGroupTests.swift | 19 +- 48 files changed, 1361 insertions(+), 586 deletions(-) create mode 100644 Classes/PropertyStates.swift create mode 100644 Examples/MotionExamples/Assets.xcassets/Contents.json diff --git a/CHANGELOG.md b/CHANGELOG.md index c677a50..d2aeab9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +#### 1.3.0 +- Refactored the "finalState" convenience initializer for the Motion class to now take an Array of PropertyStates objects. This allows you to provide both starting and ending representational value objects for easy animation properties creation. Most of the ValueAssistant objects had significant updates to support this. +- A new "buildPropertyData(fromObject: AnyObject, propertyStates: [PropertyStates])" public method has been added to the Motion class, which creates and returns an array of PropertyData objects. This method is used in conjunction with the above convenience initializer, but can be called ad hoc to generate PropertyData objects from a set of state objects you pass in. +- Bugfix: ValueAssistants now won't exclude properties from being created when the ending value is the same as the object's original value, but the specified starting value is different. +- Minor updates for Swift 4 compatibility. The Examples and Tests projects now target Swift 4. +- Updated tests, and additional test coverage for ValueAssistant classes. + #### 1.2.0 Support for Swift 4.0. diff --git a/Classes/CATempo.swift b/Classes/CATempo.swift index bf13825..a04be50 100644 --- a/Classes/CATempo.swift +++ b/Classes/CATempo.swift @@ -3,7 +3,7 @@ // MotionMachine // // Created by Brett Walker on 4/19/16. -// Copyright © 2016 Poet & Mountain, LLC. All rights reserved. +// Copyright © 2016-2018 Poet & Mountain, LLC. All rights reserved. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal diff --git a/Classes/EasingTypes/EasingBack.swift b/Classes/EasingTypes/EasingBack.swift index c7db84e..5dfc989 100644 --- a/Classes/EasingTypes/EasingBack.swift +++ b/Classes/EasingTypes/EasingBack.swift @@ -3,7 +3,7 @@ // MotionMachine // // Created by Brett Walker on 5/3/16. -// Copyright © 2016 Poet & Mountain, LLC. All rights reserved. +// Copyright © 2016-2018 Poet & Mountain, LLC. All rights reserved. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal diff --git a/Classes/EasingTypes/EasingBounce.swift b/Classes/EasingTypes/EasingBounce.swift index ab7d8f3..5f15cb9 100644 --- a/Classes/EasingTypes/EasingBounce.swift +++ b/Classes/EasingTypes/EasingBounce.swift @@ -3,7 +3,7 @@ // MotionMachine // // Created by Brett Walker on 5/3/16. -// Copyright © 2016 Poet & Mountain, LLC. All rights reserved. +// Copyright © 2016-2018 Poet & Mountain, LLC. All rights reserved. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal diff --git a/Classes/EasingTypes/EasingCircular.swift b/Classes/EasingTypes/EasingCircular.swift index 6ee7ca0..c3acead 100644 --- a/Classes/EasingTypes/EasingCircular.swift +++ b/Classes/EasingTypes/EasingCircular.swift @@ -3,7 +3,7 @@ // MotionMachine // // Created by Brett Walker on 5/3/16. -// Copyright © 2016 Poet & Mountain, LLC. All rights reserved. +// Copyright © 2016-2018 Poet & Mountain, LLC. All rights reserved. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal diff --git a/Classes/EasingTypes/EasingCubic.swift b/Classes/EasingTypes/EasingCubic.swift index acb1dd7..c4fa3f2 100644 --- a/Classes/EasingTypes/EasingCubic.swift +++ b/Classes/EasingTypes/EasingCubic.swift @@ -3,7 +3,7 @@ // MotionMachine // // Created by Brett Walker on 5/3/16. -// Copyright © 2016 Poet & Mountain, LLC. All rights reserved. +// Copyright © 2016-2018 Poet & Mountain, LLC. All rights reserved. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal diff --git a/Classes/EasingTypes/EasingElastic.swift b/Classes/EasingTypes/EasingElastic.swift index 21090c5..67f1be4 100644 --- a/Classes/EasingTypes/EasingElastic.swift +++ b/Classes/EasingTypes/EasingElastic.swift @@ -3,7 +3,7 @@ // MotionMachine // // Created by Brett Walker on 5/3/16. -// Copyright © 2016 Poet & Mountain, LLC. All rights reserved. +// Copyright © 2016-2018 Poet & Mountain, LLC. All rights reserved. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal diff --git a/Classes/EasingTypes/EasingExpo.swift b/Classes/EasingTypes/EasingExpo.swift index 48cc0aa..3a24fe3 100644 --- a/Classes/EasingTypes/EasingExpo.swift +++ b/Classes/EasingTypes/EasingExpo.swift @@ -3,7 +3,7 @@ // MotionMachine // // Created by Brett Walker on 5/3/16. -// Copyright © 2016 Poet & Mountain, LLC. All rights reserved. +// Copyright © 2016-2018 Poet & Mountain, LLC. All rights reserved. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal diff --git a/Classes/EasingTypes/EasingLinear.swift b/Classes/EasingTypes/EasingLinear.swift index e80ad5a..ef8bf85 100644 --- a/Classes/EasingTypes/EasingLinear.swift +++ b/Classes/EasingTypes/EasingLinear.swift @@ -3,7 +3,7 @@ // MotionMachine // // Created by Brett Walker on 4/19/16. -// Copyright © 2016 Poet & Mountain, LLC. All rights reserved. +// Copyright © 2016-2018 Poet & Mountain, LLC. All rights reserved. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal diff --git a/Classes/EasingTypes/EasingQuadratic.swift b/Classes/EasingTypes/EasingQuadratic.swift index 3a34cf5..d858287 100644 --- a/Classes/EasingTypes/EasingQuadratic.swift +++ b/Classes/EasingTypes/EasingQuadratic.swift @@ -3,7 +3,7 @@ // MotionMachine // // Created by Brett Walker on 4/30/16. -// Copyright © 2016 Poet & Mountain, LLC. All rights reserved. +// Copyright © 2016-2018 Poet & Mountain, LLC. All rights reserved. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal diff --git a/Classes/EasingTypes/EasingQuartic.swift b/Classes/EasingTypes/EasingQuartic.swift index 099a1df..6efd45a 100644 --- a/Classes/EasingTypes/EasingQuartic.swift +++ b/Classes/EasingTypes/EasingQuartic.swift @@ -3,7 +3,7 @@ // MotionMachine // // Created by Brett Walker on 5/3/16. -// Copyright © 2016 Poet & Mountain, LLC. All rights reserved. +// Copyright © 2016-2018 Poet & Mountain, LLC. All rights reserved. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal diff --git a/Classes/EasingTypes/EasingQuintic.swift b/Classes/EasingTypes/EasingQuintic.swift index 0277d01..f72c77e 100644 --- a/Classes/EasingTypes/EasingQuintic.swift +++ b/Classes/EasingTypes/EasingQuintic.swift @@ -3,7 +3,7 @@ // MotionMachine // // Created by Brett Walker on 5/3/16. -// Copyright © 2016 Poet & Mountain, LLC. All rights reserved. +// Copyright © 2016-2018 Poet & Mountain, LLC. All rights reserved. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal diff --git a/Classes/EasingTypes/EasingSine.swift b/Classes/EasingTypes/EasingSine.swift index 0b1d301..99ffe61 100644 --- a/Classes/EasingTypes/EasingSine.swift +++ b/Classes/EasingTypes/EasingSine.swift @@ -3,7 +3,7 @@ // MotionMachine // // Created by Brett Walker on 5/3/16. -// Copyright © 2016 Poet & Mountain, LLC. All rights reserved. +// Copyright © 2016-2018 Poet & Mountain, LLC. All rights reserved. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal diff --git a/Classes/Motion.swift b/Classes/Motion.swift index 25cfb15..2240749 100644 --- a/Classes/Motion.swift +++ b/Classes/Motion.swift @@ -3,7 +3,7 @@ // MotionMachine // // Created by Brett Walker on 4/19/16. -// Copyright © 2016 Poet & Mountain, LLC. All rights reserved. +// Copyright © 2016-2018 Poet & Mountain, LLC. All rights reserved. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -524,7 +524,7 @@ public class Motion: Moveable, Additive, TempoDriven, PropertyDataDelegate { */ public convenience init(target targetObject: NSObject, properties: [PropertyData], duration: TimeInterval, easing: EasingUpdateClosure?=EasingLinear.easeNone(), options: MotionOptions?=MotionOptions.None) { - self.init(target: targetObject, properties: properties, finalStates: nil, duration: duration, easing: easing, options: options) + self.init(target: targetObject, properties: properties, statesForProperties: nil, duration: duration, easing: easing, options: options) } @@ -539,26 +539,26 @@ public class Motion: Moveable, Additive, TempoDriven, PropertyDataDelegate { */ public convenience init(target targetObject: NSObject, duration: TimeInterval, easing: EasingUpdateClosure?=EasingLinear.easeNone(), options: MotionOptions?=MotionOptions.None) { - self.init(target: targetObject, properties: [], finalStates: nil, duration: duration, easing: easing, options: options) + self.init(target: targetObject, properties: [], statesForProperties: nil, duration: duration, easing: easing, options: options) } /** - * Initializer. + * Initializer. Using this convenience method, you can pass in objects of the value type you're modifying without having to manually create `PropertyData` objects for each object property you wish to modify. For instance, if you're modifying a CGRect object, you can provide CGRect objects that represent its starting and ending states and it will handle the setup for all the properties of the CGRect that have changed between the two states. * * - parameters: * - target: The target object whose properties should be modified. - * - finalState: A Dictionary of template objects, with keys representing property keypaths (relative to the target object), and values that represent their final states. These final states must be of the same object type as the property located at the keypath. + * - statesForProperties: An Array of `PropertyStates` objects which represent property keypaths (relative to the target object), and values that represent their starting and ending states. By using `PropertyStates` objects, you can pass in objects of the value type you're modifying without having to manually create `PropertyData` objects for each object property you wish to modify. Please see the `PropertyStates` documentation for usage information. * - duration: The length of the motion, in seconds. * - easing: An optional `EasingUpdateClosure` easing equation to use when moving the values of the given properties. `EasingLinear.easeNone()` is the default equation if none is provided. * - options: An optional set of `MotionsOptions`. */ - public convenience init(target targetObject: NSObject, finalState templateObjects: [String:Any], duration: TimeInterval, easing: EasingUpdateClosure?=EasingLinear.easeNone(), options: MotionOptions?=MotionOptions.None) { + public convenience init(target targetObject: NSObject, statesForProperties templateObjects: [PropertyStates], duration: TimeInterval, easing: EasingUpdateClosure?=EasingLinear.easeNone(), options: MotionOptions?=MotionOptions.None) { - self.init(target: targetObject, properties: nil, finalStates: templateObjects, duration: duration, easing: easing, options: options) + self.init(target: targetObject, properties: nil, statesForProperties: templateObjects, duration: duration, easing: easing, options: options) } - private init(target targetObject: NSObject, properties props: [PropertyData]?, finalStates: [String:Any]?, duration: TimeInterval, easing: EasingUpdateClosure?, options: MotionOptions?) { + private init(target targetObject: NSObject, properties props: [PropertyData]?, statesForProperties: [PropertyStates]?, duration: TimeInterval, easing: EasingUpdateClosure?, options: MotionOptions?) { var properties = props ?? [] @@ -587,43 +587,8 @@ public class Motion: Moveable, Additive, TempoDriven, PropertyDataDelegate { _tempo?.delegate = self - if let final_object_states = finalStates { - for (path, final_state) in final_object_states { - var tobj: AnyObject = targetObject - if (path != "" && valueAssistant.acceptsKeypath(targetObject)) { - if let tvalue = targetObject.value(forKeyPath: path) as AnyObject? { - tobj = tvalue - } - } - - if let val = CGStructAssistant.valueForCGStruct(final_state) { - do { - let generated = try valueAssistant.generateProperties(fromObject: val, keyPath: path, targetObject: tobj) - properties.append(contentsOf: generated) - - } catch ValueAssistantError.typeRequirement(let valueType) { - ValueAssistantError.typeRequirement(valueType).printError(fromFunction: #function) - - } catch { - // any other errors - } - - } else { - do { - let generated = try valueAssistant.generateProperties(fromObject: (final_state as AnyObject), keyPath: path, targetObject: tobj) - properties.append(contentsOf: generated) - - } catch ValueAssistantError.typeRequirement(let valueType) { - ValueAssistantError.typeRequirement(valueType).printError(fromFunction: #function) - - } catch { - // any other errors - } - - } - - } - + if let unwrapped_states = statesForProperties { + properties = buildPropertyData(forObject: targetObject, propertyStates: unwrapped_states) } for property in properties { @@ -710,7 +675,7 @@ public class Motion: Moveable, Additive, TempoDriven, PropertyDataDelegate { * * - remark: When this method is used there is no need to specify `.Reverse` in the `options` parameter of the init method. * - * - parameter easing: The easing equation to be used while reversing. When no equation is provided, the normal `easing` closure will be used in both movement directions. + * - parameter withEasing: The easing equation to be used while reversing. When no equation is provided, the normal `easing` closure will be used in both movement directions. * - returns: A reference to this Motion instance, for the purpose of chaining multiple calls to this method. * - seealso: reversing, reverseEasing */ @@ -723,6 +688,64 @@ public class Motion: Moveable, Additive, TempoDriven, PropertyDataDelegate { } + /** + * Builds `PropertyData` objects for the supplied PropertyStates objects. + * + * - parameter forObject: The object to be modified, and the base object for the paths of the `PropertyStates` objects. + * - parameter propertyStates: An Array of `PropertyStates` objects that define how the `PropertyData` objects are constructed. + * - remark: This method is used internally by the initializer when the `statesForProperties` convenience method is used, but you can also call it directly to build an array of `PropertyData` objects. + * - returns: An Array of `PropertyData` objects. + */ + public func buildPropertyData(forObject targetObject: AnyObject, propertyStates: [PropertyStates]) -> [PropertyData] { + var data: [PropertyData] = [] + + for var property_states in propertyStates { + var tobj: AnyObject = targetObject + if (property_states.path != "" && valueAssistant.acceptsKeypath(targetObject)) { + if let tvalue = targetObject.value(forKeyPath: property_states.path) as AnyObject? { + tobj = tvalue + } + } + + if let end_val = CGStructAssistant.valueForCGStruct(property_states.end) { + do { + // the `generateProperties` method expects AnyObject for the states, so convert them to NSValue if we have a CGStruct + property_states.end = end_val + if let unwrapped_start = property_states.start, let start_val = CGStructAssistant.valueForCGStruct(unwrapped_start) { + property_states.start = start_val + } + + let generated = try valueAssistant.generateProperties(targetObject: tobj, propertyStates: property_states) + data.append(contentsOf: generated) + + } catch ValueAssistantError.typeRequirement(let valueType) { + ValueAssistantError.typeRequirement(valueType).printError(fromFunction: #function) + + } catch { + // any other errors + } + + } else { + do { + let generated = try valueAssistant.generateProperties(targetObject: tobj, propertyStates: property_states) + data.append(contentsOf: generated) + + } catch ValueAssistantError.typeRequirement(let valueType) { + ValueAssistantError.typeRequirement(valueType).printError(fromFunction: #function) + + } catch { + // any other errors + } + + } + + } + + return data + } + + + // MARK: - Private methods /** @@ -935,6 +958,7 @@ public class Motion: Moveable, Additive, TempoDriven, PropertyDataDelegate { private func updatePropertyValue(forProperty property: inout PropertyData) { let new_value = (additive) ? property.delta : property.current + if (property.targetObject == nil) { if let new_prop = valueAssistant.calculateValue(forProperty: property, newValue: new_value) { diff --git a/Classes/MotionGroup.swift b/Classes/MotionGroup.swift index 54a0002..0d17c28 100644 --- a/Classes/MotionGroup.swift +++ b/Classes/MotionGroup.swift @@ -3,7 +3,7 @@ // MotionMachine // // Created by Brett Walker on 5/6/16. -// Copyright © 2016 Poet & Mountain, LLC. All rights reserved. +// Copyright © 2016-2018 Poet & Mountain, LLC. All rights reserved. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal diff --git a/Classes/MotionMachine.swift b/Classes/MotionMachine.swift index 2d4c210..93d7c3f 100644 --- a/Classes/MotionMachine.swift +++ b/Classes/MotionMachine.swift @@ -3,7 +3,7 @@ // MotionMachine // // Created by Brett Walker on 4/19/16. -// Copyright © 2016 Poet & Mountain, LLC. All rights reserved. +// Copyright © 2016-2018 Poet & Mountain, LLC. All rights reserved. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -237,6 +237,8 @@ public protocol MotionUpdateDelegate: class { /// This protocol defines methods and properties that must be adopted for any value assistant. public protocol ValueAssistant { + init() + /** * This method returns an array of PropertyData instances based on the values of the provided object. * @@ -247,7 +249,7 @@ public protocol ValueAssistant { * * - returns: An array of PropertyData instances representing the values of the provided object. */ - func generateProperties(fromObject object: AnyObject, keyPath path: String, targetObject target: AnyObject) throws -> [PropertyData] + func generateProperties(targetObject target: AnyObject, propertyStates: PropertyStates) throws -> [PropertyData] /** * This method replaces an element of an AnyObject subclass by assigning new values. diff --git a/Classes/MotionSequence.swift b/Classes/MotionSequence.swift index d866c64..1bb821e 100644 --- a/Classes/MotionSequence.swift +++ b/Classes/MotionSequence.swift @@ -3,7 +3,7 @@ // MotionMachine // // Created by Brett Walker on 5/11/16. -// Copyright © 2016 Poet & Mountain, LLC. All rights reserved. +// Copyright © 2016-2018 Poet & Mountain, LLC. All rights reserved. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal diff --git a/Classes/MotionSupport.swift b/Classes/MotionSupport.swift index 80ab8c8..a57d4c7 100644 --- a/Classes/MotionSupport.swift +++ b/Classes/MotionSupport.swift @@ -3,7 +3,7 @@ // MotionMachine // // Created by Brett Walker on 4/20/16. -// Copyright © 2016 Poet & Mountain, LLC. All rights reserved. +// Copyright © 2016-2018 Poet & Mountain, LLC. All rights reserved. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal diff --git a/Classes/PhysicsMotion.swift b/Classes/PhysicsMotion.swift index 410841f..2bfde5e 100644 --- a/Classes/PhysicsMotion.swift +++ b/Classes/PhysicsMotion.swift @@ -3,7 +3,7 @@ // MotionMachine // // Created by Brett Walker on 5/16/16. -// Copyright © 2016 Poet & Mountain, LLC. All rights reserved. +// Copyright © 2016-2018 Poet & Mountain, LLC. All rights reserved. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal diff --git a/Classes/PhysicsSystem.swift b/Classes/PhysicsSystem.swift index fd62c1d..aec3ff8 100644 --- a/Classes/PhysicsSystem.swift +++ b/Classes/PhysicsSystem.swift @@ -3,7 +3,7 @@ // MotionMachine // // Created by Brett Walker on 5/16/16. -// Copyright © 2016 Poet & Mountain, LLC. All rights reserved. +// Copyright © 2016-2018 Poet & Mountain, LLC. All rights reserved. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal diff --git a/Classes/PropertyData.swift b/Classes/PropertyData.swift index 2d57dfc..9ff300e 100644 --- a/Classes/PropertyData.swift +++ b/Classes/PropertyData.swift @@ -3,7 +3,7 @@ // MotionMachine // // Created by Brett Walker on 4/26/16. -// Copyright © 2016 Poet & Mountain, LLC. All rights reserved. +// Copyright © 2016-2018 Poet & Mountain, LLC. All rights reserved. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -83,7 +83,7 @@ public struct PropertyData { public weak var targetObject: NSObject? /** - * The keyPath of the property to be moved. The keyPath must be a valid, KVC-compliant keyPath of `targetObject`. + * The keyPath of the property to be transformed. The keyPath must be a valid, KVC-compliant keyPath of `targetObject`. For your own classes, you must flag the property with `@objc` for Swift to find it. * * - seealso: targetObject */ diff --git a/Classes/PropertyStates.swift b/Classes/PropertyStates.swift new file mode 100644 index 0000000..342633a --- /dev/null +++ b/Classes/PropertyStates.swift @@ -0,0 +1,83 @@ +// +// PropertyStates.swift +// MotionMachine +// +// Created by Brett Walker on 3/17/18. +// Copyright © 2018 Poet & Mountain, LLC. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +import Foundation + +/** + * This struct represents the states of a single object property, to be used in a motion operation. Because the `start` and `end` properties can represent any value type, it is used to create `Motion` objects that conveniently handle many property value interpolations by simply passing in representations of that object at its starting and ending points. + * + * - remark: These state values must be of the same object type as the property located at the keypath. For instance, if the `path` property points to a CGRect object, you must provide CGRect objects for the `start` and `end` properties. + + **/ +public struct PropertyStates { + + /** + * The keyPath of the property to be transformed. The keyPath must be a valid, KVC-compliant keyPath of `targetObject`. For your own classes, you must flag the property with `@objc` for Swift to find it. + * + * - seealso: targetObject + */ + public let path: String + + /** + * An optional starting value of the motion operation. + * + * - remark: In typical cases, not specifying a starting value will result in the Motion class using the property's current value at the time the Motion is created. Note that for non-numeric properties like structs this may affect multiple values, such as the x and y properties of CGPoint. + * - warning: This value must be of the same object type as the property located at the specified path. For instance, if you're modifying a CGRect object, you must provide a CGRect object here. + * + * - seealso: end + */ + public var start: Any? + + /** + * The ending value of the motion operation. + * + * - remark: Note that for non-numeric properties like structs this may affect multiple values, such as the x and y properties of CGPoint. + * - warning: This value must be of the same object type as the property located at the specified path. For instance, if you're modifying a CGRect object, you must provide a CGRect object here. + */ + public var end: Any + + + /** + * Initializer. + * + * - parameters: + * - path: The keypath of the property to modify, relative to the target object provided to a Motion. + * - start: An optional starting value for the motion. + * - end: The ending value of the motion. + */ + public init(path: String, start: Any?=nil, end: Any) { + + self.path = path + + if let unwrapped_start = start { + self.start = unwrapped_start + } + + self.end = end + } + + +} diff --git a/Classes/Tempo.swift b/Classes/Tempo.swift index e5b8a43..a6038f0 100644 --- a/Classes/Tempo.swift +++ b/Classes/Tempo.swift @@ -3,7 +3,7 @@ // MotionMachine // // Created by Brett Walker on 4/19/16. -// Copyright © 2016 Poet & Mountain, LLC. All rights reserved. +// Copyright © 2016-2018 Poet & Mountain, LLC. All rights reserved. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal diff --git a/Classes/TimerTempo.swift b/Classes/TimerTempo.swift index 25cf595..e42711b 100644 --- a/Classes/TimerTempo.swift +++ b/Classes/TimerTempo.swift @@ -3,7 +3,7 @@ // MotionMachine // // Created by Brett Walker on 5/20/16. -// Copyright © 2016 Poet & Mountain, LLC. All rights reserved. +// Copyright © 2016-2018 Poet & Mountain, LLC. All rights reserved. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal diff --git a/Classes/ValueAssistants/CGStructAssistant.swift b/Classes/ValueAssistants/CGStructAssistant.swift index a62e769..be006fd 100644 --- a/Classes/ValueAssistants/CGStructAssistant.swift +++ b/Classes/ValueAssistants/CGStructAssistant.swift @@ -3,7 +3,7 @@ // MotionMachine // // Created by Brett Walker on 5/18/16. -// Copyright © 2016 Poet & Mountain, LLC. All rights reserved. +// Copyright © 2016-2018 Poet & Mountain, LLC. All rights reserved. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -43,24 +43,40 @@ public class CGStructAssistant : ValueAssistant { } } + public required init() {} + // MARK: ValueAssistant methods - public func generateProperties(fromObject object: AnyObject, keyPath path: String, targetObject target: AnyObject) throws -> [PropertyData] { + public func generateProperties(targetObject target: AnyObject, propertyStates: PropertyStates) throws -> [PropertyData] { + var properties: [PropertyData] = [] - guard let value = object as? NSValue else { throw ValueAssistantError.typeRequirement("NSValue") } + guard let end_value = propertyStates.end as? NSValue else { throw ValueAssistantError.typeRequirement("NSValue") } + var start_value: NSValue? + var start_type: ValueStructTypes = .unsupported + if let unwrapped_start = propertyStates.start { + if (propertyStates.start is NSValue) { + start_value = unwrapped_start as? NSValue + start_type = CGStructAssistant.determineType(forValue: start_value!) + } + } + + let end_type = CGStructAssistant.determineType(forValue: end_value) - let value_type = CGStructAssistant.determineType(forValue: value) - switch value_type { + switch end_type { case .number: - let number = value as! NSNumber - let property = PropertyData(path, number.doubleValue) + var start_state: Double? + if (start_value != nil && start_type == .number) { + start_state = (start_value as! NSNumber).doubleValue + } + let end_state = (end_value as! NSNumber).doubleValue + let property = PropertyData(path: propertyStates.path, start: start_state, end: end_state) properties.append(property) case .point: - var base_path: String = path + "." + var base_path: String = propertyStates.path + "." var org_x: Double? var org_y: Double? @@ -80,27 +96,37 @@ public class CGStructAssistant : ValueAssistant { } #endif - let pt = value.cgPointValue + let end_pt = end_value.cgPointValue if let unwrapped_x = org_x { - if (Double(pt.x) !≈ unwrapped_x) { - var prop_x = PropertyData("x", Double(pt.x)) - prop_x.path = base_path + prop_x.path - + var start_state: Double + if (start_value != nil && start_type == .point) { + start_state = Double(start_value!.cgPointValue.x) + } else { + start_state = unwrapped_x + } + + if (Double(end_pt.x) !≈ start_state) { + let prop_x = PropertyData(path: base_path + "x", start: start_state, end: Double(end_pt.x)) properties.append(prop_x) } } if let unwrapped_y = org_y { - if (Double(pt.y) !≈ unwrapped_y) { - var prop_y = PropertyData("y", Double(pt.y)) - prop_y.path = base_path + prop_y.path - + var start_state: Double + if (start_value != nil && start_type == .point) { + start_state = Double(start_value!.cgPointValue.y) + } else { + start_state = unwrapped_y + } + + if (Double(end_pt.y) !≈ start_state) { + let prop_y = PropertyData(path: base_path + "y", start: start_state, end: Double(end_pt.y)) properties.append(prop_y) } } case .size: - var base_path: String = path + "." + var base_path: String = propertyStates.path + "." var org_w: Double? var org_h: Double? @@ -119,51 +145,73 @@ public class CGStructAssistant : ValueAssistant { org_h = Double(org_size.height) } } - let size = value.cgSizeValue + let end_size = end_value.cgSizeValue if let unwrapped_w = org_w { - if (Double(size.width) !≈ unwrapped_w) { - var prop_w = PropertyData("width", Double(size.width)) - prop_w.path = base_path + prop_w.path - + var start_state: Double + if (start_value != nil && start_type == .size) { + start_state = Double(start_value!.cgSizeValue.width) + } else { + start_state = unwrapped_w + } + + if (Double(end_size.width) !≈ start_state) { + let prop_w = PropertyData(path: base_path + "width", start: start_state, end: Double(end_size.width)) properties.append(prop_w) } } if let unwrapped_h = org_h { - if (Double(size.height) !≈ unwrapped_h) { - var prop_h = PropertyData("height", Double(size.height)) - prop_h.path = base_path + prop_h.path - + var start_state: Double + if (start_value != nil && start_type == .size) { + start_state = Double(start_value!.cgSizeValue.height) + } else { + start_state = unwrapped_h + } + + if (Double(end_size.height) !≈ start_state) { + let prop_h = PropertyData(path: base_path + "height", start: start_state, end: Double(end_size.height)) properties.append(prop_h) } } case .rect: - var base_path: String = path + "." + var base_path: String = propertyStates.path + "." #if os(iOS) || os(tvOS) - if (target is UIView && path == "") { + if (target is UIView && propertyStates.path == "") { base_path = "frame." } #endif - let rect = value.cgRectValue - let pt_value = NSValue.init(cgPoint: rect.origin) + let end_rect = end_value.cgRectValue var target_pt: NSValue? var target_size: NSValue? - #if os(iOS) || os(tvOS) - if let unwrapped_view = target as? UIView { - target_pt = NSValue.init(cgPoint: unwrapped_view.frame.origin) - target_size = NSValue.init(cgSize: unwrapped_view.frame.size) - } - #endif + if let unwrapped_value = target as? NSValue { let target_rect = unwrapped_value.cgRectValue target_pt = NSValue.init(cgPoint: target_rect.origin) target_size = NSValue.init(cgSize: target_rect.size) } + #if os(iOS) || os(tvOS) + if let unwrapped_view = target as? UIView { + target_pt = NSValue.init(cgPoint: unwrapped_view.frame.origin) + target_size = NSValue.init(cgSize: unwrapped_view.frame.size) + } + #endif + if let unwrapped_pt = target_pt { + let end_pt_value = NSValue.init(cgPoint: end_rect.origin) + do { - var pt_props = try generateProperties(fromObject: pt_value, keyPath: "", targetObject: unwrapped_pt) + let start_pt: NSValue + if (start_value != nil && start_type == .rect) { + let start_rect = start_value!.cgRectValue + start_pt = NSValue.init(cgPoint: start_rect.origin) + } else { + start_pt = unwrapped_pt + } + + let states = PropertyStates(path: "", start: start_pt, end: end_pt_value) + var pt_props = try generateProperties(targetObject: unwrapped_pt, propertyStates: states) var mid_path = "" if (target is NSValue) { mid_path = "origin" @@ -182,10 +230,20 @@ public class CGStructAssistant : ValueAssistant { } if let unwrapped_size = target_size { - let size_value = NSValue.init(cgSize: rect.size) + let end_size_value = NSValue.init(cgSize: end_rect.size) do { - var size_props = try generateProperties(fromObject: size_value, keyPath: "", targetObject: unwrapped_size) + let start_size: NSValue + if (start_value != nil && start_type == .rect) { + let start_rect = start_value!.cgRectValue + start_size = NSValue.init(cgSize: start_rect.size) + } else { + start_size = unwrapped_size + } + + let states = PropertyStates(path: "", start: start_size, end: end_size_value) + + var size_props = try generateProperties(targetObject: unwrapped_size, propertyStates: states) var mid_path = "" if (target is NSValue) { mid_path = "size" @@ -204,6 +262,8 @@ public class CGStructAssistant : ValueAssistant { } case .vector: + let base_path: String = propertyStates.path + "." + var org_dx: Double? var org_dy: Double? if (target is NSValue) { @@ -214,16 +274,30 @@ public class CGStructAssistant : ValueAssistant { org_dy = Double(org_vec.dy) } } - let vector = value.cgVectorValue + let end_vector = end_value.cgVectorValue if let unwrapped_dx = org_dx { - if (Double(vector.dx) !≈ unwrapped_dx) { - let prop_dx = PropertyData(path + ".dx", Double(vector.dx)) + var start_state: Double + if (start_value != nil && start_type == .vector) { + start_state = Double(start_value!.cgVectorValue.dx) + } else { + start_state = unwrapped_dx + } + + if (Double(end_vector.dx) !≈ start_state) { + let prop_dx = PropertyData(path: base_path + "dx", start: start_state, end: Double(end_vector.dx)) properties.append(prop_dx) } } if let unwrapped_dy = org_dy { - if (Double(vector.dy) !≈ unwrapped_dy) { - let prop_dy = PropertyData(path + ".dy", Double(vector.dy)) + var start_state: Double + if (start_value != nil && start_type == .vector) { + start_state = Double(start_value!.cgVectorValue.dy) + } else { + start_state = unwrapped_dy + } + + if (Double(end_vector.dy) !≈ start_state) { + let prop_dy = PropertyData(path: base_path + "dy", start: start_state, end: Double(end_vector.dy)) properties.append(prop_dy) } } @@ -249,41 +323,83 @@ public class CGStructAssistant : ValueAssistant { } // find all transform properties - let transform = value.cgAffineTransformValue - let base_path = path + "." + let end_transform = end_value.cgAffineTransformValue + let base_path = propertyStates.path + "." if let ua = oa { - if (Double(transform.a) !≈ ua) { - let p = PropertyData(base_path + "a", Double(transform.a)) + var start_state: Double + if (start_value != nil && start_type == .affineTransform) { + start_state = Double(start_value!.cgAffineTransformValue.a) + } else { + start_state = ua + } + + if (Double(end_transform.a) !≈ start_state) { + let p = PropertyData(path: base_path + "a", start: start_state, end: Double(end_transform.a)) properties.append(p) } } if let ub = ob { - if (Double(transform.b) !≈ ub) { - let p = PropertyData(base_path + "b", Double(transform.b)) + var start_state: Double + if (start_value != nil && start_type == .affineTransform) { + start_state = Double(start_value!.cgAffineTransformValue.b) + } else { + start_state = ub + } + + if (Double(end_transform.b) !≈ start_state) { + let p = PropertyData(path: base_path + "b", start: start_state, end: Double(end_transform.b)) properties.append(p) } } if let uc = oc { - if (Double(transform.c) !≈ uc) { - let p = PropertyData(base_path + "c", Double(transform.c)) + var start_state: Double + if (start_value != nil && start_type == .affineTransform) { + start_state = Double(start_value!.cgAffineTransformValue.c) + } else { + start_state = uc + } + + if (Double(end_transform.c) !≈ start_state) { + let p = PropertyData(path: base_path + "c", start: start_state, end: Double(end_transform.c)) properties.append(p) } } if let ud = od { - if (Double(transform.d) !≈ ud) { - let p = PropertyData(base_path + "d", Double(transform.d)) + var start_state: Double + if (start_value != nil && start_type == .affineTransform) { + start_state = Double(start_value!.cgAffineTransformValue.d) + } else { + start_state = ud + } + + if (Double(end_transform.d) !≈ start_state) { + let p = PropertyData(path: base_path + "d", start: start_state, end: Double(end_transform.d)) properties.append(p) } } if let utx = otx { - if (Double(transform.tx) !≈ utx) { - let p = PropertyData(base_path + "tx", Double(transform.tx)) + var start_state: Double + if (start_value != nil && start_type == .affineTransform) { + start_state = Double(start_value!.cgAffineTransformValue.tx) + } else { + start_state = utx + } + + if (Double(end_transform.tx) !≈ start_state) { + let p = PropertyData(path: base_path + "tx", start: start_state, end: Double(end_transform.tx)) properties.append(p) } } if let uty = oty { - if (Double(transform.ty) !≈ uty) { - let p = PropertyData(base_path + "ty", Double(transform.ty)) + var start_state: Double + if (start_value != nil && start_type == .affineTransform) { + start_state = Double(start_value!.cgAffineTransformValue.ty) + } else { + start_state = uty + } + + if (Double(end_transform.ty) !≈ start_state) { + let p = PropertyData(path: base_path + "ty", start: start_state, end: Double(end_transform.ty)) properties.append(p) } } @@ -314,111 +430,216 @@ public class CGStructAssistant : ValueAssistant { o44 = Double(org_t.m44) } } - let base_path = path + "." + let base_path = propertyStates.path + "." - let transform = value.caTransform3DValue + let transform = end_value.caTransform3DValue if let u11 = o11 { let double_val = Double(transform.m11) - if (double_val !≈ u11) { - let p = PropertyData(base_path + "m11", double_val) + var start_state: Double + if (start_value != nil && start_type == .transform3D) { + start_state = Double(start_value!.caTransform3DValue.m11) + } else { + start_state = u11 + } + + if (double_val !≈ start_state) { + let p = PropertyData(path: base_path + "m11", start: start_state, end: double_val) properties.append(p) } } if let u12 = o12 { let double_val = Double(transform.m12) - if (double_val !≈ u12) { - let p = PropertyData(base_path + "m12", double_val) + var start_state: Double + if (start_value != nil && start_type == .transform3D) { + start_state = Double(start_value!.caTransform3DValue.m12) + } else { + start_state = u12 + } + + if (double_val !≈ start_state) { + let p = PropertyData(path: base_path + "m12", start: start_state, end: double_val) properties.append(p) } } if let u13 = o13 { let double_val = Double(transform.m13) - if (double_val !≈ u13) { - let p = PropertyData(base_path + "m13", double_val) + var start_state: Double + if (start_value != nil && start_type == .transform3D) { + start_state = Double(start_value!.caTransform3DValue.m13) + } else { + start_state = u13 + } + + if (double_val !≈ start_state) { + let p = PropertyData(path: base_path + "m13", start: start_state, end: double_val) properties.append(p) } } if let u14 = o14 { let double_val = Double(transform.m14) - if (double_val !≈ u14) { - let p = PropertyData(base_path + "m14", double_val) + var start_state: Double + if (start_value != nil && start_type == .transform3D) { + start_state = Double(start_value!.caTransform3DValue.m14) + } else { + start_state = u14 + } + + if (double_val !≈ start_state) { + let p = PropertyData(path: base_path + "m14", start: start_state, end: double_val) properties.append(p) } } if let u21 = o21 { let double_val = Double(transform.m21) - if (double_val !≈ u21) { - let p = PropertyData(base_path + "m21", double_val) + var start_state: Double + if (start_value != nil && start_type == .transform3D) { + start_state = Double(start_value!.caTransform3DValue.m21) + } else { + start_state = u21 + } + + if (double_val !≈ start_state) { + let p = PropertyData(path: base_path + "m21", start: start_state, end: double_val) properties.append(p) } } if let u22 = o22 { let double_val = Double(transform.m22) - if (double_val !≈ u22) { - let p = PropertyData(base_path + "m22", double_val) + var start_state: Double + if (start_value != nil && start_type == .transform3D) { + start_state = Double(start_value!.caTransform3DValue.m22) + } else { + start_state = u22 + } + + if (double_val !≈ start_state) { + let p = PropertyData(path: base_path + "m22", start: start_state, end: double_val) properties.append(p) } } if let u23 = o23 { let double_val = Double(transform.m23) - if (double_val !≈ u23) { - let p = PropertyData(base_path + "m23", double_val) + var start_state: Double + if (start_value != nil && start_type == .transform3D) { + start_state = Double(start_value!.caTransform3DValue.m23) + } else { + start_state = u23 + } + + if (double_val !≈ start_state) { + let p = PropertyData(path: base_path + "m23", start: start_state, end: double_val) properties.append(p) } } if let u24 = o24 { let double_val = Double(transform.m24) - if (double_val !≈ u24) { - let p = PropertyData(base_path + "m24", double_val) + var start_state: Double + if (start_value != nil && start_type == .transform3D) { + start_state = Double(start_value!.caTransform3DValue.m24) + } else { + start_state = u24 + } + + if (double_val !≈ start_state) { + let p = PropertyData(path: base_path + "m24", start: start_state, end: double_val) properties.append(p) } } if let u31 = o31 { let double_val = Double(transform.m31) - if (double_val !≈ u31) { - let p = PropertyData(base_path + "m31", double_val) + var start_state: Double + if (start_value != nil && start_type == .transform3D) { + start_state = Double(start_value!.caTransform3DValue.m31) + } else { + start_state = u31 + } + + if (double_val !≈ start_state) { + let p = PropertyData(path: base_path + "m31", start: start_state, end: double_val) properties.append(p) } } if let u32 = o32 { let double_val = Double(transform.m32) - if (double_val !≈ u32) { - let p = PropertyData(base_path + "m32", double_val) + var start_state: Double + if (start_value != nil && start_type == .transform3D) { + start_state = Double(start_value!.caTransform3DValue.m32) + } else { + start_state = u32 + } + + if (double_val !≈ start_state) { + let p = PropertyData(path: base_path + "m32", start: start_state, end: double_val) properties.append(p) } } if let u33 = o33 { let double_val = Double(transform.m33) - if (double_val !≈ u33) { - let p = PropertyData(base_path + "m33", double_val) + var start_state: Double + if (start_value != nil && start_type == .transform3D) { + start_state = Double(start_value!.caTransform3DValue.m33) + } else { + start_state = u33 + } + + if (double_val !≈ start_state) { + let p = PropertyData(path: base_path + "m33", start: start_state, end: double_val) properties.append(p) } } if let u34 = o34 { let double_val = Double(transform.m34) - if (double_val !≈ u34) { - let p = PropertyData(base_path + "m34", double_val) + var start_state: Double + if (start_value != nil && start_type == .transform3D) { + start_state = Double(start_value!.caTransform3DValue.m34) + } else { + start_state = u34 + } + + if (double_val !≈ start_state) { + let p = PropertyData(path: base_path + "m34", start: start_state, end: double_val) properties.append(p) } } if let u42 = o42 { let double_val = Double(transform.m42) - if (double_val !≈ u42) { - let p = PropertyData(base_path + "m42", double_val) + var start_state: Double + if (start_value != nil && start_type == .transform3D) { + start_state = Double(start_value!.caTransform3DValue.m42) + } else { + start_state = u42 + } + + if (double_val !≈ start_state) { + let p = PropertyData(path: base_path + "m42", start: start_state, end: double_val) properties.append(p) } } if let u43 = o43 { let double_val = Double(transform.m43) - if (double_val !≈ u43) { - let p = PropertyData(base_path + "m43", double_val) + var start_state: Double + if (start_value != nil && start_type == .transform3D) { + start_state = Double(start_value!.caTransform3DValue.m43) + } else { + start_state = u43 + } + + if (double_val !≈ start_state) { + let p = PropertyData(path: base_path + "m43", start: start_state, end: double_val) properties.append(p) } } if let u44 = o44 { let double_val = Double(transform.m44) - if (double_val !≈ u44) { - let p = PropertyData(base_path + "m44", double_val) + var start_state: Double + if (start_value != nil && start_type == .transform3D) { + start_state = Double(start_value!.caTransform3DValue.m44) + } else { + start_state = u44 + } + + if (double_val !≈ start_state) { + let p = PropertyData(path: base_path + "m44", start: start_state, end: double_val) properties.append(p) } } diff --git a/Classes/ValueAssistants/CIColorAssistant.swift b/Classes/ValueAssistants/CIColorAssistant.swift index ba2d39a..7fa6876 100644 --- a/Classes/ValueAssistants/CIColorAssistant.swift +++ b/Classes/ValueAssistants/CIColorAssistant.swift @@ -3,7 +3,7 @@ // MotionMachine // // Created by Brett Walker on 5/26/16. -// Copyright © 2016 Poet & Mountain, LLC. All rights reserved. +// Copyright © 2016-2018 Poet & Mountain, LLC. All rights reserved. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -38,14 +38,19 @@ public class CIColorAssistant : ValueAssistant { } } + public required init() {} + + // MARK: ValueAssistant methods - public func generateProperties(fromObject object: AnyObject, keyPath path: String, targetObject target: AnyObject) -> [PropertyData] { + public func generateProperties(targetObject target: AnyObject, propertyStates: PropertyStates) throws -> [PropertyData] { + var properties: [PropertyData] = [] - if (object is CIColor) { + if (propertyStates.end is CIColor) { + - let new_color = object as! CIColor + let new_color = propertyStates.end as! CIColor var red: CGFloat = 0.0, green: CGFloat = 0.0, blue: CGFloat = 0.0, alpha: CGFloat = 0.0 var add_alpha = false @@ -61,37 +66,67 @@ public class CIColorAssistant : ValueAssistant { alpha = tcolor.alpha } + var start_color: CIColor? + if let unwrapped_start = propertyStates.start { + if (propertyStates.start is CIColor) { + start_color = unwrapped_start as? CIColor + // we need to save start color values so we can compare to new color below + let scolor = unwrapped_start as! CIColor + red = scolor.red + blue = scolor.blue + green = scolor.green + alpha = scolor.alpha + } + } + + // check each component to avoid building PropertyData objects for color components whose start and end values are the same if (Double(red) !≈ Double(new_color.red)) { add_red = true } if (Double(blue) !≈ Double(new_color.blue)) { add_blue = true } if (Double(green) !≈ Double(new_color.green)) { add_green = true } if (Double(alpha) !≈ Double(new_color.alpha)) { add_alpha = true } if (add_red) { - let p = PropertyData("red", Double(new_color.red)) + var start_state: Double? + if let unwrapped_start_color = start_color { + start_state = Double(unwrapped_start_color.red) + } + let p = PropertyData(path: "red", start: start_state, end: Double(new_color.red)) properties.append(p) } if (add_green) { - let p = PropertyData("green", Double(new_color.green)) + var start_state: Double? + if let unwrapped_start_color = start_color { + start_state = Double(unwrapped_start_color.green) + } + let p = PropertyData(path: "green", start: start_state, end: Double(new_color.green)) properties.append(p) } if (add_blue) { - let p = PropertyData("blue", Double(new_color.blue)) + var start_state: Double? + if let unwrapped_start_color = start_color { + start_state = Double(unwrapped_start_color.blue) + } + let p = PropertyData(path: "blue", start: start_state, end: Double(new_color.blue)) properties.append(p) } if (add_alpha) { - let p = PropertyData("alpha", Double(new_color.alpha)) + var start_state: Double? + if let unwrapped_start_color = start_color { + start_state = Double(unwrapped_start_color.alpha) + } + let p = PropertyData(path: "alpha", start: start_state, end: Double(new_color.alpha)) properties.append(p) } } - if (path != "") { + if (propertyStates.path != "") { for index in 0 ..< properties.count { if (properties[index].path != "") { - properties[index].path = path + "." + properties[index].path + properties[index].path = propertyStates.path + "." + properties[index].path } else { - properties[index].path = path + properties[index].path = propertyStates.path } } } diff --git a/Classes/ValueAssistants/UIColorAssistant.swift b/Classes/ValueAssistants/UIColorAssistant.swift index fcae3d7..50d4511 100644 --- a/Classes/ValueAssistants/UIColorAssistant.swift +++ b/Classes/ValueAssistants/UIColorAssistant.swift @@ -3,7 +3,7 @@ // MotionMachine // // Created by Brett Walker on 5/18/16. -// Copyright © 2016 Poet & Mountain, LLC. All rights reserved. +// Copyright © 2016-2018 Poet & Mountain, LLC. All rights reserved. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -38,13 +38,18 @@ public class UIColorAssistant : ValueAssistant { } } + public required init() {} + + // MARK: ValueAssistant methods - public func generateProperties(fromObject object: AnyObject, keyPath path: String, targetObject target: AnyObject) -> [PropertyData] { + public func generateProperties(targetObject target: AnyObject, propertyStates: PropertyStates) throws -> [PropertyData] { + var properties: [PropertyData] = [] - if (object is UIColor) { - let color = object as! UIColor + if (propertyStates.end is UIColor) { + + let new_color = propertyStates.end as! UIColor var hue: CGFloat = 0.0, saturation: CGFloat = 0.0, brightness: CGFloat = 0.0, alpha: CGFloat = 0.0 var red: CGFloat = 0.0, green: CGFloat = 0.0, blue: CGFloat = 0.0 var white: CGFloat = 0.0, walpha: CGFloat = 0.0 @@ -59,9 +64,19 @@ public class UIColorAssistant : ValueAssistant { var add_white = false var ocolor: UIColor? + + // first check if target is a UIColor, and if so use that as the ocolor base if (target is UIColor) { ocolor = target as? UIColor } + + // if there's a start value in the PropertyStates object and it's a UIColor then use that instead + if let unwrapped_start = propertyStates.start { + if (propertyStates.start is UIColor) { + ocolor = unwrapped_start as? UIColor + } + } + var ohue: CGFloat = 0.0, osaturation: CGFloat = 0.0, obrightness: CGFloat = 0.0, oalpha: CGFloat = 0.0 var ored: CGFloat = 0.0, ogreen: CGFloat = 0.0, oblue: CGFloat = 0.0 var owhite: CGFloat = 0.0, owalpha: CGFloat = 0.0 @@ -72,11 +87,12 @@ public class UIColorAssistant : ValueAssistant { ocolor!.getWhite(&owhite, alpha: &owalpha) } - color.getHue(&hue, saturation: &saturation, brightness: &brightness, alpha: &alpha) - color.getRed(&red, green: &green, blue: &blue, alpha: &alpha) - color.getWhite(&white, alpha: &walpha) + new_color.getHue(&hue, saturation: &saturation, brightness: &brightness, alpha: &alpha) + new_color.getRed(&red, green: &green, blue: &blue, alpha: &alpha) + new_color.getWhite(&white, alpha: &walpha) if (ocolor != nil) { + // check each component to avoid building PropertyData objects for color components whose start and end values are the same if (Double(red) !≈ Double(ored)) { add_red = true } if (Double(blue) !≈ Double(oblue)) { add_blue = true } if (Double(green) !≈ Double(ogreen)) { add_green = true } @@ -95,35 +111,35 @@ public class UIColorAssistant : ValueAssistant { } if (add_hue) { - let p = PropertyData("hue", Double(hue)) + let p = PropertyData(path: "hue", start: Double(ohue), end: Double(hue)) properties.append(p) } if (add_sat) { - let p = PropertyData("saturation", Double(saturation)) + let p = PropertyData(path: "saturation", start: Double(osaturation), end: Double(saturation)) properties.append(p) } if (add_brightness) { - let p = PropertyData("brightness", Double(brightness)) + let p = PropertyData(path: "brightness", start: Double(obrightness), end: Double(brightness)) properties.append(p) } if (add_alpha) { - let p = PropertyData("alpha", Double(alpha)) + let p = PropertyData(path: "alpha", start: Double(oalpha), end: Double(alpha)) properties.append(p) } if (add_red) { - let p = PropertyData("red", Double(red)) + let p = PropertyData(path: "red", start: Double(ored), end: Double(red)) properties.append(p) } if (add_green) { - let p = PropertyData("green", Double(green)) + let p = PropertyData(path: "green", start: Double(ogreen), end: Double(green)) properties.append(p) } if (add_blue) { - let p = PropertyData("blue", Double(blue)) + let p = PropertyData(path: "blue", start: Double(oblue), end: Double(blue)) properties.append(p) } if (add_white) { - let p = PropertyData("white", Double(white)) + let p = PropertyData(path: "white", start: Double(owhite), end: Double(white)) properties.append(p) } @@ -136,12 +152,12 @@ public class UIColorAssistant : ValueAssistant { } - if (path != "") { + if (propertyStates.path != "") { for index in 0 ..< properties.count { if (properties[index].path != "") { - properties[index].path = path + "." + properties[index].path + properties[index].path = propertyStates.path + "." + properties[index].path } else { - properties[index].path = path + properties[index].path = propertyStates.path } } } diff --git a/Classes/ValueAssistants/UIKitStructAssistant.swift b/Classes/ValueAssistants/UIKitStructAssistant.swift index 6d3e8c2..174a8d5 100644 --- a/Classes/ValueAssistants/UIKitStructAssistant.swift +++ b/Classes/ValueAssistants/UIKitStructAssistant.swift @@ -3,7 +3,7 @@ // MotionMachine // // Created by Brett Walker on 5/30/16. -// Copyright © 2016 Poet & Mountain, LLC. All rights reserved. +// Copyright © 2016-2018 Poet & Mountain, LLC. All rights reserved. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -42,7 +42,7 @@ public class UIKitStructAssistant : ValueAssistant { * Initializer. * */ - public init() { + public required init() { // provide support for UIKit structs // doesn't seem like there's a better way to extend the enum array from multiple assistants than this? ValueStructTypes.valueTypes[.uiEdgeInsets] = NSValue(uiEdgeInsets: UIEdgeInsets.zero).objCType @@ -52,16 +52,25 @@ public class UIKitStructAssistant : ValueAssistant { // MARK: ValueAssistant methods - public func generateProperties(fromObject object: AnyObject, keyPath path: String, targetObject target: AnyObject) throws -> [PropertyData] { + public func generateProperties(targetObject target: AnyObject, propertyStates: PropertyStates) throws -> [PropertyData] { + var properties: [PropertyData] = [] - guard let value = object as? NSValue else { throw ValueAssistantError.typeRequirement("NSValue") } - - let value_type = UIKitStructAssistant.determineType(forValue: value) + guard let end_value = propertyStates.end as? NSValue else { throw ValueAssistantError.typeRequirement("NSValue") } + var start_value: NSValue? + var start_type: ValueStructTypes = .unsupported + if let unwrapped_start = propertyStates.start { + if (propertyStates.start is NSValue) { + start_value = unwrapped_start as? NSValue + start_type = UIKitStructAssistant.determineType(forValue: start_value!) + } + } + + let end_type = UIKitStructAssistant.determineType(forValue: end_value) - switch value_type { + switch end_type { case .uiEdgeInsets: - let base_path: String = path + "." + let base_path: String = propertyStates.path + "." var org_top: Double? var org_left: Double? @@ -79,39 +88,63 @@ public class UIKitStructAssistant : ValueAssistant { } } - let insets = value.uiEdgeInsetsValue + let insets = end_value.uiEdgeInsetsValue if let unwrapped_top = org_top { - if (Double(insets.top) !≈ unwrapped_top) { - var prop = PropertyData("top", Double(insets.top)) - prop.path = base_path + prop.path + var start_state: Double + if (start_value != nil && start_type == .uiEdgeInsets) { + start_state = Double(start_value!.uiEdgeInsetsValue.top) + } else { + start_state = unwrapped_top + } + + if (Double(insets.top) !≈ start_state) { + let prop = PropertyData(path: base_path + "top", start: start_state, end: Double(insets.top)) properties.append(prop) } } if let unwrapped_left = org_left { - if (Double(insets.left) !≈ unwrapped_left) { - var prop = PropertyData("left", Double(insets.left)) - prop.path = base_path + prop.path + var start_state: Double + if (start_value != nil && start_type == .uiEdgeInsets) { + start_state = Double(start_value!.uiEdgeInsetsValue.left) + } else { + start_state = unwrapped_left + } + + if (Double(insets.left) !≈ start_state) { + let prop = PropertyData(path: base_path + "left", start: start_state, end: Double(insets.left)) properties.append(prop) } } if let unwrapped_bottom = org_bottom { - if (Double(insets.bottom) !≈ unwrapped_bottom) { - var prop = PropertyData("bottom", Double(insets.bottom)) - prop.path = base_path + prop.path + var start_state: Double + if (start_value != nil && start_type == .uiEdgeInsets) { + start_state = Double(start_value!.uiEdgeInsetsValue.bottom) + } else { + start_state = unwrapped_bottom + } + + if (Double(insets.bottom) !≈ start_state) { + let prop = PropertyData(path: base_path + "bottom", start: start_state, end: Double(insets.bottom)) properties.append(prop) } } if let unwrapped_right = org_right { - if (Double(insets.right) !≈ unwrapped_right) { - var prop = PropertyData("right", Double(insets.right)) - prop.path = base_path + prop.path + var start_state: Double + if (start_value != nil && start_type == .uiEdgeInsets) { + start_state = Double(start_value!.uiEdgeInsetsValue.right) + } else { + start_state = unwrapped_right + } + + if (Double(insets.right) !≈ start_state) { + let prop = PropertyData(path: base_path + "right", start: start_state, end: Double(insets.right)) properties.append(prop) } } case .uiOffset: - let base_path: String = path + "." + let base_path: String = propertyStates.path + "." var org_h: Double? var org_v: Double? @@ -125,19 +158,31 @@ public class UIKitStructAssistant : ValueAssistant { } } - let offset = value.uiOffsetValue + let offset = end_value.uiOffsetValue if let unwrapped_h = org_h { - if (Double(offset.horizontal) !≈ unwrapped_h) { - var prop = PropertyData("horizontal", Double(offset.horizontal)) - prop.path = base_path + prop.path + var start_state: Double + if (start_value != nil && start_type == .uiOffset) { + start_state = Double(start_value!.uiOffsetValue.horizontal) + } else { + start_state = unwrapped_h + } + + if (Double(offset.horizontal) !≈ start_state) { + let prop = PropertyData(path: base_path + "horizontal", start: start_state, end: Double(offset.horizontal)) properties.append(prop) } } if let unwrapped_v = org_v { - if (Double(offset.vertical) !≈ unwrapped_v) { - var prop = PropertyData("vertical", Double(offset.vertical)) - prop.path = base_path + prop.path + var start_state: Double + if (start_value != nil && start_type == .uiOffset) { + start_state = Double(start_value!.uiOffsetValue.vertical) + } else { + start_state = unwrapped_v + } + + if (Double(offset.vertical) !≈ start_state) { + let prop = PropertyData(path: base_path + "vertical", start: start_state, end: Double(offset.vertical)) properties.append(prop) } } diff --git a/Classes/ValueAssistants/ValueAssistantGroup.swift b/Classes/ValueAssistants/ValueAssistantGroup.swift index 52faf69..5cd11d2 100644 --- a/Classes/ValueAssistants/ValueAssistantGroup.swift +++ b/Classes/ValueAssistants/ValueAssistantGroup.swift @@ -3,7 +3,7 @@ // MotionMachine // // Created by Brett Walker on 5/18/16. -// Copyright © 2016 Poet & Mountain, LLC. All rights reserved. +// Copyright © 2016-2018 Poet & Mountain, LLC. All rights reserved. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -55,14 +55,17 @@ public class ValueAssistantGroup : ValueAssistant { * - parameters: * - assistants: An optional array of `ValueAssistant` objects to which the ValueAssistantGroup should delegate `ValueAssistant` method calls. */ - public init(assistants: [ValueAssistant]? = []) { - + public convenience init(assistants: [ValueAssistant]? = []) { + self.init() if let unwrapped_assists = assistants { self.assistants = unwrapped_assists } } + public required init() {} + + // MARK: Public Methods @@ -84,16 +87,18 @@ public class ValueAssistantGroup : ValueAssistant { // MARK: ValueAssistant methods - public func generateProperties(fromObject object: AnyObject, keyPath path: String, targetObject target: AnyObject) -> [PropertyData] { + public func generateProperties(targetObject target: AnyObject, propertyStates: PropertyStates) throws -> [PropertyData] { + var properties: [PropertyData] = [] for assistant in assistants { - if (assistant.supports(object)) { - if let generated = try? assistant.generateProperties(fromObject: object, keyPath: path, targetObject: target) { - properties = generated + if (assistant.supports(propertyStates.end as AnyObject)) { + if let generated = try? assistant.generateProperties(targetObject: target, propertyStates: propertyStates) { + properties += generated break } } + } return properties diff --git a/Examples/MotionExamples.xcodeproj/project.pbxproj b/Examples/MotionExamples.xcodeproj/project.pbxproj index 3407a28..ae451f7 100644 --- a/Examples/MotionExamples.xcodeproj/project.pbxproj +++ b/Examples/MotionExamples.xcodeproj/project.pbxproj @@ -13,37 +13,38 @@ 8B683B041D00BE76008D43E2 /* GroupMotionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B683B031D00BE76008D43E2 /* GroupMotionViewController.swift */; }; 8B683B061D00E386008D43E2 /* SequenceContiguousViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B683B051D00E386008D43E2 /* SequenceContiguousViewController.swift */; }; 8B683B081D012529008D43E2 /* SequenceViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B683B071D012529008D43E2 /* SequenceViewController.swift */; }; + 8BA8504E205F73E100F1FA7B /* Motion.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BA85030205F73E100F1FA7B /* Motion.swift */; }; + 8BA8504F205F73E100F1FA7B /* PhysicsMotion.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BA85031205F73E100F1FA7B /* PhysicsMotion.swift */; }; + 8BA85050205F73E100F1FA7B /* CATempo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BA85032205F73E100F1FA7B /* CATempo.swift */; }; + 8BA85051205F73E100F1FA7B /* PropertyStates.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BA85033205F73E100F1FA7B /* PropertyStates.swift */; }; + 8BA85052205F73E100F1FA7B /* MotionSupport.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BA85034205F73E100F1FA7B /* MotionSupport.swift */; }; + 8BA85053205F73E100F1FA7B /* EasingElastic.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BA85036205F73E100F1FA7B /* EasingElastic.swift */; }; + 8BA85054205F73E100F1FA7B /* EasingLinear.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BA85037205F73E100F1FA7B /* EasingLinear.swift */; }; + 8BA85055205F73E100F1FA7B /* EasingSine.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BA85038205F73E100F1FA7B /* EasingSine.swift */; }; + 8BA85056205F73E100F1FA7B /* EasingQuadratic.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BA85039205F73E100F1FA7B /* EasingQuadratic.swift */; }; + 8BA85057205F73E100F1FA7B /* EasingCubic.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BA8503A205F73E100F1FA7B /* EasingCubic.swift */; }; + 8BA85058205F73E100F1FA7B /* EasingCircular.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BA8503B205F73E100F1FA7B /* EasingCircular.swift */; }; + 8BA85059205F73E100F1FA7B /* EasingExpo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BA8503C205F73E100F1FA7B /* EasingExpo.swift */; }; + 8BA8505A205F73E100F1FA7B /* EasingQuartic.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BA8503D205F73E100F1FA7B /* EasingQuartic.swift */; }; + 8BA8505B205F73E100F1FA7B /* EasingBounce.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BA8503E205F73E100F1FA7B /* EasingBounce.swift */; }; + 8BA8505C205F73E100F1FA7B /* EasingQuintic.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BA8503F205F73E100F1FA7B /* EasingQuintic.swift */; }; + 8BA8505D205F73E100F1FA7B /* EasingBack.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BA85040205F73E100F1FA7B /* EasingBack.swift */; }; + 8BA8505E205F73E100F1FA7B /* PropertyData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BA85041205F73E100F1FA7B /* PropertyData.swift */; }; + 8BA8505F205F73E100F1FA7B /* Tempo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BA85042205F73E100F1FA7B /* Tempo.swift */; }; + 8BA85060205F73E100F1FA7B /* PhysicsSystem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BA85043205F73E100F1FA7B /* PhysicsSystem.swift */; }; + 8BA85061205F73E100F1FA7B /* MotionMachine.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BA85044205F73E100F1FA7B /* MotionMachine.swift */; }; + 8BA85062205F73E100F1FA7B /* MotionGroup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BA85045205F73E100F1FA7B /* MotionGroup.swift */; }; + 8BA85063205F73E100F1FA7B /* MotionSequence.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BA85046205F73E100F1FA7B /* MotionSequence.swift */; }; + 8BA85064205F73E100F1FA7B /* TimerTempo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BA85047205F73E100F1FA7B /* TimerTempo.swift */; }; + 8BA85065205F73E100F1FA7B /* UIColorAssistant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BA85049205F73E100F1FA7B /* UIColorAssistant.swift */; }; + 8BA85066205F73E100F1FA7B /* CGStructAssistant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BA8504A205F73E100F1FA7B /* CGStructAssistant.swift */; }; + 8BA85067205F73E100F1FA7B /* UIKitStructAssistant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BA8504B205F73E100F1FA7B /* UIKitStructAssistant.swift */; }; + 8BA85068205F73E100F1FA7B /* CIColorAssistant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BA8504C205F73E100F1FA7B /* CIColorAssistant.swift */; }; + 8BA85069205F73E100F1FA7B /* ValueAssistantGroup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BA8504D205F73E100F1FA7B /* ValueAssistantGroup.swift */; }; 8BB379D81CFFA17E00A35AFD /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BB379D71CFFA17E00A35AFD /* AppDelegate.swift */; }; 8BB379DA1CFFA17E00A35AFD /* MasterViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BB379D91CFFA17E00A35AFD /* MasterViewController.swift */; }; 8BB379E11CFFA17E00A35AFD /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 8BB379E01CFFA17E00A35AFD /* Assets.xcassets */; }; 8BB379E41CFFA17E00A35AFD /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 8BB379E21CFFA17E00A35AFD /* LaunchScreen.storyboard */; }; - 8BB37A0B1CFFAFBA00A35AFD /* MotionMachine.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BB379EE1CFFAFBA00A35AFD /* MotionMachine.swift */; }; - 8BB37A0C1CFFAFBA00A35AFD /* PhysicsMotion.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BB379EF1CFFAFBA00A35AFD /* PhysicsMotion.swift */; }; - 8BB37A0D1CFFAFBA00A35AFD /* Motion.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BB379F01CFFAFBA00A35AFD /* Motion.swift */; }; - 8BB37A0E1CFFAFBA00A35AFD /* MotionGroup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BB379F11CFFAFBA00A35AFD /* MotionGroup.swift */; }; - 8BB37A0F1CFFAFBA00A35AFD /* MotionSequence.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BB379F21CFFAFBA00A35AFD /* MotionSequence.swift */; }; - 8BB37A101CFFAFBA00A35AFD /* CGStructAssistant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BB379F41CFFAFBA00A35AFD /* CGStructAssistant.swift */; }; - 8BB37A111CFFAFBA00A35AFD /* CIColorAssistant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BB379F51CFFAFBA00A35AFD /* CIColorAssistant.swift */; }; - 8BB37A121CFFAFBA00A35AFD /* UIColorAssistant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BB379F61CFFAFBA00A35AFD /* UIColorAssistant.swift */; }; - 8BB37A131CFFAFBA00A35AFD /* UIKitStructAssistant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BB379F71CFFAFBA00A35AFD /* UIKitStructAssistant.swift */; }; - 8BB37A141CFFAFBA00A35AFD /* ValueAssistantGroup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BB379F81CFFAFBA00A35AFD /* ValueAssistantGroup.swift */; }; - 8BB37A151CFFAFBA00A35AFD /* MotionSupport.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BB379F91CFFAFBA00A35AFD /* MotionSupport.swift */; }; - 8BB37A161CFFAFBA00A35AFD /* PropertyData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BB379FA1CFFAFBA00A35AFD /* PropertyData.swift */; }; - 8BB37A171CFFAFBA00A35AFD /* PhysicsSystem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BB379FB1CFFAFBA00A35AFD /* PhysicsSystem.swift */; }; - 8BB37A181CFFAFBA00A35AFD /* EasingBack.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BB379FD1CFFAFBA00A35AFD /* EasingBack.swift */; }; - 8BB37A191CFFAFBA00A35AFD /* EasingBounce.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BB379FE1CFFAFBA00A35AFD /* EasingBounce.swift */; }; - 8BB37A1A1CFFAFBA00A35AFD /* EasingCircular.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BB379FF1CFFAFBA00A35AFD /* EasingCircular.swift */; }; - 8BB37A1B1CFFAFBA00A35AFD /* EasingCubic.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BB37A001CFFAFBA00A35AFD /* EasingCubic.swift */; }; - 8BB37A1C1CFFAFBA00A35AFD /* EasingElastic.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BB37A011CFFAFBA00A35AFD /* EasingElastic.swift */; }; - 8BB37A1D1CFFAFBA00A35AFD /* EasingExpo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BB37A021CFFAFBA00A35AFD /* EasingExpo.swift */; }; - 8BB37A1E1CFFAFBA00A35AFD /* EasingLinear.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BB37A031CFFAFBA00A35AFD /* EasingLinear.swift */; }; - 8BB37A1F1CFFAFBA00A35AFD /* EasingQuadratic.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BB37A041CFFAFBA00A35AFD /* EasingQuadratic.swift */; }; - 8BB37A201CFFAFBA00A35AFD /* EasingQuartic.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BB37A051CFFAFBA00A35AFD /* EasingQuartic.swift */; }; - 8BB37A211CFFAFBA00A35AFD /* EasingQuintic.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BB37A061CFFAFBA00A35AFD /* EasingQuintic.swift */; }; - 8BB37A221CFFAFBA00A35AFD /* EasingSine.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BB37A071CFFAFBA00A35AFD /* EasingSine.swift */; }; - 8BB37A231CFFAFBA00A35AFD /* TimerTempo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BB37A081CFFAFBA00A35AFD /* TimerTempo.swift */; }; - 8BB37A241CFFAFBA00A35AFD /* CATempo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BB37A091CFFAFBA00A35AFD /* CATempo.swift */; }; - 8BB37A251CFFAFBA00A35AFD /* Tempo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BB37A0A1CFFAFBA00A35AFD /* Tempo.swift */; }; 8BB37A281CFFB03F00A35AFD /* BasicMotionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BB37A271CFFB03F00A35AFD /* BasicMotionViewController.swift */; }; 8BB37A2C1CFFC64F00A35AFD /* ButtonsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BB37A2B1CFFC64F00A35AFD /* ButtonsView.swift */; }; /* End PBXBuildFile section */ @@ -55,39 +56,40 @@ 8B683B031D00BE76008D43E2 /* GroupMotionViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = GroupMotionViewController.swift; path = Classes/GroupMotionViewController.swift; sourceTree = ""; }; 8B683B051D00E386008D43E2 /* SequenceContiguousViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SequenceContiguousViewController.swift; path = Classes/SequenceContiguousViewController.swift; sourceTree = ""; }; 8B683B071D012529008D43E2 /* SequenceViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SequenceViewController.swift; path = Classes/SequenceViewController.swift; sourceTree = ""; }; + 8BA85030205F73E100F1FA7B /* Motion.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Motion.swift; sourceTree = ""; }; + 8BA85031205F73E100F1FA7B /* PhysicsMotion.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PhysicsMotion.swift; sourceTree = ""; }; + 8BA85032205F73E100F1FA7B /* CATempo.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CATempo.swift; sourceTree = ""; }; + 8BA85033205F73E100F1FA7B /* PropertyStates.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PropertyStates.swift; sourceTree = ""; }; + 8BA85034205F73E100F1FA7B /* MotionSupport.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MotionSupport.swift; sourceTree = ""; }; + 8BA85036205F73E100F1FA7B /* EasingElastic.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EasingElastic.swift; sourceTree = ""; }; + 8BA85037205F73E100F1FA7B /* EasingLinear.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EasingLinear.swift; sourceTree = ""; }; + 8BA85038205F73E100F1FA7B /* EasingSine.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EasingSine.swift; sourceTree = ""; }; + 8BA85039205F73E100F1FA7B /* EasingQuadratic.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EasingQuadratic.swift; sourceTree = ""; }; + 8BA8503A205F73E100F1FA7B /* EasingCubic.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EasingCubic.swift; sourceTree = ""; }; + 8BA8503B205F73E100F1FA7B /* EasingCircular.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EasingCircular.swift; sourceTree = ""; }; + 8BA8503C205F73E100F1FA7B /* EasingExpo.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EasingExpo.swift; sourceTree = ""; }; + 8BA8503D205F73E100F1FA7B /* EasingQuartic.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EasingQuartic.swift; sourceTree = ""; }; + 8BA8503E205F73E100F1FA7B /* EasingBounce.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EasingBounce.swift; sourceTree = ""; }; + 8BA8503F205F73E100F1FA7B /* EasingQuintic.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EasingQuintic.swift; sourceTree = ""; }; + 8BA85040205F73E100F1FA7B /* EasingBack.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EasingBack.swift; sourceTree = ""; }; + 8BA85041205F73E100F1FA7B /* PropertyData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PropertyData.swift; sourceTree = ""; }; + 8BA85042205F73E100F1FA7B /* Tempo.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Tempo.swift; sourceTree = ""; }; + 8BA85043205F73E100F1FA7B /* PhysicsSystem.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PhysicsSystem.swift; sourceTree = ""; }; + 8BA85044205F73E100F1FA7B /* MotionMachine.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MotionMachine.swift; sourceTree = ""; }; + 8BA85045205F73E100F1FA7B /* MotionGroup.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MotionGroup.swift; sourceTree = ""; }; + 8BA85046205F73E100F1FA7B /* MotionSequence.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MotionSequence.swift; sourceTree = ""; }; + 8BA85047205F73E100F1FA7B /* TimerTempo.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TimerTempo.swift; sourceTree = ""; }; + 8BA85049205F73E100F1FA7B /* UIColorAssistant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIColorAssistant.swift; sourceTree = ""; }; + 8BA8504A205F73E100F1FA7B /* CGStructAssistant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CGStructAssistant.swift; sourceTree = ""; }; + 8BA8504B205F73E100F1FA7B /* UIKitStructAssistant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIKitStructAssistant.swift; sourceTree = ""; }; + 8BA8504C205F73E100F1FA7B /* CIColorAssistant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CIColorAssistant.swift; sourceTree = ""; }; + 8BA8504D205F73E100F1FA7B /* ValueAssistantGroup.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ValueAssistantGroup.swift; sourceTree = ""; }; 8BB379D41CFFA17D00A35AFD /* MotionExamples.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MotionExamples.app; sourceTree = BUILT_PRODUCTS_DIR; }; 8BB379D71CFFA17E00A35AFD /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 8BB379D91CFFA17E00A35AFD /* MasterViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MasterViewController.swift; sourceTree = ""; }; 8BB379E01CFFA17E00A35AFD /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 8BB379E31CFFA17E00A35AFD /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 8BB379E51CFFA17E00A35AFD /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 8BB379EE1CFFAFBA00A35AFD /* MotionMachine.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = MotionMachine.swift; path = ../Classes/MotionMachine.swift; sourceTree = ""; }; - 8BB379EF1CFFAFBA00A35AFD /* PhysicsMotion.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = PhysicsMotion.swift; path = ../Classes/PhysicsMotion.swift; sourceTree = ""; }; - 8BB379F01CFFAFBA00A35AFD /* Motion.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Motion.swift; path = ../Classes/Motion.swift; sourceTree = ""; }; - 8BB379F11CFFAFBA00A35AFD /* MotionGroup.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = MotionGroup.swift; path = ../Classes/MotionGroup.swift; sourceTree = ""; }; - 8BB379F21CFFAFBA00A35AFD /* MotionSequence.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = MotionSequence.swift; path = ../Classes/MotionSequence.swift; sourceTree = ""; }; - 8BB379F41CFFAFBA00A35AFD /* CGStructAssistant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CGStructAssistant.swift; sourceTree = ""; }; - 8BB379F51CFFAFBA00A35AFD /* CIColorAssistant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CIColorAssistant.swift; sourceTree = ""; }; - 8BB379F61CFFAFBA00A35AFD /* UIColorAssistant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIColorAssistant.swift; sourceTree = ""; }; - 8BB379F71CFFAFBA00A35AFD /* UIKitStructAssistant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIKitStructAssistant.swift; sourceTree = ""; }; - 8BB379F81CFFAFBA00A35AFD /* ValueAssistantGroup.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ValueAssistantGroup.swift; sourceTree = ""; }; - 8BB379F91CFFAFBA00A35AFD /* MotionSupport.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = MotionSupport.swift; path = ../Classes/MotionSupport.swift; sourceTree = ""; }; - 8BB379FA1CFFAFBA00A35AFD /* PropertyData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = PropertyData.swift; path = ../Classes/PropertyData.swift; sourceTree = ""; }; - 8BB379FB1CFFAFBA00A35AFD /* PhysicsSystem.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = PhysicsSystem.swift; path = ../Classes/PhysicsSystem.swift; sourceTree = ""; }; - 8BB379FD1CFFAFBA00A35AFD /* EasingBack.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EasingBack.swift; sourceTree = ""; }; - 8BB379FE1CFFAFBA00A35AFD /* EasingBounce.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EasingBounce.swift; sourceTree = ""; }; - 8BB379FF1CFFAFBA00A35AFD /* EasingCircular.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EasingCircular.swift; sourceTree = ""; }; - 8BB37A001CFFAFBA00A35AFD /* EasingCubic.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EasingCubic.swift; sourceTree = ""; }; - 8BB37A011CFFAFBA00A35AFD /* EasingElastic.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EasingElastic.swift; sourceTree = ""; }; - 8BB37A021CFFAFBA00A35AFD /* EasingExpo.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EasingExpo.swift; sourceTree = ""; }; - 8BB37A031CFFAFBA00A35AFD /* EasingLinear.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EasingLinear.swift; sourceTree = ""; }; - 8BB37A041CFFAFBA00A35AFD /* EasingQuadratic.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EasingQuadratic.swift; sourceTree = ""; }; - 8BB37A051CFFAFBA00A35AFD /* EasingQuartic.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EasingQuartic.swift; sourceTree = ""; }; - 8BB37A061CFFAFBA00A35AFD /* EasingQuintic.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EasingQuintic.swift; sourceTree = ""; }; - 8BB37A071CFFAFBA00A35AFD /* EasingSine.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EasingSine.swift; sourceTree = ""; }; - 8BB37A081CFFAFBA00A35AFD /* TimerTempo.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = TimerTempo.swift; path = ../Classes/TimerTempo.swift; sourceTree = ""; }; - 8BB37A091CFFAFBA00A35AFD /* CATempo.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = CATempo.swift; path = ../Classes/CATempo.swift; sourceTree = ""; }; - 8BB37A0A1CFFAFBA00A35AFD /* Tempo.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Tempo.swift; path = ../Classes/Tempo.swift; sourceTree = ""; }; 8BB37A271CFFB03F00A35AFD /* BasicMotionViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = BasicMotionViewController.swift; path = Classes/BasicMotionViewController.swift; sourceTree = ""; }; 8BB37A2B1CFFC64F00A35AFD /* ButtonsView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ButtonsView.swift; sourceTree = ""; }; /* End PBXFileReference section */ @@ -103,87 +105,87 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ - 8BB379CB1CFFA17D00A35AFD = { + 8BA8502F205F73E100F1FA7B /* Classes */ = { isa = PBXGroup; children = ( - 8BB379ED1CFFAF9C00A35AFD /* MotionMachine */, - 8BB379D61CFFA17E00A35AFD /* MotionExamples */, - 8BB379D51CFFA17D00A35AFD /* Products */, + 8BA85030205F73E100F1FA7B /* Motion.swift */, + 8BA85031205F73E100F1FA7B /* PhysicsMotion.swift */, + 8BA85032205F73E100F1FA7B /* CATempo.swift */, + 8BA85033205F73E100F1FA7B /* PropertyStates.swift */, + 8BA85034205F73E100F1FA7B /* MotionSupport.swift */, + 8BA85035205F73E100F1FA7B /* EasingTypes */, + 8BA85041205F73E100F1FA7B /* PropertyData.swift */, + 8BA85042205F73E100F1FA7B /* Tempo.swift */, + 8BA85043205F73E100F1FA7B /* PhysicsSystem.swift */, + 8BA85044205F73E100F1FA7B /* MotionMachine.swift */, + 8BA85045205F73E100F1FA7B /* MotionGroup.swift */, + 8BA85046205F73E100F1FA7B /* MotionSequence.swift */, + 8BA85047205F73E100F1FA7B /* TimerTempo.swift */, + 8BA85048205F73E100F1FA7B /* ValueAssistants */, ); + name = Classes; + path = ../Classes; sourceTree = ""; }; - 8BB379D51CFFA17D00A35AFD /* Products */ = { + 8BA85035205F73E100F1FA7B /* EasingTypes */ = { isa = PBXGroup; children = ( - 8BB379D41CFFA17D00A35AFD /* MotionExamples.app */, + 8BA85036205F73E100F1FA7B /* EasingElastic.swift */, + 8BA85037205F73E100F1FA7B /* EasingLinear.swift */, + 8BA85038205F73E100F1FA7B /* EasingSine.swift */, + 8BA85039205F73E100F1FA7B /* EasingQuadratic.swift */, + 8BA8503A205F73E100F1FA7B /* EasingCubic.swift */, + 8BA8503B205F73E100F1FA7B /* EasingCircular.swift */, + 8BA8503C205F73E100F1FA7B /* EasingExpo.swift */, + 8BA8503D205F73E100F1FA7B /* EasingQuartic.swift */, + 8BA8503E205F73E100F1FA7B /* EasingBounce.swift */, + 8BA8503F205F73E100F1FA7B /* EasingQuintic.swift */, + 8BA85040205F73E100F1FA7B /* EasingBack.swift */, ); - name = Products; + path = EasingTypes; sourceTree = ""; }; - 8BB379D61CFFA17E00A35AFD /* MotionExamples */ = { + 8BA85048205F73E100F1FA7B /* ValueAssistants */ = { isa = PBXGroup; children = ( - 8BB37A261CFFAFEE00A35AFD /* Example VCs */, - 8BB379D71CFFA17E00A35AFD /* AppDelegate.swift */, - 8BB379D91CFFA17E00A35AFD /* MasterViewController.swift */, - 8BB379E01CFFA17E00A35AFD /* Assets.xcassets */, - 8BB379E21CFFA17E00A35AFD /* LaunchScreen.storyboard */, - 8BB379E51CFFA17E00A35AFD /* Info.plist */, - 8BB37A2B1CFFC64F00A35AFD /* ButtonsView.swift */, + 8BA85049205F73E100F1FA7B /* UIColorAssistant.swift */, + 8BA8504A205F73E100F1FA7B /* CGStructAssistant.swift */, + 8BA8504B205F73E100F1FA7B /* UIKitStructAssistant.swift */, + 8BA8504C205F73E100F1FA7B /* CIColorAssistant.swift */, + 8BA8504D205F73E100F1FA7B /* ValueAssistantGroup.swift */, ); - path = MotionExamples; + path = ValueAssistants; sourceTree = ""; }; - 8BB379ED1CFFAF9C00A35AFD /* MotionMachine */ = { + 8BB379CB1CFFA17D00A35AFD = { isa = PBXGroup; children = ( - 8BB379EE1CFFAFBA00A35AFD /* MotionMachine.swift */, - 8BB379EF1CFFAFBA00A35AFD /* PhysicsMotion.swift */, - 8BB379F01CFFAFBA00A35AFD /* Motion.swift */, - 8BB379F11CFFAFBA00A35AFD /* MotionGroup.swift */, - 8BB379F21CFFAFBA00A35AFD /* MotionSequence.swift */, - 8BB379F31CFFAFBA00A35AFD /* ValueAssistants */, - 8BB379F91CFFAFBA00A35AFD /* MotionSupport.swift */, - 8BB379FA1CFFAFBA00A35AFD /* PropertyData.swift */, - 8BB379FB1CFFAFBA00A35AFD /* PhysicsSystem.swift */, - 8BB379FC1CFFAFBA00A35AFD /* EasingTypes */, - 8BB37A081CFFAFBA00A35AFD /* TimerTempo.swift */, - 8BB37A091CFFAFBA00A35AFD /* CATempo.swift */, - 8BB37A0A1CFFAFBA00A35AFD /* Tempo.swift */, + 8BA8502F205F73E100F1FA7B /* Classes */, + 8BB379D61CFFA17E00A35AFD /* MotionExamples */, + 8BB379D51CFFA17D00A35AFD /* Products */, ); - name = MotionMachine; sourceTree = ""; }; - 8BB379F31CFFAFBA00A35AFD /* ValueAssistants */ = { + 8BB379D51CFFA17D00A35AFD /* Products */ = { isa = PBXGroup; children = ( - 8BB379F41CFFAFBA00A35AFD /* CGStructAssistant.swift */, - 8BB379F51CFFAFBA00A35AFD /* CIColorAssistant.swift */, - 8BB379F61CFFAFBA00A35AFD /* UIColorAssistant.swift */, - 8BB379F71CFFAFBA00A35AFD /* UIKitStructAssistant.swift */, - 8BB379F81CFFAFBA00A35AFD /* ValueAssistantGroup.swift */, + 8BB379D41CFFA17D00A35AFD /* MotionExamples.app */, ); - name = ValueAssistants; - path = ../Classes/ValueAssistants; + name = Products; sourceTree = ""; }; - 8BB379FC1CFFAFBA00A35AFD /* EasingTypes */ = { + 8BB379D61CFFA17E00A35AFD /* MotionExamples */ = { isa = PBXGroup; children = ( - 8BB379FD1CFFAFBA00A35AFD /* EasingBack.swift */, - 8BB379FE1CFFAFBA00A35AFD /* EasingBounce.swift */, - 8BB379FF1CFFAFBA00A35AFD /* EasingCircular.swift */, - 8BB37A001CFFAFBA00A35AFD /* EasingCubic.swift */, - 8BB37A011CFFAFBA00A35AFD /* EasingElastic.swift */, - 8BB37A021CFFAFBA00A35AFD /* EasingExpo.swift */, - 8BB37A031CFFAFBA00A35AFD /* EasingLinear.swift */, - 8BB37A041CFFAFBA00A35AFD /* EasingQuadratic.swift */, - 8BB37A051CFFAFBA00A35AFD /* EasingQuartic.swift */, - 8BB37A061CFFAFBA00A35AFD /* EasingQuintic.swift */, - 8BB37A071CFFAFBA00A35AFD /* EasingSine.swift */, + 8BB37A261CFFAFEE00A35AFD /* Example VCs */, + 8BB379D71CFFA17E00A35AFD /* AppDelegate.swift */, + 8BB379D91CFFA17E00A35AFD /* MasterViewController.swift */, + 8BB379E01CFFA17E00A35AFD /* Assets.xcassets */, + 8BB379E21CFFA17E00A35AFD /* LaunchScreen.storyboard */, + 8BB379E51CFFA17E00A35AFD /* Info.plist */, + 8BB37A2B1CFFC64F00A35AFD /* ButtonsView.swift */, ); - name = EasingTypes; - path = ../Classes/EasingTypes; + path = MotionExamples; sourceTree = ""; }; 8BB37A261CFFAFEE00A35AFD /* Example VCs */ = { @@ -272,43 +274,44 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 8BA85065205F73E100F1FA7B /* UIColorAssistant.swift in Sources */, 8B43DC421D0159BA00A58D80 /* AdditiveViewController.swift in Sources */, - 8BB37A181CFFAFBA00A35AFD /* EasingBack.swift in Sources */, - 8BB37A151CFFAFBA00A35AFD /* MotionSupport.swift in Sources */, + 8BA85058205F73E100F1FA7B /* EasingCircular.swift in Sources */, + 8BA85052205F73E100F1FA7B /* MotionSupport.swift in Sources */, + 8BA85062205F73E100F1FA7B /* MotionGroup.swift in Sources */, 8B43DC401D0150B100A58D80 /* PhysicsMotionViewController.swift in Sources */, + 8BA85064205F73E100F1FA7B /* TimerTempo.swift in Sources */, + 8BA85060205F73E100F1FA7B /* PhysicsSystem.swift in Sources */, + 8BA85069205F73E100F1FA7B /* ValueAssistantGroup.swift in Sources */, + 8BA85055205F73E100F1FA7B /* EasingSine.swift in Sources */, 8B43DC441D01764900A58D80 /* DynamicViewController.swift in Sources */, - 8BB37A111CFFAFBA00A35AFD /* CIColorAssistant.swift in Sources */, - 8BB37A101CFFAFBA00A35AFD /* CGStructAssistant.swift in Sources */, + 8BA85054205F73E100F1FA7B /* EasingLinear.swift in Sources */, + 8BA85068205F73E100F1FA7B /* CIColorAssistant.swift in Sources */, + 8BA8504F205F73E100F1FA7B /* PhysicsMotion.swift in Sources */, + 8BA85051205F73E100F1FA7B /* PropertyStates.swift in Sources */, + 8BA85050205F73E100F1FA7B /* CATempo.swift in Sources */, + 8BA85057205F73E100F1FA7B /* EasingCubic.swift in Sources */, 8BB37A2C1CFFC64F00A35AFD /* ButtonsView.swift in Sources */, + 8BA8504E205F73E100F1FA7B /* Motion.swift in Sources */, 8BB379DA1CFFA17E00A35AFD /* MasterViewController.swift in Sources */, + 8BA8505E205F73E100F1FA7B /* PropertyData.swift in Sources */, + 8BA85053205F73E100F1FA7B /* EasingElastic.swift in Sources */, + 8BA8505D205F73E100F1FA7B /* EasingBack.swift in Sources */, + 8BA8505A205F73E100F1FA7B /* EasingQuartic.swift in Sources */, + 8BA8505B205F73E100F1FA7B /* EasingBounce.swift in Sources */, 8BB37A281CFFB03F00A35AFD /* BasicMotionViewController.swift in Sources */, 8B683B081D012529008D43E2 /* SequenceViewController.swift in Sources */, - 8BB37A251CFFAFBA00A35AFD /* Tempo.swift in Sources */, - 8BB37A131CFFAFBA00A35AFD /* UIKitStructAssistant.swift in Sources */, - 8BB37A1D1CFFAFBA00A35AFD /* EasingExpo.swift in Sources */, - 8BB37A221CFFAFBA00A35AFD /* EasingSine.swift in Sources */, + 8BA85056205F73E100F1FA7B /* EasingQuadratic.swift in Sources */, + 8BA85066205F73E100F1FA7B /* CGStructAssistant.swift in Sources */, + 8BA85061205F73E100F1FA7B /* MotionMachine.swift in Sources */, + 8BA85059205F73E100F1FA7B /* EasingExpo.swift in Sources */, 8B683B061D00E386008D43E2 /* SequenceContiguousViewController.swift in Sources */, - 8BB37A1C1CFFAFBA00A35AFD /* EasingElastic.swift in Sources */, - 8BB37A141CFFAFBA00A35AFD /* ValueAssistantGroup.swift in Sources */, - 8BB37A1B1CFFAFBA00A35AFD /* EasingCubic.swift in Sources */, - 8BB37A231CFFAFBA00A35AFD /* TimerTempo.swift in Sources */, - 8BB37A0C1CFFAFBA00A35AFD /* PhysicsMotion.swift in Sources */, - 8BB37A241CFFAFBA00A35AFD /* CATempo.swift in Sources */, - 8BB37A0B1CFFAFBA00A35AFD /* MotionMachine.swift in Sources */, - 8BB37A191CFFAFBA00A35AFD /* EasingBounce.swift in Sources */, - 8BB37A1E1CFFAFBA00A35AFD /* EasingLinear.swift in Sources */, - 8BB37A201CFFAFBA00A35AFD /* EasingQuartic.swift in Sources */, - 8BB37A0D1CFFAFBA00A35AFD /* Motion.swift in Sources */, - 8BB37A121CFFAFBA00A35AFD /* UIColorAssistant.swift in Sources */, - 8BB37A161CFFAFBA00A35AFD /* PropertyData.swift in Sources */, - 8BB37A1A1CFFAFBA00A35AFD /* EasingCircular.swift in Sources */, - 8BB37A211CFFAFBA00A35AFD /* EasingQuintic.swift in Sources */, 8BB379D81CFFA17E00A35AFD /* AppDelegate.swift in Sources */, - 8BB37A0E1CFFAFBA00A35AFD /* MotionGroup.swift in Sources */, + 8BA8505C205F73E100F1FA7B /* EasingQuintic.swift in Sources */, 8B683B041D00BE76008D43E2 /* GroupMotionViewController.swift in Sources */, - 8BB37A0F1CFFAFBA00A35AFD /* MotionSequence.swift in Sources */, - 8BB37A1F1CFFAFBA00A35AFD /* EasingQuadratic.swift in Sources */, - 8BB37A171CFFAFBA00A35AFD /* PhysicsSystem.swift in Sources */, + 8BA85063205F73E100F1FA7B /* MotionSequence.swift in Sources */, + 8BA85067205F73E100F1FA7B /* UIKitStructAssistant.swift in Sources */, + 8BA8505F205F73E100F1FA7B /* Tempo.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -377,7 +380,7 @@ ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_SWIFT3_OBJC_INFERENCE = Off; + SWIFT_SWIFT3_OBJC_INFERENCE = Default; SWIFT_VERSION = 4.0; }; name = Debug; @@ -425,7 +428,7 @@ MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; - SWIFT_SWIFT3_OBJC_INFERENCE = Off; + SWIFT_SWIFT3_OBJC_INFERENCE = Default; SWIFT_VERSION = 4.0; VALIDATE_PRODUCT = YES; }; @@ -439,7 +442,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.poetmountain.MotionExamples; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_SWIFT3_OBJC_INFERENCE = Off; + SWIFT_SWIFT3_OBJC_INFERENCE = Default; SWIFT_VERSION = 4.0; }; name = Debug; @@ -452,7 +455,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.poetmountain.MotionExamples; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_SWIFT3_OBJC_INFERENCE = Off; + SWIFT_SWIFT3_OBJC_INFERENCE = Default; SWIFT_VERSION = 4.0; }; name = Release; diff --git a/Examples/MotionExamples/Assets.xcassets/Contents.json b/Examples/MotionExamples/Assets.xcassets/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/Examples/MotionExamples/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Examples/MotionExamples/Classes/SequenceContiguousViewController.swift b/Examples/MotionExamples/Classes/SequenceContiguousViewController.swift index bef6923..a96e8d0 100644 --- a/Examples/MotionExamples/Classes/SequenceContiguousViewController.swift +++ b/Examples/MotionExamples/Classes/SequenceContiguousViewController.swift @@ -51,7 +51,7 @@ public class SequenceContiguousViewController: UIViewController, ButtonsViewDele easing: EasingQuartic.easeInOut()) let change_color = Motion(target: square, - finalState: ["backgroundColor" : UIColor.init(red: 91.0/255.0, green:189.0/255.0, blue:231.0/255.0, alpha:1.0)], + statesForProperties: [PropertyStates(path: "backgroundColor", end: UIColor.init(red: 91.0/255.0, green:189.0/255.0, blue:231.0/255.0, alpha:1.0))], duration: 0.9, easing: EasingQuadratic.easeInOut()) diff --git a/Examples/MotionExamples/Classes/SequenceViewController.swift b/Examples/MotionExamples/Classes/SequenceViewController.swift index 6fb42f8..08ddd10 100644 --- a/Examples/MotionExamples/Classes/SequenceViewController.swift +++ b/Examples/MotionExamples/Classes/SequenceViewController.swift @@ -55,7 +55,7 @@ public class SequenceViewController: UIViewController, ButtonsViewDelegate { easing: EasingQuartic.easeInOut()) let color = Motion(target: squares[x], - finalState: ["backgroundColor" : UIColor.init(red: 91.0/255.0, green:189.0/255.0, blue:231.0/255.0, alpha:1.0)], + statesForProperties: [PropertyStates(path: "backgroundColor", end: UIColor.init(red: 91.0/255.0, green:189.0/255.0, blue:231.0/255.0, alpha:1.0))], duration: 0.7, easing: EasingQuadratic.easeInOut()) diff --git a/Guides/MoveableClasses.md b/Guides/MoveableClasses.md index 42d21d4..053e479 100644 --- a/Guides/MoveableClasses.md +++ b/Guides/MoveableClasses.md @@ -9,7 +9,7 @@ These value updates are made as the motion moves through time. This movement is ## Motion -`Motion` uses a keypath (i.e. "frame.origin.x") to target specific properties of an object and transform their values over a period of time via an easing equation. The keypath is relative to the parent object passed in, and normally you'd want to pass in the parent object of the object you actually want to modify (i.e. passing in a UIView object if you wish to modify its frame). This is necessary for MotionMachine to be able to modify the original object. However, you may pass in a target object directly for MotionMachine to modify, but that object will only be modified internally. In such cases you may access the object through the Motion's `PropertyData` objects, which are accessible from the `properties` property. +`Motion` uses a keyPath (i.e. "frame.origin.x") to target specific properties of an object and transform their values over a period of time via an easing equation. The keyPath is relative to the parent object passed in, and normally you'd want to pass in the parent object of the object you actually want to modify (i.e. passing in a UIView object if you wish to modify its frame). This is necessary for MotionMachine to be able to modify the original object. However, you may pass in a target object directly for MotionMachine to modify, but that object will only be modified internally. In such cases you may access the object through the Motion's `PropertyData` objects, which are accessible from the `properties` property. Here's a basic example using this workhorse of MotionMachine. We've supplied the `Motion` with a single `PropertyData` object which defines a property keyPath and an ending value, along with a duration of 1 second and a Quadratic easing equation. This easing parameter defines the easing equation assigned to the `easing` property. If your `Motion` is `reversing`, you can also specify a separate easing equation for the reverse movement via the `reverseEasing` property. If that property is undefined, the `Motion` will use the `easing` property for both motion directions. @@ -22,12 +22,14 @@ let motion = Motion(target: view, ).start() ``` -Here we add multiple `PropertyData` objects to control multiple properties. Notice that we're setting the UIView's `backgroundColor` and the end of the keypath is `blue`. But UIColor doesn't have an accessible `blue` property, you say? True, but `Motion` has a `UIColorAssistant` which understands this syntactic shorthand and knows to update the `blue` component of the UIColor. You can use this path structure for any of UIColor's value components. +This is a really convenient way to animate complex objects. Here we add `PropertyStates` objects to easily animate multiple properties by passing in representations of their start and end states for each animation. MotionMachine will take care of the rest. In the case of the frame being animated, the `Motion` initializer will setup animations for the x, width, and height properties because those values change between the two state presentations we've passed in with the `PropertyStates` object. -Also notice that we only have one Double value in each `PropertyData` object's constructor. If you don't provide a start parameter, `Motion` will use the target object's current value of the property specified in the keypath as a starting value. And if you don't use parameter labels, the `Motion` will assume the value after the path is the ending value. +Notice that we're setting the UIView's `backgroundColor` and the end of the keypath is `blue`. But UIColor doesn't have an accessible `blue` property, you say? True, but `Motion` has a `UIColorAssistant` which understands this syntactic shorthand and knows to update the `blue` component of the UIColor. You can use this path structure for any of UIColor's value components. MotionMachine comes with many value assistants by default which provide similar shortcuts to Foundation objects, and you can extend this functionality with your own assistants. + +Also notice that we only have an ending value for the UIView's `PropertyStates` object for its backgroundColor. If you don't provide a start parameter for a `PropertyStaes` or a `PropertyData` object, `Motion` will use the target object's current value of the property specified in the keyPath as a starting value. ```swift let motion = Motion(target: view, - properties: [PropertyData("frame.origin.x", 200.0), PropertyData("backgroundColor.blue", 0.5)], + statesForProperties: [PropertyStates(path: "frame", start: CGRect(x: 20.0, y: 50.0, width: 50.0, height: 50.0), end: CGRect(x: 50.0, y: 50.0, width: 200.0, height: 200.0)), PropertyStates(path: "backgroundColor.blue", end: 0.5)], duration: 1.0, easing: EasingQuadratic.easeInOut() ).start() @@ -86,7 +88,7 @@ MotionMachine includes all the standard Robert Penner easing equations, which ar ## PhysicsMotion -`PhysicsMotion` uses a keypath (i.e. "frame.origin.x") to target specific properties of an object and transform their values, using a physics system to update values with decaying velocity. The physics system conforms to the `PhysicsSolving` protocol, and though `PhysicsMotion` uses the (very basic) `PhysicsSystem` class by default you can replace it with your own custom `PhysicsSolving` system. +`PhysicsMotion` uses a keyPath (i.e. "frame.origin.x") to target specific properties of an object and transform their values, using a physics system to update values with decaying velocity. The physics system conforms to the `PhysicsSolving` protocol, and though `PhysicsMotion` uses the (very basic) `PhysicsSystem` class by default you can replace it with your own custom `PhysicsSolving` system. Here's a simple example. We pass in an initial `velocity`, along with a `friction` value which reduces the velocity over time. The `friction` value should be within a range of 0.0 to 1.0, but there is no limitation on the `velocity` value due to the differing magnitudes of property values you may want to alter. Note that the only necessary `PropertyData` parameter is `path:`; we can't guarantee a certain ending value, so the physics system will determine the value's resting place. (You can still specify a `start:` value though!) Likewise, there is also no duration property because the total movement time is determined by the `velocity` and `friction` interaction. ```swift diff --git a/MotionMachine.podspec b/MotionMachine.podspec index 5425e67..daf1382 100644 --- a/MotionMachine.podspec +++ b/MotionMachine.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'MotionMachine' - s.version = '1.2.0' + s.version = '1.3.0' s.license = { :type => 'MIT' } s.summary = 'An elegant, powerful, and modular animation library for Swift.' s.description = <<-DESC diff --git a/README.md b/README.md index 50d1b4f..31f667f 100644 --- a/README.md +++ b/README.md @@ -117,7 +117,7 @@ MotionMachine currently requires: #### Caveats -* MotionMachine uses Key-Value Coding (KVC) to introspect objects and retrieve and set their property values using keypaths. Because Swift currently offers no native ability in this regard, objects whose properties should be modified by MotionMachine must inherit from `NSObject`. If and when more dynamism is added to Swift (and the author of this library hopes that is the case), MotionMachine will hopefully be able to do away with this restriction. +* MotionMachine uses Key-Value Coding (KVC) to introspect objects and retrieve and set their property values using keypaths. Because Swift currently offers no native ability in this regard, objects whose properties should be modified by MotionMachine must inherit from `NSObject`. If and when more dynamism is added to Swift (and the author of this library hopes that is the case), MotionMachine will hopefully be able to do away with this restriction. Note that as of Swift 4.0, any properties of a custom class you wish to manipulate must be prefixed with `@objc`, or add `@objcMembers` above the class if all properties should be exposed. * Because native Swift structs cannot inherit from `NSObject`, Swift structs unfortunately cannot be used with MotionMachine at this time. diff --git a/Tests/MotionMachineTests.xcodeproj/project.pbxproj b/Tests/MotionMachineTests.xcodeproj/project.pbxproj index a73faba..fa5ea47 100644 --- a/Tests/MotionMachineTests.xcodeproj/project.pbxproj +++ b/Tests/MotionMachineTests.xcodeproj/project.pbxproj @@ -8,48 +8,49 @@ /* Begin PBXBuildFile section */ 8B62C0761CEFA2F00087727A /* MotionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B62C0751CEFA2F00087727A /* MotionTests.swift */; }; - 8B62C0931CEFA34C0087727A /* MotionSequence.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B62C0781CEFA34C0087727A /* MotionSequence.swift */; }; - 8B62C0941CEFA34C0087727A /* MotionGroup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B62C0791CEFA34C0087727A /* MotionGroup.swift */; }; - 8B62C0951CEFA34C0087727A /* Motion.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B62C07A1CEFA34C0087727A /* Motion.swift */; }; - 8B62C0981CEFA34C0087727A /* ValueAssistantGroup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B62C07E1CEFA34C0087727A /* ValueAssistantGroup.swift */; }; - 8B62C0991CEFA34C0087727A /* PhysicsMotion.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B62C07F1CEFA34C0087727A /* PhysicsMotion.swift */; }; - 8B62C09A1CEFA34C0087727A /* MotionSupport.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B62C0801CEFA34C0087727A /* MotionSupport.swift */; }; - 8B62C09B1CEFA34C0087727A /* PhysicsSystem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B62C0811CEFA34C0087727A /* PhysicsSystem.swift */; }; - 8B62C09C1CEFA34C0087727A /* CATempo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B62C0821CEFA34C0087727A /* CATempo.swift */; }; - 8B62C09E1CEFA34C0087727A /* MotionMachine.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B62C0841CEFA34C0087727A /* MotionMachine.swift */; }; - 8B62C09F1CEFA34C0087727A /* EasingBack.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B62C0861CEFA34C0087727A /* EasingBack.swift */; }; - 8B62C0A01CEFA34C0087727A /* EasingBounce.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B62C0871CEFA34C0087727A /* EasingBounce.swift */; }; - 8B62C0A11CEFA34C0087727A /* EasingCircular.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B62C0881CEFA34C0087727A /* EasingCircular.swift */; }; - 8B62C0A21CEFA34C0087727A /* EasingCubic.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B62C0891CEFA34C0087727A /* EasingCubic.swift */; }; - 8B62C0A31CEFA34C0087727A /* EasingElastic.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B62C08A1CEFA34C0087727A /* EasingElastic.swift */; }; - 8B62C0A41CEFA34C0087727A /* EasingExpo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B62C08B1CEFA34C0087727A /* EasingExpo.swift */; }; - 8B62C0A51CEFA34C0087727A /* EasingLinear.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B62C08C1CEFA34C0087727A /* EasingLinear.swift */; }; - 8B62C0A61CEFA34C0087727A /* EasingQuadratic.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B62C08D1CEFA34C0087727A /* EasingQuadratic.swift */; }; - 8B62C0A71CEFA34C0087727A /* EasingQuartic.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B62C08E1CEFA34C0087727A /* EasingQuartic.swift */; }; - 8B62C0A81CEFA34C0087727A /* EasingQuintic.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B62C08F1CEFA34C0087727A /* EasingQuintic.swift */; }; - 8B62C0A91CEFA34C0087727A /* EasingSine.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B62C0901CEFA34C0087727A /* EasingSine.swift */; }; - 8B62C0AA1CEFA34C0087727A /* Tempo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B62C0911CEFA34C0087727A /* Tempo.swift */; }; 8B62C0BC1CF014210087727A /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B62C0BB1CF014210087727A /* AppDelegate.swift */; }; 8B62C0BE1CF014210087727A /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B62C0BD1CF014210087727A /* ViewController.swift */; }; 8B62C0C11CF014210087727A /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 8B62C0BF1CF014210087727A /* Main.storyboard */; }; 8B62C0C31CF014210087727A /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 8B62C0C21CF014210087727A /* Assets.xcassets */; }; 8B62C0C61CF014210087727A /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 8B62C0C41CF014210087727A /* LaunchScreen.storyboard */; }; - 8B62C0CE1CF017640087727A /* TimerTempo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B62C0CD1CF017640087727A /* TimerTempo.swift */; }; 8B6B031B1CF3CC6300C1E216 /* PhysicsMotionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B6B031A1CF3CC6300C1E216 /* PhysicsMotionTests.swift */; }; 8B6B031D1CF3F57500C1E216 /* CGStructAssistantTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B6B031C1CF3F57500C1E216 /* CGStructAssistantTests.swift */; }; + 8BA85013205F206C00F1FA7B /* Motion.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BA84FF5205F206C00F1FA7B /* Motion.swift */; }; + 8BA85014205F206C00F1FA7B /* PhysicsMotion.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BA84FF6205F206C00F1FA7B /* PhysicsMotion.swift */; }; + 8BA85015205F206C00F1FA7B /* CATempo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BA84FF7205F206C00F1FA7B /* CATempo.swift */; }; + 8BA85016205F206C00F1FA7B /* PropertyStates.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BA84FF8205F206C00F1FA7B /* PropertyStates.swift */; }; + 8BA85017205F206C00F1FA7B /* MotionSupport.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BA84FF9205F206C00F1FA7B /* MotionSupport.swift */; }; + 8BA85018205F206C00F1FA7B /* EasingElastic.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BA84FFB205F206C00F1FA7B /* EasingElastic.swift */; }; + 8BA85019205F206C00F1FA7B /* EasingLinear.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BA84FFC205F206C00F1FA7B /* EasingLinear.swift */; }; + 8BA8501A205F206C00F1FA7B /* EasingSine.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BA84FFD205F206C00F1FA7B /* EasingSine.swift */; }; + 8BA8501B205F206C00F1FA7B /* EasingQuadratic.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BA84FFE205F206C00F1FA7B /* EasingQuadratic.swift */; }; + 8BA8501C205F206C00F1FA7B /* EasingCubic.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BA84FFF205F206C00F1FA7B /* EasingCubic.swift */; }; + 8BA8501D205F206C00F1FA7B /* EasingCircular.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BA85000205F206C00F1FA7B /* EasingCircular.swift */; }; + 8BA8501E205F206C00F1FA7B /* EasingExpo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BA85001205F206C00F1FA7B /* EasingExpo.swift */; }; + 8BA8501F205F206C00F1FA7B /* EasingQuartic.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BA85002205F206C00F1FA7B /* EasingQuartic.swift */; }; + 8BA85020205F206C00F1FA7B /* EasingBounce.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BA85003205F206C00F1FA7B /* EasingBounce.swift */; }; + 8BA85021205F206C00F1FA7B /* EasingQuintic.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BA85004205F206C00F1FA7B /* EasingQuintic.swift */; }; + 8BA85022205F206C00F1FA7B /* EasingBack.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BA85005205F206C00F1FA7B /* EasingBack.swift */; }; + 8BA85023205F206C00F1FA7B /* PropertyData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BA85006205F206C00F1FA7B /* PropertyData.swift */; }; + 8BA85024205F206C00F1FA7B /* Tempo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BA85007205F206C00F1FA7B /* Tempo.swift */; }; + 8BA85025205F206C00F1FA7B /* PhysicsSystem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BA85008205F206C00F1FA7B /* PhysicsSystem.swift */; }; + 8BA85026205F206C00F1FA7B /* MotionMachine.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BA85009205F206C00F1FA7B /* MotionMachine.swift */; }; + 8BA85027205F206C00F1FA7B /* MotionGroup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BA8500A205F206C00F1FA7B /* MotionGroup.swift */; }; + 8BA85028205F206C00F1FA7B /* MotionSequence.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BA8500B205F206C00F1FA7B /* MotionSequence.swift */; }; + 8BA85029205F206C00F1FA7B /* TimerTempo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BA8500C205F206C00F1FA7B /* TimerTempo.swift */; }; + 8BA8502A205F206C00F1FA7B /* UIColorAssistant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BA8500E205F206C00F1FA7B /* UIColorAssistant.swift */; }; + 8BA8502B205F206C00F1FA7B /* CGStructAssistant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BA8500F205F206C00F1FA7B /* CGStructAssistant.swift */; }; + 8BA8502C205F206C00F1FA7B /* UIKitStructAssistant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BA85010205F206C00F1FA7B /* UIKitStructAssistant.swift */; }; + 8BA8502D205F206C00F1FA7B /* CIColorAssistant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BA85011205F206C00F1FA7B /* CIColorAssistant.swift */; }; + 8BA8502E205F206C00F1FA7B /* ValueAssistantGroup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BA85012205F206C00F1FA7B /* ValueAssistantGroup.swift */; }; 8BAA9C481CF2574D0079A9DC /* EasingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BAA9C471CF2574D0079A9DC /* EasingTests.swift */; }; 8BAA9C4A1CF27DA40079A9DC /* MotionGroupTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BAA9C491CF27DA40079A9DC /* MotionGroupTests.swift */; }; 8BAA9C4C1CF2A4C90079A9DC /* MotionSequenceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BAA9C4B1CF2A4C90079A9DC /* MotionSequenceTests.swift */; }; 8BC143D11CF0439A00E8EBC5 /* Tester.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BC143D01CF0439A00E8EBC5 /* Tester.swift */; }; 8BC8EC6F1CF432DA00B3B0A3 /* UIColorAssistantTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BC8EC6E1CF432DA00B3B0A3 /* UIColorAssistantTests.swift */; }; - 8BD8878A1CFCEBA00085107A /* CGStructAssistant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BD887891CFCEBA00085107A /* CGStructAssistant.swift */; }; 8BD8878C1CFD69C60085107A /* UIKitStructAssistantTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BD8878B1CFD69C60085107A /* UIKitStructAssistantTests.swift */; }; - 8BD8878E1CFD69E60085107A /* UIKitStructAssistant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BD8878D1CFD69E60085107A /* UIKitStructAssistant.swift */; }; 8BF304E21CF50B5900B8BE67 /* ValueAssistantGroupTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BF304E11CF50B5900B8BE67 /* ValueAssistantGroupTests.swift */; }; - 8BF304E61CF6C4E300B8BE67 /* PropertyData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BF304E51CF6C4E300B8BE67 /* PropertyData.swift */; }; 8BF304EA1CF7D42D00B8BE67 /* CIColorAssistantTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BF304E91CF7D42D00B8BE67 /* CIColorAssistantTests.swift */; }; - 8BF304ED1CF7D44700B8BE67 /* UIColorAssistant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BF304EB1CF7D44700B8BE67 /* UIColorAssistant.swift */; }; - 8BF304EE1CF7D44700B8BE67 /* CIColorAssistant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BF304EC1CF7D44700B8BE67 /* CIColorAssistant.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -65,27 +66,6 @@ /* Begin PBXFileReference section */ 8B62C0251CEF9C0F0087727A /* MotionMachineTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = MotionMachineTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 8B62C0751CEFA2F00087727A /* MotionTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MotionTests.swift; sourceTree = ""; }; - 8B62C0781CEFA34C0087727A /* MotionSequence.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = MotionSequence.swift; path = ../Classes/MotionSequence.swift; sourceTree = ""; }; - 8B62C0791CEFA34C0087727A /* MotionGroup.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = MotionGroup.swift; path = ../Classes/MotionGroup.swift; sourceTree = ""; }; - 8B62C07A1CEFA34C0087727A /* Motion.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Motion.swift; path = ../Classes/Motion.swift; sourceTree = ""; }; - 8B62C07E1CEFA34C0087727A /* ValueAssistantGroup.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ValueAssistantGroup.swift; sourceTree = ""; }; - 8B62C07F1CEFA34C0087727A /* PhysicsMotion.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = PhysicsMotion.swift; path = ../Classes/PhysicsMotion.swift; sourceTree = ""; }; - 8B62C0801CEFA34C0087727A /* MotionSupport.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = MotionSupport.swift; path = ../Classes/MotionSupport.swift; sourceTree = ""; }; - 8B62C0811CEFA34C0087727A /* PhysicsSystem.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = PhysicsSystem.swift; path = ../Classes/PhysicsSystem.swift; sourceTree = ""; }; - 8B62C0821CEFA34C0087727A /* CATempo.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = CATempo.swift; path = ../Classes/CATempo.swift; sourceTree = ""; }; - 8B62C0841CEFA34C0087727A /* MotionMachine.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = MotionMachine.swift; path = ../Classes/MotionMachine.swift; sourceTree = ""; }; - 8B62C0861CEFA34C0087727A /* EasingBack.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EasingBack.swift; sourceTree = ""; }; - 8B62C0871CEFA34C0087727A /* EasingBounce.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EasingBounce.swift; sourceTree = ""; }; - 8B62C0881CEFA34C0087727A /* EasingCircular.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EasingCircular.swift; sourceTree = ""; }; - 8B62C0891CEFA34C0087727A /* EasingCubic.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EasingCubic.swift; sourceTree = ""; }; - 8B62C08A1CEFA34C0087727A /* EasingElastic.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EasingElastic.swift; sourceTree = ""; }; - 8B62C08B1CEFA34C0087727A /* EasingExpo.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EasingExpo.swift; sourceTree = ""; }; - 8B62C08C1CEFA34C0087727A /* EasingLinear.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EasingLinear.swift; sourceTree = ""; }; - 8B62C08D1CEFA34C0087727A /* EasingQuadratic.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EasingQuadratic.swift; sourceTree = ""; }; - 8B62C08E1CEFA34C0087727A /* EasingQuartic.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EasingQuartic.swift; sourceTree = ""; }; - 8B62C08F1CEFA34C0087727A /* EasingQuintic.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EasingQuintic.swift; sourceTree = ""; }; - 8B62C0901CEFA34C0087727A /* EasingSine.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EasingSine.swift; sourceTree = ""; }; - 8B62C0911CEFA34C0087727A /* Tempo.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Tempo.swift; path = ../Classes/Tempo.swift; sourceTree = ""; }; 8B62C0AC1CEFA3730087727A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = MotionMachineTests/Info.plist; sourceTree = ""; }; 8B62C0B91CF014210087727A /* MotionMachine.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MotionMachine.app; sourceTree = BUILT_PRODUCTS_DIR; }; 8B62C0BB1CF014210087727A /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; @@ -94,22 +74,44 @@ 8B62C0C21CF014210087727A /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 8B62C0C51CF014210087727A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 8B62C0C71CF014210087727A /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 8B62C0CD1CF017640087727A /* TimerTempo.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = TimerTempo.swift; path = ../Classes/TimerTempo.swift; sourceTree = ""; }; 8B6B031A1CF3CC6300C1E216 /* PhysicsMotionTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PhysicsMotionTests.swift; sourceTree = ""; }; 8B6B031C1CF3F57500C1E216 /* CGStructAssistantTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = CGStructAssistantTests.swift; path = ValueAssistants/CGStructAssistantTests.swift; sourceTree = ""; }; + 8BA84FF5205F206C00F1FA7B /* Motion.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Motion.swift; sourceTree = ""; }; + 8BA84FF6205F206C00F1FA7B /* PhysicsMotion.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PhysicsMotion.swift; sourceTree = ""; }; + 8BA84FF7205F206C00F1FA7B /* CATempo.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CATempo.swift; sourceTree = ""; }; + 8BA84FF8205F206C00F1FA7B /* PropertyStates.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PropertyStates.swift; sourceTree = ""; }; + 8BA84FF9205F206C00F1FA7B /* MotionSupport.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MotionSupport.swift; sourceTree = ""; }; + 8BA84FFB205F206C00F1FA7B /* EasingElastic.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EasingElastic.swift; sourceTree = ""; }; + 8BA84FFC205F206C00F1FA7B /* EasingLinear.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EasingLinear.swift; sourceTree = ""; }; + 8BA84FFD205F206C00F1FA7B /* EasingSine.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EasingSine.swift; sourceTree = ""; }; + 8BA84FFE205F206C00F1FA7B /* EasingQuadratic.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EasingQuadratic.swift; sourceTree = ""; }; + 8BA84FFF205F206C00F1FA7B /* EasingCubic.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EasingCubic.swift; sourceTree = ""; }; + 8BA85000205F206C00F1FA7B /* EasingCircular.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EasingCircular.swift; sourceTree = ""; }; + 8BA85001205F206C00F1FA7B /* EasingExpo.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EasingExpo.swift; sourceTree = ""; }; + 8BA85002205F206C00F1FA7B /* EasingQuartic.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EasingQuartic.swift; sourceTree = ""; }; + 8BA85003205F206C00F1FA7B /* EasingBounce.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EasingBounce.swift; sourceTree = ""; }; + 8BA85004205F206C00F1FA7B /* EasingQuintic.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EasingQuintic.swift; sourceTree = ""; }; + 8BA85005205F206C00F1FA7B /* EasingBack.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EasingBack.swift; sourceTree = ""; }; + 8BA85006205F206C00F1FA7B /* PropertyData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PropertyData.swift; sourceTree = ""; }; + 8BA85007205F206C00F1FA7B /* Tempo.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Tempo.swift; sourceTree = ""; }; + 8BA85008205F206C00F1FA7B /* PhysicsSystem.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PhysicsSystem.swift; sourceTree = ""; }; + 8BA85009205F206C00F1FA7B /* MotionMachine.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MotionMachine.swift; sourceTree = ""; }; + 8BA8500A205F206C00F1FA7B /* MotionGroup.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MotionGroup.swift; sourceTree = ""; }; + 8BA8500B205F206C00F1FA7B /* MotionSequence.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MotionSequence.swift; sourceTree = ""; }; + 8BA8500C205F206C00F1FA7B /* TimerTempo.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TimerTempo.swift; sourceTree = ""; }; + 8BA8500E205F206C00F1FA7B /* UIColorAssistant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIColorAssistant.swift; sourceTree = ""; }; + 8BA8500F205F206C00F1FA7B /* CGStructAssistant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CGStructAssistant.swift; sourceTree = ""; }; + 8BA85010205F206C00F1FA7B /* UIKitStructAssistant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIKitStructAssistant.swift; sourceTree = ""; }; + 8BA85011205F206C00F1FA7B /* CIColorAssistant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CIColorAssistant.swift; sourceTree = ""; }; + 8BA85012205F206C00F1FA7B /* ValueAssistantGroup.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ValueAssistantGroup.swift; sourceTree = ""; }; 8BAA9C471CF2574D0079A9DC /* EasingTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EasingTests.swift; sourceTree = ""; }; 8BAA9C491CF27DA40079A9DC /* MotionGroupTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MotionGroupTests.swift; sourceTree = ""; }; 8BAA9C4B1CF2A4C90079A9DC /* MotionSequenceTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MotionSequenceTests.swift; sourceTree = ""; }; 8BC143D01CF0439A00E8EBC5 /* Tester.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Tester.swift; path = Helpers/Tester.swift; sourceTree = ""; }; 8BC8EC6E1CF432DA00B3B0A3 /* UIColorAssistantTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = UIColorAssistantTests.swift; path = ValueAssistants/UIColorAssistantTests.swift; sourceTree = ""; }; - 8BD887891CFCEBA00085107A /* CGStructAssistant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CGStructAssistant.swift; sourceTree = ""; }; 8BD8878B1CFD69C60085107A /* UIKitStructAssistantTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = UIKitStructAssistantTests.swift; path = ValueAssistants/UIKitStructAssistantTests.swift; sourceTree = ""; }; - 8BD8878D1CFD69E60085107A /* UIKitStructAssistant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIKitStructAssistant.swift; sourceTree = ""; }; 8BF304E11CF50B5900B8BE67 /* ValueAssistantGroupTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ValueAssistantGroupTests.swift; path = ValueAssistants/ValueAssistantGroupTests.swift; sourceTree = ""; }; - 8BF304E51CF6C4E300B8BE67 /* PropertyData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = PropertyData.swift; path = ../Classes/PropertyData.swift; sourceTree = ""; }; 8BF304E91CF7D42D00B8BE67 /* CIColorAssistantTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = CIColorAssistantTests.swift; path = ValueAssistants/CIColorAssistantTests.swift; sourceTree = ""; }; - 8BF304EB1CF7D44700B8BE67 /* UIColorAssistant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIColorAssistant.swift; sourceTree = ""; }; - 8BF304EC1CF7D44700B8BE67 /* CIColorAssistant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CIColorAssistant.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -133,8 +135,8 @@ 8B62C0081CEF9C0F0087727A = { isa = PBXGroup; children = ( + 8BA84FF4205F206C00F1FA7B /* Classes */, 8B62C0AC1CEFA3730087727A /* Info.plist */, - 8B62C0771CEFA32F0087727A /* MotionMachine */, 8B62C0341CEF9CA80087727A /* Tests */, 8B62C0BA1CF014210087727A /* App */, 8B62C0121CEF9C0F0087727A /* Products */, @@ -164,58 +166,6 @@ path = Tests; sourceTree = ""; }; - 8B62C0771CEFA32F0087727A /* MotionMachine */ = { - isa = PBXGroup; - children = ( - 8BF304E51CF6C4E300B8BE67 /* PropertyData.swift */, - 8B62C0CD1CF017640087727A /* TimerTempo.swift */, - 8B62C0781CEFA34C0087727A /* MotionSequence.swift */, - 8B62C0791CEFA34C0087727A /* MotionGroup.swift */, - 8B62C07A1CEFA34C0087727A /* Motion.swift */, - 8B62C07B1CEFA34C0087727A /* ValueAssistants */, - 8B62C07F1CEFA34C0087727A /* PhysicsMotion.swift */, - 8B62C0801CEFA34C0087727A /* MotionSupport.swift */, - 8B62C0811CEFA34C0087727A /* PhysicsSystem.swift */, - 8B62C0821CEFA34C0087727A /* CATempo.swift */, - 8B62C0841CEFA34C0087727A /* MotionMachine.swift */, - 8B62C0851CEFA34C0087727A /* EasingTypes */, - 8B62C0911CEFA34C0087727A /* Tempo.swift */, - ); - name = MotionMachine; - sourceTree = ""; - }; - 8B62C07B1CEFA34C0087727A /* ValueAssistants */ = { - isa = PBXGroup; - children = ( - 8BD8878D1CFD69E60085107A /* UIKitStructAssistant.swift */, - 8BD887891CFCEBA00085107A /* CGStructAssistant.swift */, - 8BF304EB1CF7D44700B8BE67 /* UIColorAssistant.swift */, - 8BF304EC1CF7D44700B8BE67 /* CIColorAssistant.swift */, - 8B62C07E1CEFA34C0087727A /* ValueAssistantGroup.swift */, - ); - name = ValueAssistants; - path = ../Classes/ValueAssistants; - sourceTree = ""; - }; - 8B62C0851CEFA34C0087727A /* EasingTypes */ = { - isa = PBXGroup; - children = ( - 8B62C0861CEFA34C0087727A /* EasingBack.swift */, - 8B62C0871CEFA34C0087727A /* EasingBounce.swift */, - 8B62C0881CEFA34C0087727A /* EasingCircular.swift */, - 8B62C0891CEFA34C0087727A /* EasingCubic.swift */, - 8B62C08A1CEFA34C0087727A /* EasingElastic.swift */, - 8B62C08B1CEFA34C0087727A /* EasingExpo.swift */, - 8B62C08C1CEFA34C0087727A /* EasingLinear.swift */, - 8B62C08D1CEFA34C0087727A /* EasingQuadratic.swift */, - 8B62C08E1CEFA34C0087727A /* EasingQuartic.swift */, - 8B62C08F1CEFA34C0087727A /* EasingQuintic.swift */, - 8B62C0901CEFA34C0087727A /* EasingSine.swift */, - ); - name = EasingTypes; - path = ../Classes/EasingTypes; - sourceTree = ""; - }; 8B62C0BA1CF014210087727A /* App */ = { isa = PBXGroup; children = ( @@ -242,6 +192,58 @@ name = ValueAssistants; sourceTree = ""; }; + 8BA84FF4205F206C00F1FA7B /* Classes */ = { + isa = PBXGroup; + children = ( + 8BA84FF5205F206C00F1FA7B /* Motion.swift */, + 8BA84FF6205F206C00F1FA7B /* PhysicsMotion.swift */, + 8BA84FF7205F206C00F1FA7B /* CATempo.swift */, + 8BA84FF8205F206C00F1FA7B /* PropertyStates.swift */, + 8BA84FF9205F206C00F1FA7B /* MotionSupport.swift */, + 8BA84FFA205F206C00F1FA7B /* EasingTypes */, + 8BA85006205F206C00F1FA7B /* PropertyData.swift */, + 8BA85007205F206C00F1FA7B /* Tempo.swift */, + 8BA85008205F206C00F1FA7B /* PhysicsSystem.swift */, + 8BA85009205F206C00F1FA7B /* MotionMachine.swift */, + 8BA8500A205F206C00F1FA7B /* MotionGroup.swift */, + 8BA8500B205F206C00F1FA7B /* MotionSequence.swift */, + 8BA8500C205F206C00F1FA7B /* TimerTempo.swift */, + 8BA8500D205F206C00F1FA7B /* ValueAssistants */, + ); + name = Classes; + path = ../Classes; + sourceTree = ""; + }; + 8BA84FFA205F206C00F1FA7B /* EasingTypes */ = { + isa = PBXGroup; + children = ( + 8BA84FFB205F206C00F1FA7B /* EasingElastic.swift */, + 8BA84FFC205F206C00F1FA7B /* EasingLinear.swift */, + 8BA84FFD205F206C00F1FA7B /* EasingSine.swift */, + 8BA84FFE205F206C00F1FA7B /* EasingQuadratic.swift */, + 8BA84FFF205F206C00F1FA7B /* EasingCubic.swift */, + 8BA85000205F206C00F1FA7B /* EasingCircular.swift */, + 8BA85001205F206C00F1FA7B /* EasingExpo.swift */, + 8BA85002205F206C00F1FA7B /* EasingQuartic.swift */, + 8BA85003205F206C00F1FA7B /* EasingBounce.swift */, + 8BA85004205F206C00F1FA7B /* EasingQuintic.swift */, + 8BA85005205F206C00F1FA7B /* EasingBack.swift */, + ); + path = EasingTypes; + sourceTree = ""; + }; + 8BA8500D205F206C00F1FA7B /* ValueAssistants */ = { + isa = PBXGroup; + children = ( + 8BA8500E205F206C00F1FA7B /* UIColorAssistant.swift */, + 8BA8500F205F206C00F1FA7B /* CGStructAssistant.swift */, + 8BA85010205F206C00F1FA7B /* UIKitStructAssistant.swift */, + 8BA85011205F206C00F1FA7B /* CIColorAssistant.swift */, + 8BA85012205F206C00F1FA7B /* ValueAssistantGroup.swift */, + ); + path = ValueAssistants; + sourceTree = ""; + }; 8BC143D21CF043A200E8EBC5 /* Helpers */ = { isa = PBXGroup; children = ( @@ -295,18 +297,18 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0730; - LastUpgradeCheck = 0830; + LastUpgradeCheck = 0920; ORGANIZATIONNAME = "Poet & Mountain, LLC"; TargetAttributes = { 8B62C0241CEF9C0F0087727A = { CreatedOnToolsVersion = 7.3.1; - LastSwiftMigration = 0800; + LastSwiftMigration = 0920; ProvisioningStyle = Manual; TestTargetID = 8B62C0B81CF014210087727A; }; 8B62C0B81CF014210087727A = { CreatedOnToolsVersion = 7.3.1; - LastSwiftMigration = 0800; + LastSwiftMigration = 0920; ProvisioningStyle = Manual; }; }; @@ -355,44 +357,45 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 8BA85020205F206C00F1FA7B /* EasingBounce.swift in Sources */, 8BC8EC6F1CF432DA00B3B0A3 /* UIColorAssistantTests.swift in Sources */, + 8BA85017205F206C00F1FA7B /* MotionSupport.swift in Sources */, + 8BA85013205F206C00F1FA7B /* Motion.swift in Sources */, + 8BA85019205F206C00F1FA7B /* EasingLinear.swift in Sources */, 8BAA9C481CF2574D0079A9DC /* EasingTests.swift in Sources */, - 8B62C0A21CEFA34C0087727A /* EasingCubic.swift in Sources */, - 8B62C0941CEFA34C0087727A /* MotionGroup.swift in Sources */, - 8B62C0A51CEFA34C0087727A /* EasingLinear.swift in Sources */, - 8B62C0AA1CEFA34C0087727A /* Tempo.swift in Sources */, + 8BA85024205F206C00F1FA7B /* Tempo.swift in Sources */, 8BC143D11CF0439A00E8EBC5 /* Tester.swift in Sources */, - 8BF304ED1CF7D44700B8BE67 /* UIColorAssistant.swift in Sources */, - 8B62C09B1CEFA34C0087727A /* PhysicsSystem.swift in Sources */, + 8BA8501F205F206C00F1FA7B /* EasingQuartic.swift in Sources */, 8BD8878C1CFD69C60085107A /* UIKitStructAssistantTests.swift in Sources */, - 8B62C0951CEFA34C0087727A /* Motion.swift in Sources */, - 8BF304EE1CF7D44700B8BE67 /* CIColorAssistant.swift in Sources */, - 8B62C09E1CEFA34C0087727A /* MotionMachine.swift in Sources */, - 8B62C09C1CEFA34C0087727A /* CATempo.swift in Sources */, - 8B62C0A91CEFA34C0087727A /* EasingSine.swift in Sources */, - 8B62C0931CEFA34C0087727A /* MotionSequence.swift in Sources */, - 8B62C0A31CEFA34C0087727A /* EasingElastic.swift in Sources */, - 8B62C0A71CEFA34C0087727A /* EasingQuartic.swift in Sources */, - 8B62C0A81CEFA34C0087727A /* EasingQuintic.swift in Sources */, 8B6B031D1CF3F57500C1E216 /* CGStructAssistantTests.swift in Sources */, - 8BD8878A1CFCEBA00085107A /* CGStructAssistant.swift in Sources */, + 8BA8502B205F206C00F1FA7B /* CGStructAssistant.swift in Sources */, + 8BA85028205F206C00F1FA7B /* MotionSequence.swift in Sources */, + 8BA85022205F206C00F1FA7B /* EasingBack.swift in Sources */, + 8BA8502D205F206C00F1FA7B /* CIColorAssistant.swift in Sources */, + 8BA85025205F206C00F1FA7B /* PhysicsSystem.swift in Sources */, + 8BA8501E205F206C00F1FA7B /* EasingExpo.swift in Sources */, + 8BA85023205F206C00F1FA7B /* PropertyData.swift in Sources */, + 8BA85027205F206C00F1FA7B /* MotionGroup.swift in Sources */, 8BAA9C4A1CF27DA40079A9DC /* MotionGroupTests.swift in Sources */, + 8BA8501C205F206C00F1FA7B /* EasingCubic.swift in Sources */, 8BF304E21CF50B5900B8BE67 /* ValueAssistantGroupTests.swift in Sources */, + 8BA8502A205F206C00F1FA7B /* UIColorAssistant.swift in Sources */, + 8BA8501A205F206C00F1FA7B /* EasingSine.swift in Sources */, + 8BA85018205F206C00F1FA7B /* EasingElastic.swift in Sources */, 8BF304EA1CF7D42D00B8BE67 /* CIColorAssistantTests.swift in Sources */, + 8BA8501B205F206C00F1FA7B /* EasingQuadratic.swift in Sources */, + 8BA8501D205F206C00F1FA7B /* EasingCircular.swift in Sources */, 8B62C0761CEFA2F00087727A /* MotionTests.swift in Sources */, - 8B62C0A61CEFA34C0087727A /* EasingQuadratic.swift in Sources */, - 8B62C0A01CEFA34C0087727A /* EasingBounce.swift in Sources */, - 8B62C0A41CEFA34C0087727A /* EasingExpo.swift in Sources */, - 8B62C0A11CEFA34C0087727A /* EasingCircular.swift in Sources */, - 8B62C0981CEFA34C0087727A /* ValueAssistantGroup.swift in Sources */, - 8BD8878E1CFD69E60085107A /* UIKitStructAssistant.swift in Sources */, - 8B62C0CE1CF017640087727A /* TimerTempo.swift in Sources */, - 8B62C09A1CEFA34C0087727A /* MotionSupport.swift in Sources */, - 8B62C0991CEFA34C0087727A /* PhysicsMotion.swift in Sources */, + 8BA85021205F206C00F1FA7B /* EasingQuintic.swift in Sources */, + 8BA8502E205F206C00F1FA7B /* ValueAssistantGroup.swift in Sources */, + 8BA85029205F206C00F1FA7B /* TimerTempo.swift in Sources */, 8BAA9C4C1CF2A4C90079A9DC /* MotionSequenceTests.swift in Sources */, - 8B62C09F1CEFA34C0087727A /* EasingBack.swift in Sources */, - 8BF304E61CF6C4E300B8BE67 /* PropertyData.swift in Sources */, 8B6B031B1CF3CC6300C1E216 /* PhysicsMotionTests.swift in Sources */, + 8BA8502C205F206C00F1FA7B /* UIKitStructAssistant.swift in Sources */, + 8BA85026205F206C00F1FA7B /* MotionMachine.swift in Sources */, + 8BA85016205F206C00F1FA7B /* PropertyStates.swift in Sources */, + 8BA85014205F206C00F1FA7B /* PhysicsMotion.swift in Sources */, + 8BA85015205F206C00F1FA7B /* CATempo.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -444,14 +447,20 @@ CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; @@ -479,6 +488,8 @@ ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_SWIFT3_OBJC_INFERENCE = Default; + SWIFT_VERSION = 4.0; }; name = Debug; }; @@ -491,14 +502,20 @@ CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; @@ -519,6 +536,8 @@ MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + SWIFT_SWIFT3_OBJC_INFERENCE = Default; + SWIFT_VERSION = 4.0; VALIDATE_PRODUCT = YES; }; name = Release; @@ -533,7 +552,8 @@ PRODUCT_BUNDLE_IDENTIFIER = com.poetmountain.MotionMachineTests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 3.0; + SWIFT_SWIFT3_OBJC_INFERENCE = Default; + SWIFT_VERSION = 4.0; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/MotionMachine.app/MotionMachine"; }; name = Debug; @@ -547,7 +567,8 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.poetmountain.MotionMachineTests; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 3.0; + SWIFT_SWIFT3_OBJC_INFERENCE = Default; + SWIFT_VERSION = 4.0; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/MotionMachine.app/MotionMachine"; }; name = Release; @@ -560,7 +581,8 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.poetmountain.MotionMachine; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 3.0; + SWIFT_SWIFT3_OBJC_INFERENCE = Default; + SWIFT_VERSION = 4.0; }; name = Debug; }; @@ -572,7 +594,8 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.poetmountain.MotionMachine; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 3.0; + SWIFT_SWIFT3_OBJC_INFERENCE = Default; + SWIFT_VERSION = 4.0; }; name = Release; }; diff --git a/Tests/Tests/EasingTests.swift b/Tests/Tests/EasingTests.swift index 1574fad..7593932 100644 --- a/Tests/Tests/EasingTests.swift +++ b/Tests/Tests/EasingTests.swift @@ -140,7 +140,7 @@ class EasingTests: XCTestCase { let mid_in = ease_in(50, 0, 100, 100) let end_in = ease_in(100, 0, 100, 100) - XCTAssertEqualWithAccuracy(mid_in, 29.29, accuracy: 0.01) + XCTAssertEqual(mid_in, 29.29, accuracy: 0.01) XCTAssertEqual(end_in, 100) // easeOut @@ -148,7 +148,7 @@ class EasingTests: XCTestCase { let mid_out = ease_out(50, 0, 100, 100) let end_out = ease_out(100, 0, 100, 100) - XCTAssertEqualWithAccuracy(mid_out, 70.71, accuracy: 0.01) + XCTAssertEqual(mid_out, 70.71, accuracy: 0.01) XCTAssertEqual(end_out, 100) // easeInOut @@ -156,7 +156,7 @@ class EasingTests: XCTestCase { let mid_inout = ease_inout(50, 0, 100, 100) let end_inout = ease_inout(100, 0, 100, 100) - XCTAssertEqualWithAccuracy(mid_inout, 50.0, accuracy: 0.0000001) + XCTAssertEqual(mid_inout, 50.0, accuracy: 0.0000001) XCTAssertEqual(end_inout, 100) } @@ -192,7 +192,7 @@ class EasingTests: XCTestCase { let mid_in = ease_in(50, 0, 100, 100) let end_in = ease_in(100, 0, 100, 100) - XCTAssertEqualWithAccuracy(mid_in, 13.39, accuracy: 0.01) + XCTAssertEqual(mid_in, 13.39, accuracy: 0.01) XCTAssertEqual(end_in, 100) // easeOut @@ -200,7 +200,7 @@ class EasingTests: XCTestCase { let mid_out = ease_out(50, 0, 100, 100) let end_out = ease_out(100, 0, 100, 100) - XCTAssertEqualWithAccuracy(mid_out, 86.6, accuracy: 0.01) + XCTAssertEqual(mid_out, 86.6, accuracy: 0.01) XCTAssertEqual(end_out, 100) // easeInOut @@ -218,7 +218,7 @@ class EasingTests: XCTestCase { let mid_in = ease_in(50, 0, 100, 100) let end_in = ease_in(100, 0, 100, 100) - XCTAssertEqualWithAccuracy(mid_in, -1.5625, accuracy: 0.00001) + XCTAssertEqual(mid_in, -1.5625, accuracy: 0.00001) XCTAssertEqual(end_in, 100) // easeOut @@ -226,7 +226,7 @@ class EasingTests: XCTestCase { let mid_out = ease_out(50, 0, 100, 100) let end_out = ease_out(100, 0, 100, 100) - XCTAssertEqualWithAccuracy(mid_out, 101.5625, accuracy: 0.00001) + XCTAssertEqual(mid_out, 101.5625, accuracy: 0.00001) XCTAssertEqual(end_out, 100) // easeInOut @@ -244,7 +244,7 @@ class EasingTests: XCTestCase { let mid_in = ease_in(50, 0, 100, 100) let end_in = ease_in(100, 0, 100, 100) - XCTAssertEqualWithAccuracy(mid_in, -8.76975, accuracy: 0.000001) + XCTAssertEqual(mid_in, -8.76975, accuracy: 0.000001) XCTAssertEqual(end_in, 100) // easeOut @@ -252,7 +252,7 @@ class EasingTests: XCTestCase { let mid_out = ease_out(50, 0, 100, 100) let end_out = ease_out(100, 0, 100, 100) - XCTAssertEqualWithAccuracy(mid_out, 108.76975, accuracy: 0.000001) + XCTAssertEqual(mid_out, 108.76975, accuracy: 0.000001) XCTAssertEqual(end_out, 100) // easeInOut @@ -270,7 +270,7 @@ class EasingTests: XCTestCase { let mid_in = ease_in(50, 0, 100, 100) let end_in = ease_in(100, 0, 100, 100) - XCTAssertEqualWithAccuracy(mid_in, 23.4375, accuracy: 0.00001) + XCTAssertEqual(mid_in, 23.4375, accuracy: 0.00001) XCTAssertEqual(end_in, 100) // easeOut @@ -278,7 +278,7 @@ class EasingTests: XCTestCase { let mid_out = ease_out(50, 0, 100, 100) let end_out = ease_out(100, 0, 100, 100) - XCTAssertEqualWithAccuracy(mid_out, 76.5625, accuracy: 0.00001) + XCTAssertEqual(mid_out, 76.5625, accuracy: 0.00001) XCTAssertEqual(end_out, 100) // easeInOut diff --git a/Tests/Tests/Helpers/Tester.swift b/Tests/Tests/Helpers/Tester.swift index a1450c6..a2710ca 100644 --- a/Tests/Tests/Helpers/Tester.swift +++ b/Tests/Tests/Helpers/Tester.swift @@ -9,10 +9,14 @@ import Foundation import UIKit +@objcMembers class Tester: NSObject { + var value: Double = 0.0 var rect = CGRect.zero + var vector = CGVector.zero var transform = CGAffineTransform.identity + var transform3D = CATransform3D(m11: 0.0, m12: 0.0, m13: 0.0, m14: 0.0, m21: 0.0, m22: 0.0, m23: 0.0, m24: 0.0, m31: 0.0, m32: 0.0, m33: 0.0, m34: 0.0, m41: 0.0, m42: 0.0, m43: 0.0, m44: 0.0) var color = UIColor.red var insets = UIEdgeInsets.zero var offset = UIOffset.zero diff --git a/Tests/Tests/MotionGroupTests.swift b/Tests/Tests/MotionGroupTests.swift index 9e21f2d..da32f5c 100644 --- a/Tests/Tests/MotionGroupTests.swift +++ b/Tests/Tests/MotionGroupTests.swift @@ -143,7 +143,7 @@ class MotionGroupTests: XCTestCase { XCTAssertEqual(group.totalProgress, 1.0) let new_timestamp = CFAbsoluteTimeGetCurrent() let motion = group.motions.first as! Motion - XCTAssertEqualWithAccuracy(new_timestamp, timestamp + motion.duration, accuracy: 0.9) + XCTAssertEqual(new_timestamp, timestamp + motion.duration, accuracy: 0.9) did_complete.fulfill() } diff --git a/Tests/Tests/MotionSequenceTests.swift b/Tests/Tests/MotionSequenceTests.swift index f480b14..843d99c 100644 --- a/Tests/Tests/MotionSequenceTests.swift +++ b/Tests/Tests/MotionSequenceTests.swift @@ -106,10 +106,10 @@ class MotionSequenceTests: XCTestCase { func test_should_end_motions_at_proper_ending_values() { let did_start = expectation(description: "sequence called started notify closure") let did_complete = expectation(description: "sequence called completed notify closure") - + let tester = Tester() let motion = Motion(target: tester, properties: [PropertyData("value", 20.0)], duration: 0.2) - let motion2 = Motion(target: tester, finalState: ["color" : UIColor.blue], duration: 0.2) + let motion2 = Motion(target: tester, statesForProperties: [PropertyStates(path: "color", end: UIColor.blue)], duration: 0.2) let group = MotionGroup(motions: [motion, motion2]) let motion3 = Motion(target: tester, properties: [PropertyData("value", 40.0)], duration: 0.2) let motion4 = Motion(target: tester, properties: [PropertyData("value", 60.0)], duration: 0.2) @@ -151,7 +151,7 @@ class MotionSequenceTests: XCTestCase { XCTAssertEqual(sequence.totalProgress, 1.0) let new_timestamp = CFAbsoluteTimeGetCurrent() let motion = sequence.steps.first as! Motion - XCTAssertEqualWithAccuracy(new_timestamp, timestamp + motion.duration, accuracy: 0.9) + XCTAssertEqual(new_timestamp, timestamp + motion.duration, accuracy: 0.9) did_complete.fulfill() } @@ -168,7 +168,7 @@ class MotionSequenceTests: XCTestCase { let tester = Tester() let motion = Motion(target: tester, properties: [PropertyData("value", 20.0)], duration: 0.2) - let motion2 = Motion(target: tester, finalState: ["color" : UIColor.blue], duration: 0.2) + let motion2 = Motion(target: tester, statesForProperties: [PropertyStates(path: "color", end: UIColor.blue)], duration: 0.2) let group = MotionGroup(motions: [motion, motion2]) let motion3 = Motion(target: tester, properties: [PropertyData("value", 40.0)], duration: 0.2) let motion4 = Motion(target: tester, properties: [PropertyData("value", 60.0)], duration: 0.2) @@ -209,7 +209,7 @@ class MotionSequenceTests: XCTestCase { let tester = Tester() let motion = Motion(target: tester, properties: [PropertyData("value", 20.0)], duration: 0.2) - let motion2 = Motion(target: tester, finalState: ["color" : UIColor.blue], duration: 0.2) + let motion2 = Motion(target: tester, statesForProperties: [PropertyStates(path: "color", end: UIColor.blue)], duration: 0.2) let group = MotionGroup(motions: [motion, motion2]) let motion3 = Motion(target: tester, properties: [PropertyData("value", 40.0)], duration: 0.2) let motion4 = Motion(target: tester, properties: [PropertyData("value", 60.0)], duration: 0.2) @@ -272,7 +272,7 @@ class MotionSequenceTests: XCTestCase { let tester = Tester() let motion = Motion(target: tester, properties: [PropertyData("value", 20.0)], duration: 0.2) - let motion2 = Motion(target: tester, finalState: ["color" : UIColor.blue], duration: 0.2) + let motion2 = Motion(target: tester, statesForProperties: [PropertyStates(path: "color", end: UIColor.blue)], duration: 0.2) let group = MotionGroup(motions: [motion, motion2]) let motion3 = Motion(target: tester, properties: [PropertyData("value", 40.0)], duration: 0.2) let motion4 = Motion(target: tester, properties: [PropertyData("value", 60.0)], duration: 0.2) @@ -344,7 +344,7 @@ class MotionSequenceTests: XCTestCase { let tester = Tester() let motion = Motion(target: tester, properties: [PropertyData("value", 20.0)], duration: 0.2) - let motion2 = Motion(target: tester, finalState: ["color" : UIColor.blue], duration: 0.2) + let motion2 = Motion(target: tester, statesForProperties: [PropertyStates(path: "color", end: UIColor.blue)], duration: 0.2) let group = MotionGroup(motions: [motion, motion2]) let motion3 = Motion(target: tester, properties: [PropertyData("value", 40.0)], duration: 0.2) let motion4 = Motion(target: tester, properties: [PropertyData("value", 60.0)], duration: 0.2) @@ -412,7 +412,7 @@ class MotionSequenceTests: XCTestCase { let tester = Tester() let motion = Motion(target: tester, properties: [PropertyData("value", 20.0)], duration: 0.2) - let motion2 = Motion(target: tester, finalState: ["color" : UIColor.blue], duration: 0.2) + let motion2 = Motion(target: tester, statesForProperties: [PropertyStates(path: "color", end: UIColor.blue)], duration: 0.2) let group = MotionGroup(motions: [motion, motion2]) let motion3 = Motion(target: tester, properties: [PropertyData("value", 40.0)], duration: 0.2) let motion4 = Motion(target: tester, properties: [PropertyData("value", 60.0)], duration: 0.2) @@ -481,7 +481,7 @@ class MotionSequenceTests: XCTestCase { let tester = Tester() let motion = Motion(target: tester, properties: [PropertyData("value", 20.0)], duration: 0.2) - let motion2 = Motion(target: tester, finalState: ["color" : UIColor.blue], duration: 0.2) + let motion2 = Motion(target: tester, statesForProperties: [PropertyStates(path: "color", end: UIColor.blue)], duration: 0.2) let group = MotionGroup(motions: [motion, motion2]) let motion3 = Motion(target: tester, properties: [PropertyData("value", 40.0)], duration: 0.2) let motion4 = Motion(target: tester, properties: [PropertyData("value", 60.0)], duration: 0.2) diff --git a/Tests/Tests/MotionTests.swift b/Tests/Tests/MotionTests.swift index ecc3f61..c3e32ba 100644 --- a/Tests/Tests/MotionTests.swift +++ b/Tests/Tests/MotionTests.swift @@ -139,7 +139,7 @@ class MotionTests: XCTestCase { XCTAssertEqual(final_value, 100.0) XCTAssertEqual(motion.totalProgress, 1.0) let new_timestamp = CFAbsoluteTimeGetCurrent() - XCTAssertEqualWithAccuracy(new_timestamp, timestamp + motion.duration, accuracy: 0.9) + XCTAssertEqual(new_timestamp, timestamp + motion.duration, accuracy: 0.9) did_complete.fulfill() } @@ -155,7 +155,7 @@ class MotionTests: XCTestCase { let did_complete = expectation(description: "motion called completed notify closure") - let motion = Motion(target: tester, finalState: ["value" : 10.0], duration: 0.2) + let motion = Motion(target: tester, statesForProperties: [PropertyStates.init(path: "value", end: 10.0)], duration: 0.2) .completed { (motion) in let final_value = tester.value XCTAssertEqual(motion.properties[0].current, 10.0) @@ -169,6 +169,28 @@ class MotionTests: XCTestCase { } + func test_object_prop_should_follow_property_states() { + let tester = Tester() + + let did_complete = expectation(description: "motion called completed notify closure") + + let motion = Motion(target: tester, statesForProperties: [PropertyStates.init(path: "value", start: 10.0, end: 50.0)], duration: 0.2) + .started({ (motion) in + XCTAssertEqual(motion.properties[0].current, 10.0) + }) + .completed { (motion) in + let final_value = tester.value + XCTAssertEqual(motion.properties[0].current, 50.0) + XCTAssertEqual(final_value, 50.0) + + did_complete.fulfill() + } + + motion.start() + waitForExpectations(timeout: 1.0, handler: nil) + + } + func test_moving_nested_struct() { let tester = Tester() @@ -193,7 +215,7 @@ class MotionTests: XCTestCase { let did_complete = expectation(description: "motion called completed notify closure") - let motion = Motion(target: tester, finalState: ["rect" : CGRect(x: 10.0, y: 0.0, width: 0.0, height: 0.0)], duration: 0.2) + let motion = Motion(target: tester, statesForProperties: [PropertyStates(path: "rect", end: CGRect(x: 10.0, y: 0.0, width: 0.0, height: 0.0))], duration: 0.2) .updated({ (motion) in print(tester.rect) }) @@ -220,7 +242,7 @@ class MotionTests: XCTestCase { let motion2 = Motion(target: tester, properties: [PropertyData("value", -10.0)], duration: 0.4) .completed { (motion) in - XCTAssertEqualWithAccuracy(tester.value, motion.properties[0].end, accuracy: 0.0000001) + XCTAssertEqual(tester.value, motion.properties[0].end, accuracy: 0.0000001) did_complete.fulfill() } motion2.additive = true @@ -244,7 +266,7 @@ class MotionTests: XCTestCase { let motion2 = Motion(target: tester, properties: [PropertyData("value", 0.0)], duration: 0.4) .completed { (motion) in // tester value should be halfway between the motions' ending values because second starts at 50% of duration of first - XCTAssertEqualWithAccuracy(tester.value, 5.0, accuracy: 0.0000001) + XCTAssertEqual(tester.value, 5.0, accuracy: 0.0000001) did_complete.fulfill() } diff --git a/Tests/Tests/PhysicsMotionTests.swift b/Tests/Tests/PhysicsMotionTests.swift index 4dfcf3a..dee0a77 100644 --- a/Tests/Tests/PhysicsMotionTests.swift +++ b/Tests/Tests/PhysicsMotionTests.swift @@ -101,7 +101,7 @@ class PhysicsMotionTests: XCTestCase { let motion = PhysicsMotion(target: tester, properties: [PropertyData("value")], velocity: 1.5, friction: 0.999) .started({ (motion) in let new_timestamp = CFAbsoluteTimeGetCurrent() - XCTAssertEqualWithAccuracy(new_timestamp, timestamp + motion.delay, accuracy: 0.9) + XCTAssertEqual(new_timestamp, timestamp + motion.delay, accuracy: 0.9) did_start.fulfill() }) @@ -144,7 +144,7 @@ class PhysicsMotionTests: XCTestCase { let motion2 = PhysicsMotion(target: tester, properties: [PropertyData("value")], velocity: -10.0, friction: 0.98) .completed { (m) in // velocity should basically be 0 as the two velocities cancel each other out - XCTAssertEqualWithAccuracy(tester.value, 0.0, accuracy: 0.1) + XCTAssertEqual(tester.value, 0.0, accuracy: 0.1) did_complete.fulfill() } diff --git a/Tests/Tests/ValueAssistants/CGStructAssistantTests.swift b/Tests/Tests/ValueAssistants/CGStructAssistantTests.swift index 91036b9..b288877 100644 --- a/Tests/Tests/ValueAssistants/CGStructAssistantTests.swift +++ b/Tests/Tests/ValueAssistants/CGStructAssistantTests.swift @@ -12,26 +12,170 @@ class CGStructAssistantTests: XCTestCase { // MARK: generateProperties - func test_generateProperties() { + func test_generateProperties_rect() { let assistant = CGStructAssistant() let tester = Tester() - let rect = CGRect(x: 0.0, y: 10.0, width: 50.0, height: 0.0) + let end_rect = CGRect(x: 0.0, y: 20.0, width: 50.0, height: 100.0) let path = "rect" - if let val = CGStructAssistant.valueForCGStruct(rect), let target = tester.value(forKeyPath: path) { - let props = try! assistant.generateProperties(fromObject: val, keyPath: path, targetObject: target as AnyObject) + if let end_val = CGStructAssistant.valueForCGStruct(end_rect), let target = tester.value(forKeyPath: path) { + let states = PropertyStates(path: path, end: end_val) + let props = try! assistant.generateProperties(targetObject: target as AnyObject, propertyStates: states) + + // should only have three props because x is unchanged from original rect + XCTAssertEqual(props.count, 3) + + if (props.count == 3) { + let y_prop = props[0] + let width_prop = props[1] + let height_prop = props[2] + // should test that ending property states were captured and start states are set to existing rect values + XCTAssertEqual(y_prop.path, "rect.origin.y") + XCTAssertEqual(y_prop.start, 0.0) + XCTAssertEqual(y_prop.end, 20.0) + XCTAssertEqual(width_prop.path, "rect.size.width") + XCTAssertEqual(width_prop.start, 0.0) + XCTAssertEqual(width_prop.end, 50.0) + XCTAssertEqual(height_prop.path, "rect.size.height") + XCTAssertEqual(height_prop.start, 0.0) + XCTAssertEqual(height_prop.end, 100.0) + } + } + + } + + func test_generateProperties_start_states() { + let assistant = CGStructAssistant() + let tester = Tester() + let start_rect = CGRect(x: 0.0, y: 5.0, width: 20.0, height: 20.0) + let end_rect = CGRect(x: 0.0, y: 00.0, width: 50.0, height: 100.0) + let path = "rect" + if let start_val = CGStructAssistant.valueForCGStruct(start_rect), let end_val = CGStructAssistant.valueForCGStruct(end_rect), let target = tester.value(forKeyPath: path) { + let states = PropertyStates(path: path, start: start_val, end: end_val) + let props = try! assistant.generateProperties(targetObject: target as AnyObject, propertyStates: states) + + // should only have three props because x is unchanged from original rect + XCTAssertEqual(props.count, 3) + + if (props.count == 3) { + let y_prop = props[0] + let width_prop = props[1] + let height_prop = props[2] + // should test that both the starting and ending property states were captured + // the y prop is included by MotionMachine because even though the ending value is equal to the original value, + // a different starting value was specified + XCTAssertEqual(y_prop.path, "rect.origin.y") + XCTAssertEqual(y_prop.start, Double(start_rect.origin.y)) + XCTAssertEqual(y_prop.end, Double(end_rect.origin.y)) + XCTAssertEqual(width_prop.path, "rect.size.width") + XCTAssertEqual(width_prop.start, Double(start_rect.size.width)) + XCTAssertEqual(width_prop.end, Double(end_rect.size.width)) + XCTAssertEqual(height_prop.path, "rect.size.height") + XCTAssertEqual(height_prop.start, Double(start_rect.size.height)) + XCTAssertEqual(height_prop.end, Double(end_rect.size.height)) + } + } + + } + + func test_generateProperties_vector() { + let assistant = CGStructAssistant() + let tester = Tester() + let start_vector = CGVector(dx: 0.0, dy: 0.5) + let end_vector = CGVector(dx: 10.0, dy: 0.0) + let path = "vector" + if let start_val = CGStructAssistant.valueForCGStruct(start_vector), let end_val = CGStructAssistant.valueForCGStruct(end_vector), let target = tester.value(forKeyPath: path) { + let states = PropertyStates(path: path, start: start_val, end: end_val) + let props = try! assistant.generateProperties(targetObject: target as AnyObject, propertyStates: states) XCTAssertEqual(props.count, 2) - let y_prop = props[0] - let width_prop = props[1] - XCTAssertEqual(y_prop.path, "rect.origin.y") - XCTAssertEqual(y_prop.end, 10.0) - XCTAssertEqual(width_prop.path, "rect.size.width") - XCTAssertEqual(width_prop.end, 50.0) + if (props.count == 2) { + let dx_prop = props[0] + let dy_prop = props[1] + // should test that both the starting and ending property states were captured + // the dy prop is included by MotionMachine because even though the ending value is equal to the original value, + // a different starting value was specified + XCTAssertEqual(dx_prop.path, "vector.dx") + XCTAssertEqual(dx_prop.start, Double(start_vector.dx)) + XCTAssertEqual(dx_prop.end, Double(end_vector.dx)) + XCTAssertEqual(dy_prop.path, "vector.dy") + XCTAssertEqual(dy_prop.start, Double(start_vector.dy)) + XCTAssertEqual(dy_prop.end, Double(end_vector.dy)) + + } + } + + } + + + func test_generateProperties_affineTransform() { + let assistant = CGStructAssistant() + let tester = Tester() + let start_transform = CGAffineTransform(a: 0.0, b: 0.0, c: 0.0, d: 1.0, tx: 0.0, ty: 0.0) + let end_transform = CGAffineTransform(a: 0.0, b: 0.0, c: 0.0, d: 0.0, tx: 10.0, ty: 10.0) + let path = "transform" + if let start_val = CGStructAssistant.valueForCGStruct(start_transform), let end_val = CGStructAssistant.valueForCGStruct(end_transform), let target = tester.value(forKeyPath: path) { + let states = PropertyStates(path: path, start: start_val, end: end_val) + let props = try! assistant.generateProperties(targetObject: target as AnyObject, propertyStates: states) + + XCTAssertEqual(props.count, 3) + + if (props.count == 3) { + let d_prop = props[0] + let tx_prop = props[1] + let ty_prop = props[2] + // should test that both the starting and ending property states were captured + // the d prop is included by MotionMachine because even though the ending value is equal to the original value, + // a different starting value was specified + XCTAssertEqual(d_prop.path, "transform.d") + XCTAssertEqual(d_prop.start, Double(start_transform.d)) + XCTAssertEqual(d_prop.end, Double(end_transform.d)) + XCTAssertEqual(tx_prop.path, "transform.tx") + XCTAssertEqual(tx_prop.start, Double(start_transform.tx)) + XCTAssertEqual(tx_prop.end, Double(end_transform.tx)) + XCTAssertEqual(ty_prop.path, "transform.ty") + XCTAssertEqual(ty_prop.start, Double(start_transform.ty)) + XCTAssertEqual(ty_prop.end, Double(end_transform.ty)) + } } } + + func test_generateProperties_transform3D() { + let assistant = CGStructAssistant() + let tester = Tester() + let start_transform = CATransform3D(m11: 0.0, m12: 5.0, m13: 0.0, m14: 0.0, m21: 0.0, m22: 0.0, m23: 0.0, m24: 0.0, m31: 0.0, m32: 0.0, m33: 0.0, m34: 0.0, m41: 0.0, m42: 0.0, m43: 0.0, m44: 0.0) + let end_transform = CATransform3D(m11: 10.0, m12: 0.0, m13: 20.0, m14: 0.0, m21: 0.0, m22: 0.0, m23: 0.0, m24: 0.0, m31: 0.0, m32: 0.0, m33: 0.0, m34: 0.0, m41: 0.0, m42: 0.0, m43: 0.0, m44: 0.0) + let path = "transform3D" + if let start_val = CGStructAssistant.valueForCGStruct(start_transform), let end_val = CGStructAssistant.valueForCGStruct(end_transform), let target = tester.value(forKeyPath: path) { + let states = PropertyStates(path: path, start: start_val, end: end_val) + let props = try! assistant.generateProperties(targetObject: target as AnyObject, propertyStates: states) + + XCTAssertEqual(props.count, 3) + + if (props.count == 3) { + let m11_prop = props[0] + let m12_prop = props[1] + let m13_prop = props[2] + // should test that both the starting and ending property states were captured + // the m12 prop is included by MotionMachine because even though the ending value is equal to the original value, + // a different starting value was specified + XCTAssertEqual(m11_prop.path, "transform3D.m11") + XCTAssertEqual(m11_prop.start, Double(start_transform.m11)) + XCTAssertEqual(m11_prop.end, Double(end_transform.m11)) + XCTAssertEqual(m12_prop.path, "transform3D.m12") + XCTAssertEqual(m12_prop.start, Double(start_transform.m12)) + XCTAssertEqual(m12_prop.end, Double(end_transform.m12)) + XCTAssertEqual(m13_prop.path, "transform3D.m13") + XCTAssertEqual(m13_prop.start, Double(start_transform.m13)) + XCTAssertEqual(m13_prop.end, Double(end_transform.m13)) + } + } + + } + + func test_generateProperties_error() { let assistant = CGStructAssistant() let tester = Tester() @@ -40,7 +184,8 @@ class CGStructAssistantTests: XCTestCase { if let target = tester.value(forKeyPath: path) { do { // method needs an NSValue but we pass in a Tester, so this should throw an error - try _ = assistant.generateProperties(fromObject: tester, keyPath: path, targetObject: target as AnyObject) + let states = PropertyStates(path: path, end: tester) + try _ = assistant.generateProperties(targetObject: target as AnyObject, propertyStates: states) } catch ValueAssistantError.typeRequirement(let valueType) { ValueAssistantError.typeRequirement(valueType).printError(fromFunction: #function) diff --git a/Tests/Tests/ValueAssistants/CIColorAssistantTests.swift b/Tests/Tests/ValueAssistants/CIColorAssistantTests.swift index 1311dbc..431c21b 100644 --- a/Tests/Tests/ValueAssistants/CIColorAssistantTests.swift +++ b/Tests/Tests/ValueAssistants/CIColorAssistantTests.swift @@ -14,16 +14,42 @@ class CIColorAssistantTests: XCTestCase { let assistant = CIColorAssistant() let color = CIColor.init(red: 0.0, green: 0.0, blue: 0.0, alpha: 1.0) let new_color = CIColor.init(red: 0.0, green: 0.0, blue: 0.5, alpha: 1.0) - let props = assistant.generateProperties(fromObject: new_color, keyPath: "", targetObject: color) + let states = PropertyStates(path: "", end: new_color) + let props = try! assistant.generateProperties(targetObject: color as AnyObject, propertyStates: states) + // should only have 1 prop because only blue value is changed from original color XCTAssertEqual(props.count, 1) - let color_prop = props[0] - XCTAssertEqual(color_prop.path, "blue") - XCTAssertEqual(color_prop.end, 0.5) + if (props.count == 1) { + let color_prop = props[0] + // should test that ending property state was captured and start state is set to original color value + XCTAssertEqual(color_prop.path, "blue") + XCTAssertEqual(color_prop.start, 0.0) + XCTAssertEqual(color_prop.end, 0.5) + } } + func test_generateProperties_start_state() { + let assistant = CIColorAssistant() + let color = CIColor.init(red: 0.0, green: 0.0, blue: 0.0, alpha: 1.0) + let start_color = CIColor.init(red: 0.0, green: 0.0, blue: 0.2, alpha: 1.0) + let new_color = CIColor.init(red: 0.0, green: 0.0, blue: 0.5, alpha: 1.0) + let states = PropertyStates(path: "", start: start_color, end: new_color) + let props = try! assistant.generateProperties(targetObject: color as AnyObject, propertyStates: states) + + // should only have 1 prop because only blue value is changed from original color + XCTAssertEqual(props.count, 1) + + if (props.count == 1) { + let color_prop = props[0] + // should test that both the starting and ending property states were captured + XCTAssertEqual(color_prop.path, "blue") + XCTAssertEqual(color_prop.start, 0.2) + XCTAssertEqual(color_prop.end, 0.5) + } + } + func test_updateValue() { let assistant = CIColorAssistant() diff --git a/Tests/Tests/ValueAssistants/UIColorAssistantTests.swift b/Tests/Tests/ValueAssistants/UIColorAssistantTests.swift index 9a34723..6d5cef6 100644 --- a/Tests/Tests/ValueAssistants/UIColorAssistantTests.swift +++ b/Tests/Tests/ValueAssistants/UIColorAssistantTests.swift @@ -14,16 +14,41 @@ class UIColorAssistantTests: XCTestCase { let assistant = UIColorAssistant() let color = UIColor.init(red: 0.0, green: 0.0, blue: 0.0, alpha: 1.0) let new_color = UIColor.init(red: 0.0, green: 0.0, blue: 0.5, alpha: 1.0) - let props = assistant.generateProperties(fromObject: new_color, keyPath: "", targetObject: color) - + let states = PropertyStates(path: "", end: new_color) + let props = try! assistant.generateProperties(targetObject: color, propertyStates: states) + + // should only have 1 prop because only blue value is changed from the original color XCTAssertEqual(props.count, 1) - let color_prop = props[0] - XCTAssertEqual(color_prop.path, "blue") - XCTAssertEqual(color_prop.end, 0.5) - + if (props.count == 1) { + let color_prop = props[0] + // should test that ending property state was captured and start state is set to original color value + XCTAssertEqual(color_prop.path, "blue") + XCTAssertEqual(color_prop.start, 0.0) + XCTAssertEqual(color_prop.end, 0.5) + } + } + func test_generateProperties_start_state() { + let assistant = UIColorAssistant() + let color = UIColor.init(red: 0.0, green: 0.0, blue: 0.0, alpha: 1.0) + let start_color = UIColor.init(red: 0.0, green: 0.0, blue: 0.2, alpha: 1.0) + let new_color = UIColor.init(red: 0.0, green: 0.0, blue: 0.5, alpha: 1.0) + let states = PropertyStates(path: "", start: start_color, end: new_color) + let props = try! assistant.generateProperties(targetObject: color, propertyStates: states) + + // should only have 1 prop because only blue value is changed from the original color + XCTAssertEqual(props.count, 1) + + if (props.count == 1) { + let color_prop = props[0] + // should test that both the starting and ending property states were captured + XCTAssertEqual(color_prop.path, "blue") + XCTAssertEqual(color_prop.start, 0.2) + XCTAssertEqual(color_prop.end, 0.5) + } + } func test_updateValue() { let assistant = UIColorAssistant() diff --git a/Tests/Tests/ValueAssistants/UIKitStructAssistantTests.swift b/Tests/Tests/ValueAssistants/UIKitStructAssistantTests.swift index 97c61f4..d20ec43 100644 --- a/Tests/Tests/ValueAssistants/UIKitStructAssistantTests.swift +++ b/Tests/Tests/ValueAssistants/UIKitStructAssistantTests.swift @@ -18,36 +18,113 @@ class UIKitStructAssistantTests: XCTestCase { let insets = UIEdgeInsetsMake(10.0, 0.0, 20.0, 0.0) let path = "insets" if let val = UIKitStructAssistant.valueForStruct(insets), let target = tester.value(forKeyPath: path) { - let props = try! assistant.generateProperties(fromObject: val, keyPath: path, targetObject: target as AnyObject) + let states = PropertyStates(path: path, end: val) + let props = try! assistant.generateProperties(targetObject: target as AnyObject, propertyStates: states) + // should only have 2 props because left and right are unchanged from original insets XCTAssertEqual(props.count, 2) - let top_prop = props[0] - let bottom_prop = props[1] - XCTAssertEqual(top_prop.path, "insets.top") - XCTAssertEqual(top_prop.end, 10.0) - XCTAssertEqual(bottom_prop.path, "insets.bottom") - XCTAssertEqual(bottom_prop.end, 20.0) + if (props.count == 2) { + let top_prop = props[0] + let bottom_prop = props[1] + // should test that ending property states were captured and start states are set to existing inset values + XCTAssertEqual(top_prop.path, "insets.top") + XCTAssertEqual(top_prop.start, 0.0) + XCTAssertEqual(top_prop.end, 10.0) + XCTAssertEqual(bottom_prop.path, "insets.bottom") + XCTAssertEqual(bottom_prop.start, 0.0) + XCTAssertEqual(bottom_prop.end, 20.0) + } + } + + } + + func test_generateProperties_UIEdgeInsets_start_state() { + let assistant = UIKitStructAssistant() + let tester = Tester() + let start_insets = UIEdgeInsetsMake(5.0, 5.0, 10.0, 0.0) + let insets = UIEdgeInsetsMake(10.0, 0.0, 20.0, 0.0) + let path = "insets" + if let start_val = UIKitStructAssistant.valueForStruct(start_insets), let val = UIKitStructAssistant.valueForStruct(insets), let target = tester.value(forKeyPath: path) { + let states = PropertyStates(path: path, start: start_val, end: val) + let props = try! assistant.generateProperties(targetObject: target as AnyObject, propertyStates: states) + + // should only have 3 props because right is unchanged from original insets + XCTAssertEqual(props.count, 3) + + if (props.count == 3) { + let top_prop = props[0] + let left_prop = props[1] + let bottom_prop = props[2] + // should test that both the starting and ending property states were captured + // the left prop is included by MotionMachine because even though the ending value is equal to the original inset value, + // a different starting value was specified + XCTAssertEqual(top_prop.path, "insets.top") + XCTAssertEqual(top_prop.start, 5.0) + XCTAssertEqual(top_prop.end, 10.0) + XCTAssertEqual(left_prop.path, "insets.left") + XCTAssertEqual(left_prop.start, 5.0) + XCTAssertEqual(left_prop.end, 0.0) + XCTAssertEqual(bottom_prop.path, "insets.bottom") + XCTAssertEqual(bottom_prop.start, 10.0) + XCTAssertEqual(bottom_prop.end, 20.0) + } } } + func test_generateProperties_UIOffset() { let assistant = UIKitStructAssistant() let tester = Tester() let offset = UIOffsetMake(10.0, 20.0) let path = "offset" if let val = UIKitStructAssistant.valueForStruct(offset), let target = tester.value(forKeyPath: path) { - let props = try! assistant.generateProperties(fromObject: val, keyPath: path, targetObject: target as AnyObject) + let states = PropertyStates(path: path, end: val) + let props = try! assistant.generateProperties(targetObject: target as AnyObject, propertyStates: states) + // should have 2 props both offset values are changed from original XCTAssertEqual(props.count, 2) - let h_prop = props[0] - let v_prop = props[1] - XCTAssertEqual(h_prop.path, "offset.horizontal") - XCTAssertEqual(h_prop.end, 10.0) - XCTAssertEqual(v_prop.path, "offset.vertical") - XCTAssertEqual(v_prop.end, 20.0) + if (props.count == 2) { + let h_prop = props[0] + let v_prop = props[1] + // should test that ending property states were captured and start states are set to original offset values + XCTAssertEqual(h_prop.path, "offset.horizontal") + XCTAssertEqual(h_prop.start, 0.0) + XCTAssertEqual(h_prop.end, 10.0) + XCTAssertEqual(v_prop.path, "offset.vertical") + XCTAssertEqual(v_prop.start, 0.0) + XCTAssertEqual(v_prop.end, 20.0) + } + } + + } + + func test_generateProperties_UIOffset_start_state() { + let assistant = UIKitStructAssistant() + let tester = Tester() + let start_offset = UIOffsetMake(5.0, 10.0) + let offset = UIOffsetMake(10.0, 20.0) + let path = "offset" + if let start_val = UIKitStructAssistant.valueForStruct(start_offset), let val = UIKitStructAssistant.valueForStruct(offset), let target = tester.value(forKeyPath: path) { + let states = PropertyStates(path: path, start: start_val, end: val) + let props = try! assistant.generateProperties(targetObject: target as AnyObject, propertyStates: states) + + // should have 2 props both offset values are changed from original + XCTAssertEqual(props.count, 2) + + if (props.count == 2) { + let h_prop = props[0] + let v_prop = props[1] + // should test that both the starting and ending property states were captured + XCTAssertEqual(h_prop.path, "offset.horizontal") + XCTAssertEqual(h_prop.start, 5.0) + XCTAssertEqual(h_prop.end, 10.0) + XCTAssertEqual(v_prop.path, "offset.vertical") + XCTAssertEqual(v_prop.start, 10.0) + XCTAssertEqual(v_prop.end, 20.0) + } } } @@ -61,8 +138,9 @@ class UIKitStructAssistantTests: XCTestCase { if let target = tester.value(forKeyPath: path) { do { // method needs an NSValue but we pass in a Tester, so this should throw an error - try _ = assistant.generateProperties(fromObject: tester, keyPath: path, targetObject: target as AnyObject) - + let states = PropertyStates(path: path, end: tester) + try _ = assistant.generateProperties(targetObject: target as AnyObject, propertyStates: states) + } catch ValueAssistantError.typeRequirement(let valueType) { ValueAssistantError.typeRequirement(valueType).printError(fromFunction: #function) diff --git a/Tests/Tests/ValueAssistants/ValueAssistantGroupTests.swift b/Tests/Tests/ValueAssistants/ValueAssistantGroupTests.swift index 4968c0a..cd70c19 100644 --- a/Tests/Tests/ValueAssistants/ValueAssistantGroupTests.swift +++ b/Tests/Tests/ValueAssistants/ValueAssistantGroupTests.swift @@ -44,16 +44,19 @@ class ValueAssistantGroupTests: XCTestCase { let rect = CGRect.init(x: 0.0, y: 10.0, width: 50.0, height: 0.0) let path = "rect" if let struct_val = CGStructAssistant.valueForCGStruct(rect), let target = tester.value(forKeyPath: path) { - let props = assistant.generateProperties(fromObject: struct_val, keyPath: path, targetObject: target as AnyObject) - + let states = PropertyStates(path: path, end: struct_val) + let props = try! assistant.generateProperties(targetObject: target as AnyObject, propertyStates: states) + XCTAssertEqual(props.count, 2) - let y_prop = props[0] - let width_prop = props[1] - XCTAssertEqual(y_prop.path, "rect.origin.y") - XCTAssertEqual(y_prop.end, 10.0) - XCTAssertEqual(width_prop.path, "rect.size.width") - XCTAssertEqual(width_prop.end, 50.0) + if (props.count == 2) { + let y_prop = props[0] + let width_prop = props[1] + XCTAssertEqual(y_prop.path, "rect.origin.y") + XCTAssertEqual(y_prop.end, 10.0) + XCTAssertEqual(width_prop.path, "rect.size.width") + XCTAssertEqual(width_prop.end, 50.0) + } } }