From dfca5baf440593df909d118822532664f37e58cf Mon Sep 17 00:00:00 2001 From: Janic Duplessis Date: Tue, 6 Sep 2016 15:30:17 -0700 Subject: [PATCH] Add support for DiffClamp node Summary: Add native support on iOS and Android for `Animated.diffClamp` that was added in #9419. **Test plan** Tested that it works properly using the native animations UIExplorer example. Closes https://github.com/facebook/react-native/pull/9691 Differential Revision: D3813440 fbshipit-source-id: 48a3ecddf3708fa44b408954d3d8133ec8537f21 --- .../Animated/src/AnimatedImplementation.js | 14 +++++ .../Nodes/RCTDiffClampAnimatedNode.h | 14 +++++ .../Nodes/RCTDiffClampAnimatedNode.m | 62 +++++++++++++++++++ .../RCTAnimation.xcodeproj/project.pbxproj | 6 ++ .../NativeAnimation/RCTNativeAnimatedModule.m | 2 + .../react/animated/DiffClampAnimatedNode.java | 53 ++++++++++++++++ .../animated/NativeAnimatedNodesManager.java | 2 + 7 files changed, 153 insertions(+) create mode 100644 Libraries/NativeAnimation/Nodes/RCTDiffClampAnimatedNode.h create mode 100644 Libraries/NativeAnimation/Nodes/RCTDiffClampAnimatedNode.m create mode 100644 ReactAndroid/src/main/java/com/facebook/react/animated/DiffClampAnimatedNode.java diff --git a/Libraries/Animated/src/AnimatedImplementation.js b/Libraries/Animated/src/AnimatedImplementation.js index 437b6e507d85e0..4826828e9e2823 100644 --- a/Libraries/Animated/src/AnimatedImplementation.js +++ b/Libraries/Animated/src/AnimatedImplementation.js @@ -1228,6 +1228,11 @@ class AnimatedDiffClamp extends AnimatedWithChildren { this._value = this._lastValue = this._a.__getValue(); } + __makeNative() { + super.__makeNative(); + this._a.__makeNative(); + } + interpolate(config: InterpolationConfigType): AnimatedInterpolation { return new AnimatedInterpolation(this, config); } @@ -1247,6 +1252,15 @@ class AnimatedDiffClamp extends AnimatedWithChildren { __detach(): void { this._a.__removeChild(this); } + + __getNativeConfig(): any { + return { + type: 'diffclamp', + input: this._a.__getNativeTag(), + min: this._min, + max: this._max, + }; + } } class AnimatedTransform extends AnimatedWithChildren { diff --git a/Libraries/NativeAnimation/Nodes/RCTDiffClampAnimatedNode.h b/Libraries/NativeAnimation/Nodes/RCTDiffClampAnimatedNode.h new file mode 100644 index 00000000000000..3d6f1db192a228 --- /dev/null +++ b/Libraries/NativeAnimation/Nodes/RCTDiffClampAnimatedNode.h @@ -0,0 +1,14 @@ +/** + * Copyright (c) 2015-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 "RCTValueAnimatedNode.h" + +@interface RCTDiffClampAnimatedNode : RCTValueAnimatedNode + +@end diff --git a/Libraries/NativeAnimation/Nodes/RCTDiffClampAnimatedNode.m b/Libraries/NativeAnimation/Nodes/RCTDiffClampAnimatedNode.m new file mode 100644 index 00000000000000..2bdcf5fb399b85 --- /dev/null +++ b/Libraries/NativeAnimation/Nodes/RCTDiffClampAnimatedNode.m @@ -0,0 +1,62 @@ +/** + * Copyright (c) 2015-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 "RCTDiffClampAnimatedNode.h" +#import "RCTLog.h" + +@implementation RCTDiffClampAnimatedNode +{ + NSNumber *_inputNodeTag; + CGFloat _min; + CGFloat _max; + CGFloat _lastValue; +} + +- (instancetype)initWithTag:(NSNumber *)tag + config:(NSDictionary *)config +{ + if (self = [super initWithTag:tag config:config]) { + _inputNodeTag = config[@"input"]; + _min = [config[@"min"] floatValue]; + _max = [config[@"max"] floatValue]; + } + + return self; +} + +- (void)onAttachedToNode:(RCTAnimatedNode *)parent +{ + [super onAttachedToNode:parent]; + + self.value = _lastValue = [self inputNodeValue]; +} + +- (void)performUpdate +{ + [super performUpdate]; + + CGFloat value = [self inputNodeValue]; + + CGFloat diff = value - _lastValue; + _lastValue = value; + self.value = MIN(MAX(self.value + diff, _min), _max); +} + +- (CGFloat)inputNodeValue +{ + RCTValueAnimatedNode *inputNode = (RCTValueAnimatedNode *)self.parentNodes[_inputNodeTag]; + if (![inputNode isKindOfClass:[RCTValueAnimatedNode class]]) { + RCTLogError(@"Illegal node ID set as an input for Animated.DiffClamp node"); + return 0; + } + + return inputNode.value; +} + +@end diff --git a/Libraries/NativeAnimation/RCTAnimation.xcodeproj/project.pbxproj b/Libraries/NativeAnimation/RCTAnimation.xcodeproj/project.pbxproj index 6d42a4b77c01a7..b404d11fdc8d05 100644 --- a/Libraries/NativeAnimation/RCTAnimation.xcodeproj/project.pbxproj +++ b/Libraries/NativeAnimation/RCTAnimation.xcodeproj/project.pbxproj @@ -20,6 +20,7 @@ 13E501EF1D07A6C9005F35D8 /* RCTTransformAnimatedNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 13E501E51D07A6C9005F35D8 /* RCTTransformAnimatedNode.m */; }; 13E501F01D07A6C9005F35D8 /* RCTValueAnimatedNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 13E501E71D07A6C9005F35D8 /* RCTValueAnimatedNode.m */; }; 94DAE3F91D7334A70059942F /* RCTModuloAnimatedNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 94DAE3F81D7334A70059942F /* RCTModuloAnimatedNode.m */; }; + 193F64F41D776EC6004D1CAA /* RCTDiffClampAnimatedNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 193F64F31D776EC6004D1CAA /* RCTDiffClampAnimatedNode.m */; }; /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -62,6 +63,8 @@ 13E501E71D07A6C9005F35D8 /* RCTValueAnimatedNode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTValueAnimatedNode.m; sourceTree = ""; }; 94DAE3F71D7334A70059942F /* RCTModuloAnimatedNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTModuloAnimatedNode.h; sourceTree = ""; }; 94DAE3F81D7334A70059942F /* RCTModuloAnimatedNode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTModuloAnimatedNode.m; sourceTree = ""; }; + 193F64F21D776EC6004D1CAA /* RCTDiffClampAnimatedNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTDiffClampAnimatedNode.h; sourceTree = ""; }; + 193F64F31D776EC6004D1CAA /* RCTDiffClampAnimatedNode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTDiffClampAnimatedNode.m; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -86,6 +89,8 @@ 13E501D51D07A6C9005F35D8 /* Nodes */ = { isa = PBXGroup; children = ( + 193F64F21D776EC6004D1CAA /* RCTDiffClampAnimatedNode.h */, + 193F64F31D776EC6004D1CAA /* RCTDiffClampAnimatedNode.m */, 13E501D61D07A6C9005F35D8 /* RCTAdditionAnimatedNode.h */, 13E501D71D07A6C9005F35D8 /* RCTAdditionAnimatedNode.m */, 13E501D81D07A6C9005F35D8 /* RCTAnimatedNode.h */, @@ -182,6 +187,7 @@ files = ( 13E501F01D07A6C9005F35D8 /* RCTValueAnimatedNode.m in Sources */, 94DAE3F91D7334A70059942F /* RCTModuloAnimatedNode.m in Sources */, + 193F64F41D776EC6004D1CAA /* RCTDiffClampAnimatedNode.m in Sources */, 13E501EE1D07A6C9005F35D8 /* RCTStyleAnimatedNode.m in Sources */, 13E501CC1D07A644005F35D8 /* RCTAnimationUtils.m in Sources */, 13E501CF1D07A644005F35D8 /* RCTNativeAnimatedModule.m in Sources */, diff --git a/Libraries/NativeAnimation/RCTNativeAnimatedModule.m b/Libraries/NativeAnimation/RCTNativeAnimatedModule.m index a739e5ed6ca6fe..fe9771cfb71df0 100644 --- a/Libraries/NativeAnimation/RCTNativeAnimatedModule.m +++ b/Libraries/NativeAnimation/RCTNativeAnimatedModule.m @@ -15,6 +15,7 @@ #import "RCTConvert.h" #import "RCTInterpolationAnimatedNode.h" #import "RCTLog.h" +#import "RCTDiffClampAnimatedNode.h" #import "RCTModuloAnimatedNode.h" #import "RCTMultiplicationAnimatedNode.h" #import "RCTPropsAnimatedNode.h" @@ -69,6 +70,7 @@ - (dispatch_queue_t)methodQueue @"props" : [RCTPropsAnimatedNode class], @"interpolation" : [RCTInterpolationAnimatedNode class], @"addition" : [RCTAdditionAnimatedNode class], + @"diffclamp": [RCTDiffClampAnimatedNode class], @"multiplication" : [RCTMultiplicationAnimatedNode class], @"modulus" : [RCTModuloAnimatedNode class], @"transform" : [RCTTransformAnimatedNode class]}; diff --git a/ReactAndroid/src/main/java/com/facebook/react/animated/DiffClampAnimatedNode.java b/ReactAndroid/src/main/java/com/facebook/react/animated/DiffClampAnimatedNode.java new file mode 100644 index 00000000000000..2dc25d954f31ed --- /dev/null +++ b/ReactAndroid/src/main/java/com/facebook/react/animated/DiffClampAnimatedNode.java @@ -0,0 +1,53 @@ +/** + * Copyright (c) 2015-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.react.animated; + +import com.facebook.react.bridge.JSApplicationCausedNativeException; +import com.facebook.react.bridge.ReadableMap; + +/*package*/ class DiffClampAnimatedNode extends ValueAnimatedNode { + private final NativeAnimatedNodesManager mNativeAnimatedNodesManager; + private final int mInputNodeTag; + private final double mMin; + private final double mMax; + + private double mLastValue; + + public DiffClampAnimatedNode( + ReadableMap config, + NativeAnimatedNodesManager nativeAnimatedNodesManager) { + mNativeAnimatedNodesManager = nativeAnimatedNodesManager; + mInputNodeTag = config.getInt("input"); + mMin = config.getDouble("min"); + mMax = config.getDouble("max"); + + mValue = mLastValue = getInputNodeValue(); + } + + @Override + public void update() { + double value = getInputNodeValue(); + + double diff = value - mLastValue; + mLastValue = value; + mValue = Math.min(Math.max(mValue + diff, mMin), mMax); + } + + private double getInputNodeValue() { + AnimatedNode animatedNode = mNativeAnimatedNodesManager.getNodeById(mInputNodeTag); + if (animatedNode == null || !(animatedNode instanceof ValueAnimatedNode)) { + throw new JSApplicationCausedNativeException("Illegal node ID set as an input for " + + "Animated.DiffClamp node"); + + } + + return ((ValueAnimatedNode) animatedNode).mValue; + } +} diff --git a/ReactAndroid/src/main/java/com/facebook/react/animated/NativeAnimatedNodesManager.java b/ReactAndroid/src/main/java/com/facebook/react/animated/NativeAnimatedNodesManager.java index fe6613e03eb176..f312c88e612832 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/animated/NativeAnimatedNodesManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/animated/NativeAnimatedNodesManager.java @@ -78,6 +78,8 @@ public void createAnimatedNode(int tag, ReadableMap config) { node = new AdditionAnimatedNode(config, this); } else if ("multiplication".equals(type)) { node = new MultiplicationAnimatedNode(config, this); + } else if ("diffclamp".equals(type)) { + node = new DiffClampAnimatedNode(config, this); } else if ("transform".equals(type)) { node = new TransformAnimatedNode(config, this); } else {