Skip to content

Commit 7941a62

Browse files
zeyapmeta-codesync[bot]
authored andcommitted
Add support for PlatformColor type in AnimatedNodes and interpolation outputRange (#54459)
Summary: Pull Request resolved: #54459 ## Changelog: [Android] [Added] Add c++ animated support for PlatformColor type of toValue and interpolation outputRange Reviewed By: sammy-SC Differential Revision: D86350392 fbshipit-source-id: f9ea02d444c54601306f0aa37afd3cb5d8f9b1e6
1 parent c6571aa commit 7941a62

File tree

6 files changed

+122
-7
lines changed

6 files changed

+122
-7
lines changed

packages/react-native/ReactCommon/react/renderer/animated/NativeAnimatedNodesManager.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,11 +73,13 @@ thread_local bool NativeAnimatedNodesManager::isOnRenderThread_{false};
7373
NativeAnimatedNodesManager::NativeAnimatedNodesManager(
7474
DirectManipulationCallback&& directManipulationCallback,
7575
FabricCommitCallback&& fabricCommitCallback,
76+
ResolvePlatformColor&& resolvePlatformColor,
7677
StartOnRenderCallback&& startOnRenderCallback,
7778
StopOnRenderCallback&& stopOnRenderCallback,
7879
FrameRateListenerCallback&& frameRateListenerCallback) noexcept
7980
: directManipulationCallback_(std::move(directManipulationCallback)),
8081
fabricCommitCallback_(std::move(fabricCommitCallback)),
82+
resolvePlatformColor_(std::move(resolvePlatformColor)),
8183
startOnRenderCallback_(std::move(startOnRenderCallback)),
8284
stopOnRenderCallback_(std::move(stopOnRenderCallback)),
8385
frameRateListenerCallback_(std::move(frameRateListenerCallback)) {
@@ -847,6 +849,15 @@ bool NativeAnimatedNodesManager::isOnRenderThread() const noexcept {
847849
return isOnRenderThread_;
848850
}
849851

852+
void NativeAnimatedNodesManager::resolvePlatformColor(
853+
SurfaceId surfaceId,
854+
const RawValue& value,
855+
SharedColor& result) const {
856+
if (resolvePlatformColor_) {
857+
resolvePlatformColor_(surfaceId, value, result);
858+
}
859+
}
860+
850861
#pragma mark - Listeners
851862

852863
void NativeAnimatedNodesManager::startListeningToAnimatedNodeValue(

packages/react-native/ReactCommon/react/renderer/animated/NativeAnimatedNodesManager.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,12 @@ class NativeAnimatedNodesManager {
5858
using StartOnRenderCallback = std::function<void(std::function<void()> &&, bool isAsync)>;
5959
using StopOnRenderCallback = std::function<void(bool isAsync)>;
6060
using FrameRateListenerCallback = std::function<void(bool /* shouldEnableListener */)>;
61+
using ResolvePlatformColor = std::function<void(SurfaceId surfaceId, const RawValue &value, SharedColor &result)>;
6162

6263
explicit NativeAnimatedNodesManager(
6364
DirectManipulationCallback &&directManipulationCallback,
6465
FabricCommitCallback &&fabricCommitCallback,
66+
ResolvePlatformColor &&resolvePlatformColor,
6567
StartOnRenderCallback &&startOnRenderCallback = nullptr,
6668
StopOnRenderCallback &&stopOnRenderCallback = nullptr,
6769
FrameRateListenerCallback &&frameRateListenerCallback = nullptr) noexcept;
@@ -185,6 +187,8 @@ class NativeAnimatedNodesManager {
185187

186188
bool isOnRenderThread() const noexcept;
187189

190+
void resolvePlatformColor(SurfaceId surfaceId, const RawValue &value, SharedColor &result) const;
191+
188192
private:
189193
void stopRenderCallbackIfNeeded(bool isAsync) noexcept;
190194

@@ -233,6 +237,8 @@ class NativeAnimatedNodesManager {
233237
const DirectManipulationCallback directManipulationCallback_;
234238
const FabricCommitCallback fabricCommitCallback_;
235239

240+
const ResolvePlatformColor resolvePlatformColor_;
241+
236242
/*
237243
* Tracks whether the render callback loop for animations is currently active.
238244
*/

packages/react-native/ReactCommon/react/renderer/animated/NativeAnimatedNodesManagerProvider.cpp

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@
1414
#ifdef RN_USE_ANIMATION_BACKEND
1515
#include <react/renderer/animationbackend/AnimationBackend.h>
1616
#endif
17+
#include <react/renderer/animated/internal/primitives.h>
18+
#include <react/renderer/components/view/conversions.h>
19+
#include <react/renderer/scheduler/Scheduler.h>
1720
#include <react/renderer/uimanager/UIManagerBinding.h>
1821

1922
namespace facebook::react {
@@ -70,6 +73,24 @@ NativeAnimatedNodesManagerProvider::getOrCreate(
7073
uiManager->synchronouslyUpdateViewOnUIThread(viewTag, props);
7174
};
7275

76+
// TODO: remove force casting.
77+
auto* scheduler = (Scheduler*)uiManager->getDelegate();
78+
auto resolvePlatformColor = [scheduler, uiManager](
79+
SurfaceId surfaceId,
80+
const RawValue& value,
81+
SharedColor& result) {
82+
if (uiManager) {
83+
if (surfaceId != animated::undefinedAnimatedNodeIdentifier) {
84+
PropsParserContext propsParserContext{
85+
surfaceId, *scheduler->getContextContainer()};
86+
fromRawValue(propsParserContext, value, result);
87+
} else {
88+
LOG(ERROR)
89+
<< "Cannot resolve platformColor because surfaceId is unavailable.";
90+
}
91+
}
92+
};
93+
7394
if (ReactNativeFeatureFlags::useSharedAnimatedBackend()) {
7495
#ifdef RN_USE_ANIMATION_BACKEND
7596
// TODO: this should be initialized outside of animated, but for now it
@@ -95,6 +116,7 @@ NativeAnimatedNodesManagerProvider::getOrCreate(
95116
std::make_shared<NativeAnimatedNodesManager>(
96117
std::move(directManipulationCallback),
97118
std::move(fabricCommitCallback),
119+
std::move(resolvePlatformColor),
98120
std::move(startOnRenderCallback_),
99121
std::move(stopOnRenderCallback_),
100122
std::move(frameRateListenerCallback_));
@@ -128,8 +150,6 @@ NativeAnimatedNodesManagerProvider::getOrCreate(
128150

129151
uiManager->setNativeAnimatedDelegate(nativeAnimatedDelegate_);
130152

131-
// TODO: remove force casting.
132-
auto* scheduler = (Scheduler*)uiManager->getDelegate();
133153
animatedMountingOverrideDelegate_ =
134154
std::make_shared<AnimatedMountingOverrideDelegate>(
135155
*nativeAnimatedNodesManager_, *scheduler);

packages/react-native/ReactCommon/react/renderer/animated/nodes/InterpolationAnimatedNode.cpp

Lines changed: 74 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,19 @@ InterpolationAnimatedNode::InterpolationAnimatedNode(
2929
inputRanges_.push_back(rangeValue.asDouble());
3030
}
3131

32-
const bool isColorOutput = nodeConfig["outputType"].isString() &&
33-
nodeConfig["outputType"].asString() == "color";
34-
if (isColorOutput) {
32+
const auto outputType = nodeConfig["outputType"].isString()
33+
? nodeConfig["outputType"].asString()
34+
: "";
35+
outputType_ = outputType;
36+
if (outputType == "color") {
3537
isColorValue_ = true;
3638
for (const auto& rangeValue : nodeConfig["outputRange"]) {
3739
colorOutputRanges_.push_back(static_cast<int>(rangeValue.asInt()));
3840
}
41+
} else if (outputType == "platform_color") {
42+
for (const auto& rangeValue : nodeConfig["outputRange"]) {
43+
platformColorOutputRanges_.push_back(rangeValue);
44+
}
3945
} else {
4046
for (const auto& rangeValue : nodeConfig["outputRange"]) {
4147
defaultOutputRanges_.push_back(rangeValue.asDouble());
@@ -53,8 +59,10 @@ void InterpolationAnimatedNode::update() {
5359

5460
if (const auto node =
5561
manager_->getAnimatedNode<ValueAnimatedNode>(parentTag_)) {
56-
if (isColorValue_) {
62+
if (outputType_ == "color") {
5763
setRawValue(interpolateColor(node->getValue()));
64+
} else if (outputType_ == "platform_color") {
65+
setRawValue(interpolatePlatformColor(node->getValue()));
5866
} else {
5967
setRawValue(interpolateValue(node->getValue()));
6068
}
@@ -141,4 +149,66 @@ double InterpolationAnimatedNode::interpolateColor(double value) {
141149
static_cast<uint8_t>(outputValueA)));
142150
}
143151

152+
double InterpolationAnimatedNode::interpolatePlatformColor(double value) {
153+
// Compute range index
154+
size_t index = 1;
155+
for (; index < inputRanges_.size() - 1; ++index) {
156+
if (inputRanges_[index] >= value) {
157+
break;
158+
}
159+
}
160+
index--;
161+
SharedColor outputMinSharedColor;
162+
SharedColor outputMaxSharedColor;
163+
if (manager_ != nullptr) {
164+
manager_->resolvePlatformColor(
165+
connectedRootTag_,
166+
RawValue(platformColorOutputRanges_[index]),
167+
outputMinSharedColor);
168+
manager_->resolvePlatformColor(
169+
connectedRootTag_,
170+
RawValue(platformColorOutputRanges_[index + 1]),
171+
outputMaxSharedColor);
172+
}
173+
auto outputMin = *outputMinSharedColor;
174+
auto outputMax = *outputMaxSharedColor;
175+
176+
if (outputMin == outputMax) {
177+
return outputMin;
178+
}
179+
180+
const auto inputMin = inputRanges_[index];
181+
const auto inputMax = inputRanges_[index + 1];
182+
if (inputMin == inputMax) {
183+
if (value <= inputMin) {
184+
return static_cast<int32_t>(outputMin);
185+
} else {
186+
return static_cast<int32_t>(outputMax);
187+
}
188+
}
189+
190+
auto ratio = (value - inputMin) / (inputMax - inputMin);
191+
192+
auto outputMinA = alphaFromHostPlatformColor(outputMin);
193+
auto outputMinR = redFromHostPlatformColor(outputMin);
194+
auto outputMinG = greenFromHostPlatformColor(outputMin);
195+
auto outputMinB = blueFromHostPlatformColor(outputMin);
196+
197+
auto outputMaxA = alphaFromHostPlatformColor(outputMax);
198+
auto outputMaxR = redFromHostPlatformColor(outputMax);
199+
auto outputMaxG = greenFromHostPlatformColor(outputMax);
200+
auto outputMaxB = blueFromHostPlatformColor(outputMax);
201+
202+
auto outputValueA = ratio * (outputMaxA - outputMinA) + outputMinA;
203+
auto outputValueR = ratio * (outputMaxR - outputMinR) + outputMinR;
204+
auto outputValueG = ratio * (outputMaxG - outputMinG) + outputMinG;
205+
auto outputValueB = ratio * (outputMaxB - outputMinB) + outputMinB;
206+
207+
return static_cast<int32_t>(hostPlatformColorFromRGBA(
208+
static_cast<uint8_t>(outputValueR),
209+
static_cast<uint8_t>(outputValueG),
210+
static_cast<uint8_t>(outputValueB),
211+
static_cast<uint8_t>(outputValueA)));
212+
}
213+
144214
} // namespace facebook::react

packages/react-native/ReactCommon/react/renderer/animated/nodes/InterpolationAnimatedNode.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,20 @@ class InterpolationAnimatedNode final : public ValueAnimatedNode {
2929
private:
3030
double interpolateValue(double value);
3131
double interpolateColor(double value);
32+
double interpolatePlatformColor(double value);
3233

3334
std::vector<double> inputRanges_;
3435
std::vector<double> defaultOutputRanges_;
3536
std::vector<Color> colorOutputRanges_;
37+
std::vector<folly::dynamic> platformColorOutputRanges_;
3638
std::string extrapolateLeft_;
3739
std::string extrapolateRight_;
3840

41+
std::string outputType_;
42+
3943
Tag parentTag_{animated::undefinedAnimatedNodeIdentifier};
44+
45+
// Needed for PlatformColor resolver
46+
SurfaceId connectedRootTag_{animated::undefinedAnimatedNodeIdentifier};
4047
};
4148
} // namespace facebook::react

packages/react-native/ReactCommon/react/renderer/animated/tests/AnimationTestsBase.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ class AnimationTestsBase : public testing::Test {
3535
lastUpdatedNodeTag = nodesProps.begin()->first;
3636
lastCommittedProps = nodesProps.begin()->second;
3737
}
38-
});
38+
},
39+
nullptr);
3940
NativeAnimatedNodesManager::isOnRenderThread_ = true;
4041
}
4142

0 commit comments

Comments
 (0)