react-native-smooth-clip-view 0.2.9 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +132 -349
- package/android/build.gradle +8 -4
- package/android/proguard-rules.pro +3 -3
- package/android/src/main/cpp/SmoothClipAndroid.h +13 -6
- package/android/src/main/cpp/SmoothClipBindings.cpp +605 -123
- package/android/src/main/cpp/SmoothClipRegistry.cpp +975 -209
- package/android/src/main/java/com/smoothclipview/ClipGeometryNormalizer.kt +192 -118
- package/android/src/main/java/com/smoothclipview/SmoothClipBindings.kt +22 -4
- package/android/src/main/java/com/smoothclipview/SmoothClipModule.kt +81 -56
- package/android/src/main/java/com/smoothclipview/SmoothClipView.kt +449 -240
- package/android/src/main/java/com/smoothclipview/SmoothClipViewManager.kt +150 -38
- package/cpp/SmoothClipAnimationCurve.h +317 -397
- package/cpp/SmoothClipRegistry.h +84 -20
- package/cpp/SmoothClipSharedGeometry.h +131 -22
- package/cpp/SmoothClipVelocityTracker.h +16 -12
- package/ios/SmoothClipGeometry.h +188 -21
- package/ios/SmoothClipRegistry.mm +869 -368
- package/ios/SmoothClipRegistrySnapshot.h +13 -0
- package/ios/SmoothClipTurboModule.cpp +513 -156
- package/ios/SmoothClipTurboModule.h +123 -56
- package/ios/SmoothClipView.mm +1074 -449
- package/ios/SmoothClipViewRegistry.h +3 -7
- package/ios/reactnativesmoothclipview.xcodeproj/project.xcworkspace/contents.xcworkspacedata +7 -0
- package/ios/reactnativesmoothclipview.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -0
- package/lib/module/NativeSmoothClipModule.js.map +1 -1
- package/lib/module/SmoothClipView.ios.js +94 -11
- package/lib/module/SmoothClipView.ios.js.map +1 -1
- package/lib/module/SmoothClipView.js +1 -46
- package/lib/module/SmoothClipView.js.map +1 -1
- package/lib/module/SmoothClipViewNativeComponent.ts +32 -12
- package/lib/module/capabilities.js +4 -0
- package/lib/module/capabilities.js.map +1 -0
- package/lib/module/capabilities.native.js +18 -0
- package/lib/module/capabilities.native.js.map +1 -0
- package/lib/module/capabilityTypes.js +2 -0
- package/lib/module/capabilityTypes.js.map +1 -0
- package/lib/module/controllerInternals.js +28 -0
- package/lib/module/controllerInternals.js.map +1 -0
- package/lib/module/controllerLifecycle.js +9 -0
- package/lib/module/controllerLifecycle.js.map +1 -0
- package/lib/module/controllerTypes.js +4 -0
- package/lib/module/controllerTypes.js.map +1 -0
- package/lib/module/controllers.android.js +4 -0
- package/lib/module/controllers.android.js.map +1 -0
- package/lib/module/controllers.ios.js +4 -0
- package/lib/module/controllers.ios.js.map +1 -0
- package/lib/module/controllers.js +4 -0
- package/lib/module/controllers.js.map +1 -0
- package/lib/module/controllers.native.js +89 -0
- package/lib/module/controllers.native.js.map +1 -0
- package/lib/module/geometry.js +180 -30
- package/lib/module/geometry.js.map +1 -1
- package/lib/module/groupTypes.js +4 -0
- package/lib/module/groupTypes.js.map +1 -0
- package/lib/module/groups.android.js +4 -0
- package/lib/module/groups.android.js.map +1 -0
- package/lib/module/groups.ios.js +4 -0
- package/lib/module/groups.ios.js.map +1 -0
- package/lib/module/groups.js +4 -0
- package/lib/module/groups.js.map +1 -0
- package/lib/module/groups.native.js +399 -0
- package/lib/module/groups.native.js.map +1 -0
- package/lib/module/ids.js +8 -0
- package/lib/module/ids.js.map +1 -0
- package/lib/module/index.js +4 -3
- package/lib/module/index.js.map +1 -1
- package/lib/module/nativeCompletion.js +37 -16
- package/lib/module/nativeCompletion.js.map +1 -1
- package/lib/module/presentationCodec.js +81 -0
- package/lib/module/presentationCodec.js.map +1 -0
- package/lib/typescript/src/NativeSmoothClipModule.d.ts +20 -4
- package/lib/typescript/src/NativeSmoothClipModule.d.ts.map +1 -1
- package/lib/typescript/src/SmoothClipView.d.ts +2 -10
- package/lib/typescript/src/SmoothClipView.d.ts.map +1 -1
- package/lib/typescript/src/SmoothClipView.ios.d.ts +139 -4
- package/lib/typescript/src/SmoothClipView.ios.d.ts.map +1 -1
- package/lib/typescript/src/SmoothClipViewNativeComponent.d.ts +16 -3
- package/lib/typescript/src/SmoothClipViewNativeComponent.d.ts.map +1 -1
- package/lib/typescript/src/capabilities.d.ts +3 -0
- package/lib/typescript/src/capabilities.d.ts.map +1 -0
- package/lib/typescript/src/capabilities.native.d.ts +3 -0
- package/lib/typescript/src/capabilities.native.d.ts.map +1 -0
- package/lib/typescript/src/capabilityTypes.d.ts +4 -0
- package/lib/typescript/src/capabilityTypes.d.ts.map +1 -0
- package/lib/typescript/src/controllerInternals.d.ts +14 -0
- package/lib/typescript/src/controllerInternals.d.ts.map +1 -0
- package/lib/typescript/src/controllerLifecycle.d.ts +3 -0
- package/lib/typescript/src/controllerLifecycle.d.ts.map +1 -0
- package/lib/typescript/src/controllerTypes.d.ts +62 -0
- package/lib/typescript/src/controllerTypes.d.ts.map +1 -0
- package/lib/typescript/src/controllers.android.d.ts +2 -0
- package/lib/typescript/src/controllers.android.d.ts.map +1 -0
- package/lib/typescript/src/controllers.d.ts +2 -0
- package/lib/typescript/src/controllers.d.ts.map +1 -0
- package/lib/typescript/src/controllers.ios.d.ts +2 -0
- package/lib/typescript/src/controllers.ios.d.ts.map +1 -0
- package/lib/typescript/src/controllers.native.d.ts +3 -0
- package/lib/typescript/src/controllers.native.d.ts.map +1 -0
- package/lib/typescript/src/geometry.d.ts +49 -5
- package/lib/typescript/src/geometry.d.ts.map +1 -1
- package/lib/typescript/src/groupTypes.d.ts +31 -0
- package/lib/typescript/src/groupTypes.d.ts.map +1 -0
- package/lib/typescript/src/groups.android.d.ts +2 -0
- package/lib/typescript/src/groups.android.d.ts.map +1 -0
- package/lib/typescript/src/groups.d.ts +2 -0
- package/lib/typescript/src/groups.d.ts.map +1 -0
- package/lib/typescript/src/groups.ios.d.ts +2 -0
- package/lib/typescript/src/groups.ios.d.ts.map +1 -0
- package/lib/typescript/src/groups.native.d.ts +3 -0
- package/lib/typescript/src/groups.native.d.ts.map +1 -0
- package/lib/typescript/src/ids.d.ts +2 -0
- package/lib/typescript/src/ids.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +8 -5
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/nativeCompletion.d.ts +16 -6
- package/lib/typescript/src/nativeCompletion.d.ts.map +1 -1
- package/lib/typescript/src/presentationCodec.d.ts +10 -0
- package/lib/typescript/src/presentationCodec.d.ts.map +1 -0
- package/package.json +17 -13
- package/src/NativeSmoothClipModule.ts +80 -56
- package/src/SmoothClipView.ios.tsx +142 -16
- package/src/SmoothClipView.tsx +6 -76
- package/src/SmoothClipViewNativeComponent.ts +32 -12
- package/src/capabilities.native.ts +19 -0
- package/src/capabilities.ts +2 -0
- package/src/capabilityTypes.ts +3 -0
- package/src/controllerInternals.ts +52 -0
- package/src/controllerLifecycle.ts +6 -0
- package/src/controllerTypes.ts +87 -0
- package/src/controllers.android.ts +1 -0
- package/src/controllers.ios.ts +1 -0
- package/src/controllers.native.ts +104 -0
- package/src/controllers.ts +1 -0
- package/src/geometry.ts +293 -45
- package/src/groupTypes.ts +53 -0
- package/src/groups.android.ts +1 -0
- package/src/groups.ios.ts +1 -0
- package/src/groups.native.ts +604 -0
- package/src/groups.ts +1 -0
- package/src/ids.ts +6 -0
- package/src/index.ts +32 -12
- package/src/nativeCompletion.ts +67 -32
- package/src/presentationCodec.ts +134 -0
- package/lib/module/SmoothClipView.web.js +0 -54
- package/lib/module/SmoothClipView.web.js.map +0 -1
- package/lib/module/driverState.js +0 -110
- package/lib/module/driverState.js.map +0 -1
- package/lib/module/driverTypes.js +0 -4
- package/lib/module/driverTypes.js.map +0 -1
- package/lib/module/drivers.android.js +0 -6
- package/lib/module/drivers.android.js.map +0 -1
- package/lib/module/drivers.ios.js +0 -6
- package/lib/module/drivers.ios.js.map +0 -1
- package/lib/module/drivers.js +0 -284
- package/lib/module/drivers.js.map +0 -1
- package/lib/module/drivers.native.js +0 -556
- package/lib/module/drivers.native.js.map +0 -1
- package/lib/module/index.web.js +0 -8
- package/lib/module/index.web.js.map +0 -1
- package/lib/module/reactRequests.js +0 -56
- package/lib/module/reactRequests.js.map +0 -1
- package/lib/module/webClipPath.js +0 -25
- package/lib/module/webClipPath.js.map +0 -1
- package/lib/typescript/src/SmoothClipView.web.d.ts +0 -10
- package/lib/typescript/src/SmoothClipView.web.d.ts.map +0 -1
- package/lib/typescript/src/driverState.d.ts +0 -31
- package/lib/typescript/src/driverState.d.ts.map +0 -1
- package/lib/typescript/src/driverTypes.d.ts +0 -107
- package/lib/typescript/src/driverTypes.d.ts.map +0 -1
- package/lib/typescript/src/drivers.android.d.ts +0 -3
- package/lib/typescript/src/drivers.android.d.ts.map +0 -1
- package/lib/typescript/src/drivers.d.ts +0 -5
- package/lib/typescript/src/drivers.d.ts.map +0 -1
- package/lib/typescript/src/drivers.ios.d.ts +0 -3
- package/lib/typescript/src/drivers.ios.d.ts.map +0 -1
- package/lib/typescript/src/drivers.native.d.ts +0 -5
- package/lib/typescript/src/drivers.native.d.ts.map +0 -1
- package/lib/typescript/src/index.web.d.ts +0 -9
- package/lib/typescript/src/index.web.d.ts.map +0 -1
- package/lib/typescript/src/reactRequests.d.ts +0 -9
- package/lib/typescript/src/reactRequests.d.ts.map +0 -1
- package/lib/typescript/src/webClipPath.d.ts +0 -7
- package/lib/typescript/src/webClipPath.d.ts.map +0 -1
- package/src/SmoothClipView.web.tsx +0 -66
- package/src/driverState.ts +0 -158
- package/src/driverTypes.ts +0 -140
- package/src/drivers.android.ts +0 -8
- package/src/drivers.ios.ts +0 -8
- package/src/drivers.native.ts +0 -899
- package/src/drivers.ts +0 -427
- package/src/index.web.ts +0 -23
- package/src/reactRequests.ts +0 -76
- package/src/webClipPath.ts +0 -30
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
#include <fbjni/fbjni.h>
|
|
6
6
|
#include <jsi/jsi.h>
|
|
7
7
|
|
|
8
|
+
#include <algorithm>
|
|
8
9
|
#include <cmath>
|
|
9
10
|
#include <limits>
|
|
10
11
|
#include <memory>
|
|
@@ -26,26 +27,80 @@ namespace smoothclip {
|
|
|
26
27
|
namespace {
|
|
27
28
|
|
|
28
29
|
constexpr double kMaxSafeJavaScriptInteger = 9007199254740991.0;
|
|
30
|
+
constexpr size_t kPresentationStride = 21;
|
|
31
|
+
constexpr size_t kSnapshotStride = kPresentationStride + 1;
|
|
32
|
+
constexpr size_t kMotionEntryStride = kPresentationStride * 2 + 2;
|
|
29
33
|
|
|
30
34
|
bool validDriverId(double value) {
|
|
31
35
|
return std::isfinite(value) && value > 0 &&
|
|
32
36
|
value <= kMaxSafeJavaScriptInteger && std::floor(value) == value;
|
|
33
37
|
}
|
|
34
38
|
|
|
35
|
-
bool
|
|
39
|
+
bool validCurve(double value) {
|
|
40
|
+
return std::isfinite(value) && std::floor(value) == value &&
|
|
41
|
+
(value == static_cast<double>(ClipCurve::Circular) ||
|
|
42
|
+
value == static_cast<double>(ClipCurve::Continuous));
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
bool validRadiusOverride(double value) {
|
|
46
|
+
return std::isfinite(value) || std::isnan(value);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
bool finiteBasePresentation(const Presentation &presentation) {
|
|
36
50
|
return std::isfinite(presentation.clip.x) &&
|
|
37
51
|
std::isfinite(presentation.clip.y) &&
|
|
38
52
|
std::isfinite(presentation.clip.width) &&
|
|
39
53
|
std::isfinite(presentation.clip.height) &&
|
|
40
54
|
std::isfinite(presentation.clip.radius) &&
|
|
55
|
+
validRadiusOverride(presentation.clip.topLeftRadius) &&
|
|
56
|
+
validRadiusOverride(presentation.clip.topRightRadius) &&
|
|
57
|
+
validRadiusOverride(presentation.clip.bottomRightRadius) &&
|
|
58
|
+
validRadiusOverride(presentation.clip.bottomLeftRadius) &&
|
|
59
|
+
(presentation.clip.curve == ClipCurve::Circular ||
|
|
60
|
+
presentation.clip.curve == ClipCurve::Continuous) &&
|
|
41
61
|
std::isfinite(presentation.contentTranslateX) &&
|
|
42
|
-
std::isfinite(presentation.contentTranslateY)
|
|
62
|
+
std::isfinite(presentation.contentTranslateY) &&
|
|
63
|
+
std::isfinite(presentation.contentScale) &&
|
|
64
|
+
presentation.contentScale > 0;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
bool finitePresentation(const Presentation &presentation) {
|
|
68
|
+
return finiteBasePresentation(presentation) &&
|
|
69
|
+
std::isfinite(presentation.clip.topLeftRadius) &&
|
|
70
|
+
std::isfinite(presentation.clip.topRightRadius) &&
|
|
71
|
+
std::isfinite(presentation.clip.bottomRightRadius) &&
|
|
72
|
+
std::isfinite(presentation.clip.bottomLeftRadius) &&
|
|
73
|
+
std::isfinite(presentation.shadow.red) &&
|
|
74
|
+
std::isfinite(presentation.shadow.green) &&
|
|
75
|
+
std::isfinite(presentation.shadow.blue) &&
|
|
76
|
+
std::isfinite(presentation.shadow.alpha) &&
|
|
77
|
+
std::isfinite(presentation.shadow.offsetX) &&
|
|
78
|
+
std::isfinite(presentation.shadow.offsetY) &&
|
|
79
|
+
std::isfinite(presentation.shadow.blurRadius) &&
|
|
80
|
+
std::isfinite(presentation.shadow.spreadDistance) &&
|
|
81
|
+
presentation.shadow.red >= 0 && presentation.shadow.red <= 1 &&
|
|
82
|
+
presentation.shadow.green >= 0 && presentation.shadow.green <= 1 &&
|
|
83
|
+
presentation.shadow.blue >= 0 && presentation.shadow.blue <= 1 &&
|
|
84
|
+
presentation.shadow.alpha >= 0 && presentation.shadow.alpha <= 1 &&
|
|
85
|
+
presentation.shadow.blurRadius >= 0;
|
|
43
86
|
}
|
|
44
87
|
|
|
45
88
|
bool boolArg(const Value *args, size_t count, size_t index) {
|
|
46
89
|
return index < count && args[index].isBool() && args[index].getBool();
|
|
47
90
|
}
|
|
48
91
|
|
|
92
|
+
bool numberAt(
|
|
93
|
+
Runtime &runtime,
|
|
94
|
+
const Array &values,
|
|
95
|
+
size_t index,
|
|
96
|
+
double &result) {
|
|
97
|
+
if (index >= values.size(runtime)) return false;
|
|
98
|
+
const Value value = values.getValueAtIndex(runtime, index);
|
|
99
|
+
if (!value.isNumber()) return false;
|
|
100
|
+
result = value.asNumber();
|
|
101
|
+
return std::isfinite(result);
|
|
102
|
+
}
|
|
103
|
+
|
|
49
104
|
// Optional trailing start stamp (Reanimated-rule milliseconds captured in the
|
|
50
105
|
// issuing worklet), converted to the registry's CLOCK_MONOTONIC seconds. A
|
|
51
106
|
// missing or non-numeric argument — and the JS side's deliberate NaN fallback
|
|
@@ -58,26 +113,89 @@ double startStampArg(const Value *args, size_t count, size_t index) {
|
|
|
58
113
|
: std::numeric_limits<double>::quiet_NaN();
|
|
59
114
|
}
|
|
60
115
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
116
|
+
bool presentationAt(
|
|
117
|
+
Runtime &runtime,
|
|
118
|
+
const Array &values,
|
|
119
|
+
size_t offset,
|
|
120
|
+
Presentation &result) {
|
|
121
|
+
const size_t length = values.size(runtime);
|
|
122
|
+
if (offset > length || length - offset < kPresentationStride) {
|
|
123
|
+
return false;
|
|
124
|
+
}
|
|
125
|
+
double packet[kPresentationStride];
|
|
126
|
+
for (size_t index = 0; index < kPresentationStride; index += 1) {
|
|
127
|
+
const Value value = values.getValueAtIndex(runtime, offset + index);
|
|
128
|
+
if (!value.isNumber()) return false;
|
|
129
|
+
packet[index] = value.asNumber();
|
|
130
|
+
}
|
|
131
|
+
const double curveCode = packet[8];
|
|
132
|
+
if (!validCurve(curveCode) ||
|
|
133
|
+
(packet[12] != 0.0 && packet[12] != 1.0)) {
|
|
134
|
+
return false;
|
|
135
|
+
}
|
|
136
|
+
Geometry geometry{
|
|
137
|
+
packet[0], packet[1], packet[2], packet[3],
|
|
138
|
+
0.0};
|
|
139
|
+
geometry.topLeftRadius = packet[4];
|
|
140
|
+
geometry.topRightRadius = packet[5];
|
|
141
|
+
geometry.bottomRightRadius = packet[6];
|
|
142
|
+
geometry.bottomLeftRadius = packet[7];
|
|
143
|
+
geometry.curve = curveCode == static_cast<double>(ClipCurve::Continuous)
|
|
144
|
+
? ClipCurve::Continuous
|
|
145
|
+
: ClipCurve::Circular;
|
|
146
|
+
if (geometry.topLeftRadius == geometry.topRightRadius &&
|
|
147
|
+
geometry.topLeftRadius == geometry.bottomRightRadius &&
|
|
148
|
+
geometry.topLeftRadius == geometry.bottomLeftRadius) {
|
|
149
|
+
geometry.radius = geometry.topLeftRadius;
|
|
150
|
+
}
|
|
151
|
+
result = Presentation{
|
|
152
|
+
geometry,
|
|
153
|
+
packet[9], packet[10], packet[11],
|
|
154
|
+
Shadow{
|
|
155
|
+
packet[12] == 1.0,
|
|
156
|
+
packet[13], packet[14], packet[15], packet[16],
|
|
157
|
+
packet[17], packet[18], packet[19], packet[20]}};
|
|
158
|
+
return finitePresentation(result);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
void appendPresentation(
|
|
162
|
+
Runtime &runtime,
|
|
163
|
+
Array &result,
|
|
164
|
+
size_t &offset,
|
|
165
|
+
const Presentation &presentation) {
|
|
166
|
+
result.setValueAtIndex(runtime, offset++, presentation.clip.x);
|
|
167
|
+
result.setValueAtIndex(runtime, offset++, presentation.clip.y);
|
|
168
|
+
result.setValueAtIndex(runtime, offset++, presentation.clip.width);
|
|
169
|
+
result.setValueAtIndex(runtime, offset++, presentation.clip.height);
|
|
170
|
+
result.setValueAtIndex(runtime, offset++, SmoothClipResolvedRadius(
|
|
171
|
+
presentation.clip.topLeftRadius, presentation.clip.radius));
|
|
172
|
+
result.setValueAtIndex(runtime, offset++, SmoothClipResolvedRadius(
|
|
173
|
+
presentation.clip.topRightRadius, presentation.clip.radius));
|
|
174
|
+
result.setValueAtIndex(runtime, offset++, SmoothClipResolvedRadius(
|
|
175
|
+
presentation.clip.bottomRightRadius, presentation.clip.radius));
|
|
176
|
+
result.setValueAtIndex(runtime, offset++, SmoothClipResolvedRadius(
|
|
177
|
+
presentation.clip.bottomLeftRadius, presentation.clip.radius));
|
|
178
|
+
result.setValueAtIndex(
|
|
179
|
+
runtime, offset++, static_cast<double>(presentation.clip.curve));
|
|
180
|
+
result.setValueAtIndex(runtime, offset++, presentation.contentTranslateX);
|
|
181
|
+
result.setValueAtIndex(runtime, offset++, presentation.contentTranslateY);
|
|
182
|
+
result.setValueAtIndex(runtime, offset++, presentation.contentScale);
|
|
183
|
+
result.setValueAtIndex(
|
|
184
|
+
runtime, offset++, presentation.shadow.enabled ? 1.0 : 0.0);
|
|
185
|
+
result.setValueAtIndex(runtime, offset++, presentation.shadow.red);
|
|
186
|
+
result.setValueAtIndex(runtime, offset++, presentation.shadow.green);
|
|
187
|
+
result.setValueAtIndex(runtime, offset++, presentation.shadow.blue);
|
|
188
|
+
result.setValueAtIndex(runtime, offset++, presentation.shadow.alpha);
|
|
189
|
+
result.setValueAtIndex(runtime, offset++, presentation.shadow.offsetX);
|
|
190
|
+
result.setValueAtIndex(runtime, offset++, presentation.shadow.offsetY);
|
|
191
|
+
result.setValueAtIndex(runtime, offset++, presentation.shadow.blurRadius);
|
|
192
|
+
result.setValueAtIndex(runtime, offset++, presentation.shadow.spreadDistance);
|
|
70
193
|
}
|
|
71
194
|
|
|
72
195
|
Array presentationArray(Runtime &runtime, const Presentation &presentation) {
|
|
73
|
-
Array result(runtime,
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
result.setValueAtIndex(runtime, 2, presentation.clip.width);
|
|
77
|
-
result.setValueAtIndex(runtime, 3, presentation.clip.height);
|
|
78
|
-
result.setValueAtIndex(runtime, 4, presentation.clip.radius);
|
|
79
|
-
result.setValueAtIndex(runtime, 5, presentation.contentTranslateX);
|
|
80
|
-
result.setValueAtIndex(runtime, 6, presentation.contentTranslateY);
|
|
196
|
+
Array result(runtime, kPresentationStride);
|
|
197
|
+
size_t offset = 0;
|
|
198
|
+
appendPresentation(runtime, result, offset, presentation);
|
|
81
199
|
return result;
|
|
82
200
|
}
|
|
83
201
|
|
|
@@ -85,23 +203,78 @@ Array cancelResultArray(
|
|
|
85
203
|
Runtime &runtime,
|
|
86
204
|
bool handled,
|
|
87
205
|
const Presentation &presentation) {
|
|
88
|
-
Array result(runtime,
|
|
89
|
-
// JS checks `values[0] !== 1`, so the handled flag must be a number.
|
|
206
|
+
Array result(runtime, kSnapshotStride);
|
|
90
207
|
result.setValueAtIndex(runtime, 0, handled ? 1.0 : 0.0);
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
result
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
208
|
+
size_t offset = 1;
|
|
209
|
+
appendPresentation(runtime, result, offset, presentation);
|
|
210
|
+
return result;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
Array snapshotsArray(
|
|
214
|
+
Runtime &runtime,
|
|
215
|
+
const std::vector<DriverSnapshot> &snapshots) {
|
|
216
|
+
Array result(runtime, snapshots.size() * kSnapshotStride);
|
|
217
|
+
size_t offset = 0;
|
|
218
|
+
for (const DriverSnapshot &snapshot : snapshots) {
|
|
219
|
+
result.setValueAtIndex(runtime, offset++, snapshot.ready ? 1.0 : 0.0);
|
|
220
|
+
const Presentation &presentation = snapshot.presentation;
|
|
221
|
+
appendPresentation(runtime, result, offset, presentation);
|
|
222
|
+
}
|
|
98
223
|
return result;
|
|
99
224
|
}
|
|
100
225
|
|
|
226
|
+
std::vector<uint64_t> driverIdsFromArray(Runtime &runtime, const Array &values) {
|
|
227
|
+
std::vector<uint64_t> driverIds;
|
|
228
|
+
const size_t length = values.size(runtime);
|
|
229
|
+
driverIds.reserve(length);
|
|
230
|
+
for (size_t index = 0; index < length; index += 1) {
|
|
231
|
+
double value;
|
|
232
|
+
if (!numberAt(runtime, values, index, value) || !validDriverId(value) ||
|
|
233
|
+
std::find(driverIds.begin(), driverIds.end(),
|
|
234
|
+
static_cast<uint64_t>(value)) != driverIds.end()) {
|
|
235
|
+
return {};
|
|
236
|
+
}
|
|
237
|
+
driverIds.push_back(static_cast<uint64_t>(value));
|
|
238
|
+
}
|
|
239
|
+
return driverIds;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
bool parseGroupMotionEntries(
|
|
243
|
+
Runtime &runtime,
|
|
244
|
+
const Array &values,
|
|
245
|
+
std::vector<GroupMotionEntry> &entries) {
|
|
246
|
+
const size_t length = values.size(runtime);
|
|
247
|
+
if (length < kMotionEntryStride || length % kMotionEntryStride != 0) {
|
|
248
|
+
return false;
|
|
249
|
+
}
|
|
250
|
+
entries.reserve(length / kMotionEntryStride);
|
|
251
|
+
for (size_t index = 0; index < length; index += kMotionEntryStride) {
|
|
252
|
+
double driverId;
|
|
253
|
+
double hasFromValue;
|
|
254
|
+
Presentation from;
|
|
255
|
+
Presentation target;
|
|
256
|
+
if (!numberAt(runtime, values, index, driverId) ||
|
|
257
|
+
!numberAt(runtime, values, index + 1, hasFromValue) ||
|
|
258
|
+
!presentationAt(runtime, values, index + 2, from) ||
|
|
259
|
+
!presentationAt(
|
|
260
|
+
runtime, values, index + 2 + kPresentationStride, target) ||
|
|
261
|
+
!validDriverId(driverId) ||
|
|
262
|
+
(hasFromValue != 0.0 && hasFromValue != 1.0) ||
|
|
263
|
+
!finitePresentation(from) || !finitePresentation(target)) {
|
|
264
|
+
entries.clear();
|
|
265
|
+
return false;
|
|
266
|
+
}
|
|
267
|
+
entries.push_back(
|
|
268
|
+
{static_cast<uint64_t>(driverId), hasFromValue == 1.0, from, target});
|
|
269
|
+
}
|
|
270
|
+
return true;
|
|
271
|
+
}
|
|
272
|
+
|
|
101
273
|
struct BindingsState {
|
|
102
274
|
Runtime *runtime = nullptr;
|
|
103
275
|
std::shared_ptr<CallInvoker> callInvoker;
|
|
104
276
|
std::unordered_map<int32_t, std::shared_ptr<Function>> listeners;
|
|
277
|
+
std::unordered_map<int32_t, std::shared_ptr<Function>> groupListeners;
|
|
105
278
|
int32_t nextListenerId = 0;
|
|
106
279
|
};
|
|
107
280
|
|
|
@@ -137,15 +310,21 @@ void installBindings(
|
|
|
137
310
|
// against — the new one; the TurboModule invalidate hook releases them
|
|
138
311
|
// while their runtime is still alive, and this is the safety net.
|
|
139
312
|
state->listeners.clear();
|
|
313
|
+
state->groupListeners.clear();
|
|
140
314
|
state->runtime = &runtime;
|
|
141
315
|
state->callInvoker = callInvoker;
|
|
142
316
|
|
|
143
317
|
setCompletionCallback(
|
|
144
318
|
state.get(),
|
|
145
|
-
[state](
|
|
319
|
+
[state](
|
|
320
|
+
uint64_t driverId,
|
|
321
|
+
int32_t animationId,
|
|
322
|
+
int32_t completionTag,
|
|
323
|
+
bool finished) {
|
|
146
324
|
auto invoker = state->callInvoker;
|
|
147
325
|
if (!invoker) return;
|
|
148
|
-
invoker->invokeAsync(
|
|
326
|
+
invoker->invokeAsync(
|
|
327
|
+
[state, driverId, animationId, completionTag, finished]() {
|
|
149
328
|
if (state->runtime == nullptr) return;
|
|
150
329
|
Runtime &rt = *state->runtime;
|
|
151
330
|
std::vector<std::shared_ptr<Function>> snapshot;
|
|
@@ -157,30 +336,260 @@ void installBindings(
|
|
|
157
336
|
Object result(rt);
|
|
158
337
|
result.setProperty(rt, "driverId", static_cast<double>(driverId));
|
|
159
338
|
result.setProperty(rt, "animationId", animationId);
|
|
339
|
+
result.setProperty(rt, "completionTag", completionTag);
|
|
160
340
|
result.setProperty(rt, "finished", finished);
|
|
161
341
|
listener->call(rt, std::move(result));
|
|
162
342
|
}
|
|
163
343
|
});
|
|
164
344
|
});
|
|
165
345
|
|
|
346
|
+
setGroupCompletionCallback(
|
|
347
|
+
state.get(),
|
|
348
|
+
[state](
|
|
349
|
+
uint64_t controllerId,
|
|
350
|
+
int32_t groupId,
|
|
351
|
+
int32_t completionTag,
|
|
352
|
+
bool finished,
|
|
353
|
+
std::vector<DriverSnapshot> snapshots) {
|
|
354
|
+
auto invoker = state->callInvoker;
|
|
355
|
+
if (!invoker) return;
|
|
356
|
+
invoker->invokeAsync(
|
|
357
|
+
[state, controllerId, groupId, completionTag, finished,
|
|
358
|
+
snapshots = std::move(snapshots)]() {
|
|
359
|
+
if (state->runtime == nullptr) return;
|
|
360
|
+
Runtime &rt = *state->runtime;
|
|
361
|
+
std::vector<std::shared_ptr<Function>> snapshot;
|
|
362
|
+
snapshot.reserve(state->groupListeners.size());
|
|
363
|
+
for (const auto &entry : state->groupListeners) {
|
|
364
|
+
snapshot.push_back(entry.second);
|
|
365
|
+
}
|
|
366
|
+
for (const auto &listener : snapshot) {
|
|
367
|
+
Object result(rt);
|
|
368
|
+
result.setProperty(
|
|
369
|
+
rt, "controllerId", static_cast<double>(controllerId));
|
|
370
|
+
result.setProperty(rt, "groupId", groupId);
|
|
371
|
+
result.setProperty(rt, "completionTag", completionTag);
|
|
372
|
+
result.setProperty(rt, "finished", finished);
|
|
373
|
+
result.setProperty(
|
|
374
|
+
rt, "snapshots", snapshotsArray(rt, snapshots));
|
|
375
|
+
listener->call(rt, std::move(result));
|
|
376
|
+
}
|
|
377
|
+
});
|
|
378
|
+
});
|
|
379
|
+
|
|
166
380
|
Object bindings(runtime);
|
|
167
381
|
|
|
168
382
|
setHostFunction(
|
|
169
|
-
runtime, bindings, "
|
|
383
|
+
runtime, bindings, "supportsAutonomousComplexPathAnimation", 0,
|
|
384
|
+
[](Runtime &, const Value &, const Value *, size_t) -> Value {
|
|
385
|
+
// Static complex clipping is available. Autonomous complex-path
|
|
386
|
+
// animation is deliberately gated off until physical-device sampling
|
|
387
|
+
// proves the release tolerance and frame-time requirements.
|
|
388
|
+
return Value(false);
|
|
389
|
+
});
|
|
390
|
+
|
|
391
|
+
setHostFunction(
|
|
392
|
+
runtime, bindings, "beginGroupInteraction", 1,
|
|
393
|
+
[](Runtime &rt, const Value &, const Value *args, size_t count) -> Value {
|
|
394
|
+
if (count < 1 || !args[0].isObject() ||
|
|
395
|
+
!args[0].getObject(rt).isArray(rt)) {
|
|
396
|
+
return Array(rt, 0);
|
|
397
|
+
}
|
|
398
|
+
Array values = args[0].getObject(rt).getArray(rt);
|
|
399
|
+
const std::vector<uint64_t> driverIds = driverIdsFromArray(rt, values);
|
|
400
|
+
if (driverIds.empty()) return Array(rt, 0);
|
|
401
|
+
return snapshotsArray(rt, beginGroupInteraction(driverIds));
|
|
402
|
+
});
|
|
403
|
+
|
|
404
|
+
setHostFunction(
|
|
405
|
+
runtime, bindings, "snapshotGroup", 1,
|
|
406
|
+
[](Runtime &rt, const Value &, const Value *args, size_t count) -> Value {
|
|
407
|
+
if (count < 1 || !args[0].isObject() ||
|
|
408
|
+
!args[0].getObject(rt).isArray(rt)) {
|
|
409
|
+
return Array(rt, 0);
|
|
410
|
+
}
|
|
411
|
+
Array values = args[0].getObject(rt).getArray(rt);
|
|
412
|
+
const std::vector<uint64_t> driverIds = driverIdsFromArray(rt, values);
|
|
413
|
+
if (driverIds.empty()) return Array(rt, 0);
|
|
414
|
+
return snapshotsArray(rt, snapshotGroup(driverIds));
|
|
415
|
+
});
|
|
416
|
+
|
|
417
|
+
setHostFunction(
|
|
418
|
+
runtime, bindings, "setClipPresentationBatch", 1,
|
|
419
|
+
[](Runtime &rt, const Value &, const Value *args, size_t count) -> Value {
|
|
420
|
+
if (count < 1 || !args[0].isObject() ||
|
|
421
|
+
!args[0].getObject(rt).isArray(rt)) {
|
|
422
|
+
return Value(false);
|
|
423
|
+
}
|
|
424
|
+
Array values = args[0].getObject(rt).getArray(rt);
|
|
425
|
+
const size_t length = values.size(rt);
|
|
426
|
+
if (length < kSnapshotStride || length % kSnapshotStride != 0) {
|
|
427
|
+
return Value(false);
|
|
428
|
+
}
|
|
429
|
+
std::vector<BatchEntry> entries;
|
|
430
|
+
entries.reserve(length / kSnapshotStride);
|
|
431
|
+
for (size_t index = 0; index < length; index += kSnapshotStride) {
|
|
432
|
+
double driverId;
|
|
433
|
+
Presentation presentation;
|
|
434
|
+
if (!numberAt(rt, values, index, driverId) ||
|
|
435
|
+
!presentationAt(rt, values, index + 1, presentation) ||
|
|
436
|
+
!validDriverId(driverId) || !finitePresentation(presentation)) {
|
|
437
|
+
return Value(false);
|
|
438
|
+
}
|
|
439
|
+
entries.push_back(
|
|
440
|
+
{static_cast<uint64_t>(driverId), presentation});
|
|
441
|
+
}
|
|
442
|
+
return Value(setPresentationBatch(entries));
|
|
443
|
+
});
|
|
444
|
+
|
|
445
|
+
setHostFunction(
|
|
446
|
+
runtime, bindings, "animateTimingGroup", 10,
|
|
447
|
+
[](Runtime &rt, const Value &, const Value *args, size_t count) -> Value {
|
|
448
|
+
if (count < 10 || !args[1].isObject() ||
|
|
449
|
+
!args[1].getObject(rt).isArray(rt)) {
|
|
450
|
+
return Value(0);
|
|
451
|
+
}
|
|
452
|
+
const double controllerId = args[0].asNumber();
|
|
453
|
+
Array values = args[1].getObject(rt).getArray(rt);
|
|
454
|
+
std::vector<GroupMotionEntry> entries;
|
|
455
|
+
const TimingAnimation animation{
|
|
456
|
+
args[2].asNumber(), args[3].asNumber(), args[4].asNumber(),
|
|
457
|
+
args[5].asNumber(), args[6].asNumber(),
|
|
458
|
+
static_cast<int32_t>(args[7].asNumber())};
|
|
459
|
+
if (!validDriverId(controllerId) ||
|
|
460
|
+
!parseGroupMotionEntries(rt, values, entries) ||
|
|
461
|
+
!std::isfinite(animation.durationMs) ||
|
|
462
|
+
!std::isfinite(animation.controlPoint1X) ||
|
|
463
|
+
!std::isfinite(animation.controlPoint1Y) ||
|
|
464
|
+
!std::isfinite(animation.controlPoint2X) ||
|
|
465
|
+
!std::isfinite(animation.controlPoint2Y) ||
|
|
466
|
+
!std::isfinite(args[8].asNumber())) {
|
|
467
|
+
return Value(0);
|
|
468
|
+
}
|
|
469
|
+
return Value(animateTimingGroup(
|
|
470
|
+
static_cast<uint64_t>(controllerId),
|
|
471
|
+
std::move(entries),
|
|
472
|
+
animation,
|
|
473
|
+
static_cast<int32_t>(args[8].asNumber()),
|
|
474
|
+
startStampArg(args, count, 9)));
|
|
475
|
+
});
|
|
476
|
+
|
|
477
|
+
setHostFunction(
|
|
478
|
+
runtime, bindings, "animateSpringGroup", 10,
|
|
170
479
|
[](Runtime &rt, const Value &, const Value *args, size_t count) -> Value {
|
|
171
|
-
if (count <
|
|
480
|
+
if (count < 10 || !args[1].isObject() ||
|
|
481
|
+
!args[1].getObject(rt).isArray(rt)) {
|
|
482
|
+
return Value(0);
|
|
483
|
+
}
|
|
484
|
+
const double controllerId = args[0].asNumber();
|
|
485
|
+
Array values = args[1].getObject(rt).getArray(rt);
|
|
486
|
+
std::vector<GroupMotionEntry> entries;
|
|
487
|
+
const SpringAnimation animation{
|
|
488
|
+
args[2].asNumber(), args[3].asNumber(), args[4].asNumber(),
|
|
489
|
+
args[5].asNumber(), false,
|
|
490
|
+
static_cast<int32_t>(args[7].asNumber()),
|
|
491
|
+
args[6].asNumber()};
|
|
492
|
+
if (!validDriverId(controllerId) ||
|
|
493
|
+
!parseGroupMotionEntries(rt, values, entries) ||
|
|
494
|
+
!std::isfinite(animation.mass) ||
|
|
495
|
+
!std::isfinite(animation.stiffness) ||
|
|
496
|
+
!std::isfinite(animation.damping) ||
|
|
497
|
+
!std::isfinite(animation.initialVelocity) || animation.mass <= 0 ||
|
|
498
|
+
!std::isfinite(animation.energyThreshold) ||
|
|
499
|
+
!std::isfinite(args[8].asNumber()) || animation.stiffness <= 0 ||
|
|
500
|
+
animation.damping < 0 || animation.energyThreshold <= 0) {
|
|
501
|
+
return Value(0);
|
|
502
|
+
}
|
|
503
|
+
return Value(animateSpringGroup(
|
|
504
|
+
static_cast<uint64_t>(controllerId),
|
|
505
|
+
std::move(entries),
|
|
506
|
+
animation,
|
|
507
|
+
static_cast<int32_t>(args[8].asNumber()),
|
|
508
|
+
startStampArg(args, count, 9)));
|
|
509
|
+
});
|
|
510
|
+
|
|
511
|
+
setHostFunction(
|
|
512
|
+
runtime, bindings, "cancelAnimationGroup", 2,
|
|
513
|
+
[](Runtime &rt, const Value &, const Value *args, size_t count) -> Value {
|
|
514
|
+
if (count < 2 || !args[0].isNumber() || !args[1].isNumber()) {
|
|
515
|
+
return Array(rt, 0);
|
|
516
|
+
}
|
|
517
|
+
const double groupId = args[0].asNumber();
|
|
518
|
+
const double behavior = args[1].asNumber();
|
|
519
|
+
if (!std::isfinite(groupId) || groupId <= 0 ||
|
|
520
|
+
std::floor(groupId) != groupId ||
|
|
521
|
+
(behavior != static_cast<double>(GroupCancelBehavior::Freeze) &&
|
|
522
|
+
behavior != static_cast<double>(GroupCancelBehavior::Finish))) {
|
|
523
|
+
return Array(rt, 0);
|
|
524
|
+
}
|
|
525
|
+
return snapshotsArray(
|
|
526
|
+
rt,
|
|
527
|
+
cancelAnimationGroup(
|
|
528
|
+
static_cast<int32_t>(groupId),
|
|
529
|
+
static_cast<GroupCancelBehavior>(
|
|
530
|
+
static_cast<int32_t>(behavior))));
|
|
531
|
+
});
|
|
532
|
+
|
|
533
|
+
setHostFunction(
|
|
534
|
+
runtime, bindings, "setClipPresentation", 4,
|
|
535
|
+
[](Runtime &rt, const Value &, const Value *args, size_t count) -> Value {
|
|
536
|
+
if (count < 4 || !args[0].isNumber() || !args[1].isObject() ||
|
|
537
|
+
!args[1].getObject(rt).isArray(rt)) {
|
|
538
|
+
return Value::undefined();
|
|
539
|
+
}
|
|
540
|
+
const double driverId = args[0].asNumber();
|
|
541
|
+
const Array values = args[1].getObject(rt).getArray(rt);
|
|
542
|
+
Presentation presentation;
|
|
543
|
+
if (values.size(rt) == kPresentationStride &&
|
|
544
|
+
validDriverId(driverId) &&
|
|
545
|
+
presentationAt(rt, values, 0, presentation)) {
|
|
546
|
+
setPresentation(
|
|
547
|
+
static_cast<uint64_t>(driverId), presentation,
|
|
548
|
+
boolArg(args, count, 2), boolArg(args, count, 3), true);
|
|
549
|
+
}
|
|
550
|
+
return Value::undefined();
|
|
551
|
+
});
|
|
552
|
+
|
|
553
|
+
setHostFunction(
|
|
554
|
+
runtime, bindings, "setClipFrameScalars", 22,
|
|
555
|
+
[](Runtime &, const Value &, const Value *args, size_t count) -> Value {
|
|
556
|
+
if (count < 22) return Value::undefined();
|
|
172
557
|
const double driverId = args[0].asNumber();
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
558
|
+
Geometry geometry{
|
|
559
|
+
args[1].asNumber(), args[2].asNumber(), args[3].asNumber(),
|
|
560
|
+
args[4].asNumber(), 0};
|
|
561
|
+
geometry.topLeftRadius = args[5].asNumber();
|
|
562
|
+
geometry.topRightRadius = args[6].asNumber();
|
|
563
|
+
geometry.bottomRightRadius = args[7].asNumber();
|
|
564
|
+
geometry.bottomLeftRadius = args[8].asNumber();
|
|
565
|
+
geometry.curve = static_cast<ClipCurve>(
|
|
566
|
+
static_cast<int32_t>(args[9].asNumber()));
|
|
567
|
+
if (geometry.topLeftRadius == geometry.topRightRadius &&
|
|
568
|
+
geometry.topLeftRadius == geometry.bottomRightRadius &&
|
|
569
|
+
geometry.topLeftRadius == geometry.bottomLeftRadius) {
|
|
570
|
+
geometry.radius = geometry.topLeftRadius;
|
|
571
|
+
}
|
|
572
|
+
const Presentation presentation{
|
|
573
|
+
geometry,
|
|
574
|
+
args[10].asNumber(),
|
|
575
|
+
args[11].asNumber(),
|
|
576
|
+
args[12].asNumber(),
|
|
577
|
+
{
|
|
578
|
+
boolArg(args, count, 13),
|
|
579
|
+
args[14].asNumber(),
|
|
580
|
+
args[15].asNumber(),
|
|
581
|
+
args[16].asNumber(),
|
|
582
|
+
args[17].asNumber(),
|
|
583
|
+
args[18].asNumber(),
|
|
584
|
+
args[19].asNumber(),
|
|
585
|
+
args[20].asNumber(),
|
|
586
|
+
args[21].asNumber(),
|
|
587
|
+
}};
|
|
588
|
+
if (validDriverId(driverId) && validCurve(args[9].asNumber()) &&
|
|
589
|
+
finitePresentation(presentation)) {
|
|
181
590
|
setPresentation(
|
|
182
|
-
static_cast<uint64_t>(driverId), presentation,
|
|
183
|
-
|
|
591
|
+
static_cast<uint64_t>(driverId), presentation,
|
|
592
|
+
true, false, true);
|
|
184
593
|
}
|
|
185
594
|
return Value::undefined();
|
|
186
595
|
});
|
|
@@ -196,104 +605,91 @@ void installBindings(
|
|
|
196
605
|
});
|
|
197
606
|
|
|
198
607
|
setHostFunction(
|
|
199
|
-
runtime, bindings, "
|
|
608
|
+
runtime, bindings, "snapshotCurrent", 1,
|
|
200
609
|
[](Runtime &rt, const Value &, const Value *args, size_t count) -> Value {
|
|
201
|
-
if (count <
|
|
202
|
-
|
|
203
|
-
const Presentation start = presentationFromArgs(args, 2);
|
|
204
|
-
const Presentation target = presentationFromArgs(args, 9);
|
|
205
|
-
const TimingAnimation animation{
|
|
206
|
-
args[16].asNumber(), args[17].asNumber(), args[18].asNumber(),
|
|
207
|
-
args[19].asNumber(), args[20].asNumber(),
|
|
208
|
-
static_cast<int32_t>(args[21].asNumber())};
|
|
209
|
-
if (!validDriverId(driverId) || !finitePresentation(start) ||
|
|
210
|
-
!finitePresentation(target) ||
|
|
211
|
-
!std::isfinite(animation.durationMs)) {
|
|
212
|
-
return Value(0);
|
|
610
|
+
if (count < 1 || !validDriverId(args[0].asNumber())) {
|
|
611
|
+
return presentationArray(rt, {{0, 0, 0, 0, 0}, 0, 0});
|
|
213
612
|
}
|
|
214
|
-
return
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
animation));
|
|
613
|
+
return presentationArray(
|
|
614
|
+
rt,
|
|
615
|
+
snapshotCurrentAndroid(
|
|
616
|
+
static_cast<uint64_t>(args[0].asNumber())));
|
|
219
617
|
});
|
|
220
618
|
|
|
221
619
|
setHostFunction(
|
|
222
|
-
runtime, bindings, "
|
|
620
|
+
runtime, bindings, "animateTiming", 11,
|
|
223
621
|
[](Runtime &rt, const Value &, const Value *args, size_t count) -> Value {
|
|
224
|
-
if (count <
|
|
622
|
+
if (count < 10 || !args[0].isNumber() || !args[1].isObject() ||
|
|
623
|
+
!args[1].getObject(rt).isArray(rt) || !args[2].isObject() ||
|
|
624
|
+
!args[2].getObject(rt).isArray(rt) || !args[9].isNumber() ||
|
|
625
|
+
!std::isfinite(args[9].asNumber())) {
|
|
626
|
+
return Value(0);
|
|
627
|
+
}
|
|
225
628
|
const double driverId = args[0].asNumber();
|
|
226
|
-
const
|
|
227
|
-
const
|
|
228
|
-
const
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
629
|
+
const Array startValues = args[1].getObject(rt).getArray(rt);
|
|
630
|
+
const Array targetValues = args[2].getObject(rt).getArray(rt);
|
|
631
|
+
const bool hasInteractiveStart = startValues.size(rt) != 0;
|
|
632
|
+
Presentation start{};
|
|
633
|
+
Presentation target;
|
|
634
|
+
const TimingAnimation animation{
|
|
635
|
+
args[3].asNumber(), args[4].asNumber(), args[5].asNumber(),
|
|
636
|
+
args[6].asNumber(), args[7].asNumber(),
|
|
637
|
+
static_cast<int32_t>(args[8].asNumber())};
|
|
638
|
+
if (!validDriverId(driverId) ||
|
|
639
|
+
(hasInteractiveStart &&
|
|
640
|
+
(startValues.size(rt) != kPresentationStride ||
|
|
641
|
+
!presentationAt(rt, startValues, 0, start))) ||
|
|
642
|
+
targetValues.size(rt) != kPresentationStride ||
|
|
643
|
+
!presentationAt(rt, targetValues, 0, target) ||
|
|
644
|
+
!std::isfinite(animation.durationMs)) {
|
|
239
645
|
return Value(0);
|
|
240
646
|
}
|
|
241
|
-
return Value(
|
|
647
|
+
return Value(animateTiming(
|
|
242
648
|
static_cast<uint64_t>(driverId),
|
|
243
|
-
{
|
|
649
|
+
{hasInteractiveStart, start, startStampArg(args, count, 10)},
|
|
244
650
|
target,
|
|
245
|
-
animation
|
|
651
|
+
animation,
|
|
652
|
+
static_cast<int32_t>(args[9].asNumber())));
|
|
246
653
|
});
|
|
247
654
|
|
|
248
655
|
setHostFunction(
|
|
249
|
-
runtime, bindings, "
|
|
656
|
+
runtime, bindings, "animateSpring", 11,
|
|
250
657
|
[](Runtime &rt, const Value &, const Value *args, size_t count) -> Value {
|
|
251
|
-
if (count <
|
|
252
|
-
!args[
|
|
658
|
+
if (count < 10 || !args[0].isNumber() || !args[1].isObject() ||
|
|
659
|
+
!args[1].getObject(rt).isArray(rt) || !args[2].isObject() ||
|
|
660
|
+
!args[2].getObject(rt).isArray(rt) || !args[9].isNumber() ||
|
|
661
|
+
!std::isfinite(args[9].asNumber())) {
|
|
253
662
|
return Value(0);
|
|
254
663
|
}
|
|
255
664
|
const double driverId = args[0].asNumber();
|
|
256
|
-
const
|
|
257
|
-
const
|
|
258
|
-
const
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
const
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
frames.getValueAtIndex(rt, index + 4).asNumber(),
|
|
277
|
-
frames.getValueAtIndex(rt, index + 5).asNumber()},
|
|
278
|
-
frames.getValueAtIndex(rt, index + 6).asNumber(),
|
|
279
|
-
frames.getValueAtIndex(rt, index + 7).asNumber()};
|
|
280
|
-
if (!std::isfinite(offset) || offset < 0 || offset > 1 ||
|
|
281
|
-
offset <= previousOffset || !finitePresentation(frame)) {
|
|
282
|
-
return Value(0);
|
|
283
|
-
}
|
|
284
|
-
previousOffset = offset;
|
|
285
|
-
keyframes.push_back({offset, frame});
|
|
286
|
-
}
|
|
287
|
-
if (keyframes.front().offset != 0 || keyframes.back().offset != 1) {
|
|
665
|
+
const Array startValues = args[1].getObject(rt).getArray(rt);
|
|
666
|
+
const Array targetValues = args[2].getObject(rt).getArray(rt);
|
|
667
|
+
const bool hasInteractiveStart = startValues.size(rt) != 0;
|
|
668
|
+
Presentation start{};
|
|
669
|
+
Presentation target;
|
|
670
|
+
const SpringAnimation animation{
|
|
671
|
+
args[3].asNumber(), args[4].asNumber(), args[5].asNumber(),
|
|
672
|
+
args[6].asNumber(), boolArg(args, count, 7),
|
|
673
|
+
static_cast<int32_t>(args[8].asNumber())};
|
|
674
|
+
if (!validDriverId(driverId) ||
|
|
675
|
+
(hasInteractiveStart &&
|
|
676
|
+
(startValues.size(rt) != kPresentationStride ||
|
|
677
|
+
!presentationAt(rt, startValues, 0, start))) ||
|
|
678
|
+
targetValues.size(rt) != kPresentationStride ||
|
|
679
|
+
!presentationAt(rt, targetValues, 0, target) ||
|
|
680
|
+
!std::isfinite(animation.mass) ||
|
|
681
|
+
!std::isfinite(animation.stiffness) ||
|
|
682
|
+
!std::isfinite(animation.damping) ||
|
|
683
|
+
!std::isfinite(animation.initialVelocity) || animation.mass <= 0 ||
|
|
684
|
+
animation.stiffness <= 0 || animation.damping < 0) {
|
|
288
685
|
return Value(0);
|
|
289
686
|
}
|
|
290
|
-
return Value(
|
|
687
|
+
return Value(animateSpring(
|
|
291
688
|
static_cast<uint64_t>(driverId),
|
|
292
|
-
{
|
|
689
|
+
{hasInteractiveStart, start, startStampArg(args, count, 10)},
|
|
293
690
|
target,
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
reduceMotion));
|
|
691
|
+
animation,
|
|
692
|
+
static_cast<int32_t>(args[9].asNumber())));
|
|
297
693
|
});
|
|
298
694
|
|
|
299
695
|
setHostFunction(
|
|
@@ -308,13 +704,15 @@ void installBindings(
|
|
|
308
704
|
runtime, bindings, "cancelAnimation", 3,
|
|
309
705
|
[](Runtime &rt, const Value &, const Value *args, size_t count) -> Value {
|
|
310
706
|
if (count < 3 || !validDriverId(args[0].asNumber())) {
|
|
311
|
-
return cancelResultArray(
|
|
707
|
+
return cancelResultArray(
|
|
708
|
+
rt, false, {{0, 0, 0, 0, 0}, 0, 0});
|
|
312
709
|
}
|
|
313
710
|
const CancelResult result = cancelAnimation(
|
|
314
711
|
static_cast<uint64_t>(args[0].asNumber()),
|
|
315
712
|
static_cast<int32_t>(args[1].asNumber()),
|
|
316
713
|
static_cast<int32_t>(args[2].asNumber()) == 1);
|
|
317
|
-
return cancelResultArray(
|
|
714
|
+
return cancelResultArray(
|
|
715
|
+
rt, result.handled, result.presentation);
|
|
318
716
|
});
|
|
319
717
|
|
|
320
718
|
setHostFunction(
|
|
@@ -349,6 +747,29 @@ void installBindings(
|
|
|
349
747
|
return subscription;
|
|
350
748
|
});
|
|
351
749
|
|
|
750
|
+
setHostFunction(
|
|
751
|
+
runtime, bindings, "onClipGroupAnimationComplete", 1,
|
|
752
|
+
[state](Runtime &rt, const Value &, const Value *args, size_t count)
|
|
753
|
+
-> Value {
|
|
754
|
+
if (count < 1 || !args[0].isObject() ||
|
|
755
|
+
!args[0].getObject(rt).isFunction(rt)) {
|
|
756
|
+
return Value::undefined();
|
|
757
|
+
}
|
|
758
|
+
auto listener = std::make_shared<Function>(
|
|
759
|
+
args[0].getObject(rt).getFunction(rt));
|
|
760
|
+
const int32_t listenerId = ++state->nextListenerId;
|
|
761
|
+
state->groupListeners.emplace(listenerId, std::move(listener));
|
|
762
|
+
Object subscription(rt);
|
|
763
|
+
setHostFunction(
|
|
764
|
+
rt, subscription, "remove", 0,
|
|
765
|
+
[state, listenerId](
|
|
766
|
+
Runtime &, const Value &, const Value *, size_t) -> Value {
|
|
767
|
+
state->groupListeners.erase(listenerId);
|
|
768
|
+
return Value::undefined();
|
|
769
|
+
});
|
|
770
|
+
return subscription;
|
|
771
|
+
});
|
|
772
|
+
|
|
352
773
|
runtime.global().setProperty(runtime, "__SmoothClipView", bindings);
|
|
353
774
|
}
|
|
354
775
|
|
|
@@ -359,7 +780,9 @@ void invalidateBindings() {
|
|
|
359
780
|
// own runtime.
|
|
360
781
|
auto state = bindingsState();
|
|
361
782
|
clearCompletionCallback(state.get());
|
|
783
|
+
clearGroupCompletionCallback(state.get());
|
|
362
784
|
state->listeners.clear();
|
|
785
|
+
state->groupListeners.clear();
|
|
363
786
|
state->runtime = nullptr;
|
|
364
787
|
state->callInvoker = nullptr;
|
|
365
788
|
}
|
|
@@ -388,19 +811,70 @@ void nativeRegisterView(
|
|
|
388
811
|
jdouble y,
|
|
389
812
|
jdouble width,
|
|
390
813
|
jdouble height,
|
|
391
|
-
jdouble
|
|
814
|
+
jdouble topLeftRadius,
|
|
815
|
+
jdouble topRightRadius,
|
|
816
|
+
jdouble bottomRightRadius,
|
|
817
|
+
jdouble bottomLeftRadius,
|
|
818
|
+
jint curveCode,
|
|
392
819
|
jdouble contentTranslateX,
|
|
393
820
|
jdouble contentTranslateY,
|
|
821
|
+
jdouble contentScale,
|
|
822
|
+
jboolean shadowEnabled,
|
|
823
|
+
jdouble shadowRed,
|
|
824
|
+
jdouble shadowGreen,
|
|
825
|
+
jdouble shadowBlue,
|
|
826
|
+
jdouble shadowAlpha,
|
|
827
|
+
jdouble shadowOffsetX,
|
|
828
|
+
jdouble shadowOffsetY,
|
|
829
|
+
jdouble shadowBlurRadius,
|
|
830
|
+
jdouble shadowSpreadDistance,
|
|
394
831
|
jdouble density,
|
|
395
832
|
jdouble widthPx,
|
|
396
833
|
jdouble heightPx,
|
|
397
834
|
jboolean lifecycleVisible) {
|
|
398
|
-
if (driverId <= 0 || !std::isfinite(driverId))
|
|
835
|
+
if (driverId <= 0 || !std::isfinite(driverId) || !std::isfinite(x) ||
|
|
836
|
+
!std::isfinite(y) || !std::isfinite(width) || !std::isfinite(height) ||
|
|
837
|
+
!std::isfinite(topLeftRadius) || !std::isfinite(topRightRadius) ||
|
|
838
|
+
!std::isfinite(bottomRightRadius) || !std::isfinite(bottomLeftRadius) ||
|
|
839
|
+
!std::isfinite(contentTranslateX) ||
|
|
840
|
+
!std::isfinite(contentTranslateY) || !std::isfinite(contentScale) ||
|
|
841
|
+
!std::isfinite(shadowRed) || !std::isfinite(shadowGreen) ||
|
|
842
|
+
!std::isfinite(shadowBlue) || !std::isfinite(shadowAlpha) ||
|
|
843
|
+
!std::isfinite(shadowOffsetX) ||
|
|
844
|
+
!std::isfinite(shadowOffsetY) || !std::isfinite(shadowBlurRadius) ||
|
|
845
|
+
!std::isfinite(shadowSpreadDistance) || contentScale <= 0 ||
|
|
846
|
+
shadowRed < 0 || shadowRed > 1 || shadowGreen < 0 || shadowGreen > 1 ||
|
|
847
|
+
shadowBlue < 0 || shadowBlue > 1 || shadowAlpha < 0 || shadowAlpha > 1 ||
|
|
848
|
+
shadowBlurRadius < 0 ||
|
|
849
|
+
(curveCode != static_cast<jint>(smoothclip::ClipCurve::Circular) &&
|
|
850
|
+
curveCode != static_cast<jint>(smoothclip::ClipCurve::Continuous))) {
|
|
851
|
+
return;
|
|
852
|
+
}
|
|
853
|
+
smoothclip::Geometry geometry{x, y, width, height, 0.0};
|
|
854
|
+
geometry.topLeftRadius = topLeftRadius;
|
|
855
|
+
geometry.topRightRadius = topRightRadius;
|
|
856
|
+
geometry.bottomRightRadius = bottomRightRadius;
|
|
857
|
+
geometry.bottomLeftRadius = bottomLeftRadius;
|
|
858
|
+
geometry.curve = static_cast<smoothclip::ClipCurve>(curveCode);
|
|
859
|
+
if (topLeftRadius == topRightRadius && topLeftRadius == bottomRightRadius &&
|
|
860
|
+
topLeftRadius == bottomLeftRadius) {
|
|
861
|
+
geometry.radius = topLeftRadius;
|
|
862
|
+
}
|
|
863
|
+
smoothclip::Shadow shadow{
|
|
864
|
+
shadowEnabled != 0,
|
|
865
|
+
shadowRed,
|
|
866
|
+
shadowGreen,
|
|
867
|
+
shadowBlue,
|
|
868
|
+
shadowAlpha,
|
|
869
|
+
shadowOffsetX,
|
|
870
|
+
shadowOffsetY,
|
|
871
|
+
shadowBlurRadius,
|
|
872
|
+
shadowSpreadDistance};
|
|
399
873
|
smoothclip::registerViewAndroid(
|
|
400
874
|
static_cast<uint64_t>(driverId),
|
|
401
875
|
view,
|
|
402
876
|
smoothclip::Presentation{
|
|
403
|
-
|
|
877
|
+
geometry, contentTranslateX, contentTranslateY, contentScale, shadow},
|
|
404
878
|
density,
|
|
405
879
|
widthPx,
|
|
406
880
|
heightPx,
|
|
@@ -427,6 +901,13 @@ void nativeUnregisterView(
|
|
|
427
901
|
smoothclip::unregisterViewAndroid(static_cast<uint64_t>(driverId), view);
|
|
428
902
|
}
|
|
429
903
|
|
|
904
|
+
void nativeDestroyDriver(
|
|
905
|
+
jni::alias_ref<jni::JObject>,
|
|
906
|
+
jdouble driverId) {
|
|
907
|
+
if (driverId <= 0 || !std::isfinite(driverId)) return;
|
|
908
|
+
smoothclip::destroyDriver(static_cast<uint64_t>(driverId));
|
|
909
|
+
}
|
|
910
|
+
|
|
430
911
|
void nativeSetViewLifecycleVisibility(
|
|
431
912
|
jni::alias_ref<jni::JObject>,
|
|
432
913
|
jdouble driverId,
|
|
@@ -457,6 +938,7 @@ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *) {
|
|
|
457
938
|
makeNativeMethod(
|
|
458
939
|
"nativeSetViewHostGeometry", nativeSetViewHostGeometry),
|
|
459
940
|
makeNativeMethod("nativeUnregisterView", nativeUnregisterView),
|
|
941
|
+
makeNativeMethod("nativeDestroyDriver", nativeDestroyDriver),
|
|
460
942
|
makeNativeMethod(
|
|
461
943
|
"nativeSetViewLifecycleVisibility",
|
|
462
944
|
nativeSetViewLifecycleVisibility),
|