mirror of
https://github.com/zhigang1992/react-native-reanimated.git
synced 2026-06-15 02:19:30 +08:00
This PR adds new "round" and "color" nodes. Color nodes can be used to map to color props in view (e.g. backgroundColor) Round is required for the color math to function properly (each color component needs to be an integer). Added demo app where you can pan view around that changes color depending on the position on HSV palette.
105 lines
3.2 KiB
Objective-C
105 lines
3.2 KiB
Objective-C
#include <tgmath.h>
|
|
|
|
#import "REAOperatorNode.h"
|
|
#import "REANodesManager.h"
|
|
|
|
typedef id (^REAOperatorBlock)(NSArray<REANode *> *inputNodes);
|
|
|
|
#define REA_REDUCE(OP) ^(NSArray<REANode *> *inputNodes) { \
|
|
CGFloat acc = [[inputNodes[0] value] doubleValue]; \
|
|
for (NSUInteger i = 1; i < inputNodes.count; i++) { \
|
|
CGFloat a = acc, b = [[inputNodes[i] value] doubleValue]; \
|
|
acc = OP; \
|
|
} \
|
|
return @(acc); \
|
|
}
|
|
|
|
#define REA_SINGLE(OP) ^(NSArray<REANode *> *inputNodes) { \
|
|
CGFloat a = [[inputNodes[0] value] doubleValue]; \
|
|
return @(OP); \
|
|
}
|
|
|
|
#define REA_INFIX(OP) ^(NSArray<REANode *> *inputNodes) { \
|
|
CGFloat a = [[inputNodes[0] value] doubleValue]; \
|
|
CGFloat b = [[inputNodes[1] value] doubleValue]; \
|
|
return @(OP); \
|
|
}
|
|
|
|
@implementation REAOperatorNode {
|
|
NSArray<NSNumber *> *_input;
|
|
NSMutableArray<REANode *> *_inputNodes;
|
|
REAOperatorBlock _op;
|
|
}
|
|
|
|
- (instancetype)initWithID:(REANodeID)nodeID config:(NSDictionary<NSString *,id> *)config
|
|
{
|
|
static NSDictionary *OPS;
|
|
static dispatch_once_t opsToken;
|
|
dispatch_once(&opsToken, ^{
|
|
OPS = @{
|
|
// arithmetic
|
|
@"add": REA_REDUCE(a + b),
|
|
@"sub": REA_REDUCE(a - b),
|
|
@"multiply": REA_REDUCE(a * b),
|
|
@"divide": REA_REDUCE(a / b),
|
|
@"pow": REA_REDUCE(pow(a, b)),
|
|
@"modulo": REA_REDUCE(fmodf(fmodf(a, b) + b, b)),
|
|
@"sqrt": REA_SINGLE(sqrt(a)),
|
|
@"sin": REA_SINGLE(sin(a)),
|
|
@"cos": REA_SINGLE(cos(a)),
|
|
@"exp": REA_SINGLE(exp(a)),
|
|
@"round": REA_SINGLE(round(a)),
|
|
|
|
// logical
|
|
@"and": ^(NSArray<REANode *> *inputNodes) {
|
|
BOOL res = [[inputNodes[0] value] doubleValue];
|
|
for (NSUInteger i = 1; i < inputNodes.count && res; i++) {
|
|
res = res && [[inputNodes[i] value] doubleValue];
|
|
}
|
|
return res ? @(1.) : @(0.);
|
|
},
|
|
@"or": ^(NSArray<REANode *> *inputNodes) {
|
|
BOOL res = [[inputNodes[0] value] doubleValue];
|
|
for (NSUInteger i = 1; i < inputNodes.count && !res; i++) {
|
|
res = res || [[inputNodes[i] value] doubleValue];
|
|
}
|
|
return res ? @(1.) : @(0.);
|
|
},
|
|
@"not": REA_SINGLE(!a),
|
|
@"defined": ^(NSArray<REANode *> *inputNodes) {
|
|
id val = [inputNodes[0] value];
|
|
id res = @(val != nil && !isnan([val doubleValue]));
|
|
return res;
|
|
},
|
|
|
|
// comparing
|
|
@"lessThan": REA_INFIX(a < b),
|
|
@"eq": REA_INFIX(a == b),
|
|
@"greaterThan": REA_INFIX(a > b),
|
|
@"lessOrEq": REA_INFIX(a <= b),
|
|
@"greaterOrEq": REA_INFIX(a >= b),
|
|
@"neq": REA_INFIX(a != b),
|
|
};
|
|
});
|
|
if ((self = [super initWithID:nodeID config:config])) {
|
|
_input = config[@"input"];
|
|
_inputNodes = [NSMutableArray arrayWithCapacity:_input.count];
|
|
_op = OPS[config[@"op"]];
|
|
if (!_op) {
|
|
RCTLogError(@"Operator '%@' not found", config[@"op"]);
|
|
}
|
|
}
|
|
return self;
|
|
}
|
|
|
|
- (id)evaluate
|
|
{
|
|
for (NSUInteger i = 0; i < _input.count; i++) {
|
|
_inputNodes[i] = [self.nodesManager findNodeByID:_input[i]];
|
|
}
|
|
return _op(_inputNodes);
|
|
}
|
|
|
|
@end
|
|
|