diff --git a/.gitignore b/.gitignore index 7ecd1172..060f5cfd 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,5 @@ Pods DerivedData build + +.ruby-version \ No newline at end of file diff --git a/.travis.yml b/.travis.yml index 4ca68c37..15b3f254 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,10 +1,39 @@ +branches: + only: + - master language: objective-c -xcode_workspace: pop.xcworkspace -xcode_scheme: pop -xcode_sdk: iphonesimulator7.0 -before_script: - - brew update - - brew upgrade xctool -before_install: - - export LANG=en_US.UTF-8 - - gem install cocoapods -v '0.32.1' +os: osx +osx_image: xcode9.2 +env: + matrix: + - TEST_TYPE=iOS + - TEST_TYPE=OSX + - TEST_TYPE=tvOS + - TEST_TYPE=CocoaPods +install: +- | + if [ "$TEST_TYPE" = iOS ] || [ "$TEST_TYPE" = OSX ] || [ "$TEST_TYPE" = tvOS ]; then + gem install xcpretty -N --no-ri --no-rdoc + gem install cocoapods --quiet --no-ri --no-rdoc + pod install + fi +script: +- | + if [ "$TEST_TYPE" = iOS ]; then + set -o pipefail + xcodebuild -workspace pop.xcworkspace -scheme pop-ios-framework -sdk iphonesimulator build test -destination "platform=iOS Simulator,name=iPhone SE" GCC_INSTRUMENT_PROGRAM_FLOW_ARCS=YES GCC_GENERATE_TEST_COVERAGE_FILES=YES | xcpretty -c + elif [ "$TEST_TYPE" = OSX ]; then + set -o pipefail + xcodebuild -workspace pop.xcworkspace -scheme pop-osx-framework -sdk macosx build test GCC_INSTRUMENT_PROGRAM_FLOW_ARCS=YES GCC_GENERATE_TEST_COVERAGE_FILES=YES | xcpretty -c + elif [ "$TEST_TYPE" = tvOS ]; then + set -o pipefail + xcodebuild -workspace pop.xcworkspace -scheme pop-tvos-framework -sdk appletvsimulator build test -destination "platform=tvOS Simulator,name=Apple TV" GCC_INSTRUMENT_PROGRAM_FLOW_ARCS=YES GCC_GENERATE_TEST_COVERAGE_FILES=YES | xcpretty -c + elif [ "$TEST_TYPE" = CocoaPods ]; then + pod lib lint pop.podspec + pod lib lint --use-libraries pop.podspec + fi +after_success: +- | + if [ "$TEST_TYPE" = iOS ] || [ "$TEST_TYPE" = OSX ] || [ "$TEST_TYPE" = tvOS ]; then + bash <(curl -s https://codecov.io/bash) + fi diff --git a/Configuration/Base-OSX.xcconfig b/Configuration/Base-OSX.xcconfig deleted file mode 100644 index 4aa529af..00000000 --- a/Configuration/Base-OSX.xcconfig +++ /dev/null @@ -1,12 +0,0 @@ -// -// Copyright (c) 2014-present, Facebook, Inc. -// All rights reserved. -// -// This source code is licensed under the BSD-style license found in the -// LICENSE file in the root directory of this source tree. An additional grant -// of patent rights can be found in the PATENTS file in the same directory. -// - -// Base xcconfig for OS X targets. -#include "Platform/OSX.xcconfig" -#include "Platform/Compiler.xcconfig" diff --git a/Configuration/Compiler.xcconfig b/Configuration/Compiler.xcconfig new file mode 100644 index 00000000..95904dbb --- /dev/null +++ b/Configuration/Compiler.xcconfig @@ -0,0 +1,77 @@ +// +// Copyright (c) 2014-present, Facebook, Inc. +// All rights reserved. +// +// This source code is licensed under the BSD-style license found in the +// LICENSE file in the root directory of this source tree. An additional grant +// of patent rights can be found in the PATENTS file in the same directory. +// + +// Deployment targets +MACOSX_DEPLOYMENT_TARGET = 10.7 +IPHONEOS_DEPLOYMENT_TARGET = 8.0 +TVOS_DEPLOYMENT_TARGET = 9.0 + +// Warnings +GCC_TREAT_WARNINGS_AS_ERRORS = YES +CLANG_WARN_CONSTANT_CONVERSION = YES +CLANG_WARN_ENUM_CONVERSION = YES +CLANG_WARN_INT_CONVERSION = YES +CLANG_WARN_INFINITE_RECURSION = YES +CLANG_WARN_SUSPICIOUS_MOVE = YES +CLANG_WARN__DUPLICATE_METHOD_MATCH = YES +CLANG_WARN_BOOL_CONVERSION = YES +CLANG_WARN_EMPTY_BODY = YES +CLANG_WARN_OBJC_MISSING_PROPERTY_SYNTHESIS = YES +CLANG_WARN_CXX0X_EXTENSIONS = NO +CLANG_WARN_UNREACHABLE_CODE = YES +CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES +CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES +CLANG_WARN_STRICT_PROTOTYPES = YES +GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO +GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES +GCC_WARN_ABOUT_RETURN_TYPE = YES +GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES +GCC_WARN_MISSING_PARENTHESES = YES +GCC_WARN_SHADOW = YES +GCC_WARN_SIGN_COMPARE = YES +GCC_WARN_UNINITIALIZED_AUTOS = YES +GCC_WARN_UNDECLARED_SELECTOR = YES +GCC_WARN_UNUSED_FUNCTION = YES +GCC_WARN_UNUSED_VARIABLE = YES +GCC_WARN_64_TO_32_BIT_CONVERSION = YES +CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES +CLANG_WARN_COMMA = YES +CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES +CLANG_WARN_OBJC_LITERAL_CONVERSION = YES +CLANG_WARN_RANGE_LOOP_ANALYSIS = YES +WARNING_CFLAGS = -Wall -Wextra -Wno-unused-parameter + +// Language +GCC_C_LANGUAGE_STANDARD = gnu99 +CLANG_CXX_LANGUAGE_STANDARD = c++11 +CLANG_CXX_LIBRARY = libc++ + +// Application Extension +APPLICATION_EXTENSION_API_ONLY = YES + +// Preprocessing +ENABLE_STRICT_OBJC_MSGSEND = YES + +// Enable ARC +CLANG_ENABLE_OBJC_ARC = YES + +// Modules +CLANG_ENABLE_MODULES=YES + +// Search Paths +ALWAYS_SEARCH_USER_PATHS = NO +FRAMEWORK_SEARCH_PATHS = $(inherited) $(BUILT_PRODUCTS_DIR) +LIBRARY_SEARCH_PATHS = $(BUILT_PRODUCTS_DIR) $(inherited) +HEADER_SEARCH_PATHS = $(inherited) $(SYMROOT)/Headers $(DERIVED_FILE_DIR) + +// Code Generation +GCC_DYNAMIC_NO_PIC = NO +GCC_NO_COMMON_BLOCKS = YES +GCC_INLINES_ARE_PRIVATE_EXTERN = YES +GCC_SYMBOLS_PRIVATE_EXTERN = NO diff --git a/Configuration/Platform/Compiler.xcconfig b/Configuration/Platform/Compiler.xcconfig deleted file mode 100644 index d87d7567..00000000 --- a/Configuration/Platform/Compiler.xcconfig +++ /dev/null @@ -1,36 +0,0 @@ -// -// Copyright (c) 2014-present, Facebook, Inc. -// All rights reserved. -// -// This source code is licensed under the BSD-style license found in the -// LICENSE file in the root directory of this source tree. An additional grant -// of patent rights can be found in the PATENTS file in the same directory. -// - -// Don't warn on implicit property synthesis -CLANG_WARN_OBJC_MISSING_PROPERTY_SYNTHESIS = NO - -// Treat warnings as errors -GCC_TREAT_WARNINGS_AS_ERRORS = YES -CLANG_WARN_CONSTANT_CONVERSION = YES -CLANG_WARN_ENUM_CONVERSION = YES -CLANG_WARN_INT_CONVERSION = YES -CLANG_WARN__DUPLICATE_METHOD_MATCH = YES -CLANG_WARN_BOOL_CONVERSION = YES -CLANG_WARN_EMPTY_BODY = YES -GCC_WARN_UNINITIALIZED_AUTOS = YES -GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO -GCC_WARN_UNUSED_FUNCTION = YES - -// Silence Eigen warnings -GCC_WARN_SHADOW = NO - -// Enable C++11 support -CLANG_CXX_LANGUAGE_STANDARD = c++11 -CLANG_CXX_LIBRARY = libc++ - -// Enable ARC -CLANG_ENABLE_OBJC_ARC = YES - -// Allow #import'ing code generated headers from DERIVED_FILE_DIR. -HEADER_SEARCH_PATHS = $(inherited) $(DERIVED_FILE_DIR) \ No newline at end of file diff --git a/Configuration/Platform/OSX.xcconfig b/Configuration/Platform/OSX.xcconfig deleted file mode 100644 index 8a7d68be..00000000 --- a/Configuration/Platform/OSX.xcconfig +++ /dev/null @@ -1,18 +0,0 @@ -// -// Copyright (c) 2014-present, Facebook, Inc. -// All rights reserved. -// -// This source code is licensed under the BSD-style license found in the -// LICENSE file in the root directory of this source tree. An additional grant -// of patent rights can be found in the PATENTS file in the same directory. -// - -// OS X Platform -SDKROOT = macosx -SUPPORTED_PLATFORMS = macosx - -// Standard Architectures -ARCHS = $(ARCHS_STANDARD) - -// Limit to OS X 64-bit (x86_64) -VALID_ARCHS = x86_64 \ No newline at end of file diff --git a/Configuration/Platform/iOS.xcconfig b/Configuration/Platform/iOS.xcconfig deleted file mode 100644 index 015e6437..00000000 --- a/Configuration/Platform/iOS.xcconfig +++ /dev/null @@ -1,18 +0,0 @@ -// -// Copyright (c) 2014-present, Facebook, Inc. -// All rights reserved. -// -// This source code is licensed under the BSD-style license found in the -// LICENSE file in the root directory of this source tree. An additional grant -// of patent rights can be found in the PATENTS file in the same directory. -// - -// iOS Platform -SDKROOT = iphoneos -IPHONEOS_DEPLOYMENT_TARGET = 6.0 - -// Standard Architectures, including 64-bit -ARCHS = $(ARCHS_STANDARD_INCLUDING_64_BIT) - -// Code Signing -CODE_SIGN_IDENTITY[sdk=iphoneos*] = iPhone Developer diff --git a/Configuration/Tests/ApplicationTests.xcconfig b/Configuration/Product/ApplicationTests.xcconfig similarity index 100% rename from Configuration/Tests/ApplicationTests.xcconfig rename to Configuration/Product/ApplicationTests.xcconfig diff --git a/Configuration/Projects/Project-GCOV.xcconfig b/Configuration/Product/Framework.xcconfig similarity index 68% rename from Configuration/Projects/Project-GCOV.xcconfig rename to Configuration/Product/Framework.xcconfig index 9b64e786..b4353a45 100644 --- a/Configuration/Projects/Project-GCOV.xcconfig +++ b/Configuration/Product/Framework.xcconfig @@ -1,13 +1,15 @@ -// +// // Copyright (c) 2014-present, Facebook, Inc. // All rights reserved. -// +// // This source code is licensed under the BSD-style license found in the // LICENSE file in the root directory of this source tree. An additional grant // of patent rights can be found in the PATENTS file in the same directory. -// +// -#include "Project-Debug.xcconfig" +#include "../Compiler.xcconfig" -GCC_GENERATE_TEST_COVERAGE_FILES = YES -GCC_INSTRUMENT_PROGRAM_FLOW_ARCS = YES \ No newline at end of file +// Version +DYLIB_COMPATIBILITY_VERSION = 1 +DYLIB_CURRENT_VERSION = 1 +CURRENT_PROJECT_VERSION = 1 diff --git a/Configuration/Applications/Application-OSX.xcconfig b/Configuration/Product/LogicTests.xcconfig similarity index 75% rename from Configuration/Applications/Application-OSX.xcconfig rename to Configuration/Product/LogicTests.xcconfig index 9b9bc91b..863fe2d4 100644 --- a/Configuration/Applications/Application-OSX.xcconfig +++ b/Configuration/Product/LogicTests.xcconfig @@ -7,14 +7,8 @@ // of patent rights can be found in the PATENTS file in the same directory. // -#include "../Base-OSX.xcconfig" +#include "../Compiler.xcconfig" // Deployment DSTROOT = /tmp/$(TARGET_NAME) SKIP_INSTALL = YES - -// Linking -OTHER_LDFLAGS = -ObjC -all_load -lc++ - -// Packaging -WRAPPER_EXTENSION = app diff --git a/Configuration/Applications/Application-iOS.xcconfig b/Configuration/Product/StaticLibrary.xcconfig similarity index 57% rename from Configuration/Applications/Application-iOS.xcconfig rename to Configuration/Product/StaticLibrary.xcconfig index 3214cd40..ce7a3d91 100644 --- a/Configuration/Applications/Application-iOS.xcconfig +++ b/Configuration/Product/StaticLibrary.xcconfig @@ -7,17 +7,15 @@ // of patent rights can be found in the PATENTS file in the same directory. // -#include "../Base-iOS.xcconfig" - -// Code Signing -CODE_SIGN_IDENTITY[sdk=iphoneos*] = iPhone Developer +#include "../Compiler.xcconfig" // Deployment DSTROOT = /tmp/$(TARGET_NAME) +INSTALL_PATH = $(SYMROOT)/Headers SKIP_INSTALL = YES -// Linking -OTHER_LDFLAGS = -ObjC -all_load -lc++ +// declare inlines as extern +GCC_INLINES_ARE_PRIVATE_EXTERN = YES -// Packaging -WRAPPER_EXTENSION = app +// Use PRODUCT_NAME instead of TARGET_NAME to support multiple targets for different platforms +PUBLIC_HEADERS_FOLDER_PATH = include/$(PRODUCT_NAME) diff --git a/Configuration/Projects/Project-Debug.xcconfig b/Configuration/Project/Project-Debug.xcconfig similarity index 88% rename from Configuration/Projects/Project-Debug.xcconfig rename to Configuration/Project/Project-Debug.xcconfig index a94dfe9d..550196d3 100644 --- a/Configuration/Projects/Project-Debug.xcconfig +++ b/Configuration/Project/Project-Debug.xcconfig @@ -9,6 +9,9 @@ #include "Project.xcconfig" +// Architectures +ONLY_ACTIVE_ARCH = YES + // Code Generation GCC_OPTIMIZATION_LEVEL = 0 @@ -23,3 +26,6 @@ COPY_PHASE_STRIP = NO // Default to dwarf DEBUG_INFORMATION_FORMAT = dwarf + +// Testing +ENABLE_TESTABILITY = YES diff --git a/Configuration/Projects/Project-Profile.xcconfig b/Configuration/Project/Project-Profile.xcconfig similarity index 100% rename from Configuration/Projects/Project-Profile.xcconfig rename to Configuration/Project/Project-Profile.xcconfig diff --git a/Configuration/Projects/Project-Release.xcconfig b/Configuration/Project/Project-Release.xcconfig similarity index 100% rename from Configuration/Projects/Project-Release.xcconfig rename to Configuration/Project/Project-Release.xcconfig diff --git a/Configuration/Base-iOS.xcconfig b/Configuration/Project/Project.xcconfig similarity index 74% rename from Configuration/Base-iOS.xcconfig rename to Configuration/Project/Project.xcconfig index 1fde7c64..f0551ab0 100644 --- a/Configuration/Base-iOS.xcconfig +++ b/Configuration/Project/Project.xcconfig @@ -7,6 +7,10 @@ // of patent rights can be found in the PATENTS file in the same directory. // -// Base xcconfig for iOS targets. -#include "Platform/iOS.xcconfig" -#include "Platform/Compiler.xcconfig" \ No newline at end of file +#include "../Compiler.xcconfig" + +// Install +SKIP_INSTALL = YES + +// Code Signing +CODE_SIGN_IDENTITY = diff --git a/Configuration/Projects/Project.xcconfig b/Configuration/Projects/Project.xcconfig deleted file mode 100644 index 1a175af9..00000000 --- a/Configuration/Projects/Project.xcconfig +++ /dev/null @@ -1,48 +0,0 @@ -// -// Copyright (c) 2014-present, Facebook, Inc. -// All rights reserved. -// -// This source code is licensed under the BSD-style license found in the -// LICENSE file in the root directory of this source tree. An additional grant -// of patent rights can be found in the PATENTS file in the same directory. -// - -#include "../Base-iOS.xcconfig" - -SDKROOT = iphoneos - -// Build Options -GCC_VERSION = com.apple.compilers.llvm.clang.1_0 - -// Deployment -TARGETED_DEVICE_FAMILY = 1,2 // iPhone, iPad - -// Packaging -PRODUCT_NAME = $(TARGET_NAME) -INFOPLIST_FILE = $(TARGET_NAME)/$(TARGET_NAME)-Info.plist - -// Search Paths -ALWAYS_SEARCH_USER_PATHS = NO -HEADER_SEARCH_PATHS = $(SYMROOT)/Headers -FRAMEWORK_SEARCH_PATHS = $(inherited) $(BUILT_PRODUCTS_DIR) -LIBRARY_SEARCH_PATHS = $(BUILT_PRODUCTS_DIR) $(inherited) - -// Code Generation -GCC_DYNAMIC_NO_PIC = NO -GCC_INLINES_ARE_PRIVATE_EXTERN = YES -GCC_SYMBOLS_PRIVATE_EXTERN = NO - -// Language -GCC_C_LANGUAGE_STANDARD = gnu99 -CLANG_ENABLE_OBJC_ARC = NO -GCC_PRECOMPILE_PREFIX_HEADER = YES -GCC_PREFIX_HEADER = $(TARGET_NAME)/$(TARGET_NAME)-Prefix.pch - -// Warnings -GCC_WARN_ABOUT_RETURN_TYPE = YES -GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES -GCC_WARN_MISSING_PARENTHESES = YES -GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES -GCC_WARN_SHADOW = YES -GCC_WARN_UNUSED_VARIABLE = YES -CLANG_WARN_CXX0X_EXTENSIONS = NO diff --git a/Configuration/Static Libraries/StaticLibrary-OSX.xcconfig b/Configuration/Static Libraries/StaticLibrary-OSX.xcconfig deleted file mode 100644 index 88b6fbce..00000000 --- a/Configuration/Static Libraries/StaticLibrary-OSX.xcconfig +++ /dev/null @@ -1,27 +0,0 @@ -// -// Copyright (c) 2014-present, Facebook, Inc. -// All rights reserved. -// -// This source code is licensed under the BSD-style license found in the -// LICENSE file in the root directory of this source tree. An additional grant -// of patent rights can be found in the PATENTS file in the same directory. -// - -#include "../Base-OSX.xcconfig" - -// Deployment -DSTROOT = /tmp/$(TARGET_NAME) -INSTALL_PATH = $(SYMROOT)/Headers -SKIP_INSTALL = YES - -// Packaging: Put headers in $(SYMROOT) instead of $(CONFIGURATION_BUILD_DIR) -// so header paths across projects don't depend on all projects having an -// identical configuration name. -// -// Note: PUBLIC_HEADERS_FOLDER_PATH is directly appended to $(CONFIGURATION_BUILD_DIR), -// so the path is relative to that. - -PUBLIC_HEADERS_FOLDER_PATH = ../Headers/$(TARGET_NAME) - -// declare inlines as extern -GCC_INLINES_ARE_PRIVATE_EXTERN = YES diff --git a/Configuration/Static Libraries/StaticLibrary-iOS.xcconfig b/Configuration/Static Libraries/StaticLibrary-iOS.xcconfig deleted file mode 100644 index a414eb37..00000000 --- a/Configuration/Static Libraries/StaticLibrary-iOS.xcconfig +++ /dev/null @@ -1,27 +0,0 @@ -// -// Copyright (c) 2014-present, Facebook, Inc. -// All rights reserved. -// -// This source code is licensed under the BSD-style license found in the -// LICENSE file in the root directory of this source tree. An additional grant -// of patent rights can be found in the PATENTS file in the same directory. -// - -#include "../Base-iOS.xcconfig" - -// Deployment -DSTROOT = /tmp/$(TARGET_NAME) -INSTALL_PATH = $(SYMROOT)/Headers -SKIP_INSTALL = YES - -// Packaging: Put headers in $(SYMROOT) instead of $(CONFIGURATION_BUILD_DIR) -// so header paths across projects don't depend on all projects having an -// identical configuration name. -// -// Note: PUBLIC_HEADERS_FOLDER_PATH is directly appended to $(CONFIGURATION_BUILD_DIR), -// so the path is relative to that. - -PUBLIC_HEADERS_FOLDER_PATH = ../Headers/$(TARGET_NAME) - -// declare inlines as extern -GCC_INLINES_ARE_PRIVATE_EXTERN = YES diff --git a/Configuration/Tests/LogicTests-OSX.xcconfig b/Configuration/Tests/LogicTests-OSX.xcconfig deleted file mode 100644 index a1b1ba1b..00000000 --- a/Configuration/Tests/LogicTests-OSX.xcconfig +++ /dev/null @@ -1,23 +0,0 @@ -// -// Copyright (c) 2014-present, Facebook, Inc. -// All rights reserved. -// -// This source code is licensed under the BSD-style license found in the -// LICENSE file in the root directory of this source tree. An additional grant -// of patent rights can be found in the PATENTS file in the same directory. -// - -#include "../Base-OSX.xcconfig" - -// Deployment -DSTROOT = /tmp/$(TARGET_NAME) -SKIP_INSTALL = YES - -// Linking -OTHER_LDFLAGS = -framework SenTestingKit -all_load -lc++ - -// Packaging -WRAPPER_EXTENSION = octest - -// Search Paths -FRAMEWORK_SEARCH_PATHS = $(DEVELOPER_FRAMEWORKS_DIR) diff --git a/Configuration/Tests/LogicTests-iOS.xcconfig b/Configuration/Tests/LogicTests-iOS.xcconfig deleted file mode 100644 index 2d2a95e6..00000000 --- a/Configuration/Tests/LogicTests-iOS.xcconfig +++ /dev/null @@ -1,26 +0,0 @@ -// -// Copyright (c) 2014-present, Facebook, Inc. -// All rights reserved. -// -// This source code is licensed under the BSD-style license found in the -// LICENSE file in the root directory of this source tree. An additional grant -// of patent rights can be found in the PATENTS file in the same directory. -// - -#include "../Base-iOS.xcconfig" - -// Code Signing -CODE_SIGN_IDENTITY[sdk=iphoneos*] = iPhone Developer - -// Deployment -DSTROOT = /tmp/$(TARGET_NAME) -SKIP_INSTALL = YES - -// Linking -OTHER_LDFLAGS = -framework SenTestingKit -all_load -lc++ - -// Packaging -WRAPPER_EXTENSION = octest - -// Search Paths -FRAMEWORK_SEARCH_PATHS = $(SDKROOT)/Developer/Library/Frameworks $(DEVELOPER_FRAMEWORKS_DIR) diff --git a/Images/EmbeddedBinaries.png b/Images/EmbeddedBinaries.png new file mode 100644 index 00000000..3766c47e Binary files /dev/null and b/Images/EmbeddedBinaries.png differ diff --git a/PATENTS b/PATENTS index 7920535f..c7cc4c39 100644 --- a/PATENTS +++ b/PATENTS @@ -1,23 +1,33 @@ -Additional Grant of Patent Rights +Additional Grant of Patent Rights Version 2 "Software" means the Pop software distributed by Facebook, Inc. -Facebook hereby grants you a perpetual, worldwide, royalty-free, non-exclusive, -irrevocable (subject to the termination provision below) license under any -rights in any patent claims owned by Facebook, to make, have made, use, sell, -offer to sell, import, and otherwise transfer the Software. For avoidance of -doubt, no license is granted under Facebook’s rights in any patent claims that -are infringed by (i) modifications to the Software made by you or a third party, -or (ii) the Software in combination with any software or other technology -provided by you or a third party. +Facebook, Inc. ("Facebook") hereby grants to each recipient of the Software +("you") a perpetual, worldwide, royalty-free, non-exclusive, irrevocable +(subject to the termination provision below) license under any Necessary +Claims, to make, have made, use, sell, offer to sell, import, and otherwise +transfer the Software. For avoidance of doubt, no license is granted under +Facebook’s rights in any patent claims that are infringed by (i) modifications +to the Software made by you or any third party or (ii) the Software in +combination with any software or other technology. The license granted hereunder will terminate, automatically and without notice, -for anyone that makes any claim (including by filing any lawsuit, assertion or -other action) alleging (a) direct, indirect, or contributory infringement or -inducement to infringe any patent: (i) by Facebook or any of its subsidiaries or -affiliates, whether or not such claim is related to the Software, (ii) by any -party if such claim arises in whole or in part from any software, product or -service of Facebook or any of its subsidiaries or affiliates, whether or not -such claim is related to the Software, or (iii) by any party relating to the -Software; or (b) that any right in any patent claim of Facebook is invalid or -unenforceable. +if you (or any of your subsidiaries, corporate affiliates or agents) initiate +directly or indirectly, or take a direct financial interest in, any Patent +Assertion: (i) against Facebook or any of its subsidiaries or corporate +affiliates, (ii) against any party if such Patent Assertion arises in whole or +in part from any software, technology, product or service of Facebook or any of +its subsidiaries or corporate affiliates, or (iii) against any party relating +to the Software. Notwithstanding the foregoing, if Facebook or any of its +subsidiaries or corporate affiliates files a lawsuit alleging patent +infringement against you in the first instance, and you respond by filing a +patent infringement counterclaim in that lawsuit against that party that is +unrelated to the Software, the license granted hereunder will not terminate +under section (i) of this paragraph due to such counterclaim. + +A "Necessary Claim" is a claim of a patent owned by Facebook that is +necessarily infringed by the Software standing alone. + +A "Patent Assertion" is any lawsuit or other action alleging direct, indirect, +or contributory infringement or inducement to infringe any patent, including a +cross-claim or counterclaim. diff --git a/Podfile b/Podfile index a1f2b93a..72f67fc7 100755 --- a/Podfile +++ b/Podfile @@ -1,10 +1,15 @@ -platform :ios, '7.0' - -target :'pop-tests', :exclusive => true do +abstract_target 'Tests' do pod 'OCMock', '~> 2.2' -end + + target :'pop-tests-ios' do + platform :ios, '6.0' + end -target :'pop-tests-osx', :exclusive => true do - platform :osx, '10.9' - pod 'OCMock', '~> 2.2' -end \ No newline at end of file + target :'pop-tests-tvos' do + platform :tvos, '9.0' + end + + target :'pop-tests-osx' do + platform :osx, '10.8' + end +end diff --git a/Podfile.lock b/Podfile.lock index 5a3394c7..d49a68f3 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -1,10 +1,12 @@ PODS: - - OCMock (2.2.3) + - OCMock (2.2.4) DEPENDENCIES: - OCMock (~> 2.2) SPEC CHECKSUMS: - OCMock: ea7fe30ee99e4e3186ad47d032a301fa7e8793ec + OCMock: a6a7dc0e3997fb9f35d99f72528698ebf60d64f2 -COCOAPODS: 0.32.1 +PODFILE CHECKSUM: 06e2f62938dff5782de5abf2adf6966a85f24637 + +COCOAPODS: 1.2.1 diff --git a/README.md b/README.md index 3cf65b99..e7a5595d 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ ![pop](https://github.com/facebook/pop/blob/master/Images/pop.gif?raw=true) -Pop is an extensible animation engine for iOS and OS X. In addition to basic static animations, it supports spring and decay dynamic animations, making it useful for building realistic, physics-based interactions. The API allows quick integration with existing Objective-C codebases and enables the animation of any property on any object. It's a mature and well-tested framework that drives all the animations and transitions in [Paper](http://www.facebook.com/paper). +Pop is an extensible animation engine for iOS, tvOS, and OS X. In addition to basic static animations, it supports spring and decay dynamic animations, making it useful for building realistic, physics-based interactions. The API allows quick integration with existing Objective-C or Swift codebases and enables the animation of any property on any object. It's a mature and well-tested framework that drives all the animations and transitions in [Paper](https://en.wikipedia.org/wiki/Facebook_Paper). [![Build Status](https://travis-ci.org/facebook/pop.svg)](https://travis-ci.org/facebook/pop) @@ -9,36 +9,87 @@ Pop is an extensible animation engine for iOS and OS X. In addition to basic sta Pop is available on [CocoaPods](http://cocoapods.org). Just add the following to your project Podfile: ```ruby -pod 'pop' +pod 'pop', '~> 1.0' ``` + +Bugs are first fixed in master and then made available via a designated release. If you tend to live on the bleeding edge, you can use Pop from master with the following Podfile entry: + +```ruby +pod 'pop', :git => 'https://github.com/facebook/pop.git' +``` + +### Framework (manual) +By adding the project to your project and adding pop.embedded framework to the Embedded Binaries section on the General tab of your app's target, you can set up pop in seconds! This also enables `@import pop` syntax with header modules. + +**Note**: because of some awkward limitations with Xcode, embedded binaries must share the same name as the module and must have `.framework` as an extension. This means that you'll see three pop.frameworks when adding embedded binaries (one for OS X, one for tvOS, and one for iOS). You'll need to be sure to add the right one; they appear identically in the list but note the list is populated in order of targets. You can verify the correct one was chosen by checking the path next to the framework listed, in the format `-` (e.g. `Debug-iphoneos`). + +![Embedded Binaries](Images/EmbeddedBinaries.png?raw=true) + +**Note 2**: this method does not currently play nicely with workspaces. Since targets can only depend on and embed products from other targets in the same project, it only works when pop.xcodeproj is added as a subproject to the current target's project. Otherwise, you'll need to manually set the build ordering in the scheme and copy in the product. + +### Static Library (manual) Alternatively, you can add the project to your workspace and adopt the provided configuration files or manually copy the files under the pop subdirectory into your project. If installing manually, ensure the C++ standard library is also linked by including `-lc++` to your project linker flags. ## Usage Pop adopts the Core Animation explicit animation programming model. Use by including the following import: +#### Objective-C + ```objective-c -#import +#import +``` + +or if you're using the embedded framework: + +```objective-c +@import pop; +``` + +#### Swift + +```swift +import pop ``` ### Start, Stop & Update To start an animation, add it to the object you wish to animate: +#### Objective-C + ```objective-c POPSpringAnimation *anim = [POPSpringAnimation animation]; ... [layer pop_addAnimation:anim forKey:@"myKey"]; ``` +#### Swift + +```swift +let anim = POPSpringAnimation() +... +layer.pop_add(anim, forKey: "myKey") +``` + To stop an animation, remove it from the object referencing the key specified on start: +#### Objective-C + ```objective-c [layer pop_removeAnimationForKey:@"myKey"]; ``` +#### Swift + +```swift +layer.pop_removeAnimation(forKey: "myKey") +``` + The key can also be used to query for the existence of an animation. Updating the toValue of a running animation can provide the most seamless way to change course: +#### Objective-C + ```objective-c anim = [layer pop_animationForKey:@"myKey"]; if (anim) { @@ -50,6 +101,18 @@ if (anim) { } ``` +#### Swift + +```swift +if let anim = layer.pop_animation(forKey: "myKey") as? POPSpringAnimation { + /* update to value to new destination */ + anim.toValue = 42.0 +} else { + /* create and start a new animation */ + .... +} +``` + While a layer was used in the above examples, the Pop interface is implemented as a category addition on NSObject. Any NSObject or subclass can be animated. ### Types @@ -58,27 +121,65 @@ There are four concrete animation types: spring, decay, basic and custom. Spring animations can be used to give objects a delightful bounce. In this example, we use a spring animation to animate a layer's bounds from its current value to (0, 0, 400, 400): +#### Objective-C + ```objective-c POPSpringAnimation *anim = [POPSpringAnimation animationWithPropertyNamed:kPOPLayerBounds]; anim.toValue = [NSValue valueWithCGRect:CGRectMake(0, 0, 400, 400)]; [layer pop_addAnimation:anim forKey:@"size"]; ``` + +#### Swift + +```swift +if let anim = POPSpringAnimation(propertyNamed: kPOPLayerBounds) { + anim.toValue = NSValue(cgRect: CGRect(x: 0, y: 0, width: 400, height: 400)) + layer.pop_add(anim, forKey: "size") +} +``` + Decay animations can be used to gradually slow an object to a halt. In this example, we decay a layer's positionX from it's current value and velocity 1000pts per second: +#### Objective-C + ```objective-c POPDecayAnimation *anim = [POPDecayAnimation animationWithPropertyNamed:kPOPLayerPositionX]; anim.velocity = @(1000.); [layer pop_addAnimation:anim forKey:@"slide"]; ``` +#### Swift + +```swift +if let anim = POPDecayAnimation(propertyNamed: kPOPLayerPositionX) { + anim.velocity = 1000.0 + layer.pop_add(anim, forKey: "slide") +} +``` + Basic animations can be used to interpolate values over a specified time period. To use an ease-in ease-out animation to animate a view's alpha from 0.0 to 1.0 over the default duration: + +#### Objective-C + ```objective-c POPBasicAnimation *anim = [POPBasicAnimation animationWithPropertyNamed:kPOPViewAlpha]; anim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; anim.fromValue = @(0.0); anim.toValue = @(1.0); -[view pop_addAnimation:anim forKey:@"slide"]; +[view pop_addAnimation:anim forKey:@"fade"]; ``` + +#### Swift + +```swift +if let anim = POPBasicAnimation(propertyNamed: kPOPViewAlpha) { + anim.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut) + anim.fromValue = 0.0 + anim.toValue = 1.0 + view.pop_add(anim, forKey: "fade") +} +``` + `POPCustomAnimation` makes creating custom animations and transitions easier by handling CADisplayLink and associated time-step management. See header for more details. @@ -86,13 +187,26 @@ anim.toValue = @(1.0); The property animated is specified by the `POPAnimatableProperty` class. In this example we create a spring animation and explicitly set the animatable property corresponding to `-[CALayer bounds]`: +#### Objective-C + ```objective-c POPSpringAnimation *anim = [POPSpringAnimation animation]; anim.property = [POPAnimatableProperty propertyWithName:kPOPLayerBounds]; ``` +#### Swift + +```swift +let anim = POPSpringAnimation() +if let property = POPAnimatableProperty.property(withName: kPOPLayerBounds) as? POPAnimatableProperty { + anim.property = property +} +``` + The framework provides many common layer and view animatable properties out of box. You can animate a custom property by creating a new instance of the class. In this example, we declare a custom volume property: +#### Objective-C + ```objective-c prop = [POPAnimatableProperty propertyWithName:@"com.foo.radio.volume" initializer:^(POPMutableAnimatableProperty *prop) { // read value @@ -110,6 +224,36 @@ prop = [POPAnimatableProperty propertyWithName:@"com.foo.radio.volume" initializ anim.property = prop; ``` +#### Swift + +```swift +if let prop = POPAnimatableProperty.property(withName: "com.foo.radio.volume", initializer: { prop in + guard let prop = prop else { + return + } + // read value + prop.readBlock = { obj, values in + guard let obj = obj as? Volumeable, let values = values else { + return + } + + values[0] = obj.volume + } + // write value + prop.writeBlock = { obj, values in + guard var obj = obj as? Volumeable, let values = values else { + return + } + + obj.volume = values[0] + } + // dynamics threshold + prop.threshold = 0.01 +}) as? POPAnimatableProperty { + anim.property = prop +} +``` + For a complete listing of provided animatable properties, as well more information on declaring custom properties see `POPAnimatableProperty.h`. @@ -119,18 +263,37 @@ Here are a few tips when debugging. Pop obeys the Simulator's Toggle Slow Animat Consider naming your animations. This will allow you to more easily identify them when referencing them, either via logging or in the debugger: +#### Objective-C + ```objective-c anim.name = @"springOpen"; ``` +#### Swift + +```swift +anim.name = "springOpen" +``` + Each animation comes with an associated tracer. The tracer allows you to record all animation-related events, in a fast and efficient manner, allowing you to query and analyze them after animation completion. The below example starts the tracer and configures it to log all events on animation completion: +#### Objective-C + ```objective-c POPAnimationTracer *tracer = anim.tracer; tracer.shouldLogAndResetOnCompletion = YES; [tracer start]; ``` +#### Swift + +```swift +if let tracer = anim.tracer { + tracer.shouldLogAndResetOnCompletion = true + tracer.start() +} +``` + See `POPAnimationTracer.h` for more details. ## Testing @@ -143,15 +306,32 @@ pod install Assuming CocoaPods is installed, this will include the necessary OCMock dependency to the unit test targets. +## SceneKit + +Due to SceneKit requiring iOS 8 and OS X 10.9, POP's SceneKit extensions aren't provided out of box. Unfortunately, [weakly linked frameworks](https://developer.apple.com/library/mac/documentation/MacOSX/Conceptual/BPFrameworks/Concepts/WeakLinking.html) cannot be used due to issues mentioned in the [Xcode 6.1 Release Notes](https://developer.apple.com/library/ios/releasenotes/DeveloperTools/RN-Xcode/Chapters/xc6_release_notes.html). + +To remedy this, you can easily opt-in to use SceneKit! Simply add this to the Preprocessor Macros section of your Xcode Project: + +``` +POP_USE_SCENEKIT=1 +``` + ## Resources A collection of links to external resources that may prove valuable: -* [Core Animation Programming Guide](https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/CoreAnimation_guide/Introduction/Introduction.html) +* [AGGeometryKit+POP - Animating Quadrilaterals with Pop](https://github.com/hfossli/aggeometrykit-pop) +* [Apple – Core Animation Programming Guide](https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/CoreAnimation_guide/Introduction/Introduction.html) +* [iOS Development Tips – UIScrollView-like deceleration with Pop](http://iosdevtips.co/post/84571595353/replicating-uiscrollviews-deceleration-with-facebook) +* [Pop Playground – Repository of Pop animation examples](https://github.com/callmeed/pop-playground) +* [Pop Playground 2 – Playing with Facebook's framework](http://victorbaro.com/2014/05/pop-playground-playing-with-facebooks-framework/) +* [POP-MCAnimate – Concise syntax for the Pop animation framework](https://github.com/matthewcheok/POP-MCAnimate) +* [Popping - Great examples in one project](https://github.com/schneiderandre/popping) +* [Rebound – Spring Animations for Android](http://facebook.github.io/rebound/) * [Tapity Tutorial – Getting Started with Pop](http://tapity.com/tutorial-getting-started-with-pop/) * [Tweaks – Easily adjust parameters for iOS apps in development](https://github.com/facebook/tweaks) -* [Rebound – Springs Animations for Android](http://facebook.github.io/rebound/) - +* [POP Tutorial in 5 steps](https://github.com/maxmyers/FacebookPop) +* [VBFPopFlatButton – Flat animatable button, using Pop to transition between states](https://github.com/victorBaro/VBFPopFlatButton) ## Contributing See the CONTRIBUTING file for how to help out. diff --git a/codecov.yml b/codecov.yml new file mode 100644 index 00000000..2363e8bc --- /dev/null +++ b/codecov.yml @@ -0,0 +1,10 @@ +coverage: + ignore: + - pop-tests/* + status: + patch: false + changes: false + project: + default: + target: 50 +comment: false diff --git a/pop-tests-osx/en.lproj/InfoPlist.strings b/pop-tests-osx/en.lproj/InfoPlist.strings deleted file mode 100644 index 477b28ff..00000000 --- a/pop-tests-osx/en.lproj/InfoPlist.strings +++ /dev/null @@ -1,2 +0,0 @@ -/* Localized versions of Info.plist keys */ - diff --git a/pop-tests-osx/pop-tests-OSX-Prefix.pch b/pop-tests-osx/pop-tests-OSX-Prefix.pch deleted file mode 100644 index 4187f19f..00000000 --- a/pop-tests-osx/pop-tests-OSX-Prefix.pch +++ /dev/null @@ -1,9 +0,0 @@ -// -// Prefix header -// -// The contents of this file are implicitly included at the beginning of every source file. -// - -#ifdef __OBJC__ - #import -#endif diff --git a/pop-tests/POPAnimatable.h b/pop-tests/POPAnimatable.h index 3783fae4..1272cba0 100644 --- a/pop-tests/POPAnimatable.h +++ b/pop-tests/POPAnimatable.h @@ -8,7 +8,9 @@ */ #import + #import + #import @interface POPAnimatable : NSObject diff --git a/pop-tests/POPAnimatable.mm b/pop-tests/POPAnimatable.mm index 00c10887..1bf4caab 100644 --- a/pop-tests/POPAnimatable.mm +++ b/pop-tests/POPAnimatable.mm @@ -9,13 +9,15 @@ #import "POPAnimatable.h" -#import +#import @implementation POPAnimatable { BOOL _recording; NSMutableDictionary *_recordedValuesDict; } +@synthesize radius = _radius; +@synthesize position = _position; static void record_value(POPAnimatable *self, NSString *key, id value) { diff --git a/pop-tests/POPAnimatablePropertyTests.mm b/pop-tests/POPAnimatablePropertyTests.mm index ac0dd576..fac6b06b 100644 --- a/pop-tests/POPAnimatablePropertyTests.mm +++ b/pop-tests/POPAnimatablePropertyTests.mm @@ -7,9 +7,9 @@ of patent rights can be found in the PATENTS file in the same directory. */ -#import +#import -#import +#import static const CGFloat epsilon = 0.0001f; static NSArray *properties = @[@"name", @"readBlock", @"writeBlock", @"threshold"]; @@ -19,11 +19,11 @@ static void assertPropertyEqual(id self, POPAnimatableProperty *prop1, POPAnimat for (NSString *property in properties) { id value = [prop1 valueForKey:property]; id valueCopy = [prop2 valueForKey:property]; - STAssertEqualObjects(value, valueCopy, @"unexpected inequality; value:%@ copy:%@", value, valueCopy); + XCTAssertEqualObjects(value, valueCopy, @"unexpected inequality; value:%@ copy:%@", value, valueCopy); } } -@interface POPAnimatablePropertyTests : SenTestCase +@interface POPAnimatablePropertyTests : XCTestCase @end @implementation POPAnimatablePropertyTests @@ -43,6 +43,18 @@ - (void)testProvidedExistence kPOPLayerRotation, kPOPLayerRotationY, kPOPLayerRotationX, + kPOPLayerShadowColor, + kPOPLayerShadowOffset, + kPOPLayerShadowOpacity, + kPOPLayerShadowRadius, + kPOPLayerCornerRadius, + kPOPLayerBorderWidth, + kPOPLayerBorderColor, + kPOPShapeLayerStrokeStart, + kPOPShapeLayerStrokeEnd, + kPOPShapeLayerStrokeColor, + kPOPShapeLayerLineWidth, + kPOPShapeLayerLineDashPhase, #if TARGET_OS_IPHONE kPOPViewAlpha, kPOPViewBackgroundColor, @@ -50,14 +62,29 @@ - (void)testProvidedExistence kPOPViewFrame, kPOPViewBounds, kPOPViewSize, + kPOPViewTintColor, + kPOPScrollViewZoomScale, kPOPTableViewContentSize, - kPOPTableViewContentOffset + kPOPTableViewContentOffset, + kPOPCollectionViewContentSize, + kPOPCollectionViewContentSize, + kPOPLabelTextColor +#else + kPOPViewFrame, + kPOPViewBounds, + kPOPViewAlphaValue, + kPOPViewFrameRotation, + kPOPViewFrameCenterRotation, + kPOPViewBoundsRotation, + kPOPWindowFrame, + kPOPWindowAlphaValue, + kPOPWindowBackgroundColor #endif ]; for (NSString *name in names) { POPAnimatableProperty *prop = [POPAnimatableProperty propertyWithName:name]; - STAssertNotNil(prop, @"animatable property %@ should exist", name); + XCTAssertNotNil(prop, @"animatable property %@ should exist", name); } } @@ -68,23 +95,23 @@ - (void)testUserCreation POPAnimatableProperty *prop; prop = [POPAnimatableProperty propertyWithName:name]; - STAssertNil(prop, @"animatable property %@ should not exist", name); + XCTAssertNil(prop, @"animatable property %@ should not exist", name); prop = [POPAnimatableProperty propertyWithName:name initializer:^(POPMutableAnimatableProperty *p){ p.threshold = threshold; }]; - STAssertNotNil(prop, @"animatable property %@ should exist", name); - STAssertEqualsWithAccuracy(threshold, prop.threshold, epsilon, @"property threshold %f should equal %f", prop.threshold, threshold); + XCTAssertNotNil(prop, @"animatable property %@ should exist", name); + XCTAssertEqualWithAccuracy(threshold, prop.threshold, epsilon, @"property threshold %f should equal %f", prop.threshold, threshold); } - (void)testClassCluster { POPAnimatableProperty *instance1 = [[POPAnimatableProperty alloc] init]; POPAnimatableProperty *instance2 = [[POPAnimatableProperty alloc] init]; - STAssertTrue(instance1 == instance2, @"instance1:%@ instance2:%@", instance1, instance2); + XCTAssertTrue(instance1 == instance2, @"instance1:%@ instance2:%@", instance1, instance2); for (NSString *property in properties) { - STAssertNoThrow([instance1 valueForKey:property], @"exception on %@", property); + XCTAssertNoThrow([instance1 valueForKey:property], @"exception on %@", property); } } diff --git a/pop-tests/POPAnimationMRRTests.mm b/pop-tests/POPAnimationMRRTests.mm index 405700ed..3a798488 100644 --- a/pop-tests/POPAnimationMRRTests.mm +++ b/pop-tests/POPAnimationMRRTests.mm @@ -10,13 +10,15 @@ #import #import -#import -#import +#import + +#import +#import #import "POPAnimationTestsExtras.h" -@interface POPAnimationMRRTests : SenTestCase +@interface POPAnimationMRRTests : XCTestCase { POPAnimator *_animator; CFTimeInterval _beginTime; @@ -30,6 +32,7 @@ - (void)setUp [super setUp]; _animator = [[POPAnimator sharedAnimator] retain]; _beginTime = CACurrentMediaTime(); + _animator.beginTime = _beginTime; } - (void)tearDown @@ -46,10 +49,10 @@ - (void)testZeroingDelegate @autoreleasepool { id delegate = [OCMockObject niceMockForProtocol:@protocol(POPAnimationDelegate)]; anim.delegate = delegate; - STAssertNotNil(anim.delegate, @"delegate should not be nil"); + XCTAssertNotNil(anim.delegate, @"delegate should not be nil"); } - STAssertNil(anim.delegate, @"delegate should be nil"); + XCTAssertNil(anim.delegate, @"delegate should be nil"); } - (void)testAnimationCancellationOnAnimatableDeallocation diff --git a/pop-tests/POPAnimationTests.mm b/pop-tests/POPAnimationTests.mm index 5a928df1..5c23eff6 100644 --- a/pop-tests/POPAnimationTests.mm +++ b/pop-tests/POPAnimationTests.mm @@ -10,16 +10,19 @@ #import #import -#import -#import -#import -#import +#import + +#import +#import +#import #import "POPAnimatable.h" #import "POPAnimationRuntime.h" #import "POPAnimationTestsExtras.h" #import "POPBaseAnimationTests.h" +#import "POPCGUtils.h" +#import "POPAnimationInternal.h" using namespace POP; @@ -39,15 +42,15 @@ @implementation POPAnimationTests - (void)testOrneryAbstractClasses { - STAssertThrows([[POPAnimation alloc] init], @"should not be able to instiate abstract class"); - STAssertThrows([[POPPropertyAnimation alloc] init], @"should not be able to instiate abstract class"); + XCTAssertThrows([[POPAnimation alloc] init], @"should not be able to instiate abstract class"); + XCTAssertThrows([[POPPropertyAnimation alloc] init], @"should not be able to instiate abstract class"); } - (void)testWithPropertyNamedConstruction { POPSpringAnimation *anim = [POPSpringAnimation animationWithPropertyNamed:kPOPLayerBounds]; POPAnimatableProperty *prop = [POPAnimatableProperty propertyWithName:kPOPLayerBounds]; - STAssertTrue(anim.property == prop, @"expected:%@ actual:%@", prop, anim.property); + XCTAssertTrue(anim.property == prop, @"expected:%@ actual:%@", prop, anim.property); } - (void)testAdditionRemoval @@ -61,22 +64,22 @@ - (void)testAdditionRemoval [layer1 pop_addAnimation:anim forKey:@"hello"]; NSArray *keys = [layer1 pop_animationKeys]; - STAssertTrue(1 == keys.count, nil); - STAssertTrue([@"hello" isEqualToString:keys.lastObject], nil); + XCTAssertTrue(1 == keys.count); + XCTAssertTrue([@"hello" isEqualToString:keys.lastObject]); [layer1 pop_removeAnimationForKey:@"hello"]; - STAssertTrue(0 == [layer1 pop_animationKeys].count, nil); + XCTAssertTrue(0 == [layer1 pop_animationKeys].count); [layer1 pop_addAnimation:FBTestLinearPositionAnimation(self.beginTime) forKey:@"hello"]; [layer1 pop_addAnimation:FBTestLinearPositionAnimation(self.beginTime) forKey:@"world"]; [layer2 pop_addAnimation:FBTestLinearPositionAnimation(self.beginTime) forKey:@"hello"]; - STAssertTrue(2 == [layer1 pop_animationKeys].count, nil); - STAssertTrue(1 == [layer2 pop_animationKeys].count, nil); + XCTAssertTrue(2 == [layer1 pop_animationKeys].count); + XCTAssertTrue(1 == [layer2 pop_animationKeys].count); [layer1 pop_removeAllAnimations]; - STAssertTrue(0 == [layer1 pop_animationKeys].count, nil); - STAssertTrue(1 == [layer2 pop_animationKeys].count, nil); + XCTAssertTrue(0 == [layer1 pop_animationKeys].count); + XCTAssertTrue(1 == [layer2 pop_animationKeys].count); } - (void)testStartStopDelegation @@ -118,6 +121,134 @@ - (void)testAnimationValues [layer verify]; } +- (void)testNoAutoreverseRepeatCount0 +{ + CALayer *layer1 = self.layer1; + [layer1 removeAllAnimations]; + + POPBasicAnimation *anim = FBTestLinearPositionAnimation(self.beginTime); + anim.repeatCount = 0; + anim.roundingFactor = 1.0; + anim.autoreverses = NO; + + NSValue *originalToValue = anim.toValue; + + [layer1 pop_addAnimation:anim forKey:@"key"]; + POPAnimatorRenderDuration(self.animator, self.beginTime, 2.0, 0.25); // animate longer than needed to verify animation has stopped in the appropriate place + + XCTAssertEqualObjects([layer1 valueForKeyPath:@"position"], originalToValue, @"expected equality; value1:%@ value2:%@", [layer1 valueForKey:@"position"], originalToValue); +} + +- (void)testNoAutoreverseRepeatCount1 +{ + CALayer *layer1 = self.layer1; + [layer1 removeAllAnimations]; + + POPBasicAnimation *anim = FBTestLinearPositionAnimation(self.beginTime); + anim.repeatCount = 1; + anim.roundingFactor = 1.0; + anim.autoreverses = NO; + + NSValue *originalToValue = anim.toValue; + + [layer1 pop_addAnimation:anim forKey:@"key"]; + POPAnimatorRenderDuration(self.animator, self.beginTime, 3.0, 0.25); // animate longer than needed to verify animation has stopped in the appropriate place + + XCTAssertEqualObjects([layer1 valueForKeyPath:@"position"], originalToValue, @"expected equality; value1:%@ value2:%@", [layer1 valueForKey:@"position"], originalToValue); +} + +- (void)testNoAutoreverseRepeatCount4 +{ + CALayer *layer1 = self.layer1; + [layer1 removeAllAnimations]; + + POPBasicAnimation *anim = FBTestLinearPositionAnimation(self.beginTime); + anim.repeatCount = 4; + anim.roundingFactor = 1.0; + anim.autoreverses = NO; + + NSValue *originalToValue = anim.toValue; + + [layer1 pop_addAnimation:anim forKey:@"key"]; + POPAnimatorRenderDuration(self.animator, self.beginTime, 6.0, 0.25); // animate longer than needed to verify animation has stopped in the appropriate place + + XCTAssertEqualObjects([layer1 valueForKeyPath:@"position"], originalToValue, @"expected equality; value1:%@ value2:%@", [layer1 valueForKey:@"position"], originalToValue); +} + +- (void)testAutoreverseRepeatCount0 +{ + CALayer *layer1 = self.layer1; + [layer1 removeAllAnimations]; + + POPBasicAnimation *anim = FBTestLinearPositionAnimation(self.beginTime); + anim.roundingFactor = 1.0; + anim.autoreverses = YES; + anim.repeatCount = 0; + [anim.tracer start]; + + NSValue *originalFromValue = anim.fromValue; + + [layer1 pop_addAnimation:anim forKey:@"key"]; + POPAnimatorRenderDuration(self.animator, self.beginTime, 3.0, 0.25); // animate longer than needed to verify animation has stopped in the appropriate place + + XCTAssertEqualObjects([layer1 valueForKey:@"position"], originalFromValue, @"expected equality; value1:%@ value2:%@", [layer1 valueForKey:@"position"], originalFromValue); + + NSArray *autoreversedEvents = [anim.tracer eventsWithType:kPOPAnimationEventAutoreversed]; + XCTAssertTrue(1 == autoreversedEvents.count, @"unexpected autoreversed events %@", autoreversedEvents); + + anim.autoreverses = NO; +} + +- (void)testAutoreverseRepeatCount1 +{ + CALayer *layer1 = self.layer1; + [layer1 removeAllAnimations]; + + POPBasicAnimation *anim = FBTestLinearPositionAnimation(self.beginTime); + anim.roundingFactor = 1.0; + anim.autoreverses = YES; + anim.repeatCount = 1; + [anim.tracer start]; + + NSValue *originalFromValue = anim.fromValue; + + [layer1 pop_addAnimation:anim forKey:@"key"]; + POPAnimatorRenderDuration(self.animator, self.beginTime, 3.0, 0.25); // animate longer than needed to verify animation has stopped in the appropriate place + + XCTAssertEqualObjects([layer1 valueForKey:@"position"], originalFromValue, @"expected equality; value1:%@ value2:%@", [layer1 valueForKey:@"position"], originalFromValue); + + NSArray *autoreversedEvents = [anim.tracer eventsWithType:kPOPAnimationEventAutoreversed]; + XCTAssertTrue(1 == autoreversedEvents.count, @"unexpected autoreversed events %@", autoreversedEvents); + + anim.autoreverses = NO; +} + +- (void)testAutoreverseRepeatCount4 +{ + CALayer *layer1 = self.layer1; + [layer1 removeAllAnimations]; + + POPBasicAnimation *anim = FBTestLinearPositionAnimation(self.beginTime); + anim.roundingFactor = 1.0; + anim.autoreverses = YES; + + NSInteger repeatCount = 4; + anim.repeatCount = repeatCount; + [anim.tracer start]; + + NSValue *originalFromValue = anim.fromValue; + + [layer1 pop_addAnimation:anim forKey:@"key"]; + POPAnimatorRenderDuration(self.animator, self.beginTime, 9.0, 0.25); // animate longer than needed to verify animation has stopped in the appropriate place + + XCTAssertEqualObjects([layer1 valueForKey:@"position"], originalFromValue, @"expected equality; value1:%@ value2:%@", [layer1 valueForKey:@"position"], originalFromValue); + + NSArray *autoreversedEvents = [anim.tracer eventsWithType:kPOPAnimationEventAutoreversed]; + XCTAssertTrue((repeatCount * 2) - 1 == (int)autoreversedEvents.count, @"unexpected autoreversed events %@", autoreversedEvents); + + anim.autoreverses = NO; +} + - (void)testReAddition { CALayer *layer1 = self.layer1; @@ -157,6 +288,46 @@ - (void)testReAddition [delegate2 verify]; } +- (void)testAnimationDidStartBlock +{ + CALayer *layer1 = self.layer1; + [layer1 removeAllAnimations]; + + POPAnimation *anim = FBTestLinearPositionAnimation(self.beginTime); + id delegate = [OCMockObject niceMockForProtocol:@protocol(POPAnimationDelegate)]; + + // set animation did start block + anim.animationDidStartBlock = ^(POPAnimation *a) { + [delegate pop_animationDidStart:a]; + }; + + [[delegate expect] pop_animationDidStart:anim]; + + [layer1 pop_addAnimation:anim forKey:@"key"]; + POPAnimatorRenderTimes(self.animator, self.beginTime, @[@0.0, @1.0]); + [delegate verify]; +} + +- (void)testAnimationDidReachToValueBlock +{ + CALayer *layer1 = self.layer1; + [layer1 removeAllAnimations]; + + POPAnimation *anim = FBTestLinearPositionAnimation(self.beginTime); + id delegate = [OCMockObject niceMockForProtocol:@protocol(POPAnimationDelegate)]; + + // set animation did reach to value block + anim.animationDidReachToValueBlock = ^(POPAnimation *a) { + [delegate pop_animationDidReachToValue:a]; + }; + + [[delegate expect] pop_animationDidReachToValue:anim]; + + [layer1 pop_addAnimation:anim forKey:@"key"]; + POPAnimatorRenderTimes(self.animator, self.beginTime, @[@0.0, @1.0]); + [delegate verify]; +} + - (void)testCompletionBlock { CALayer *layer1 = self.layer1; @@ -192,6 +363,26 @@ - (void)testCompletionBlock [delegate verify]; } +- (void)testAnimationDidApplyBlock +{ + CALayer *layer1 = self.layer1; + [layer1 removeAllAnimations]; + + POPAnimation *anim = FBTestLinearPositionAnimation(self.beginTime); + id delegate = [OCMockObject niceMockForProtocol:@protocol(POPAnimationDelegate)]; + + // set animation did apply block + anim.animationDidApplyBlock = ^(POPAnimation *a) { + [delegate pop_animationDidApply:a]; + }; + + [[delegate expect] pop_animationDidApply:anim]; + + [layer1 pop_addAnimation:anim forKey:@"key"]; + POPAnimatorRenderTimes(self.animator, self.beginTime, @[@0.0, @1.0]); + [delegate verify]; +} + - (void)testReuse { NSValue *fromValue = [NSValue valueWithCGPoint:CGPointMake(100, 100)]; @@ -238,28 +429,43 @@ - (void)testReuse [delegate verify]; } +- (void)testCancelBeforeBegin +{ + POPAnimation *anim = FBTestLinearPositionAnimation(self.beginTime + 100000); + [anim.tracer start]; + + CALayer *layer = [CALayer layer]; + [layer pop_addAnimation:anim forKey:@"key"]; + [layer pop_removeAllAnimations]; + + NSArray *didStartEvents = [anim.tracer eventsWithType:kPOPAnimationEventDidStart]; + NSArray *didStopEvents = [anim.tracer eventsWithType:kPOPAnimationEventDidStop]; + XCTAssertTrue(1 == didStartEvents.count, @"unexpected start events %@", didStartEvents); + XCTAssertTrue(1 == didStopEvents.count, @"unexpected stop events %@", didStopEvents); +} + - (void)testAddedKeys { POPAnimation *anim = FBTestLinearPositionAnimation(); anim.sampleKey = @"value"; - STAssertEqualObjects(anim.sampleKey, @"value", @"property value read should equal write"); + XCTAssertEqualObjects(anim.sampleKey, @"value", @"property value read should equal write"); } - (void)testValueTypeResolution { POPSpringAnimation *anim = [POPSpringAnimation animation]; - STAssertNil(anim.fromValue, nil); - STAssertNil(anim.toValue, nil); - STAssertNil(anim.velocity, nil); + XCTAssertNil(anim.fromValue); + XCTAssertNil(anim.toValue); + XCTAssertNil(anim.velocity); id pointValue = [NSValue valueWithCGPoint:CGPointMake(1, 2)]; anim.fromValue = pointValue; anim.toValue = pointValue; anim.velocity = pointValue; - STAssertEqualObjects(anim.fromValue, pointValue, @"property value read should equal write"); - STAssertEqualObjects(anim.toValue, pointValue, @"property value read should equal write"); - STAssertEqualObjects(anim.velocity, pointValue, @"property value read should equal write"); + XCTAssertEqualObjects(anim.fromValue, pointValue, @"property value read should equal write"); + XCTAssertEqualObjects(anim.toValue, pointValue, @"property value read should equal write"); + XCTAssertEqualObjects(anim.velocity, pointValue, @"property value read should equal write"); POPSpringAnimation *anim2 = [POPSpringAnimation animation]; @@ -268,13 +474,28 @@ - (void)testValueTypeResolution anim2.toValue = rectValue; anim2.velocity = rectValue; - STAssertEqualObjects(anim2.fromValue, rectValue, @"property value read should equal write"); - STAssertEqualObjects(anim2.toValue, rectValue, @"property value read should equal write"); - STAssertEqualObjects(anim2.velocity, rectValue, @"property value read should equal write"); + XCTAssertEqualObjects(anim2.fromValue, rectValue, @"property value read should equal write"); + XCTAssertEqualObjects(anim2.toValue, rectValue, @"property value read should equal write"); + XCTAssertEqualObjects(anim2.velocity, rectValue, @"property value read should equal write"); + +#if TARGET_OS_IPHONE POPSpringAnimation *anim3 = [POPSpringAnimation animation]; + + id edgeInsetsValue = [NSValue valueWithUIEdgeInsets:UIEdgeInsetsMake(20, 40, 20, 40)]; + anim3.fromValue = edgeInsetsValue; + anim3.toValue = edgeInsetsValue; + anim3.velocity = edgeInsetsValue; + + XCTAssertEqualObjects(anim3.fromValue, edgeInsetsValue, @"property value read should equal write"); + XCTAssertEqualObjects(anim3.toValue, edgeInsetsValue, @"property value read should equal write"); + XCTAssertEqualObjects(anim3.velocity, edgeInsetsValue, @"property value read should equal write"); + +#endif + + POPSpringAnimation *anim4 = [POPSpringAnimation animation]; id transformValue = [NSValue valueWithCATransform3D:CATransform3DIdentity]; - STAssertThrows(anim3.fromValue = transformValue, @"should not be able to set %@", transformValue); + XCTAssertThrows(anim4.fromValue = transformValue, @"should not be able to set %@", transformValue); } - (void)testTracer @@ -282,7 +503,7 @@ - (void)testTracer POPAnimatable *circle = [POPAnimatable new]; POPSpringAnimation *anim = [POPSpringAnimation animation]; POPAnimationTracer *tracer = anim.tracer; - STAssertNotNil(tracer, @"missing tracer"); + XCTAssertNotNil(tracer, @"missing tracer"); [tracer start]; NSNumber *animFromValue = @0.0; @@ -323,71 +544,71 @@ - (void)testTracer NSArray *writeEvents = [tracer eventsWithType:kPOPAnimationEventPropertyWrite]; // all events - STAssertTrue(0 != allEvents.count, @"unexpected allEvents count %@", allEvents); + XCTAssertTrue(0 != allEvents.count, @"unexpected allEvents count %@", allEvents); // from events - STAssertTrue(1 == fromEvents.count, @"unexpected fromEvents count %@", fromEvents); + XCTAssertTrue(1 == fromEvents.count, @"unexpected fromEvents count %@", fromEvents); id eventFromValue = [(POPAnimationValueEvent *)fromEvents.lastObject value]; - STAssertEqualObjects(animFromValue, eventFromValue, @"unexpected eventFromValue; expected:%@ actual:%@", animFromValue, eventFromValue); + XCTAssertEqualObjects(animFromValue, eventFromValue, @"unexpected eventFromValue; expected:%@ actual:%@", animFromValue, eventFromValue); // to events - STAssertTrue(1 == toEvents.count, @"unexpected toEvents count %@", toEvents); + XCTAssertTrue(1 == toEvents.count, @"unexpected toEvents count %@", toEvents); id eventToValue = [(POPAnimationValueEvent *)toEvents.lastObject value]; - STAssertEqualObjects(animToValue, eventToValue, @"unexpected eventToValue; expected:%@ actual:%@", animToValue, eventToValue); + XCTAssertEqualObjects(animToValue, eventToValue, @"unexpected eventToValue; expected:%@ actual:%@", animToValue, eventToValue); // velocity events - STAssertTrue(1 == velocityEvents.count, @"unexpected velocityEvents count %@", velocityEvents); + XCTAssertTrue(1 == velocityEvents.count, @"unexpected velocityEvents count %@", velocityEvents); id eventVelocity = [(POPAnimationValueEvent *)velocityEvents.lastObject value]; - STAssertEqualObjects(animVelocity, eventVelocity, @"unexpected eventVelocity; expected:%@ actual:%@", animVelocity, eventVelocity); + XCTAssertEqualObjects(animVelocity, eventVelocity, @"unexpected eventVelocity; expected:%@ actual:%@", animVelocity, eventVelocity); // bounciness events - STAssertTrue(1 == bouncinessEvents.count, @"unexpected bouncinessEvents count %@", bouncinessEvents); + XCTAssertTrue(1 == bouncinessEvents.count, @"unexpected bouncinessEvents count %@", bouncinessEvents); id eventBounciness = [(POPAnimationValueEvent *)bouncinessEvents.lastObject value]; - STAssertEqualObjects(@(animBounciness), eventBounciness, @"unexpected bounciness; expected:%@ actual:%@", @(animBounciness), eventBounciness); + XCTAssertEqualObjects(@(animBounciness), eventBounciness, @"unexpected bounciness; expected:%@ actual:%@", @(animBounciness), eventBounciness); // speed events - STAssertTrue(1 == speedEvents.count, @"unexpected speedEvents count %@", speedEvents); + XCTAssertTrue(1 == speedEvents.count, @"unexpected speedEvents count %@", speedEvents); id eventSpeed = [(POPAnimationValueEvent *)speedEvents.lastObject value]; - STAssertEqualObjects(@(animSpeed), eventSpeed, @"unexpected speed; expected:%@ actual:%@", @(animSpeed), eventSpeed); + XCTAssertEqualObjects(@(animSpeed), eventSpeed, @"unexpected speed; expected:%@ actual:%@", @(animSpeed), eventSpeed); // friction events - STAssertTrue(1 == frictionEvents.count, @"unexpected frictionEvents count %@", frictionEvents); + XCTAssertTrue(1 == frictionEvents.count, @"unexpected frictionEvents count %@", frictionEvents); id eventFriction = [(POPAnimationValueEvent *)frictionEvents.lastObject value]; - STAssertEqualObjects(@(animFriction), eventFriction, @"unexpected friction; expected:%@ actual:%@", @(animFriction), eventFriction); + XCTAssertEqualObjects(@(animFriction), eventFriction, @"unexpected friction; expected:%@ actual:%@", @(animFriction), eventFriction); // mass events - STAssertTrue(1 == massEvents.count, @"unexpected massEvents count %@", massEvents); + XCTAssertTrue(1 == massEvents.count, @"unexpected massEvents count %@", massEvents); id eventMass = [(POPAnimationValueEvent *)massEvents.lastObject value]; - STAssertEqualObjects(@(animMass), eventMass, @"unexpected mass; expected:%@ actual:%@", @(animMass), eventMass); + XCTAssertEqualObjects(@(animMass), eventMass, @"unexpected mass; expected:%@ actual:%@", @(animMass), eventMass); // tension events - STAssertTrue(1 == tensionEvents.count, @"unexpected tensionEvents count %@", tensionEvents); + XCTAssertTrue(1 == tensionEvents.count, @"unexpected tensionEvents count %@", tensionEvents); id eventTension = [(POPAnimationValueEvent *)tensionEvents.lastObject value]; - STAssertEqualObjects(@(animTension), eventTension, @"unexpected tension; expected:%@ actual:%@", @(animTension), eventTension); + XCTAssertEqualObjects(@(animTension), eventTension, @"unexpected tension; expected:%@ actual:%@", @(animTension), eventTension); // start & stop event - STAssertTrue(1 == startEvents.count, @"unexpected startEvents count %@", startEvents); - STAssertTrue(1 == stopEvents.count, @"unexpected stopEvents count %@", stopEvents); + XCTAssertTrue(1 == startEvents.count, @"unexpected startEvents count %@", startEvents); + XCTAssertTrue(1 == stopEvents.count, @"unexpected stopEvents count %@", stopEvents); // start before stop NSUInteger startIdx = [allEvents indexOfObjectIdenticalTo:startEvents.firstObject]; NSUInteger stopIdx = [allEvents indexOfObjectIdenticalTo:stopEvents.firstObject]; - STAssertTrue(startIdx < stopIdx, @"unexpected start/stop ordering startIdx:%d stopIdx:%d", startIdx, stopIdx); + XCTAssertTrue(startIdx < stopIdx, @"unexpected start/stop ordering startIdx:%lu stopIdx:%lu", (unsigned long)startIdx, (unsigned long)stopIdx); // did reach event - STAssertTrue(1 == didReachEvents.count, @"unexpected didReachEvents %@", didReachEvents); + XCTAssertTrue(1 == didReachEvents.count, @"unexpected didReachEvents %@", didReachEvents); // did reach after start before stop NSUInteger didReachIdx = [allEvents indexOfObjectIdenticalTo:didReachEvents.firstObject]; - STAssertTrue(didReachIdx > startIdx, @"unexpected didReach/start ordering didReachIdx:%d startIdx:%d", didReachIdx, startIdx); - STAssertTrue(didReachIdx < stopIdx, @"unexpected didReach/stop ordering didReachIdx:%d stopIdx:%d", didReachIdx, stopIdx); + XCTAssertTrue(didReachIdx > startIdx, @"unexpected didReach/start ordering didReachIdx:%lu startIdx:%lu", (unsigned long)didReachIdx, (unsigned long)startIdx); + XCTAssertTrue(didReachIdx < stopIdx, @"unexpected didReach/stop ordering didReachIdx:%lu stopIdx:%lu", (unsigned long)didReachIdx, (unsigned long)stopIdx); // write events - STAssertTrue(0 != writeEvents.count, @"unexpected writeEvents count %@", writeEvents); + XCTAssertTrue(0 != writeEvents.count, @"unexpected writeEvents count %@", writeEvents); id firstWriteValue = [(POPAnimationValueEvent *)writeEvents.firstObject value]; - STAssertTrue(NSOrderedAscending == [anim.fromValue compare:firstWriteValue], @"unexpected firstWriteValue; fromValue:%@ actual:%@", anim.fromValue, firstWriteValue); + XCTAssertTrue(NSOrderedSame == [anim.fromValue compare:firstWriteValue], @"unexpected firstWriteValue; fromValue:%@ actual:%@", anim.fromValue, firstWriteValue); id lastWriteValue = [(POPAnimationValueEvent *)writeEvents.lastObject value]; - STAssertEqualObjects(lastWriteValue, anim.toValue, @"unexpected lastWriteValue; expected:%@ actual:%@", anim.toValue, lastWriteValue); + XCTAssertEqualObjects(lastWriteValue, anim.toValue, @"unexpected lastWriteValue; expected:%@ actual:%@", anim.toValue, lastWriteValue); } - (void)testAnimationContinuation @@ -410,8 +631,8 @@ - (void)testAnimationContinuation NSArray *stopEvents = [tracer eventsWithType:kPOPAnimationEventDidStop]; // assert did reach but not stop - STAssertTrue(1 == didReachToEvents.count, @"unexpected didReachToEvents count %@", didReachToEvents); - STAssertTrue(0 == stopEvents.count, @"unexpected stopEvents count %@", stopEvents); + XCTAssertTrue(1 == didReachToEvents.count, @"unexpected didReachToEvents count %@", didReachToEvents); + XCTAssertTrue(0 == stopEvents.count, @"unexpected stopEvents count %@", stopEvents); // update to value continuing animation anim.toValue = @0.0; @@ -420,20 +641,20 @@ - (void)testAnimationContinuation // two did reach to events didReachToEvents = [tracer eventsWithType:kPOPAnimationEventDidReachToValue]; - STAssertTrue(2 == didReachToEvents.count, @"unexpected didReachToEvents count %@", didReachToEvents); + XCTAssertTrue(2 == didReachToEvents.count, @"unexpected didReachToEvents count %@", didReachToEvents); // first event value > animation to value id firstDidReachValue = [(POPAnimationValueEvent *)didReachToEvents.firstObject value]; - STAssertTrue(NSOrderedAscending == [anim.toValue compare:firstDidReachValue], @"unexpected firstDidReachValue; toValue:%@ actual:%@", anim.toValue, firstDidReachValue); + XCTAssertTrue(NSOrderedAscending == [anim.toValue compare:firstDidReachValue], @"unexpected firstDidReachValue; toValue:%@ actual:%@", anim.toValue, firstDidReachValue); // second event value < animation to value id lastDidReachValue = [(POPAnimationValueEvent *)didReachToEvents.lastObject value]; - STAssertTrue(NSOrderedDescending == [anim.toValue compare:lastDidReachValue], @"unexpected lastDidReachValue; toValue:%@ actual:%@", anim.toValue, lastDidReachValue); + XCTAssertTrue(NSOrderedDescending == [anim.toValue compare:lastDidReachValue], @"unexpected lastDidReachValue; toValue:%@ actual:%@", anim.toValue, lastDidReachValue); // did stop event stopEvents = [tracer eventsWithType:kPOPAnimationEventDidStop]; - STAssertTrue(1 == stopEvents.count, @"unexpected stopEvents count %@", stopEvents); - STAssertEqualObjects([(POPAnimationValueEvent *)stopEvents.lastObject value], @YES, @"unexpected stop event: %@", stopEvents.lastObject); + XCTAssertTrue(1 == stopEvents.count, @"unexpected stopEvents count %@", stopEvents); + XCTAssertEqualObjects([(POPAnimationValueEvent *)stopEvents.lastObject value], @YES, @"unexpected stop event: %@", stopEvents.lastObject); } - (void)testRoundingFactor @@ -460,7 +681,7 @@ - (void)testRoundingFactor NSArray *writeEvents = [tracer eventsWithType:kPOPAnimationEventPropertyWrite]; BOOL containValue = POPAnimationEventsContainValue(writeEvents, @0.5); - STAssertFalse(containValue, @"unexpected write value %@", writeEvents); + XCTAssertFalse(containValue, @"unexpected write value %@", writeEvents); if (!additive) { additive = YES; @@ -487,7 +708,7 @@ - (void)testRoundingFactor NSArray *writeEvents = [tracer eventsWithType:kPOPAnimationEventPropertyWrite]; BOOL containValue = POPAnimationEventsContainValue(writeEvents, @0.5); - STAssertTrue(containValue, @"unexpected write value %@", writeEvents); + XCTAssertTrue(containValue, @"unexpected write value %@", writeEvents); if (!additive) { additive = YES; @@ -521,8 +742,8 @@ - (void)testAdditiveAnimation CGFloat firstValue = [[writeEvents firstObject] floatValue]; CGFloat lastValue = [[writeEvents lastObject] floatValue]; - STAssertTrue(firstValue >= baseValue + fromValue, @"write value expected:%f actual:%f", baseValue + fromValue, firstValue); - STAssertTrue(lastValue == baseValue + toValue, @"write value expected:%f actual:%f", baseValue + toValue, lastValue); + XCTAssertTrue(firstValue >= baseValue + fromValue, @"write value expected:%f actual:%f", baseValue + fromValue, firstValue); + XCTAssertTrue(lastValue == baseValue + toValue, @"write value expected:%f actual:%f", baseValue + toValue, lastValue); } - (void)testNilKey @@ -542,7 +763,7 @@ - (void)testNilKey [layer pop_addAnimation:anim forKey:nil]; // verify attempting to remove nil key is a noop, same as CA - STAssertNoThrow([layer pop_removeAnimationForKey:nil], @"unexpected exception"); + XCTAssertNoThrow([layer pop_removeAnimationForKey:nil], @"unexpected exception"); POPAnimatorRenderDuration(self.animator, self.beginTime, 1, 0.25); [layer verify]; @@ -557,60 +778,114 @@ - (void)testIntegerAnimation // literal anim = [POPBasicAnimation animationWithPropertyNamed:kPOPLayerOpacity]; - STAssertNoThrow(anim.toValue = @(toValue), @"unexpected exception"); - STAssertEqualObjects(anim.toValue, boxedToValue, @"expected equality; value1:%@ value2:%@", anim.toValue, boxedToValue); + XCTAssertNoThrow(anim.toValue = @(toValue), @"unexpected exception"); + XCTAssertEqualObjects(anim.toValue, boxedToValue, @"expected equality; value1:%@ value2:%@", anim.toValue, boxedToValue); // integer anim = [POPBasicAnimation animationWithPropertyNamed:kPOPLayerOpacity]; - STAssertNoThrow(anim.toValue = @(toValue), @"unexpected exception"); - STAssertEqualObjects(anim.toValue, boxedToValue, @"expected equality; value1:%@ value2:%@", anim.toValue, boxedToValue); + XCTAssertNoThrow(anim.toValue = @(toValue), @"unexpected exception"); + XCTAssertEqualObjects(anim.toValue, boxedToValue, @"expected equality; value1:%@ value2:%@", anim.toValue, boxedToValue); // short anim = [POPBasicAnimation animationWithPropertyNamed:kPOPLayerOpacity]; - STAssertNoThrow(anim.toValue = @(toValue), @"unexpected exception"); - STAssertEqualObjects(anim.toValue, boxedToValue, @"expected equality; value1:%@ value2:%@", anim.toValue, boxedToValue); + XCTAssertNoThrow(anim.toValue = @(toValue), @"unexpected exception"); + XCTAssertEqualObjects(anim.toValue, boxedToValue, @"expected equality; value1:%@ value2:%@", anim.toValue, boxedToValue); // unsigned short anim = [POPBasicAnimation animationWithPropertyNamed:kPOPLayerOpacity]; - STAssertNoThrow(anim.toValue = @(toValue), @"unexpected exception"); - STAssertEqualObjects(anim.toValue, boxedToValue, @"expected equality; value1:%@ value2:%@", anim.toValue, boxedToValue); + XCTAssertNoThrow(anim.toValue = @(toValue), @"unexpected exception"); + XCTAssertEqualObjects(anim.toValue, boxedToValue, @"expected equality; value1:%@ value2:%@", anim.toValue, boxedToValue); // int anim = [POPBasicAnimation animationWithPropertyNamed:kPOPLayerOpacity]; - STAssertNoThrow(anim.toValue = @(toValue), @"unexpected exception"); - STAssertEqualObjects(anim.toValue, boxedToValue, @"expected equality; value1:%@ value2:%@", anim.toValue, boxedToValue); + XCTAssertNoThrow(anim.toValue = @(toValue), @"unexpected exception"); + XCTAssertEqualObjects(anim.toValue, boxedToValue, @"expected equality; value1:%@ value2:%@", anim.toValue, boxedToValue); // unsigned int anim = [POPBasicAnimation animationWithPropertyNamed:kPOPLayerOpacity]; - STAssertNoThrow(anim.toValue = @(toValue), @"unexpected exception"); - STAssertEqualObjects(anim.toValue, boxedToValue, @"expected equality; value1:%@ value2:%@", anim.toValue, boxedToValue); + XCTAssertNoThrow(anim.toValue = @(toValue), @"unexpected exception"); + XCTAssertEqualObjects(anim.toValue, boxedToValue, @"expected equality; value1:%@ value2:%@", anim.toValue, boxedToValue); // long anim = [POPBasicAnimation animationWithPropertyNamed:kPOPLayerOpacity]; - STAssertNoThrow(anim.toValue = @(toValue), @"unexpected exception"); - STAssertEqualObjects(anim.toValue, boxedToValue, @"expected equality; value1:%@ value2:%@", anim.toValue, boxedToValue); + XCTAssertNoThrow(anim.toValue = @(toValue), @"unexpected exception"); + XCTAssertEqualObjects(anim.toValue, boxedToValue, @"expected equality; value1:%@ value2:%@", anim.toValue, boxedToValue); // unsigned long anim = [POPBasicAnimation animationWithPropertyNamed:kPOPLayerOpacity]; - STAssertNoThrow(anim.toValue = @(toValue), @"unexpected exception"); - STAssertEqualObjects(anim.toValue, boxedToValue, @"expected equality; value1:%@ value2:%@", anim.toValue, boxedToValue); + XCTAssertNoThrow(anim.toValue = @(toValue), @"unexpected exception"); + XCTAssertEqualObjects(anim.toValue, boxedToValue, @"expected equality; value1:%@ value2:%@", anim.toValue, boxedToValue); anim.fromValue = @0; POPAnimationTracer *tracer = anim.tracer; [tracer start]; CALayer *layer = [CALayer layer]; - layer.opacity = 0; [layer pop_addAnimation:anim forKey:nil]; - POPAnimatorRenderDuration(self.animator, self.beginTime, 1, 0.1); + POPAnimatorRenderDuration(self.animator, self.beginTime + 0.1, 1, 0.1); // verify writes happened NSArray *writeEvents = tracer.writeEvents; - STAssertTrue(writeEvents.count == 5, @"unexpected events:%@", writeEvents); + XCTAssertTrue(writeEvents.count == 5, @"unexpected events:%@", writeEvents); + + // verify initial value + POPAnimationValueEvent *firstWriteEvent = writeEvents.firstObject; + XCTAssertTrue([firstWriteEvent.value isEqual:anim.fromValue], @"expected equality; value1:%@ value%@", firstWriteEvent.value, anim.fromValue); // verify final value - STAssertEqualObjects([layer valueForKey:@"opacity"], anim.toValue, @"expected equality; value1:%@ value2:%@", [layer valueForKey:@"opacity"], anim.toValue); + XCTAssertEqualObjects([layer valueForKey:@"opacity"], anim.toValue, @"expected equality; value1:%@ value2:%@", [layer valueForKey:@"opacity"], anim.toValue); +} + +- (void)testPlatformColorSupport +{ + POPSpringAnimation *anim = [POPSpringAnimation animationWithPropertyNamed:kPOPLayerBackgroundColor]; + +#if TARGET_OS_IPHONE + XCTAssertNoThrow(anim.fromValue = [UIColor whiteColor], @"unexpected exception"); + XCTAssertNoThrow(anim.toValue = [UIColor redColor], @"unexpected exception"); +#else + XCTAssertNoThrow(anim.fromValue = [NSColor whiteColor], @"unexpected exception"); + XCTAssertNoThrow(anim.toValue = [NSColor redColor], @"unexpected exception"); +#endif + + POPAnimationTracer *tracer = anim.tracer; + [tracer start]; + + CALayer *layer = [CALayer layer]; + [layer pop_addAnimation:anim forKey:@"color"]; + POPAnimatorRenderDuration(self.animator, self.beginTime, 1, 0.1); + + // expect some interpolation + NSArray *writeEvents = tracer.writeEvents; + XCTAssertTrue(writeEvents.count > 1, @"unexpected write events %@", writeEvents); + + // get layer color components + CGFloat layerValues[4]; + POPCGColorGetRGBAComponents(layer.backgroundColor, layerValues); + + // get to color components + CGFloat toValues[4]; + POPCGColorGetRGBAComponents((__bridge CGColorRef)anim.toValue, toValues); + + // assert equality + XCTAssertTrue(layerValues[0] == toValues[0] && layerValues[1] == toValues[1] && layerValues[2] == toValues[2] && layerValues[3] == toValues[3], @"unexpected last color: [r:%f g:%f b:%f a:%f]", layerValues[0], layerValues[1], layerValues[2], layerValues[3]); +} + +- (void)testNSCopyingSupportPOPBasicAnimation +{ + POPBasicAnimation *anim = [POPBasicAnimation animationWithPropertyNamed:@"test_property_name"]; + + configureConcretePropertyAnimation(anim); + [self testCopyingSucceedsForConcretePropertyAnimation:anim]; + + anim.duration = 1.8; + anim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; + + POPBasicAnimation *copy = [anim copy]; + + XCTAssertEqual(copy.duration, anim.duration, @"expected equality; value1:%@ value2:%@", @(copy.duration), @(anim.duration)); + XCTAssertEqualObjects(copy.timingFunction, anim.timingFunction, @"expected equality; value1:%@ value2:%@", copy.timingFunction, anim.timingFunction); } @end diff --git a/pop-tests/POPAnimationTestsExtras.h b/pop-tests/POPAnimationTestsExtras.h index 3d95fd55..6d0639b8 100644 --- a/pop-tests/POPAnimationTestsExtras.h +++ b/pop-tests/POPAnimationTestsExtras.h @@ -11,6 +11,7 @@ @class POPAnimator; @class POPBasicAnimation; +extern void POPAnimatorRenderTime(POPAnimator *animator, CFTimeInterval beginTime, CFTimeInterval time); extern void POPAnimatorRenderTimes(POPAnimator *animator, CFTimeInterval beginTime, NSArray *times); extern void POPAnimatorRenderDuration(POPAnimator *animator, CFAbsoluteTime beginTime, CFTimeInterval duration, CFTimeInterval step); diff --git a/pop-tests/POPAnimationTestsExtras.mm b/pop-tests/POPAnimationTestsExtras.mm index 1a20f32f..61edfc19 100644 --- a/pop-tests/POPAnimationTestsExtras.mm +++ b/pop-tests/POPAnimationTestsExtras.mm @@ -9,8 +9,13 @@ #import "POPAnimationTestsExtras.h" -#import -#import +#import +#import + +void POPAnimatorRenderTime(POPAnimator *animator, CFTimeInterval beginTime, CFTimeInterval time) +{ + [animator renderTime:beginTime + time]; +} void POPAnimatorRenderTimes(POPAnimator *animator, CFTimeInterval beginTime, NSArray *times) { @@ -21,12 +26,15 @@ void POPAnimatorRenderTimes(POPAnimator *animator, CFTimeInterval beginTime, NSA void POPAnimatorRenderDuration(POPAnimator *animator, CFTimeInterval beginTime, CFTimeInterval duration, CFTimeInterval step) { + CFTimeInterval initialTime = animator.beginTime; + animator.beginTime = beginTime; NSCAssert(step > 0, @"unexpected step %f", step); CFTimeInterval time = 0; while(time <= duration) { [animator renderTime:beginTime + time]; time += step; } + animator.beginTime = initialTime; } POPBasicAnimation *FBTestLinearPositionAnimation(CFTimeInterval beginTime) diff --git a/pop-tests/POPBaseAnimationTests.h b/pop-tests/POPBaseAnimationTests.h index 75bff862..d244c151 100644 --- a/pop-tests/POPBaseAnimationTests.h +++ b/pop-tests/POPBaseAnimationTests.h @@ -7,13 +7,19 @@ of patent rights can be found in the PATENTS file in the same directory. */ -#import +#import + +#import + +#import "POPCGUtils.h" @class CALayer; @class POPAnimator; @class POPAnimatableProperty; +@class POPAnimation; +@class POPPropertyAnimation; -@interface POPBaseAnimationTests : SenTestCase +@interface POPBaseAnimationTests : XCTestCase // two layers for test use @property (strong, nonatomic) CALayer *layer1, *layer2; @@ -27,6 +33,9 @@ // radius animatable property @property (strong, nonatomic) POPAnimatableProperty *radiusProperty; +- (void)testCopyingSucceedsForConcreteAnimation:(POPAnimation *)anim; +- (void)testCopyingSucceedsForConcretePropertyAnimation:(POPPropertyAnimation *)anim; + @end // max frame count required for animations to converge @@ -37,3 +46,18 @@ extern NSUInteger POPAnimationCountLastEventValues(NSArray *events, NSNumber *va // returns YES if array of value events contain specified value extern BOOL POPAnimationEventsContainValue(NSArray *events, NSNumber *value); + +// equality with epsilon +#define _EQL_(x, y, epsilon) (std::abs ((x) - (y)) < epsilon) + +// color equality assert +#define POPAssertColorEqual(c1, c2) \ +{ \ + CGFloat v1[4], v2[4]; \ + POPCGColorGetRGBAComponents(c1, v1); \ + POPCGColorGetRGBAComponents(c2, v2); \ + XCTAssertTrue(_EQL_(v1[0], v2[0], 1e-6) && _EQL_(v1[1], v2[1], 1e-6) && _EQL_(v1[2], v2[2], 1e-6) && _EQL_(v1[3], v2[3], 1e-6), @"not equal color:[r:%f g:%f b:%f a:%f] color:[r:%f g:%f b:%f a:%f]", v1[0], v1[1], v1[2], v1[3], v2[0], v2[1], v2[2], v2[3]); \ +} + +extern void configureConcreteAnimation(POPAnimation *anim); +extern void configureConcretePropertyAnimation(POPPropertyAnimation *anim); diff --git a/pop-tests/POPBaseAnimationTests.mm b/pop-tests/POPBaseAnimationTests.mm index 3ae112a1..2bac4f8d 100644 --- a/pop-tests/POPBaseAnimationTests.mm +++ b/pop-tests/POPBaseAnimationTests.mm @@ -13,10 +13,12 @@ #import -#import +#import +#import #import "POPAnimatable.h" #import "POPAnimationTestsExtras.h" +#import "POPAnimationInternal.h" @implementation POPBaseAnimationTests { @@ -25,7 +27,13 @@ @implementation POPBaseAnimationTests POPAnimator *_animator; CFTimeInterval _beginTime; POPAnimatableProperty *_radiusProperty; + id delegate; } +@synthesize layer1 = _layer1; +@synthesize layer2 = _layer2; +@synthesize animator = _animator; +@synthesize beginTime = _beginTime; +@synthesize radiusProperty = _radiusProperty; - (void)setUp { @@ -43,6 +51,37 @@ - (void)setUp prop.threshold = 0.01; }]; _beginTime = CACurrentMediaTime(); + _animator.beginTime = _beginTime; +} + +- (void)testCopyingSucceedsForConcreteAnimation:(POPAnimation *)anim +{ + POPAnimation *copy = [anim copy]; + + XCTAssertEqualObjects(copy.name, anim.name, @"expected equality; value1:%@ value2:%@", copy.name, anim.name); + XCTAssertEqual(copy.beginTime, anim.beginTime, @"expected equality; value1:%@ value2:%@", @(copy.beginTime), @(anim.beginTime)); + XCTAssertEqualObjects(copy.delegate, anim.delegate, @"expected equality; value1:%@ value2:%@", copy.delegate, anim.delegate); + XCTAssertEqualObjects(copy.animationDidStartBlock, anim.animationDidStartBlock, @"expected equality; value1:%@ value2:%@", copy.animationDidStartBlock, anim.animationDidStartBlock); + XCTAssertEqualObjects(copy.animationDidReachToValueBlock, anim.animationDidReachToValueBlock, @"expected equality; value1:%@ value2:%@", copy.animationDidReachToValueBlock, anim.animationDidReachToValueBlock); + XCTAssertEqualObjects(copy.completionBlock, anim.completionBlock, @"expected equality; value1:%@ value2:%@", copy.completionBlock, anim.completionBlock); + XCTAssertEqualObjects(copy.animationDidApplyBlock, anim.animationDidApplyBlock, @"expected equality; value1:%@ value2:%@", copy.animationDidApplyBlock, anim.animationDidApplyBlock); + XCTAssertEqual(copy.removedOnCompletion, anim.removedOnCompletion, @"expected equality; value1:%@ value2:%@", @(copy.removedOnCompletion), @(anim.removedOnCompletion)); + XCTAssertEqual(copy.autoreverses, anim.autoreverses, @"expected equality; value1:%@ value2:%@", @(copy.autoreverses), @(anim.autoreverses)); + XCTAssertEqual(copy.repeatCount, anim.repeatCount, @"expected equality; value1:%@ value2:%@", @(copy.repeatCount), @(anim.repeatCount)); + XCTAssertEqual(copy.repeatForever, anim.repeatForever, @"expected equality; value1:%@ value2:%@", @(copy.repeatForever), @(anim.repeatForever)); +} + +- (void)testCopyingSucceedsForConcretePropertyAnimation:(POPPropertyAnimation *)anim +{ + [self testCopyingSucceedsForConcreteAnimation:anim]; + + POPPropertyAnimation *copy = [anim copy]; + + XCTAssertEqualObjects(copy.fromValue, anim.fromValue, @"expected equality; value1:%@ value2:%@", copy.fromValue, anim.fromValue); + XCTAssertEqualObjects(copy.toValue, anim.toValue, @"expected equality; value1:%@ value2:%@", copy.toValue, anim.toValue); + XCTAssertEqual(copy.roundingFactor, anim.roundingFactor, @"expected equality; value1:%@ value2:%@", @(copy.roundingFactor), @(anim.roundingFactor)); + XCTAssertEqual(copy.clampMode, anim.clampMode, @"expected equality; value1:%@ value2:%@", @(copy.clampMode), @(anim.clampMode)); + XCTAssertEqual(copy.additive, anim.additive, @"expected equality; value1:%@ value2:%@", @(copy.additive), @(anim.additive)); } @end @@ -74,3 +113,35 @@ BOOL POPAnimationEventsContainValue(NSArray *events, NSNumber *value) return NO; } +void configureConcreteAnimation(POPAnimation *anim) +{ + static id delegate = [NSObject new]; + + anim.name = @"pop_animation_copy_test"; + anim.beginTime = 1.234; + anim.delegate = delegate; // dummy delegate + anim.animationDidStartBlock = ^(POPAnimation *a){ NSLog(@"Animation Did Start"); }; + anim.animationDidReachToValueBlock = ^(POPAnimation *a){ NSLog(@"Animation Did Reach To Value"); }; + anim.completionBlock = ^(POPAnimation *a, BOOL finished){ NSLog(@"Animation Finished"); }; + anim.animationDidApplyBlock = ^(POPAnimation *){ NSLog(@"Animation Applied"); }; + anim.removedOnCompletion = NO; // not default + anim.autoreverses = YES; // not default + anim.repeatCount = 42; + anim.repeatForever = YES; // not default +} + +void configureConcretePropertyAnimation(POPPropertyAnimation *anim) +{ + configureConcreteAnimation(anim); + + // Decay animations don't use fromValue, so setting it here causes issues. + if (![anim isMemberOfClass:[POPDecayAnimation class]]) { + + anim.fromValue = @(12345); + } + + anim.toValue = @(77888); + anim.roundingFactor = 0.257; + anim.clampMode = 87; + anim.additive = YES; // not default +} diff --git a/pop-tests/POPBasicAnimationTests.mm b/pop-tests/POPBasicAnimationTests.mm new file mode 100644 index 00000000..5c7bc6a6 --- /dev/null +++ b/pop-tests/POPBasicAnimationTests.mm @@ -0,0 +1,162 @@ +/** + Copyright (c) 2014-present, Facebook, Inc. + All rights reserved. + + This source code is licensed under the BSD-style license found in the + LICENSE file in the root directory of this source tree. An additional grant + of patent rights can be found in the PATENTS file in the same directory. + */ + +#import + +#import +#import + +#import "POPAnimatable.h" +#import "POPAnimationTestsExtras.h" +#import "POPBaseAnimationTests.h" + +@interface POPBasicAnimationTests : POPBaseAnimationTests + +@end + +@implementation POPBasicAnimationTests + +- (void)testGreaterThanOneControlPointC1Y +{ + POPBasicAnimation *anim = [POPBasicAnimation animationWithPropertyNamed:kPOPLayerPositionX]; + anim.fromValue = @0; + anim.toValue = @100; + anim.timingFunction = [CAMediaTimingFunction functionWithControlPoints:0.15f :1.5f :0.55f :1.0f]; + anim.duration = 0.36; + + POPAnimationTracer *tracer = anim.tracer; + [tracer start]; + + CALayer *layer = [CALayer layer]; + [layer pop_addAnimation:anim forKey:nil]; + + // run animation + POPAnimatorRenderDuration(self.animator, self.beginTime, 3, 1.0/60.0); + + // verify write count + NSArray *writeEvents = [tracer eventsWithType:kPOPAnimationEventPropertyWrite]; + XCTAssertTrue(writeEvents.count > 10, @"expected more write events %@", tracer.allEvents); + + // verify last written value is equal to animation to value + id lastValue = [(POPAnimationValueEvent *)writeEvents.lastObject value]; + XCTAssertEqualObjects(lastValue, anim.toValue, @"expected more write events %@", tracer.allEvents); + + // verify last written value is less than previous value + id prevLastValue = [(POPAnimationValueEvent *)writeEvents[writeEvents.count - 2] value]; + XCTAssertTrue(NSOrderedDescending == [prevLastValue compare:lastValue], @"unexpected lastValue; prevLastValue:%@ events:%@", prevLastValue, tracer.allEvents); +} + +- (void)testColorInterpolation +{ + POPBasicAnimation *anim = [POPBasicAnimation animationWithPropertyNamed:kPOPLayerBackgroundColor]; + +#if TARGET_OS_IPHONE + anim.fromValue = [UIColor whiteColor]; + anim.toValue = [UIColor redColor]; +#else + anim.fromValue = [NSColor whiteColor]; + anim.toValue = [NSColor redColor]; +#endif + + POPAnimationTracer *tracer = anim.tracer; + [tracer start]; + + CALayer *layer = [CALayer layer]; + [layer pop_addAnimation:anim forKey:nil]; + + // run animation + POPAnimatorRenderDuration(self.animator, self.beginTime, 3, 1.0/60.0); + + // verify write events + NSArray *writeEvents = [tracer eventsWithType:kPOPAnimationEventPropertyWrite]; + XCTAssertTrue(writeEvents.count > 5, @"expected more write events %@", tracer.allEvents); + + // assert final value + POPAssertColorEqual((__bridge CGColorRef)anim.toValue, layer.backgroundColor); +} + +- (void)testZeroDurationAnimation +{ + POPBasicAnimation *anim = [POPBasicAnimation animationWithPropertyNamed:kPOPLayerBackgroundColor]; + anim.duration = 0.0f; + +#if TARGET_OS_IPHONE + anim.fromValue = [UIColor whiteColor]; + anim.toValue = [UIColor redColor]; +#else + anim.fromValue = [NSColor whiteColor]; + anim.toValue = [NSColor redColor]; +#endif + + POPAnimationTracer *tracer = anim.tracer; + [tracer start]; + + CALayer *layer = [CALayer layer]; + [layer pop_addAnimation:anim forKey:nil]; + + // run animation + POPAnimatorRenderDuration(self.animator, self.beginTime, 3, 1.0/60.0); + + // verify write events + NSArray *writeEvents = [tracer eventsWithType:kPOPAnimationEventPropertyWrite]; + XCTAssertTrue(writeEvents.count == 1, @"expected one write event %@", tracer.allEvents); + NSArray *stopEvents = [tracer eventsWithType:kPOPAnimationEventDidStop]; + XCTAssertTrue(stopEvents.count == 1, @"expected one stop event %@", tracer.allEvents); + + // assert final value + POPAssertColorEqual((__bridge CGColorRef)anim.toValue, layer.backgroundColor); +} + +#if TARGET_OS_IPHONE +- (void)testEdgeInsetsSupport +{ + const UIEdgeInsets fromEdgeInsets = UIEdgeInsetsZero; + const UIEdgeInsets toEdgeInsets = UIEdgeInsetsMake(100, 200, 200, 400); + + POPBasicAnimation *anim = [POPBasicAnimation animationWithPropertyNamed:kPOPScrollViewContentInset]; + anim.fromValue = [NSValue valueWithUIEdgeInsets:fromEdgeInsets]; + anim.toValue = [NSValue valueWithUIEdgeInsets:toEdgeInsets]; + + id delegate = [OCMockObject niceMockForProtocol:@protocol(POPAnimationDelegate)]; + anim.delegate = delegate; + + // expect start and stop to be called + [[delegate expect] pop_animationDidStart:anim]; + [[delegate expect] pop_animationDidStop:anim finished:YES]; + + // start tracer + POPAnimationTracer *tracer = anim.tracer; + [tracer start]; + + id scrollView = [OCMockObject niceMockForClass:[UIScrollView class]]; + [scrollView pop_addAnimation:anim forKey:nil]; + + // expect final value to be set + [[scrollView expect] setContentInset:toEdgeInsets]; + + // run animation + POPAnimatorRenderDuration(self.animator, self.beginTime, 3, 1.0/60.0); + + NSArray *writeEvents = [tracer eventsWithType:kPOPAnimationEventPropertyWrite]; + + // verify delegate + [delegate verify]; + + // verify scroll view + [scrollView verify]; + + POPAnimationValueEvent *lastEvent = [writeEvents lastObject]; + UIEdgeInsets lastEdgeInsets = [lastEvent.value UIEdgeInsetsValue]; + + // verify last insets are to insets + XCTAssertTrue(UIEdgeInsetsEqualToEdgeInsets(lastEdgeInsets, toEdgeInsets), @"unexpected last edge insets value: %@", lastEvent); +} +#endif + +@end diff --git a/pop-tests/POPCustomAnimationTests.mm b/pop-tests/POPCustomAnimationTests.mm index 10dfa566..ecb397a3 100644 --- a/pop-tests/POPCustomAnimationTests.mm +++ b/pop-tests/POPCustomAnimationTests.mm @@ -7,10 +7,11 @@ of patent rights can be found in the PATENTS file in the same directory. */ -#import - #import -#import + +#import + +#import #import "POPAnimatable.h" #import "POPAnimationTestsExtras.h" @@ -32,8 +33,10 @@ - (void)testCallbackFinished // animation POPCustomAnimation *anim = [POPCustomAnimation animationWithBlock:^BOOL(id target, POPCustomAnimation *animation) { - // validate elapsed time - STAssertEqualsWithAccuracy(animation.elapsedTime, timeInterval, epsilon, @"expected elapsedTime:%f %@", timeInterval, animation); + if (0 != callbackCount) { + // validate elapsed time + XCTAssertEqualWithAccuracy(animation.elapsedTime, timeInterval, epsilon, @"expected elapsedTime:%f %@", timeInterval, animation); + } // increment callback count callbackCount++; @@ -52,22 +55,22 @@ - (void)testCallbackFinished [[delegate expect] pop_animationDidApply:anim]; anim.delegate = delegate; + + POPAnimationTracer *tracer = anim.tracer; + [tracer start]; // layer id layer = [OCMockObject niceMockForClass:[CALayer class]]; [layer pop_addAnimation:anim forKey:key]; - POPAnimationTracer *tracer = anim.tracer; - [tracer start]; - - POPAnimatorRenderDuration(self.animator, self.beginTime, 5, 0.1); - STAssertTrue(callbackCount == 3, @"unexpected callbackCount:%d", callbackCount); + POPAnimatorRenderDuration(self.animator, self.beginTime + 0.1, 5, 0.1); + XCTAssertTrue(callbackCount == 3, @"unexpected callbackCount:%lu", (unsigned long)callbackCount); NSArray *startEvents = [tracer eventsWithType:kPOPAnimationEventDidStart]; - STAssertTrue(1 == startEvents.count, @"unexpected startEvents count %@", startEvents); + XCTAssertTrue(1 == startEvents.count, @"unexpected startEvents count %@", startEvents); NSArray *stopEvents = [tracer eventsWithType:kPOPAnimationEventDidStop]; - STAssertTrue(1 == stopEvents.count, @"unexpected stopEvents count %@", stopEvents); + XCTAssertTrue(1 == stopEvents.count, @"unexpected stopEvents count %@", stopEvents); [layer verify]; [delegate verify]; @@ -82,8 +85,13 @@ - (void)testCallbackCancelled // animation POPCustomAnimation *anim = [POPCustomAnimation animationWithBlock:^BOOL(id target, POPCustomAnimation *animation) { - // validate elapsed time acruel - STAssertEqualsWithAccuracy(animation.elapsedTime, timeInterval, epsilon, @"expected elapsedTime:%f %@", timeInterval, animation); + if (0 == callbackCount) { + // validate elapsed time acruel + XCTAssertEqualWithAccuracy(animation.elapsedTime, 0., epsilon, @"expected elapsedTime:%f %@", timeInterval, animation); + } else { + // validate elapsed time acruel + XCTAssertEqualWithAccuracy(animation.elapsedTime, timeInterval, epsilon, @"expected elapsedTime:%f %@", timeInterval, animation); + } // increment callback count callbackCount++; @@ -107,21 +115,21 @@ - (void)testCallbackCancelled anim.delegate = delegate; + POPAnimationTracer *tracer = anim.tracer; + [tracer start]; + // layer id layer = [OCMockObject niceMockForClass:[CALayer class]]; [layer pop_addAnimation:anim forKey:key]; - - POPAnimationTracer *tracer = anim.tracer; - [tracer start]; - POPAnimatorRenderDuration(self.animator, self.beginTime, 5, 0.1); - STAssertTrue(callbackCount == 3, @"unexpected callbackCount:%d", callbackCount); + POPAnimatorRenderDuration(self.animator, self.beginTime + 0.1, 5, 0.1); + XCTAssertTrue(callbackCount == 3, @"unexpected callbackCount:%lu", (unsigned long)callbackCount); NSArray *startEvents = [tracer eventsWithType:kPOPAnimationEventDidStart]; - STAssertTrue(1 == startEvents.count, @"unexpected startEvents count %@", startEvents); + XCTAssertTrue(1 == startEvents.count, @"unexpected startEvents count %@", startEvents); NSArray *stopEvents = [tracer eventsWithType:kPOPAnimationEventDidStop]; - STAssertTrue(1 == stopEvents.count, @"unexpected stopEvents count %@", stopEvents); + XCTAssertTrue(1 == stopEvents.count, @"unexpected stopEvents count %@", stopEvents); [layer verify]; [delegate verify]; @@ -143,19 +151,19 @@ - (void)testAssociation [layer pop_addAnimation:anim forKey:key]; // verify animation & key - STAssertTrue(anim == [layer pop_animationForKey:key], @"expected:%@ actual:%@", anim, [layer pop_animationForKey:key]); - STAssertTrue([[layer pop_animationKeys] containsObject:key], @"expected:%@ actual:%@", key, [layer pop_animationKeys]); + XCTAssertTrue(anim == [layer pop_animationForKey:key], @"expected:%@ actual:%@", anim, [layer pop_animationForKey:key]); + XCTAssertTrue([[layer pop_animationKeys] containsObject:key], @"expected:%@ actual:%@", key, [layer pop_animationKeys]); POPAnimatorRenderDuration(self.animator, self.beginTime, 1, 0.1); - STAssertEqualObjects(layer, blockTarget, @"expected:%@ actual:%@", layer, blockTarget); + XCTAssertEqualObjects(layer, blockTarget, @"expected:%@ actual:%@", layer, blockTarget); // remove animations [layer pop_removeAnimationForKey:key]; // verify animation & key - STAssertFalse(anim == [layer pop_animationForKey:key], @"expected:%@ actual:%@", nil, [layer pop_animationForKey:key]); - STAssertFalse([[layer pop_animationKeys] containsObject:key], @"expected:%@ actual:%@", nil, [layer pop_animationKeys]); + XCTAssertFalse(anim == [layer pop_animationForKey:key], @"expected:%@ actual:%@", (id)nil, [layer pop_animationForKey:key]); + XCTAssertFalse([[layer pop_animationKeys] containsObject:key], @"expected:%@ actual:%@", (id)nil, [layer pop_animationKeys]); } @end diff --git a/pop-tests/POPDecayAnimationTests.mm b/pop-tests/POPDecayAnimationTests.mm index 03c9690c..04963b78 100644 --- a/pop-tests/POPDecayAnimationTests.mm +++ b/pop-tests/POPDecayAnimationTests.mm @@ -10,10 +10,11 @@ #import #import -#import -#import -#import +#import + +#import +#import #import "POPAnimatable.h" #import "POPAnimationTestsExtras.h" @@ -68,11 +69,11 @@ - (void)testConvergence // did reach to value POPAnimationValueEvent *didReachToEvent = [[tracer eventsWithType:kPOPAnimationEventDidReachToValue] lastObject]; - STAssertEqualObjects(didReachToEvent.value, anim.toValue, @"unexpected did reach to event: %@ anim:%@", didReachToEvent, anim); + XCTAssertEqualObjects(didReachToEvent.value, anim.toValue, @"unexpected did reach to event: %@ anim:%@", didReachToEvent, anim); // finished POPAnimationValueEvent *stopEvent = [[tracer eventsWithType:kPOPAnimationEventDidStop] lastObject]; - STAssertEqualObjects(stopEvent.value, @YES, @"unexpected stop event %@", stopEvent); + XCTAssertEqualObjects(stopEvent.value, @YES, @"unexpected stop event %@", stopEvent); // all write values monotonically increasing NSArray *writeEvents = [tracer eventsWithType:kPOPAnimationEventPropertyWrite]; @@ -80,14 +81,14 @@ - (void)testConvergence for (POPAnimationValueEvent *writeEvent in writeEvents) { if (lastWriteEvent) { NSComparisonResult result = [lastWriteEvent.value compare:writeEvent.value]; - STAssertTrue(NSOrderedAscending == result || NSOrderedSame == result, @"write event values not monotonically increasing current:%@ last:%@ all:%@", writeEvent, lastWriteEvent, writeEvents); + XCTAssertTrue(NSOrderedAscending == result || NSOrderedSame == result, @"write event values not monotonically increasing current:%@ last:%@ all:%@", writeEvent, lastWriteEvent, writeEvents); } lastWriteEvent = writeEvent; } // convergence threshold NSUInteger toValueFrameCount = POPAnimationCountLastEventValues(writeEvents, anim.toValue, anim.property.threshold); - STAssertTrue(toValueFrameCount <= kPOPAnimationConvergenceMaxFrameCount, @"unexpected convergence; toValueFrameCount: %d", toValueFrameCount); + XCTAssertTrue(toValueFrameCount <= kPOPAnimationConvergenceMaxFrameCount, @"unexpected convergence; toValueFrameCount: %lu", (unsigned long)toValueFrameCount); } - (void)testConvergenceNegativeVelocity @@ -105,11 +106,11 @@ - (void)testConvergenceNegativeVelocity // did reach to value POPAnimationValueEvent *didReachToEvent = [[tracer eventsWithType:kPOPAnimationEventDidReachToValue] lastObject]; - STAssertEqualObjects(didReachToEvent.value, anim.toValue, @"unexpected did reach to event: %@ anim:%@", didReachToEvent, anim); + XCTAssertEqualObjects(didReachToEvent.value, anim.toValue, @"unexpected did reach to event: %@ anim:%@", didReachToEvent, anim); // finished POPAnimationValueEvent *stopEvent = [[tracer eventsWithType:kPOPAnimationEventDidStop] lastObject]; - STAssertEqualObjects(stopEvent.value, @YES, @"unexpected stop event %@", stopEvent); + XCTAssertEqualObjects(stopEvent.value, @YES, @"unexpected stop event %@", stopEvent); // all write values monotonically increasing NSArray *writeEvents = [tracer eventsWithType:kPOPAnimationEventPropertyWrite]; @@ -117,27 +118,27 @@ - (void)testConvergenceNegativeVelocity for (POPAnimationValueEvent *writeEvent in writeEvents) { if (lastWriteEvent) { NSComparisonResult result = [lastWriteEvent.value compare:writeEvent.value]; - STAssertTrue(NSOrderedDescending == result || NSOrderedSame == result, @"write event values not monotonically decreasing current:%@ last:%@ all:%@", writeEvent, lastWriteEvent, writeEvents); + XCTAssertTrue(NSOrderedDescending == result || NSOrderedSame == result, @"write event values not monotonically decreasing current:%@ last:%@ all:%@", writeEvent, lastWriteEvent, writeEvents); } lastWriteEvent = writeEvent; } // convergence threshold NSUInteger toValueFrameCount = POPAnimationCountLastEventValues(writeEvents, anim.toValue, anim.property.threshold); - STAssertTrue(toValueFrameCount <= kPOPAnimationConvergenceMaxFrameCount, @"unexpected convergence; toValueFrameCount: %d", toValueFrameCount); + XCTAssertTrue(toValueFrameCount <= kPOPAnimationConvergenceMaxFrameCount, @"unexpected convergence; toValueFrameCount: %lu", (unsigned long)toValueFrameCount); } - (void)test2DConvergence { POPDecayAnimation *animX = self._positionXAnimation; POPDecayAnimation *animY = self._positionYAnimation; - STAssertEquals(animX.duration, animY.duration, @"unexpected durations animX:%@ animY:%@", animX, animY); - STAssertEqualObjects(animX.toValue, animY.toValue, @"unexpected toValue animX:%@ animY:%@", animX, animY); + XCTAssertEqual(animX.duration, animY.duration, @"unexpected durations animX:%@ animY:%@", animX, animY); + XCTAssertEqualObjects(animX.toValue, animY.toValue, @"unexpected toValue animX:%@ animY:%@", animX, animY); POPDecayAnimation *anim = self._positionAnimation; CFTimeInterval duration = anim.duration; - STAssertEqualsWithAccuracy(animX.duration, duration, epsilon, @"unexpected durations animX:%@ anim:%@", animX, anim); - STAssertEqualObjects(animX.toValue, @([anim.toValue CGPointValue].x), @"unexpected toValue animX:%@ anim:%@", animX, anim); + XCTAssertEqualWithAccuracy(animX.duration, duration, epsilon, @"unexpected durations animX:%@ anim:%@", animX, anim); + XCTAssertEqualObjects(animX.toValue, @([anim.toValue CGPointValue].x), @"unexpected toValue animX:%@ anim:%@", animX, anim); POPAnimatable *circle = [POPAnimatable new]; POPAnimationTracer *tracer = anim.tracer; @@ -149,19 +150,19 @@ - (void)test2DConvergence // did reach to value POPAnimationValueEvent *didReachToEvent = [[tracer eventsWithType:kPOPAnimationEventDidReachToValue] lastObject]; - STAssertEqualObjects(didReachToEvent.value, anim.toValue, @"unexpected did reach to event: %@ anim:%@", didReachToEvent, anim); + XCTAssertEqualObjects(didReachToEvent.value, anim.toValue, @"unexpected did reach to event: %@ anim:%@", didReachToEvent, anim); // finished POPAnimationValueEvent *stopEvent = [[tracer eventsWithType:kPOPAnimationEventDidStop] lastObject]; - STAssertEqualObjects(stopEvent.value, @YES, @"unexpected stop event %@", stopEvent); + XCTAssertEqualObjects(stopEvent.value, @YES, @"unexpected stop event %@", stopEvent); // increase X velocity anim.velocity = [NSValue valueWithCGPoint:CGPointMake(7223.021 + 1000, 7223.021)]; - STAssertTrue(anim.duration > duration, @"unexpected duration expected:%f anim:%@", duration, anim); + XCTAssertTrue(anim.duration > duration, @"unexpected duration expected:%f anim:%@", duration, anim); // increase Y velocity anim.velocity = [NSValue valueWithCGPoint:CGPointMake(7223.021, 7223.021 + 1000)]; - STAssertTrue(anim.duration > duration, @"unexpected duration expected:%f anim:%@", duration, anim); + XCTAssertTrue(anim.duration > duration, @"unexpected duration expected:%f anim:%@", duration, anim); } - (void)testRemovedOnCompletionNoStartStopBasics @@ -200,11 +201,11 @@ - (void)testRemovedOnCompletionNoStartStopBasics // verify delegate [delegate verify]; - STAssertTrue(completionBlock, @"completion block did not execute %@", allEvents); - STAssertTrue(completionBlockFinished, @"completion block did not finish %@", allEvents); + XCTAssertTrue(completionBlock, @"completion block did not execute %@", allEvents); + XCTAssertTrue(completionBlockFinished, @"completion block did not finish %@", allEvents); // assert animation has not been removed - STAssertTrue(anim == [layer pop_animationForKey:animationKey], @"expected animation on layer animations:%@", [layer pop_animationKeys]); + XCTAssertTrue(anim == [layer pop_animationForKey:animationKey], @"expected animation on layer animations:%@", [layer pop_animationKeys]); } - (void)testRemovedOnCompletionNoContinuations @@ -259,9 +260,9 @@ - (void)testRemovedOnCompletionNoContinuations // verify delegate [delegate verify]; - STAssertTrue(1 == didReachEvents.count, @"unexpected didReachEvents %@", didReachEvents); - STAssertTrue(completionBlock, @"completion block did not execute %@", allEvents); - STAssertTrue(completionBlockFinished, @"completion block did not finish %@", allEvents); + XCTAssertTrue(1 == didReachEvents.count, @"unexpected didReachEvents %@", didReachEvents); + XCTAssertTrue(completionBlock, @"completion block did not execute %@", allEvents); + XCTAssertTrue(completionBlockFinished, @"completion block did not finish %@", allEvents); } else if (velocities.count - 1 == idx) { // continue stoped animation [tracer reset]; @@ -278,9 +279,9 @@ - (void)testRemovedOnCompletionNoContinuations // verify delegate [delegate verify]; - STAssertTrue(1 == didReachEvents.count, @"unexpected didReachEvents %@", didReachEvents); - STAssertTrue(completionBlock, @"completion block did not execute %@", allEvents); - STAssertTrue(completionBlockFinished, @"completion block did not finish %@", allEvents); + XCTAssertTrue(1 == didReachEvents.count, @"unexpected didReachEvents %@", didReachEvents); + XCTAssertTrue(completionBlock, @"completion block did not execute %@", allEvents); + XCTAssertTrue(completionBlockFinished, @"completion block did not finish %@", allEvents); } else { // continue stoped (idx = 1) or started animation if (1 == idx) { @@ -301,13 +302,13 @@ - (void)testRemovedOnCompletionNoContinuations // verify delegate [delegate verify]; - STAssertTrue(0 == didReachEvents.count, @"unexpected didReachEvents %@", didReachEvents); - STAssertFalse(completionBlock, @"completion block did not execute %@ %@", anim, allEvents); - STAssertFalse(completionBlockFinished, @"completion block did not finish %@ %@", anim, allEvents); + XCTAssertTrue(0 == didReachEvents.count, @"unexpected didReachEvents %@", didReachEvents); + XCTAssertFalse(completionBlock, @"completion block did not execute %@ %@", anim, allEvents); + XCTAssertFalse(completionBlockFinished, @"completion block did not finish %@ %@", anim, allEvents); } // assert animation has not been removed - STAssertTrue(anim == [layer pop_animationForKey:animationKey], @"expected animation on layer animations:%@", [layer pop_animationKeys]); + XCTAssertTrue(anim == [layer pop_animationForKey:animationKey], @"expected animation on layer animations:%@", [layer pop_animationKeys]); }]; } @@ -341,7 +342,7 @@ - (void)testNoOperationAnimation // verify number values NSArray *writeEvents = [tracer eventsWithType:kPOPAnimationEventPropertyWrite]; for (POPAnimationValueEvent *writeEvent in writeEvents) { - STAssertEqualObjects(writeEvent.value, [NSValue valueWithCGPoint:initialValue], @"unexpected write event:%@ anim:%@", writeEvent, anim); + XCTAssertEqualObjects(writeEvent.value, [NSValue valueWithCGPoint:initialValue], @"unexpected write event:%@ anim:%@", writeEvent, anim); } } @@ -375,7 +376,7 @@ - (void)testContinuation [[delegate expect] pop_animationDidStop:anim finished:YES]; // run animation some more - POPAnimatorRenderDuration(self.animator, CACurrentMediaTime(), 4, 1.0/60.0); + POPAnimatorRenderDuration(self.animator, self.beginTime + 1, 4, 1.0/60.0); NSArray *moreWriteEvents = [tracer eventsWithType:kPOPAnimationEventPropertyWrite]; // verify stop delegation @@ -385,7 +386,7 @@ - (void)testContinuation POPAnimationValueEvent *firstEvent = [writeEvents firstObject]; POPAnimationValueEvent *lastEvent = [writeEvents lastObject]; POPAnimationValueEvent *firstMoreEvent = [moreWriteEvents firstObject]; - STAssertTrue(NSOrderedAscending == [firstEvent.value compare:lastEvent.value] + XCTAssertTrue(NSOrderedAscending == [firstEvent.value compare:lastEvent.value] && NSOrderedAscending == [lastEvent.value compare:firstMoreEvent.value], @"write event values not monotonically increasing %@ %@ %@", firstEvent, lastEvent, firstMoreEvent); } @@ -423,9 +424,50 @@ - (void)testRectSupport POPAnimationValueEvent *lastEvent = [writeEvents lastObject]; CGRect lastRect = [lastEvent.value CGRectValue]; - STAssertTrue(!CGRectEqualToRect(fromRect, lastRect), @"unexpected last rect value: %@", lastEvent); - STAssertTrue(lastRect.origin.x == lastRect.origin.y && lastRect.size.width == lastRect.size.height && lastRect.origin.x < lastRect.size.width, @"unexpected last rect value: %@", lastEvent); + XCTAssertTrue(!CGRectEqualToRect(fromRect, lastRect), @"unexpected last rect value: %@", lastEvent); + XCTAssertTrue(lastRect.origin.x == lastRect.origin.y && lastRect.size.width == lastRect.size.height && lastRect.origin.x < lastRect.size.width, @"unexpected last rect value: %@", lastEvent); +} + +#if TARGET_OS_IPHONE +- (void)testEdgeInsetsSupport +{ + const UIEdgeInsets fromEdgeInsets = UIEdgeInsetsZero; + const UIEdgeInsets velocityEdgeInsets = UIEdgeInsetsMake(100, 100, 1000, 1000); + + POPDecayAnimation *anim = [POPDecayAnimation animation]; + anim.property = [POPAnimatableProperty propertyWithName:kPOPScrollViewContentInset]; + anim.fromValue = [NSValue valueWithUIEdgeInsets:fromEdgeInsets]; + anim.velocity = [NSValue valueWithUIEdgeInsets:velocityEdgeInsets]; + + id delegate = [OCMockObject niceMockForProtocol:@protocol(POPAnimationDelegate)]; + anim.delegate = delegate; + + // expect start and stop to be called + [[delegate expect] pop_animationDidStart:anim]; + [[delegate expect] pop_animationDidStop:anim finished:YES]; + + // start tracer + POPAnimationTracer *tracer = anim.tracer; + [tracer start]; + + id scrollView = [OCMockObject niceMockForClass:[UIScrollView class]]; + [scrollView pop_addAnimation:anim forKey:nil]; + + // run animation + POPAnimatorRenderDuration(self.animator, self.beginTime, 3, 1.0/60.0); + + NSArray *writeEvents = [tracer eventsWithType:kPOPAnimationEventPropertyWrite]; + + // verify delegate + [delegate verify]; + + POPAnimationValueEvent *lastEvent = [writeEvents lastObject]; + UIEdgeInsets lastEdgeInsets = [lastEvent.value UIEdgeInsetsValue]; + + XCTAssertTrue(!UIEdgeInsetsEqualToEdgeInsets(fromEdgeInsets, lastEdgeInsets), @"unexpected last edge insets value: %@", lastEvent); + XCTAssertTrue(lastEdgeInsets.top == lastEdgeInsets.left && lastEdgeInsets.bottom == lastEdgeInsets.right && lastEdgeInsets.top < lastEdgeInsets.bottom, @"unexpected last edge insets value: %@", lastEvent); } +#endif - (void)testEndValueOnReuse { @@ -441,10 +483,10 @@ - (void)testEndValueOnReuse POPAnimatorRenderDuration(self.animator, self.beginTime, 5.0, 1.0/60.0); NSArray *stopEvent = [tracer eventsWithType:kPOPAnimationEventDidStop]; - STAssertTrue(1 == stopEvent.count, @"unexpected events:%@", tracer.allEvents); + XCTAssertTrue(1 == stopEvent.count, @"unexpected events:%@", tracer.allEvents); CGFloat lastValue = [[(POPAnimationValueEvent *)tracer.writeEvents.lastObject value] floatValue]; - STAssertEqualsWithAccuracy(toValue, lastValue, 0.5, @"expected:%f actual event:%@", tracer.writeEvents.lastObject); + XCTAssertEqualWithAccuracy(toValue, lastValue, 0.5, @"expected:%f actual event:%@", lastValue, tracer.writeEvents.lastObject); // update animation anim.fromValue = @([anim.toValue floatValue] - 100); anim.velocity = @(5000.); @@ -456,7 +498,47 @@ - (void)testEndValueOnReuse // verify decayed passed initial toValue lastValue = [[(POPAnimationValueEvent *)tracer.writeEvents.lastObject value] floatValue]; - STAssertTrue(lastValue > toValue, @"unexpected last value:%f"); + XCTAssertTrue(lastValue > toValue, @"unexpected last value:%f", lastValue); +} + +- (void)testComputedProperties +{ + POPDecayAnimation *anim = [POPDecayAnimation animationWithPropertyNamed:kPOPLayerPositionX]; + + // set velocity, test duration + anim.velocity = @(100); + CGFloat d1 = anim.duration; + XCTAssertTrue(d1 > 0, @"unexpected duration %@", anim); + + // set velocity, test duration + anim.velocity = @(1000); + CGFloat d2 = anim.duration; + XCTAssertTrue(d2 > d1, @"unexpected duration %@", anim); + + // set from value, test to value + anim.fromValue = @(0); + CGFloat p1 = [anim.toValue floatValue]; + XCTAssertTrue(p1 > [anim.fromValue floatValue], @"unexpected to value %@", anim); + + // set from value, test to value + anim.fromValue = @(10000); + CGFloat p2 = [anim.toValue floatValue]; + XCTAssertTrue(p2 > [anim.fromValue floatValue] && p2 > p1, @"unexpected to value %@", anim); +} + +- (void)testNSCopyingSupportPOPDecayAnimation +{ + POPDecayAnimation *anim = [POPDecayAnimation animationWithPropertyNamed:@"test_prop_name"]; + + configureConcretePropertyAnimation(anim); + + anim.velocity = @(1.8888); + anim.deceleration = -9.8; + + POPDecayAnimation *copy = [anim copy]; + + XCTAssertEqualObjects(copy.velocity, anim.velocity, @"expected equality; value1:%@ value2:%@", copy.velocity, anim.velocity); + XCTAssertEqual(copy.deceleration, anim.deceleration, @"expected equality; value1:%@ value2:%@", @(copy.deceleration), @(anim.deceleration)); } @end diff --git a/pop-tests/POPEaseInEaseOutAnimationTests.mm b/pop-tests/POPEaseInEaseOutAnimationTests.mm index e2950462..d8c582ae 100644 --- a/pop-tests/POPEaseInEaseOutAnimationTests.mm +++ b/pop-tests/POPEaseInEaseOutAnimationTests.mm @@ -7,13 +7,14 @@ of patent rights can be found in the PATENTS file in the same directory. */ +#import + #import -#import -#import +#import -#import -#import +#import +#import #import "POPAnimatable.h" #import "POPAnimationTestsExtras.h" @@ -85,7 +86,7 @@ - (void)testRectSupport CGRect lastRect = [lastEvent.value CGRectValue]; // verify last rect is to rect - STAssertTrue(CGRectEqualToRect(lastRect, toRect), @"unexpected last rect value: %@", lastEvent); + XCTAssertTrue(CGRectEqualToRect(lastRect, toRect), @"unexpected last rect value: %@", lastEvent); } @end diff --git a/pop-tests/POPSpringAnimationTests.mm b/pop-tests/POPSpringAnimationTests.mm index e34cef7b..ce99c321 100644 --- a/pop-tests/POPSpringAnimationTests.mm +++ b/pop-tests/POPSpringAnimationTests.mm @@ -7,16 +7,17 @@ of patent rights can be found in the PATENTS file in the same directory. */ -#import - #import + #import -#import -#import -#import -#import -#import +#import + +#import +#import +#import +#import +#import #import "POPAnimatable.h" #import "POPAnimationInternal.h" @@ -48,7 +49,7 @@ - (void)testCompletion POPSpringAnimation *anim = [POPSpringAnimation animation]; anim.property = [POPAnimatableProperty propertyWithName:kPOPLayerPosition]; anim.progressMarkers = markers; - STAssertEqualObjects(markers, anim.progressMarkers, @"%@ shoudl equal %@", markers, anim.progressMarkers); + XCTAssertEqualObjects(markers, anim.progressMarkers, @"%@ shoudl equal %@", markers, anim.progressMarkers); // delegate id delegate = [OCMockObject niceMockForProtocol:@protocol(POPAnimationDelegate)]; @@ -64,7 +65,7 @@ - (void)testCompletion // expect position to be called CGPoint position = CGPointMake(100, 100); - [(CALayer *)[[layer stub] andReturnValue:OCMOCK_VALUE(position)] position]; + position = [(CALayer *)[[layer stub] andReturnValue:OCMOCK_VALUE(position)] position]; [layer pop_addAnimation:anim forKey:@"key"]; POPAnimatorRenderTimes(self.animator, self.beginTime, @[@0.0, @0.1, @0.2]); @@ -91,12 +92,12 @@ - (void)testConvergence // finished POPAnimationValueEvent *stopEvent = [[tracer eventsWithType:kPOPAnimationEventDidStop] lastObject]; - STAssertEqualObjects(stopEvent.value, @YES, @"unexpected stop event %@", stopEvent); + XCTAssertEqualObjects(stopEvent.value, @YES, @"unexpected stop event %@", stopEvent); // convergence threshold NSArray *writeEvents = [tracer eventsWithType:kPOPAnimationEventPropertyWrite]; NSUInteger toValueFrameCount = POPAnimationCountLastEventValues(writeEvents, anim.toValue, anim.property.threshold); - STAssertTrue(toValueFrameCount < kPOPAnimationConvergenceMaxFrameCount, @"unexpected convergence; toValueFrameCount: %d", toValueFrameCount); + XCTAssertTrue(toValueFrameCount < kPOPAnimationConvergenceMaxFrameCount, @"unexpected convergence; toValueFrameCount: %lu", (unsigned long)toValueFrameCount); } - (void)testConvergenceRounded @@ -119,12 +120,12 @@ - (void)testConvergenceRounded // finished POPAnimationValueEvent *stopEvent = [[tracer eventsWithType:kPOPAnimationEventDidStop] lastObject]; - STAssertEqualObjects(stopEvent.value, @YES, @"unexpected stop event %@", stopEvent); + XCTAssertEqualObjects(stopEvent.value, @YES, @"unexpected stop event %@", stopEvent); // convergence threshold NSArray *writeEvents = [tracer eventsWithType:kPOPAnimationEventPropertyWrite]; NSUInteger toValueFrameCount = POPAnimationCountLastEventValues(writeEvents, anim.toValue); - STAssertTrue(toValueFrameCount < kPOPAnimationConvergenceMaxFrameCount, @"unexpected convergence; toValueFrameCount: %d", toValueFrameCount); + XCTAssertTrue(toValueFrameCount < kPOPAnimationConvergenceMaxFrameCount, @"unexpected convergence; toValueFrameCount: %lu", (unsigned long)toValueFrameCount); } - (void)testConvergenceClampedRounded @@ -148,12 +149,12 @@ - (void)testConvergenceClampedRounded // finished POPAnimationValueEvent *stopEvent = [[tracer eventsWithType:kPOPAnimationEventDidStop] lastObject]; - STAssertEqualObjects(stopEvent.value, @YES, @"unexpected stop event %@", stopEvent); + XCTAssertEqualObjects(stopEvent.value, @YES, @"unexpected stop event %@", stopEvent); // convergence threshold NSArray *writeEvents = [tracer eventsWithType:kPOPAnimationEventPropertyWrite]; NSUInteger toValueFrameCount = POPAnimationCountLastEventValues(writeEvents, anim.toValue); - STAssertTrue(toValueFrameCount < kPOPAnimationConvergenceMaxFrameCount, @"unexpected convergence; toValueFrameCount: %d", toValueFrameCount); + XCTAssertTrue(toValueFrameCount < kPOPAnimationConvergenceMaxFrameCount, @"unexpected convergence; toValueFrameCount: %lu", (unsigned long)toValueFrameCount); } - (void)testRemovedOnCompletionNoStartStopBasics @@ -191,11 +192,11 @@ - (void)testRemovedOnCompletionNoStartStopBasics // verify delegate [delegate verify]; - STAssertTrue(completionBlock, @"completion block did not execute %@", allEvents); - STAssertTrue(completionBlockFinished, @"completion block did not finish %@", allEvents); + XCTAssertTrue(completionBlock, @"completion block did not execute %@", allEvents); + XCTAssertTrue(completionBlockFinished, @"completion block did not finish %@", allEvents); // assert animation has not been removed - STAssertTrue(anim == [layer pop_animationForKey:animationKey], @"expected animation on layer animations:%@", [layer pop_animationKeys]); + XCTAssertTrue(anim == [layer pop_animationForKey:animationKey], @"expected animation on layer animations:%@", [layer pop_animationKeys]); } - (void)testRemovedOnCompletionNoContinuations @@ -250,9 +251,9 @@ - (void)testRemovedOnCompletionNoContinuations // verify delegate [delegate verify]; - STAssertTrue(1 == didReachEvents.count, @"unexpected didReachEvents %@", didReachEvents); - STAssertTrue(completionBlock, @"completion block did not execute %@", allEvents); - STAssertTrue(completionBlockFinished, @"completion block did not finish %@", allEvents); + XCTAssertTrue(1 == didReachEvents.count, @"unexpected didReachEvents %@", didReachEvents); + XCTAssertTrue(completionBlock, @"completion block did not execute %@", allEvents); + XCTAssertTrue(completionBlockFinished, @"completion block did not finish %@", allEvents); } else if (toValues.count - 1 == idx) { // continue stoped animation [tracer reset]; @@ -269,9 +270,9 @@ - (void)testRemovedOnCompletionNoContinuations // verify delegate [delegate verify]; - STAssertTrue(1 == didReachEvents.count, @"unexpected didReachEvents %@", didReachEvents); - STAssertTrue(completionBlock, @"completion block did not execute %@", allEvents); - STAssertTrue(completionBlockFinished, @"completion block did not finish %@", allEvents); + XCTAssertTrue(1 == didReachEvents.count, @"unexpected didReachEvents %@", didReachEvents); + XCTAssertTrue(completionBlock, @"completion block did not execute %@", allEvents); + XCTAssertTrue(completionBlockFinished, @"completion block did not finish %@", allEvents); } else { // continue stoped (idx = 1) or started animation if (1 == idx) { @@ -292,13 +293,13 @@ - (void)testRemovedOnCompletionNoContinuations // verify delegate [delegate verify]; - STAssertTrue(1 == didReachEvents.count, @"unexpected didReachEvents %@", didReachEvents); - STAssertFalse(completionBlock, @"completion block did not execute %@ %@", anim, allEvents); - STAssertFalse(completionBlockFinished, @"completion block did not finish %@ %@", anim, allEvents); + XCTAssertTrue(1 == didReachEvents.count, @"unexpected didReachEvents %@", didReachEvents); + XCTAssertFalse(completionBlock, @"completion block did not execute %@ %@", anim, allEvents); + XCTAssertFalse(completionBlockFinished, @"completion block did not finish %@ %@", anim, allEvents); } // assert animation has not been removed - STAssertTrue(anim == [layer pop_animationForKey:animationKey], @"expected animation on layer animations:%@", [layer pop_animationKeys]); + XCTAssertTrue(anim == [layer pop_animationForKey:animationKey], @"expected animation on layer animations:%@", [layer pop_animationKeys]); }]; } @@ -332,7 +333,7 @@ - (void)testNoOperationAnimation // verify number values NSArray *writeEvents = [tracer eventsWithType:kPOPAnimationEventPropertyWrite]; for (POPAnimationValueEvent *writeEvent in writeEvents) { - STAssertEqualObjects(writeEvent.value, [NSValue valueWithCGPoint:initialValue], @"unexpected write event:%@ anim:%@", writeEvent, anim); + XCTAssertEqualObjects(writeEvent.value, [NSValue valueWithCGPoint:initialValue], @"unexpected write event:%@ anim:%@", writeEvent, anim); } } @@ -352,20 +353,20 @@ - (void)testLazyValueInitialization // add animation, but do not start [layer pop_addAnimation:anim forKey:animationKey]; POPAnimatorRenderDuration(self.animator, self.beginTime, 0.2, 1.0/60.0); - STAssertNotNil(anim.fromValue, @"unexpected from value %@", anim); - STAssertNil(anim.toValue, @"unexpected to value %@", anim); + XCTAssertNotNil(anim.fromValue, @"unexpected from value %@", anim); + XCTAssertNil(anim.toValue, @"unexpected to value %@", anim); // start animation POPAnimatorRenderDuration(self.animator, self.beginTime + 0.2, 0.2, 1.0/60.0); - STAssertNotNil(anim.fromValue, @"unexpected from value %@", anim); - STAssertNotNil(anim.toValue, @"unexpected to value %@", anim); + XCTAssertNotNil(anim.fromValue, @"unexpected from value %@", anim); + XCTAssertNotNil(anim.toValue, @"unexpected to value %@", anim); // continue running animation anim.fromValue = nil; anim.toValue = @200.0; POPAnimatorRenderDuration(self.animator, self.beginTime + 0.4, 0.2, 1.0/60.0); - STAssertNotNil(anim.fromValue, @"unexpected from value %@", anim); - STAssertNotNil(anim.toValue, @"unexpected to value %@", anim); + XCTAssertNotNil(anim.fromValue, @"unexpected from value %@", anim); + XCTAssertNotNil(anim.toValue, @"unexpected to value %@", anim); } - (void)testLatentSpring @@ -417,9 +418,57 @@ - (void)testRectSupport CGRect lastRect = [lastEvent.value CGRectValue]; // verify last rect is to rect - STAssertTrue(CGRectEqualToRect(lastRect, toRect), @"unexpected last rect value: %@", lastEvent); + XCTAssertTrue(CGRectEqualToRect(lastRect, toRect), @"unexpected last rect value: %@", lastEvent); } +#if TARGET_OS_IPHONE +- (void)testEdgeInsetsSupport +{ + const UIEdgeInsets fromEdgeInsets = UIEdgeInsetsZero; + const UIEdgeInsets toEdgeInsets = UIEdgeInsetsMake(100, 200, 200, 400); + const UIEdgeInsets velocityEdgeInsets = UIEdgeInsetsMake(1000, 1000, 1000, 1000); + + POPSpringAnimation *anim = [POPSpringAnimation animation]; + anim.property = [POPAnimatableProperty propertyWithName:kPOPScrollViewContentInset]; + anim.fromValue = [NSValue valueWithUIEdgeInsets:fromEdgeInsets]; + anim.toValue = [NSValue valueWithUIEdgeInsets:toEdgeInsets]; + anim.velocity = [NSValue valueWithUIEdgeInsets:velocityEdgeInsets]; + id delegate = [OCMockObject niceMockForProtocol:@protocol(POPAnimationDelegate)]; + anim.delegate = delegate; + + // expect start and stop to be called + [[delegate expect] pop_animationDidStart:anim]; + [[delegate expect] pop_animationDidStop:anim finished:YES]; + + // start tracer + POPAnimationTracer *tracer = anim.tracer; + [tracer start]; + + id scrollView = [OCMockObject niceMockForClass:[UIScrollView class]]; + [scrollView pop_addAnimation:anim forKey:nil]; + + // expect final value to be set + [[scrollView expect] setContentInset:toEdgeInsets]; + + // run animation + POPAnimatorRenderDuration(self.animator, self.beginTime, 3, 1.0/60.0); + + NSArray *writeEvents = [tracer eventsWithType:kPOPAnimationEventPropertyWrite]; + + // verify delegate + [delegate verify]; + + // verify scroll view + [scrollView verify]; + + POPAnimationValueEvent *lastEvent = [writeEvents lastObject]; + UIEdgeInsets lastEdgeInsets = [lastEvent.value UIEdgeInsetsValue]; + + // verify last insets are to insets + XCTAssertTrue(UIEdgeInsetsEqualToEdgeInsets(lastEdgeInsets, toEdgeInsets), @"unexpected last edge insets value: %@", lastEvent); +} +#endif + - (void)testColorSupport { CGFloat fromValues[4] = {1, 1, 1, 1}; @@ -451,19 +500,17 @@ - (void)testColorSupport [delegate verify]; // expect some interpolation - STAssertTrue(writeEvents.count > 1, @"unexpected write events %@", writeEvents); + XCTAssertTrue(writeEvents.count > 1, @"unexpected write events %@", writeEvents); POPAnimationValueEvent *lastEvent = [writeEvents lastObject]; // verify last written color is to color - CGFloat lastValues[4]; - POPCGColorGetRGBAComponents((__bridge CGColorRef)lastEvent.value, lastValues); - STAssertTrue(lastValues[0] == toValues[0] && lastValues[1] == toValues[1] && lastValues[2] == toValues[2] && lastValues[3] == toValues[3], @"unexpected last color: [r:%f g:%f b:%f a:%f]", lastValues[0], lastValues[1], lastValues[2], lastValues[3]); + POPAssertColorEqual((__bridge CGColorRef)lastEvent.value, (__bridge CGColorRef)anim.toValue); } static BOOL _floatingPointEqual(CGFloat a, CGFloat b) { CGFloat epsilon = 0.0001; - return fabsf(a - b) < epsilon; + return std::abs(a - b) < epsilon; } - (void)testBouncinessSpeedToTensionFrictionConversion @@ -477,7 +524,7 @@ - (void)testBouncinessSpeedToTensionFrictionConversion CGFloat outBounciness, outSpeed; [POPSpringAnimation convertTension:tension friction:friction toBounciness:&outBounciness speed:&outSpeed]; - STAssertTrue(_floatingPointEqual(sampleBounciness, outBounciness) && _floatingPointEqual(sampleSpeed, outSpeed), @"(bounciness, speed) conversion failed. Mapped (%f, %f) back to (%f, %f)", sampleBounciness, sampleSpeed, outBounciness, outSpeed); + XCTAssertTrue(_floatingPointEqual(sampleBounciness, outBounciness) && _floatingPointEqual(sampleSpeed, outSpeed), @"(bounciness, speed) conversion failed. Mapped (%f, %f) back to (%f, %f)", sampleBounciness, sampleSpeed, outBounciness, outSpeed); } - (void)testTensionFrictionToBouncinessSpeedConversion @@ -491,7 +538,7 @@ - (void)testTensionFrictionToBouncinessSpeedConversion CGFloat outTension, outFriction, outMass; [POPSpringAnimation convertBounciness:bounciness speed:speed toTension:&outTension friction:&outFriction mass:&outMass]; - STAssertTrue(_floatingPointEqual(sampleTension, outTension) && _floatingPointEqual(sampleFriction, outFriction), @"(tension, friction) conversion failed. Mapped (%f, %f) back to (%f, %f)", sampleTension, sampleFriction, outTension, outFriction); + XCTAssertTrue(_floatingPointEqual(sampleTension, outTension) && _floatingPointEqual(sampleFriction, outFriction), @"(tension, friction) conversion failed. Mapped (%f, %f) back to (%f, %f)", sampleTension, sampleFriction, outTension, outFriction); } - (void)testRemovedOnCompletionNoContinuationValues @@ -511,7 +558,7 @@ - (void)testRemovedOnCompletionNoContinuationValues POPAnimatorRenderDuration(self.animator, self.beginTime, 3, 1.0/60.0); // assert reached to value - STAssertTrue(layer.position.x == [anim.toValue floatValue], @"unexpected value:%@ %@", layer, anim); + XCTAssertTrue(layer.position.x == [anim.toValue floatValue], @"unexpected value:%@ %@", layer, anim); // start tracer POPAnimationTracer *tracer = anim.tracer; @@ -523,12 +570,12 @@ - (void)testRemovedOnCompletionNoContinuationValues // verify from 200 to 400 NSArray *writeEvents = [tracer eventsWithType:kPOPAnimationEventPropertyWrite]; - STAssertTrue(writeEvents.count > 5, @"unexpected frame count %@", writeEvents); + XCTAssertTrue(writeEvents.count > 5, @"unexpected frame count %@", writeEvents); CGFloat firstValue = [[(POPAnimationValueEvent *)[writeEvents firstObject] value] floatValue]; CGFloat lastValue = [[(POPAnimationValueEvent *)[writeEvents lastObject] value] floatValue]; - STAssertEqualsWithAccuracy(((CGFloat)[toValues[0] floatValue]), firstValue, 10, @"unexpected first value %@", writeEvents); - STAssertEqualsWithAccuracy(((CGFloat)[toValues[1] floatValue]), lastValue, 10, @"unexpected last value %@", writeEvents); + XCTAssertEqualWithAccuracy(((CGFloat)[toValues[0] floatValue]), firstValue, 10, @"unexpected first value %@", writeEvents); + XCTAssertEqualWithAccuracy(((CGFloat)[toValues[1] floatValue]), lastValue, 10, @"unexpected last value %@", writeEvents); } - (void)testNilColor @@ -553,12 +600,14 @@ - (void)testNilColor // verify valid from color exists CGColorRef fromColor = (__bridge CGColorRef)anim.fromValue; - STAssertTrue(fromColor, @"unexpected value %p", fromColor); + XCTAssertTrue(fromColor, @"unexpected value %p", fromColor); // verify from color clear - CGFloat components[4]; - POPCGColorGetRGBAComponents(fromColor, components); - STAssertTrue(components[0] == 0 && components[1] == 0 && components[2] == 0 && components[3] == 0, @"unexpected components {%f, %f, %f, %f}", components[0], components[1], components[2], components[3]); +#if TARGET_OS_IPHONE + POPAssertColorEqual(fromColor, [UIColor clearColor].CGColor); +#else + POPAssertColorEqual(fromColor, [NSColor clearColor].CGColor); +#endif } - (void)testExcessiveJumpInTime @@ -588,7 +637,51 @@ - (void)testExcessiveJumpInTime // verify last write event value POPAnimationValueEvent *writeEvent = [[tracer eventsWithType:kPOPAnimationEventPropertyWrite] lastObject]; - STAssertEqualObjects(writeEvent.value, anim.toValue, @"unexpected last write event %@", writeEvent); + XCTAssertEqualObjects(writeEvent.value, anim.toValue, @"unexpected last write event %@", writeEvent); +} + +- (void)testEquivalentFromToValues +{ + POPSpringAnimation *anim = [POPSpringAnimation animationWithPropertyNamed:kPOPLayerPosition]; + anim.fromValue = [NSValue valueWithCGPoint:CGPointZero]; + anim.toValue = [NSValue valueWithCGPoint:CGPointZero]; + anim.velocity = [NSValue valueWithCGPoint:CGPointMake(1000.0, 1000.0)]; + + // start tracer + POPAnimationTracer *tracer = anim.tracer; + [tracer start]; + + // run animation + CALayer *layer = [CALayer layer]; + [layer pop_addAnimation:anim forKey:@""]; + POPAnimatorRenderDuration(self.animator, self.beginTime, 3, 1.0/60.0); + + // verify last write event value + POPAnimationValueEvent *writeEvent = [[tracer eventsWithType:kPOPAnimationEventPropertyWrite] lastObject]; + XCTAssertEqualObjects(writeEvent.value, anim.toValue, @"unexpected last write event %@", writeEvent); +} + +- (void)testNSCopyingSupportPOPSpringAnimation +{ + POPSpringAnimation *anim = [POPSpringAnimation animationWithPropertyNamed:@"asdf_asdf_asdf"]; + + configureConcretePropertyAnimation(anim); + + anim.velocity = @(4321); + anim.springBounciness = 11.1; + anim.springSpeed = 12; + anim.dynamicsTension = 0.83; + anim.dynamicsFriction = 0.97; + anim.dynamicsMass = 100; + + POPSpringAnimation *copy = [anim copy]; + + XCTAssertEqualObjects(copy.velocity, anim.velocity, @"expected equality; value1:%@ value2:%@", copy.velocity, anim.velocity); + XCTAssertEqual(copy.springBounciness, anim.springBounciness, @"expected equality; value1:%@ value2:%@", @(copy.springBounciness), @(anim.springBounciness)); + XCTAssertEqual(copy.springSpeed, anim.springSpeed, @"expected equality; value1:%@ value2:%@", @(copy.springSpeed), @(anim.springSpeed)); + XCTAssertEqual(copy.dynamicsTension, anim.dynamicsTension, @"expected equality; value1:%@ value2:%@", @(copy.dynamicsTension), @(anim.dynamicsTension)); + XCTAssertEqual(copy.dynamicsFriction, anim.dynamicsFriction, @"expected equality; value1:%@ value2:%@", @(copy.dynamicsFriction), @(anim.dynamicsFriction)); + XCTAssertEqual(copy.dynamicsMass, anim.dynamicsMass, @"expected equality; value1:%@ value2:%@", @(copy.dynamicsMass), @(anim.dynamicsMass)); } @end diff --git a/pop-tests/en.lproj/InfoPlist.strings b/pop-tests/en.lproj/InfoPlist.strings deleted file mode 100644 index 477b28ff..00000000 --- a/pop-tests/en.lproj/InfoPlist.strings +++ /dev/null @@ -1,2 +0,0 @@ -/* Localized versions of Info.plist keys */ - diff --git a/pop-tests/pop-tests-Prefix.pch b/pop-tests/pop-tests-Prefix.pch deleted file mode 100644 index c331e570..00000000 --- a/pop-tests/pop-tests-Prefix.pch +++ /dev/null @@ -1,10 +0,0 @@ -// -// Prefix header -// -// The contents of this file are implicitly included at the beginning of every source file. -// - -#ifdef __OBJC__ - #import - #import -#endif diff --git a/pop-tests-osx/pop-tests-OSX-Info.plist b/pop-tests/pop-tests-ios-Info.plist similarity index 90% rename from pop-tests-osx/pop-tests-OSX-Info.plist rename to pop-tests/pop-tests-ios-Info.plist index c317ef52..169b6f71 100644 --- a/pop-tests-osx/pop-tests-OSX-Info.plist +++ b/pop-tests/pop-tests-ios-Info.plist @@ -7,7 +7,7 @@ CFBundleExecutable ${EXECUTABLE_NAME} CFBundleIdentifier - com.facebook.${PRODUCT_NAME:rfc1034identifier} + $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundlePackageType diff --git a/pop-tests/pop-tests-Info.plist b/pop-tests/pop-tests-osx-Info.plist similarity index 90% rename from pop-tests/pop-tests-Info.plist rename to pop-tests/pop-tests-osx-Info.plist index c317ef52..169b6f71 100644 --- a/pop-tests/pop-tests-Info.plist +++ b/pop-tests/pop-tests-osx-Info.plist @@ -7,7 +7,7 @@ CFBundleExecutable ${EXECUTABLE_NAME} CFBundleIdentifier - com.facebook.${PRODUCT_NAME:rfc1034identifier} + $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundlePackageType diff --git a/pop-tests/pop-tests-tvos-Info.plist b/pop-tests/pop-tests-tvos-Info.plist new file mode 100644 index 00000000..ba72822e --- /dev/null +++ b/pop-tests/pop-tests-tvos-Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + + diff --git a/pop.podspec b/pop.podspec index 9d563669..4fa7bda8 100644 --- a/pop.podspec +++ b/pop.podspec @@ -1,21 +1,21 @@ Pod::Spec.new do |spec| spec.name = 'pop' - spec.version = '1.0.2' + spec.version = '1.0.11' spec.license = { :type => 'BSD' } spec.homepage = 'https://github.com/facebook/pop' spec.authors = { 'Kimon Tsinteris' => 'kimon@mac.com' } - spec.summary = 'Animation framework for iOS and OS X.' - spec.source = { :git => 'https://github.com/facebook/pop.git', :tag => '1.0.2' } + spec.summary = 'Extensible animation framework for iOS and OS X.' + spec.source = { :git => 'https://github.com/facebook/pop.git', :tag => '1.0.10' } spec.source_files = 'pop/**/*.{h,m,mm,cpp}' - spec.public_header_files = 'pop/{POP,POPAnimatableProperty,POPAnimation,POPAnimationEvent,POPAnimationExtras,POPAnimationTracer,POPAnimator,POPBasicAnimation,POPCustomAnimation,POPDecayAnimation,POPDefines,POPGeometry,POPPropertyAnimation,POPSpringAnimation}.h' + spec.public_header_files = 'pop/{POP,POPAnimatableProperty,POPAnimatablePropertyTypes,POPAnimation,POPAnimationEvent,POPAnimationExtras,POPAnimationTracer,POPAnimator,POPBasicAnimation,POPCustomAnimation,POPDecayAnimation,POPDefines,POPGeometry,POPLayerExtras,POPPropertyAnimation,POPSpringAnimation,POPVector}.h' spec.requires_arc = true spec.social_media_url = 'https://twitter.com/fbOpenSource' spec.library = 'c++' - spec.xcconfig = { + spec.pod_target_xcconfig = { 'CLANG_CXX_LANGUAGE_STANDARD' => 'c++11', 'CLANG_CXX_LIBRARY' => 'libc++' } - - spec.ios.deployment_target = '6.0' - spec.osx.deployment_target = '10.7' + spec.ios.deployment_target = '8.0' + spec.osx.deployment_target = '10.8' + spec.tvos.deployment_target = '9.0' end diff --git a/pop.xcodeproj/project.pbxproj b/pop.xcodeproj/project.pbxproj index 9125aa78..bf4f98ec 100644 --- a/pop.xcodeproj/project.pbxproj +++ b/pop.xcodeproj/project.pbxproj @@ -7,14 +7,128 @@ objects = { /* Begin PBXBuildFile section */ + 0755AE591BEA15A80094AB41 /* CoreImage.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0755AE581BEA15A80094AB41 /* CoreImage.framework */; }; + 0755AE5B1BEA15B30094AB41 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0755AE5A1BEA15B30094AB41 /* UIKit.framework */; }; + 0755AE5D1BEA15BA0094AB41 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0755AE5C1BEA15BA0094AB41 /* CoreFoundation.framework */; }; + 0755AE5F1BEA15BF0094AB41 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0755AE5E1BEA15BF0094AB41 /* Foundation.framework */; }; + 0755AE611BEA15C60094AB41 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0755AE601BEA15C60094AB41 /* CoreGraphics.framework */; }; + 0755AE631BEA15CB0094AB41 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0755AE621BEA15CB0094AB41 /* QuartzCore.framework */; }; + 0755AE651BEA17620094AB41 /* POP.h in Headers */ = {isa = PBXBuildFile; fileRef = ECA94D0B18ECAE82002E4CEB /* POP.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 0755AE661BEA17670094AB41 /* POPAnimation.h in Headers */ = {isa = PBXBuildFile; fileRef = EC191288162FB5B700E0CC76 /* POPAnimation.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 0755AE671BEA17780094AB41 /* POPAnimationPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = EC1CD94E18D80A5C00DE2649 /* POPAnimationPrivate.h */; }; + 0755AE681BEA177C0094AB41 /* POPPropertyAnimation.h in Headers */ = {isa = PBXBuildFile; fileRef = EC8F013E18FFBBD300DF8905 /* POPPropertyAnimation.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 0755AE691BEA17840094AB41 /* POPBasicAnimation.h in Headers */ = {isa = PBXBuildFile; fileRef = EC8F014D18FFBD3E00DF8905 /* POPBasicAnimation.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 0755AE6A1BEA178B0094AB41 /* POPCustomAnimation.h in Headers */ = {isa = PBXBuildFile; fileRef = 5E17BB1E17457345009842B6 /* POPCustomAnimation.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 0755AE6B1BEA17930094AB41 /* POPDecayAnimation.h in Headers */ = {isa = PBXBuildFile; fileRef = EC8F015A18FFBE8C00DF8905 /* POPDecayAnimation.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 0755AE6C1BEA17980094AB41 /* POPSpringAnimation.h in Headers */ = {isa = PBXBuildFile; fileRef = EC8F016618FFBEB500DF8905 /* POPSpringAnimation.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 0755AE6D1BEA17A70094AB41 /* POPAnimation.mm in Sources */ = {isa = PBXBuildFile; fileRef = EC191289162FB5B700E0CC76 /* POPAnimation.mm */; }; + 0755AE6E1BEA17A70094AB41 /* POPPropertyAnimation.mm in Sources */ = {isa = PBXBuildFile; fileRef = EC8F014A18FFBC8200DF8905 /* POPPropertyAnimation.mm */; }; + 0755AE6F1BEA17A70094AB41 /* POPBasicAnimation.mm in Sources */ = {isa = PBXBuildFile; fileRef = EC8F014E18FFBD3E00DF8905 /* POPBasicAnimation.mm */; }; + 0755AE701BEA17A70094AB41 /* POPCustomAnimation.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5E17BB1F17457345009842B6 /* POPCustomAnimation.mm */; }; + 0755AE711BEA17A70094AB41 /* POPDecayAnimation.mm in Sources */ = {isa = PBXBuildFile; fileRef = EC8F015B18FFBE8C00DF8905 /* POPDecayAnimation.mm */; }; + 0755AE721BEA17A70094AB41 /* POPSpringAnimation.mm in Sources */ = {isa = PBXBuildFile; fileRef = EC8F016718FFBEB500DF8905 /* POPSpringAnimation.mm */; }; + 0755AE731BEA17AD0094AB41 /* POPAnimatableProperty.h in Headers */ = {isa = PBXBuildFile; fileRef = EC19128E162FB5B700E0CC76 /* POPAnimatableProperty.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 0755AE741BEA17B10094AB41 /* POPAnimatableProperty.mm in Sources */ = {isa = PBXBuildFile; fileRef = EC19128F162FB5B700E0CC76 /* POPAnimatableProperty.mm */; }; + 0755AE751BEA17B30094AB41 /* POPAnimationEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = EC9997531756A0C300A73F49 /* POPAnimationEvent.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 0755AE761BEA17B80094AB41 /* POPAnimationEvent.mm in Sources */ = {isa = PBXBuildFile; fileRef = EC9997541756A0C300A73F49 /* POPAnimationEvent.mm */; }; + 0755AE771BEA17BC0094AB41 /* POPAnimationExtras.h in Headers */ = {isa = PBXBuildFile; fileRef = EC0AE12F16BC73CE001DA2CE /* POPAnimationExtras.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 0755AE781BEA17C00094AB41 /* POPAnimationExtras.mm in Sources */ = {isa = PBXBuildFile; fileRef = EC0AE13016BC73CE001DA2CE /* POPAnimationExtras.mm */; }; + 0755AE791BEA17C40094AB41 /* POPAnimationRuntime.mm in Sources */ = {isa = PBXBuildFile; fileRef = EC95538F1743E278001E6AF2 /* POPAnimationRuntime.mm */; }; + 0755AE7A1BEA17C70094AB41 /* POPAnimationTracer.h in Headers */ = {isa = PBXBuildFile; fileRef = EC35DB2618EE3E820023E077 /* POPAnimationTracer.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 0755AE7B1BEA17CA0094AB41 /* POPAnimationTracer.mm in Sources */ = {isa = PBXBuildFile; fileRef = EC35DB2718EE3E820023E077 /* POPAnimationTracer.mm */; }; + 0755AE7C1BEA17CF0094AB41 /* POPAnimator.h in Headers */ = {isa = PBXBuildFile; fileRef = EC19128B162FB5B700E0CC76 /* POPAnimator.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 0755AE7D1BEA17D30094AB41 /* POPAnimator.mm in Sources */ = {isa = PBXBuildFile; fileRef = EC19128C162FB5B700E0CC76 /* POPAnimator.mm */; }; + 0755AE7E1BEA17D60094AB41 /* POPAnimatorPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = EC19128D162FB5B700E0CC76 /* POPAnimatorPrivate.h */; }; + 0755AE7F1BEA17E70094AB41 /* POPCGUtils.mm in Sources */ = {isa = PBXBuildFile; fileRef = EC67007118D3D89F00F7387F /* POPCGUtils.mm */; }; + 0755AE801BEA17EA0094AB41 /* POPDefines.h in Headers */ = {isa = PBXBuildFile; fileRef = EC91E95F18C00EC90025B8AD /* POPDefines.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 0755AE811BEA17EF0094AB41 /* POPGeometry.h in Headers */ = {isa = PBXBuildFile; fileRef = ECD80F0F18CFD2EF00AE4303 /* POPGeometry.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 0755AE821BEA17F20094AB41 /* POPGeometry.mm in Sources */ = {isa = PBXBuildFile; fileRef = ECD80F1018CFD2EF00AE4303 /* POPGeometry.mm */; }; + 0755AE831BEA17F50094AB41 /* POPLayerExtras.h in Headers */ = {isa = PBXBuildFile; fileRef = EC94B07B17D95CAA003CE2C8 /* POPLayerExtras.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 0755AE841BEA17F90094AB41 /* POPLayerExtras.mm in Sources */ = {isa = PBXBuildFile; fileRef = EC94B07C17D95CAA003CE2C8 /* POPLayerExtras.mm */; }; + 0755AE851BEA17FD0094AB41 /* POPMath.mm in Sources */ = {isa = PBXBuildFile; fileRef = EC6465CF1794B4660014176F /* POPMath.mm */; }; + 0755AE861BEA18060094AB41 /* POPVector.mm in Sources */ = {isa = PBXBuildFile; fileRef = EC70AC4218CCF4FC0067018C /* POPVector.mm */; }; + 0755AE871BEA180F0094AB41 /* TransformationMatrix.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EC94B07717D95447003CE2C8 /* TransformationMatrix.cpp */; }; + 0755AE911BEA19580094AB41 /* pop.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0755AE4F1BEA15950094AB41 /* pop.framework */; }; + 0755AE991BEA19F40094AB41 /* POPAnimatable.mm in Sources */ = {isa = PBXBuildFile; fileRef = EC99974A17568DAD00A73F49 /* POPAnimatable.mm */; }; + 0755AE9A1BEA19F40094AB41 /* POPBaseAnimationTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = EC6F55A4175E6641008D995D /* POPBaseAnimationTests.mm */; }; + 0755AE9B1BEA19F40094AB41 /* POPAnimationTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = EC191239162FB53A00E0CC76 /* POPAnimationTests.mm */; }; + 0755AE9C1BEA19F40094AB41 /* POPAnimationMRRTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = EC3F125916FB728B00922E3A /* POPAnimationMRRTests.mm */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 0755AE9D1BEA19F40094AB41 /* POPAnimationTestsExtras.mm in Sources */ = {isa = PBXBuildFile; fileRef = EC3F125C16FB78E800922E3A /* POPAnimationTestsExtras.mm */; }; + 0755AE9E1BEA19F40094AB41 /* POPAnimatablePropertyTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = EC91D51B16FCC45C00E22B47 /* POPAnimatablePropertyTests.mm */; }; + 0755AE9F1BEA19F40094AB41 /* POPDecayAnimationTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = EC6F55A1175E654B008D995D /* POPDecayAnimationTests.mm */; }; + 0755AEA01BEA19F40094AB41 /* POPSpringAnimationTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = EC6F55AA175E6B11008D995D /* POPSpringAnimationTests.mm */; }; + 0755AEA11BEA19F40094AB41 /* POPEaseInEaseOutAnimationTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = EC7D2CFB1795AB3100E50A78 /* POPEaseInEaseOutAnimationTests.mm */; }; + 0755AEA21BEA19F40094AB41 /* POPCustomAnimationTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = EC72875418E13348006EEE54 /* POPCustomAnimationTests.mm */; }; + 0755AEA31BEA19F40094AB41 /* POPBasicAnimationTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = EC6C098819141BBD00F8EA96 /* POPBasicAnimationTests.mm */; }; + 0B6BE76819FFD3FF00762101 /* POPAnimationTracer.h in Headers */ = {isa = PBXBuildFile; fileRef = EC35DB2618EE3E820023E077 /* POPAnimationTracer.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 0B6BE76919FFD40700762101 /* POP.h in Headers */ = {isa = PBXBuildFile; fileRef = ECA94D0B18ECAE82002E4CEB /* POP.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 0B6BE76A19FFD41100762101 /* POPAnimationEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = EC9997531756A0C300A73F49 /* POPAnimationEvent.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 0B6BE76B19FFD41500762101 /* POPDefines.h in Headers */ = {isa = PBXBuildFile; fileRef = EC91E95F18C00EC90025B8AD /* POPDefines.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 0B6BE76C19FFD41D00762101 /* POPDecayAnimation.h in Headers */ = {isa = PBXBuildFile; fileRef = EC8F015A18FFBE8C00DF8905 /* POPDecayAnimation.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 0B6BE76D19FFD42700762101 /* POPAnimationExtras.h in Headers */ = {isa = PBXBuildFile; fileRef = EC0AE12F16BC73CE001DA2CE /* POPAnimationExtras.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 0B6BE76E19FFD43800762101 /* POPCustomAnimation.h in Headers */ = {isa = PBXBuildFile; fileRef = 5E17BB1E17457345009842B6 /* POPCustomAnimation.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 0B6BE76F19FFD44000762101 /* POPSpringAnimation.h in Headers */ = {isa = PBXBuildFile; fileRef = EC8F016618FFBEB500DF8905 /* POPSpringAnimation.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 0B6BE77019FFD46600762101 /* POPLayerExtras.h in Headers */ = {isa = PBXBuildFile; fileRef = EC94B07B17D95CAA003CE2C8 /* POPLayerExtras.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 0B6BE77119FFD46F00762101 /* POPAnimatorPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = EC19128D162FB5B700E0CC76 /* POPAnimatorPrivate.h */; }; + 0B6BE77219FFD47800762101 /* POPPropertyAnimation.h in Headers */ = {isa = PBXBuildFile; fileRef = EC8F013E18FFBBD300DF8905 /* POPPropertyAnimation.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 0B6BE77319FFD47F00762101 /* POPBasicAnimation.h in Headers */ = {isa = PBXBuildFile; fileRef = EC8F014D18FFBD3E00DF8905 /* POPBasicAnimation.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 0B6BE77419FFD48700762101 /* POPAnimatableProperty.h in Headers */ = {isa = PBXBuildFile; fileRef = EC19128E162FB5B700E0CC76 /* POPAnimatableProperty.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 0B6BE77519FFD49100762101 /* POPAnimator.h in Headers */ = {isa = PBXBuildFile; fileRef = EC19128B162FB5B700E0CC76 /* POPAnimator.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 0B6BE77619FFD49A00762101 /* POPAnimation.h in Headers */ = {isa = PBXBuildFile; fileRef = EC191288162FB5B700E0CC76 /* POPAnimation.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 0B6BE77719FFD4A300762101 /* POPAnimationPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = EC1CD94E18D80A5C00DE2649 /* POPAnimationPrivate.h */; }; + 0B6BE77819FFD4AB00762101 /* POPGeometry.h in Headers */ = {isa = PBXBuildFile; fileRef = ECD80F0F18CFD2EF00AE4303 /* POPGeometry.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 0B6BE7D019FFD90F00762101 /* TransformationMatrix.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EC94B07717D95447003CE2C8 /* TransformationMatrix.cpp */; }; + 0B6BE7D119FFD92700762101 /* POPAnimation.mm in Sources */ = {isa = PBXBuildFile; fileRef = EC191289162FB5B700E0CC76 /* POPAnimation.mm */; }; + 0B6BE7D219FFD92700762101 /* POPPropertyAnimation.mm in Sources */ = {isa = PBXBuildFile; fileRef = EC8F014A18FFBC8200DF8905 /* POPPropertyAnimation.mm */; }; + 0B6BE7D319FFD92700762101 /* POPBasicAnimation.mm in Sources */ = {isa = PBXBuildFile; fileRef = EC8F014E18FFBD3E00DF8905 /* POPBasicAnimation.mm */; }; + 0B6BE7D419FFD92700762101 /* POPCustomAnimation.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5E17BB1F17457345009842B6 /* POPCustomAnimation.mm */; }; + 0B6BE7D519FFD92700762101 /* POPDecayAnimation.mm in Sources */ = {isa = PBXBuildFile; fileRef = EC8F015B18FFBE8C00DF8905 /* POPDecayAnimation.mm */; }; + 0B6BE7D619FFD92700762101 /* POPSpringAnimation.mm in Sources */ = {isa = PBXBuildFile; fileRef = EC8F016718FFBEB500DF8905 /* POPSpringAnimation.mm */; }; + 0B6BE7D719FFD92700762101 /* POPAnimatableProperty.mm in Sources */ = {isa = PBXBuildFile; fileRef = EC19128F162FB5B700E0CC76 /* POPAnimatableProperty.mm */; }; + 0B6BE7D819FFD92700762101 /* POPAnimationEvent.mm in Sources */ = {isa = PBXBuildFile; fileRef = EC9997541756A0C300A73F49 /* POPAnimationEvent.mm */; }; + 0B6BE7D919FFD92700762101 /* POPAnimationExtras.mm in Sources */ = {isa = PBXBuildFile; fileRef = EC0AE13016BC73CE001DA2CE /* POPAnimationExtras.mm */; }; + 0B6BE7DA19FFD92700762101 /* POPAnimationRuntime.mm in Sources */ = {isa = PBXBuildFile; fileRef = EC95538F1743E278001E6AF2 /* POPAnimationRuntime.mm */; }; + 0B6BE7DB19FFD92700762101 /* POPAnimationTracer.mm in Sources */ = {isa = PBXBuildFile; fileRef = EC35DB2718EE3E820023E077 /* POPAnimationTracer.mm */; }; + 0B6BE7DC19FFD92700762101 /* POPAnimator.mm in Sources */ = {isa = PBXBuildFile; fileRef = EC19128C162FB5B700E0CC76 /* POPAnimator.mm */; }; + 0B6BE7DD19FFD92700762101 /* POPCGUtils.mm in Sources */ = {isa = PBXBuildFile; fileRef = EC67007118D3D89F00F7387F /* POPCGUtils.mm */; }; + 0B6BE7DE19FFD92700762101 /* POPGeometry.mm in Sources */ = {isa = PBXBuildFile; fileRef = ECD80F1018CFD2EF00AE4303 /* POPGeometry.mm */; }; + 0B6BE7DF19FFD92700762101 /* POPLayerExtras.mm in Sources */ = {isa = PBXBuildFile; fileRef = EC94B07C17D95CAA003CE2C8 /* POPLayerExtras.mm */; }; + 0B6BE7E019FFD92800762101 /* POPMath.mm in Sources */ = {isa = PBXBuildFile; fileRef = EC6465CF1794B4660014176F /* POPMath.mm */; }; + 0B6BE7E119FFD92800762101 /* POPVector.mm in Sources */ = {isa = PBXBuildFile; fileRef = EC70AC4218CCF4FC0067018C /* POPVector.mm */; }; + 0BB8E7B920A498AA00AAA7F1 /* POPVector.h in Headers */ = {isa = PBXBuildFile; fileRef = EC70AC4318CCF4FC0067018C /* POPVector.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 0BB8E7BA20A498C900AAA7F1 /* POPVector.h in Headers */ = {isa = PBXBuildFile; fileRef = EC70AC4318CCF4FC0067018C /* POPVector.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 181893701B3B7763002C4A59 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = ECC5A887162FBD6200F7F15C /* QuartzCore.framework */; }; + 181893711B3B7767002C4A59 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = ECC5A89D162FBD9B00F7F15C /* CoreGraphics.framework */; }; + 181893721B3B776A002C4A59 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EC19121B162FB53A00E0CC76 /* Foundation.framework */; }; + 181893741B3B776B002C4A59 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 181893731B3B776B002C4A59 /* CoreFoundation.framework */; }; + 181893751B3B777A002C4A59 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = ECC5A887162FBD6200F7F15C /* QuartzCore.framework */; }; + 181893761B3B777E002C4A59 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = ECEED93D18C91ACF00DD95F2 /* UIKit.framework */; }; + 181893771B3B7781002C4A59 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 181893731B3B776B002C4A59 /* CoreFoundation.framework */; }; + 181893781B3B7781002C4A59 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EC19121B162FB53A00E0CC76 /* Foundation.framework */; }; + 181893791B3B7785002C4A59 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = ECC5A89D162FBD9B00F7F15C /* CoreGraphics.framework */; }; + 1818937A1B3B77B2002C4A59 /* CoreImage.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0B6BE7E619FFD98100762101 /* CoreImage.framework */; }; + 1818937B1B3B77B7002C4A59 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = ECEED93D18C91ACF00DD95F2 /* UIKit.framework */; }; + 1818937C1B3B77BB002C4A59 /* CoreImage.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0B6BE7E619FFD98100762101 /* CoreImage.framework */; }; + 1818937E1B3B79D7002C4A59 /* pop-tests-osx-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 1818937D1B3B79D7002C4A59 /* pop-tests-osx-Info.plist */; }; + 1836BBE41B3B7B9C0041334F /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1836BBE31B3B7B9C0041334F /* Cocoa.framework */; }; + 4A5B97399E5024273715DD47 /* libPods-Tests-pop-tests-ios.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 0648E9DF7DFD7360DDB00E86 /* libPods-Tests-pop-tests-ios.a */; }; + 5C8B2FCA1E847C1000A6A646 /* POPAnimatablePropertyTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = 5C8B2FC91E847C1000A6A646 /* POPAnimatablePropertyTypes.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 5C8B2FCB1E847C4700A6A646 /* POPAnimatablePropertyTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = 5C8B2FC91E847C1000A6A646 /* POPAnimatablePropertyTypes.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 5C8B2FCC1E847C4700A6A646 /* POPAnimatablePropertyTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = 5C8B2FC91E847C1000A6A646 /* POPAnimatablePropertyTypes.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 5C8B2FCF1E847C4B00A6A646 /* POPAnimatablePropertyTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = 5C8B2FC91E847C1000A6A646 /* POPAnimatablePropertyTypes.h */; settings = {ATTRIBUTES = (Public, ); }; }; 5E17BB2017457345009842B6 /* POPCustomAnimation.h in Headers */ = {isa = PBXBuildFile; fileRef = 5E17BB1E17457345009842B6 /* POPCustomAnimation.h */; settings = {ATTRIBUTES = (Public, ); }; }; 5E17BB2117457345009842B6 /* POPCustomAnimation.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5E17BB1F17457345009842B6 /* POPCustomAnimation.mm */; }; + 6868EA130B28C6C61C4A4BD2 /* libPods-Tests-pop-tests-osx.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 432CE3E78A1381BD39B03505 /* libPods-Tests-pop-tests-osx.a */; }; + 810EC68A1CE2E19000BE2B9C /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 810EC6891CE2E19000BE2B9C /* UIKit.framework */; }; + 810EC6951CE2E19700BE2B9C /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 810EC6941CE2E19700BE2B9C /* CoreGraphics.framework */; }; + 810EC69F1CE2E19C00BE2B9C /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 810EC69E1CE2E19C00BE2B9C /* QuartzCore.framework */; }; + 810EC6B71CE2E1BE00BE2B9C /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 810EC6B61CE2E1BE00BE2B9C /* CoreGraphics.framework */; }; + 810EC6C51CE2E1E000BE2B9C /* AppKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 810EC6C41CE2E1E000BE2B9C /* AppKit.framework */; }; + 816FEE211FFC68130069EF43 /* pop.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0B6BE74819FFD3B900762101 /* pop.framework */; }; 90AA30B718988BBE00E3BDF7 /* POPSpringSolver.h in Headers */ = {isa = PBXBuildFile; fileRef = 90AA30B618988BBE00E3BDF7 /* POPSpringSolver.h */; }; - ADE1BB0636F940EC8EA7EE57 /* libPods-pop-tests-osx.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D411892A480A401FB4D1AA07 /* libPods-pop-tests-osx.a */; }; - BFD8EB4ECB184EF99C22123A /* libPods-pop-tests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D075ECD10B62441CBB9A90F6 /* libPods-pop-tests.a */; }; + C6DB62F0D381303B499E49C7 /* libPods-Tests-pop-tests-tvos.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 62526242E5E68FDF16B4B25D /* libPods-Tests-pop-tests-tvos.a */; }; EC0AE13116BC73CE001DA2CE /* POPAnimationExtras.h in Headers */ = {isa = PBXBuildFile; fileRef = EC0AE12F16BC73CE001DA2CE /* POPAnimationExtras.h */; settings = {ATTRIBUTES = (Public, ); }; }; EC0AE13216BC73CE001DA2CE /* POPAnimationExtras.mm in Sources */ = {isa = PBXBuildFile; fileRef = EC0AE13016BC73CE001DA2CE /* POPAnimationExtras.mm */; }; - EC19121C162FB53A00E0CC76 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EC19121B162FB53A00E0CC76 /* Foundation.framework */; }; EC191291162FB5B700E0CC76 /* POPAnimation.mm in Sources */ = {isa = PBXBuildFile; fileRef = EC191289162FB5B700E0CC76 /* POPAnimation.mm */; }; EC191292162FB5B700E0CC76 /* POPAnimator.mm in Sources */ = {isa = PBXBuildFile; fileRef = EC19128C162FB5B700E0CC76 /* POPAnimator.mm */; }; EC191293162FB5B700E0CC76 /* POPAnimatableProperty.mm in Sources */ = {isa = PBXBuildFile; fileRef = EC19128F162FB5B700E0CC76 /* POPAnimatableProperty.mm */; }; @@ -39,8 +153,6 @@ EC67007518D3D89F00F7387F /* POPCGUtils.mm in Sources */ = {isa = PBXBuildFile; fileRef = EC67007118D3D89F00F7387F /* POPCGUtils.mm */; }; EC67007618D3D96500F7387F /* POPCGUtils.mm in Sources */ = {isa = PBXBuildFile; fileRef = EC67007118D3D89F00F7387F /* POPCGUtils.mm */; }; EC67007718D3D96600F7387F /* POPCGUtils.mm in Sources */ = {isa = PBXBuildFile; fileRef = EC67007118D3D89F00F7387F /* POPCGUtils.mm */; }; - EC68858118C7B60000C6194C /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EC68858018C7B60000C6194C /* Cocoa.framework */; }; - EC68858B18C7B60000C6194C /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = EC68858918C7B60000C6194C /* InfoPlist.strings */; }; EC6885B018C7BD0A00C6194C /* POPAnimatableProperty.h in Headers */ = {isa = PBXBuildFile; fileRef = EC19128E162FB5B700E0CC76 /* POPAnimatableProperty.h */; settings = {ATTRIBUTES = (Public, ); }; }; EC6885B118C7BD1000C6194C /* POPAnimatableProperty.mm in Sources */ = {isa = PBXBuildFile; fileRef = EC19128F162FB5B700E0CC76 /* POPAnimatableProperty.mm */; }; EC6885B318C7BD1500C6194C /* POPAnimation.h in Headers */ = {isa = PBXBuildFile; fileRef = EC191288162FB5B700E0CC76 /* POPAnimation.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -69,14 +181,14 @@ EC6885D118C7BD8500C6194C /* TransformationMatrix.h in Headers */ = {isa = PBXBuildFile; fileRef = EC94B07817D95447003CE2C8 /* TransformationMatrix.h */; }; EC6885D218C7BD8900C6194C /* TransformationMatrix.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EC94B07717D95447003CE2C8 /* TransformationMatrix.cpp */; }; EC6885D418C7C44E00C6194C /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EC6885D318C7C44E00C6194C /* QuartzCore.framework */; }; + EC6C098919141BBD00F8EA96 /* POPBasicAnimationTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = EC6C098819141BBD00F8EA96 /* POPBasicAnimationTests.mm */; }; + EC6C098A19141BBD00F8EA96 /* POPBasicAnimationTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = EC6C098819141BBD00F8EA96 /* POPBasicAnimationTests.mm */; }; EC70AC4418CCF4FC0067018C /* POPVector.mm in Sources */ = {isa = PBXBuildFile; fileRef = EC70AC4218CCF4FC0067018C /* POPVector.mm */; }; EC70AC4518CCF4FC0067018C /* POPVector.mm in Sources */ = {isa = PBXBuildFile; fileRef = EC70AC4218CCF4FC0067018C /* POPVector.mm */; }; - EC70AC4618CCF4FC0067018C /* POPVector.h in Headers */ = {isa = PBXBuildFile; fileRef = EC70AC4318CCF4FC0067018C /* POPVector.h */; }; - EC70AC4718CCF4FC0067018C /* POPVector.h in Headers */ = {isa = PBXBuildFile; fileRef = EC70AC4318CCF4FC0067018C /* POPVector.h */; }; + EC70AC4618CCF4FC0067018C /* POPVector.h in Headers */ = {isa = PBXBuildFile; fileRef = EC70AC4318CCF4FC0067018C /* POPVector.h */; settings = {ATTRIBUTES = (Public, ); }; }; + EC70AC4718CCF4FC0067018C /* POPVector.h in Headers */ = {isa = PBXBuildFile; fileRef = EC70AC4318CCF4FC0067018C /* POPVector.h */; settings = {ATTRIBUTES = (Public, ); }; }; EC72875518E13348006EEE54 /* POPCustomAnimationTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = EC72875418E13348006EEE54 /* POPCustomAnimationTests.mm */; }; EC72875618E13348006EEE54 /* POPCustomAnimationTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = EC72875418E13348006EEE54 /* POPCustomAnimationTests.mm */; }; - EC7E319A18C93D6500B38170 /* SenTestingKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EC19122A162FB53A00E0CC76 /* SenTestingKit.framework */; }; - EC7E31A018C93D6500B38170 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = EC7E319E18C93D6500B38170 /* InfoPlist.strings */; }; EC7E31AB18C9419000B38170 /* POPAnimatable.mm in Sources */ = {isa = PBXBuildFile; fileRef = EC99974A17568DAD00A73F49 /* POPAnimatable.mm */; }; EC7E31AC18C9419200B38170 /* POPBaseAnimationTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = EC6F55A4175E6641008D995D /* POPBaseAnimationTests.mm */; }; EC7E31AD18C9419600B38170 /* POPAnimationTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = EC191239162FB53A00E0CC76 /* POPAnimationTests.mm */; }; @@ -142,27 +254,32 @@ ECDA0CCD18C92BD200D14897 /* POPSpringAnimationTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = EC6F55AA175E6B11008D995D /* POPSpringAnimationTests.mm */; }; ECDA0CCE18C92BD200D14897 /* POPEaseInEaseOutAnimationTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = EC7D2CFB1795AB3100E50A78 /* POPEaseInEaseOutAnimationTests.mm */; }; ECDA0CCF18C92C3E00D14897 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = ECC5A887162FBD6200F7F15C /* QuartzCore.framework */; }; - ECDA0CD018C92C4C00D14897 /* libpop.a in Frameworks */ = {isa = PBXBuildFile; fileRef = EC191218162FB53A00E0CC76 /* libpop.a */; }; ECDA0CD118C92D3900D14897 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = ECC5A89D162FBD9B00F7F15C /* CoreGraphics.framework */; }; - ECF01ED418C92B7F009E0AD1 /* SenTestingKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EC19122A162FB53A00E0CC76 /* SenTestingKit.framework */; }; ECF01ED518C92B7F009E0AD1 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EC19121B162FB53A00E0CC76 /* Foundation.framework */; }; ECF01ED618C92B7F009E0AD1 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = ECEED93D18C91ACF00DD95F2 /* UIKit.framework */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ - EC7E31A418C93D6600B38170 /* PBXContainerItemProxy */ = { + 0755AE921BEA19580094AB41 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = EC19120F162FB53A00E0CC76 /* Project object */; proxyType = 1; - remoteGlobalIDString = EC68857E18C7B60000C6194C; - remoteInfo = "POP-OSX"; + remoteGlobalIDString = 0755AE4E1BEA15950094AB41; + remoteInfo = "pop-tvos-framework"; + }; + 816FEE221FFC68370069EF43 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = EC19120F162FB53A00E0CC76 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 0B6BE74719FFD3B900762101; + remoteInfo = "pop-ios-framework"; }; - ECF01EE018C92B80009E0AD1 /* PBXContainerItemProxy */ = { + EC7E31A418C93D6600B38170 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = EC19120F162FB53A00E0CC76 /* Project object */; proxyType = 1; - remoteGlobalIDString = EC191217162FB53A00E0CC76; - remoteInfo = POP; + remoteGlobalIDString = EC68857E18C7B60000C6194C; + remoteInfo = "POP-OSX"; }; /* End PBXContainerItemProxy section */ @@ -179,28 +296,49 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ - 02E3EF56E92B403A9BF79E26 /* boost */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = archive.ar; name = boost; path = ../../Vendor/Boost/boost.framework/boost; sourceTree = SRCROOT; }; - 403DCBBC1783F4A000793AE1 /* libFBWebP.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libFBWebP.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 04C0670F1B8D577C00ED0525 /* Framework.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Framework.xcconfig; sourceTree = ""; }; + 0648E9DF7DFD7360DDB00E86 /* libPods-Tests-pop-tests-ios.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Tests-pop-tests-ios.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + 0755AE4F1BEA15950094AB41 /* pop.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = pop.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 0755AE531BEA15950094AB41 /* pop-tvos-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = "pop-tvos-Info.plist"; path = "pop-tvos-framework/pop-tvos-Info.plist"; sourceTree = SOURCE_ROOT; }; + 0755AE581BEA15A80094AB41 /* CoreImage.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreImage.framework; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS9.0.sdk/System/Library/Frameworks/CoreImage.framework; sourceTree = DEVELOPER_DIR; }; + 0755AE5A1BEA15B30094AB41 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS9.0.sdk/System/Library/Frameworks/UIKit.framework; sourceTree = DEVELOPER_DIR; }; + 0755AE5C1BEA15BA0094AB41 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS9.0.sdk/System/Library/Frameworks/CoreFoundation.framework; sourceTree = DEVELOPER_DIR; }; + 0755AE5E1BEA15BF0094AB41 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS9.0.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; + 0755AE601BEA15C60094AB41 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS9.0.sdk/System/Library/Frameworks/CoreGraphics.framework; sourceTree = DEVELOPER_DIR; }; + 0755AE621BEA15CB0094AB41 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS9.0.sdk/System/Library/Frameworks/QuartzCore.framework; sourceTree = DEVELOPER_DIR; }; + 0755AE8C1BEA19580094AB41 /* pop-tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "pop-tests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; + 0755AE901BEA19580094AB41 /* pop-tvos-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = "pop-tvos-Info.plist"; path = "pop/pop-tvos-Info.plist"; sourceTree = SOURCE_ROOT; }; + 0B6BE74819FFD3B900762101 /* pop.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = pop.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 0B6BE7E619FFD98100762101 /* CoreImage.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreImage.framework; path = System/Library/Frameworks/CoreImage.framework; sourceTree = SDKROOT; }; + 1818936D1B3B74DE002C4A59 /* pop-ios-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "pop-ios-Info.plist"; path = "pop/pop-ios-Info.plist"; sourceTree = SOURCE_ROOT; }; + 181893731B3B776B002C4A59 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = System/Library/Frameworks/CoreFoundation.framework; sourceTree = SDKROOT; }; + 1818937D1B3B79D7002C4A59 /* pop-tests-osx-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "pop-tests-osx-Info.plist"; path = "pop-tests/pop-tests-osx-Info.plist"; sourceTree = SOURCE_ROOT; }; + 1836BBE31B3B7B9C0041334F /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.10.sdk/System/Library/Frameworks/Cocoa.framework; sourceTree = DEVELOPER_DIR; }; + 406331B5EF869E167FFA3454 /* Pods-Tests-pop-tests-osx.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Tests-pop-tests-osx.profile.xcconfig"; path = "Pods/Target Support Files/Pods-Tests-pop-tests-osx/Pods-Tests-pop-tests-osx.profile.xcconfig"; sourceTree = ""; }; + 432CE3E78A1381BD39B03505 /* libPods-Tests-pop-tests-osx.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Tests-pop-tests-osx.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + 55AC0296922C5E9D7B593C59 /* Pods-Tests-pop-tests-osx.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Tests-pop-tests-osx.release.xcconfig"; path = "Pods/Target Support Files/Pods-Tests-pop-tests-osx/Pods-Tests-pop-tests-osx.release.xcconfig"; sourceTree = ""; }; + 55EA9621113E7E17CB5A65C3 /* Pods-Tests-pop-tests-tvos.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Tests-pop-tests-tvos.profile.xcconfig"; path = "Pods/Target Support Files/Pods-Tests-pop-tests-tvos/Pods-Tests-pop-tests-tvos.profile.xcconfig"; sourceTree = ""; }; + 5677DA2A8DA5A9DF667D2F25 /* Pods-Tests-pop-tests-osx.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Tests-pop-tests-osx.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Tests-pop-tests-osx/Pods-Tests-pop-tests-osx.debug.xcconfig"; sourceTree = ""; }; + 5C8B2FC91E847C1000A6A646 /* POPAnimatablePropertyTypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = POPAnimatablePropertyTypes.h; sourceTree = ""; }; 5E17BB1E17457345009842B6 /* POPCustomAnimation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = POPCustomAnimation.h; sourceTree = ""; }; 5E17BB1F17457345009842B6 /* POPCustomAnimation.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = POPCustomAnimation.mm; sourceTree = ""; }; - 68569BF4084F464294AFEBA1 /* libFBReachability.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libFBReachability.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 62526242E5E68FDF16B4B25D /* libPods-Tests-pop-tests-tvos.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Tests-pop-tests-tvos.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + 66F8502AAF59876387597FEC /* Pods-Tests-pop-tests-tvos.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Tests-pop-tests-tvos.release.xcconfig"; path = "Pods/Target Support Files/Pods-Tests-pop-tests-tvos/Pods-Tests-pop-tests-tvos.release.xcconfig"; sourceTree = ""; }; + 75AB0405A39E769FDEA67DFE /* Pods-Tests-pop-tests-tvos.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Tests-pop-tests-tvos.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Tests-pop-tests-tvos/Pods-Tests-pop-tests-tvos.debug.xcconfig"; sourceTree = ""; }; + 810EC6891CE2E19000BE2B9C /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS9.2.sdk/System/Library/Frameworks/UIKit.framework; sourceTree = DEVELOPER_DIR; }; + 810EC6941CE2E19700BE2B9C /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS9.2.sdk/System/Library/Frameworks/CoreGraphics.framework; sourceTree = DEVELOPER_DIR; }; + 810EC69E1CE2E19C00BE2B9C /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS9.2.sdk/System/Library/Frameworks/QuartzCore.framework; sourceTree = DEVELOPER_DIR; }; + 810EC6B61CE2E1BE00BE2B9C /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/System/Library/Frameworks/CoreGraphics.framework; sourceTree = DEVELOPER_DIR; }; + 810EC6C41CE2E1E000BE2B9C /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/System/Library/Frameworks/AppKit.framework; sourceTree = DEVELOPER_DIR; }; + 84EDB88DF38CE22AC4893B65 /* Pods-Tests-pop-tests-ios.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Tests-pop-tests-ios.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Tests-pop-tests-ios/Pods-Tests-pop-tests-ios.debug.xcconfig"; sourceTree = ""; }; + 85D44E5C12C69E1AC9E27D0B /* Pods-Tests-pop-tests-ios.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Tests-pop-tests-ios.release.xcconfig"; path = "Pods/Target Support Files/Pods-Tests-pop-tests-ios/Pods-Tests-pop-tests-ios.release.xcconfig"; sourceTree = ""; }; 90AA30B618988BBE00E3BDF7 /* POPSpringSolver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = POPSpringSolver.h; sourceTree = ""; }; - B551F115E86E4C7CA0D92E78 /* libDoubleConversion.a */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = archive.ar; path = libDoubleConversion.a; sourceTree = BUILT_PRODUCTS_DIR; }; - BD1A8D5BCA37415F86519334 /* libCAres.a */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = archive.ar; path = libCAres.a; sourceTree = BUILT_PRODUCTS_DIR; }; - C4E7267217CE4436805A912B /* libFBCoreDataKit.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libFBCoreDataKit.a; sourceTree = BUILT_PRODUCTS_DIR; }; - CD38BFD00B29456D9B40D640 /* Pods-pop-tests.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-pop-tests.xcconfig"; path = "Pods/Pods-pop-tests.xcconfig"; sourceTree = ""; }; - D075ECD10B62441CBB9A90F6 /* libPods-pop-tests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-pop-tests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; - D411892A480A401FB4D1AA07 /* libPods-pop-tests-osx.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-pop-tests-osx.a"; sourceTree = BUILT_PRODUCTS_DIR; }; - D49ED131870840178CA788F1 /* Pods-pop-tests-osx.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-pop-tests-osx.xcconfig"; path = "Pods/Pods-pop-tests-osx.xcconfig"; sourceTree = ""; }; - D52A06EC505A4B82B3BBD5E6 /* libEvent.a */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = archive.ar; path = libEvent.a; sourceTree = BUILT_PRODUCTS_DIR; }; - E5D894724A104C729754ABCA /* libGLog.a */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = archive.ar; path = libGLog.a; sourceTree = BUILT_PRODUCTS_DIR; }; + CD42CE6B1B541B1300EC9556 /* module.modulemap */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.module-map"; name = module.modulemap; path = pop/module.modulemap; sourceTree = SOURCE_ROOT; }; + D35FAC2FD6DFC1CC1BD1A636 /* Pods-Tests-pop-tests-ios.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Tests-pop-tests-ios.profile.xcconfig"; path = "Pods/Target Support Files/Pods-Tests-pop-tests-ios/Pods-Tests-pop-tests-ios.profile.xcconfig"; sourceTree = ""; }; EC0AE12F16BC73CE001DA2CE /* POPAnimationExtras.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = POPAnimationExtras.h; sourceTree = ""; }; EC0AE13016BC73CE001DA2CE /* POPAnimationExtras.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = POPAnimationExtras.mm; sourceTree = ""; }; EC191218162FB53A00E0CC76 /* libpop.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libpop.a; sourceTree = BUILT_PRODUCTS_DIR; }; EC19121B162FB53A00E0CC76 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; - EC19121F162FB53A00E0CC76 /* POP-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "POP-Prefix.pch"; path = "../pop/POP-Prefix.pch"; sourceTree = ""; }; - EC19122A162FB53A00E0CC76 /* SenTestingKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SenTestingKit.framework; path = Library/Frameworks/SenTestingKit.framework; sourceTree = DEVELOPER_DIR; }; - EC19122C162FB53A00E0CC76 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = Library/Frameworks/UIKit.framework; sourceTree = DEVELOPER_DIR; }; EC191239162FB53A00E0CC76 /* POPAnimationTests.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = POPAnimationTests.mm; sourceTree = ""; }; EC191288162FB5B700E0CC76 /* POPAnimation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = POPAnimation.h; sourceTree = ""; }; EC191289162FB5B700E0CC76 /* POPAnimation.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = POPAnimation.mm; sourceTree = ""; }; @@ -222,15 +360,9 @@ EC67007018D3D89F00F7387F /* POPCGUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = POPCGUtils.h; sourceTree = ""; }; EC67007118D3D89F00F7387F /* POPCGUtils.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = POPCGUtils.mm; sourceTree = ""; }; EC68857F18C7B60000C6194C /* pop.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = pop.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - EC68858018C7B60000C6194C /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = Library/Frameworks/Cocoa.framework; sourceTree = DEVELOPER_DIR; }; - EC68858318C7B60000C6194C /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; - EC68858418C7B60000C6194C /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; }; - EC68858518C7B60000C6194C /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; }; - EC68858818C7B60000C6194C /* pop-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "pop-Info.plist"; sourceTree = ""; }; - EC68858A18C7B60000C6194C /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; - EC68858C18C7B60000C6194C /* pop-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "pop-Prefix.pch"; sourceTree = ""; }; - EC68859518C7B60100C6194C /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; + EC68858818C7B60000C6194C /* pop-osx-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "pop-osx-Info.plist"; sourceTree = ""; }; EC6885D318C7C44E00C6194C /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk/System/Library/Frameworks/QuartzCore.framework; sourceTree = DEVELOPER_DIR; }; + EC6C098819141BBD00F8EA96 /* POPBasicAnimationTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = POPBasicAnimationTests.mm; sourceTree = ""; }; EC6F55A1175E654B008D995D /* POPDecayAnimationTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = POPDecayAnimationTests.mm; sourceTree = ""; }; EC6F55A3175E6641008D995D /* POPBaseAnimationTests.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = POPBaseAnimationTests.h; sourceTree = ""; }; EC6F55A4175E6641008D995D /* POPBaseAnimationTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = POPBaseAnimationTests.mm; sourceTree = ""; }; @@ -239,13 +371,8 @@ EC70AC4318CCF4FC0067018C /* POPVector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = POPVector.h; sourceTree = ""; }; EC72875418E13348006EEE54 /* POPCustomAnimationTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = POPCustomAnimationTests.mm; sourceTree = ""; }; EC7D2CFB1795AB3100E50A78 /* POPEaseInEaseOutAnimationTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = POPEaseInEaseOutAnimationTests.mm; sourceTree = ""; }; - EC7E319918C93D6500B38170 /* pop-tests-osx.octest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "pop-tests-osx.octest"; sourceTree = BUILT_PRODUCTS_DIR; }; - EC7E319D18C93D6500B38170 /* pop-tests-osx-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "pop-tests-osx-Info.plist"; sourceTree = ""; }; - EC7E319F18C93D6500B38170 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; - EC7E31A318C93D6500B38170 /* pop-tests-osx-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "pop-tests-osx-Prefix.pch"; sourceTree = ""; }; - EC882A7718C91983007829CC /* pop-tests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "pop-tests-Info.plist"; sourceTree = ""; }; - EC882A7918C91983007829CC /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; - EC882A7D18C91983007829CC /* pop-tests-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "pop-tests-Prefix.pch"; sourceTree = ""; }; + EC7E319918C93D6500B38170 /* pop-tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "pop-tests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; + EC882A7718C91983007829CC /* pop-tests-ios-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "pop-tests-ios-Info.plist"; sourceTree = ""; }; EC8F013E18FFBBD300DF8905 /* POPPropertyAnimation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = POPPropertyAnimation.h; sourceTree = ""; }; EC8F014418FFBC2D00DF8905 /* POPPropertyAnimationInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = POPPropertyAnimationInternal.h; sourceTree = ""; }; EC8F014A18FFBC8200DF8905 /* POPPropertyAnimation.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = POPPropertyAnimation.mm; sourceTree = ""; }; @@ -274,65 +401,72 @@ EC9997571756A17B00A73F49 /* POPAnimationEventInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = POPAnimationEventInternal.h; sourceTree = ""; }; ECA0D5BF18D8196A003720DF /* UnitBezier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = UnitBezier.h; path = WebCore/UnitBezier.h; sourceTree = ""; }; ECA94D0B18ECAE82002E4CEB /* POP.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = POP.h; path = pop/POP.h; sourceTree = SOURCE_ROOT; }; - ECADA2A416A8A99E00A20182 /* libMessagePack.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libMessagePack.a; sourceTree = BUILT_PRODUCTS_DIR; }; - ECADA2A516A8A99E00A20182 /* libSPDY.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libSPDY.a; sourceTree = BUILT_PRODUCTS_DIR; }; - ECC1DB0918CA291B008C7DEA /* Application-iOS.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Application-iOS.xcconfig"; sourceTree = ""; }; - ECC1DB0A18CA291B008C7DEA /* Application-OSX.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Application-OSX.xcconfig"; sourceTree = ""; }; - ECC1DB0B18CA291B008C7DEA /* Base-iOS.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Base-iOS.xcconfig"; sourceTree = ""; }; - ECC1DB0C18CA291B008C7DEA /* Base-OSX.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Base-OSX.xcconfig"; sourceTree = ""; }; - ECC1DB0E18CA291B008C7DEA /* Compiler.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Compiler.xcconfig; sourceTree = ""; }; - ECC1DB0F18CA291B008C7DEA /* iOS.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = iOS.xcconfig; sourceTree = ""; }; - ECC1DB1018CA291B008C7DEA /* OSX.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = OSX.xcconfig; sourceTree = ""; }; + ECC1DB0B18CA291B008C7DEA /* Compiler.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Compiler.xcconfig; sourceTree = ""; }; ECC1DB1218CA291B008C7DEA /* Project-Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Project-Debug.xcconfig"; sourceTree = ""; }; - ECC1DB1318CA291B008C7DEA /* Project-GCOV.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Project-GCOV.xcconfig"; sourceTree = ""; }; ECC1DB1618CA291B008C7DEA /* Project-Profile.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Project-Profile.xcconfig"; sourceTree = ""; }; ECC1DB1718CA291B008C7DEA /* Project-Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Project-Release.xcconfig"; sourceTree = ""; }; ECC1DB1818CA291B008C7DEA /* Project.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Project.xcconfig; sourceTree = ""; }; - ECC1DB1A18CA291B008C7DEA /* StaticLibrary-iOS.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "StaticLibrary-iOS.xcconfig"; sourceTree = ""; }; - ECC1DB1B18CA291B008C7DEA /* StaticLibrary-OSX.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "StaticLibrary-OSX.xcconfig"; sourceTree = ""; }; + ECC1DB1A18CA291B008C7DEA /* StaticLibrary.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = StaticLibrary.xcconfig; sourceTree = ""; }; ECC1DB1D18CA291B008C7DEA /* ApplicationTests.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = ApplicationTests.xcconfig; sourceTree = ""; }; - ECC1DB1E18CA291B008C7DEA /* LogicTests-iOS.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "LogicTests-iOS.xcconfig"; sourceTree = ""; }; - ECC1DB1F18CA291B008C7DEA /* LogicTests-OSX.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "LogicTests-OSX.xcconfig"; sourceTree = ""; }; + ECC1DB1E18CA291B008C7DEA /* LogicTests.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = LogicTests.xcconfig; sourceTree = ""; }; ECC5A887162FBD6200F7F15C /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; - ECC5A889162FBD7600F7F15C /* libFBAnalytics.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libFBAnalytics.a; sourceTree = BUILT_PRODUCTS_DIR; }; - ECC5A88B162FBD7600F7F15C /* libFBFoundation.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libFBFoundation.a; sourceTree = BUILT_PRODUCTS_DIR; }; - ECC5A88C162FBD7600F7F15C /* libFBProvider.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libFBProvider.a; sourceTree = BUILT_PRODUCTS_DIR; }; - ECC5A88D162FBD7600F7F15C /* libFBTest.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libFBTest.a; sourceTree = BUILT_PRODUCTS_DIR; }; - ECC5A88F162FBD7600F7F15C /* libOCMock.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libOCMock.a; sourceTree = BUILT_PRODUCTS_DIR; }; - ECC5A897162FBD8700F7F15C /* AddressBook.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AddressBook.framework; path = System/Library/Frameworks/AddressBook.framework; sourceTree = SDKROOT; }; - ECC5A899162FBD8E00F7F15C /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; - ECC5A89B162FBD9500F7F15C /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; }; ECC5A89D162FBD9B00F7F15C /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; - ECC5A89F162FBDA400F7F15C /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; }; - ECC5A8A1162FBDAB00F7F15C /* MobileCoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MobileCoreServices.framework; path = System/Library/Frameworks/MobileCoreServices.framework; sourceTree = SDKROOT; }; - ECC5A8A3162FBDC400F7F15C /* Accounts.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Accounts.framework; path = System/Library/Frameworks/Accounts.framework; sourceTree = SDKROOT; }; - ECC5A8A5162FBDCA00F7F15C /* AVFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AVFoundation.framework; path = System/Library/Frameworks/AVFoundation.framework; sourceTree = SDKROOT; }; - ECC5A8A7162FBDCF00F7F15C /* CoreLocation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreLocation.framework; path = System/Library/Frameworks/CoreLocation.framework; sourceTree = SDKROOT; }; - ECC5A8A9162FBDD800F7F15C /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; - ECC5A8AB162FBDE100F7F15C /* ImageIO.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ImageIO.framework; path = System/Library/Frameworks/ImageIO.framework; sourceTree = SDKROOT; }; - ECC5A8AD162FBDEB00F7F15C /* CoreText.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreText.framework; path = System/Library/Frameworks/CoreText.framework; sourceTree = SDKROOT; }; - ECC5A8AF162FBDF600F7F15C /* CoreTelephony.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreTelephony.framework; path = System/Library/Frameworks/CoreTelephony.framework; sourceTree = SDKROOT; }; - ECC5A8B1162FBE0400F7F15C /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = usr/lib/libz.dylib; sourceTree = SDKROOT; }; - ECC5A8B3162FBE0900F7F15C /* libicucore.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libicucore.dylib; path = usr/lib/libicucore.dylib; sourceTree = SDKROOT; }; - ECC5A8B5162FBE1600F7F15C /* AssetsLibrary.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AssetsLibrary.framework; path = System/Library/Frameworks/AssetsLibrary.framework; sourceTree = SDKROOT; }; - ECC5A8B7162FBE1B00F7F15C /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; }; - ECC5A8BA162FBF3A00F7F15C /* AdSupport.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AdSupport.framework; path = System/Library/Frameworks/AdSupport.framework; sourceTree = SDKROOT; }; - ECC63411C31441ECAC3F5559 /* libLiger.a */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = archive.ar; path = libLiger.a; sourceTree = BUILT_PRODUCTS_DIR; }; ECCBC57117D96DBD00C69976 /* FloatConversion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FloatConversion.h; path = WebCore/FloatConversion.h; sourceTree = ""; }; ECD80F0F18CFD2EF00AE4303 /* POPGeometry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = POPGeometry.h; sourceTree = ""; }; ECD80F1018CFD2EF00AE4303 /* POPGeometry.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = POPGeometry.mm; sourceTree = ""; }; - ECED421816F7D1FD00FFBEAC /* libFBNetworker.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libFBNetworker.a; sourceTree = BUILT_PRODUCTS_DIR; }; - ECEED93A18C91AB600DD95F2 /* libOCMock.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libOCMock.a; sourceTree = BUILT_PRODUCTS_DIR; }; ECEED93D18C91ACF00DD95F2 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; - ECF01ED318C92B7F009E0AD1 /* pop-tests.octest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "pop-tests.octest"; sourceTree = BUILT_PRODUCTS_DIR; }; + ECF01ED318C92B7F009E0AD1 /* pop-tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "pop-tests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ + 0755AE4B1BEA15950094AB41 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 0755AE631BEA15CB0094AB41 /* QuartzCore.framework in Frameworks */, + 0755AE611BEA15C60094AB41 /* CoreGraphics.framework in Frameworks */, + 0755AE5F1BEA15BF0094AB41 /* Foundation.framework in Frameworks */, + 0755AE5D1BEA15BA0094AB41 /* CoreFoundation.framework in Frameworks */, + 0755AE5B1BEA15B30094AB41 /* UIKit.framework in Frameworks */, + 0755AE591BEA15A80094AB41 /* CoreImage.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 0755AE891BEA19580094AB41 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 810EC69F1CE2E19C00BE2B9C /* QuartzCore.framework in Frameworks */, + 810EC6951CE2E19700BE2B9C /* CoreGraphics.framework in Frameworks */, + 810EC68A1CE2E19000BE2B9C /* UIKit.framework in Frameworks */, + 0755AE911BEA19580094AB41 /* pop.framework in Frameworks */, + C6DB62F0D381303B499E49C7 /* libPods-Tests-pop-tests-tvos.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 0B6BE74419FFD3B900762101 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 1818937C1B3B77BB002C4A59 /* CoreImage.framework in Frameworks */, + 1818937B1B3B77B7002C4A59 /* UIKit.framework in Frameworks */, + 181893741B3B776B002C4A59 /* CoreFoundation.framework in Frameworks */, + 181893721B3B776A002C4A59 /* Foundation.framework in Frameworks */, + 181893711B3B7767002C4A59 /* CoreGraphics.framework in Frameworks */, + 181893701B3B7763002C4A59 /* QuartzCore.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; EC191215162FB53A00E0CC76 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - EC19121C162FB53A00E0CC76 /* Foundation.framework in Frameworks */, + 1818937A1B3B77B2002C4A59 /* CoreImage.framework in Frameworks */, + 181893791B3B7785002C4A59 /* CoreGraphics.framework in Frameworks */, + 181893771B3B7781002C4A59 /* CoreFoundation.framework in Frameworks */, + 181893781B3B7781002C4A59 /* Foundation.framework in Frameworks */, + 181893761B3B777E002C4A59 /* UIKit.framework in Frameworks */, + 181893751B3B777A002C4A59 /* QuartzCore.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -340,8 +474,8 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 1836BBE41B3B7B9C0041334F /* Cocoa.framework in Frameworks */, EC6885D418C7C44E00C6194C /* QuartzCore.framework in Frameworks */, - EC68858118C7B60000C6194C /* Cocoa.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -349,10 +483,11 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 810EC6C51CE2E1E000BE2B9C /* AppKit.framework in Frameworks */, + 810EC6B71CE2E1BE00BE2B9C /* CoreGraphics.framework in Frameworks */, EC7E31B518C9422F00B38170 /* pop.framework in Frameworks */, EC7E31B418C9422600B38170 /* QuartzCore.framework in Frameworks */, - EC7E319A18C93D6500B38170 /* SenTestingKit.framework in Frameworks */, - ADE1BB0636F940EC8EA7EE57 /* libPods-pop-tests-osx.a in Frameworks */, + 6868EA130B28C6C61C4A4BD2 /* libPods-Tests-pop-tests-osx.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -360,19 +495,50 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 816FEE211FFC68130069EF43 /* pop.framework in Frameworks */, ECDA0CD118C92D3900D14897 /* CoreGraphics.framework in Frameworks */, - ECDA0CD018C92C4C00D14897 /* libpop.a in Frameworks */, ECDA0CCF18C92C3E00D14897 /* QuartzCore.framework in Frameworks */, - ECF01ED418C92B7F009E0AD1 /* SenTestingKit.framework in Frameworks */, ECF01ED618C92B7F009E0AD1 /* UIKit.framework in Frameworks */, ECF01ED518C92B7F009E0AD1 /* Foundation.framework in Frameworks */, - BFD8EB4ECB184EF99C22123A /* libPods-pop-tests.a in Frameworks */, + 4A5B97399E5024273715DD47 /* libPods-Tests-pop-tests-ios.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 0755AE641BEA16170094AB41 /* Supporting Files (tvOS) */ = { + isa = PBXGroup; + children = ( + 0755AE531BEA15950094AB41 /* pop-tvos-Info.plist */, + ); + name = "Supporting Files (tvOS)"; + sourceTree = ""; + }; + 0755AE981BEA197E0094AB41 /* Supporting Files (tvOS) */ = { + isa = PBXGroup; + children = ( + 0755AE901BEA19580094AB41 /* pop-tvos-Info.plist */, + ); + name = "Supporting Files (tvOS)"; + sourceTree = ""; + }; + 419601F3A7432256D076DE4C /* Pods */ = { + isa = PBXGroup; + children = ( + 84EDB88DF38CE22AC4893B65 /* Pods-Tests-pop-tests-ios.debug.xcconfig */, + 85D44E5C12C69E1AC9E27D0B /* Pods-Tests-pop-tests-ios.release.xcconfig */, + D35FAC2FD6DFC1CC1BD1A636 /* Pods-Tests-pop-tests-ios.profile.xcconfig */, + 5677DA2A8DA5A9DF667D2F25 /* Pods-Tests-pop-tests-osx.debug.xcconfig */, + 55AC0296922C5E9D7B593C59 /* Pods-Tests-pop-tests-osx.release.xcconfig */, + 406331B5EF869E167FFA3454 /* Pods-Tests-pop-tests-osx.profile.xcconfig */, + 75AB0405A39E769FDEA67DFE /* Pods-Tests-pop-tests-tvos.debug.xcconfig */, + 66F8502AAF59876387597FEC /* Pods-Tests-pop-tests-tvos.release.xcconfig */, + 55EA9621113E7E17CB5A65C3 /* Pods-Tests-pop-tests-tvos.profile.xcconfig */, + ); + name = Pods; + sourceTree = ""; + }; EC19120D162FB53A00E0CC76 = { isa = PBXGroup; children = ( @@ -381,8 +547,7 @@ ECC1DB0718CA291B008C7DEA /* Configuration */, EC19121A162FB53A00E0CC76 /* Frameworks */, EC191219162FB53A00E0CC76 /* Products */, - CD38BFD00B29456D9B40D640 /* Pods-pop-tests.xcconfig */, - D49ED131870840178CA788F1 /* Pods-pop-tests-osx.xcconfig */, + 419601F3A7432256D076DE4C /* Pods */, ); sourceTree = ""; }; @@ -391,8 +556,11 @@ children = ( EC191218162FB53A00E0CC76 /* libpop.a */, EC68857F18C7B60000C6194C /* pop.framework */, - ECF01ED318C92B7F009E0AD1 /* pop-tests.octest */, - EC7E319918C93D6500B38170 /* pop-tests-osx.octest */, + ECF01ED318C92B7F009E0AD1 /* pop-tests.xctest */, + EC7E319918C93D6500B38170 /* pop-tests.xctest */, + 0B6BE74819FFD3B900762101 /* pop.framework */, + 0755AE4F1BEA15950094AB41 /* pop.framework */, + 0755AE8C1BEA19580094AB41 /* pop-tests.xctest */, ); name = Products; sourceTree = ""; @@ -400,53 +568,28 @@ EC19121A162FB53A00E0CC76 /* Frameworks */ = { isa = PBXGroup; children = ( + 810EC6C41CE2E1E000BE2B9C /* AppKit.framework */, + 810EC6B61CE2E1BE00BE2B9C /* CoreGraphics.framework */, + 810EC69E1CE2E19C00BE2B9C /* QuartzCore.framework */, + 810EC6941CE2E19700BE2B9C /* CoreGraphics.framework */, + 810EC6891CE2E19000BE2B9C /* UIKit.framework */, + 0755AE621BEA15CB0094AB41 /* QuartzCore.framework */, + 0755AE601BEA15C60094AB41 /* CoreGraphics.framework */, + 0755AE5E1BEA15BF0094AB41 /* Foundation.framework */, + 0755AE5C1BEA15BA0094AB41 /* CoreFoundation.framework */, + 0755AE5A1BEA15B30094AB41 /* UIKit.framework */, + 0755AE581BEA15A80094AB41 /* CoreImage.framework */, + 1836BBE31B3B7B9C0041334F /* Cocoa.framework */, + 181893731B3B776B002C4A59 /* CoreFoundation.framework */, + 0B6BE7E619FFD98100762101 /* CoreImage.framework */, ECEED93D18C91ACF00DD95F2 /* UIKit.framework */, - ECEED93A18C91AB600DD95F2 /* libOCMock.a */, EC6885D318C7C44E00C6194C /* QuartzCore.framework */, - 403DCBBC1783F4A000793AE1 /* libFBWebP.a */, - ECED421816F7D1FD00FFBEAC /* libFBNetworker.a */, - 68569BF4084F464294AFEBA1 /* libFBReachability.a */, - ECADA2A416A8A99E00A20182 /* libMessagePack.a */, - ECADA2A516A8A99E00A20182 /* libSPDY.a */, - ECC5A8BA162FBF3A00F7F15C /* AdSupport.framework */, - ECC5A8B7162FBE1B00F7F15C /* Security.framework */, - ECC5A8B5162FBE1600F7F15C /* AssetsLibrary.framework */, - ECC5A8B3162FBE0900F7F15C /* libicucore.dylib */, - ECC5A8B1162FBE0400F7F15C /* libz.dylib */, - ECC5A8AF162FBDF600F7F15C /* CoreTelephony.framework */, - ECC5A8AD162FBDEB00F7F15C /* CoreText.framework */, - ECC5A8AB162FBDE100F7F15C /* ImageIO.framework */, - ECC5A8A9162FBDD800F7F15C /* SystemConfiguration.framework */, - ECC5A8A7162FBDCF00F7F15C /* CoreLocation.framework */, - ECC5A8A5162FBDCA00F7F15C /* AVFoundation.framework */, - ECC5A8A3162FBDC400F7F15C /* Accounts.framework */, - ECC5A8A1162FBDAB00F7F15C /* MobileCoreServices.framework */, - ECC5A89F162FBDA400F7F15C /* CoreData.framework */, ECC5A89D162FBD9B00F7F15C /* CoreGraphics.framework */, - ECC5A89B162FBD9500F7F15C /* AudioToolbox.framework */, - ECC5A899162FBD8E00F7F15C /* CFNetwork.framework */, - ECC5A897162FBD8700F7F15C /* AddressBook.framework */, - ECC5A889162FBD7600F7F15C /* libFBAnalytics.a */, - ECC5A88B162FBD7600F7F15C /* libFBFoundation.a */, - C4E7267217CE4436805A912B /* libFBCoreDataKit.a */, - ECC5A88C162FBD7600F7F15C /* libFBProvider.a */, - ECC5A88D162FBD7600F7F15C /* libFBTest.a */, - ECC5A88F162FBD7600F7F15C /* libOCMock.a */, ECC5A887162FBD6200F7F15C /* QuartzCore.framework */, EC19121B162FB53A00E0CC76 /* Foundation.framework */, - EC19122A162FB53A00E0CC76 /* SenTestingKit.framework */, - EC19122C162FB53A00E0CC76 /* UIKit.framework */, - E5D894724A104C729754ABCA /* libGLog.a */, - B551F115E86E4C7CA0D92E78 /* libDoubleConversion.a */, - D52A06EC505A4B82B3BBD5E6 /* libEvent.a */, - BD1A8D5BCA37415F86519334 /* libCAres.a */, - ECC63411C31441ECAC3F5559 /* libLiger.a */, - 02E3EF56E92B403A9BF79E26 /* boost */, - EC68858018C7B60000C6194C /* Cocoa.framework */, - EC68859518C7B60100C6194C /* XCTest.framework */, - EC68858218C7B60000C6194C /* Other Frameworks */, - D075ECD10B62441CBB9A90F6 /* libPods-pop-tests.a */, - D411892A480A401FB4D1AA07 /* libPods-pop-tests-osx.a */, + 0648E9DF7DFD7360DDB00E86 /* libPods-Tests-pop-tests-ios.a */, + 432CE3E78A1381BD39B03505 /* libPods-Tests-pop-tests-osx.a */, + 62526242E5E68FDF16B4B25D /* libPods-Tests-pop-tests-tvos.a */, ); name = Frameworks; sourceTree = ""; @@ -454,54 +597,42 @@ EC19121D162FB53A00E0CC76 /* pop */ = { isa = PBXGroup; children = ( + ECA94D0B18ECAE82002E4CEB /* POP.h */, EC8F015918FFBD7A00DF8905 /* Animations */, EC8F017318FFC4CB00DF8905 /* Engine */, EC8F017218FFC44800DF8905 /* Utility */, ECA0D5BE18D818C3003720DF /* WebCore */, - EC6885AF18C7BCA400C6194C /* iOS Supporting Files */, - EC68858618C7B60000C6194C /* OSX Supporting Files */, - ECA94D0B18ECAE82002E4CEB /* POP.h */, + EC6885AF18C7BCA400C6194C /* Supporting Files (iOS) */, + EC68858618C7B60000C6194C /* Supporting Files (OS X) */, + 0755AE641BEA16170094AB41 /* Supporting Files (tvOS) */, ); path = pop; sourceTree = ""; }; - EC68858218C7B60000C6194C /* Other Frameworks */ = { + EC68858618C7B60000C6194C /* Supporting Files (OS X) */ = { isa = PBXGroup; children = ( - EC68858318C7B60000C6194C /* Foundation.framework */, - EC68858418C7B60000C6194C /* CoreData.framework */, - EC68858518C7B60000C6194C /* AppKit.framework */, + EC68858818C7B60000C6194C /* pop-osx-Info.plist */, ); - name = "Other Frameworks"; + name = "Supporting Files (OS X)"; sourceTree = ""; }; - EC68858618C7B60000C6194C /* OSX Supporting Files */ = { + EC6885AF18C7BCA400C6194C /* Supporting Files (iOS) */ = { isa = PBXGroup; children = ( - EC68858818C7B60000C6194C /* pop-Info.plist */, - EC68858918C7B60000C6194C /* InfoPlist.strings */, - EC68858C18C7B60000C6194C /* pop-Prefix.pch */, + 1818936D1B3B74DE002C4A59 /* pop-ios-Info.plist */, + CD42CE6B1B541B1300EC9556 /* module.modulemap */, ); - name = "OSX Supporting Files"; - sourceTree = ""; - }; - EC6885AF18C7BCA400C6194C /* iOS Supporting Files */ = { - isa = PBXGroup; - children = ( - EC19121F162FB53A00E0CC76 /* POP-Prefix.pch */, - ); - name = "iOS Supporting Files"; + name = "Supporting Files (iOS)"; path = "pop-tests"; sourceTree = SOURCE_ROOT; }; - EC7E319C18C93D6500B38170 /* Supporting Files - OSX */ = { + EC7E319C18C93D6500B38170 /* Supporting Files (OS X) */ = { isa = PBXGroup; children = ( - EC7E319D18C93D6500B38170 /* pop-tests-osx-Info.plist */, - EC7E319E18C93D6500B38170 /* InfoPlist.strings */, - EC7E31A318C93D6500B38170 /* pop-tests-osx-Prefix.pch */, + 1818937D1B3B79D7002C4A59 /* pop-tests-osx-Info.plist */, ); - name = "Supporting Files - OSX"; + name = "Supporting Files (OS X)"; path = "pop-tests-osx"; sourceTree = SOURCE_ROOT; }; @@ -521,20 +652,20 @@ EC6F55AA175E6B11008D995D /* POPSpringAnimationTests.mm */, EC7D2CFB1795AB3100E50A78 /* POPEaseInEaseOutAnimationTests.mm */, EC72875418E13348006EEE54 /* POPCustomAnimationTests.mm */, - EC7E319C18C93D6500B38170 /* Supporting Files - OSX */, - EC882A7618C91983007829CC /* Supporting Files - iOS */, + EC6C098819141BBD00F8EA96 /* POPBasicAnimationTests.mm */, + 0755AE981BEA197E0094AB41 /* Supporting Files (tvOS) */, + EC882A7618C91983007829CC /* Supporting Files (iOS) */, + EC7E319C18C93D6500B38170 /* Supporting Files (OS X) */, ); path = "pop-tests"; sourceTree = ""; }; - EC882A7618C91983007829CC /* Supporting Files - iOS */ = { + EC882A7618C91983007829CC /* Supporting Files (iOS) */ = { isa = PBXGroup; children = ( - EC882A7718C91983007829CC /* pop-tests-Info.plist */, - EC882A7818C91983007829CC /* InfoPlist.strings */, - EC882A7D18C91983007829CC /* pop-tests-Prefix.pch */, + EC882A7718C91983007829CC /* pop-tests-ios-Info.plist */, ); - name = "Supporting Files - iOS"; + name = "Supporting Files (iOS)"; sourceTree = ""; }; EC8F015918FFBD7A00DF8905 /* Animations */ = { @@ -587,6 +718,7 @@ children = ( EC19128E162FB5B700E0CC76 /* POPAnimatableProperty.h */, EC19128F162FB5B700E0CC76 /* POPAnimatableProperty.mm */, + 5C8B2FC91E847C1000A6A646 /* POPAnimatablePropertyTypes.h */, EC9997531756A0C300A73F49 /* POPAnimationEvent.h */, EC9997541756A0C300A73F49 /* POPAnimationEvent.mm */, EC9997571756A17B00A73F49 /* POPAnimationEventInternal.h */, @@ -618,70 +750,90 @@ ECC1DB0718CA291B008C7DEA /* Configuration */ = { isa = PBXGroup; children = ( - ECC1DB0818CA291B008C7DEA /* Applications */, - ECC1DB0B18CA291B008C7DEA /* Base-iOS.xcconfig */, - ECC1DB0C18CA291B008C7DEA /* Base-OSX.xcconfig */, - ECC1DB0D18CA291B008C7DEA /* Platform */, - ECC1DB1118CA291B008C7DEA /* Projects */, - ECC1DB1918CA291B008C7DEA /* Static Libraries */, - ECC1DB1C18CA291B008C7DEA /* Tests */, + ECC1DB0B18CA291B008C7DEA /* Compiler.xcconfig */, + ECC1DB1118CA291B008C7DEA /* Project */, + ECC1DB1918CA291B008C7DEA /* Product */, ); path = Configuration; sourceTree = ""; }; - ECC1DB0818CA291B008C7DEA /* Applications */ = { - isa = PBXGroup; - children = ( - ECC1DB0918CA291B008C7DEA /* Application-iOS.xcconfig */, - ECC1DB0A18CA291B008C7DEA /* Application-OSX.xcconfig */, - ); - path = Applications; - sourceTree = ""; - }; - ECC1DB0D18CA291B008C7DEA /* Platform */ = { - isa = PBXGroup; - children = ( - ECC1DB0E18CA291B008C7DEA /* Compiler.xcconfig */, - ECC1DB0F18CA291B008C7DEA /* iOS.xcconfig */, - ECC1DB1018CA291B008C7DEA /* OSX.xcconfig */, - ); - path = Platform; - sourceTree = ""; - }; - ECC1DB1118CA291B008C7DEA /* Projects */ = { + ECC1DB1118CA291B008C7DEA /* Project */ = { isa = PBXGroup; children = ( ECC1DB1218CA291B008C7DEA /* Project-Debug.xcconfig */, - ECC1DB1318CA291B008C7DEA /* Project-GCOV.xcconfig */, ECC1DB1618CA291B008C7DEA /* Project-Profile.xcconfig */, ECC1DB1718CA291B008C7DEA /* Project-Release.xcconfig */, ECC1DB1818CA291B008C7DEA /* Project.xcconfig */, ); - path = Projects; - sourceTree = ""; - }; - ECC1DB1918CA291B008C7DEA /* Static Libraries */ = { - isa = PBXGroup; - children = ( - ECC1DB1A18CA291B008C7DEA /* StaticLibrary-iOS.xcconfig */, - ECC1DB1B18CA291B008C7DEA /* StaticLibrary-OSX.xcconfig */, - ); - path = "Static Libraries"; + path = Project; sourceTree = ""; }; - ECC1DB1C18CA291B008C7DEA /* Tests */ = { + ECC1DB1918CA291B008C7DEA /* Product */ = { isa = PBXGroup; children = ( + ECC1DB1A18CA291B008C7DEA /* StaticLibrary.xcconfig */, + 04C0670F1B8D577C00ED0525 /* Framework.xcconfig */, ECC1DB1D18CA291B008C7DEA /* ApplicationTests.xcconfig */, - ECC1DB1E18CA291B008C7DEA /* LogicTests-iOS.xcconfig */, - ECC1DB1F18CA291B008C7DEA /* LogicTests-OSX.xcconfig */, + ECC1DB1E18CA291B008C7DEA /* LogicTests.xcconfig */, ); - path = Tests; + path = Product; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ + 0755AE4C1BEA15950094AB41 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 0755AE7A1BEA17C70094AB41 /* POPAnimationTracer.h in Headers */, + 0755AE811BEA17EF0094AB41 /* POPGeometry.h in Headers */, + 0755AE7C1BEA17CF0094AB41 /* POPAnimator.h in Headers */, + 0755AE751BEA17B30094AB41 /* POPAnimationEvent.h in Headers */, + 0755AE691BEA17840094AB41 /* POPBasicAnimation.h in Headers */, + 0755AE731BEA17AD0094AB41 /* POPAnimatableProperty.h in Headers */, + 0755AE651BEA17620094AB41 /* POP.h in Headers */, + 0755AE771BEA17BC0094AB41 /* POPAnimationExtras.h in Headers */, + 0755AE671BEA17780094AB41 /* POPAnimationPrivate.h in Headers */, + 5C8B2FCC1E847C4700A6A646 /* POPAnimatablePropertyTypes.h in Headers */, + 0755AE831BEA17F50094AB41 /* POPLayerExtras.h in Headers */, + 0755AE681BEA177C0094AB41 /* POPPropertyAnimation.h in Headers */, + 0755AE6C1BEA17980094AB41 /* POPSpringAnimation.h in Headers */, + 0755AE7E1BEA17D60094AB41 /* POPAnimatorPrivate.h in Headers */, + 0755AE6A1BEA178B0094AB41 /* POPCustomAnimation.h in Headers */, + 0755AE6B1BEA17930094AB41 /* POPDecayAnimation.h in Headers */, + 0BB8E7BA20A498C900AAA7F1 /* POPVector.h in Headers */, + 0755AE661BEA17670094AB41 /* POPAnimation.h in Headers */, + 0755AE801BEA17EA0094AB41 /* POPDefines.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 0B6BE74519FFD3B900762101 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 0B6BE76919FFD40700762101 /* POP.h in Headers */, + 0B6BE76B19FFD41500762101 /* POPDefines.h in Headers */, + 0B6BE77419FFD48700762101 /* POPAnimatableProperty.h in Headers */, + 0B6BE77619FFD49A00762101 /* POPAnimation.h in Headers */, + 0B6BE76A19FFD41100762101 /* POPAnimationEvent.h in Headers */, + 0B6BE76D19FFD42700762101 /* POPAnimationExtras.h in Headers */, + 0B6BE76819FFD3FF00762101 /* POPAnimationTracer.h in Headers */, + 0B6BE77519FFD49100762101 /* POPAnimator.h in Headers */, + 0B6BE77319FFD47F00762101 /* POPBasicAnimation.h in Headers */, + 5C8B2FCB1E847C4700A6A646 /* POPAnimatablePropertyTypes.h in Headers */, + 0B6BE76E19FFD43800762101 /* POPCustomAnimation.h in Headers */, + 0B6BE76C19FFD41D00762101 /* POPDecayAnimation.h in Headers */, + 0B6BE77819FFD4AB00762101 /* POPGeometry.h in Headers */, + 0B6BE77019FFD46600762101 /* POPLayerExtras.h in Headers */, + 0B6BE77219FFD47800762101 /* POPPropertyAnimation.h in Headers */, + 0B6BE76F19FFD44000762101 /* POPSpringAnimation.h in Headers */, + 0BB8E7B920A498AA00AAA7F1 /* POPVector.h in Headers */, + 0B6BE77119FFD46F00762101 /* POPAnimatorPrivate.h in Headers */, + 0B6BE77719FFD4A300762101 /* POPAnimationPrivate.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; EC191294162FB5DD00E0CC76 /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; @@ -703,12 +855,12 @@ EC67007218D3D89F00F7387F /* POPCGUtils.h in Headers */, EC8F016218FFBE9D00DF8905 /* POPDecayAnimationInternal.h in Headers */, EC0AE13116BC73CE001DA2CE /* POPAnimationExtras.h in Headers */, + EC70AC4618CCF4FC0067018C /* POPVector.h in Headers */, EC91E96E18C014DE0025B8AD /* POPAction.h in Headers */, 90AA30B718988BBE00E3BDF7 /* POPSpringSolver.h in Headers */, EC8F014618FFBC2D00DF8905 /* POPPropertyAnimationInternal.h in Headers */, EC8F015C18FFBE8C00DF8905 /* POPDecayAnimation.h in Headers */, EC91E96018C00EC90025B8AD /* POPDefines.h in Headers */, - EC70AC4618CCF4FC0067018C /* POPVector.h in Headers */, EC9553901743E278001E6AF2 /* POPAnimationRuntime.h in Headers */, EC6465D01794B4660014176F /* POPMath.h in Headers */, EC8F016E18FFBEC200DF8905 /* POPSpringAnimationInternal.h in Headers */, @@ -717,6 +869,7 @@ EC9997591756A17B00A73F49 /* POPAnimationEventInternal.h in Headers */, EC94B07A17D95447003CE2C8 /* TransformationMatrix.h in Headers */, EC8F015518FFBD5600DF8905 /* POPBasicAnimationInternal.h in Headers */, + 5C8B2FCA1E847C1000A6A646 /* POPAnimatablePropertyTypes.h in Headers */, EC35DB2918EE3E820023E077 /* POPAnimationTracer.h in Headers */, ECA0D5C018D8196A003720DF /* UnitBezier.h in Headers */, ); @@ -757,6 +910,7 @@ EC6885B018C7BD0A00C6194C /* POPAnimatableProperty.h in Headers */, ECA0D5C118D8196A003720DF /* UnitBezier.h in Headers */, EC8F015618FFBD5600DF8905 /* POPBasicAnimationInternal.h in Headers */, + 5C8B2FCF1E847C4B00A6A646 /* POPAnimatablePropertyTypes.h in Headers */, EC35DB2A18EE3E820023E077 /* POPAnimationTracer.h in Headers */, EC6885BD18C7BD3E00C6194C /* POPAnimationRuntime.h in Headers */, ); @@ -765,9 +919,66 @@ /* End PBXHeadersBuildPhase section */ /* Begin PBXNativeTarget section */ - EC191217162FB53A00E0CC76 /* pop */ = { + 0755AE4E1BEA15950094AB41 /* pop-tvos-framework */ = { + isa = PBXNativeTarget; + buildConfigurationList = 0755AE571BEA15950094AB41 /* Build configuration list for PBXNativeTarget "pop-tvos-framework" */; + buildPhases = ( + 0755AE4A1BEA15950094AB41 /* Sources */, + 0755AE4B1BEA15950094AB41 /* Frameworks */, + 0755AE4C1BEA15950094AB41 /* Headers */, + 0755AE4D1BEA15950094AB41 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "pop-tvos-framework"; + productName = "pop-tvos-framework"; + productReference = 0755AE4F1BEA15950094AB41 /* pop.framework */; + productType = "com.apple.product-type.framework"; + }; + 0755AE8B1BEA19580094AB41 /* pop-tests-tvos */ = { + isa = PBXNativeTarget; + buildConfigurationList = 0755AE941BEA19580094AB41 /* Build configuration list for PBXNativeTarget "pop-tests-tvos" */; + buildPhases = ( + 438D7049A40532D60B1CFFD1 /* [CP] Check Pods Manifest.lock */, + 0755AE881BEA19580094AB41 /* Sources */, + 0755AE891BEA19580094AB41 /* Frameworks */, + 0755AE8A1BEA19580094AB41 /* Resources */, + 3A53D0B6BA95C3BBF6D969C3 /* [CP] Embed Pods Frameworks */, + C1BD52275F7F60A567C78D67 /* [CP] Copy Pods Resources */, + ); + buildRules = ( + ); + dependencies = ( + 0755AE931BEA19580094AB41 /* PBXTargetDependency */, + ); + name = "pop-tests-tvos"; + productName = "pop-tests-tvos"; + productReference = 0755AE8C1BEA19580094AB41 /* pop-tests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 0B6BE74719FFD3B900762101 /* pop-ios-framework */ = { isa = PBXNativeTarget; - buildConfigurationList = EC19123D162FB53A00E0CC76 /* Build configuration list for PBXNativeTarget "pop" */; + buildConfigurationList = 0B6BE75B19FFD3B900762101 /* Build configuration list for PBXNativeTarget "pop-ios-framework" */; + buildPhases = ( + 0B6BE74319FFD3B900762101 /* Sources */, + 0B6BE74419FFD3B900762101 /* Frameworks */, + 0B6BE74519FFD3B900762101 /* Headers */, + 0B6BE74619FFD3B900762101 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "pop-ios-framework"; + productName = "pop-ios"; + productReference = 0B6BE74819FFD3B900762101 /* pop.framework */; + productType = "com.apple.product-type.framework"; + }; + EC191217162FB53A00E0CC76 /* pop-ios-static */ = { + isa = PBXNativeTarget; + buildConfigurationList = EC19123D162FB53A00E0CC76 /* Build configuration list for PBXNativeTarget "pop-ios-static" */; buildPhases = ( EC191214162FB53A00E0CC76 /* Sources */, EC191215162FB53A00E0CC76 /* Frameworks */, @@ -778,14 +989,14 @@ ); dependencies = ( ); - name = pop; + name = "pop-ios-static"; productName = POP; productReference = EC191218162FB53A00E0CC76 /* libpop.a */; productType = "com.apple.product-type.library.static"; }; - EC68857E18C7B60000C6194C /* pop-osx */ = { + EC68857E18C7B60000C6194C /* pop-osx-framework */ = { isa = PBXNativeTarget; - buildConfigurationList = EC6885A318C7B60100C6194C /* Build configuration list for PBXNativeTarget "pop-osx" */; + buildConfigurationList = EC6885A318C7B60100C6194C /* Build configuration list for PBXNativeTarget "pop-osx-framework" */; buildPhases = ( EC68857A18C7B60000C6194C /* Sources */, EC68857B18C7B60000C6194C /* Frameworks */, @@ -796,7 +1007,7 @@ ); dependencies = ( ); - name = "pop-osx"; + name = "pop-osx-framework"; productName = POP; productReference = EC68857F18C7B60000C6194C /* pop.framework */; productType = "com.apple.product-type.framework"; @@ -805,11 +1016,12 @@ isa = PBXNativeTarget; buildConfigurationList = EC7E31A618C93D6600B38170 /* Build configuration list for PBXNativeTarget "pop-tests-osx" */; buildPhases = ( - 2F7E04AE9A5B41869AF78DA9 /* Check Pods Manifest.lock */, + F4415E40040FA8BD0169207E /* [CP] Check Pods Manifest.lock */, EC7E319518C93D6500B38170 /* Sources */, EC7E319618C93D6500B38170 /* Frameworks */, EC7E319718C93D6500B38170 /* Resources */, - 063BFBF07EAD4D74B19E2BC0 /* Copy Pods Resources */, + 8C22F2D1DF67D20F75F93301 /* [CP] Embed Pods Frameworks */, + 87C11C7E3C11F27907D777EE /* [CP] Copy Pods Resources */, ); buildRules = ( ); @@ -818,28 +1030,29 @@ ); name = "pop-tests-osx"; productName = "pop-tests-osx"; - productReference = EC7E319918C93D6500B38170 /* pop-tests-osx.octest */; - productType = "com.apple.product-type.bundle"; + productReference = EC7E319918C93D6500B38170 /* pop-tests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; }; - ECF01ED218C92B7F009E0AD1 /* pop-tests */ = { + ECF01ED218C92B7F009E0AD1 /* pop-tests-ios */ = { isa = PBXNativeTarget; - buildConfigurationList = ECF01EE218C92B80009E0AD1 /* Build configuration list for PBXNativeTarget "pop-tests" */; + buildConfigurationList = ECF01EE218C92B80009E0AD1 /* Build configuration list for PBXNativeTarget "pop-tests-ios" */; buildPhases = ( - 093AEF8FEE094AECB5EDCED2 /* Check Pods Manifest.lock */, + CA15F9BB92BDB47C58EBAC0D /* [CP] Check Pods Manifest.lock */, ECF01ECF18C92B7F009E0AD1 /* Sources */, ECF01ED018C92B7F009E0AD1 /* Frameworks */, ECF01ED118C92B7F009E0AD1 /* Resources */, - 394D14BF947A476EB827103B /* Copy Pods Resources */, + CFC3BF04D331650C5B4A16CC /* [CP] Embed Pods Frameworks */, + 691A59DA7BDEDCB681FC9C87 /* [CP] Copy Pods Resources */, ); buildRules = ( ); dependencies = ( - ECF01EE118C92B80009E0AD1 /* PBXTargetDependency */, + 816FEE231FFC68370069EF43 /* PBXTargetDependency */, ); - name = "pop-tests"; + name = "pop-tests-ios"; productName = "pop-tests"; - productReference = ECF01ED318C92B7F009E0AD1 /* pop-tests.octest */; - productType = "com.apple.product-type.bundle"; + productReference = ECF01ED318C92B7F009E0AD1 /* pop-tests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; }; /* End PBXNativeTarget section */ @@ -847,9 +1060,19 @@ EC19120F162FB53A00E0CC76 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0500; + LastTestingUpgradeCheck = 0700; + LastUpgradeCheck = 1000; ORGANIZATIONNAME = Facebook; TargetAttributes = { + 0755AE4E1BEA15950094AB41 = { + CreatedOnToolsVersion = 7.1; + }; + 0755AE8B1BEA19580094AB41 = { + CreatedOnToolsVersion = 7.1; + }; + 0B6BE74719FFD3B900762101 = { + CreatedOnToolsVersion = 6.1; + }; EC7E319818C93D6500B38170 = { TestTargetID = EC68857E18C7B60000C6194C; }; @@ -870,20 +1093,44 @@ projectDirPath = ""; projectRoot = ""; targets = ( - EC191217162FB53A00E0CC76 /* pop */, - EC68857E18C7B60000C6194C /* pop-osx */, - ECF01ED218C92B7F009E0AD1 /* pop-tests */, + EC191217162FB53A00E0CC76 /* pop-ios-static */, + 0B6BE74719FFD3B900762101 /* pop-ios-framework */, + EC68857E18C7B60000C6194C /* pop-osx-framework */, + 0755AE4E1BEA15950094AB41 /* pop-tvos-framework */, + ECF01ED218C92B7F009E0AD1 /* pop-tests-ios */, EC7E319818C93D6500B38170 /* pop-tests-osx */, + 0755AE8B1BEA19580094AB41 /* pop-tests-tvos */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ + 0755AE4D1BEA15950094AB41 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 0755AE8A1BEA19580094AB41 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 0B6BE74619FFD3B900762101 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1818937E1B3B79D7002C4A59 /* pop-tests-osx-Info.plist in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; EC68857D18C7B60000C6194C /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - EC68858B18C7B60000C6194C /* InfoPlist.strings in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -891,7 +1138,6 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - EC7E31A018C93D6500B38170 /* InfoPlist.strings in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -905,69 +1151,221 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ - 063BFBF07EAD4D74B19E2BC0 /* Copy Pods Resources */ = { + 3A53D0B6BA95C3BBF6D969C3 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "[CP] Embed Pods Frameworks"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Tests-pop-tests-tvos/Pods-Tests-pop-tests-tvos-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + 438D7049A40532D60B1CFFD1 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Tests-pop-tests-tvos-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + 691A59DA7BDEDCB681FC9C87 /* [CP] Copy Pods Resources */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); - name = "Copy Pods Resources"; + name = "[CP] Copy Pods Resources"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "\"${SRCROOT}/Pods/Pods-pop-tests-osx-resources.sh\"\n"; + shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Tests-pop-tests-ios/Pods-Tests-pop-tests-ios-resources.sh\"\n"; showEnvVarsInLog = 0; }; - 093AEF8FEE094AECB5EDCED2 /* Check Pods Manifest.lock */ = { + 87C11C7E3C11F27907D777EE /* [CP] Copy Pods Resources */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); - name = "Check Pods Manifest.lock"; + name = "[CP] Copy Pods Resources"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n"; + shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Tests-pop-tests-osx/Pods-Tests-pop-tests-osx-resources.sh\"\n"; showEnvVarsInLog = 0; }; - 2F7E04AE9A5B41869AF78DA9 /* Check Pods Manifest.lock */ = { + 8C22F2D1DF67D20F75F93301 /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); - name = "Check Pods Manifest.lock"; + name = "[CP] Embed Pods Frameworks"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n"; + shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Tests-pop-tests-osx/Pods-Tests-pop-tests-osx-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; - 394D14BF947A476EB827103B /* Copy Pods Resources */ = { + C1BD52275F7F60A567C78D67 /* [CP] Copy Pods Resources */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); - name = "Copy Pods Resources"; + name = "[CP] Copy Pods Resources"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "\"${SRCROOT}/Pods/Pods-pop-tests-resources.sh\"\n"; + shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Tests-pop-tests-tvos/Pods-Tests-pop-tests-tvos-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; + CA15F9BB92BDB47C58EBAC0D /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Tests-pop-tests-ios-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + CFC3BF04D331650C5B4A16CC /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "[CP] Embed Pods Frameworks"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Tests-pop-tests-ios/Pods-Tests-pop-tests-ios-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + F4415E40040FA8BD0169207E /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Tests-pop-tests-osx-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ + 0755AE4A1BEA15950094AB41 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 0755AE781BEA17C00094AB41 /* POPAnimationExtras.mm in Sources */, + 0755AE711BEA17A70094AB41 /* POPDecayAnimation.mm in Sources */, + 0755AE741BEA17B10094AB41 /* POPAnimatableProperty.mm in Sources */, + 0755AE821BEA17F20094AB41 /* POPGeometry.mm in Sources */, + 0755AE6D1BEA17A70094AB41 /* POPAnimation.mm in Sources */, + 0755AE7D1BEA17D30094AB41 /* POPAnimator.mm in Sources */, + 0755AE7B1BEA17CA0094AB41 /* POPAnimationTracer.mm in Sources */, + 0755AE861BEA18060094AB41 /* POPVector.mm in Sources */, + 0755AE841BEA17F90094AB41 /* POPLayerExtras.mm in Sources */, + 0755AE6E1BEA17A70094AB41 /* POPPropertyAnimation.mm in Sources */, + 0755AE6F1BEA17A70094AB41 /* POPBasicAnimation.mm in Sources */, + 0755AE761BEA17B80094AB41 /* POPAnimationEvent.mm in Sources */, + 0755AE851BEA17FD0094AB41 /* POPMath.mm in Sources */, + 0755AE871BEA180F0094AB41 /* TransformationMatrix.cpp in Sources */, + 0755AE791BEA17C40094AB41 /* POPAnimationRuntime.mm in Sources */, + 0755AE7F1BEA17E70094AB41 /* POPCGUtils.mm in Sources */, + 0755AE701BEA17A70094AB41 /* POPCustomAnimation.mm in Sources */, + 0755AE721BEA17A70094AB41 /* POPSpringAnimation.mm in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 0755AE881BEA19580094AB41 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 0755AE9D1BEA19F40094AB41 /* POPAnimationTestsExtras.mm in Sources */, + 0755AE991BEA19F40094AB41 /* POPAnimatable.mm in Sources */, + 0755AE9E1BEA19F40094AB41 /* POPAnimatablePropertyTests.mm in Sources */, + 0755AE9F1BEA19F40094AB41 /* POPDecayAnimationTests.mm in Sources */, + 0755AEA11BEA19F40094AB41 /* POPEaseInEaseOutAnimationTests.mm in Sources */, + 0755AE9A1BEA19F40094AB41 /* POPBaseAnimationTests.mm in Sources */, + 0755AEA31BEA19F40094AB41 /* POPBasicAnimationTests.mm in Sources */, + 0755AE9C1BEA19F40094AB41 /* POPAnimationMRRTests.mm in Sources */, + 0755AEA21BEA19F40094AB41 /* POPCustomAnimationTests.mm in Sources */, + 0755AE9B1BEA19F40094AB41 /* POPAnimationTests.mm in Sources */, + 0755AEA01BEA19F40094AB41 /* POPSpringAnimationTests.mm in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 0B6BE74319FFD3B900762101 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 0B6BE7D119FFD92700762101 /* POPAnimation.mm in Sources */, + 0B6BE7D219FFD92700762101 /* POPPropertyAnimation.mm in Sources */, + 0B6BE7D319FFD92700762101 /* POPBasicAnimation.mm in Sources */, + 0B6BE7D419FFD92700762101 /* POPCustomAnimation.mm in Sources */, + 0B6BE7D519FFD92700762101 /* POPDecayAnimation.mm in Sources */, + 0B6BE7D619FFD92700762101 /* POPSpringAnimation.mm in Sources */, + 0B6BE7D719FFD92700762101 /* POPAnimatableProperty.mm in Sources */, + 0B6BE7D819FFD92700762101 /* POPAnimationEvent.mm in Sources */, + 0B6BE7D919FFD92700762101 /* POPAnimationExtras.mm in Sources */, + 0B6BE7DA19FFD92700762101 /* POPAnimationRuntime.mm in Sources */, + 0B6BE7DB19FFD92700762101 /* POPAnimationTracer.mm in Sources */, + 0B6BE7DC19FFD92700762101 /* POPAnimator.mm in Sources */, + 0B6BE7DD19FFD92700762101 /* POPCGUtils.mm in Sources */, + 0B6BE7DE19FFD92700762101 /* POPGeometry.mm in Sources */, + 0B6BE7DF19FFD92700762101 /* POPLayerExtras.mm in Sources */, + 0B6BE7E019FFD92800762101 /* POPMath.mm in Sources */, + 0B6BE7E119FFD92800762101 /* POPVector.mm in Sources */, + 0B6BE7D019FFD90F00762101 /* TransformationMatrix.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; EC191214162FB53A00E0CC76 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -1025,6 +1423,7 @@ EC72875618E13348006EEE54 /* POPCustomAnimationTests.mm in Sources */, EC7E31AB18C9419000B38170 /* POPAnimatable.mm in Sources */, EC7E31AD18C9419600B38170 /* POPAnimationTests.mm in Sources */, + EC6C098A19141BBD00F8EA96 /* POPBasicAnimationTests.mm in Sources */, EC7E31B318C941A700B38170 /* POPEaseInEaseOutAnimationTests.mm in Sources */, EC7E31AE18C9419900B38170 /* POPAnimationMRRTests.mm in Sources */, EC7E31AC18C9419200B38170 /* POPBaseAnimationTests.mm in Sources */, @@ -1043,6 +1442,7 @@ EC72875518E13348006EEE54 /* POPCustomAnimationTests.mm in Sources */, ECDA0CC618C92BC900D14897 /* POPAnimatable.mm in Sources */, ECDA0CC818C92BD200D14897 /* POPAnimationTests.mm in Sources */, + EC6C098919141BBD00F8EA96 /* POPBasicAnimationTests.mm in Sources */, ECDA0CCE18C92BD200D14897 /* POPEaseInEaseOutAnimationTests.mm in Sources */, ECDA0CC918C92BD200D14897 /* POPAnimationMRRTests.mm in Sources */, ECDA0CC718C92BD200D14897 /* POPBaseAnimationTests.mm in Sources */, @@ -1057,63 +1457,220 @@ /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ - EC7E31A518C93D6600B38170 /* PBXTargetDependency */ = { + 0755AE931BEA19580094AB41 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - target = EC68857E18C7B60000C6194C /* pop-osx */; - targetProxy = EC7E31A418C93D6600B38170 /* PBXContainerItemProxy */; + target = 0755AE4E1BEA15950094AB41 /* pop-tvos-framework */; + targetProxy = 0755AE921BEA19580094AB41 /* PBXContainerItemProxy */; }; - ECF01EE118C92B80009E0AD1 /* PBXTargetDependency */ = { + 816FEE231FFC68370069EF43 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - target = EC191217162FB53A00E0CC76 /* pop */; - targetProxy = ECF01EE018C92B80009E0AD1 /* PBXContainerItemProxy */; + target = 0B6BE74719FFD3B900762101 /* pop-ios-framework */; + targetProxy = 816FEE221FFC68370069EF43 /* PBXContainerItemProxy */; + }; + EC7E31A518C93D6600B38170 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = EC68857E18C7B60000C6194C /* pop-osx-framework */; + targetProxy = EC7E31A418C93D6600B38170 /* PBXContainerItemProxy */; }; /* End PBXTargetDependency section */ -/* Begin PBXVariantGroup section */ - EC68858918C7B60000C6194C /* InfoPlist.strings */ = { - isa = PBXVariantGroup; - children = ( - EC68858A18C7B60000C6194C /* en */, - ); - name = InfoPlist.strings; - sourceTree = ""; +/* Begin XCBuildConfiguration section */ + 0755AE541BEA15950094AB41 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 04C0670F1B8D577C00ED0525 /* Framework.xcconfig */; + buildSettings = { + DEFINES_MODULE = YES; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "$(PROJECT_DIR)/pop/pop-tvos-Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "$(PROJECT_DIR)/pop/module.modulemap"; + PRODUCT_BUNDLE_IDENTIFIER = com.facebook.pop; + PRODUCT_NAME = pop; + SDKROOT = appletvos; + TARGETED_DEVICE_FAMILY = 3; + }; + name = Debug; }; - EC7E319E18C93D6500B38170 /* InfoPlist.strings */ = { - isa = PBXVariantGroup; - children = ( - EC7E319F18C93D6500B38170 /* en */, - ); - name = InfoPlist.strings; - sourceTree = ""; + 0755AE551BEA15950094AB41 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 04C0670F1B8D577C00ED0525 /* Framework.xcconfig */; + buildSettings = { + DEFINES_MODULE = YES; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "$(PROJECT_DIR)/pop/pop-tvos-Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "$(PROJECT_DIR)/pop/module.modulemap"; + PRODUCT_BUNDLE_IDENTIFIER = com.facebook.pop; + PRODUCT_NAME = pop; + SDKROOT = appletvos; + TARGETED_DEVICE_FAMILY = 3; + }; + name = Release; }; - EC882A7818C91983007829CC /* InfoPlist.strings */ = { - isa = PBXVariantGroup; - children = ( - EC882A7918C91983007829CC /* en */, - ); - name = InfoPlist.strings; - sourceTree = ""; + 0755AE561BEA15950094AB41 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 04C0670F1B8D577C00ED0525 /* Framework.xcconfig */; + buildSettings = { + DEFINES_MODULE = YES; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "$(PROJECT_DIR)/pop/pop-tvos-Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "$(PROJECT_DIR)/pop/module.modulemap"; + PRODUCT_BUNDLE_IDENTIFIER = com.facebook.pop; + PRODUCT_NAME = pop; + SDKROOT = appletvos; + TARGETED_DEVICE_FAMILY = 3; + }; + name = Profile; }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 9062CE2A16BC56CC00655F1D /* GCOV */ = { + 0755AE951BEA19580094AB41 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 75AB0405A39E769FDEA67DFE /* Pods-Tests-pop-tests-tvos.debug.xcconfig */; + buildSettings = { + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_WARN_BOOL_CONVERSION = 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_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + INFOPLIST_FILE = "$(PROJECT_DIR)/pop-tests/pop-tests-tvos-Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MTL_ENABLE_DEBUG_INFO = YES; + PRODUCT_BUNDLE_IDENTIFIER = "com.facebook.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "pop-tests"; + SDKROOT = appletvos; + }; + name = Debug; + }; + 0755AE961BEA19580094AB41 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 66F8502AAF59876387597FEC /* Pods-Tests-pop-tests-tvos.release.xcconfig */; + buildSettings = { + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_WARN_BOOL_CONVERSION = 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_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + INFOPLIST_FILE = "$(PROJECT_DIR)/pop-tests/pop-tests-tvos-Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MTL_ENABLE_DEBUG_INFO = NO; + PRODUCT_BUNDLE_IDENTIFIER = "com.facebook.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "pop-tests"; + SDKROOT = appletvos; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 0755AE971BEA19580094AB41 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 55EA9621113E7E17CB5A65C3 /* Pods-Tests-pop-tests-tvos.profile.xcconfig */; + buildSettings = { + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_WARN_BOOL_CONVERSION = 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_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + INFOPLIST_FILE = "$(PROJECT_DIR)/pop-tests/pop-tests-tvos-Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MTL_ENABLE_DEBUG_INFO = NO; + PRODUCT_BUNDLE_IDENTIFIER = "com.facebook.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "pop-tests"; + SDKROOT = appletvos; + VALIDATE_PRODUCT = YES; + }; + name = Profile; + }; + 0B6BE75C19FFD3B900762101 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 04C0670F1B8D577C00ED0525 /* Framework.xcconfig */; + buildSettings = { + DEFINES_MODULE = YES; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "$(PROJECT_DIR)/pop/pop-ios-Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "$(PROJECT_DIR)/pop/module.modulemap"; + PRODUCT_BUNDLE_IDENTIFIER = com.facebook.pop; + PRODUCT_NAME = pop; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 0B6BE75E19FFD3B900762101 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = ECC1DB1318CA291B008C7DEA /* Project-GCOV.xcconfig */; + baseConfigurationReference = 04C0670F1B8D577C00ED0525 /* Framework.xcconfig */; buildSettings = { + DEFINES_MODULE = YES; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "$(PROJECT_DIR)/pop/pop-ios-Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "$(PROJECT_DIR)/pop/module.modulemap"; + PRODUCT_BUNDLE_IDENTIFIER = com.facebook.pop; + PRODUCT_NAME = pop; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; }; - name = GCOV; + name = Release; }; - 9062CE2B16BC56CC00655F1D /* GCOV */ = { + 0B6BE75F19FFD3B900762101 /* Profile */ = { isa = XCBuildConfiguration; - baseConfigurationReference = ECC1DB1A18CA291B008C7DEA /* StaticLibrary-iOS.xcconfig */; + baseConfigurationReference = 04C0670F1B8D577C00ED0525 /* Framework.xcconfig */; buildSettings = { - GCC_PREFIX_HEADER = "pop/pop-Prefix.pch"; - INFOPLIST_FILE = "POP/pop-Info.plist"; + DEFINES_MODULE = YES; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "$(PROJECT_DIR)/pop/pop-ios-Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "$(PROJECT_DIR)/pop/module.modulemap"; + PRODUCT_BUNDLE_IDENTIFIER = com.facebook.pop; PRODUCT_NAME = pop; - PUBLIC_HEADERS_FOLDER_PATH = ../Headers/POP; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; }; - name = GCOV; + name = Profile; }; A2BDDD3D185A687F00838797 /* Profile */ = { isa = XCBuildConfiguration; @@ -1124,12 +1681,10 @@ }; A2BDDD3E185A687F00838797 /* Profile */ = { isa = XCBuildConfiguration; - baseConfigurationReference = ECC1DB1A18CA291B008C7DEA /* StaticLibrary-iOS.xcconfig */; + baseConfigurationReference = ECC1DB1A18CA291B008C7DEA /* StaticLibrary.xcconfig */; buildSettings = { - GCC_PREFIX_HEADER = "pop/pop-Prefix.pch"; - INFOPLIST_FILE = "POP/pop-Info.plist"; PRODUCT_NAME = pop; - PUBLIC_HEADERS_FOLDER_PATH = ../Headers/POP; + SDKROOT = iphoneos; }; name = Profile; }; @@ -1149,454 +1704,218 @@ }; EC19123E162FB53A00E0CC76 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = ECC1DB1A18CA291B008C7DEA /* StaticLibrary-iOS.xcconfig */; + baseConfigurationReference = ECC1DB1A18CA291B008C7DEA /* StaticLibrary.xcconfig */; buildSettings = { - GCC_PREFIX_HEADER = "pop/pop-Prefix.pch"; - INFOPLIST_FILE = "POP/pop-Info.plist"; PRODUCT_NAME = pop; - PUBLIC_HEADERS_FOLDER_PATH = ../Headers/POP; + SDKROOT = iphoneos; }; name = Debug; }; EC19123F162FB53A00E0CC76 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = ECC1DB1A18CA291B008C7DEA /* StaticLibrary-iOS.xcconfig */; + baseConfigurationReference = ECC1DB1A18CA291B008C7DEA /* StaticLibrary.xcconfig */; buildSettings = { - GCC_PREFIX_HEADER = "pop/pop-Prefix.pch"; - INFOPLIST_FILE = "POP/pop-Info.plist"; PRODUCT_NAME = pop; - PUBLIC_HEADERS_FOLDER_PATH = ../Headers/POP; + SDKROOT = iphoneos; }; name = Release; }; EC6885A418C7B60100C6194C /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = ECC1DB1B18CA291B008C7DEA /* StaticLibrary-OSX.xcconfig */; + baseConfigurationReference = 04C0670F1B8D577C00ED0525 /* Framework.xcconfig */; buildSettings = { COMBINE_HIDPI_IMAGES = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - FRAMEWORK_VERSION = A; - GCC_PREFIX_HEADER = "$(PRODUCT_NAME)/$(PRODUCT_NAME)-Prefix.pch"; - INFOPLIST_FILE = "POP/pop-Info.plist"; + INFOPLIST_FILE = "$(PROJECT_DIR)/pop/pop-osx-Info.plist"; + INSTALL_PATH = "@rpath"; + PRODUCT_BUNDLE_IDENTIFIER = com.facebook.pop; PRODUCT_NAME = pop; - PUBLIC_HEADERS_FOLDER_PATH = ../Headers/POP; + SDKROOT = macosx; }; name = Debug; }; - EC6885A518C7B60100C6194C /* GCOV */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = ECC1DB1B18CA291B008C7DEA /* StaticLibrary-OSX.xcconfig */; - buildSettings = { - COMBINE_HIDPI_IMAGES = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - FRAMEWORK_VERSION = A; - GCC_PREFIX_HEADER = "$(PRODUCT_NAME)/$(PRODUCT_NAME)-Prefix.pch"; - INFOPLIST_FILE = "POP/pop-Info.plist"; - PRODUCT_NAME = pop; - PUBLIC_HEADERS_FOLDER_PATH = ../Headers/POP; - }; - name = GCOV; - }; EC6885A618C7B60100C6194C /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = ECC1DB1B18CA291B008C7DEA /* StaticLibrary-OSX.xcconfig */; + baseConfigurationReference = 04C0670F1B8D577C00ED0525 /* Framework.xcconfig */; buildSettings = { COMBINE_HIDPI_IMAGES = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - FRAMEWORK_VERSION = A; - GCC_PREFIX_HEADER = "$(PRODUCT_NAME)/$(PRODUCT_NAME)-Prefix.pch"; - INFOPLIST_FILE = "POP/pop-Info.plist"; + INFOPLIST_FILE = "$(PROJECT_DIR)/pop/pop-osx-Info.plist"; + INSTALL_PATH = "@rpath"; + PRODUCT_BUNDLE_IDENTIFIER = com.facebook.pop; PRODUCT_NAME = pop; - PUBLIC_HEADERS_FOLDER_PATH = ../Headers/POP; + SDKROOT = macosx; }; name = Release; }; EC6885A718C7B60100C6194C /* Profile */ = { isa = XCBuildConfiguration; - baseConfigurationReference = ECC1DB1B18CA291B008C7DEA /* StaticLibrary-OSX.xcconfig */; + baseConfigurationReference = 04C0670F1B8D577C00ED0525 /* Framework.xcconfig */; buildSettings = { COMBINE_HIDPI_IMAGES = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - FRAMEWORK_VERSION = A; - GCC_PREFIX_HEADER = "$(PRODUCT_NAME)/$(PRODUCT_NAME)-Prefix.pch"; - INFOPLIST_FILE = "POP/pop-Info.plist"; + INFOPLIST_FILE = "$(PROJECT_DIR)/pop/pop-osx-Info.plist"; + INSTALL_PATH = "@rpath"; + PRODUCT_BUNDLE_IDENTIFIER = com.facebook.pop; PRODUCT_NAME = pop; - PUBLIC_HEADERS_FOLDER_PATH = ../Headers/POP; + SDKROOT = macosx; }; name = Profile; }; EC7E31A718C93D6600B38170 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = D49ED131870840178CA788F1 /* Pods-pop-tests-osx.xcconfig */; + baseConfigurationReference = 5677DA2A8DA5A9DF667D2F25 /* Pods-Tests-pop-tests-osx.debug.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = "$(ARCHS_STANDARD)"; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = 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_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = NO; + COMBINE_HIDPI_IMAGES = YES; FRAMEWORK_SEARCH_PATHS = ( "$(DEVELOPER_FRAMEWORKS_DIR)", "$(inherited)", ); - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_ENABLE_OBJC_EXCEPTIONS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = "pop-tests-osx/pop-tests-osx-Prefix.pch"; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_SHADOW = NO; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - INFOPLIST_FILE = "pop-tests-osx/pop-tests-osx-Info.plist"; - MACOSX_DEPLOYMENT_TARGET = 10.9; + INFOPLIST_FILE = "$(PROJECT_DIR)/pop-tests/pop-tests-osx-Info.plist"; ONLY_ACTIVE_ARCH = YES; - PRODUCT_NAME = "pop-tests-osx"; + PRODUCT_BUNDLE_IDENTIFIER = "com.facebook.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "pop-tests"; SDKROOT = macosx; - WRAPPER_EXTENSION = octest; }; name = Debug; }; - EC7E31A818C93D6600B38170 /* GCOV */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = D49ED131870840178CA788F1 /* Pods-pop-tests-osx.xcconfig */; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = "$(ARCHS_STANDARD)"; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = 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_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = YES; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - FRAMEWORK_SEARCH_PATHS = ( - "$(DEVELOPER_FRAMEWORKS_DIR)", - "$(inherited)", - ); - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_ENABLE_OBJC_EXCEPTIONS = YES; - GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = "pop-tests-osx/pop-tests-osx-Prefix.pch"; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_SHADOW = NO; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - INFOPLIST_FILE = "pop-tests-osx/pop-tests-osx-Info.plist"; - MACOSX_DEPLOYMENT_TARGET = 10.9; - PRODUCT_NAME = "pop-tests-osx"; - SDKROOT = macosx; - WRAPPER_EXTENSION = octest; - }; - name = GCOV; - }; EC7E31A918C93D6600B38170 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = D49ED131870840178CA788F1 /* Pods-pop-tests-osx.xcconfig */; + baseConfigurationReference = 55AC0296922C5E9D7B593C59 /* Pods-Tests-pop-tests-osx.release.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = "$(ARCHS_STANDARD)"; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = 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_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = YES; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; + COMBINE_HIDPI_IMAGES = YES; FRAMEWORK_SEARCH_PATHS = ( "$(DEVELOPER_FRAMEWORKS_DIR)", "$(inherited)", ); - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_ENABLE_OBJC_EXCEPTIONS = YES; - GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = "pop-tests-osx/pop-tests-osx-Prefix.pch"; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_SHADOW = NO; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - INFOPLIST_FILE = "pop-tests-osx/pop-tests-osx-Info.plist"; - MACOSX_DEPLOYMENT_TARGET = 10.9; - PRODUCT_NAME = "pop-tests-osx"; + INFOPLIST_FILE = "$(PROJECT_DIR)/pop-tests/pop-tests-osx-Info.plist"; + PRODUCT_BUNDLE_IDENTIFIER = "com.facebook.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "pop-tests"; SDKROOT = macosx; - WRAPPER_EXTENSION = octest; }; name = Release; }; EC7E31AA18C93D6600B38170 /* Profile */ = { isa = XCBuildConfiguration; - baseConfigurationReference = D49ED131870840178CA788F1 /* Pods-pop-tests-osx.xcconfig */; + baseConfigurationReference = 406331B5EF869E167FFA3454 /* Pods-Tests-pop-tests-osx.profile.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = "$(ARCHS_STANDARD)"; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = 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_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = YES; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; + COMBINE_HIDPI_IMAGES = YES; FRAMEWORK_SEARCH_PATHS = ( "$(DEVELOPER_FRAMEWORKS_DIR)", "$(inherited)", ); - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_ENABLE_OBJC_EXCEPTIONS = YES; - GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = "pop-tests-osx/pop-tests-osx-Prefix.pch"; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_SHADOW = NO; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - INFOPLIST_FILE = "pop-tests-osx/pop-tests-osx-Info.plist"; - MACOSX_DEPLOYMENT_TARGET = 10.9; - PRODUCT_NAME = "pop-tests-osx"; + INFOPLIST_FILE = "$(PROJECT_DIR)/pop-tests/pop-tests-osx-Info.plist"; + PRODUCT_BUNDLE_IDENTIFIER = "com.facebook.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "pop-tests"; SDKROOT = macosx; - WRAPPER_EXTENSION = octest; }; name = Profile; }; ECF01EE318C92B80009E0AD1 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = CD38BFD00B29456D9B40D640 /* Pods-pop-tests.xcconfig */; + baseConfigurationReference = 84EDB88DF38CE22AC4893B65 /* Pods-Tests-pop-tests-ios.debug.xcconfig */; buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)"; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = 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_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; FRAMEWORK_SEARCH_PATHS = ( "$(SDKROOT)/Developer/Library/Frameworks", "$(inherited)", "$(DEVELOPER_FRAMEWORKS_DIR)", ); - GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = "pop-tests/pop-tests-Prefix.pch"; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_SHADOW = NO; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 7.0; - ONLY_ACTIVE_ARCH = YES; + INFOPLIST_FILE = "$(PROJECT_DIR)/pop-tests/pop-tests-ios-Info.plist"; + PRODUCT_BUNDLE_IDENTIFIER = "com.facebook.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "pop-tests"; - WRAPPER_EXTENSION = octest; + SDKROOT = iphoneos; }; name = Debug; }; - ECF01EE418C92B80009E0AD1 /* GCOV */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = CD38BFD00B29456D9B40D640 /* Pods-pop-tests.xcconfig */; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)"; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = 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_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - ENABLE_NS_ASSERTIONS = NO; - FRAMEWORK_SEARCH_PATHS = ( - "$(SDKROOT)/Developer/Library/Frameworks", - "$(inherited)", - "$(DEVELOPER_FRAMEWORKS_DIR)", - ); - GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = "pop-tests/pop-tests-Prefix.pch"; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_SHADOW = NO; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 7.0; - PRODUCT_NAME = "pop-tests"; - WRAPPER_EXTENSION = octest; - }; - name = GCOV; - }; ECF01EE518C92B80009E0AD1 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = CD38BFD00B29456D9B40D640 /* Pods-pop-tests.xcconfig */; + baseConfigurationReference = 85D44E5C12C69E1AC9E27D0B /* Pods-Tests-pop-tests-ios.release.xcconfig */; buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)"; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = 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_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - ENABLE_NS_ASSERTIONS = NO; FRAMEWORK_SEARCH_PATHS = ( "$(SDKROOT)/Developer/Library/Frameworks", "$(inherited)", "$(DEVELOPER_FRAMEWORKS_DIR)", ); - GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = "pop-tests/pop-tests-Prefix.pch"; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_SHADOW = NO; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 7.0; + INFOPLIST_FILE = "$(PROJECT_DIR)/pop-tests/pop-tests-ios-Info.plist"; + PRODUCT_BUNDLE_IDENTIFIER = "com.facebook.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "pop-tests"; - WRAPPER_EXTENSION = octest; + SDKROOT = iphoneos; }; name = Release; }; ECF01EE618C92B80009E0AD1 /* Profile */ = { isa = XCBuildConfiguration; - baseConfigurationReference = CD38BFD00B29456D9B40D640 /* Pods-pop-tests.xcconfig */; + baseConfigurationReference = D35FAC2FD6DFC1CC1BD1A636 /* Pods-Tests-pop-tests-ios.profile.xcconfig */; buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)"; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = 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_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - ENABLE_NS_ASSERTIONS = NO; FRAMEWORK_SEARCH_PATHS = ( "$(SDKROOT)/Developer/Library/Frameworks", "$(inherited)", "$(DEVELOPER_FRAMEWORKS_DIR)", ); - GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = "pop-tests/pop-tests-Prefix.pch"; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_SHADOW = NO; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 7.0; + INFOPLIST_FILE = "$(PROJECT_DIR)/pop-tests/pop-tests-ios-Info.plist"; + PRODUCT_BUNDLE_IDENTIFIER = "com.facebook.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "pop-tests"; - WRAPPER_EXTENSION = octest; + SDKROOT = iphoneos; }; name = Profile; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ + 0755AE571BEA15950094AB41 /* Build configuration list for PBXNativeTarget "pop-tvos-framework" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 0755AE541BEA15950094AB41 /* Debug */, + 0755AE551BEA15950094AB41 /* Release */, + 0755AE561BEA15950094AB41 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 0755AE941BEA19580094AB41 /* Build configuration list for PBXNativeTarget "pop-tests-tvos" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 0755AE951BEA19580094AB41 /* Debug */, + 0755AE961BEA19580094AB41 /* Release */, + 0755AE971BEA19580094AB41 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 0B6BE75B19FFD3B900762101 /* Build configuration list for PBXNativeTarget "pop-ios-framework" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 0B6BE75C19FFD3B900762101 /* Debug */, + 0B6BE75E19FFD3B900762101 /* Release */, + 0B6BE75F19FFD3B900762101 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; EC191212162FB53A00E0CC76 /* Build configuration list for PBXProject "pop" */ = { isa = XCConfigurationList; buildConfigurations = ( EC19123B162FB53A00E0CC76 /* Debug */, - 9062CE2A16BC56CC00655F1D /* GCOV */, EC19123C162FB53A00E0CC76 /* Release */, A2BDDD3D185A687F00838797 /* Profile */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - EC19123D162FB53A00E0CC76 /* Build configuration list for PBXNativeTarget "pop" */ = { + EC19123D162FB53A00E0CC76 /* Build configuration list for PBXNativeTarget "pop-ios-static" */ = { isa = XCConfigurationList; buildConfigurations = ( EC19123E162FB53A00E0CC76 /* Debug */, - 9062CE2B16BC56CC00655F1D /* GCOV */, EC19123F162FB53A00E0CC76 /* Release */, A2BDDD3E185A687F00838797 /* Profile */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - EC6885A318C7B60100C6194C /* Build configuration list for PBXNativeTarget "pop-osx" */ = { + EC6885A318C7B60100C6194C /* Build configuration list for PBXNativeTarget "pop-osx-framework" */ = { isa = XCConfigurationList; buildConfigurations = ( EC6885A418C7B60100C6194C /* Debug */, - EC6885A518C7B60100C6194C /* GCOV */, EC6885A618C7B60100C6194C /* Release */, EC6885A718C7B60100C6194C /* Profile */, ); @@ -1607,18 +1926,16 @@ isa = XCConfigurationList; buildConfigurations = ( EC7E31A718C93D6600B38170 /* Debug */, - EC7E31A818C93D6600B38170 /* GCOV */, EC7E31A918C93D6600B38170 /* Release */, EC7E31AA18C93D6600B38170 /* Profile */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - ECF01EE218C92B80009E0AD1 /* Build configuration list for PBXNativeTarget "pop-tests" */ = { + ECF01EE218C92B80009E0AD1 /* Build configuration list for PBXNativeTarget "pop-tests-ios" */ = { isa = XCConfigurationList; buildConfigurations = ( ECF01EE318C92B80009E0AD1 /* Debug */, - ECF01EE418C92B80009E0AD1 /* GCOV */, ECF01EE518C92B80009E0AD1 /* Release */, ECF01EE618C92B80009E0AD1 /* Profile */, ); diff --git a/pop.xcodeproj/xcshareddata/xcschemes/pop-ios-framework.xcscheme b/pop.xcodeproj/xcshareddata/xcschemes/pop-ios-framework.xcscheme new file mode 100644 index 00000000..9765eb4e --- /dev/null +++ b/pop.xcodeproj/xcshareddata/xcschemes/pop-ios-framework.xcscheme @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/pop.xcodeproj/xcshareddata/xcschemes/pop.xcscheme b/pop.xcodeproj/xcshareddata/xcschemes/pop-ios-static.xcscheme similarity index 63% rename from pop.xcodeproj/xcshareddata/xcschemes/pop.xcscheme rename to pop.xcodeproj/xcshareddata/xcschemes/pop-ios-static.xcscheme index 289e3fbf..a626b971 100644 --- a/pop.xcodeproj/xcshareddata/xcschemes/pop.xcscheme +++ b/pop.xcodeproj/xcshareddata/xcschemes/pop-ios-static.xcscheme @@ -1,6 +1,6 @@ @@ -29,63 +29,79 @@ - - - - + shouldUseLaunchSchemeArgsEnv = "YES"> + + + + + + + + + + + + + + diff --git a/pop.xcodeproj/xcshareddata/xcschemes/pop-osx.xcscheme b/pop.xcodeproj/xcshareddata/xcschemes/pop-osx-framework.xcscheme similarity index 77% rename from pop.xcodeproj/xcshareddata/xcschemes/pop-osx.xcscheme rename to pop.xcodeproj/xcshareddata/xcschemes/pop-osx-framework.xcscheme index 9dc3e7f2..273256dd 100644 --- a/pop.xcodeproj/xcshareddata/xcschemes/pop-osx.xcscheme +++ b/pop.xcodeproj/xcshareddata/xcschemes/pop-osx-framework.xcscheme @@ -1,6 +1,6 @@ + shouldUseLaunchSchemeArgsEnv = "YES"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/pop.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/pop.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/pop.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/pop/POP.h b/pop/POP.h index 29d5c43a..291db8d2 100644 --- a/pop/POP.h +++ b/pop/POP.h @@ -10,19 +10,21 @@ #ifndef POP_POP_H #define POP_POP_H -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import #endif /* POP_POP_H */ diff --git a/pop/POPAction.h b/pop/POPAction.h index 0827a354..85cca192 100644 --- a/pop/POPAction.h +++ b/pop/POPAction.h @@ -11,7 +11,8 @@ #define POPACTION_H #import -#import + +#import #ifdef __cplusplus diff --git a/pop/POPAnimatableProperty.h b/pop/POPAnimatableProperty.h index 25371fa5..d35f4248 100644 --- a/pop/POPAnimatableProperty.h +++ b/pop/POPAnimatableProperty.h @@ -8,8 +8,12 @@ */ #import + #import +#import +#import + @class POPMutableAnimatableProperty; /** @@ -43,12 +47,12 @@ /** @abstract Block used to read values from a property into an array of floats. */ -@property (readonly, nonatomic, copy) void (^readBlock)(id obj, CGFloat values[]); +@property (readonly, nonatomic, copy) POPAnimatablePropertyReadBlock readBlock; /** @abstract Block used to write values from an array of floats into a property. */ -@property (readonly, nonatomic, copy) void (^writeBlock)(id obj, const CGFloat values[]); +@property (readonly, nonatomic, copy) POPAnimatablePropertyWriteBlock writeBlock; /** @abstract The threshold value used when determining completion of dynamics simulations. @@ -70,12 +74,12 @@ /** @abstract A read-write version of POPAnimatableProperty readBlock property. */ -@property (readwrite, nonatomic, copy) void (^readBlock)(id obj, CGFloat values[]); +@property (readwrite, nonatomic, copy) POPAnimatablePropertyReadBlock readBlock; /** @abstract A read-write version of POPAnimatableProperty writeBlock property. */ -@property (readwrite, nonatomic, copy) void (^writeBlock)(id obj, const CGFloat values[]); +@property (readwrite, nonatomic, copy) POPAnimatablePropertyWriteBlock writeBlock; /** @abstract A read-write version of POPAnimatableProperty threshold property. @@ -84,11 +88,16 @@ @end +POP_EXTERN_C_BEGIN + /** Common CALayer property names. */ extern NSString * const kPOPLayerBackgroundColor; extern NSString * const kPOPLayerBounds; +extern NSString * const kPOPLayerCornerRadius; +extern NSString * const kPOPLayerBorderWidth; +extern NSString * const kPOPLayerBorderColor; extern NSString * const kPOPLayerOpacity; extern NSString * const kPOPLayerPosition; extern NSString * const kPOPLayerPositionX; @@ -110,7 +119,20 @@ extern NSString * const kPOPLayerTranslationXY; extern NSString * const kPOPLayerTranslationY; extern NSString * const kPOPLayerTranslationZ; extern NSString * const kPOPLayerZPosition; +extern NSString * const kPOPLayerShadowColor; +extern NSString * const kPOPLayerShadowOffset; +extern NSString * const kPOPLayerShadowOpacity; +extern NSString * const kPOPLayerShadowRadius; +/** + Common CAShapeLayer property names. + */ +extern NSString * const kPOPShapeLayerStrokeStart; +extern NSString * const kPOPShapeLayerStrokeEnd; +extern NSString * const kPOPShapeLayerStrokeColor; +extern NSString * const kPOPShapeLayerFillColor; +extern NSString * const kPOPShapeLayerLineWidth; +extern NSString * const kPOPShapeLayerLineDashPhase; /** Common NSLayoutConstraint property names. @@ -132,7 +154,16 @@ extern NSString * const kPOPViewScaleX; extern NSString * const kPOPViewScaleXY; extern NSString * const kPOPViewScaleY; extern NSString * const kPOPViewSize; +extern NSString * const kPOPViewTintColor; +/** + Common UIScrollView property names. + */ +extern NSString * const kPOPScrollViewContentOffset; +extern NSString * const kPOPScrollViewContentSize; +extern NSString * const kPOPScrollViewZoomScale; +extern NSString * const kPOPScrollViewContentInset; +extern NSString * const kPOPScrollViewScrollIndicatorInsets; /** Common UITableView property names. @@ -140,5 +171,86 @@ extern NSString * const kPOPViewSize; extern NSString * const kPOPTableViewContentOffset; extern NSString * const kPOPTableViewContentSize; +/** + Common UICollectionView property names. + */ +extern NSString * const kPOPCollectionViewContentOffset; +extern NSString * const kPOPCollectionViewContentSize; + +/** + Common UINavigationBar property names. + */ +extern NSString * const kPOPNavigationBarBarTintColor; + +/** + Common UIToolbar property names. + */ +extern NSString * const kPOPToolbarBarTintColor; + +/** + Common UITabBar property names. + */ +extern NSString * const kPOPTabBarBarTintColor; + +/** + Common UILabel property names. + */ +extern NSString * const kPOPLabelTextColor; + +#else + +/** + Common NSView property names. + */ +extern NSString * const kPOPViewFrame; +extern NSString * const kPOPViewBounds; +extern NSString * const kPOPViewAlphaValue; +extern NSString * const kPOPViewFrameRotation; +extern NSString * const kPOPViewFrameCenterRotation; +extern NSString * const kPOPViewBoundsRotation; + +/** + Common NSWindow property names. + */ +extern NSString * const kPOPWindowFrame; +extern NSString * const kPOPWindowAlphaValue; +extern NSString * const kPOPWindowBackgroundColor; #endif + +#if SCENEKIT_SDK_AVAILABLE + +/** + Common SceneKit property names. + */ +extern NSString * const kPOPSCNNodePosition; +extern NSString * const kPOPSCNNodePositionX; +extern NSString * const kPOPSCNNodePositionY; +extern NSString * const kPOPSCNNodePositionZ; +extern NSString * const kPOPSCNNodeTranslation; +extern NSString * const kPOPSCNNodeTranslationX; +extern NSString * const kPOPSCNNodeTranslationY; +extern NSString * const kPOPSCNNodeTranslationZ; +extern NSString * const kPOPSCNNodeRotation; +extern NSString * const kPOPSCNNodeRotationX; +extern NSString * const kPOPSCNNodeRotationY; +extern NSString * const kPOPSCNNodeRotationZ; +extern NSString * const kPOPSCNNodeRotationW; +extern NSString * const kPOPSCNNodeEulerAngles; +extern NSString * const kPOPSCNNodeEulerAnglesX; +extern NSString * const kPOPSCNNodeEulerAnglesY; +extern NSString * const kPOPSCNNodeEulerAnglesZ; +extern NSString * const kPOPSCNNodeOrientation; +extern NSString * const kPOPSCNNodeOrientationX; +extern NSString * const kPOPSCNNodeOrientationY; +extern NSString * const kPOPSCNNodeOrientationZ; +extern NSString * const kPOPSCNNodeOrientationW; +extern NSString * const kPOPSCNNodeScale; +extern NSString * const kPOPSCNNodeScaleX; +extern NSString * const kPOPSCNNodeScaleY; +extern NSString * const kPOPSCNNodeScaleZ; +extern NSString * const kPOPSCNNodeScaleXY; + +#endif + +POP_EXTERN_C_END diff --git a/pop/POPAnimatableProperty.mm b/pop/POPAnimatableProperty.mm index b5857452..7b63c50f 100644 --- a/pop/POPAnimatableProperty.mm +++ b/pop/POPAnimatableProperty.mm @@ -8,24 +8,30 @@ */ #import "POPAnimatableProperty.h" -#import "POPCGUtils.h" -#import "POPAnimationRuntime.h" #import -#import +#import "POPAnimationRuntime.h" +#import "POPCGUtils.h" +#import "POPDefines.h" +#import "POPLayerExtras.h" -#if TARGET_OS_IPHONE -#import -#import -#else -#import -#endif +// common threshold definitions +static CGFloat const kPOPThresholdColor = 0.01; +static CGFloat const kPOPThresholdPoint = 1.0; +static CGFloat const kPOPThresholdOpacity = 0.01; +static CGFloat const kPOPThresholdScale = 0.005; +static CGFloat const kPOPThresholdRotation = 0.01; +static CGFloat const kPOPThresholdRadius = 0.01; #pragma mark - Static +// CALayer NSString * const kPOPLayerBackgroundColor = @"backgroundColor"; NSString * const kPOPLayerBounds = @"bounds"; +NSString * const kPOPLayerCornerRadius = @"cornerRadius"; +NSString * const kPOPLayerBorderWidth = @"borderWidth"; +NSString * const kPOPLayerBorderColor = @"borderColor"; NSString * const kPOPLayerOpacity = @"opacity"; NSString * const kPOPLayerPosition = @"position"; NSString * const kPOPLayerPositionX = @"positionX"; @@ -47,9 +53,25 @@ NSString * const kPOPLayerTranslationY = @"translationY"; NSString * const kPOPLayerTranslationZ = @"translationZ"; NSString * const kPOPLayerZPosition = @"zPosition"; - +NSString * const kPOPLayerShadowColor = @"shadowColor"; +NSString * const kPOPLayerShadowOffset = @"shadowOffset"; +NSString * const kPOPLayerShadowOpacity = @"shadowOpacity"; +NSString * const kPOPLayerShadowRadius = @"shadowRadius"; + +// CAShapeLayer +NSString * const kPOPShapeLayerStrokeStart = @"shapeLayer.strokeStart"; +NSString * const kPOPShapeLayerStrokeEnd = @"shapeLayer.strokeEnd"; +NSString * const kPOPShapeLayerStrokeColor = @"shapeLayer.strokeColor"; +NSString * const kPOPShapeLayerFillColor = @"shapeLayer.fillColor"; +NSString * const kPOPShapeLayerLineWidth = @"shapeLayer.lineWidth"; +NSString * const kPOPShapeLayerLineDashPhase = @"shapeLayer.lineDashPhase"; + +// NSLayoutConstraint NSString * const kPOPLayoutConstraintConstant = @"layoutConstraint.constant"; +#if TARGET_OS_IPHONE + +// UIView NSString * const kPOPViewAlpha = @"view.alpha"; NSString * const kPOPViewBackgroundColor = @"view.backgroundColor"; NSString * const kPOPViewBounds = kPOPLayerBounds; @@ -59,10 +81,84 @@ NSString * const kPOPViewScaleXY = @"view.scaleXY"; NSString * const kPOPViewScaleY = @"view.scaleY"; NSString * const kPOPViewSize = kPOPLayerSize; +NSString * const kPOPViewTintColor = @"view.tintColor"; + +// UIScrollView +NSString * const kPOPScrollViewContentOffset = @"scrollView.contentOffset"; +NSString * const kPOPScrollViewContentSize = @"scrollView.contentSize"; +NSString * const kPOPScrollViewZoomScale = @"scrollView.zoomScale"; +NSString * const kPOPScrollViewContentInset = @"scrollView.contentInset"; +NSString * const kPOPScrollViewScrollIndicatorInsets = @"scrollView.scrollIndicatorInsets"; + +// UITableView +NSString * const kPOPTableViewContentOffset = kPOPScrollViewContentOffset; +NSString * const kPOPTableViewContentSize = kPOPScrollViewContentSize; + +// UICollectionView +NSString * const kPOPCollectionViewContentOffset = kPOPScrollViewContentOffset; +NSString * const kPOPCollectionViewContentSize = kPOPScrollViewContentSize; + +// UINavigationBar +NSString * const kPOPNavigationBarBarTintColor = @"navigationBar.barTintColor"; + +// UIToolbar +NSString * const kPOPToolbarBarTintColor = kPOPNavigationBarBarTintColor; + +// UITabBar +NSString * const kPOPTabBarBarTintColor = kPOPNavigationBarBarTintColor; + +// UILabel +NSString * const kPOPLabelTextColor = @"label.textColor"; + +#else + +// NSView +NSString * const kPOPViewFrame = @"view.frame"; +NSString * const kPOPViewBounds = @"view.bounds"; +NSString * const kPOPViewAlphaValue = @"view.alphaValue"; +NSString * const kPOPViewFrameRotation = @"view.frameRotation"; +NSString * const kPOPViewFrameCenterRotation = @"view.frameCenterRotation"; +NSString * const kPOPViewBoundsRotation = @"view.boundsRotation"; -NSString * const kPOPTableViewContentOffset = @"tableView.contentOffset"; -NSString * const kPOPTableViewContentSize = @"tableView.contentSize"; +// NSWindow +NSString * const kPOPWindowFrame = @"window.frame"; +NSString * const kPOPWindowAlphaValue = @"window.alphaValue"; +NSString * const kPOPWindowBackgroundColor = @"window.backgroundColor"; + +#endif +#if SCENEKIT_SDK_AVAILABLE + +// SceneKit +NSString * const kPOPSCNNodePosition = @"scnode.position"; +NSString * const kPOPSCNNodePositionX = @"scnnode.position.x"; +NSString * const kPOPSCNNodePositionY = @"scnnode.position.y"; +NSString * const kPOPSCNNodePositionZ = @"scnnode.position.z"; +NSString * const kPOPSCNNodeTranslation = @"scnnode.translation"; +NSString * const kPOPSCNNodeTranslationX = @"scnnode.translation.x"; +NSString * const kPOPSCNNodeTranslationY = @"scnnode.translation.y"; +NSString * const kPOPSCNNodeTranslationZ = @"scnnode.translation.z"; +NSString * const kPOPSCNNodeRotation = @"scnnode.rotation"; +NSString * const kPOPSCNNodeRotationX = @"scnnode.rotation.x"; +NSString * const kPOPSCNNodeRotationY = @"scnnode.rotation.y"; +NSString * const kPOPSCNNodeRotationZ = @"scnnode.rotation.z"; +NSString * const kPOPSCNNodeRotationW = @"scnnode.rotation.w"; +NSString * const kPOPSCNNodeEulerAngles = @"scnnode.eulerAngles"; +NSString * const kPOPSCNNodeEulerAnglesX = @"scnnode.eulerAngles.x"; +NSString * const kPOPSCNNodeEulerAnglesY = @"scnnode.eulerAngles.y"; +NSString * const kPOPSCNNodeEulerAnglesZ = @"scnnode.eulerAngles.z"; +NSString * const kPOPSCNNodeOrientation = @"scnnode.orientation"; +NSString * const kPOPSCNNodeOrientationX = @"scnnode.orientation.x"; +NSString * const kPOPSCNNodeOrientationY = @"scnnode.orientation.y"; +NSString * const kPOPSCNNodeOrientationZ = @"scnnode.orientation.z"; +NSString * const kPOPSCNNodeOrientationW = @"scnnode.orientation.w"; +NSString * const kPOPSCNNodeScale = @"scnnode.scale"; +NSString * const kPOPSCNNodeScaleX = @"scnnode.scale.x"; +NSString * const kPOPSCNNodeScaleY = @"scnnode.scale.y"; +NSString * const kPOPSCNNodeScaleZ = @"scnnode.scale.z"; +NSString * const kPOPSCNNodeScaleXY = @"scnnode.scale.xy"; + +#endif /** State structure internal to static animatable property. @@ -70,16 +166,18 @@ typedef struct { NSString *name; - pop_animatable_read_block readBlock; - pop_animatable_write_block writeBlock; - float threshold; + POPAnimatablePropertyReadBlock readBlock; + POPAnimatablePropertyWriteBlock writeBlock; + CGFloat threshold; } _POPStaticAnimatablePropertyState; typedef _POPStaticAnimatablePropertyState POPStaticAnimatablePropertyState; +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wglobal-constructors" static POPStaticAnimatablePropertyState _staticStates[] = { /* CALayer */ - + {kPOPLayerBackgroundColor, ^(CALayer *obj, CGFloat values[]) { POPCGColorGetRGBAComponents(obj.backgroundColor, values); @@ -89,7 +187,7 @@ [obj setBackgroundColor:color]; CGColorRelease(color); }, - 0.01 + kPOPThresholdColor }, {kPOPLayerBounds, @@ -99,7 +197,39 @@ ^(CALayer *obj, const CGFloat values[]) { [obj setBounds:values_to_rect(values)]; }, - 1.0 + kPOPThresholdPoint + }, + + {kPOPLayerCornerRadius, + ^(CALayer *obj, CGFloat values[]) { + values[0] = [obj cornerRadius]; + }, + ^(CALayer *obj, const CGFloat values[]) { + [obj setCornerRadius:values[0]]; + }, + kPOPThresholdRadius + }, + + {kPOPLayerBorderWidth, + ^(CALayer *obj, CGFloat values[]) { + values[0] = [obj borderWidth]; + }, + ^(CALayer *obj, const CGFloat values[]) { + [obj setBorderWidth:values[0]]; + }, + 0.01 + }, + + {kPOPLayerBorderColor, + ^(CALayer *obj, CGFloat values[]) { + POPCGColorGetRGBAComponents(obj.borderColor, values); + }, + ^(CALayer *obj, const CGFloat values[]) { + CGColorRef color = POPCGColorRGBACreate(values); + [obj setBorderColor:color]; + CGColorRelease(color); + }, + kPOPThresholdColor }, {kPOPLayerPosition, @@ -109,7 +239,7 @@ ^(CALayer *obj, const CGFloat values[]) { [obj setPosition:values_to_point(values)]; }, - 1.0 + kPOPThresholdPoint }, {kPOPLayerPositionX, @@ -121,7 +251,7 @@ p.x = values[0]; [obj setPosition:p]; }, - 1.0 + kPOPThresholdPoint }, {kPOPLayerPositionY, @@ -133,7 +263,7 @@ p.y = values[0]; [obj setPosition:p]; }, - 1.0 + kPOPThresholdPoint }, {kPOPLayerOpacity, @@ -143,7 +273,7 @@ ^(CALayer *obj, const CGFloat values[]) { [obj setOpacity:((float)values[0])]; }, - 0.01 + kPOPThresholdOpacity }, {kPOPLayerScaleX, @@ -153,7 +283,7 @@ ^(CALayer *obj, const CGFloat values[]) { POPLayerSetScaleX(obj, values[0]); }, - 0.005 + kPOPThresholdScale }, {kPOPLayerScaleY, @@ -163,7 +293,7 @@ ^(CALayer *obj, const CGFloat values[]) { POPLayerSetScaleY(obj, values[0]); }, - 0.005 + kPOPThresholdScale }, {kPOPLayerScaleXY, @@ -173,7 +303,7 @@ ^(CALayer *obj, const CGFloat values[]) { POPLayerSetScaleXY(obj, values_to_point(values)); }, - 0.005 + kPOPThresholdScale }, {kPOPLayerSubscaleXY, @@ -183,7 +313,7 @@ ^(CALayer *obj, const CGFloat values[]) { POPLayerSetSubScaleXY(obj, values_to_point(values)); }, - 0.005 + kPOPThresholdScale }, {kPOPLayerTranslationX, @@ -193,7 +323,7 @@ ^(CALayer *obj, const CGFloat values[]) { POPLayerSetTranslationX(obj, values[0]); }, - 1.0 + kPOPThresholdPoint }, {kPOPLayerTranslationY, @@ -203,7 +333,7 @@ ^(CALayer *obj, const CGFloat values[]) { POPLayerSetTranslationY(obj, values[0]); }, - 1.0 + kPOPThresholdPoint }, {kPOPLayerTranslationZ, @@ -213,7 +343,7 @@ ^(CALayer *obj, const CGFloat values[]) { POPLayerSetTranslationZ(obj, values[0]); }, - 1.0 + kPOPThresholdPoint }, {kPOPLayerTranslationXY, @@ -223,7 +353,7 @@ ^(CALayer *obj, const CGFloat values[]) { POPLayerSetTranslationXY(obj, values_to_point(values)); }, - 1.0 + kPOPThresholdPoint }, {kPOPLayerSubtranslationX, @@ -233,7 +363,7 @@ ^(CALayer *obj, const CGFloat values[]) { POPLayerSetSubTranslationX(obj, values[0]); }, - 1.0 + kPOPThresholdPoint }, {kPOPLayerSubtranslationY, @@ -243,7 +373,7 @@ ^(CALayer *obj, const CGFloat values[]) { POPLayerSetSubTranslationY(obj, values[0]); }, - 1.0 + kPOPThresholdPoint }, {kPOPLayerSubtranslationZ, @@ -253,7 +383,7 @@ ^(CALayer *obj, const CGFloat values[]) { POPLayerSetSubTranslationZ(obj, values[0]); }, - 1.0 + kPOPThresholdPoint }, {kPOPLayerSubtranslationXY, @@ -263,7 +393,7 @@ ^(CALayer *obj, const CGFloat values[]) { POPLayerSetSubTranslationXY(obj, values_to_point(values)); }, - 1.0 + kPOPThresholdPoint }, {kPOPLayerZPosition, @@ -273,7 +403,7 @@ ^(CALayer *obj, const CGFloat values[]) { [obj setZPosition:values[0]]; }, - 1.0 + kPOPThresholdPoint }, {kPOPLayerSize, @@ -289,7 +419,7 @@ b.size = size; [obj setBounds:b]; }, - 1.0 + kPOPThresholdPoint }, {kPOPLayerRotation, @@ -299,7 +429,7 @@ ^(CALayer *obj, const CGFloat values[]) { POPLayerSetRotation(obj, values[0]); }, - 0.01 + kPOPThresholdRotation }, {kPOPLayerRotationY, @@ -309,7 +439,7 @@ ^(id obj, const CGFloat values[]) { POPLayerSetRotationY(obj, values[0]); }, - 0.01 + kPOPThresholdRotation }, {kPOPLayerRotationX, @@ -319,9 +449,118 @@ ^(CALayer *obj, const CGFloat values[]) { POPLayerSetRotationX(obj, values[0]); }, + kPOPThresholdRotation + }, + + {kPOPLayerShadowColor, + ^(CALayer *obj, CGFloat values[]) { + POPCGColorGetRGBAComponents(obj.shadowColor, values); + }, + ^(CALayer *obj, const CGFloat values[]) { + CGColorRef color = POPCGColorRGBACreate(values); + [obj setShadowColor:color]; + CGColorRelease(color); + }, + 0.01 + }, + + {kPOPLayerShadowOffset, + ^(CALayer *obj, CGFloat values[]) { + values_from_size(values, [obj shadowOffset]); + }, + ^(CALayer *obj, const CGFloat values[]) { + CGSize size = values_to_size(values); + [obj setShadowOffset:size]; + }, 0.01 }, + {kPOPLayerShadowOpacity, + ^(CALayer *obj, CGFloat values[]) { + values[0] = [obj shadowOpacity]; + }, + ^(CALayer *obj, const CGFloat values[]) { + [obj setShadowOpacity:values[0]]; + }, + kPOPThresholdOpacity + }, + + {kPOPLayerShadowRadius, + ^(CALayer *obj, CGFloat values[]) { + values[0] = [obj shadowRadius]; + }, + ^(CALayer *obj, const CGFloat values[]) { + [obj setShadowRadius:values[0]]; + }, + kPOPThresholdRadius + }, + + /* CAShapeLayer */ + + {kPOPShapeLayerStrokeStart, + ^(CAShapeLayer *obj, CGFloat values[]) { + values[0] = obj.strokeStart; + }, + ^(CAShapeLayer *obj, const CGFloat values[]) { + obj.strokeStart = values[0]; + }, + 0.01 + }, + + {kPOPShapeLayerStrokeEnd, + ^(CAShapeLayer *obj, CGFloat values[]) { + values[0] = obj.strokeEnd; + }, + ^(CAShapeLayer *obj, const CGFloat values[]) { + obj.strokeEnd = values[0]; + }, + 0.01 + }, + + {kPOPShapeLayerStrokeColor, + ^(CAShapeLayer *obj, CGFloat values[]) { + POPCGColorGetRGBAComponents(obj.strokeColor, values); + }, + ^(CAShapeLayer *obj, const CGFloat values[]) { + CGColorRef color = POPCGColorRGBACreate(values); + [obj setStrokeColor:color]; + CGColorRelease(color); + }, + kPOPThresholdColor + }, + + {kPOPShapeLayerFillColor, + ^(CAShapeLayer *obj, CGFloat values[]) { + POPCGColorGetRGBAComponents(obj.fillColor, values); + }, + ^(CAShapeLayer *obj, const CGFloat values[]) { + CGColorRef color = POPCGColorRGBACreate(values); + [obj setFillColor:color]; + CGColorRelease(color); + }, + kPOPThresholdColor + }, + + {kPOPShapeLayerLineWidth, + ^(CAShapeLayer *obj, CGFloat values[]) { + values[0] = obj.lineWidth; + }, + ^(CAShapeLayer *obj, const CGFloat values[]) { + obj.lineWidth = values[0]; + }, + 0.01 + }, + + {kPOPShapeLayerLineDashPhase, + ^(CAShapeLayer *obj, CGFloat values[]) { + values[0] = obj.lineDashPhase; + }, + ^(CAShapeLayer *obj, const CGFloat values[]) { + obj.lineDashPhase = values[0]; + }, + 0.01 + }, + {kPOPLayoutConstraintConstant, ^(NSLayoutConstraint *obj, CGFloat values[]) { values[0] = obj.constant; @@ -333,9 +572,9 @@ }, #if TARGET_OS_IPHONE - + /* UIView */ - + {kPOPViewAlpha, ^(UIView *obj, CGFloat values[]) { values[0] = obj.alpha; @@ -343,7 +582,7 @@ ^(UIView *obj, const CGFloat values[]) { obj.alpha = values[0]; }, - 1.0 + kPOPThresholdOpacity }, {kPOPViewBackgroundColor, @@ -353,7 +592,7 @@ ^(UIView *obj, const CGFloat values[]) { obj.backgroundColor = POPUIColorRGBACreate(values); }, - 1.0 + kPOPThresholdColor }, {kPOPViewCenter, @@ -363,7 +602,7 @@ ^(UIView *obj, const CGFloat values[]) { obj.center = values_to_point(values); }, - 1.0 + kPOPThresholdPoint }, {kPOPViewFrame, @@ -373,7 +612,7 @@ ^(UIView *obj, const CGFloat values[]) { obj.frame = values_to_rect(values); }, - 1.0 + kPOPThresholdPoint }, {kPOPViewScaleX, @@ -383,7 +622,7 @@ ^(UIView *obj, const CGFloat values[]) { POPLayerSetScaleX(obj.layer, values[0]); }, - 0.005 + kPOPThresholdScale }, {kPOPViewScaleY, @@ -393,7 +632,7 @@ ^(UIView *obj, const CGFloat values[]) { POPLayerSetScaleY(obj.layer, values[0]); }, - 0.005 + kPOPThresholdScale }, {kPOPViewScaleXY, @@ -403,34 +642,480 @@ ^(UIView *obj, const CGFloat values[]) { POPLayerSetScaleXY(obj.layer, values_to_point(values)); }, - 0.005 + kPOPThresholdScale }, - - /* UITableView */ - - {kPOPTableViewContentOffset, - ^(UITableView *obj, CGFloat values[]) { + + {kPOPViewTintColor, + ^(UIView *obj, CGFloat values[]) { + POPUIColorGetRGBAComponents(obj.tintColor, values); + }, + ^(UIView *obj, const CGFloat values[]) { + obj.tintColor = POPUIColorRGBACreate(values); + }, + kPOPThresholdColor + }, + + /* UIScrollView */ + + {kPOPScrollViewContentOffset, + ^(UIScrollView *obj, CGFloat values[]) { values_from_point(values, obj.contentOffset); }, - ^(UITableView *obj, const CGFloat values[]) { - obj.contentOffset = values_to_point(values); + ^(UIScrollView *obj, const CGFloat values[]) { + [obj setContentOffset:values_to_point(values) animated:NO]; }, - 1.0 + kPOPThresholdPoint }, - {kPOPTableViewContentSize, - ^(UITableView *obj, CGFloat values[]) { + {kPOPScrollViewContentSize, + ^(UIScrollView *obj, CGFloat values[]) { values_from_size(values, obj.contentSize); }, - ^(UITableView *obj, const CGFloat values[]) { + ^(UIScrollView *obj, const CGFloat values[]) { obj.contentSize = values_to_size(values); }, - 1.0 + kPOPThresholdPoint + }, + + {kPOPScrollViewZoomScale, + ^(UIScrollView *obj, CGFloat values[]) { + values[0]=obj.zoomScale; + }, + ^(UIScrollView *obj, const CGFloat values[]) { + obj.zoomScale=values[0]; + }, + kPOPThresholdScale + }, + + {kPOPScrollViewContentInset, + ^(UIScrollView *obj, CGFloat values[]) { + values[0] = obj.contentInset.top; + values[1] = obj.contentInset.left; + values[2] = obj.contentInset.bottom; + values[3] = obj.contentInset.right; + }, + ^(UIScrollView *obj, const CGFloat values[]) { + obj.contentInset = values_to_edge_insets(values); + }, + kPOPThresholdPoint + }, + + {kPOPScrollViewScrollIndicatorInsets, + ^(UIScrollView *obj, CGFloat values[]) { + values[0] = obj.scrollIndicatorInsets.top; + values[1] = obj.scrollIndicatorInsets.left; + values[2] = obj.scrollIndicatorInsets.bottom; + values[3] = obj.scrollIndicatorInsets.right; + }, + ^(UIScrollView *obj, const CGFloat values[]) { + obj.scrollIndicatorInsets = values_to_edge_insets(values); + }, + kPOPThresholdPoint + }, + + /* UINavigationBar */ + + {kPOPNavigationBarBarTintColor, + ^(UINavigationBar *obj, CGFloat values[]) { + POPUIColorGetRGBAComponents(obj.barTintColor, values); + }, + ^(UINavigationBar *obj, const CGFloat values[]) { + obj.barTintColor = POPUIColorRGBACreate(values); + }, + kPOPThresholdColor + }, + + /* UILabel */ + + {kPOPLabelTextColor, + ^(UILabel *obj, CGFloat values[]) { + POPUIColorGetRGBAComponents(obj.textColor, values); + }, + ^(UILabel *obj, const CGFloat values[]) { + obj.textColor = POPUIColorRGBACreate(values); + }, + kPOPThresholdColor + }, + +#else + + /* NSView */ + + {kPOPViewFrame, + ^(NSView *obj, CGFloat values[]) { + values_from_rect(values, NSRectToCGRect(obj.frame)); + }, + ^(NSView *obj, const CGFloat values[]) { + obj.frame = NSRectFromCGRect(values_to_rect(values)); + }, + kPOPThresholdPoint + }, + + {kPOPViewBounds, + ^(NSView *obj, CGFloat values[]) { + values_from_rect(values, NSRectToCGRect(obj.frame)); + }, + ^(NSView *obj, const CGFloat values[]) { + obj.bounds = NSRectFromCGRect(values_to_rect(values)); + }, + kPOPThresholdPoint + }, + + {kPOPViewAlphaValue, + ^(NSView *obj, CGFloat values[]) { + values[0] = obj.alphaValue; + }, + ^(NSView *obj, const CGFloat values[]) { + obj.alphaValue = values[0]; + }, + kPOPThresholdOpacity + }, + + {kPOPViewFrameRotation, + ^(NSView *obj, CGFloat values[]) { + values[0] = obj.frameRotation; + }, + ^(NSView *obj, const CGFloat values[]) { + obj.frameRotation = values[0]; + }, + kPOPThresholdRotation + }, + + {kPOPViewFrameCenterRotation, + ^(NSView *obj, CGFloat values[]) { + values[0] = obj.frameCenterRotation; + }, + ^(NSView *obj, const CGFloat values[]) { + obj.frameCenterRotation = values[0]; + }, + kPOPThresholdRotation + }, + + {kPOPViewBoundsRotation, + ^(NSView *obj, CGFloat values[]) { + values[0] = obj.boundsRotation; + }, + ^(NSView *obj, const CGFloat values[]) { + obj.boundsRotation = values[0]; + }, + kPOPThresholdRotation + }, + + /* NSWindow */ + + {kPOPWindowFrame, + ^(NSWindow *obj, CGFloat values[]) { + values_from_rect(values, NSRectToCGRect(obj.frame)); + }, + ^(NSWindow *obj, const CGFloat values[]) { + [obj setFrame:NSRectFromCGRect(values_to_rect(values)) display:YES]; + }, + kPOPThresholdPoint + }, + + {kPOPWindowAlphaValue, + ^(NSWindow *obj, CGFloat values[]) { + values[0] = obj.alphaValue; + }, + ^(NSWindow *obj, const CGFloat values[]) { + obj.alphaValue = values[0]; + }, + kPOPThresholdOpacity + }, + + {kPOPWindowBackgroundColor, + ^(NSWindow *obj, CGFloat values[]) { + POPNSColorGetRGBAComponents(obj.backgroundColor, values); + }, + ^(NSWindow *obj, const CGFloat values[]) { + obj.backgroundColor = POPNSColorRGBACreate(values); + }, + kPOPThresholdColor + }, + +#endif + +#if SCENEKIT_SDK_AVAILABLE + + /* SceneKit */ + + {kPOPSCNNodePosition, + ^(SCNNode *obj, CGFloat values[]) { + values_from_vec3(values, obj.position); + }, + ^(SCNNode *obj, const CGFloat values[]) { + obj.position = values_to_vec3(values); + }, + kPOPThresholdScale + }, + + {kPOPSCNNodePositionX, + ^(SCNNode *obj, CGFloat values[]) { + values[0] = obj.position.x; + }, + ^(SCNNode *obj, const CGFloat values[]) { + obj.position = SCNVector3Make(values[0], obj.position.y, obj.position.z); + }, + kPOPThresholdScale + }, + + {kPOPSCNNodePositionY, + ^(SCNNode *obj, CGFloat values[]) { + values[0] = obj.position.y; + }, + ^(SCNNode *obj, const CGFloat values[]) { + obj.position = SCNVector3Make(obj.position.x, values[0], obj.position.z); + }, + kPOPThresholdScale + }, + + {kPOPSCNNodePositionZ, + ^(SCNNode *obj, CGFloat values[]) { + values[0] = obj.position.z; + }, + ^(SCNNode *obj, const CGFloat values[]) { + obj.position = SCNVector3Make(obj.position.x, obj.position.y, values[0]); + }, + kPOPThresholdScale + }, + + {kPOPSCNNodeTranslation, + ^(SCNNode *obj, CGFloat values[]) { + values[0] = obj.transform.m41; + values[1] = obj.transform.m42; + values[2] = obj.transform.m43; + }, + ^(SCNNode *obj, const CGFloat values[]) { + obj.transform = SCNMatrix4MakeTranslation(values[0], values[1], values[2]); + }, + kPOPThresholdScale + }, + + {kPOPSCNNodeTranslationX, + ^(SCNNode *obj, CGFloat values[]) { + values[0] = obj.transform.m41; + }, + ^(SCNNode *obj, const CGFloat values[]) { + obj.transform = SCNMatrix4MakeTranslation(values[0], obj.transform.m42, obj.transform.m43); + }, + kPOPThresholdScale + }, + + {kPOPSCNNodeTranslationY, + ^(SCNNode *obj, CGFloat values[]) { + values[0] = obj.transform.m42; + }, + ^(SCNNode *obj, const CGFloat values[]) { + obj.transform = SCNMatrix4MakeTranslation(obj.transform.m41, values[0], obj.transform.m43); + }, + kPOPThresholdScale + }, + + {kPOPSCNNodeTranslationY, + ^(SCNNode *obj, CGFloat values[]) { + values[0] = obj.transform.m43; + }, + ^(SCNNode *obj, const CGFloat values[]) { + obj.transform = SCNMatrix4MakeTranslation(obj.transform.m41, obj.transform.m42, values[0]); + }, + kPOPThresholdScale + }, + + {kPOPSCNNodeRotation, + ^(SCNNode *obj, CGFloat values[]) { + values_from_vec4(values, obj.rotation); + }, + ^(SCNNode *obj, const CGFloat values[]) { + obj.rotation = values_to_vec4(values); + }, + kPOPThresholdScale + }, + + {kPOPSCNNodeRotationX, + ^(SCNNode *obj, CGFloat values[]) { + values[0] = obj.rotation.x; + }, + ^(SCNNode *obj, const CGFloat values[]) { + obj.rotation = SCNVector4Make(1.0, obj.rotation.y, obj.rotation.z, values[0]); + }, + kPOPThresholdScale + }, + + {kPOPSCNNodeRotationY, + ^(SCNNode *obj, CGFloat values[]) { + values[0] = obj.rotation.y; + }, + ^(SCNNode *obj, const CGFloat values[]) { + obj.rotation = SCNVector4Make(obj.rotation.x, 1.0, obj.rotation.z, values[0]); + }, + kPOPThresholdScale + }, + + {kPOPSCNNodeRotationZ, + ^(SCNNode *obj, CGFloat values[]) { + values[0] = obj.rotation.z; + }, + ^(SCNNode *obj, const CGFloat values[]) { + obj.rotation = SCNVector4Make(obj.rotation.x, obj.rotation.y, 1.0, values[0]); + }, + kPOPThresholdScale + }, + + {kPOPSCNNodeRotationW, + ^(SCNNode *obj, CGFloat values[]) { + values[0] = obj.rotation.w; + }, + ^(SCNNode *obj, const CGFloat values[]) { + obj.rotation = SCNVector4Make(obj.rotation.x, obj.rotation.y, obj.rotation.z, values[0]); + }, + kPOPThresholdScale + }, + + {kPOPSCNNodeEulerAngles, + ^(SCNNode *obj, CGFloat values[]) { + values_from_vec3(values, obj.eulerAngles); + }, + ^(SCNNode *obj, const CGFloat values[]) { + obj.eulerAngles = values_to_vec3(values); + }, + kPOPThresholdScale + }, + + {kPOPSCNNodeEulerAnglesX, + ^(SCNNode *obj, CGFloat values[]) { + values[0] = obj.eulerAngles.x; + }, + ^(SCNNode *obj, const CGFloat values[]) { + obj.eulerAngles = SCNVector3Make(values[0], obj.eulerAngles.y, obj.eulerAngles.z); + }, + kPOPThresholdScale + }, + + {kPOPSCNNodeEulerAnglesY, + ^(SCNNode *obj, CGFloat values[]) { + values[0] = obj.eulerAngles.y; + }, + ^(SCNNode *obj, const CGFloat values[]) { + obj.eulerAngles = SCNVector3Make(obj.eulerAngles.x, values[0], obj.eulerAngles.z); + }, + kPOPThresholdScale + }, + + {kPOPSCNNodeEulerAnglesZ, + ^(SCNNode *obj, CGFloat values[]) { + values[0] = obj.eulerAngles.z; + }, + ^(SCNNode *obj, const CGFloat values[]) { + obj.eulerAngles = SCNVector3Make(obj.eulerAngles.x, obj.eulerAngles.y, values[0]); + }, + kPOPThresholdScale + }, + + {kPOPSCNNodeOrientation, + ^(SCNNode *obj, CGFloat values[]) { + values_from_vec4(values, obj.orientation); + }, + ^(SCNNode *obj, const CGFloat values[]) { + obj.orientation = values_to_vec4(values); + }, + kPOPThresholdScale + }, + + {kPOPSCNNodeOrientationX, + ^(SCNNode *obj, CGFloat values[]) { + values[0] = obj.orientation.x; + }, + ^(SCNNode *obj, const CGFloat values[]) { + obj.orientation = SCNVector4Make(values[0], obj.orientation.y, obj.orientation.z, obj.orientation.w); + }, + kPOPThresholdScale + }, + + {kPOPSCNNodeOrientationY, + ^(SCNNode *obj, CGFloat values[]) { + values[0] = obj.orientation.y; + }, + ^(SCNNode *obj, const CGFloat values[]) { + obj.orientation = SCNVector4Make(obj.orientation.x, values[0], obj.orientation.z, obj.orientation.w); + }, + kPOPThresholdScale + }, + + {kPOPSCNNodeOrientationZ, + ^(SCNNode *obj, CGFloat values[]) { + values[0] = obj.orientation.z; + }, + ^(SCNNode *obj, const CGFloat values[]) { + obj.orientation = SCNVector4Make(obj.orientation.x, obj.orientation.y, values[0], obj.orientation.w); + }, + kPOPThresholdScale + }, + + {kPOPSCNNodeOrientationW, + ^(SCNNode *obj, CGFloat values[]) { + values[0] = obj.orientation.w; + }, + ^(SCNNode *obj, const CGFloat values[]) { + obj.orientation = SCNVector4Make(obj.orientation.x, obj.orientation.y, obj.orientation.z, values[0]); + }, + kPOPThresholdScale + }, + + {kPOPSCNNodeScale, + ^(SCNNode *obj, CGFloat values[]) { + values_from_vec3(values, obj.scale); + }, + ^(SCNNode *obj, const CGFloat values[]) { + obj.scale = values_to_vec3(values); + }, + kPOPThresholdScale + }, + + {kPOPSCNNodeScaleX, + ^(SCNNode *obj, CGFloat values[]) { + values[0] = obj.scale.x; + }, + ^(SCNNode *obj, const CGFloat values[]) { + obj.scale = SCNVector3Make(values[0], obj.scale.y, obj.scale.z); + }, + kPOPThresholdScale + }, + + {kPOPSCNNodeScaleY, + ^(SCNNode *obj, CGFloat values[]) { + values[0] = obj.scale.y; + }, + ^(SCNNode *obj, const CGFloat values[]) { + obj.position = SCNVector3Make(obj.scale.x, values[0], obj.scale.z); + }, + kPOPThresholdScale + }, + + {kPOPSCNNodeScaleZ, + ^(SCNNode *obj, CGFloat values[]) { + values[0] = obj.scale.z; + }, + ^(SCNNode *obj, const CGFloat values[]) { + obj.scale = SCNVector3Make(obj.scale.x, obj.scale.y, values[0]); + }, + kPOPThresholdScale + }, + + {kPOPSCNNodeScaleXY, + ^(SCNNode *obj, CGFloat values[]) { + values[0] = obj.scale.x; + values[1] = obj.scale.y; + }, + ^(SCNNode *obj, const CGFloat values[]) { + obj.scale = SCNVector3Make(values[0], values[1], obj.scale.z); + }, + kPOPThresholdScale }, #endif }; +#pragma clang diagnostic pop static NSUInteger staticIndexWithName(NSString *aName) { @@ -462,12 +1147,12 @@ - (NSString *)name return _state->name; } -- (pop_animatable_read_block)readBlock +- (POPAnimatablePropertyReadBlock)readBlock { return _state->readBlock; } -- (pop_animatable_write_block)writeBlock +- (POPAnimatablePropertyWriteBlock)writeBlock { return _state->writeBlock; } @@ -485,7 +1170,7 @@ - (CGFloat)threshold Concrete immutable property class. */ @interface POPConcreteAnimatableProperty : POPAnimatableProperty -- (instancetype)initWithName:(NSString *)name readBlock:(pop_animatable_read_block)read writeBlock:(pop_animatable_write_block)write threshold:(CGFloat)threshold; +- (instancetype)initWithName:(NSString *)name readBlock:(POPAnimatablePropertyReadBlock)read writeBlock:(POPAnimatablePropertyWriteBlock)write threshold:(CGFloat)threshold; @end @implementation POPConcreteAnimatableProperty @@ -493,7 +1178,7 @@ @implementation POPConcreteAnimatableProperty // default synthesis @synthesize name, readBlock, writeBlock, threshold; -- (instancetype)initWithName:(NSString *)aName readBlock:(pop_animatable_read_block)aReadBlock writeBlock:(pop_animatable_write_block)aWriteBlock threshold:(CGFloat)aThreshold +- (instancetype)initWithName:(NSString *)aName readBlock:(POPAnimatablePropertyReadBlock)aReadBlock writeBlock:(POPAnimatablePropertyWriteBlock)aWriteBlock threshold:(CGFloat)aThreshold { self = [super init]; if (nil != self) { diff --git a/pop/POPAnimatablePropertyTypes.h b/pop/POPAnimatablePropertyTypes.h new file mode 100644 index 00000000..27f6379d --- /dev/null +++ b/pop/POPAnimatablePropertyTypes.h @@ -0,0 +1,11 @@ +/** + Copyright (c) 2014-present, Facebook, Inc. + All rights reserved. + + This source code is licensed under the BSD-style license found in the + LICENSE file in the root directory of this source tree. An additional grant + of patent rights can be found in the PATENTS file in the same directory. + */ + +typedef void (^POPAnimatablePropertyReadBlock)(id obj, CGFloat values[]); +typedef void (^POPAnimatablePropertyWriteBlock)(id obj, const CGFloat values[]); diff --git a/pop/POPAnimation.h b/pop/POPAnimation.h index 4b62afc8..7f568cf1 100644 --- a/pop/POPAnimation.h +++ b/pop/POPAnimation.h @@ -9,8 +9,8 @@ #import -#import -#import +#import +#import @class CAMediaTimingFunction; @@ -44,11 +44,26 @@ */ @property (readonly, nonatomic) POPAnimationTracer *tracer; +/** + @abstract Optional block called on animation start. + */ +@property (copy, nonatomic) void (^animationDidStartBlock)(POPAnimation *anim); + +/** + @abstract Optional block called when value meets or exceeds to value. + */ +@property (copy, nonatomic) void (^animationDidReachToValueBlock)(POPAnimation *anim); + /** @abstract Optional block called on animation completion. */ @property (copy, nonatomic) void (^completionBlock)(POPAnimation *anim, BOOL finished); +/** + @abstract Optional block called each frame animation is applied. + */ +@property (copy, nonatomic) void (^animationDidApplyBlock)(POPAnimation *anim); + /** @abstract Flag indicating whether animation should be removed on completion. @discussion Setting to NO can facilitate animation reuse. Defaults to YES. @@ -61,6 +76,34 @@ */ @property (assign, nonatomic, getter = isPaused) BOOL paused; +/** + @abstract Flag indicating whether animation autoreverses. + @discussion An animation that autoreverses will have twice the duration before it is considered finished. It will animate to the toValue, stop, then animate back to the original fromValue. The delegate methods are called as follows: + + 1) animationDidStart: is called at the beginning, as usual, and then after each toValue is reached and the autoreverse is going to start. + 2) animationDidReachToValue: is called every time the toValue is reached. The toValue is swapped with the fromValue at the end of each animation segment. This means that with autoreverses set to YES, the animationDidReachToValue: delegate method will be called a minimum of twice. + 3) animationDidStop:finished: is called every time the toValue is reached, the finished argument will be NO if the autoreverse is not yet complete. + */ +@property (assign, nonatomic) BOOL autoreverses; + +/** + @abstract The number of times to repeat the animation. + @discussion A repeatCount of 0 or 1 means that the animation will not repeat, just like Core Animation. A repeatCount of 2 or greater means that the animation will run that many times before stopping. The delegate methods are called as follows: + + 1) animationDidStart: is called at the beginning of each animation repeat. + 2) animationDidReachToValue: is called every time the toValue is reached. + 3) animationDidStop:finished: is called every time the toValue is reached, the finished argument will be NO if the autoreverse is not yet complete. + +When combined with the autoreverses property, a singular animation is effectively twice as long. + */ +@property (assign, nonatomic) NSInteger repeatCount; + +/** + @abstract Repeat the animation forever. + @discussion This property will make the animation repeat forever. The value of the repeatCount property is undefined when this property is set. The finished parameter of the delegate callback animationDidStop:finished: will always be NO. + */ +@property (assign, nonatomic) BOOL repeatForever; + @end /** @@ -120,7 +163,7 @@ /** @abstract Returns an array containing the keys of all animations currently attached to the receiver. - @param The order of keys reflects the order in which animations will be applied. + The order of keys reflects the order in which animations will be applied. */ - (NSArray *)pop_animationKeys; @@ -132,3 +175,14 @@ - (id)pop_animationForKey:(NSString *)key; @end + +/** + * This implementation of NSCopying does not do any copying of animation's state, but only configuration. + * i.e. you cannot copy an animation and expect to apply it to a view and have the copied animation pick up where the original left off. + * Two common uses of copying animations: + * * you need to apply the same animation to multiple different views. + * * you need to absolutely ensure that the the caller of your function cannot mutate the animation once it's been passed in. + */ +@interface POPAnimation (NSCopying) + +@end diff --git a/pop/POPAnimation.mm b/pop/POPAnimation.mm index 91b3ca70..75bdeb12 100644 --- a/pop/POPAnimation.mm +++ b/pop/POPAnimation.mm @@ -7,22 +7,24 @@ of patent rights can be found in the PATENTS file in the same directory. */ +#import "POPAnimationExtras.h" #import "POPAnimationInternal.h" -#import "POPAnimationTracerInternal.h" #import -#include -#import "POPAnimationExtras.h" +#import "POPAction.h" #import "POPAnimationRuntime.h" +#import "POPAnimationTracerInternal.h" #import "POPAnimatorPrivate.h" -#import "POPAction.h" using namespace POP; #pragma mark - POPAnimation @implementation POPAnimation +@synthesize solver = _solver; +@synthesize currentValue = _currentValue; +@synthesize progressMarkers = _progressMarkers; #pragma mark - Lifecycle @@ -76,11 +78,54 @@ - (void)setPaused:(BOOL)paused _state->setPaused(paused ? true : false); } +- (NSInteger)repeatCount +{ + if (_state->autoreverses) { + return _state->repeatCount / 2; + } else { + return _state->repeatCount; + } +} + +- (void)setRepeatCount:(NSInteger)repeatCount +{ + if (repeatCount > 0) { + if (repeatCount > NSIntegerMax / 2) { + repeatCount = NSIntegerMax / 2; + } + + if (_state->autoreverses) { + _state->repeatCount = (repeatCount * 2); + } else { + _state->repeatCount = repeatCount; + } + } +} + +- (BOOL)autoreverses +{ + return _state->autoreverses; +} + +- (void)setAutoreverses:(BOOL)autoreverses +{ + _state->autoreverses = autoreverses; + if (autoreverses) { + if (_state->repeatCount == 0) { + [self setRepeatCount:1]; + } + } +} + FB_PROPERTY_GET(POPAnimationState, type, POPAnimationType); +DEFINE_RW_PROPERTY_OBJ_COPY(POPAnimationState, animationDidStartBlock, setAnimationDidStartBlock:, POPAnimationDidStartBlock); +DEFINE_RW_PROPERTY_OBJ_COPY(POPAnimationState, animationDidReachToValueBlock, setAnimationDidReachToValueBlock:, POPAnimationDidReachToValueBlock); DEFINE_RW_PROPERTY_OBJ_COPY(POPAnimationState, completionBlock, setCompletionBlock:, POPAnimationCompletionBlock); +DEFINE_RW_PROPERTY_OBJ_COPY(POPAnimationState, animationDidApplyBlock, setAnimationDidApplyBlock:, POPAnimationDidApplyBlock); DEFINE_RW_PROPERTY_OBJ_COPY(POPAnimationState, name, setName:, NSString*); DEFINE_RW_PROPERTY(POPAnimationState, beginTime, setBeginTime:, CFTimeInterval); DEFINE_RW_FLAG(POPAnimationState, removedOnCompletion, removedOnCompletion, setRemovedOnCompletion:); +DEFINE_RW_FLAG(POPAnimationState, repeatForever, repeatForever, setRepeatForever:); - (id)valueForUndefinedKey:(NSString *)key { @@ -100,11 +145,10 @@ - (void)setValue:(id)value forUndefinedKey:(NSString *)key - (POPAnimationTracer *)tracer { - POPAnimationState *s = POPAnimationGetState(self); - if (!s->tracer) { - s->tracer = [[POPAnimationTracer alloc] initWithAnimation:self]; + if (!_state->tracer) { + _state->tracer = [[POPAnimationTracer alloc] initWithAnimation:self]; } - return s->tracer; + return _state->tracer; } - (NSString *)description @@ -226,3 +270,34 @@ - (id)pop_animationForKey:(NSString *)key } @end + +@implementation POPAnimation (NSCopying) + +- (instancetype)copyWithZone:(NSZone *)zone +{ + /* + * Must use [self class] instead of POPAnimation so that subclasses can call this via super. + * Even though POPAnimation and POPPropertyAnimation throw exceptions on init, + * it's safe to call it since you can only copy objects that have been successfully created. + */ + POPAnimation *copy = [[[self class] allocWithZone:zone] init]; + + if (copy) { + copy.name = self.name; + copy.beginTime = self.beginTime; + copy.delegate = self.delegate; + copy.animationDidStartBlock = self.animationDidStartBlock; + copy.animationDidReachToValueBlock = self.animationDidReachToValueBlock; + copy.completionBlock = self.completionBlock; + copy.animationDidApplyBlock = self.animationDidApplyBlock; + copy.removedOnCompletion = self.removedOnCompletion; + + copy.autoreverses = self.autoreverses; + copy.repeatCount = self.repeatCount; + copy.repeatForever = self.repeatForever; + } + + return copy; +} + +@end \ No newline at end of file diff --git a/pop/POPAnimationEvent.h b/pop/POPAnimationEvent.h index cd1414f6..e761091f 100644 --- a/pop/POPAnimationEvent.h +++ b/pop/POPAnimationEvent.h @@ -26,6 +26,7 @@ typedef NS_ENUM(NSUInteger, POPAnimationEventType) { kPOPAnimationEventDidStart, kPOPAnimationEventDidStop, kPOPAnimationEventDidReachToValue, + kPOPAnimationEventAutoreversed }; /** diff --git a/pop/POPAnimationEvent.mm b/pop/POPAnimationEvent.mm index 3456e566..d3a13b69 100644 --- a/pop/POPAnimationEvent.mm +++ b/pop/POPAnimationEvent.mm @@ -39,12 +39,17 @@ return @"didStop"; case kPOPAnimationEventDidReachToValue: return @"didReachToValue"; + case kPOPAnimationEventAutoreversed: + return @"autoreversed"; default: return nil; } } @implementation POPAnimationEvent +@synthesize type = _type; +@synthesize time = _time; +@synthesize animationDescription = _animationDescription; - (instancetype)initWithType:(POPAnimationEventType)aType time:(CFTimeInterval)aTime { @@ -75,6 +80,8 @@ - (void)_appendDescription:(NSMutableString *)s @end @implementation POPAnimationValueEvent +@synthesize value = _value; +@synthesize velocity = _velocity; - (instancetype)initWithType:(POPAnimationEventType)aType time:(CFTimeInterval)aTime value:(id)aValue { diff --git a/pop/POPAnimationExtras.h b/pop/POPAnimationExtras.h index 6c06800a..a4c83488 100644 --- a/pop/POPAnimationExtras.h +++ b/pop/POPAnimationExtras.h @@ -9,14 +9,14 @@ #import -#import -#import +#import +#import /** @abstract The current drag coefficient. @discussion A value greater than 1.0 indicates Simulator slow-motion animations are enabled. Defaults to 1.0. */ -extern CGFloat POPAnimationDragCoefficient(); +extern CGFloat POPAnimationDragCoefficient(void); @interface CAAnimation (POPAnimationExtras) diff --git a/pop/POPAnimationExtras.mm b/pop/POPAnimationExtras.mm index d7abbfe6..d705815b 100644 --- a/pop/POPAnimationExtras.mm +++ b/pop/POPAnimationExtras.mm @@ -8,18 +8,18 @@ */ #import "POPAnimationExtras.h" - #import "POPAnimationPrivate.h" -#import "POPMath.h" #if TARGET_OS_IPHONE #import #endif #if TARGET_IPHONE_SIMULATOR -UIKIT_EXTERN CGFloat UIAnimationDragCoefficient(); // UIKit private drag coeffient, use judiciously +UIKIT_EXTERN float UIAnimationDragCoefficient(); // UIKit private drag coefficient, use judiciously #endif +#import "POPMath.h" + CGFloat POPAnimationDragCoefficient() { #if TARGET_IPHONE_SIMULATOR @@ -52,13 +52,13 @@ @implementation POPSpringAnimation (POPAnimationExtras) + (void)convertBounciness:(CGFloat)bounciness speed:(CGFloat)speed toTension:(CGFloat *)outTension friction:(CGFloat *)outFriction mass:(CGFloat *)outMass { - double b = normalize(bounciness / POPBouncy3NormalizationScale, 0, POPBouncy3NormalizationRange); - b = project_normal(b, POPBouncy3BouncinessNormalizedMin, POPBouncy3BouncinessNormalizedMax); + double b = POPNormalize(bounciness / POPBouncy3NormalizationScale, 0, POPBouncy3NormalizationRange); + b = POPProjectNormal(b, POPBouncy3BouncinessNormalizedMin, POPBouncy3BouncinessNormalizedMax); - double s = normalize(speed / POPBouncy3NormalizationScale, 0, POPBouncy3NormalizationRange); + double s = POPNormalize(speed / POPBouncy3NormalizationScale, 0, POPBouncy3NormalizationRange); - CGFloat tension = project_normal(s, POPBouncy3SpeedNormalizedMin, POPBouncy3SpeedNormalizedMax); - CGFloat friction = quadratic_out_interpolation(b, b3_nobounce(tension), POPBouncy3FrictionInterpolationMax); + CGFloat tension = POPProjectNormal(s, POPBouncy3SpeedNormalizedMin, POPBouncy3SpeedNormalizedMax); + CGFloat friction = POPQuadraticOutInterpolation(b, POPBouncy3NoBounce(tension), POPBouncy3FrictionInterpolationMax); tension = POP_ANIMATION_TENSION_FOR_QC_TENSION(tension); friction = POP_ANIMATION_FRICTION_FOR_QC_FRICTION(friction); @@ -83,13 +83,13 @@ + (void)convertTension:(CGFloat)tension friction:(CGFloat)friction toBounciness: CGFloat qcTension = QC_TENSION_FOR_POP_ANIMATION_TENSION(tension); // Friction is a function of bounciness and tension, according to the following: - // friction = quadratic_out_interpolation(b, b3_nobounce(tension), POPBouncy3FrictionInterpolationMax); + // friction = POPQuadraticOutInterpolation(b, POPBouncy3NoBounce(tension), POPBouncy3FrictionInterpolationMax); // Solve for bounciness, given a tension and friction. - CGFloat nobounceTension = b3_nobounce(qcTension); + CGFloat nobounceTension = POPBouncy3NoBounce(qcTension); CGFloat bounciness1, bounciness2; - quadratic_solve((nobounceTension - POPBouncy3FrictionInterpolationMax), // a + POPQuadraticSolve((nobounceTension - POPBouncy3FrictionInterpolationMax), // a 2 * (POPBouncy3FrictionInterpolationMax - nobounceTension), // b (nobounceTension - qcFriction), // c bounciness1, // x1 diff --git a/pop/POPAnimationInternal.h b/pop/POPAnimationInternal.h index 777d441e..cb8bf6c7 100644 --- a/pop/POPAnimationInternal.h +++ b/pop/POPAnimationInternal.h @@ -1,22 +1,21 @@ /** Copyright (c) 2014-present, Facebook, Inc. All rights reserved. - + This source code is licensed under the BSD-style license found in the LICENSE file in the root directory of this source tree. An additional grant of patent rights can be found in the PATENTS file in the same directory. */ +#import "POPAnimation.h" + #import -#import "POPAnimation.h" +#import "POPAction.h" #import "POPAnimationRuntime.h" -#import "POPAnimationTracer.h" #import "POPAnimationTracerInternal.h" -#import "POPSpringSolver.h" -#import "POPVector.h" -#import "POPAction.h" #import "POPMath.h" +#import "POPSpringSolver.h" using namespace POP; @@ -37,7 +36,10 @@ typedef struct bool reached; } POPProgressMarker; +typedef void (^POPAnimationDidStartBlock)(POPAnimation *anim); +typedef void (^POPAnimationDidReachToValueBlock)(POPAnimation *anim); typedef void (^POPAnimationCompletionBlock)(POPAnimation *anim, BOOL finished); +typedef void (^POPAnimationDidApplyBlock)(POPAnimation *anim); @interface POPAnimation() - (instancetype)_init; @@ -115,7 +117,7 @@ struct ComputeProgressFunctor { CGFloat s = (value - start).squaredNorm(); // distance from start CGFloat e = (value - end).squaredNorm(); // distance from end CGFloat d = (end - start).squaredNorm(); // distance from start to end - + if (0 == d) { return 1; } else if (s > e) { @@ -202,27 +204,33 @@ struct _POPAnimationState CFTimeInterval startTime; CFTimeInterval lastTime; id __weak delegate; + POPAnimationDidStartBlock animationDidStartBlock; + POPAnimationDidReachToValueBlock animationDidReachToValueBlock; POPAnimationCompletionBlock completionBlock; + POPAnimationDidApplyBlock animationDidApplyBlock; NSMutableDictionary *dict; POPAnimationTracer *tracer; CGFloat progress; - + NSInteger repeatCount; + bool active:1; bool paused:1; bool removedOnCompletion:1; - + bool delegateDidStart:1; bool delegateDidStop:1; bool delegateDidProgress:1; bool delegateDidApply:1; bool delegateDidReachToValue:1; - + bool additive:1; bool didReachToValue:1; bool tracing:1; // corresponds to tracer started bool userSpecifiedDynamics:1; + bool autoreverses:1; + bool repeatForever:1; bool customFinished:1; - + _POPAnimationState(id __unsafe_unretained anim) : self(anim), type((POPAnimationType)0), @@ -232,10 +240,14 @@ struct _POPAnimationState startTime(0), lastTime(0), delegate(nil), + animationDidStartBlock(nil), + animationDidReachToValueBlock(nil), completionBlock(nil), + animationDidApplyBlock(nil), dict(nil), tracer(nil), progress(0), + repeatCount(0), active(false), paused(true), removedOnCompletion(true), @@ -248,20 +260,25 @@ struct _POPAnimationState didReachToValue(false), tracing(false), userSpecifiedDynamics(false), + autoreverses(false), + repeatForever(false), customFinished(false) {} - + virtual ~_POPAnimationState() { name = nil; dict = nil; tracer = nil; + animationDidStartBlock = NULL; + animationDidReachToValueBlock = NULL; completionBlock = NULL; + animationDidApplyBlock = NULL; } - + bool isCustom() { return kPOPAnimationCustom == type; } - + bool isStarted() { return 0 != startTime; } @@ -269,7 +286,7 @@ struct _POPAnimationState id getDelegate() { return delegate; } - + void setDelegate(id d) { if (d != delegate) { delegate = d; @@ -284,7 +301,7 @@ struct _POPAnimationState bool getPaused() { return paused; } - + void setPaused(bool f) { if (f != paused) { paused = f; @@ -293,28 +310,23 @@ struct _POPAnimationState } } } - + CGFloat getProgress() { return progress; } - + /* returns true if started */ bool startIfNeeded(id obj, CFTimeInterval time, CFTimeInterval offset) { bool started = false; - + // detect start based on time if (0 == startTime && time >= beginTime + offset) { - + // activate & unpause active = true; setPaused(false); - - // start us one frame in the past (when we added the animation) - if (0 == beginTime) { - time -= 1/60.; - } - + // note start time startTime = lastTime = time; started = true; @@ -341,14 +353,14 @@ struct _POPAnimationState if (done) { delegateProgress(); } - + if (removing) { active = false; } - + handleDidStop(done); } else { - + // stopped before even started // delegate start and stop regardless; matches CA behavior if (!isStarted()) { @@ -356,36 +368,42 @@ struct _POPAnimationState handleDidStop(false); } } - + setPaused(true); } - + virtual void handleDidStart() { if (delegateDidStart) { ActionEnabler enabler; [delegate pop_animationDidStart:self]; } - + + POPAnimationDidStartBlock block = animationDidStartBlock; + if (block != NULL) { + ActionEnabler enabler; + block(self); + } + if (tracing) { [tracer didStart]; } } - + void handleDidStop(BOOL done) { if (delegateDidStop) { ActionEnabler enabler; [delegate pop_animationDidStop:self finished:done]; } - + // add another strong reference to completion block before callout POPAnimationCompletionBlock block = completionBlock; if (block != NULL) { ActionEnabler enabler; block(self, done); } - + if (tracing) { [tracer didStop:done]; } @@ -396,18 +414,15 @@ struct _POPAnimationState if (isCustom()) { return customFinished; } - + return false; } - + bool advanceTime(CFTimeInterval time, id obj) { bool advanced = false; bool computedProgress = false; - CFTimeInterval dt = time - lastTime; - if (dt < 0.001) - return advanced; - + switch (type) { case kPOPAnimationSpring: advanced = advance(time, dt, obj); @@ -428,24 +443,24 @@ struct _POPAnimationState default: break; } - + if (advanced) { - + // estimate progress if (!computedProgress) { computeProgress(); } - + // delegate progress delegateProgress(); - + // update time lastTime = time; } - + return advanced; } - + virtual void willRun(bool started, id obj) {} virtual bool advance(CFTimeInterval time, CFTimeInterval dt, id obj) { return false; } virtual void computeProgress() {} @@ -456,8 +471,14 @@ struct _POPAnimationState ActionEnabler enabler; [delegate pop_animationDidApply:self]; } + + POPAnimationDidApplyBlock block = animationDidApplyBlock; + if (block != NULL) { + ActionEnabler enabler; + block(self); + } } - + virtual void reset(bool all) { startTime = 0; lastTime = 0; @@ -475,7 +496,7 @@ typedef struct _POPAnimationState POPAnimationState; @end -// NSProxy extensions, for testing pursposes +// NSProxy extensions, for testing purposes @interface NSProxy (POP) - (void)pop_addAnimation:(POPAnimation *)anim forKey:(NSString *)key; - (void)pop_removeAllAnimations; diff --git a/pop/POPAnimationPrivate.h b/pop/POPAnimationPrivate.h index 0b7189f0..c0f06c52 100644 --- a/pop/POPAnimationPrivate.h +++ b/pop/POPAnimationPrivate.h @@ -7,7 +7,7 @@ of patent rights can be found in the PATENTS file in the same directory. */ -#import +#import #define POP_ANIMATION_FRICTION_FOR_QC_FRICTION(qcFriction) (25.0 + (((qcFriction - 8.0) / 2.0) * (25.0 - 19.0))) #define POP_ANIMATION_TENSION_FOR_QC_TENSION(qcTension) (194.0 + (((qcTension - 30.0) / 50.0) * (375.0 - 194.0))) diff --git a/pop/POPAnimationRuntime.h b/pop/POPAnimationRuntime.h index bc02e9b5..1b99bddb 100644 --- a/pop/POPAnimationRuntime.h +++ b/pop/POPAnimationRuntime.h @@ -8,11 +8,11 @@ */ #import -#include +#import #import -#import "POPMath.h" +#import "POPAnimatablePropertyTypes.h" #import "POPVector.h" enum POPValueType @@ -23,10 +23,13 @@ enum POPValueType kPOPValuePoint, kPOPValueSize, kPOPValueRect, + kPOPValueEdgeInsets, kPOPValueAffineTransform, kPOPValueTransform, kPOPValueRange, kPOPValueColor, + kPOPValueSCNVector3, + kPOPValueSCNVector4, }; using namespace POP; @@ -44,12 +47,12 @@ extern POPValueType POPSelectValueType(id obj, const POPValueType *types, size_t /** Array of all value types. */ -extern const POPValueType kPOPAnimatableAllTypes[9]; +extern const POPValueType kPOPAnimatableAllTypes[12]; /** Array of all value types supported for animation. */ -extern const POPValueType kPOPAnimatableSupportTypes[7]; +extern const POPValueType kPOPAnimatableSupportTypes[10]; /** Returns a string description of a value type. @@ -76,16 +79,10 @@ extern id POPBox(VectorConstRef vec, POPValueType type, bool force = false); */ extern VectorRef POPUnbox(id value, POPValueType &type, NSUInteger &count, bool validate); -/** - Read/write block typedefs for convenience. - */ -typedef void(^pop_animatable_read_block)(id obj, CGFloat *value); -typedef void(^pop_animatable_write_block)(id obj, const CGFloat *value); - /** Read object value and return a Vector4r. */ -NS_INLINE Vector4r read_values(pop_animatable_read_block read, id obj, size_t count) +NS_INLINE Vector4r read_values(POPAnimatablePropertyReadBlock read, id obj, size_t count) { Vector4r vec = Vector4r::Zero(); if (0 == count) diff --git a/pop/POPAnimationRuntime.mm b/pop/POPAnimationRuntime.mm index eb3b5689..371e0093 100644 --- a/pop/POPAnimationRuntime.mm +++ b/pop/POPAnimationRuntime.mm @@ -14,14 +14,13 @@ #import #if TARGET_OS_IPHONE -#import -#else -#import +#import #endif -#import "POPVector.h" -#import "POPAnimationRuntime.h" +#import "POPCGUtils.h" +#import "POPDefines.h" #import "POPGeometry.h" +#import "POPVector.h" static Boolean pointerEqual(const void *ptr1, const void *ptr2) { return ptr1 == ptr2; @@ -37,7 +36,7 @@ CFMutableDictionaryRef POPDictionaryCreateMutableWeakPointerToWeakPointer(NSUInt // weak, pointer keys kcb.retain = NULL; - kcb.retain = NULL; + kcb.release = NULL; kcb.equal = pointerEqual; kcb.hash = pointerHash; @@ -96,7 +95,13 @@ static bool FBCompareTypeEncoding(const char *objctype, POPValueType type) || strcmp(objctype, @encode(NSRect)) == 0 #endif ); - + case kPOPValueEdgeInsets: +#if TARGET_OS_IPHONE + return strcmp(objctype, @encode(UIEdgeInsets)) == 0; +#else + return false; +#endif + case kPOPValueAffineTransform: return strcmp(objctype, @encode(CGAffineTransform)) == 0; @@ -117,6 +122,21 @@ static bool FBCompareTypeEncoding(const char *objctype, POPValueType type) || strcmp(objctype, @encode(long long)) == 0 || strcmp(objctype, @encode(unsigned long long)) == 0 ); + + case kPOPValueSCNVector3: +#if SCENEKIT_SDK_AVAILABLE + return strcmp(objctype, @encode(SCNVector3)) == 0; +#else + return false; +#endif + + case kPOPValueSCNVector4: +#if SCENEKIT_SDK_AVAILABLE + return strcmp(objctype, @encode(SCNVector4)) == 0; +#else + return false; +#endif + default: return false; } @@ -137,15 +157,15 @@ POPValueType POPSelectValueType(id obj, const POPValueType *types, size_t length { if ([obj isKindOfClass:[NSValue class]]) { return POPSelectValueType([obj objCType], types, length); - } else if (CFGetTypeID((__bridge CFTypeRef)obj) == CGColorGetTypeID()) { + } else if (NULL != POPCGColorWithColor(obj)) { return kPOPValueColor; } return kPOPValueUnknown; } -const POPValueType kPOPAnimatableAllTypes[9] = {kPOPValueInteger, kPOPValueFloat, kPOPValuePoint, kPOPValueSize, kPOPValueRect, kPOPValueAffineTransform, kPOPValueTransform, kPOPValueRange, kPOPValueColor}; +const POPValueType kPOPAnimatableAllTypes[12] = {kPOPValueInteger, kPOPValueFloat, kPOPValuePoint, kPOPValueSize, kPOPValueRect, kPOPValueEdgeInsets, kPOPValueAffineTransform, kPOPValueTransform, kPOPValueRange, kPOPValueColor, kPOPValueSCNVector3, kPOPValueSCNVector4}; -const POPValueType kPOPAnimatableSupportTypes[7] = {kPOPValueInteger, kPOPValueFloat, kPOPValuePoint, kPOPValueSize, kPOPValueRect, kPOPValueColor}; +const POPValueType kPOPAnimatableSupportTypes[10] = {kPOPValueInteger, kPOPValueFloat, kPOPValuePoint, kPOPValueSize, kPOPValueRect, kPOPValueEdgeInsets, kPOPValueColor, kPOPValueSCNVector3, kPOPValueSCNVector4}; NSString *POPValueTypeToString(POPValueType t) { @@ -162,6 +182,8 @@ POPValueType POPSelectValueType(id obj, const POPValueType *types, size_t length return @"CGSize"; case kPOPValueRect: return @"CGRect"; + case kPOPValueEdgeInsets: + return @"UIEdgeInsets"; case kPOPValueAffineTransform: return @"CGAffineTransform"; case kPOPValueTransform: @@ -170,6 +192,10 @@ POPValueType POPSelectValueType(id obj, const POPValueType *types, size_t length return @"CFRange"; case kPOPValueColor: return @"CGColorRef"; + case kPOPValueSCNVector3: + return @"SCNVector3"; + case kPOPValueSCNVector4: + return @"SCNVector4"; default: return nil; } @@ -194,10 +220,25 @@ id POPBox(VectorConstRef vec, POPValueType type, bool force) case kPOPValueRect: return [NSValue valueWithCGRect:vec->cg_rect()]; break; +#if TARGET_OS_IPHONE + case kPOPValueEdgeInsets: + return [NSValue valueWithUIEdgeInsets:vec->ui_edge_insets()]; + break; +#endif case kPOPValueColor: { return (__bridge_transfer id)vec->cg_color(); break; } +#if SCENEKIT_SDK_AVAILABLE + case kPOPValueSCNVector3: { + return [NSValue valueWithSCNVector3:vec->scn_vector3()]; + break; + } + case kPOPValueSCNVector4: { + return [NSValue valueWithSCNVector4:vec->scn_vector4()]; + break; + } +#endif default: return force ? [NSValue valueWithCGPoint:vec->cg_point()] : nil; break; @@ -211,7 +252,11 @@ static VectorRef vectorize(id value, POPValueType type) switch (type) { case kPOPValueInteger: case kPOPValueFloat: +#if CGFLOAT_IS_DOUBLE + vec = Vector::new_cg_float([value doubleValue]); +#else vec = Vector::new_cg_float([value floatValue]); +#endif break; case kPOPValuePoint: vec = Vector::new_cg_point([value CGPointValue]); @@ -222,11 +267,25 @@ static VectorRef vectorize(id value, POPValueType type) case kPOPValueRect: vec = Vector::new_cg_rect([value CGRectValue]); break; +#if TARGET_OS_IPHONE + case kPOPValueEdgeInsets: + vec = Vector::new_ui_edge_insets([value UIEdgeInsetsValue]); + break; +#endif case kPOPValueAffineTransform: vec = Vector::new_cg_affine_transform([value CGAffineTransformValue]); break; case kPOPValueColor: - vec = Vector::new_cg_color((__bridge CGColorRef)value); + vec = Vector::new_cg_color(POPCGColorWithColor(value)); + break; +#if SCENEKIT_SDK_AVAILABLE + case kPOPValueSCNVector3: + vec = Vector::new_scn_vector3([value SCNVector3Value]); + break; + case kPOPValueSCNVector4: + vec = Vector::new_scn_vector4([value SCNVector4Value]); + break; +#endif default: break; } @@ -246,7 +305,7 @@ VectorRef POPUnbox(id value, POPValueType &animationType, NSUInteger &count, boo // handle unknown types if (kPOPValueUnknown == valueType) { - NSString *valueDesc = kPOPValueUnknown != valueType ? POPValueTypeToString(valueType) : [[value class] description]; + NSString *valueDesc = [[value class] description]; [NSException raise:@"Unsuported value" format:@"Animating %@ values is not supported", valueDesc]; } diff --git a/pop/POPAnimationTracer.h b/pop/POPAnimationTracer.h index 53a6a03d..1de56615 100644 --- a/pop/POPAnimationTracer.h +++ b/pop/POPAnimationTracer.h @@ -9,12 +9,12 @@ #import -#import +#import @class POPAnimation; /** - @abstract Tracer of animation events to fasciliate unit testing & debugging. + @abstract Tracer of animation events to facilitate unit testing & debugging. */ @interface POPAnimationTracer : NSObject @@ -35,20 +35,20 @@ /** @abstract Property representing all recorded events. - @discussion Events are returned in order of occurence. + @discussion Events are returned in order of occurrence. */ @property (nonatomic, assign, readonly) NSArray *allEvents; /** @abstract Property representing all recorded write events for convenience. - @discussion Events are returned in order of occurence. + @discussion Events are returned in order of occurrence. */ @property (nonatomic, assign, readonly) NSArray *writeEvents; /** @abstract Queries for events of specified type. @param type The type of event to return. - @returns An array of events of specified type in order of occurence. + @returns An array of events of specified type in order of occurrence. */ - (NSArray *)eventsWithType:(POPAnimationEventType)type; diff --git a/pop/POPAnimationTracer.mm b/pop/POPAnimationTracer.mm index e2ebfb47..73065246 100644 --- a/pop/POPAnimationTracer.mm +++ b/pop/POPAnimationTracer.mm @@ -22,6 +22,7 @@ @implementation POPAnimationTracer NSMutableArray *_events; BOOL _animationHasVelocity; } +@synthesize shouldLogAndResetOnCompletion = _shouldLogAndResetOnCompletion; static POPAnimationEvent *create_event(POPAnimationTracer *self, POPAnimationEventType type, id value = nil, bool recordAnimation = false) { @@ -31,18 +32,19 @@ @implementation POPAnimationTracer : self->_animationState->lastTime; POPAnimationEvent *event; + __strong POPAnimation* animation = self->_animation; if (!value) { event = [[POPAnimationEvent alloc] initWithType:type time:time]; } else { event = [[POPAnimationValueEvent alloc] initWithType:type time:time value:value]; if (self->_animationHasVelocity) { - [(POPAnimationValueEvent *)event setVelocity:[(POPSpringAnimation *)self->_animation velocity]]; + [(POPAnimationValueEvent *)event setVelocity:[(POPSpringAnimation *)animation velocity]]; } } if (recordAnimation) { - event.animationDescription = [self->_animation description]; + event.animationDescription = [animation description]; } return event; @@ -143,6 +145,12 @@ - (void)didReachToValue:(id)aValue [_events addObject:event]; } +- (void)autoreversed +{ + POPAnimationEvent *event = create_event(self, kPOPAnimationEventAutoreversed); + [_events addObject:event]; +} + - (void)start { POPAnimationState *s = POPAnimationGetState(_animation); diff --git a/pop/POPAnimationTracerInternal.h b/pop/POPAnimationTracerInternal.h index 748b9954..27b7cde3 100644 --- a/pop/POPAnimationTracerInternal.h +++ b/pop/POPAnimationTracerInternal.h @@ -9,12 +9,12 @@ #import -#import +#import @interface POPAnimationTracer (Internal) /** - @abstract Designated initalizer. Pass the animation being traced. + @abstract Designated initializer. Pass the animation being traced. */ - (instancetype)initWithAnimation:(POPAnimation *)anAnim; @@ -88,4 +88,9 @@ */ - (void)didReachToValue:(id)aValue; +/** + @abstract Records when an autoreverse animation takes place. + */ +- (void)autoreversed; + @end diff --git a/pop/POPAnimator.h b/pop/POPAnimator.h index 7d71d248..2c568579 100644 --- a/pop/POPAnimator.h +++ b/pop/POPAnimator.h @@ -7,7 +7,7 @@ of patent rights can be found in the PATENTS file in the same directory. */ -#import +#import @protocol POPAnimatorDelegate; @@ -22,11 +22,23 @@ */ + (instancetype)sharedAnimator; +#if !TARGET_OS_IPHONE +/** + @abstract Allows to select display to bind. Returns nil if failed to create the display link. + */ +- (instancetype)initWithDisplayID:(CGDirectDisplayID)displayID; +#endif + /** @abstract The optional animator delegate. */ @property (weak, nonatomic) id delegate; +/** + @abstract Retrieves the nominal refresh period of a display link. Returns zero if unavailable. + */ +@property (readonly, nonatomic) CFTimeInterval refreshPeriod; + @end /** diff --git a/pop/POPAnimator.mm b/pop/POPAnimator.mm index 1eab8a57..c3e988df 100644 --- a/pop/POPAnimator.mm +++ b/pop/POPAnimator.mm @@ -11,19 +11,20 @@ #import "POPAnimatorPrivate.h" #import -#import #import +#if !TARGET_OS_IPHONE +#import +#endif + +#import + #import #import "POPAnimation.h" #import "POPAnimationExtras.h" -#import "POPAnimationInternal.h" -#import "POPAnimationRuntime.h" #import "POPBasicAnimationInternal.h" -#import "POPDecayAnimationInternal.h" -#import "POPSpringAnimationInternal.h" -#import "POPSpringSolver.h" +#import "POPDecayAnimation.h" using namespace std; using namespace POP; @@ -43,6 +44,10 @@ #define FBLogAnimInfo(...) #endif +#if !TARGET_OS_IPHONE +static const uint64_t kDisplayTimerFrequency = 60ull; // Hz +#endif + class POPAnimatorItem { public: @@ -78,7 +83,10 @@ typedef POPAnimatorItemList::iterator POPAnimatorItemListIterator; typedef POPAnimatorItemList::const_iterator POPAnimatorItemListConstIterator; +#if !TARGET_OS_IPHONE static BOOL _disableBackgroundThread = YES; +static uint64_t _displayTimerFrequency = kDisplayTimerFrequency; +#endif @interface POPAnimator () { @@ -86,25 +94,42 @@ @interface POPAnimator () CADisplayLink *_displayLink; #else CVDisplayLinkRef _displayLink; + dispatch_source_t _displayTimer; + BOOL _displayTimerRunning; + int32_t _enqueuedRender; #endif POPAnimatorItemList _list; CFMutableDictionaryRef _dict; - NSMutableSet *_observers; + NSMutableArray *_observers; + POPAnimatorItemList _pendingList; + CFRunLoopObserverRef _pendingListObserver; CFTimeInterval _slowMotionStartTime; CFTimeInterval _slowMotionLastTime; CFTimeInterval _slowMotionAccumulator; + CFTimeInterval _beginTime; + pthread_mutex_t _lock; + BOOL _disableDisplayLink; } @end @implementation POPAnimator +@synthesize delegate = _delegate; +@synthesize disableDisplayLink = _disableDisplayLink; +@synthesize beginTime = _beginTime; #if !TARGET_OS_IPHONE static CVReturn displayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeStamp *now, const CVTimeStamp *outputTime, CVOptionFlags flagsIn, CVOptionFlags *flagsOut, void *context) { if (_disableBackgroundThread) { + __unsafe_unretained POPAnimator *pa = (__bridge POPAnimator *)context; + int32_t* enqueuedRender = &pa->_enqueuedRender; + if (*enqueuedRender == 0) { + OSAtomicIncrement32(enqueuedRender); dispatch_async(dispatch_get_main_queue(), ^{ [(__bridge POPAnimator*)context render]; + OSAtomicDecrement32(enqueuedRender); }); + } } else { [(__bridge POPAnimator*)context render]; } @@ -112,9 +137,10 @@ static CVReturn displayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeSt } #endif -static void updateAnimating(POPAnimator *self) +// call while holding lock +static void updateDisplayLink(POPAnimator *self) { - BOOL paused = 0 == self->_observers.count && self->_list.empty(); + BOOL paused = (0 == self->_observers.count && self->_list.empty()) || self->_disableDisplayLink; #if TARGET_OS_IPHONE if (paused != self->_displayLink.paused) { @@ -122,32 +148,60 @@ static void updateAnimating(POPAnimator *self) self->_displayLink.paused = paused; } #else - if (paused == CVDisplayLinkIsRunning(self->_displayLink)) { - FBLogAnimInfo(paused ? @"pausing display link" : @"unpausing display link"); - if (paused) { - CVDisplayLinkStop(self->_displayLink); - } else { - CVDisplayLinkStart(self->_displayLink); + if (NULL != self->_displayLink) { + if (paused == CVDisplayLinkIsRunning(self->_displayLink)) { + FBLogAnimInfo(paused ? @"pausing display link" : @"unpausing display link"); + if (paused) { + CVDisplayLinkStop(self->_displayLink); + } else { + CVDisplayLinkStart(self->_displayLink); + } + } + } else { + if (paused == self->_displayTimerRunning) { + FBLogAnimInfo(paused ? @"pausing display timer" : @"unpausing display timer"); + if (paused) { + self->_displayTimerRunning = NO; + dispatch_suspend(self->_displayTimer); + } else { + self->_displayTimerRunning = YES; + dispatch_resume(self->_displayTimer); + } } } #endif } -static void updateAnimatable(id obj, POPPropertyAnimationState *anim) +static void updateAnimatable(id obj, POPPropertyAnimationState *anim, bool shouldAvoidExtraneousWrite = false) { - // handle user-initiated stop or pause; hault animation + // handle user-initiated stop or pause; halt animation if (!anim->active || anim->paused) return; if (anim->hasValue()) { - pop_animatable_write_block write = anim->property.writeBlock; + POPAnimatablePropertyWriteBlock write = anim->property.writeBlock; if (NULL == write) return; - + + // current animation value + VectorRef currentVec = anim->currentValue(); + if (!anim->additive) { - - VectorRef currentVec = anim->currentValue(); + // if avoiding extraneous writes and we have a read block defined + if (shouldAvoidExtraneousWrite) { + + POPAnimatablePropertyReadBlock read = anim->property.readBlock; + if (read) { + // compare current animation value with object value + Vector4r currentValue = currentVec->vector4r(); + Vector4r objectValue = read_values(read, obj, anim->valueCount); + if (objectValue == currentValue) { + return; + } + } + } + // update previous values; support animation convergence anim->previous2Vec = anim->previousVec; anim->previousVec = currentVec; @@ -158,23 +212,29 @@ static void updateAnimatable(id obj, POPPropertyAnimationState *anim) [anim->tracer writePropertyValue:POPBox(currentVec, anim->valueType, true)]; } } else { - pop_animatable_read_block read = anim->property.readBlock; - if (NULL == read) + POPAnimatablePropertyReadBlock read = anim->property.readBlock; + NSCAssert(read, @"additive requires an animatable property readBlock"); + if (NULL == read) { return; - + } + // object value Vector4r objectValue = read_values(read, obj, anim->valueCount); - // current animation value - VectorRef currentVec = anim->currentValue(); + // current value Vector4r currentValue = currentVec->vector4r(); - + // determine animation change if (anim->previousVec) { Vector4r previousValue = anim->previousVec->vector4r(); currentValue -= previousValue; } + // avoid writing no change + if (shouldAvoidExtraneousWrite && currentValue == Vector4r::Zero()) { + return; + } + // add to object value currentValue += objectValue; @@ -205,15 +265,17 @@ static void applyAnimationTime(id obj, POPAnimationState *state, CFTimeInterval state->delegateApply(); } -static void applyAnimationProgress(id obj, POPAnimationState *state, CGFloat progress) +static void applyAnimationToValue(id obj, POPAnimationState *state) { POPPropertyAnimationState *ps = dynamic_cast(state); - if (ps && !ps->advanceProgress(progress)) { - return; - } if (NULL != ps) { - updateAnimatable(obj, ps); + + // finalize progress + ps->finalizeProgress(); + + // write to value, updating only if needed + updateAnimatable(obj, ps, true); } state->delegateApply(); @@ -221,21 +283,29 @@ static void applyAnimationProgress(id obj, POPAnimationState *state, CGFloat pro static POPAnimation *deleteDictEntry(POPAnimator *self, id __unsafe_unretained obj, NSString *key, BOOL cleanup = YES) { - NSMutableDictionary *animations = (__bridge id)CFDictionaryGetValue(self->_dict, (__bridge void *)obj); - if (nil == animations) - return nil; + POPAnimation *anim = nil; - POPAnimation *anim = animations[key]; - if (nil == anim) - return nil; + // lock + pthread_mutex_lock(&self->_lock); + + NSMutableDictionary *keyAnimationsDict = (__bridge id)CFDictionaryGetValue(self->_dict, (__bridge void *)obj); + if (keyAnimationsDict) { + + anim = keyAnimationsDict[key]; + if (anim) { - // remove key - [animations removeObjectForKey:key]; + // remove key + [keyAnimationsDict removeObjectForKey:key]; - // cleanup empty dictionaries - if (cleanup && 0 == animations.count) - CFDictionaryRemoveValue(self->_dict, (__bridge void *)obj); + // cleanup empty dictionaries + if (cleanup && 0 == keyAnimationsDict.count) { + CFDictionaryRemoveValue(self->_dict, (__bridge void *)obj); + } + } + } + // unlock + pthread_mutex_unlock(&self->_lock); return anim; } @@ -251,7 +321,10 @@ static void stopAndCleanup(POPAnimator *self, POPAnimatorItemRef item, bool shou state->stop(shouldRemove, finished); if (shouldRemove) { - // find item im list + // lock + pthread_mutex_lock(&self->_lock); + + // find item in list // may have already been removed on animationDidStop: POPAnimatorItemListIterator find_iter = find(self->_list.begin(), self->_list.end(), item); BOOL found = find_iter != self->_list.end(); @@ -259,6 +332,9 @@ static void stopAndCleanup(POPAnimator *self, POPAnimatorItemRef item, bool shou if (found) { self->_list.erase(find_iter); } + + // unlock + pthread_mutex_unlock(&self->_lock); } } @@ -272,6 +348,7 @@ + (id)sharedAnimator return _animator; } +#if !TARGET_OS_IPHONE + (BOOL)disableBackgroundThread { return _disableBackgroundThread; @@ -282,7 +359,20 @@ + (void)setDisableBackgroundThread:(BOOL)flag _disableBackgroundThread = flag; } -- (id)init ++ (uint64_t)displayTimerFrequency +{ + return _displayTimerFrequency; +} + ++ (void)setDisplayTimerFrequency:(uint64_t)frequency +{ + _displayTimerFrequency = frequency; +} +#endif + +#pragma mark - Lifecycle + +- (instancetype)init { self = [super init]; if (nil == self) return nil; @@ -293,22 +383,260 @@ - (id)init [_displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes]; #else CVReturn ret = CVDisplayLinkCreateWithActiveCGDisplays(&_displayLink); - ret = CVDisplayLinkSetOutputCallback(_displayLink, displayLinkCallback, (__bridge void *)self); + if (kCVReturnSuccess != ret) { + ret = CVDisplayLinkCreateWithCGDisplay(CGMainDisplayID(), &_displayLink); + } + if (kCVReturnSuccess == ret) { + CVDisplayLinkSetOutputCallback(_displayLink, displayLinkCallback, (__bridge void *)self); + } else { + FBLogAnimInfo(@"cannot create display link: ret=%ld, falling back to display timer at %llu Hz", (long)ret, _displayTimerFrequency); + // Thanks to Apple, on older OSes DISPATCH_TIMER_STRICT is not supported and dispatch_source_create failed if we use it. + unsigned long mask = (NSFoundationVersionNumber >= NSFoundationVersionNumber10_9) ? DISPATCH_TIMER_STRICT : 0; + _displayTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, mask, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0)); + NSAssert(nil != _displayTimer, @"Cannot create display timer"); + dispatch_source_set_timer(_displayTimer, DISPATCH_TIME_NOW, NSEC_PER_SEC / _displayTimerFrequency, 0); + __weak POPAnimator *weakSelf = self; + dispatch_source_set_event_handler(_displayTimer, ^{ + __strong POPAnimator *strongSelf = weakSelf; + if (__builtin_expect(nil != strongSelf, 1)) { + (void) displayLinkCallback(NULL, NULL, NULL, 0, NULL, (__bridge void *)strongSelf); + } + }); + } #endif _dict = POPDictionaryCreateMutableWeakPointerToStrongObject(5); + pthread_mutex_init(&_lock, NULL); + + return self; +} +#if !TARGET_OS_IPHONE +- (instancetype)initWithDisplayID:(CGDirectDisplayID)displayID +{ + if (kCGNullDirectDisplay == displayID) { + return [self init]; + } + + self = [super init]; + if (nil == self) return nil; + + CVReturn ret = CVDisplayLinkCreateWithCGDisplay(displayID, &_displayLink); + if (kCVReturnSuccess != ret) { + return nil; + } + CVDisplayLinkSetOutputCallback(_displayLink, displayLinkCallback, (__bridge void *)self); + + _dict = POPDictionaryCreateMutableWeakPointerToStrongObject(5); + pthread_mutex_init(&_lock, NULL); + return self; } +#endif - (void)dealloc { #if TARGET_OS_IPHONE [_displayLink invalidate]; #else - CVDisplayLinkStop(_displayLink); - CVDisplayLinkRelease(_displayLink); + if (_displayLink != NULL) { + CVDisplayLinkStop(_displayLink); + CVDisplayLinkRelease(_displayLink); + } + if (_displayTimer != NULL) { + dispatch_source_cancel(_displayTimer); +#if !OS_OBJECT_USE_OBJC + dispatch_release(_displayTimer); #endif + _displayTimer = NULL; + } +#endif + [self _clearPendingListObserver]; + + pthread_mutex_destroy(&_lock); +} + +#pragma mark - Utility + +- (void)_processPendingList +{ + // rendering pending animations + CFTimeInterval time = [self _currentRenderTime]; + [self _renderTime:(0 != _beginTime) ? _beginTime : time items:_pendingList]; + + // lock + pthread_mutex_lock(&_lock); + + // clear list and observer + _pendingList.clear(); + [self _clearPendingListObserver]; + + // unlock + pthread_mutex_unlock(&_lock); +} + +- (void)_clearPendingListObserver +{ + if (_pendingListObserver) { + CFRunLoopRemoveObserver(CFRunLoopGetMain(), _pendingListObserver, kCFRunLoopCommonModes); + CFRelease(_pendingListObserver); + _pendingListObserver = NULL; + } +} + +- (void)_scheduleProcessPendingList +{ + // see WebKit for magic numbers, eg http://trac.webkit.org/changeset/166540 + static const CFIndex CATransactionCommitRunLoopOrder = 2000000; + static const CFIndex POPAnimationApplyRunLoopOrder = CATransactionCommitRunLoopOrder - 1; + + // lock + pthread_mutex_lock(&_lock); + + if (!_pendingListObserver) { + __weak POPAnimator *weakSelf = self; + + _pendingListObserver = CFRunLoopObserverCreateWithHandler(kCFAllocatorDefault, kCFRunLoopBeforeWaiting | kCFRunLoopExit, false, POPAnimationApplyRunLoopOrder, ^(CFRunLoopObserverRef observer, CFRunLoopActivity activity) { + [weakSelf _processPendingList]; + }); + + if (_pendingListObserver) { + CFRunLoopAddObserver(CFRunLoopGetMain(), _pendingListObserver, kCFRunLoopCommonModes); + } + } + + // unlock + pthread_mutex_unlock(&_lock); +} + +- (void)_renderTime:(CFTimeInterval)time items:(std::list)items +{ + // begin transaction with actions disabled + [CATransaction begin]; + [CATransaction setDisableActions:YES]; + + // notify delegate + __strong __typeof__(_delegate) delegate = _delegate; + [delegate animatorWillAnimate:self]; + + // lock + pthread_mutex_lock(&_lock); + + // count active animations + const NSUInteger count = items.size(); + if (0 == count) { + // unlock + pthread_mutex_unlock(&_lock); + } else { + // copy list into vector + std::vector vector{ items.begin(), items.end() }; + + // unlock + pthread_mutex_unlock(&_lock); + + for (auto item : vector) { + [self _renderTime:time item:item]; + } + } + + // notify observers + for (id observer in self.observers) { + [observer animatorDidAnimate:(id)self]; + } + + // lock + pthread_mutex_lock(&_lock); + + // update display link + updateDisplayLink(self); + + // unlock + pthread_mutex_unlock(&_lock); + + // notify delegate and commit + [delegate animatorDidAnimate:self]; + [CATransaction commit]; +} + +- (void)_renderTime:(CFTimeInterval)time item:(POPAnimatorItemRef)item +{ + id obj = item->object; + POPAnimation *anim = item->animation; + POPAnimationState *state = POPAnimationGetState(anim); + + if (nil == obj) { + // object exists not; stop animating + NSAssert(item->unretainedObject, @"object should exist"); + stopAndCleanup(self, item, true, false); + } else { + + // start if needed + state->startIfNeeded(obj, time, _slowMotionAccumulator); + + // only run active, not paused animations + if (state->active && !state->paused) { + // object exists; animate + applyAnimationTime(obj, state, time); + + FBLogAnimDebug(@"time:%f running:%@", time, item->animation); + if (state->isDone()) { + // set end value + applyAnimationToValue(obj, state); + + state->repeatCount--; + if (state->repeatForever || state->repeatCount > 0) { + if ([anim isKindOfClass:[POPPropertyAnimation class]]) { + POPPropertyAnimation *propAnim = (POPPropertyAnimation *)anim; + id oldFromValue = propAnim.fromValue; + propAnim.fromValue = propAnim.toValue; + + if (state->autoreverses) { + if (state->tracing) { + [state->tracer autoreversed]; + } + + if (state->type == kPOPAnimationDecay) { + POPDecayAnimation *decayAnimation = (POPDecayAnimation *)propAnim; + decayAnimation.velocity = [decayAnimation reversedVelocity]; + } else { + propAnim.toValue = oldFromValue; + } + } else { + if (state->type == kPOPAnimationDecay) { + POPDecayAnimation *decayAnimation = (POPDecayAnimation *)propAnim; + id originalVelocity = decayAnimation.originalVelocity; + decayAnimation.velocity = originalVelocity; + } else { + propAnim.fromValue = oldFromValue; + } + } + } + + state->stop(NO, NO); + state->reset(true); + + state->startIfNeeded(obj, time, _slowMotionAccumulator); + } else { + stopAndCleanup(self, item, state->removedOnCompletion, YES); + } + } + } + } +} + +#pragma mark - API + +- (NSArray *)observers +{ + // lock + pthread_mutex_lock(&_lock); + + // get observers + NSArray *observers = 0 != _observers.count ? [_observers copy] : nil; + + // unlock + pthread_mutex_unlock(&_lock); + return observers; } - (void)addAnimation:(POPAnimation *)anim forObject:(id)obj key:(NSString *)key @@ -321,61 +649,90 @@ - (void)addAnimation:(POPAnimation *)anim forObject:(id)obj key:(NSString *)key if (!key) { key = [[NSUUID UUID] UUIDString]; } - - NSMutableDictionary *animations = (__bridge id)CFDictionaryGetValue(_dict, (__bridge void *)obj); + + // lock + pthread_mutex_lock(&_lock); + + // get key, animation dict associated with object + NSMutableDictionary *keyAnimationDict = (__bridge id)CFDictionaryGetValue(_dict, (__bridge void *)obj); // update associated animation state - if (nil == animations) { - animations = [NSMutableDictionary dictionary]; - CFDictionarySetValue(_dict, (__bridge void *)obj, (__bridge void *)animations); + if (nil == keyAnimationDict) { + keyAnimationDict = [NSMutableDictionary dictionary]; + CFDictionarySetValue(_dict, (__bridge void *)obj, (__bridge void *)keyAnimationDict); } else { // if the animation instance already exists, avoid cancelling only to restart - POPAnimation *existingAnim = animations[key]; + POPAnimation *existingAnim = keyAnimationDict[key]; if (existingAnim) { + // unlock + pthread_mutex_unlock(&_lock); + if (existingAnim == anim) { return; } [self removeAnimationForObject:obj key:key cleanupDict:NO]; + + // lock + pthread_mutex_lock(&_lock); } } - animations[key] = anim; + keyAnimationDict[key] = anim; // create entry after potential removal POPAnimatorItemRef item(new POPAnimatorItem(obj, key, anim)); + + // add to list and pending list _list.push_back(item); + _pendingList.push_back(item); // support animation re-use, reset all animation state POPAnimationGetState(anim)->reset(true); - // start animating if necessary - updateAnimating(self); + // update display link + updateDisplayLink(self); + + // unlock + pthread_mutex_unlock(&_lock); + + // schedule runloop processing of pending animations + [self _scheduleProcessPendingList]; } - (void)removeAllAnimationsForObject:(id)obj { + // lock + pthread_mutex_lock(&_lock); + NSArray *animations = [(__bridge id)CFDictionaryGetValue(_dict, (__bridge void *)obj) allValues]; CFDictionaryRemoveValue(_dict, (__bridge void *)obj); - if (0 == animations.count) + // unlock + pthread_mutex_unlock(&_lock); + + if (0 == animations.count) { return; + } NSHashTable *animationSet = [[NSHashTable alloc] initWithOptions:NSHashTableObjectPointerPersonality capacity:animations.count]; for (id animation in animations) { [animationSet addObject:animation]; } + // lock + pthread_mutex_lock(&_lock); + POPAnimatorItemRef item; for (auto iter = _list.begin(); iter != _list.end();) { item = *iter; if(![animationSet containsObject:item->animation]) { iter++; } else { - POPAnimationState *state = POPAnimationGetState(item->animation); - state->stop(true, !state->active); iter = _list.erase(iter); } } + // unlock + pthread_mutex_unlock(&_lock); for (POPAnimation *anim in animations) { POPAnimationState *state = POPAnimationGetState(anim); @@ -386,21 +743,42 @@ - (void)removeAllAnimationsForObject:(id)obj - (void)removeAnimationForObject:(id)obj key:(NSString *)key cleanupDict:(BOOL)cleanupDict { POPAnimation *anim = deleteDictEntry(self, obj, key, cleanupDict); - if (nil == anim) + if (nil == anim) { return; + } + // lock + pthread_mutex_lock(&_lock); + + // remove from list POPAnimatorItemRef item; for (auto iter = _list.begin(); iter != _list.end();) { item = *iter; if(anim == item->animation) { - POPAnimationState *state = POPAnimationGetState(item->animation); - state->stop(true, (!state->active && !state->paused)); - iter = _list.erase(iter); + _list.erase(iter); + break; + } else { + iter++; + } + } + + // remove from pending list + for (auto iter = _pendingList.begin(); iter != _pendingList.end();) { + item = *iter; + if(anim == item->animation) { + _pendingList.erase(iter); break; } else { iter++; } } + + // unlock + pthread_mutex_unlock(&_lock); + + // stop animation and callout + POPAnimationState *state = POPAnimationGetState(anim); + state->stop(true, (!state->active && !state->paused)); } - (void)removeAnimationForObject:(id)obj key:(NSString *)key @@ -410,17 +788,48 @@ - (void)removeAnimationForObject:(id)obj key:(NSString *)key - (NSArray *)animationKeysForObject:(id)obj { - NSArray *keys = [(__bridge id)CFDictionaryGetValue(_dict, (__bridge void *)obj) allKeys]; + // lock + pthread_mutex_lock(&_lock); + + // get keys + NSArray *keys = [(__bridge NSDictionary *)CFDictionaryGetValue(_dict, (__bridge void *)obj) allKeys]; + + // unlock + pthread_mutex_unlock(&_lock); return keys; } - (id)animationForObject:(id)obj key:(NSString *)key { - NSDictionary *animations = (__bridge id)CFDictionaryGetValue(_dict, (__bridge void *)obj); - return animations[key]; + // lock + pthread_mutex_lock(&_lock); + + // lookup animation + NSDictionary *keyAnimationsDict = (__bridge id)CFDictionaryGetValue(_dict, (__bridge void *)obj); + POPAnimation *animation = keyAnimationsDict[key]; + + // unlock + pthread_mutex_unlock(&_lock); + return animation; } -- (void)render +- (CFTimeInterval)refreshPeriod +{ +#if TARGET_OS_IPHONE + return self->_displayLink.duration; +#else + if (NULL != self->_displayLink) { + CVTime period = CVDisplayLinkGetNominalOutputVideoRefreshPeriod(self->_displayLink); + if (period.flags & kCVTimeIsIndefinite) { + return 0; + } + return ((CFTimeInterval)period.timeValue / (CFTimeInterval)period.timeScale); + } + return (1.0 / (CFTimeInterval)_displayTimerFrequency); +#endif +} + +- (CFTimeInterval)_currentRenderTime { CFTimeInterval time = CACurrentMediaTime(); @@ -444,93 +853,57 @@ - (void)render } #endif + return time; +} + +- (void)render +{ + CFTimeInterval time = [self _currentRenderTime]; [self renderTime:time]; } - (void)renderTime:(CFTimeInterval)time { - [CATransaction begin]; - [CATransaction setDisableActions:YES]; - - [_delegate animatorWillAnimate:self]; - - const NSUInteger count = _list.size(); - if (0 != count) { - - std::vector vector{ std::begin(_list), std::end(_list) }; - - id obj; - POPAnimation *anim; - POPAnimationState *state; - - for (auto item : vector) { - obj = item->object; - anim = item->animation; - state = POPAnimationGetState(anim); - - if (nil == obj) { - - // object exists not; stop animating - NSAssert(item->unretainedObject, @"object should exist"); - stopAndCleanup(self, item, true, false); - - } else { - // start if needed - state->startIfNeeded(obj, time, _slowMotionAccumulator); - - // only run active, not paused animations - if (state->active && !state->paused) { - // object exists; animate - applyAnimationTime(obj, state, time); - - FBLogAnimDebug(@"time:%f running:%@", time, item->animation); - - if (state->isDone()) { - // set end value - applyAnimationProgress(obj, state, 1.0); - - // finished succesfully, cleanup - stopAndCleanup(self, item, state->removedOnCompletion, YES); - } - } - } - } - } - - for (id observer in _observers) { - [observer animatorDidAnimate:(id)self]; - } - - updateAnimating(self); - [_delegate animatorDidAnimate:self]; - - [CATransaction commit]; + [self _renderTime:time items:_list]; } - (void)addObserver:(id)observer { - NSAssert([NSThread isMainThread], @"unexpected thread %@", [NSThread currentThread]); NSAssert(nil != observer, @"attempting to add nil %@ observer", self); - if (nil == observer) + if (nil == observer) { return; + } + + // lock + pthread_mutex_lock(&_lock); - NSMutableSet *observers = _observers ? [_observers mutableCopy] : [[NSMutableSet alloc] initWithCapacity:1]; - [observers addObject:observer]; - _observers = observers; - updateAnimating(self); + if (!_observers) { + // use ordered collection for deterministic callout + _observers = [[NSMutableArray alloc] initWithCapacity:1]; + } + + [_observers addObject:observer]; + updateDisplayLink(self); + + // unlock + pthread_mutex_unlock(&_lock); } - (void)removeObserver:(id)observer { - NSAssert([NSThread isMainThread], @"unexpected thread %@", [NSThread currentThread]); NSAssert(nil != observer, @"attempting to remove nil %@ observer", self); - if (nil == observer) + if (nil == observer) { return; + } + + // lock + pthread_mutex_lock(&_lock); + + [_observers removeObject:observer]; + updateDisplayLink(self); - NSMutableSet *observers = [_observers mutableCopy]; - [observers removeObject:observer]; - _observers = observers; - updateAnimating(self); + // unlock + pthread_mutex_unlock(&_lock); } @end diff --git a/pop/POPAnimatorPrivate.h b/pop/POPAnimatorPrivate.h index f04fad68..8ddf2e0d 100644 --- a/pop/POPAnimatorPrivate.h +++ b/pop/POPAnimatorPrivate.h @@ -7,7 +7,7 @@ of patent rights can be found in the PATENTS file in the same directory. */ -#import +#import @class POPAnimation; @@ -23,14 +23,30 @@ @interface POPAnimator () -#if !TARGET_OS_PHONE +#if !TARGET_OS_IPHONE /** Determines whether or not to use a high priority background thread for animation updates. Using a background thread can result in faster, more responsive updates, but may be less compatible. Defaults to YES. */ + (BOOL)disableBackgroundThread; + (void)setDisableBackgroundThread:(BOOL)flag; + +/** + Determines the frequency (Hz) of the timer used when no display is available. Defaults to 60Hz. + */ ++ (uint64_t)displayTimerFrequency; ++ (void)setDisplayTimerFrequency:(uint64_t)frequency; #endif +/** + Used for externally driven animator instances. + */ +@property (assign, nonatomic) BOOL disableDisplayLink; + +/** + Time used when starting animations. Defaults to 0 meaning current media time is used. Exposed for unit testing. + */ +@property (assign, nonatomic) CFTimeInterval beginTime; + /** Exposed for unit testing. */ diff --git a/pop/POPBasicAnimation.h b/pop/POPBasicAnimation.h index a993d828..ce2e23af 100644 --- a/pop/POPBasicAnimation.h +++ b/pop/POPBasicAnimation.h @@ -7,7 +7,7 @@ of patent rights can be found in the PATENTS file in the same directory. */ -#import +#import /** @abstract A concrete basic animation class. diff --git a/pop/POPBasicAnimation.mm b/pop/POPBasicAnimation.mm index f53bba14..2843c993 100644 --- a/pop/POPBasicAnimation.mm +++ b/pop/POPBasicAnimation.mm @@ -88,3 +88,19 @@ - (void)_appendDescription:(NSMutableString *)s debug:(BOOL)debug } @end + +@implementation POPBasicAnimation (NSCopying) + +- (instancetype)copyWithZone:(NSZone *)zone { + + POPBasicAnimation *copy = [super copyWithZone:zone]; + + if (copy) { + copy.duration = self.duration; + copy.timingFunction = self.timingFunction; // not a 'copy', but timing functions are publicly immutable. + } + + return copy; +} + +@end \ No newline at end of file diff --git a/pop/POPBasicAnimationInternal.h b/pop/POPBasicAnimationInternal.h index 89f9861f..14dd64d4 100644 --- a/pop/POPBasicAnimationInternal.h +++ b/pop/POPBasicAnimationInternal.h @@ -8,12 +8,16 @@ */ #import "POPBasicAnimation.h" + #import "POPPropertyAnimationInternal.h" // default animation duration -static CGFloat kPOPAnimationDurationDefault = 0.4; +static CGFloat const kPOPAnimationDurationDefault = 0.4; + +// progress threshold for computing done +static CGFloat const kPOPProgressThreshold = 1e-6; -static void interpolate(POPValueType valueType, NSUInteger count, const CGFloat *fromVec, const CGFloat *toVec, CGFloat *outVec, double p) +static void interpolate(POPValueType valueType, NSUInteger count, const CGFloat *fromVec, const CGFloat *toVec, CGFloat *outVec, CGFloat p) { switch (valueType) { case kPOPValueInteger: @@ -21,7 +25,9 @@ static void interpolate(POPValueType valueType, NSUInteger count, const CGFloat case kPOPValuePoint: case kPOPValueSize: case kPOPValueRect: - interpolate_vector(count, outVec, fromVec, toVec, p); + case kPOPValueEdgeInsets: + case kPOPValueColor: + POPInterpolateVector(count, outVec, fromVec, toVec, p); break; default: NSCAssert(false, @"unhandled type %d", valueType); @@ -34,25 +40,27 @@ struct _POPBasicAnimationState : _POPPropertyAnimationState CAMediaTimingFunction *timingFunction; double timingControlPoints[4]; CFTimeInterval duration; + CFTimeInterval timeProgress; _POPBasicAnimationState(id __unsafe_unretained anim) : _POPPropertyAnimationState(anim), + timingFunction(nil), + timingControlPoints{0.}, duration(kPOPAnimationDurationDefault), - timingFunction(nil) + timeProgress(0.) { type = kPOPAnimationBasic; - memset(timingControlPoints, 0, sizeof(timingControlPoints)); } bool isDone() { if (_POPPropertyAnimationState::isDone()) { return true; } - return _EQLF_(progress, 1., 1e-2); + return timeProgress + kPOPProgressThreshold >= 1.; } void updatedTimingFunction() { - float vec[4] = {0., 0., 0., 0.}; + float vec[4] = {0.}; [timingFunction getControlPointAtIndex:1 values:&vec[0]]; [timingFunction getControlPointAtIndex:2 values:&vec[2]]; for (NSUInteger idx = 0; idx < POP_ARRAY_COUNT(vec); idx++) { @@ -66,22 +74,23 @@ struct _POPBasicAnimationState : _POPPropertyAnimationState ((POPBasicAnimation *)self).timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionDefault]; } - // cap local time to duration - CFTimeInterval t = MIN(time - startTime, duration) / duration; - - // solve for normalized time, aka progresss [0, 1] - double p = timing_function_solve(timingControlPoints, t, SOLVE_EPS(duration)); - - // interpolate and advance - if (p != progress) { - interpolate(valueType, valueCount, fromVec->data(), toVec->data(), currentVec->data(), p); - progress = p; - return true; + // solve for normalized time, aka progress [0, 1] + CGFloat p = 1.0f; + if (duration > 0.0f) { + // cap local time to duration + CFTimeInterval t = MIN(time - startTime, duration) / duration; + p = POPTimingFunctionSolve(timingControlPoints, t, SOLVE_EPS(duration)); + timeProgress = t; + } else { + timeProgress = 1.; } + // interpolate and advance + interpolate(valueType, valueCount, fromVec->data(), toVec->data(), currentVec->data(), p); + progress = p; clampCurrentValue(); - return false; + return true; } }; diff --git a/pop/POPCGUtils.h b/pop/POPCGUtils.h index b268842f..c8439478 100644 --- a/pop/POPCGUtils.h +++ b/pop/POPCGUtils.h @@ -8,10 +8,17 @@ */ #import -#import "POPDefines.h" #if TARGET_OS_IPHONE -@class UIColor; +#import +#else +#import +#endif + +#import "POPDefines.h" + +#if SCENEKIT_SDK_AVAILABLE +#import #endif POP_EXTERN_C_BEGIN @@ -31,6 +38,27 @@ NS_INLINE CGRect values_to_rect(const CGFloat values[]) return CGRectMake(values[0], values[1], values[2], values[3]); } +#if SCENEKIT_SDK_AVAILABLE +NS_INLINE SCNVector3 values_to_vec3(const CGFloat values[]) +{ + return SCNVector3Make(values[0], values[1], values[2]); +} + +NS_INLINE SCNVector4 values_to_vec4(const CGFloat values[]) +{ + return SCNVector4Make(values[0], values[1], values[2], values[3]); +} +#endif + +#if TARGET_OS_IPHONE + +NS_INLINE UIEdgeInsets values_to_edge_insets(const CGFloat values[]) +{ + return UIEdgeInsetsMake(values[0], values[1], values[2], values[3]); +} + +#endif + NS_INLINE void values_from_point(CGFloat values[], CGPoint p) { values[0] = p.x; @@ -51,6 +79,35 @@ NS_INLINE void values_from_rect(CGFloat values[], CGRect r) values[3] = r.size.height; } +#if SCENEKIT_SDK_AVAILABLE +NS_INLINE void values_from_vec3(CGFloat values[], SCNVector3 v) +{ + values[0] = v.x; + values[1] = v.y; + values[2] = v.z; +} + +NS_INLINE void values_from_vec4(CGFloat values[], SCNVector4 v) +{ + values[0] = v.x; + values[1] = v.y; + values[2] = v.z; + values[3] = v.w; +} +#endif + +#if TARGET_OS_IPHONE + +NS_INLINE void values_from_edge_insets(CGFloat values[], UIEdgeInsets i) +{ + values[0] = i.top; + values[1] = i.left; + values[2] = i.bottom; + values[3] = i.right; +} + +#endif + /** Takes a CGColorRef and converts it into RGBA components, if necessary. */ @@ -61,6 +118,11 @@ extern void POPCGColorGetRGBAComponents(CGColorRef color, CGFloat components[]); */ extern CGColorRef POPCGColorRGBACreate(const CGFloat components[]) CF_RETURNS_RETAINED; +/** + Takes a color reference and returns a CGColor. + */ +extern CGColorRef POPCGColorWithColor(id color) CF_RETURNS_NOT_RETAINED; + #if TARGET_OS_IPHONE /** @@ -73,6 +135,18 @@ extern void POPUIColorGetRGBAComponents(UIColor *color, CGFloat components[]); */ extern UIColor *POPUIColorRGBACreate(const CGFloat components[]) NS_RETURNS_RETAINED; +#else + +/** + Takes a NSColor and converts it into RGBA components, if necessary. + */ +extern void POPNSColorGetRGBAComponents(NSColor *color, CGFloat components[]); + +/** + Takes RGBA components and returns a NSColor. + */ +extern NSColor *POPNSColorRGBACreate(const CGFloat components[]) NS_RETURNS_RETAINED; + #endif POP_EXTERN_C_END diff --git a/pop/POPCGUtils.mm b/pop/POPCGUtils.mm index 97e68327..acc7dfec 100644 --- a/pop/POPCGUtils.mm +++ b/pop/POPCGUtils.mm @@ -9,38 +9,34 @@ #import "POPCGUtils.h" -#if TARGET_OS_IPHONE -#import -#else -#import -#endif +#import void POPCGColorGetRGBAComponents(CGColorRef color, CGFloat components[]) { - if (!color) { -#if TARGET_OS_IPHONE - color = [UIColor clearColor].CGColor; -#else - color = [NSColor clearColor].CGColor; -#endif - } - - const CGFloat *colors = CGColorGetComponents(color); - size_t count = CGColorGetNumberOfComponents(color); - - if (4 == count) { - // RGB colorspace - components[0] = colors[0]; - components[1] = colors[1]; - components[2] = colors[2]; - components[3] = colors[3]; - } else if (2 == count) { - // Grey colorspace - components[0] = components[1] = components[2] = colors[0]; - components[3] = colors[1]; + if (color) { + const CGFloat *colors = CGColorGetComponents(color); + size_t count = CGColorGetNumberOfComponents(color); + + if (4 == count) { + // RGB colorspace + components[0] = colors[0]; + components[1] = colors[1]; + components[2] = colors[2]; + components[3] = colors[3]; + } else if (2 == count) { + // Grey colorspace + components[0] = components[1] = components[2] = colors[0]; + components[3] = colors[1]; + } else { + // Use CI to convert + CIColor *ciColor = [CIColor colorWithCGColor:color]; + components[0] = ciColor.red; + components[1] = ciColor.green; + components[2] = ciColor.blue; + components[3] = ciColor.alpha; + } } else { - // TODO HSV and CMYK conversion - NSCAssert(NO, @"unsuported color space conversion, component count:%lu", count); + memset(components, 0, 4 * sizeof(components[0])); } } @@ -56,11 +52,65 @@ CGColorRef POPCGColorRGBACreate(const CGFloat components[]) #endif } +CGColorRef POPCGColorWithColor(id color) +{ + if (CFGetTypeID((__bridge CFTypeRef)color) == CGColorGetTypeID()) { + return ((__bridge CGColorRef)color); + } +#if TARGET_OS_IPHONE + else if ([color isKindOfClass:[UIColor class]]) { + return [color CGColor]; + } +#else + else if ([color isKindOfClass:[NSColor class]]) { + // -[NSColor CGColor] is only supported since OSX 10.8+ + if ([color respondsToSelector:@selector(CGColor)]) { + return [color CGColor]; + } + + /* + * Otherwise create a CGColorRef manually. + * + * The original accessor is (or would be) declared as: + * @property(readonly) CGColorRef CGColor; + * - (CGColorRef)CGColor NS_RETURNS_INNER_POINTER CF_RETURNS_NOT_RETAINED; + * + * (Please note that OSX' accessor is atomic, while iOS' isn't.) + * + * The access to the NSColor object must thus be synchronized + * and the CGColorRef be stored as an associated object, + * to return a reference which doesn't need to be released manually. + */ + @synchronized(color) { + static const void* key = &key; + + CGColorRef colorRef = (__bridge CGColorRef)objc_getAssociatedObject(color, key); + + if (!colorRef) { + size_t numberOfComponents = [(NSColor *)color numberOfComponents]; + CGFloat components[numberOfComponents]; + CGColorSpaceRef colorSpace = [[(NSColor *)color colorSpace] CGColorSpace]; + + [color getComponents:components]; + + colorRef = CGColorCreate(colorSpace, components); + + objc_setAssociatedObject(color, key, (__bridge id)colorRef, OBJC_ASSOCIATION_RETAIN_NONATOMIC); + CGColorRelease(colorRef); + } + + return colorRef; + } + } +#endif + return nil; +} + #if TARGET_OS_IPHONE void POPUIColorGetRGBAComponents(UIColor *color, CGFloat components[]) { - return POPCGColorGetRGBAComponents(color.CGColor, components); + return POPCGColorGetRGBAComponents(POPCGColorWithColor(color), components); } UIColor *POPUIColorRGBACreate(const CGFloat components[]) @@ -71,5 +121,30 @@ void POPUIColorGetRGBAComponents(UIColor *color, CGFloat components[]) return color; } +#else + +void POPNSColorGetRGBAComponents(NSColor *color, CGFloat components[]) +{ + return POPCGColorGetRGBAComponents(POPCGColorWithColor(color), components); +} + +NSColor *POPNSColorRGBACreate(const CGFloat components[]) +{ + CGColorRef colorRef = POPCGColorRGBACreate(components); + NSColor *color = nil; + + if (colorRef) { + if ([NSColor respondsToSelector:@selector(colorWithCGColor:)]) { + color = [NSColor colorWithCGColor:colorRef]; + } else { + color = [NSColor colorWithCIColor:[CIColor colorWithCGColor:colorRef]]; + } + + CGColorRelease(colorRef); + } + + return color; +} + #endif diff --git a/pop/POPCustomAnimation.h b/pop/POPCustomAnimation.h index fd93da68..501a755b 100644 --- a/pop/POPCustomAnimation.h +++ b/pop/POPCustomAnimation.h @@ -7,7 +7,7 @@ of patent rights can be found in the PATENTS file in the same directory. */ -#import +#import @class POPCustomAnimation; @@ -15,7 +15,7 @@ @abstract POPCustomAnimationBlock is the callback block of a custom animation. @discussion This block will be executed for each animation frame and should update the property or properties being animated based on current timing. @param target The object being animated. Reference the passed in target to help avoid retain loops. - @param target The custom animation instance. Use to determine the current and elapsed time since last callback. Reference the passed in animation to help avoid retain loops. + @param animation The custom animation instance. Use to determine the current and elapsed time since last callback. Reference the passed in animation to help avoid retain loops. @return Flag indicating whether the animation should continue animating. Return NO to indicate animation is done. */ typedef BOOL (^POPCustomAnimationBlock)(id target, POPCustomAnimation *animation); diff --git a/pop/POPCustomAnimation.mm b/pop/POPCustomAnimation.mm index beb309cd..8cb79135 100644 --- a/pop/POPCustomAnimation.mm +++ b/pop/POPCustomAnimation.mm @@ -7,14 +7,18 @@ of patent rights can be found in the PATENTS file in the same directory. */ -#import "POPCustomAnimation.h" #import "POPAnimationInternal.h" +#import "POPCustomAnimation.h" + @interface POPCustomAnimation () @property (nonatomic, copy) POPCustomAnimationBlock animate; @end @implementation POPCustomAnimation +@synthesize currentTime = _currentTime; +@synthesize elapsedTime = _elapsedTime; +@synthesize animate = _animate; + (instancetype)animationWithBlock:(BOOL(^)(id target, POPCustomAnimation *))block { @@ -51,3 +55,21 @@ - (void)_appendDescription:(NSMutableString *)s debug:(BOOL)debug } @end + +/** + * Note that only the animate block is copied, but not the current/elapsed times + */ +@implementation POPCustomAnimation (NSCopying) + +- (instancetype)copyWithZone:(NSZone *)zone { + + POPCustomAnimation *copy = [super copyWithZone:zone]; + + if (copy) { + copy.animate = self.animate; + } + + return copy; +} + +@end \ No newline at end of file diff --git a/pop/POPDecayAnimation.h b/pop/POPDecayAnimation.h index 9018cd83..92c6b604 100644 --- a/pop/POPDecayAnimation.h +++ b/pop/POPDecayAnimation.h @@ -7,7 +7,7 @@ of patent rights can be found in the PATENTS file in the same directory. */ -#import +#import /** @abstract A concrete decay animation class. @@ -30,10 +30,16 @@ /** @abstract The current velocity value. - @discussion Set before animation start to account for initial velocity. Expressed in change of value units per second. + @discussion Set before animation start to account for initial velocity. Expressed in change of value units per second. The only POPValueTypes supported for velocity are: kPOPValuePoint, kPOPValueInteger, kPOPValueFloat, kPOPValueRect, and kPOPValueSize. */ @property (copy, nonatomic) id velocity; +/** + @abstract The original velocity value. + @discussion Since the velocity property is modified as the animation progresses, this property stores the original, passed in velocity to support autoreverse and repeatCount. + */ +@property (copy, nonatomic, readonly) id originalVelocity; + /** @abstract The deceleration factor. @discussion Values specifies should be in the range [0, 1]. Lower values results in faster deceleration. Defaults to 0.998. @@ -51,4 +57,10 @@ */ - (void)setToValue:(id)toValue NS_UNAVAILABLE; +/** + @abstract The reversed velocity. + @discussion The reversed velocity based on the originalVelocity when the animation was set up. + */ +- (id)reversedVelocity; + @end diff --git a/pop/POPDecayAnimation.mm b/pop/POPDecayAnimation.mm index 2a0bbc75..4698fd0d 100644 --- a/pop/POPDecayAnimation.mm +++ b/pop/POPDecayAnimation.mm @@ -9,6 +9,12 @@ #import "POPDecayAnimationInternal.h" +#if TARGET_OS_IPHONE +#import +#endif + +const POPValueType supportedVelocityTypes[6] = { kPOPValuePoint, kPOPValueInteger, kPOPValueFloat, kPOPValueRect, kPOPValueSize, kPOPValueEdgeInsets }; + @implementation POPDecayAnimation #pragma mark - Lifecycle @@ -68,6 +74,51 @@ - (void)setToValue:(id)aValue NSLog(@"ignoring to value on decay animation %@", self); } +- (id)reversedVelocity +{ + id reversedVelocity = nil; + + POPValueType velocityType = POPSelectValueType(self.originalVelocity, supportedVelocityTypes, POP_ARRAY_COUNT(supportedVelocityTypes)); + if (velocityType == kPOPValueFloat) { +#if CGFLOAT_IS_DOUBLE + CGFloat originalVelocityFloat = [(NSNumber *)self.originalVelocity doubleValue]; +#else + CGFloat originalVelocityFloat = [(NSNumber *)self.originalVelocity floatValue]; +#endif + NSNumber *negativeOriginalVelocityNumber = @(-originalVelocityFloat); + reversedVelocity = negativeOriginalVelocityNumber; + } else if (velocityType == kPOPValueInteger) { + NSInteger originalVelocityInteger = [(NSNumber *)self.originalVelocity integerValue]; + NSNumber *negativeOriginalVelocityNumber = @(-originalVelocityInteger); + reversedVelocity = negativeOriginalVelocityNumber; + } else if (velocityType == kPOPValuePoint) { + CGPoint originalVelocityPoint = [self.originalVelocity CGPointValue]; + CGPoint negativeOriginalVelocityPoint = CGPointMake(-originalVelocityPoint.x, -originalVelocityPoint.y); + reversedVelocity = [NSValue valueWithCGPoint:negativeOriginalVelocityPoint]; + } else if (velocityType == kPOPValueRect) { + CGRect originalVelocityRect = [self.originalVelocity CGRectValue]; + CGRect negativeOriginalVelocityRect = CGRectMake(-originalVelocityRect.origin.x, -originalVelocityRect.origin.y, -originalVelocityRect.size.width, -originalVelocityRect.size.height); + reversedVelocity = [NSValue valueWithCGRect:negativeOriginalVelocityRect]; + } else if (velocityType == kPOPValueSize) { + CGSize originalVelocitySize = [self.originalVelocity CGSizeValue]; + CGSize negativeOriginalVelocitySize = CGSizeMake(-originalVelocitySize.width, -originalVelocitySize.height); + reversedVelocity = [NSValue valueWithCGSize:negativeOriginalVelocitySize]; + } else if (velocityType == kPOPValueEdgeInsets) { +#if TARGET_OS_IPHONE + UIEdgeInsets originalVelocityInsets = [self.originalVelocity UIEdgeInsetsValue]; + UIEdgeInsets negativeOriginalVelocityInsets = UIEdgeInsetsMake(-originalVelocityInsets.top, -originalVelocityInsets.left, -originalVelocityInsets.bottom, -originalVelocityInsets.right); + reversedVelocity = [NSValue valueWithUIEdgeInsets:negativeOriginalVelocityInsets]; +#endif + } + + return reversedVelocity; +} + +- (id)originalVelocity +{ + return POPBox(__state->originalVelocityVec, __state->valueType); +} + - (id)velocity { return POPBox(__state->velocityVec, __state->valueType); @@ -75,22 +126,30 @@ - (id)velocity - (void)setVelocity:(id)aValue { - VectorRef vec = POPUnbox(aValue, __state->valueType, __state->valueCount, YES); - - if (!vec_equal(vec, __state->velocityVec)) { - __state->velocityVec = vec; - - if (__state->tracing) { - [__state->tracer updateVelocity:aValue]; - } - - [self _invalidateComputedProperties]; - - // automatically unpause active animations - if (__state->active && __state->paused) { - __state->fromVec = NULL; - __state->setPaused(false); + POPValueType valueType = POPSelectValueType(aValue, supportedVelocityTypes, POP_ARRAY_COUNT(supportedVelocityTypes)); + if (valueType != kPOPValueUnknown) { + VectorRef vec = POPUnbox(aValue, __state->valueType, __state->valueCount, YES); + VectorRef origVec = POPUnbox(aValue, __state->valueType, __state->valueCount, YES); + + if (!vec_equal(vec, __state->velocityVec)) { + __state->velocityVec = vec; + __state->originalVelocityVec = origVec; + + if (__state->tracing) { + [__state->tracer updateVelocity:aValue]; + } + + [self _invalidateComputedProperties]; + + // automatically unpause active animations + if (__state->active && __state->paused) { + __state->fromVec = NULL; + __state->setPaused(false); + } } + } else { + __state->velocityVec = NULL; + NSLog(@"Invalid velocity value for the decayAnimation: %@", aValue); } } @@ -99,7 +158,8 @@ - (void)setVelocity:(id)aValue - (void)_ensureComputedProperties { if (NULL == __state->toVec) { - __state->computeDestinationValues(); + __state->computeDuration(); + __state->computeToValue(); } } @@ -113,11 +173,31 @@ - (void)_appendDescription:(NSMutableString *)s debug:(BOOL)debug { [super _appendDescription:s debug:debug]; - if (NULL != __state->toVec) + if (0 != self.duration) { [s appendFormat:@"; duration = %f", self.duration]; + } - if (__state->deceleration) + if (__state->deceleration) { [s appendFormat:@"; deceleration = %f", __state->deceleration]; + } } @end + +@implementation POPDecayAnimation (NSCopying) + +- (instancetype)copyWithZone:(NSZone *)zone { + + POPDecayAnimation *copy = [super copyWithZone:zone]; + + if (copy) { + // Set the velocity to the animation's original velocity, not its current. + copy.velocity = self.originalVelocity; + copy.deceleration = self.deceleration; + + } + + return copy; +} + +@end \ No newline at end of file diff --git a/pop/POPDecayAnimationInternal.h b/pop/POPDecayAnimationInternal.h index aca98c43..c1017611 100644 --- a/pop/POPDecayAnimationInternal.h +++ b/pop/POPDecayAnimationInternal.h @@ -8,6 +8,9 @@ */ #import "POPDecayAnimation.h" + +#import + #import "POPPropertyAnimationInternal.h" // minimal velocity factor before decay animation is considered complete, in units / s @@ -44,8 +47,9 @@ struct _POPDecayAnimationState : _POPPropertyAnimationState _POPDecayAnimationState(id __unsafe_unretained anim) : _POPPropertyAnimationState(anim), - duration(0), - deceleration(kPOPAnimationDecayDecelerationDefault) { + deceleration(kPOPAnimationDecayDecelerationDefault), + duration(0) + { type = kPOPAnimationDecay; } @@ -57,23 +61,14 @@ struct _POPDecayAnimationState : _POPPropertyAnimationState CGFloat f = dynamicsThreshold * kPOPAnimationDecayMinimalVelocityFactor; const CGFloat *velocityValues = vec_data(velocityVec); for (NSUInteger idx = 0; idx < valueCount; idx++) { - if (fabsf(velocityValues[idx]) >= f) + if (std::abs((velocityValues[idx])) >= f) return false; } return true; } - void computeDestinationValues() { - // to value assuming final velocity as a factor of dynamics threshold - // derived from v' = v * d^dt used in decay_position - // to compute the to value with maximal dt, p' = p + (v * d) / (1 - d) - VectorRef fromValue = NULL != currentVec ? currentVec : fromVec; - if (!fromValue) { - return; - } - - VectorRef toValue(Vector::new_vector(fromValue.get())); + void computeDuration() { // compute duration till threshold velocity Vector4r scaledVelocity = vector4(velocityVec) / 1000.; @@ -87,14 +82,29 @@ struct _POPDecayAnimationState : _POPPropertyAnimationState duration = MAX(MAX(MAX(log(fabs(vx)) / d, log(fabs(vy)) / d), log(fabs(vz)) / d), log(fabs(vw)) / d); // ensure velocity threshold is exceeded - if (isnan(duration) || duration < 0) { + if (std::isnan(duration) || duration < 0) { duration = 0; - } else { - // compute to value - Vector4r velocity = velocityVec->vector4r(); - decay_position(toValue->data(), velocity.data(), valueCount, duration, deceleration); } + } + void computeToValue() { + // to value assuming final velocity as a factor of dynamics threshold + // derived from v' = v * d^dt used in decay_position + // to compute the to value with maximal dt, p' = p + (v * d) / (1 - d) + VectorRef fromValue = NULL != currentVec ? currentVec : fromVec; + if (!fromValue) { + return; + } + + // ensure duration is computed + if (0 == duration) { + computeDuration(); + } + + // compute to value + VectorRef toValue(Vector::new_vector(fromValue.get())); + Vector4r velocity = velocityVec->vector4r(); + decay_position(toValue->data(), velocity.data(), valueCount, duration, deceleration); toVec = toValue; } diff --git a/pop/POPDefines.h b/pop/POPDefines.h index 92cf8018..a1ed381e 100644 --- a/pop/POPDefines.h +++ b/pop/POPDefines.h @@ -10,6 +10,8 @@ #ifndef POP_POPDefines_h #define POP_POPDefines_h +#import + #ifdef __cplusplus # define POP_EXTERN_C_BEGIN extern "C" { # define POP_EXTERN_C_END } @@ -26,4 +28,10 @@ # define POP_NOTHROW #endif +#if defined(POP_USE_SCENEKIT) +# if TARGET_OS_MAC || TARGET_OS_IPHONE +# define SCENEKIT_SDK_AVAILABLE 1 +# endif +#endif + #endif diff --git a/pop/POPGeometry.h b/pop/POPGeometry.h index cc783175..8ba07e33 100644 --- a/pop/POPGeometry.h +++ b/pop/POPGeometry.h @@ -33,6 +33,16 @@ */ + (NSValue *)valueWithCGRect:(CGRect)rect; +/** + @abstract Creates an NSValue given a CFRange. + */ ++ (NSValue *)valueWithCFRange:(CFRange)range; + +/** + @abstract Creates an NSValue given a CGAffineTransform. + */ ++ (NSValue *)valueWithCGAffineTransform:(CGAffineTransform)transform; + /** @abstract Returns the underlying CGPoint value. */ @@ -48,6 +58,16 @@ */ - (CGRect)CGRectValue; +/** + @abstract Returns the underlying CFRange value. + */ +- (CFRange)CFRangeValue; + +/** + @abstract Returns the underlying CGAffineTransform value. + */ +- (CGAffineTransform)CGAffineTransformValue; + @end #endif diff --git a/pop/POPGeometry.mm b/pop/POPGeometry.mm index 29c75a44..41998b10 100644 --- a/pop/POPGeometry.mm +++ b/pop/POPGeometry.mm @@ -65,3 +65,30 @@ - (CGAffineTransform)CGAffineTransformValue { @end #endif + +#if TARGET_OS_IPHONE +#import "POPDefines.h" + +#if SCENEKIT_SDK_AVAILABLE +#import + +/** + Dirty hacks because iOS is weird and decided to define both SCNVector3's and SCNVector4's objCType as "t". However @encode(SCNVector3) and @encode(SCNVector4) both return the proper definition ("{SCNVector3=fff}" and "{SCNVector4=ffff}" respectively) + + [[NSValue valueWithSCNVector3:SCNVector3Make(0.0, 0.0, 0.0)] objcType] returns "t", whereas it should return "{SCNVector3=fff}". + + *flips table* + */ +@implementation NSValue (SceneKitFixes) + ++ (NSValue *)valueWithSCNVector3:(SCNVector3)vec3 { + return [NSValue valueWithBytes:&vec3 objCType:@encode(SCNVector3)]; +} + ++ (NSValue *)valueWithSCNVector4:(SCNVector4)vec4 { + return [NSValue valueWithBytes:&vec4 objCType:@encode(SCNVector4)]; +} + +@end +#endif +#endif diff --git a/pop/POPLayerExtras.h b/pop/POPLayerExtras.h index 25a28750..ec4c29a4 100644 --- a/pop/POPLayerExtras.h +++ b/pop/POPLayerExtras.h @@ -9,7 +9,7 @@ #import -#import +#import POP_EXTERN_C_BEGIN diff --git a/pop/POPLayerExtras.mm b/pop/POPLayerExtras.mm index aff8af25..c8ad7f90 100644 --- a/pop/POPLayerExtras.mm +++ b/pop/POPLayerExtras.mm @@ -37,6 +37,21 @@ #pragma mark - Scale +NS_INLINE void ensureNonZeroValue(CGFloat &f) +{ + if (f == 0) { + f = 1e-6; + } +} + +NS_INLINE void ensureNonZeroValue(CGPoint &p) +{ + if (p.x == 0 && p.y == 0) { + p.x = 1e-6; + p.y = 1e-6; + } +} + CGFloat POPLayerGetScaleX(CALayer *l) { DECOMPOSE_TRANSFORM(l); @@ -45,6 +60,7 @@ CGFloat POPLayerGetScaleX(CALayer *l) void POPLayerSetScaleX(CALayer *l, CGFloat f) { + ensureNonZeroValue(f); DECOMPOSE_TRANSFORM(l); _d.scaleX = f; RECOMPOSE_TRANSFORM(l); @@ -58,6 +74,7 @@ CGFloat POPLayerGetScaleY(CALayer *l) void POPLayerSetScaleY(CALayer *l, CGFloat f) { + ensureNonZeroValue(f); DECOMPOSE_TRANSFORM(l); _d.scaleY = f; RECOMPOSE_TRANSFORM(l); @@ -71,6 +88,7 @@ CGFloat POPLayerGetScaleZ(CALayer *l) void POPLayerSetScaleZ(CALayer *l, CGFloat f) { + ensureNonZeroValue(f); DECOMPOSE_TRANSFORM(l); _d.scaleZ = f; RECOMPOSE_TRANSFORM(l); @@ -84,6 +102,7 @@ CGPoint POPLayerGetScaleXY(CALayer *l) void POPLayerSetScaleXY(CALayer *l, CGPoint p) { + ensureNonZeroValue(p); DECOMPOSE_TRANSFORM(l); _d.scaleX = p.x; _d.scaleY = p.y; @@ -206,6 +225,7 @@ CGPoint POPLayerGetSubScaleXY(CALayer *l) void POPLayerSetSubScaleXY(CALayer *l, CGPoint p) { + ensureNonZeroValue(p); DECOMPOSE_SUBLAYER_TRANSFORM(l); _d.scaleX = p.x; _d.scaleY = p.y; diff --git a/pop/POPMath.h b/pop/POPMath.h index a5142f94..2e8d3abb 100644 --- a/pop/POPMath.h +++ b/pop/POPMath.h @@ -1,18 +1,17 @@ /** Copyright (c) 2014-present, Facebook, Inc. All rights reserved. - + This source code is licensed under the BSD-style license found in the LICENSE file in the root directory of this source tree. An additional grant of patent rights can be found in the PATENTS file in the same directory. */ #import -#import -#import +#import -#import "POPVector.h" +#import "POPDefines.h" NS_INLINE CGFloat sqrtr(CGFloat f) { @@ -36,21 +35,21 @@ NS_INLINE CGFloat POPSubRound(CGFloat f, CGFloat sub) #define _EQLF_(x, y, epsilon) (fabsf ((x) - (y)) < epsilon) -extern void interpolate_vector(NSUInteger count, CGFloat *dst, const CGFloat *from, const CGFloat *to, double f); +extern void POPInterpolateVector(NSUInteger count, CGFloat *dst, const CGFloat *from, const CGFloat *to, CGFloat f); -extern double timing_function_solve(const double vec[4], double t, double eps); +extern double POPTimingFunctionSolve(const double vec[4], double t, double eps); // quadratic mapping of t [0, 1] to [start, end] -extern double quadratic_out_interpolation(double t, double start, double end); +extern double POPQuadraticOutInterpolation(double t, double start, double end); // normalize value to [0, 1] based on its range [startValue, endValue] -extern double normalize(double value, double startValue, double endValue); +extern double POPNormalize(double value, double startValue, double endValue); // project a normalized value [0, 1] to a given range [start, end] -extern double project_normal(double n, double start, double end); +extern double POPProjectNormal(double n, double start, double end); // solve a quadratic equation of the form a * x^2 + b * x + c = 0 -extern void quadratic_solve(CGFloat a, CGFloat b, CGFloat c, CGFloat &x1, CGFloat &x2); +extern void POPQuadraticSolve(CGFloat a, CGFloat b, CGFloat c, CGFloat &x1, CGFloat &x2); // for a given tension return the bouncy 3 friction that produces no bounce -extern double b3_nobounce(double tension); +extern double POPBouncy3NoBounce(double tension); diff --git a/pop/POPMath.mm b/pop/POPMath.mm index dc494573..69a506aa 100644 --- a/pop/POPMath.mm +++ b/pop/POPMath.mm @@ -8,28 +8,29 @@ */ #import "POPMath.h" -#import "UnitBezier.h" + #import "POPAnimationPrivate.h" +#import "UnitBezier.h" -void interpolate_vector(NSUInteger count, CGFloat *dst, const CGFloat *from, const CGFloat *to, double f) +void POPInterpolateVector(NSUInteger count, CGFloat *dst, const CGFloat *from, const CGFloat *to, CGFloat f) { for (NSUInteger idx = 0; idx < count; idx++) { dst[idx] = MIX(from[idx], to[idx], f); } } -double timing_function_solve(const double vec[4], double t, double eps) +double POPTimingFunctionSolve(const double vec[4], double t, double eps) { WebCore::UnitBezier bezier(vec[0], vec[1], vec[2], vec[3]); return bezier.solve(t, eps); } -double normalize(double value, double startValue, double endValue) +double POPNormalize(double value, double startValue, double endValue) { return (value - startValue) / (endValue - startValue); } -double project_normal(double n, double start, double end) +double POPProjectNormal(double n, double start, double end) { return start + (n * (end - start)); } @@ -39,7 +40,7 @@ static double linear_interpolation(double t, double start, double end) return t * end + (1.f - t) * start; } -double quadratic_out_interpolation(double t, double start, double end) +double POPQuadraticOutInterpolation(double t, double start, double end) { return linear_interpolation(2*t - t*t, start, end); } @@ -59,7 +60,7 @@ static double b3_friction3(double x) return (0.00000045 * pow(x, 3)) - (0.000332 * pow(x, 2)) + 0.1078 * x + 5.84; } -double b3_nobounce(double tension) +double POPBouncy3NoBounce(double tension) { double friction = 0; if (tension <= 18.) { @@ -74,7 +75,7 @@ static double b3_friction3(double x) return friction; } -void quadratic_solve(CGFloat a, CGFloat b, CGFloat c, CGFloat &x1, CGFloat &x2) +void POPQuadraticSolve(CGFloat a, CGFloat b, CGFloat c, CGFloat &x1, CGFloat &x2) { CGFloat discriminant = sqrt(b * b - 4 * a * c); x1 = (-b + discriminant) / (2 * a); diff --git a/pop/POPPropertyAnimation.h b/pop/POPPropertyAnimation.h index 9dcfe2a1..cf895726 100644 --- a/pop/POPPropertyAnimation.h +++ b/pop/POPPropertyAnimation.h @@ -7,8 +7,8 @@ of patent rights can be found in the PATENTS file in the same directory. */ -#import -#import +#import +#import /** @abstract Flags for clamping animation values. @@ -63,3 +63,14 @@ typedef NS_OPTIONS(NSUInteger, POPAnimationClampFlags) @property (assign, nonatomic, getter = isAdditive) BOOL additive; @end + +@interface POPPropertyAnimation (CustomProperty) + ++ (instancetype)animationWithCustomPropertyNamed:(NSString *)name + readBlock:(POPAnimatablePropertyReadBlock)readBlock + writeBlock:(POPAnimatablePropertyWriteBlock)writeBlock; + ++ (instancetype)animationWithCustomPropertyReadBlock:(POPAnimatablePropertyReadBlock)readBlock + writeBlock:(POPAnimatablePropertyWriteBlock)writeBlock; + +@end diff --git a/pop/POPPropertyAnimation.mm b/pop/POPPropertyAnimation.mm index ccabc488..06f8cfa8 100644 --- a/pop/POPPropertyAnimation.mm +++ b/pop/POPPropertyAnimation.mm @@ -54,7 +54,7 @@ - (id)toValue - (void)setToValue:(id)aValue { - POPPropertyAnimationState *s = (POPPropertyAnimationState *)POPAnimationGetState(self); + POPPropertyAnimationState *s = __state; VectorRef vec = POPUnbox(aValue, s->valueType, s->valueCount, YES); if (!vec_equal(vec, s->toVec)) { @@ -103,3 +103,47 @@ - (void)_appendDescription:(NSMutableString *)s debug:(BOOL)debug } @end + +@implementation POPPropertyAnimation (NSCopying) + +- (instancetype)copyWithZone:(NSZone *)zone { + + POPPropertyAnimation *copy = [super copyWithZone:zone]; + + if (copy) { + copy.property = [self.property copyWithZone:zone]; + copy.fromValue = self.fromValue; + copy.toValue = self.toValue; + copy.roundingFactor = self.roundingFactor; + copy.clampMode = self.clampMode; + copy.additive = self.additive; + } + + return copy; +} + +@end + +@implementation POPPropertyAnimation (CustomProperty) + ++ (instancetype)animationWithCustomPropertyNamed:(NSString *)name + readBlock:(POPAnimatablePropertyReadBlock)readBlock + writeBlock:(POPAnimatablePropertyWriteBlock)writeBlock +{ + POPPropertyAnimation *animation = [[self alloc] init]; + animation.property = [POPAnimatableProperty propertyWithName:name initializer:^(POPMutableAnimatableProperty *prop) { + prop.readBlock = readBlock; + prop.writeBlock = writeBlock; + }]; + return animation; +} + ++ (instancetype)animationWithCustomPropertyReadBlock:(POPAnimatablePropertyReadBlock)readBlock + writeBlock:(POPAnimatablePropertyWriteBlock)writeBlock +{ + return [self animationWithCustomPropertyNamed:[NSUUID UUID].UUIDString + readBlock:readBlock + writeBlock:writeBlock]; +} + +@end diff --git a/pop/POPPropertyAnimationInternal.h b/pop/POPPropertyAnimationInternal.h index ff742ff5..20471cac 100644 --- a/pop/POPPropertyAnimationInternal.h +++ b/pop/POPPropertyAnimationInternal.h @@ -38,6 +38,7 @@ struct _POPPropertyAnimationState : _POPAnimationState VectorRef previousVec; VectorRef previous2Vec; VectorRef velocityVec; + VectorRef originalVelocityVec; VectorRef distanceVec; CGFloat roundingFactor; NSUInteger clampMode; @@ -50,13 +51,14 @@ struct _POPPropertyAnimationState : _POPAnimationState _POPPropertyAnimationState(id __unsafe_unretained anim) : _POPAnimationState(anim), property(nil), valueType((POPValueType)0), - valueCount(nil), + valueCount(0), fromVec(nullptr), toVec(nullptr), currentVec(nullptr), previousVec(nullptr), previous2Vec(nullptr), velocityVec(nullptr), + originalVelocityVec(nullptr), distanceVec(nullptr), roundingFactor(0), clampMode(0), @@ -105,13 +107,11 @@ struct _POPPropertyAnimationState : _POPAnimationState // returns a copy of the currentVec, rounding if needed VectorRef currentValue() { - if (!shouldRound()) { - return VectorRef(Vector::new_vector(currentVec.get())); - } else { - VectorRef vec = VectorRef(Vector::new_vector(currentVec.get())); + VectorRef vec = VectorRef(Vector::new_vector(currentVec.get())); + if (shouldRound()) { vec->subRound(1 / roundingFactor); - return vec; } + return vec; } void resetProgressMarkerState() @@ -147,27 +147,19 @@ struct _POPPropertyAnimationState : _POPAnimationState dynamicsThreshold = property.threshold; } - bool advanceProgress(CGFloat p) + void finalizeProgress() { - bool advanced = progress != p; - if (advanced) { - progress = p; - NSUInteger count = valueCount; - VectorRef outVec(Vector::new_vector(count, NULL)); - - if (1.0 == progress) { - if (outVec && toVec) { - *outVec = *toVec; - } - } else { - interpolate_vector(count, vec_data(outVec), vec_data(fromVec), vec_data(toVec), progress); - } + progress = 1.0; + NSUInteger count = valueCount; + VectorRef outVec(Vector::new_vector(count, NULL)); - currentVec = outVec; - clampCurrentValue(); - delegateProgress(); + if (outVec && toVec) { + *outVec = *toVec; } - return advanced; + + currentVec = outVec; + clampCurrentValue(); + delegateProgress(); } void computeProgress() { @@ -219,7 +211,7 @@ struct _POPPropertyAnimationState : _POPAnimationState didReachToValue = true; const CGFloat *distanceValues = distanceVec->data(); for (NSUInteger idx = 0; idx < valueCount; idx++) { - didReachToValue &= signbit(distance[idx]) != signbit(distanceValues[idx]); + didReachToValue &= (signbit(distance[idx]) != signbit(distanceValues[idx])); } } } @@ -239,6 +231,12 @@ struct _POPPropertyAnimationState : _POPAnimationState [delegate pop_animationDidReachToValue:self]; } + POPAnimationDidReachToValueBlock block = animationDidReachToValueBlock; + if (block != NULL) { + ActionEnabler enabler; + block(self); + } + if (tracing) { [tracer didReachToValue:POPBox(currentValue(), valueType, true)]; } @@ -247,7 +245,7 @@ struct _POPPropertyAnimationState : _POPAnimationState void readObjectValue(VectorRef *ptrVec, id obj) { // use current object value as from value - pop_animatable_read_block read = property.readBlock; + POPAnimatablePropertyReadBlock read = property.readBlock; if (NULL != read) { Vector4r vec = read_values(read, obj, valueCount); @@ -295,13 +293,16 @@ struct _POPPropertyAnimationState : _POPAnimationState if (!velocityVec) { velocityVec = VectorRef(Vector::new_vector(valueCount, NULL)); } + if (!originalVelocityVec) { + originalVelocityVec = VectorRef(Vector::new_vector(valueCount, NULL)); + } } // ensure distance value initialized // depends on current value set on one time start if (NULL == distanceVec) { - // not yet started animations may not have from value + // not yet started animations may not have current value VectorRef fromVec2 = NULL != currentVec ? currentVec : fromVec; if (fromVec2 && toVec) { diff --git a/pop/POPSpringAnimation.h b/pop/POPSpringAnimation.h index 75c3babf..a22cd5be 100644 --- a/pop/POPSpringAnimation.h +++ b/pop/POPSpringAnimation.h @@ -7,7 +7,7 @@ of patent rights can be found in the PATENTS file in the same directory. */ -#import +#import /** @abstract A concrete spring animation class. @@ -36,13 +36,13 @@ /** @abstract The effective bounciness. - @discussion Use in conjunction with 'springSpeed' to change animation effect. Values are converted into corresponding dynamics constants. Defined as a value in the range [0, 20]. Defaults to 4. + @discussion Use in conjunction with 'springSpeed' to change animation effect. Values are converted into corresponding dynamics constants. Higher values increase spring movement range resulting in more oscillations and springiness. Defined as a value in the range [0, 20]. Defaults to 4. */ @property (assign, nonatomic) CGFloat springBounciness; /** @abstract The effective speed. - @discussion Use in conjunction with 'springBounciness' to change animation effect. Values are converted into corresponding dynamics constants. Defined as a value in the range [0, 20]. Defaults to 12. + @discussion Use in conjunction with 'springBounciness' to change animation effect. Values are converted into corresponding dynamics constants. Higher values increase the dampening power of the spring resulting in a faster initial velocity and more rapid bounce slowdown. Defined as a value in the range [0, 20]. Defaults to 12. */ @property (assign, nonatomic) CGFloat springSpeed; diff --git a/pop/POPSpringAnimation.mm b/pop/POPSpringAnimation.mm index 10cb510a..d2997707 100644 --- a/pop/POPSpringAnimation.mm +++ b/pop/POPSpringAnimation.mm @@ -63,8 +63,10 @@ - (void)setVelocity:(id)aValue { POPPropertyAnimationState *s = __state; VectorRef vec = POPUnbox(aValue, s->valueType, s->valueCount, YES); + VectorRef origVec = POPUnbox(aValue, s->valueType, s->valueCount, YES); if (!vec_equal(vec, s->velocityVec)) { s->velocityVec = vec; + s->originalVelocityVec = origVec; if (s->tracing) { [s->tracer updateVelocity:aValue]; @@ -162,3 +164,29 @@ - (void)_appendDescription:(NSMutableString *)s debug:(BOOL)debug } @end + +@implementation POPSpringAnimation (NSCopying) + +- (instancetype)copyWithZone:(NSZone *)zone { + + POPSpringAnimation *copy = [super copyWithZone:zone]; + + if (copy) { + id velocity = POPBox(__state->originalVelocityVec, __state->valueType); + + // If velocity never gets set, then POPBox will return nil, messing up __state->valueCount. + if (velocity) { + copy.velocity = velocity; + } + + copy.springBounciness = self.springBounciness; + copy.springSpeed = self.springSpeed; + copy.dynamicsTension = self.dynamicsTension; + copy.dynamicsFriction = self.dynamicsFriction; + copy.dynamicsMass = self.dynamicsMass; + } + + return copy; +} + +@end \ No newline at end of file diff --git a/pop/POPSpringAnimationInternal.h b/pop/POPSpringAnimationInternal.h index 82df1ac1..6a72a432 100644 --- a/pop/POPSpringAnimationInternal.h +++ b/pop/POPSpringAnimationInternal.h @@ -7,9 +7,10 @@ of patent rights can be found in the PATENTS file in the same directory. */ +#import + #import "POPAnimationExtras.h" #import "POPPropertyAnimationInternal.h" -#import "POPSpringAnimation.h" struct _POPSpringAnimationState : _POPPropertyAnimationState { @@ -47,7 +48,7 @@ struct _POPSpringAnimationState : _POPPropertyAnimationState const CGFloat *previous2Values = previous2Vec->data(); for (NSUInteger idx = 0; idx < count; idx++) { - if ((fabsf(toValues[idx] - previousValues[idx]) >= t) || (fabsf(previous2Values[idx] - previousValues[idx]) >= t)) { + if ((std::abs(toValues[idx] - previousValues[idx]) >= t) || (std::abs(previous2Values[idx] - previousValues[idx]) >= t)) { return false; } } diff --git a/pop/POPSpringSolver.h b/pop/POPSpringSolver.h index 76e1cda4..6db4260f 100644 --- a/pop/POPSpringSolver.h +++ b/pop/POPSpringSolver.h @@ -9,7 +9,7 @@ #import -#import "POPVector.h" +#import namespace POP { @@ -161,7 +161,7 @@ namespace POP { return false; } - for (int idx = 0; idx < _lastState.p.size(); idx++) { + for (size_t idx = 0; idx < _lastState.p.size(); idx++) { if (fabs(_lastState.p(idx)) >= _tp) { return false; } diff --git a/pop/POPVector.h b/pop/POPVector.h index 05a4a740..32173ff8 100644 --- a/pop/POPVector.h +++ b/pop/POPVector.h @@ -10,12 +10,25 @@ #ifndef __POP__FBVector__ #define __POP__FBVector__ +#ifdef __cplusplus + #include #include -#import #import -#import "POPMath.h" + +#import +#import + +#import "POPDefines.h" + +#if SCENEKIT_SDK_AVAILABLE +#import +#endif + +#if TARGET_OS_IPHONE +#import +#endif namespace POP { @@ -226,7 +239,7 @@ namespace POP { // Equality bool operator== (T v) const { return (x == v && y == v && z = v, w = v); } - bool operator== (const Vector4 &v) const { return (x == v.x && y == v.y && z == v.z && w = v.w); } + bool operator== (const Vector4 &v) const { return (x == v.x && y == v.y && z == v.z && w == v.w); } // Inequality bool operator!= (T v) const {return (x != v || y != v || z != v || w != v); } @@ -320,6 +333,12 @@ namespace POP { CGRect cg_rect() const; static Vector *new_cg_rect(const CGRect &r); +#if TARGET_OS_IPHONE + // UIEdgeInsets support + UIEdgeInsets ui_edge_insets() const; + static Vector *new_ui_edge_insets(const UIEdgeInsets &i); +#endif + // CGAffineTransform support CGAffineTransform cg_affine_transform() const; static Vector *new_cg_affine_transform(const CGAffineTransform &t); @@ -328,6 +347,16 @@ namespace POP { CGColorRef cg_color() const CF_RETURNS_RETAINED; static Vector *new_cg_color(CGColorRef color); +#if SCENEKIT_SDK_AVAILABLE + // SCNVector3 support + SCNVector3 scn_vector3() const; + static Vector *new_scn_vector3(const SCNVector3 &vec3); + + // SCNVector4 support + SCNVector4 scn_vector4() const; + static Vector *new_scn_vector4(const SCNVector4 &vec4); +#endif + // operator overloads CGFloat &operator[](size_t i) const { NSCAssert(size() > i, @"unexpected vector size:%lu", (unsigned long)size()); @@ -342,7 +371,7 @@ namespace POP { void subRound(CGFloat sub); // Returns string description - NSString * const toString() const; + NSString * toString() const; // Operator overloads template Vector& operator= (const Vector4& other) { @@ -363,4 +392,5 @@ namespace POP { typedef std::shared_ptr VectorConstRef; } +#endif /* __cplusplus */ #endif /* defined(__POP__FBVector__) */ diff --git a/pop/POPVector.mm b/pop/POPVector.mm index f9bf1f5d..4035cb97 100644 --- a/pop/POPVector.mm +++ b/pop/POPVector.mm @@ -1,19 +1,21 @@ /** Copyright (c) 2014-present, Facebook, Inc. All rights reserved. - + This source code is licensed under the BSD-style license found in the LICENSE file in the root directory of this source tree. An additional grant of patent rights can be found in the PATENTS file in the same directory. */ #import "POPVector.h" -#import "POPAnimationRuntime.h" + +#import "POPDefines.h" #import "POPCGUtils.h" +#import "POPMath.h" namespace POP { - + Vector::Vector(const size_t count) { _count = count; @@ -28,7 +30,7 @@ memcpy(_values, other.data(), _count * sizeof(CGFloat)); } } - + Vector::~Vector() { if (NULL != _values) { @@ -37,14 +39,14 @@ } _count = 0; } - + void Vector::swap(Vector &first, Vector &second) { using std::swap; swap(first._count, second._count); swap(first._values, second._values); } - + Vector& Vector::operator=(const Vector& other) { Vector temp(other); @@ -58,7 +60,7 @@ } const CGFloat * const values = other.data(); - + for (NSUInteger idx = 0; idx < _count; idx++) { if (_values[idx] != values[idx]) { return false; @@ -72,15 +74,15 @@ if (_count == other.size()) { return false; } - + const CGFloat * const values = other.data(); - + for (NSUInteger idx = 0; idx < _count; idx++) { if (_values[idx] != values[idx]) { return false; } } - + return true; } @@ -89,7 +91,7 @@ if (0 == count) { return NULL; } - + Vector *v = new Vector(count); if (NULL != values) { memcpy(v->_values, values, count * sizeof(CGFloat)); @@ -102,7 +104,7 @@ if (NULL == other) { return NULL; } - + return Vector::new_vector(other->size(), other->data()); } @@ -115,22 +117,22 @@ Vector *v = new Vector(count); NSCAssert(count <= 4, @"unexpected count %lu", (unsigned long)count); - for (NSUInteger i = 0; i < MIN(count, 4); i++) { + for (NSUInteger i = 0; i < MIN(count, (NSUInteger)4); i++) { v->_values[i] = vec[i]; } - + return v; } Vector4r Vector::vector4r() const { Vector4r v = Vector4r::Zero(); - for (int i = 0; i < _count; i++) { + for (size_t i = 0; i < _count; i++) { v(i) = _values[i]; } return v; } - + Vector2r Vector::vector2r() const { Vector2r v = Vector2r::Zero(); @@ -138,7 +140,7 @@ if (_count > 1) v(1) = _values[1]; return v; } - + Vector *Vector::new_cg_float(CGFloat f) { Vector *v = new Vector(1); @@ -159,7 +161,7 @@ v->_values[1] = p.y; return v; } - + CGSize Vector::cg_size () const { Vector2r v = vector2r(); @@ -173,7 +175,7 @@ v->_values[1] = s.height; return v; } - + CGRect Vector::cg_rect() const { return _count < 4 ? CGRectZero : CGRectMake(_values[0], _values[1], _values[2], _values[3]); @@ -188,13 +190,32 @@ v->_values[3] = r.size.height; return v; } - + +#if TARGET_OS_IPHONE + + UIEdgeInsets Vector::ui_edge_insets() const + { + return _count < 4 ? UIEdgeInsetsZero : UIEdgeInsetsMake(_values[0], _values[1], _values[2], _values[3]); + } + + Vector *Vector::new_ui_edge_insets(const UIEdgeInsets &i) + { + Vector *v = new Vector(4); + v->_values[0] = i.top; + v->_values[1] = i.left; + v->_values[2] = i.bottom; + v->_values[3] = i.right; + return v; + } + +#endif + CGAffineTransform Vector::cg_affine_transform() const { if (_count < 6) { return CGAffineTransformIdentity; } - + NSCAssert(size() >= 6, @"unexpected vector size:%lu", (unsigned long)size()); CGAffineTransform t; t.a = _values[0]; @@ -208,7 +229,7 @@ Vector *Vector::new_cg_affine_transform(const CGAffineTransform &t) { - Vector *v = new Vector(4); + Vector *v = new Vector(6); v->_values[0] = t.a; v->_values[1] = t.b; v->_values[2] = t.c; @@ -225,7 +246,7 @@ } return POPCGColorRGBACreate(_values); } - + Vector *Vector::new_cg_color(CGColorRef color) { CGFloat rgba[4]; @@ -233,13 +254,44 @@ return new_vector(4, rgba); } +#if SCENEKIT_SDK_AVAILABLE + SCNVector3 Vector::scn_vector3() const + { + return _count < 3 ? SCNVector3Make(0.0, 0.0, 0.0) : SCNVector3Make(_values[0], _values[1], _values[2]); + } + + Vector *Vector::new_scn_vector3(const SCNVector3 &vec3) + { + Vector *v = new Vector(3); + v->_values[0] = vec3.x; + v->_values[1] = vec3.y; + v->_values[2] = vec3.z; + return v; + } + + SCNVector4 Vector::scn_vector4() const + { + return _count < 4 ? SCNVector4Make(0.0, 0.0, 0.0, 0.0) : SCNVector4Make(_values[0], _values[1], _values[2], _values[3]); + } + + Vector *Vector::new_scn_vector4(const SCNVector4 &vec4) + { + Vector *v = new Vector(4); + v->_values[0] = vec4.x; + v->_values[1] = vec4.y; + v->_values[2] = vec4.z; + v->_values[3] = vec4.w; + return v; + } +#endif + void Vector::subRound(CGFloat sub) { for (NSUInteger idx = 0; idx < _count; idx++) { _values[idx] = POPSubRound(_values[idx], sub); } } - + CGFloat Vector::norm() const { return sqrtr(squaredNorm()); @@ -254,19 +306,19 @@ return d; } - NSString * const Vector::toString() const + NSString * Vector::toString() const { if (0 == _count) return @"()"; - + if (1 == _count) return [NSString stringWithFormat:@"%f", _values[0]]; - + if (2 == _count) return [NSString stringWithFormat:@"(%.3f, %.3f)", _values[0], _values[1]]; - + NSMutableString *s = [NSMutableString stringWithCapacity:10]; - + for (NSUInteger idx = 0; idx < _count; idx++) { if (0 == idx) { [s appendFormat:@"[%.3f", _values[idx]]; @@ -276,8 +328,8 @@ [s appendFormat:@", %.3f", _values[idx]]; } } - + return s; - + } } diff --git a/pop/WebCore/TransformationMatrix.cpp b/pop/WebCore/TransformationMatrix.cpp index cbfd701c..7264ab56 100644 --- a/pop/WebCore/TransformationMatrix.cpp +++ b/pop/WebCore/TransformationMatrix.cpp @@ -25,9 +25,11 @@ */ #include "TransformationMatrix.h" -#include "FloatConversion.h" + #include +#include "FloatConversion.h" + inline double deg2rad(double d) { return d * M_PI / 180.0; } inline double rad2deg(double r) { return r * 180.0 / M_PI; } inline double deg2grad(double d) { return d * 400.0 / 360.0; } diff --git a/pop/WebCore/TransformationMatrix.h b/pop/WebCore/TransformationMatrix.h index 9dad2e9b..b99ae892 100644 --- a/pop/WebCore/TransformationMatrix.h +++ b/pop/WebCore/TransformationMatrix.h @@ -27,7 +27,9 @@ #define TransformationMatrix_h #include //for memcpy + #include + #include namespace WebCore { diff --git a/pop/en.lproj/InfoPlist.strings b/pop/en.lproj/InfoPlist.strings deleted file mode 100644 index 477b28ff..00000000 --- a/pop/en.lproj/InfoPlist.strings +++ /dev/null @@ -1,2 +0,0 @@ -/* Localized versions of Info.plist keys */ - diff --git a/pop/module.modulemap b/pop/module.modulemap new file mode 100644 index 00000000..fca69f0d --- /dev/null +++ b/pop/module.modulemap @@ -0,0 +1,6 @@ +framework module pop { + umbrella header "POP.h" + + exclude header "POPAnimationPrivate.h" + exclude header "POPAnimatorPrivate.h" +} diff --git a/pop/pop-Prefix.pch b/pop/pop-Prefix.pch deleted file mode 100644 index 43519d3c..00000000 --- a/pop/pop-Prefix.pch +++ /dev/null @@ -1,7 +0,0 @@ -// -// Prefix header for all source files of the 'POPAnimation' target in the 'POPAnimation' project -// - -#ifdef __OBJC__ - #import -#endif diff --git a/pop/pop-ios-Info.plist b/pop/pop-ios-Info.plist new file mode 100644 index 00000000..decc0dac --- /dev/null +++ b/pop/pop-ios-Info.plist @@ -0,0 +1,28 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + com.facebook.$(PRODUCT_NAME:rfc1034identifier) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + NSHumanReadableCopyright + Copyright © 2014 Facebook. All rights reserved. + NSPrincipalClass + + + diff --git a/pop/pop-Info.plist b/pop/pop-osx-Info.plist similarity index 100% rename from pop/pop-Info.plist rename to pop/pop-osx-Info.plist diff --git a/pop/pop-tvos-Info.plist b/pop/pop-tvos-Info.plist new file mode 100644 index 00000000..63f8161e --- /dev/null +++ b/pop/pop-tvos-Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + com.facebook.$(PRODUCT_NAME:rfc1034identifier) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + NSPrincipalClass + + +