first commit

This commit is contained in:
2026-03-10 16:18:05 +00:00
commit 11f9c069b5
31635 changed files with 3187747 additions and 0 deletions

View File

@@ -0,0 +1,30 @@
/*
* 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 "AdditionAnimatedNode.h"
#include <react/debug/react_native_assert.h>
#include <react/renderer/animated/NativeAnimatedNodesManager.h>
namespace facebook::react {
void AdditionAnimatedNode::update() {
auto rawValue = 0.0;
for (const auto tag : inputNodes_) {
const auto node = manager_->getAnimatedNode<ValueAnimatedNode>(tag);
react_native_assert(
node && "Invalid node tag set as input for AdditionAnimatedNode");
rawValue += node->getValue();
}
setRawValue(rawValue);
}
} // namespace facebook::react

View File

@@ -0,0 +1,28 @@
/*
* 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.
*/
#pragma once
#include "ValueAnimatedNode.h"
namespace facebook::react {
class AdditionAnimatedNode final : public OperatorAnimatedNode {
public:
AdditionAnimatedNode(Tag tag, const folly::dynamic &config, NativeAnimatedNodesManager &manager)
: OperatorAnimatedNode(tag, config, manager)
{
}
void update() override;
};
} // namespace facebook::react

View File

@@ -0,0 +1,83 @@
/*
* 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 "AnimatedNode.h"
#include <react/renderer/animated/NativeAnimatedNodesManager.h>
#include <utility>
namespace facebook::react {
AnimatedNode::AnimatedNode(
Tag tag,
folly::dynamic config,
NativeAnimatedNodesManager& manager,
AnimatedNodeType type)
: tag_(tag), manager_(&manager), type_(type), config_(std::move(config)) {}
void AnimatedNode::addChild(const Tag animatedNodeTag) {
children_.insert(animatedNodeTag);
getChildNode(animatedNodeTag)->onAttachToNode(tag_);
}
void AnimatedNode::removeChild(const Tag tag) {
if (const auto childNode = getChildNode(tag)) {
childNode->onDetachedFromNode(tag_);
children_.erase(tag);
}
}
AnimatedNode* AnimatedNode::getChildNode(Tag tag) {
if (children_.find(tag) != children_.end()) {
return manager_->getAnimatedNode<AnimatedNode>(tag);
}
return nullptr;
}
std::optional<AnimatedNodeType> AnimatedNode::getNodeTypeByName(
const std::string& nodeTypeName) {
if (nodeTypeName == "style") {
return AnimatedNodeType::Style;
} else if (nodeTypeName == "value") {
return AnimatedNodeType::Value;
} else if (nodeTypeName == "color") {
return AnimatedNodeType::Color;
} else if (nodeTypeName == "props") {
return AnimatedNodeType::Props;
} else if (nodeTypeName == "interpolation") {
return AnimatedNodeType::Interpolation;
} else if (nodeTypeName == "addition") {
return AnimatedNodeType::Addition;
} else if (nodeTypeName == "subtraction") {
return AnimatedNodeType::Subtraction;
} else if (nodeTypeName == "division") {
return AnimatedNodeType::Division;
} else if (nodeTypeName == "multiplication") {
return AnimatedNodeType::Multiplication;
} else if (nodeTypeName == "modulus") {
return AnimatedNodeType::Modulus;
} else if (nodeTypeName == "diffclamp") {
return AnimatedNodeType::Diffclamp;
} else if (nodeTypeName == "transform") {
return AnimatedNodeType::Transform;
} else if (nodeTypeName == "tracking") {
return AnimatedNodeType::Tracking;
} else if (nodeTypeName == "round") {
return AnimatedNodeType::Round;
} else if (nodeTypeName == "object") {
return AnimatedNodeType::Object;
} else {
return std::nullopt;
}
}
} // namespace facebook::react

View File

@@ -0,0 +1,112 @@
/*
* 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.
*/
#pragma once
#include <folly/dynamic.h>
#include <react/debug/flags.h>
#include <react/renderer/core/ReactPrimitives.h>
namespace facebook::react {
enum class AnimatedNodeType {
Style,
Value,
Props,
Interpolation,
Addition,
Subtraction,
Division,
Multiplication,
Modulus,
Diffclamp,
Transform,
Tracking,
Color,
Round,
Object
};
class NativeAnimatedNodesManager;
class AnimatedNode {
public:
AnimatedNode(
Tag tag,
folly::dynamic config,
// TODO: T190028913 maybe pass in strongly typed data when constructing
// AnimatedNode
NativeAnimatedNodesManager &manager,
AnimatedNodeType type);
// Detach Node
virtual ~AnimatedNode() = default;
AnimatedNode(AnimatedNode &&) noexcept = default;
AnimatedNode &operator=(AnimatedNode &&) noexcept = default;
AnimatedNode(const AnimatedNode &) = default;
AnimatedNode &operator=(const AnimatedNode &) = default;
Tag tag() const noexcept
{
return tag_;
}
void addChild(Tag tag);
void removeChild(Tag tag);
const std::unordered_set<Tag> &getChildren() const noexcept
{
return children_;
}
AnimatedNodeType type() const noexcept
{
return type_;
}
const folly::dynamic &getConfig() const noexcept
{
return config_;
}
#ifdef REACT_NATIVE_DEBUG
std::string debugID() const
{
return (getConfig().count("debugID") != 0u) ? getConfig()["debugID"].asString() : "";
}
#endif
virtual void update() {}
virtual void onDetachedFromNode(Tag /*animatedNodeTag*/) {}
virtual void onAttachToNode(Tag /*animatedNodeTag*/) {}
static std::optional<AnimatedNodeType> getNodeTypeByName(const std::string &nodeTypeName);
int activeIncomingNodes = 0;
int bfsColor = 0;
static constexpr int INITIAL_BFS_COLOR = 0;
protected:
AnimatedNode *getChildNode(Tag tag);
Tag tag_{0};
NativeAnimatedNodesManager *manager_;
AnimatedNodeType type_;
std::unordered_set<Tag> children_{};
private:
// Should remain unchanged after initialized in constructor
folly::dynamic config_;
};
} // namespace facebook::react

View File

@@ -0,0 +1,68 @@
/*
* 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 "ColorAnimatedNode.h"
#include <react/renderer/animated/NativeAnimatedNodesManager.h>
#include <react/renderer/animated/nodes/ValueAnimatedNode.h>
namespace facebook::react {
namespace {
uint8_t getColorValue(
const NativeAnimatedNodesManager& manager,
Tag nodeTag,
bool isDecimal = false) {
if (const auto node = manager.getAnimatedNode<ValueAnimatedNode>(nodeTag)) {
if (isDecimal) {
return std::clamp(
static_cast<uint32_t>(node->getValue() * 255), 0u, 255u);
} else {
return std::clamp(static_cast<uint32_t>(node->getValue()), 0u, 255u);
}
}
return 0;
}
uint8_t getAlphaValue(const NativeAnimatedNodesManager& manager, Tag nodeTag) {
return getColorValue(manager, nodeTag, true);
}
} // namespace
ColorAnimatedNode::ColorAnimatedNode(
Tag tag,
const folly::dynamic& config,
NativeAnimatedNodesManager& manager)
: AnimatedNode(tag, config, manager, AnimatedNodeType::Color),
rNodeTag_(static_cast<Tag>(getConfig()["r"].asInt())),
gNodeTag_(static_cast<Tag>(getConfig()["g"].asInt())),
bNodeTag_(static_cast<Tag>(getConfig()["b"].asInt())),
aNodeTag_(static_cast<Tag>(getConfig()["a"].asInt())) {}
void ColorAnimatedNode::update() {
color_ = *colorFromRGBA(
getColorValue(*manager_, rNodeTag_),
getColorValue(*manager_, gNodeTag_),
getColorValue(*manager_, bNodeTag_),
getAlphaValue(*manager_, aNodeTag_));
}
Color ColorAnimatedNode::getColor() {
if (manager_->updatedNodeTags_.contains(tag_)) {
update();
manager_->updatedNodeTags_.erase(tag_);
}
return color_;
return 0;
}
} // namespace facebook::react

View File

@@ -0,0 +1,35 @@
/*
* 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.
*/
#pragma once
#include "AnimatedNode.h"
#include <react/renderer/graphics/Color.h>
namespace facebook::react {
class ColorAnimatedNode final : public AnimatedNode {
public:
ColorAnimatedNode(Tag tag, const folly::dynamic &config, NativeAnimatedNodesManager &manager);
void update() override;
Color getColor();
private:
Tag rNodeTag_{};
Tag gNodeTag_{};
Tag bNodeTag_{};
Tag aNodeTag_{};
Color color_{0};
};
} // namespace facebook::react

View File

@@ -0,0 +1,37 @@
/*
* 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 "DiffClampAnimatedNode.h"
#include <react/renderer/animated/NativeAnimatedNodesManager.h>
namespace facebook::react {
DiffClampAnimatedNode::DiffClampAnimatedNode(
Tag tag,
const folly::dynamic& config,
NativeAnimatedNodesManager& manager)
: ValueAnimatedNode(tag, config, manager),
inputNodeTag_(static_cast<Tag>(getConfig()["input"].asDouble())),
min_(getConfig()["min"].asDouble()),
max_(getConfig()["max"].asDouble()) {}
void DiffClampAnimatedNode::update() {
if (const auto node =
manager_->getAnimatedNode<ValueAnimatedNode>(inputNodeTag_)) {
const auto value = node->getValue();
const auto diff = value - lastValue_;
lastValue_ = value;
setRawValue(std::clamp(this->getValue() + diff, min_, max_));
}
}
} // namespace facebook::react

View File

@@ -0,0 +1,31 @@
/*
* 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.
*/
#pragma once
#include "ValueAnimatedNode.h"
namespace facebook::react {
class DiffClampAnimatedNode final : public ValueAnimatedNode {
public:
DiffClampAnimatedNode(Tag tag, const folly::dynamic &config, NativeAnimatedNodesManager &manager);
void update() override;
private:
Tag inputNodeTag_;
double min_;
double max_;
double lastValue_{0};
};
} // namespace facebook::react

View File

@@ -0,0 +1,37 @@
/*
* 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 "DivisionAnimatedNode.h"
#include <react/debug/react_native_assert.h>
#include <react/renderer/animated/NativeAnimatedNodesManager.h>
namespace facebook::react {
void DivisionAnimatedNode::update() {
auto rawValue = 0.0;
int count = 0;
for (const auto tag : inputNodes_) {
const auto node = manager_->getAnimatedNode<ValueAnimatedNode>(tag);
react_native_assert(
node && "Invalid node tag set as input for DivisionAnimatedNode");
if (count == 0) {
rawValue = node->getValue();
} else {
rawValue /= node->getValue();
}
count++;
}
setRawValue(rawValue);
}
} // namespace facebook::react

View File

@@ -0,0 +1,28 @@
/*
* 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.
*/
#pragma once
#include "ValueAnimatedNode.h"
namespace facebook::react {
class DivisionAnimatedNode final : public OperatorAnimatedNode {
public:
DivisionAnimatedNode(Tag tag, const folly::dynamic &config, NativeAnimatedNodesManager &manager)
: OperatorAnimatedNode(tag, config, manager)
{
}
void update() override;
};
} // namespace facebook::react

View File

@@ -0,0 +1,144 @@
/*
* 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 "InterpolationAnimatedNode.h"
#include <react/renderer/animated/NativeAnimatedNodesManager.h>
#include <react/renderer/animated/drivers/AnimationDriverUtils.h>
#include <react/renderer/animated/internal/primitives.h>
#include <react/renderer/graphics/HostPlatformColor.h>
namespace facebook::react {
InterpolationAnimatedNode::InterpolationAnimatedNode(
Tag tag,
const folly::dynamic& config,
NativeAnimatedNodesManager& manager)
: ValueAnimatedNode(tag, config, manager) {
// inputRange example: [0, 1, 10], [1, 1.4, 1.5]
const auto& nodeConfig = getConfig();
for (const auto& rangeValue : nodeConfig["inputRange"]) {
inputRanges_.push_back(rangeValue.asDouble());
}
const bool isColorOutput = nodeConfig["outputType"].isString() &&
nodeConfig["outputType"].asString() == "color";
if (isColorOutput) {
isColorValue_ = true;
for (const auto& rangeValue : nodeConfig["outputRange"]) {
colorOutputRanges_.push_back(static_cast<int>(rangeValue.asInt()));
}
} else {
for (const auto& rangeValue : nodeConfig["outputRange"]) {
defaultOutputRanges_.push_back(rangeValue.asDouble());
}
}
extrapolateLeft_ = nodeConfig["extrapolateLeft"].asString();
extrapolateRight_ = nodeConfig["extrapolateRight"].asString();
}
void InterpolationAnimatedNode::update() {
if (parentTag_ == animated::undefinedAnimatedNodeIdentifier) {
return;
}
if (const auto node =
manager_->getAnimatedNode<ValueAnimatedNode>(parentTag_)) {
if (isColorValue_) {
setRawValue(interpolateColor(node->getValue()));
} else {
setRawValue(interpolateValue(node->getValue()));
}
}
}
void InterpolationAnimatedNode::onDetachedFromNode(Tag animatedNodeTag) {
assert(parentTag_ == animatedNodeTag);
parentTag_ = animated::undefinedAnimatedNodeIdentifier;
}
void InterpolationAnimatedNode::onAttachToNode(Tag animatedNodeTag) {
assert(!parentTag_);
parentTag_ = animatedNodeTag;
}
double InterpolationAnimatedNode::interpolateValue(double value) {
// Compute range index
int index = 1;
for (; index < inputRanges_.size() - 1; ++index) {
if (inputRanges_[index] >= value) {
break;
}
}
index--;
return interpolate(
value,
inputRanges_[index],
inputRanges_[index + 1],
defaultOutputRanges_[index],
defaultOutputRanges_[index + 1],
extrapolateLeft_,
extrapolateRight_);
}
double InterpolationAnimatedNode::interpolateColor(double value) {
// Compute range index
int index = 1;
for (; index < inputRanges_.size() - 1; ++index) {
if (inputRanges_[index] >= value) {
break;
}
}
index--;
const auto outputMin = colorOutputRanges_[index];
const auto outputMax = colorOutputRanges_[index + 1];
if (outputMin == outputMax) {
return outputMin;
}
const auto inputMin = inputRanges_[index];
const auto inputMax = inputRanges_[index + 1];
if (inputMin == inputMax) {
if (value <= inputMin) {
return static_cast<int32_t>(outputMin);
} else {
return static_cast<int32_t>(outputMax);
}
}
auto ratio = (value - inputMin) / (inputMax - inputMin);
auto outputMinA = alphaFromHostPlatformColor(outputMin);
auto outputMinR = redFromHostPlatformColor(outputMin);
auto outputMinG = greenFromHostPlatformColor(outputMin);
auto outputMinB = blueFromHostPlatformColor(outputMin);
auto outputMaxA = alphaFromHostPlatformColor(outputMax);
auto outputMaxR = redFromHostPlatformColor(outputMax);
auto outputMaxG = greenFromHostPlatformColor(outputMax);
auto outputMaxB = blueFromHostPlatformColor(outputMax);
auto outputValueA = ratio * (outputMaxA - outputMinA) + outputMinA;
auto outputValueR = ratio * (outputMaxR - outputMinR) + outputMinR;
auto outputValueG = ratio * (outputMaxG - outputMinG) + outputMinG;
auto outputValueB = ratio * (outputMaxB - outputMinB) + outputMinB;
return static_cast<int32_t>(hostPlatformColorFromRGBA(
static_cast<uint8_t>(outputValueR),
static_cast<uint8_t>(outputValueG),
static_cast<uint8_t>(outputValueB),
static_cast<uint8_t>(outputValueA)));
}
} // namespace facebook::react

View File

@@ -0,0 +1,41 @@
/*
* 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.
*/
#pragma once
#include "ValueAnimatedNode.h"
#include <react/renderer/animated/internal/primitives.h>
#include <react/renderer/graphics/Color.h>
namespace facebook::react {
class InterpolationAnimatedNode final : public ValueAnimatedNode {
public:
InterpolationAnimatedNode(Tag tag, const folly::dynamic &config, NativeAnimatedNodesManager &manager);
void update() override;
void onDetachedFromNode(Tag animatedNodeTag) override;
void onAttachToNode(Tag animatedNodeTag) override;
private:
double interpolateValue(double value);
double interpolateColor(double value);
std::vector<double> inputRanges_;
std::vector<double> defaultOutputRanges_;
std::vector<Color> colorOutputRanges_;
std::string extrapolateLeft_;
std::string extrapolateRight_;
Tag parentTag_{animated::undefinedAnimatedNodeIdentifier};
};
} // namespace facebook::react

View File

@@ -0,0 +1,33 @@
/*
* 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 "ModulusAnimatedNode.h"
#include <react/renderer/animated/NativeAnimatedNodesManager.h>
namespace facebook::react {
ModulusAnimatedNode::ModulusAnimatedNode(
Tag tag,
const folly::dynamic& config,
NativeAnimatedNodesManager& manager)
: ValueAnimatedNode(tag, config, manager),
inputNodeTag_(static_cast<Tag>(getConfig()["input"].asInt())),
modulus_(getConfig()["modulus"].asDouble()) {}
void ModulusAnimatedNode::update() {
if (const auto node =
manager_->getAnimatedNode<ValueAnimatedNode>(inputNodeTag_)) {
setRawValue(std::fmod(node->getValue(), modulus_));
}
}
} // namespace facebook::react

View File

@@ -0,0 +1,29 @@
/*
* 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.
*/
#pragma once
#include "ValueAnimatedNode.h"
namespace facebook::react {
class ModulusAnimatedNode final : public ValueAnimatedNode {
public:
ModulusAnimatedNode(Tag tag, const folly::dynamic &config, NativeAnimatedNodesManager &manager);
void update() override;
private:
Tag inputNodeTag_{};
double modulus_{};
};
} // namespace facebook::react

View File

@@ -0,0 +1,36 @@
/*
* 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 "MultiplicationAnimatedNode.h"
#include <react/debug/react_native_assert.h>
#include <react/renderer/animated/NativeAnimatedNodesManager.h>
namespace facebook::react {
void MultiplicationAnimatedNode::update() {
auto rawValue = 0.0;
int count = 0;
for (const auto tag : inputNodes_) {
const auto node = manager_->getAnimatedNode<ValueAnimatedNode>(tag);
react_native_assert(
node && "Invalid node tag set as input for MultiplicationAnimatedNode");
if (count == 0) {
rawValue = node->getValue();
} else {
rawValue *= node->getValue();
}
count++;
}
setRawValue(rawValue);
}
} // namespace facebook::react

View File

@@ -0,0 +1,28 @@
/*
* 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.
*/
#pragma once
#include "ValueAnimatedNode.h"
namespace facebook::react {
class MultiplicationAnimatedNode final : public OperatorAnimatedNode {
public:
MultiplicationAnimatedNode(Tag tag, const folly::dynamic &config, NativeAnimatedNodesManager &manager)
: OperatorAnimatedNode(tag, config, manager)
{
}
void update() override;
};
} // namespace facebook::react

View File

@@ -0,0 +1,121 @@
/*
* 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 "ObjectAnimatedNode.h"
#include <glog/logging.h>
#include <react/renderer/animated/NativeAnimatedNodesManager.h>
#include <react/renderer/animated/internal/NativeAnimatedAllowlist.h>
#include <react/renderer/animated/nodes/ColorAnimatedNode.h>
#include <react/renderer/animated/nodes/TransformAnimatedNode.h>
#include <react/renderer/animated/nodes/ValueAnimatedNode.h>
namespace facebook::react {
ObjectAnimatedNode::ObjectAnimatedNode(
Tag tag,
const folly::dynamic& config,
NativeAnimatedNodesManager& manager)
: AnimatedNode(tag, config, manager, AnimatedNodeType::Object) {}
void ObjectAnimatedNode::collectViewUpdates(
std::string propKey,
folly::dynamic& props) {
const auto& value = getConfig()["value"];
switch (value.type()) {
case folly::dynamic::OBJECT: {
props.insert(propKey, collectViewUpdatesObjectHelper(value));
} break;
case folly::dynamic::ARRAY: {
props.insert(propKey, collectViewUpdatesArrayHelper(value));
} break;
default: {
LOG(ERROR) << "Invalid value type for ObjectAnimatedNode";
} break;
}
}
folly::dynamic ObjectAnimatedNode::collectViewUpdatesObjectHelper(
const folly::dynamic& value) const {
folly::dynamic result = folly::dynamic::object();
for (const auto& valueProp : value.items()) {
result.insert(valueProp.first.asString(), getValueProp(valueProp.second));
}
return result;
}
folly::dynamic ObjectAnimatedNode::collectViewUpdatesArrayHelper(
const folly::dynamic& value) const {
folly::dynamic result = folly::dynamic::array();
for (const auto& valueProp : value) {
result.push_back(getValueProp(valueProp));
}
return result;
}
folly::dynamic ObjectAnimatedNode::getValueProp(
const folly::dynamic& prop) const {
switch (prop.type()) {
case folly::dynamic::OBJECT: {
if (auto itNodeTag = prop.find("nodeTag");
itNodeTag != prop.items().end()) {
auto nodeTag = static_cast<Tag>(itNodeTag->second.asInt());
if (auto node = manager_->getAnimatedNode<AnimatedNode>(nodeTag)) {
switch (node->type()) {
case AnimatedNodeType::Value:
case AnimatedNodeType::Interpolation:
case AnimatedNodeType::Modulus:
case AnimatedNodeType::Round:
case AnimatedNodeType::Diffclamp:
// Operators
case AnimatedNodeType::Addition:
case AnimatedNodeType::Subtraction:
case AnimatedNodeType::Multiplication:
case AnimatedNodeType::Division: {
if (const auto valueNode =
manager_->getAnimatedNode<ValueAnimatedNode>(nodeTag)) {
if (valueNode->getIsColorValue()) {
return static_cast<int32_t>(valueNode->getValue());
} else {
return valueNode->getValue();
}
}
} break;
case AnimatedNodeType::Color: {
if (const auto colorAnimNode =
manager_->getAnimatedNode<ColorAnimatedNode>(nodeTag)) {
return static_cast<int32_t>(colorAnimNode->getColor());
}
} break;
default:
break;
}
}
} else {
return collectViewUpdatesObjectHelper(prop);
}
} break;
case folly::dynamic::ARRAY: {
return collectViewUpdatesArrayHelper(prop);
};
case folly::dynamic::NULLT:
case folly::dynamic::BOOL:
case folly::dynamic::DOUBLE:
case folly::dynamic::INT64:
case folly::dynamic::STRING: {
return prop;
};
}
LOG(ERROR) << "Invalid prop type for ObjectAnimatedNode";
return nullptr;
}
} // namespace facebook::react

View File

@@ -0,0 +1,33 @@
/*
* 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.
*/
#pragma once
#include "AnimatedNode.h"
#include <folly/dynamic.h>
namespace facebook::react {
class ObjectAnimatedNode final : public AnimatedNode {
public:
ObjectAnimatedNode(Tag tag, const folly::dynamic &config, NativeAnimatedNodesManager &manager);
void collectViewUpdates(std::string propKey, folly::dynamic &props);
private:
folly::dynamic collectViewUpdatesObjectHelper(const folly::dynamic &value) const;
folly::dynamic collectViewUpdatesArrayHelper(const folly::dynamic &value) const;
folly::dynamic getValueProp(const folly::dynamic &prop) const;
};
} // namespace facebook::react

View File

@@ -0,0 +1,150 @@
/*
* 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 "PropsAnimatedNode.h"
#include <react/debug/react_native_assert.h>
#include <react/renderer/animated/NativeAnimatedNodesManager.h>
#include <react/renderer/animated/nodes/ColorAnimatedNode.h>
#include <react/renderer/animated/nodes/ObjectAnimatedNode.h>
#include <react/renderer/animated/nodes/StyleAnimatedNode.h>
#include <react/renderer/animated/nodes/ValueAnimatedNode.h>
namespace facebook::react {
namespace {
bool isLayoutStyleUpdated(
const folly::dynamic& props,
NativeAnimatedNodesManager& manager) {
for (const auto& entry : props.items()) {
auto nodeTag = static_cast<Tag>(entry.second.asInt());
if (const auto& node = manager.getAnimatedNode<AnimatedNode>(nodeTag)) {
if (node->type() == AnimatedNodeType::Style) {
if (const auto& styleNode =
manager.getAnimatedNode<StyleAnimatedNode>(nodeTag)) {
if (styleNode->isLayoutStyleUpdated()) {
return true;
}
}
}
}
}
return false;
}
} // namespace
PropsAnimatedNode::PropsAnimatedNode(
Tag tag,
const folly::dynamic& config,
NativeAnimatedNodesManager& manager)
: AnimatedNode(tag, config, manager, AnimatedNodeType::Props),
props_(folly::dynamic::object()) {}
void PropsAnimatedNode::connectToView(Tag viewTag) {
react_native_assert(
connectedViewTag_ == animated::undefinedAnimatedNodeIdentifier &&
"Animated node has already been attached to a view already exists.");
connectedViewTag_ = viewTag;
}
void PropsAnimatedNode::disconnectFromView(Tag viewTag) {
react_native_assert(
connectedViewTag_ == viewTag &&
"Attempting to disconnect view that has not been connected with the given animated node.");
connectedViewTag_ = animated::undefinedAnimatedNodeIdentifier;
}
// restore the value to whatever the value was on the ShadowNode instead of in
// the View hierarchy
void PropsAnimatedNode::restoreDefaultValues() {
// If node is already disconnected from View, we cannot restore default values
if (connectedViewTag_ != animated::undefinedAnimatedNodeIdentifier) {
manager_->schedulePropsCommit(
connectedViewTag_, folly::dynamic::object(), false, false);
}
}
void PropsAnimatedNode::update() {
return update(false);
}
void PropsAnimatedNode::update(bool forceFabricCommit) {
if (connectedViewTag_ == animated::undefinedAnimatedNodeIdentifier) {
return;
}
// TODO: T190192206 consolidate shared update logic between
// Props/StyleAnimatedNode
std::lock_guard<std::mutex> lock(propsMutex_);
const auto& configProps = getConfig()["props"];
for (const auto& entry : configProps.items()) {
auto propName = entry.first.asString();
auto nodeTag = static_cast<Tag>(entry.second.asInt());
if (auto node = manager_->getAnimatedNode<AnimatedNode>(nodeTag)) {
switch (node->type()) {
case AnimatedNodeType::Value:
case AnimatedNodeType::Interpolation:
case AnimatedNodeType::Modulus:
case AnimatedNodeType::Round:
case AnimatedNodeType::Diffclamp:
// Operators
case AnimatedNodeType::Addition:
case AnimatedNodeType::Subtraction:
case AnimatedNodeType::Multiplication:
case AnimatedNodeType::Division: {
if (const auto& valueNode =
manager_->getAnimatedNode<ValueAnimatedNode>(nodeTag)) {
if (valueNode->getIsColorValue()) {
props_.insert(
propName.c_str(),
static_cast<int32_t>(valueNode->getValue()));
} else {
props_.insert(propName.c_str(), valueNode->getValue());
}
}
} break;
case AnimatedNodeType::Color: {
if (const auto& colorNode =
manager_->getAnimatedNode<ColorAnimatedNode>(nodeTag)) {
props_.insert(
propName.c_str(), static_cast<int32_t>(colorNode->getColor()));
}
} break;
case AnimatedNodeType::Style: {
if (const auto& styleNode =
manager_->getAnimatedNode<StyleAnimatedNode>(nodeTag)) {
styleNode->collectViewUpdates(props_);
}
} break;
case AnimatedNodeType::Object: {
if (const auto objectNode =
manager_->getAnimatedNode<ObjectAnimatedNode>(nodeTag)) {
objectNode->collectViewUpdates(propName, props_);
}
} break;
case AnimatedNodeType::Props:
case AnimatedNodeType::Tracking:
case AnimatedNodeType::Transform:
break;
}
}
}
layoutStyleUpdated_ = isLayoutStyleUpdated(getConfig()["props"], *manager_);
manager_->schedulePropsCommit(
connectedViewTag_, props_, layoutStyleUpdated_, forceFabricCommit);
}
} // namespace facebook::react

View File

@@ -0,0 +1,49 @@
/*
* 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.
*/
#pragma once
#include "AnimatedNode.h"
#include <react/renderer/animated/internal/primitives.h>
#include <mutex>
namespace facebook::react {
class PropsAnimatedNode final : public AnimatedNode {
public:
PropsAnimatedNode(Tag tag, const folly::dynamic &config, NativeAnimatedNodesManager &manager);
void connectToView(Tag viewTag);
void disconnectFromView(Tag viewTag);
void restoreDefaultValues();
Tag connectedViewTag() const
{
return connectedViewTag_;
}
folly::dynamic props()
{
std::lock_guard<std::mutex> lock(propsMutex_);
return props_;
}
void update() override;
void update(bool forceFabricCommit);
private:
std::mutex propsMutex_;
folly::dynamic props_;
bool layoutStyleUpdated_{false};
Tag connectedViewTag_{animated::undefinedAnimatedNodeIdentifier};
};
} // namespace facebook::react

View File

@@ -0,0 +1,38 @@
/*
* 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 "RoundAnimatedNode.h"
#include <react/debug/react_native_assert.h>
#include <react/renderer/animated/NativeAnimatedNodesManager.h>
namespace facebook::react {
RoundAnimatedNode::RoundAnimatedNode(
Tag tag,
const folly::dynamic& config,
NativeAnimatedNodesManager& manager)
: ValueAnimatedNode(tag, config, manager),
inputNodeTag_(static_cast<Tag>(getConfig()["input"].asInt())),
nearest_(getConfig()["input"].asDouble()) {
react_native_assert(
nearest_ != 0 &&
"'nearest' cannot be 0 (can't round to the nearest multiple of 0)");
}
void RoundAnimatedNode::update() {
auto node = manager_->getAnimatedNode<ValueAnimatedNode>(inputNodeTag_);
react_native_assert(
node && "Illegal node ID set as an input for Animated.round node");
setRawValue(round(node->getValue() / nearest_) * nearest_);
}
} // namespace facebook::react

View File

@@ -0,0 +1,35 @@
/*
* 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.
*/
#pragma once
#include "ValueAnimatedNode.h"
#include <react/renderer/animated/NativeAnimatedNodesManager.h>
namespace facebook::react {
/**
* Animated node that rounds the value of another animated node to the nearest
* multiple of a given number.
*/
class RoundAnimatedNode : public ValueAnimatedNode {
public:
RoundAnimatedNode(Tag tag, const folly::dynamic &config, NativeAnimatedNodesManager &manager);
void update() override;
private:
Tag inputNodeTag_;
double nearest_;
};
} // namespace facebook::react

View File

@@ -0,0 +1,103 @@
/*
* 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 "StyleAnimatedNode.h"
#include <react/renderer/animated/NativeAnimatedNodesManager.h>
#include <react/renderer/animated/internal/NativeAnimatedAllowlist.h>
#include <react/renderer/animated/nodes/ColorAnimatedNode.h>
#include <react/renderer/animated/nodes/ObjectAnimatedNode.h>
#include <react/renderer/animated/nodes/TransformAnimatedNode.h>
#include <react/renderer/animated/nodes/ValueAnimatedNode.h>
namespace facebook::react {
namespace {
bool isLayoutPropsUpdated(const folly::dynamic& props) {
for (const auto& styleNodeProp : props.items()) {
if (getDirectManipulationAllowlist().count(
styleNodeProp.first.asString()) == 0u) {
return true;
}
}
return false;
}
} // namespace
StyleAnimatedNode::StyleAnimatedNode(
Tag tag,
const folly::dynamic& config,
NativeAnimatedNodesManager& manager)
: AnimatedNode(tag, config, manager, AnimatedNodeType::Style) {}
void StyleAnimatedNode::collectViewUpdates(folly::dynamic& props) {
const auto& style = getConfig()["style"];
for (const auto& styleProp : style.items()) {
auto propName = styleProp.first.asString();
const auto nodeTag = static_cast<Tag>(styleProp.second.asInt());
if (auto node = manager_->getAnimatedNode<AnimatedNode>(nodeTag)) {
switch (node->type()) {
case AnimatedNodeType::Transform: {
if (const auto transformNode =
manager_->getAnimatedNode<TransformAnimatedNode>(nodeTag)) {
transformNode->collectViewUpdates(props);
}
} break;
case AnimatedNodeType::Value:
case AnimatedNodeType::Interpolation:
case AnimatedNodeType::Modulus:
case AnimatedNodeType::Round:
case AnimatedNodeType::Diffclamp:
// Operators
case AnimatedNodeType::Addition:
case AnimatedNodeType::Subtraction:
case AnimatedNodeType::Multiplication:
case AnimatedNodeType::Division: {
if (const auto valueNode =
manager_->getAnimatedNode<ValueAnimatedNode>(nodeTag)) {
if (valueNode->getIsColorValue()) {
props.insert(
propName.c_str(),
static_cast<int32_t>(valueNode->getValue()));
} else {
props.insert(propName.c_str(), valueNode->getValue());
}
}
} break;
case AnimatedNodeType::Color: {
if (const auto colorAnimNode =
manager_->getAnimatedNode<ColorAnimatedNode>(nodeTag)) {
props.insert(
propName.c_str(),
static_cast<int32_t>(colorAnimNode->getColor()));
}
} break;
case AnimatedNodeType::Object: {
if (const auto objectNode =
manager_->getAnimatedNode<ObjectAnimatedNode>(nodeTag)) {
objectNode->collectViewUpdates(propName, props);
}
} break;
case AnimatedNodeType::Tracking:
case AnimatedNodeType::Style:
case AnimatedNodeType::Props:
break;
}
}
}
layoutStyleUpdated_ = isLayoutPropsUpdated(props);
}
} // namespace facebook::react

View File

@@ -0,0 +1,32 @@
/*
* 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.
*/
#pragma once
#include "AnimatedNode.h"
#include <folly/dynamic.h>
namespace facebook::react {
class StyleAnimatedNode final : public AnimatedNode {
public:
StyleAnimatedNode(Tag tag, const folly::dynamic &config, NativeAnimatedNodesManager &manager);
void collectViewUpdates(folly::dynamic &props);
bool isLayoutStyleUpdated() const noexcept
{
return layoutStyleUpdated_;
}
private:
bool layoutStyleUpdated_{};
};
} // namespace facebook::react

View File

@@ -0,0 +1,37 @@
/*
* 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 "SubtractionAnimatedNode.h"
#include <react/debug/react_native_assert.h>
#include <react/renderer/animated/NativeAnimatedNodesManager.h>
namespace facebook::react {
void SubtractionAnimatedNode::update() {
auto rawValue = 0.0;
int count = 0;
for (const auto& tag : inputNodes_) {
const auto node = manager_->getAnimatedNode<ValueAnimatedNode>(tag);
react_native_assert(
node && "Invalid node tag set as input for SubtractionAnimatedNode");
if (count == 0) {
rawValue = node->getValue();
} else {
rawValue -= node->getValue();
}
count++;
}
setRawValue(rawValue);
}
} // namespace facebook::react

View File

@@ -0,0 +1,29 @@
/*
* 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.
*/
#pragma once
#include <folly/dynamic.h>
#include "ValueAnimatedNode.h"
namespace facebook::react {
class SubtractionAnimatedNode final : public OperatorAnimatedNode {
public:
SubtractionAnimatedNode(Tag tag, const folly::dynamic &config, NativeAnimatedNodesManager &manager)
: OperatorAnimatedNode(tag, config, manager)
{
}
void update() override;
};
} // namespace facebook::react

View File

@@ -0,0 +1,43 @@
/*
* 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 "TrackingAnimatedNode.h"
#include <react/renderer/animated/NativeAnimatedNodesManager.h>
#include <react/renderer/animated/nodes/ValueAnimatedNode.h>
namespace facebook::react {
TrackingAnimatedNode::TrackingAnimatedNode(
Tag tag,
const folly::dynamic& config,
NativeAnimatedNodesManager& manager)
: AnimatedNode(tag, config, manager, AnimatedNodeType::Tracking),
animationId_(static_cast<int>(getConfig()["animationId"].asInt())),
toValueNodeId_(static_cast<Tag>(getConfig()["toValue"].asInt())),
valueNodeId_(static_cast<Tag>(getConfig()["value"].asInt())) {}
void TrackingAnimatedNode::update() {
if (const auto toValueNode =
manager_->getAnimatedNode<ValueAnimatedNode>(toValueNodeId_)) {
// In case the animation is already running, we need to stop it to free up
// the animationId key in the active animations map in the animation
// manager.
manager_->stopAnimation(animationId_, true);
auto animationConfig = getConfig()["animationConfig"];
animationConfig["toValue"] = toValueNode->getValue();
manager_->startAnimatingNode(
animationId_, valueNodeId_, animationConfig, std::nullopt);
}
};
} // namespace facebook::react

View File

@@ -0,0 +1,30 @@
/*
* 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.
*/
#pragma once
#include "AnimatedNode.h"
namespace facebook::react {
class TrackingAnimatedNode final : public AnimatedNode {
public:
TrackingAnimatedNode(Tag tag, const folly::dynamic &config, NativeAnimatedNodesManager &manager);
void update() override;
private:
int animationId_{};
Tag toValueNodeId_{}; // Value node to be tracked
Tag valueNodeId_{}; // Value node to be updated
};
} // namespace facebook::react

View File

@@ -0,0 +1,58 @@
/*
* 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 "TransformAnimatedNode.h"
#include <react/debug/react_native_assert.h>
#include <react/renderer/animated/NativeAnimatedNodesManager.h>
#include <react/renderer/animated/nodes/ValueAnimatedNode.h>
#include <utility>
namespace facebook::react {
static constexpr std::string_view sTransformsName{"transforms"};
static constexpr std::string_view sPropertyName{"property"};
static constexpr std::string_view sTypeName{"type"};
static constexpr std::string_view sAnimatedName{"animated"};
static constexpr std::string_view sNodeTagName{"nodeTag"};
static constexpr std::string_view sValueName{"value"};
static constexpr std::string_view sTransformPropName{"transform"};
TransformAnimatedNode::TransformAnimatedNode(
Tag tag,
const folly::dynamic& config,
NativeAnimatedNodesManager& manager)
: AnimatedNode(tag, config, manager, AnimatedNodeType::Transform) {}
void TransformAnimatedNode::collectViewUpdates(folly::dynamic& props) {
folly::dynamic transforms = folly::dynamic::array();
auto transformsArray = getConfig()[sTransformsName];
react_native_assert(transformsArray.type() == folly::dynamic::ARRAY);
for (const auto& transform : transformsArray) {
std::optional<double> value;
if (transform[sTypeName].asString() == sAnimatedName) {
const auto inputTag = static_cast<Tag>(transform[sNodeTagName].asInt());
if (const auto node =
manager_->getAnimatedNode<ValueAnimatedNode>(inputTag)) {
value = node->getValue();
}
} else {
value = transform[sValueName].asDouble();
}
if (value) {
const auto property = transform[sPropertyName].asString();
transforms.push_back(folly::dynamic::object(property, value.value()));
}
}
props[sTransformPropName] = std::move(transforms);
}
} // namespace facebook::react

View File

@@ -0,0 +1,31 @@
/*
* 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.
*/
#pragma once
#include "AnimatedNode.h"
namespace facebook::react {
struct TransformConfig {
public:
std::string property;
Tag nodeTag;
double value;
};
class TransformAnimatedNode final : public AnimatedNode {
public:
TransformAnimatedNode(Tag tag, const folly::dynamic &config, NativeAnimatedNodesManager &manager);
void collectViewUpdates(folly::dynamic &props);
};
} // namespace facebook::react

View File

@@ -0,0 +1,101 @@
/*
* 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 "ValueAnimatedNode.h"
#include <react/debug/react_native_assert.h>
#include <react/renderer/animated/NativeAnimatedNodesManager.h>
namespace facebook::react {
ValueAnimatedNode::ValueAnimatedNode(
Tag tag,
const folly::dynamic& config,
NativeAnimatedNodesManager& manager)
: AnimatedNode(tag, config, manager, AnimatedNodeType::Value) {
auto value = 0.0;
auto offset = 0.0;
if ((getConfig().count("value") != 0u) &&
(getConfig().count("offset") != 0u)) {
value = getConfig()["value"].asDouble();
offset = getConfig()["offset"].asDouble();
}
value_ = value;
offset_ = offset;
}
bool ValueAnimatedNode::setRawValue(double value) noexcept {
if (value_ != value) {
value_ = value;
onValueUpdate();
return true;
}
return false;
}
double ValueAnimatedNode::getRawValue() const noexcept {
return value_;
}
double ValueAnimatedNode::getOffset() const noexcept {
return offset_;
}
bool ValueAnimatedNode::setOffset(double offset) noexcept {
if (offset_ != offset) {
offset_ = offset;
return true;
}
return true;
}
double ValueAnimatedNode::getValue() const noexcept {
return value_ + getOffset();
}
void ValueAnimatedNode::flattenOffset() noexcept {
value_ = value_ + offset_;
offset_ = 0;
}
void ValueAnimatedNode::extractOffset() noexcept {
offset_ += value_;
value_ = 0;
}
void ValueAnimatedNode::onValueUpdate() noexcept {
if (valueListener_) {
valueListener_(getValue());
}
}
void ValueAnimatedNode::setValueListener(
ValueListenerCallback&& callback) noexcept {
valueListener_ = std::move(callback);
}
OperatorAnimatedNode::OperatorAnimatedNode(
Tag tag,
const folly::dynamic& config,
NativeAnimatedNodesManager& manager)
: ValueAnimatedNode(tag, config, manager) {
const auto& input = getConfig()["input"];
react_native_assert(
input.type() == folly::dynamic::ARRAY && input.size() >= 2);
for (const auto& inputNode : input) {
const auto inputTag = static_cast<Tag>(inputNode.asInt());
inputNodes_.push_back(inputTag);
}
}
} // namespace facebook::react

View File

@@ -0,0 +1,58 @@
/*
* 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.
*/
#pragma once
#include "AnimatedNode.h"
#include <vector>
namespace facebook::react {
using ValueListenerCallback = std::function<void(double)>;
class ValueAnimatedNode : public AnimatedNode {
public:
ValueAnimatedNode(Tag tag, const folly::dynamic &config, NativeAnimatedNodesManager &manager);
double getValue() const noexcept;
double getRawValue() const noexcept;
bool setRawValue(double value) noexcept;
double getOffset() const noexcept;
bool setOffset(double offset) noexcept;
void flattenOffset() noexcept;
void extractOffset() noexcept;
void setValueListener(ValueListenerCallback &&callback) noexcept;
bool getIsColorValue() const noexcept
{
return isColorValue_;
}
protected:
bool isColorValue_{false};
private:
void onValueUpdate() noexcept;
double value_{0.0};
double offset_{0.0};
ValueListenerCallback valueListener_{};
};
class OperatorAnimatedNode : public ValueAnimatedNode {
public:
OperatorAnimatedNode(Tag tag, const folly::dynamic &config, NativeAnimatedNodesManager &manager);
protected:
std::vector<Tag> inputNodes_{};
};
} // namespace facebook::react