You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
133 lines
3.4 KiB
133 lines
3.4 KiB
9 years ago
|
/**
|
||
|
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 <cmath>
|
||
|
|
||
|
#import "POPAnimationExtras.h"
|
||
|
#import "POPPropertyAnimationInternal.h"
|
||
|
|
||
|
struct _POPSpringAnimationState : _POPPropertyAnimationState
|
||
|
{
|
||
|
SpringSolver4d *solver;
|
||
|
CGFloat springSpeed;
|
||
|
CGFloat springBounciness; // normalized springiness
|
||
|
CGFloat dynamicsTension; // tension
|
||
|
CGFloat dynamicsFriction; // friction
|
||
|
CGFloat dynamicsMass; // mass
|
||
|
|
||
|
_POPSpringAnimationState(id __unsafe_unretained anim) : _POPPropertyAnimationState(anim),
|
||
|
solver(nullptr),
|
||
|
springSpeed(12.),
|
||
|
springBounciness(4.),
|
||
|
dynamicsTension(0),
|
||
|
dynamicsFriction(0),
|
||
|
dynamicsMass(0)
|
||
|
{
|
||
|
type = kPOPAnimationSpring;
|
||
|
}
|
||
|
|
||
|
bool hasConverged()
|
||
|
{
|
||
|
NSUInteger count = valueCount;
|
||
|
if (shouldRound()) {
|
||
|
return vec_equal(previous2Vec, previousVec) && vec_equal(previousVec, toVec);
|
||
|
} else {
|
||
|
if (!previousVec || !previous2Vec)
|
||
|
return false;
|
||
|
|
||
|
CGFloat t = dynamicsThreshold / 5;
|
||
|
|
||
|
const CGFloat *toValues = toVec->data();
|
||
|
const CGFloat *previousValues = previousVec->data();
|
||
|
const CGFloat *previous2Values = previous2Vec->data();
|
||
|
|
||
|
for (NSUInteger idx = 0; idx < count; idx++) {
|
||
|
if ((std::abs(toValues[idx] - previousValues[idx]) >= t) || (std::abs(previous2Values[idx] - previousValues[idx]) >= t)) {
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
bool isDone() {
|
||
|
if (_POPPropertyAnimationState::isDone()) {
|
||
|
return true;
|
||
|
}
|
||
|
return solver->started() && (hasConverged() || solver->hasConverged());
|
||
|
}
|
||
|
|
||
|
void updatedDynamics()
|
||
|
{
|
||
|
if (NULL != solver) {
|
||
|
solver->setConstants(dynamicsTension, dynamicsFriction, dynamicsMass);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void updatedDynamicsThreshold()
|
||
|
{
|
||
|
_POPPropertyAnimationState::updatedDynamicsThreshold();
|
||
|
if (NULL != solver) {
|
||
|
solver->setThreshold(dynamicsThreshold);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void updatedBouncinessAndSpeed() {
|
||
|
[POPSpringAnimation convertBounciness:springBounciness speed:springSpeed toTension:&dynamicsTension friction:&dynamicsFriction mass:&dynamicsMass];
|
||
|
updatedDynamics();
|
||
|
}
|
||
|
|
||
|
bool advance(CFTimeInterval time, CFTimeInterval dt, id obj) {
|
||
|
// advance past not yet initialized animations
|
||
|
if (NULL == currentVec) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
CFTimeInterval localTime = time - startTime;
|
||
|
|
||
|
Vector4d value = vector4d(currentVec);
|
||
|
Vector4d toValue = vector4d(toVec);
|
||
|
Vector4d velocity = vector4d(velocityVec);
|
||
|
|
||
|
SSState4d state;
|
||
|
state.p = toValue - value;
|
||
|
|
||
|
// the solver assumes a spring of size zero
|
||
|
// flip the velocity from user perspective to solver perspective
|
||
|
state.v = velocity * -1;
|
||
|
|
||
|
solver->advance(state, localTime, dt);
|
||
|
value = toValue - state.p;
|
||
|
|
||
|
// flip velocity back to user perspective
|
||
|
velocity = state.v * -1;
|
||
|
|
||
|
*currentVec = value;
|
||
|
|
||
|
if (velocityVec) {
|
||
|
*velocityVec = velocity;
|
||
|
}
|
||
|
|
||
|
clampCurrentValue();
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
virtual void reset(bool all) {
|
||
|
_POPPropertyAnimationState::reset(all);
|
||
|
|
||
|
if (solver) {
|
||
|
solver->setConstants(dynamicsTension, dynamicsFriction, dynamicsMass);
|
||
|
solver->reset();
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
|
||
|
typedef struct _POPSpringAnimationState POPSpringAnimationState;
|