Files
react-native/packages/react-native/ReactCxxPlatform/react/renderer/animated/drivers/FrameAnimationDriver.cpp
T
Samuel Susla 091eb2ea11 clean up interface of AnimationDriver (#51663)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/51663

changelog: [internal]

mark getters as noexcept const and use `get` prefix.

Reviewed By: christophpurrer

Differential Revision: D75531202

fbshipit-source-id: d66132ee3ec459e73ab3dc33c726c73d5afb6e72
2025-05-28 14:18:24 -07:00

114 lines
3.1 KiB
C++

/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/*
* Adapted from react-native-windows under the MIT license.
*/
#include "FrameAnimationDriver.h"
#include <react/debug/react_native_assert.h>
#include <react/renderer/animated/drivers/AnimationDriver.h>
#include <react/renderer/animated/drivers/AnimationDriverUtils.h>
#include <react/renderer/animated/nodes/ValueAnimatedNode.h>
#include <cmath>
#include <utility>
namespace facebook::react {
FrameAnimationDriver::FrameAnimationDriver(
int id,
Tag animatedValueTag,
std::optional<AnimationEndCallback> endCallback,
const folly::dynamic& config,
NativeAnimatedNodesManager* manager)
: AnimationDriver(
id,
animatedValueTag,
std::move(endCallback),
config,
manager) {
onConfigChanged();
}
void FrameAnimationDriver::updateConfig(folly::dynamic config) {
AnimationDriver::updateConfig(config);
onConfigChanged();
}
void FrameAnimationDriver::onConfigChanged() {
auto frames = config_["frames"];
react_native_assert(frames.type() == folly::dynamic::ARRAY);
for (const auto& frame : frames) {
auto frameValue = frame.asDouble();
frames_.push_back(frameValue);
}
toValue_ = config_["toValue"].asDouble();
}
bool FrameAnimationDriver::update(double timeDeltaMs, bool /*restarting*/) {
if (auto node =
manager_->getAnimatedNode<ValueAnimatedNode>(animatedValueTag_)) {
if (!startValue_) {
startValue_ = node->getRawValue();
}
const auto startIndex =
static_cast<size_t>(timeDeltaMs / SingleFrameIntervalMs);
assert(startIndex >= 0);
const auto nextIndex = startIndex + 1;
double nextValue = NAN;
auto isComplete = false;
if (nextIndex >= frames_.size()) {
if (iterations_ == -1 || currentIteration_ < iterations_) {
// Use last frame value, just in case it's different from toValue_
nextValue = startValue_.value() +
frames_[frames_.size() - 1] * (toValue_ - startValue_.value());
} else {
nextValue = toValue_;
}
isComplete = true;
} else {
const auto fromInterval = startIndex * SingleFrameIntervalMs;
const auto toInterval = nextIndex * SingleFrameIntervalMs;
const auto fromValue = frames_[startIndex];
const auto toValue = frames_[nextIndex];
// Map timestamp to frame value (frames_ elements are in [0,1])
const auto frameOutput = interpolate(
timeDeltaMs,
fromInterval,
toInterval,
fromValue,
toValue,
ExtrapolateTypeExtend,
ExtrapolateTypeExtend);
// Map frame to output value
nextValue = interpolate(
frameOutput,
0,
1,
startValue_.value(),
toValue_,
ExtrapolateTypeExtend,
ExtrapolateTypeExtend);
}
if (node->setRawValue(nextValue)) {
markNodeUpdated(node->tag());
}
return isComplete;
}
return true;
}
} // namespace facebook::react