/** * Copyright (c) 2017-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. */ package com.facebook.litho.dataflow; import com.facebook.litho.dataflow.springs.Spring; /** * A node that implements spring physics: it takes an initial value ("initial" input) and * end value ("end" input) and animates that value on each frame, outputting the progress over time. */ public class SpringNode extends ValueNode implements NodeCanFinish { public static final double NS_PER_SECOND = 1000_000_000.; public static final String INITIAL_INPUT = "initial"; public static final String END_INPUT = "end"; private final Spring mSpring; private long mLastFrameTimeNs = Long.MIN_VALUE; private boolean mAreParentsFinished = false; public SpringNode() { mSpring = new Spring(); } @Override public float calculateValue(long frameTimeNanos) { if (mLastFrameTimeNs == Long.MIN_VALUE) { mLastFrameTimeNs = frameTimeNanos; float initialValue = getInput(INITIAL_INPUT).getValue(); final float endValue = getInput(END_INPUT).getValue(); mSpring.setCurrentValue(initialValue); mSpring.setEndValue(endValue); return initialValue; } final float endValue = getInput(END_INPUT).getValue(); mSpring.setEndValue(endValue); if (isFinished()) { return endValue; } double timeDeltaSec = (frameTimeNanos - mLastFrameTimeNs) / NS_PER_SECOND; mSpring.advance(timeDeltaSec); mLastFrameTimeNs = frameTimeNanos; return (float) mSpring.getCurrentValue(); } @Override public boolean isFinished() { return mAreParentsFinished && mSpring.isAtRest(); } @Override public void onInputsFinished() { mAreParentsFinished = true; } }