chore: update map
This commit is contained in:
+62
-18
@@ -441,6 +441,41 @@
|
|||||||
"@babel/core": "^7.0.0-0"
|
"@babel/core": "^7.0.0-0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@babel/plugin-proposal-nullish-coalescing-operator": {
|
||||||
|
"version": "7.18.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz",
|
||||||
|
"integrity": "sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA==",
|
||||||
|
"deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-nullish-coalescing-operator instead.",
|
||||||
|
"peer": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/helper-plugin-utils": "^7.18.6",
|
||||||
|
"@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.9.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@babel/core": "^7.0.0-0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@babel/plugin-proposal-optional-chaining": {
|
||||||
|
"version": "7.21.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.21.0.tgz",
|
||||||
|
"integrity": "sha512-p4zeefM72gpmEe2fkUr/OnOXpWEf8nAgk7ZYVqqfFiyIG7oFfVZcCrU64hWn5xp4tQ9LkV4bTIa5rD0KANpKNA==",
|
||||||
|
"deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-optional-chaining instead.",
|
||||||
|
"peer": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/helper-plugin-utils": "^7.20.2",
|
||||||
|
"@babel/helper-skip-transparent-expression-wrappers": "^7.20.0",
|
||||||
|
"@babel/plugin-syntax-optional-chaining": "^7.8.3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.9.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@babel/core": "^7.0.0-0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@babel/plugin-syntax-async-generators": {
|
"node_modules/@babel/plugin-syntax-async-generators": {
|
||||||
"version": "7.8.4",
|
"version": "7.8.4",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz",
|
||||||
@@ -984,6 +1019,20 @@
|
|||||||
"@babel/core": "^7.0.0-0"
|
"@babel/core": "^7.0.0-0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@babel/plugin-transform-object-assign": {
|
||||||
|
"version": "7.27.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-assign/-/plugin-transform-object-assign-7.27.1.tgz",
|
||||||
|
"integrity": "sha512-LP6tsnirA6iy13uBKiYgjJsfQrodmlSrpZModtlo1Vk8sOO68gfo7dfA9TGJyEgxTiO7czK4EGZm8FJEZtk4kQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/helper-plugin-utils": "^7.27.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.9.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@babel/core": "^7.0.0-0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@babel/plugin-transform-object-rest-spread": {
|
"node_modules/@babel/plugin-transform-object-rest-spread": {
|
||||||
"version": "7.28.6",
|
"version": "7.28.6",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.28.6.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.28.6.tgz",
|
||||||
@@ -6601,29 +6650,24 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/react-native-reanimated": {
|
"node_modules/react-native-reanimated": {
|
||||||
"version": "4.1.6",
|
"version": "3.6.3",
|
||||||
"resolved": "https://registry.npmjs.org/react-native-reanimated/-/react-native-reanimated-4.1.6.tgz",
|
"resolved": "https://registry.npmjs.org/react-native-reanimated/-/react-native-reanimated-3.6.3.tgz",
|
||||||
"integrity": "sha512-F+ZJBYiok/6Jzp1re75F/9aLzkgoQCOh4yxrnwATa8392RvM3kx+fiXXFvwcgE59v48lMwd9q0nzF1oJLXpfxQ==",
|
"integrity": "sha512-2KkkPozoIvDbJcHuf8qeyoLROXQxizSi+2CTCkuNVkVZOxxY4B0Omvgq61aOQhSZUh/649x1YHoAaTyGMGDJUw==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"react-native-is-edge-to-edge": "^1.2.1",
|
"@babel/plugin-transform-object-assign": "^7.16.7",
|
||||||
"semver": "7.7.2"
|
"@babel/preset-typescript": "^7.16.7",
|
||||||
|
"convert-source-map": "^2.0.0",
|
||||||
|
"invariant": "^2.2.4"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@babel/core": "^7.0.0-0",
|
"@babel/core": "^7.0.0-0",
|
||||||
|
"@babel/plugin-proposal-nullish-coalescing-operator": "^7.0.0-0",
|
||||||
|
"@babel/plugin-proposal-optional-chaining": "^7.0.0-0",
|
||||||
|
"@babel/plugin-transform-arrow-functions": "^7.0.0-0",
|
||||||
|
"@babel/plugin-transform-shorthand-properties": "^7.0.0-0",
|
||||||
|
"@babel/plugin-transform-template-literals": "^7.0.0-0",
|
||||||
"react": "*",
|
"react": "*",
|
||||||
"react-native": "*",
|
"react-native": "*"
|
||||||
"react-native-worklets": ">=0.5.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/react-native-reanimated/node_modules/semver": {
|
|
||||||
"version": "7.7.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz",
|
|
||||||
"integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==",
|
|
||||||
"bin": {
|
|
||||||
"semver": "bin/semver.js"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=10"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/react-native-safe-area-context": {
|
"node_modules/react-native-safe-area-context": {
|
||||||
|
|||||||
Generated
Vendored
-89
@@ -1,89 +0,0 @@
|
|||||||
#include <react/debug/react_native_assert.h>
|
|
||||||
#include <reanimated/AnimatedSensor/AnimatedSensorModule.h>
|
|
||||||
|
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
namespace reanimated {
|
|
||||||
|
|
||||||
AnimatedSensorModule::AnimatedSensorModule(
|
|
||||||
const PlatformDepMethodsHolder &platformDepMethodsHolder)
|
|
||||||
: platformRegisterSensorFunction_(platformDepMethodsHolder.registerSensor),
|
|
||||||
platformUnregisterSensorFunction_(
|
|
||||||
platformDepMethodsHolder.unregisterSensor) {}
|
|
||||||
|
|
||||||
AnimatedSensorModule::~AnimatedSensorModule() {
|
|
||||||
react_native_assert(
|
|
||||||
sensorsIds_.empty() &&
|
|
||||||
"Tried to deallocate AnimatedSensorModule with registered sensors");
|
|
||||||
}
|
|
||||||
|
|
||||||
jsi::Value AnimatedSensorModule::registerSensor(
|
|
||||||
jsi::Runtime &rt,
|
|
||||||
const std::shared_ptr<WorkletRuntime> &uiWorkletRuntime,
|
|
||||||
const jsi::Value &sensorTypeValue,
|
|
||||||
const jsi::Value &interval,
|
|
||||||
const jsi::Value &iosReferenceFrame,
|
|
||||||
const jsi::Value &sensorDataHandler) {
|
|
||||||
SensorType sensorType = static_cast<SensorType>(sensorTypeValue.asNumber());
|
|
||||||
|
|
||||||
auto serializableHandler = extractSerializableOrThrow<SerializableWorklet>(
|
|
||||||
rt,
|
|
||||||
sensorDataHandler,
|
|
||||||
"[Reanimated] Sensor event handler must be a worklet.");
|
|
||||||
|
|
||||||
int sensorId = platformRegisterSensorFunction_(
|
|
||||||
sensorType,
|
|
||||||
interval.asNumber(),
|
|
||||||
iosReferenceFrame.asNumber(),
|
|
||||||
[sensorType,
|
|
||||||
serializableHandler,
|
|
||||||
weakUiWorkletRuntime = std::weak_ptr<WorkletRuntime>(uiWorkletRuntime)](
|
|
||||||
double newValues[], int orientationDegrees) {
|
|
||||||
auto uiWorkletRuntime = weakUiWorkletRuntime.lock();
|
|
||||||
if (uiWorkletRuntime == nullptr) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
jsi::Runtime &uiRuntime = uiWorkletRuntime->getJSIRuntime();
|
|
||||||
jsi::Object value(uiRuntime);
|
|
||||||
if (sensorType == SensorType::ROTATION_VECTOR) {
|
|
||||||
// TODO: timestamp should be provided by the platform implementation
|
|
||||||
// such that the native side has a chance of providing a true event
|
|
||||||
// timestamp
|
|
||||||
value.setProperty(uiRuntime, "qx", newValues[0]);
|
|
||||||
value.setProperty(uiRuntime, "qy", newValues[1]);
|
|
||||||
value.setProperty(uiRuntime, "qz", newValues[2]);
|
|
||||||
value.setProperty(uiRuntime, "qw", newValues[3]);
|
|
||||||
value.setProperty(uiRuntime, "yaw", newValues[4]);
|
|
||||||
value.setProperty(uiRuntime, "pitch", newValues[5]);
|
|
||||||
value.setProperty(uiRuntime, "roll", newValues[6]);
|
|
||||||
} else {
|
|
||||||
value.setProperty(uiRuntime, "x", newValues[0]);
|
|
||||||
value.setProperty(uiRuntime, "y", newValues[1]);
|
|
||||||
value.setProperty(uiRuntime, "z", newValues[2]);
|
|
||||||
}
|
|
||||||
value.setProperty(
|
|
||||||
uiRuntime, "interfaceOrientation", orientationDegrees);
|
|
||||||
|
|
||||||
uiWorkletRuntime->runGuarded(serializableHandler, value);
|
|
||||||
});
|
|
||||||
if (sensorId != -1) {
|
|
||||||
sensorsIds_.insert(sensorId);
|
|
||||||
}
|
|
||||||
return jsi::Value(sensorId);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AnimatedSensorModule::unregisterSensor(const jsi::Value &sensorId) {
|
|
||||||
// It is called during sensor hook unmounting
|
|
||||||
sensorsIds_.erase(sensorId.getNumber());
|
|
||||||
platformUnregisterSensorFunction_(sensorId.asNumber());
|
|
||||||
}
|
|
||||||
|
|
||||||
void AnimatedSensorModule::unregisterAllSensors() {
|
|
||||||
for (auto sensorId : sensorsIds_) {
|
|
||||||
platformUnregisterSensorFunction_(sensorId);
|
|
||||||
}
|
|
||||||
sensorsIds_.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace reanimated
|
|
||||||
Generated
Vendored
-47
@@ -1,47 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <reanimated/Tools/PlatformDepMethodsHolder.h>
|
|
||||||
|
|
||||||
#include <worklets/SharedItems/Serializable.h>
|
|
||||||
#include <worklets/WorkletRuntime/WorkletRuntime.h>
|
|
||||||
|
|
||||||
#include <jsi/jsi.h>
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <unordered_set>
|
|
||||||
|
|
||||||
namespace reanimated {
|
|
||||||
|
|
||||||
using namespace facebook;
|
|
||||||
using namespace worklets;
|
|
||||||
|
|
||||||
enum SensorType {
|
|
||||||
ACCELEROMETER = 1,
|
|
||||||
GYROSCOPE = 2,
|
|
||||||
GRAVITY = 3,
|
|
||||||
MAGNETIC_FIELD = 4,
|
|
||||||
ROTATION_VECTOR = 5,
|
|
||||||
};
|
|
||||||
|
|
||||||
class AnimatedSensorModule {
|
|
||||||
std::unordered_set<int> sensorsIds_;
|
|
||||||
RegisterSensorFunction platformRegisterSensorFunction_;
|
|
||||||
UnregisterSensorFunction platformUnregisterSensorFunction_;
|
|
||||||
|
|
||||||
public:
|
|
||||||
AnimatedSensorModule(
|
|
||||||
const PlatformDepMethodsHolder &platformDepMethodsHolder);
|
|
||||||
~AnimatedSensorModule();
|
|
||||||
|
|
||||||
jsi::Value registerSensor(
|
|
||||||
jsi::Runtime &rt,
|
|
||||||
const std::shared_ptr<WorkletRuntime> &uiWorkletRuntime,
|
|
||||||
const jsi::Value &sensorType,
|
|
||||||
const jsi::Value &interval,
|
|
||||||
const jsi::Value &iosReferenceFrame,
|
|
||||||
const jsi::Value &sensorDataContainer);
|
|
||||||
void unregisterSensor(const jsi::Value &sensorId);
|
|
||||||
void unregisterAllSensors();
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace reanimated
|
|
||||||
Generated
Vendored
-427
@@ -1,427 +0,0 @@
|
|||||||
#include <reanimated/CSS/InterpolatorRegistry.h>
|
|
||||||
#include <reanimated/Tools/FeatureFlags.h>
|
|
||||||
|
|
||||||
#include <reanimated/CSS/common/values/CSSAngle.h>
|
|
||||||
#include <reanimated/CSS/common/values/CSSBoolean.h>
|
|
||||||
#include <reanimated/CSS/common/values/CSSColor.h>
|
|
||||||
#include <reanimated/CSS/common/values/CSSDiscreteArray.h>
|
|
||||||
#include <reanimated/CSS/common/values/CSSKeyword.h>
|
|
||||||
#include <reanimated/CSS/common/values/CSSLength.h>
|
|
||||||
#include <reanimated/CSS/common/values/CSSNumber.h>
|
|
||||||
#include <reanimated/CSS/common/values/CSSValue.h>
|
|
||||||
|
|
||||||
#include <reanimated/CSS/common/transforms/TransformMatrix3D.h>
|
|
||||||
|
|
||||||
#include <reanimated/CSS/svg/values/SVGLength.h>
|
|
||||||
#include <reanimated/CSS/svg/values/SVGStrokeDashArray.h>
|
|
||||||
|
|
||||||
#include <reanimated/CSS/interpolation/InterpolatorFactory.h>
|
|
||||||
#include <reanimated/CSS/interpolation/transforms/operations/matrix.h>
|
|
||||||
#include <reanimated/CSS/interpolation/transforms/operations/perspective.h>
|
|
||||||
#include <reanimated/CSS/interpolation/transforms/operations/rotate.h>
|
|
||||||
#include <reanimated/CSS/interpolation/transforms/operations/scale.h>
|
|
||||||
#include <reanimated/CSS/interpolation/transforms/operations/skew.h>
|
|
||||||
#include <reanimated/CSS/interpolation/transforms/operations/translate.h>
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace reanimated::css {
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
// Private implementation details
|
|
||||||
const auto BLACK = CSSColor(0, 0, 0, 255);
|
|
||||||
const auto TRANSPARENT = CSSColor::Transparent;
|
|
||||||
|
|
||||||
InterpolatorFactoriesRecord mergeInterpolators(
|
|
||||||
const std::vector<InterpolatorFactoriesRecord> &maps) {
|
|
||||||
InterpolatorFactoriesRecord result;
|
|
||||||
for (const auto &map : maps) {
|
|
||||||
result.insert(map.begin(), map.end());
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ==========================
|
|
||||||
// React Native Interpolators
|
|
||||||
// ==========================
|
|
||||||
|
|
||||||
const InterpolatorFactoriesRecord FLEX_INTERPOLATORS = {
|
|
||||||
{"alignContent", value<CSSKeyword>("flex-start")},
|
|
||||||
{"alignItems", value<CSSKeyword>("stretch")},
|
|
||||||
{"alignSelf", value<CSSKeyword>("auto")},
|
|
||||||
{"aspectRatio", value<CSSDouble, CSSKeyword>("auto")},
|
|
||||||
{"borderBottomWidth", value<CSSDouble>(0)},
|
|
||||||
{"borderEndWidth", value<CSSDouble>(0)},
|
|
||||||
{"borderLeftWidth", value<CSSDouble>(0)},
|
|
||||||
{"borderRightWidth", value<CSSDouble>(0)},
|
|
||||||
{"borderStartWidth", value<CSSDouble>(0)},
|
|
||||||
{"borderTopWidth", value<CSSDouble>(0)},
|
|
||||||
{"borderWidth", value<CSSDouble>(0)},
|
|
||||||
{"bottom",
|
|
||||||
value<CSSLength, CSSKeyword>(RelativeTo::Parent, "height", "auto")},
|
|
||||||
{"boxSizing", value<CSSKeyword>("border-box")},
|
|
||||||
{"display", value<CSSDisplay>("flex")},
|
|
||||||
{"end", value<CSSLength, CSSKeyword>(RelativeTo::Parent, "width", "auto")},
|
|
||||||
{"flex", value<CSSDouble>(0)},
|
|
||||||
{"flexBasis",
|
|
||||||
value<CSSLength, CSSKeyword>(RelativeTo::Parent, "width", "auto")},
|
|
||||||
{"flexDirection", value<CSSKeyword>("column")},
|
|
||||||
{"rowGap", value<CSSLength>(RelativeTo::Self, "height", 0)},
|
|
||||||
{"columnGap", value<CSSLength>(RelativeTo::Self, "width", 0)},
|
|
||||||
{"flexGrow", value<CSSDouble>(0)},
|
|
||||||
{"flexShrink", value<CSSDouble>(0)},
|
|
||||||
{"flexWrap", value<CSSKeyword>("no-wrap")},
|
|
||||||
{"height",
|
|
||||||
value<CSSLength, CSSKeyword>(RelativeTo::Parent, "height", "auto")},
|
|
||||||
{"justifyContent", value<CSSKeyword>("flex-start")},
|
|
||||||
{"left", value<CSSLength, CSSKeyword>(RelativeTo::Parent, "width", "auto")},
|
|
||||||
{"margin", value<CSSLength, CSSKeyword>(RelativeTo::Parent, "width", 0)},
|
|
||||||
{"marginBottom",
|
|
||||||
value<CSSLength, CSSKeyword>(RelativeTo::Parent, "width", 0)},
|
|
||||||
{"marginEnd", value<CSSLength, CSSKeyword>(RelativeTo::Parent, "width", 0)},
|
|
||||||
{"marginHorizontal",
|
|
||||||
value<CSSLength, CSSKeyword>(RelativeTo::Parent, "width", 0)},
|
|
||||||
{"marginLeft",
|
|
||||||
value<CSSLength, CSSKeyword>(RelativeTo::Parent, "width", 0)},
|
|
||||||
{"marginRight",
|
|
||||||
value<CSSLength, CSSKeyword>(RelativeTo::Parent, "width", 0)},
|
|
||||||
{"marginStart",
|
|
||||||
value<CSSLength, CSSKeyword>(RelativeTo::Parent, "width", 0)},
|
|
||||||
{"marginTop", value<CSSLength, CSSKeyword>(RelativeTo::Parent, "width", 0)},
|
|
||||||
{"marginVertical",
|
|
||||||
value<CSSLength, CSSKeyword>(RelativeTo::Parent, "width", 0)},
|
|
||||||
{"maxHeight",
|
|
||||||
value<CSSLength, CSSKeyword>(RelativeTo::Parent, "height", "auto")},
|
|
||||||
{"maxWidth",
|
|
||||||
value<CSSLength, CSSKeyword>(RelativeTo::Parent, "width", "auto")},
|
|
||||||
{"minHeight",
|
|
||||||
value<CSSLength, CSSKeyword>(RelativeTo::Parent, "height", "auto")},
|
|
||||||
{"minWidth",
|
|
||||||
value<CSSLength, CSSKeyword>(RelativeTo::Parent, "width", "auto")},
|
|
||||||
{"overflow", value<CSSKeyword>("visible")},
|
|
||||||
{"padding", value<CSSLength, CSSKeyword>(RelativeTo::Parent, "width", 0)},
|
|
||||||
{"paddingBottom",
|
|
||||||
value<CSSLength, CSSKeyword>(RelativeTo::Parent, "width", 0)},
|
|
||||||
{"paddingEnd",
|
|
||||||
value<CSSLength, CSSKeyword>(RelativeTo::Parent, "width", 0)},
|
|
||||||
{"paddingHorizontal",
|
|
||||||
value<CSSLength, CSSKeyword>(RelativeTo::Parent, "width", 0)},
|
|
||||||
{"paddingLeft",
|
|
||||||
value<CSSLength, CSSKeyword>(RelativeTo::Parent, "width", 0)},
|
|
||||||
{"paddingRight",
|
|
||||||
value<CSSLength, CSSKeyword>(RelativeTo::Parent, "width", 0)},
|
|
||||||
{"paddingStart",
|
|
||||||
value<CSSLength, CSSKeyword>(RelativeTo::Parent, "width", 0)},
|
|
||||||
{"paddingTop",
|
|
||||||
value<CSSLength, CSSKeyword>(RelativeTo::Parent, "width", 0)},
|
|
||||||
{"paddingVertical",
|
|
||||||
value<CSSLength, CSSKeyword>(RelativeTo::Parent, "width", 0)},
|
|
||||||
{"position", value<CSSKeyword>("relative")},
|
|
||||||
{"right",
|
|
||||||
value<CSSLength, CSSKeyword>(RelativeTo::Parent, "width", "auto")},
|
|
||||||
{"start",
|
|
||||||
value<CSSLength, CSSKeyword>(RelativeTo::Parent, "width", "auto")},
|
|
||||||
{"top", value<CSSLength, CSSKeyword>(RelativeTo::Parent, "height", "auto")},
|
|
||||||
{"width",
|
|
||||||
value<CSSLength, CSSKeyword>(RelativeTo::Parent, "width", "auto")},
|
|
||||||
{"zIndex", value<CSSInteger>(0)},
|
|
||||||
{"direction", value<CSSKeyword>("inherit")}};
|
|
||||||
|
|
||||||
const InterpolatorFactoriesRecord SHADOW_INTERPOLATORS_IOS = {
|
|
||||||
{"shadowColor", value<CSSColor>(BLACK)},
|
|
||||||
{"shadowOffset",
|
|
||||||
record({{"width", value<CSSDouble>(0)}, {"height", value<CSSDouble>(0)}})},
|
|
||||||
{"shadowRadius", value<CSSDouble>(0)},
|
|
||||||
{"shadowOpacity", value<CSSDouble>(1)}};
|
|
||||||
|
|
||||||
const InterpolatorFactoriesRecord TRANSFORMS_INTERPOLATORS = {
|
|
||||||
{"transformOrigin",
|
|
||||||
array(
|
|
||||||
{value<CSSLength>(RelativeTo::Self, "width", "50%"),
|
|
||||||
value<CSSLength>(RelativeTo::Self, "height", "50%"),
|
|
||||||
value<CSSDouble>(0)})},
|
|
||||||
{"transform",
|
|
||||||
transforms(
|
|
||||||
{{"perspective",
|
|
||||||
transformOp<PerspectiveOperation>(0)}, // 0 - no perspective
|
|
||||||
{"rotate", transformOp<RotateOperation>("0deg")},
|
|
||||||
{"rotateX", transformOp<RotateXOperation>("0deg")},
|
|
||||||
{"rotateY", transformOp<RotateYOperation>("0deg")},
|
|
||||||
{"rotateZ", transformOp<RotateZOperation>("0deg")},
|
|
||||||
{"scale", transformOp<ScaleOperation>(1)},
|
|
||||||
{"scaleX", transformOp<ScaleXOperation>(1)},
|
|
||||||
{"scaleY", transformOp<ScaleYOperation>(1)},
|
|
||||||
{"translateX",
|
|
||||||
transformOp<TranslateXOperation>(RelativeTo::Self, "width", 0)},
|
|
||||||
{"translateY",
|
|
||||||
transformOp<TranslateYOperation>(RelativeTo::Self, "height", 0)},
|
|
||||||
{"skewX", transformOp<SkewXOperation>("0deg")},
|
|
||||||
{"skewY", transformOp<SkewYOperation>("0deg")},
|
|
||||||
{"matrix",
|
|
||||||
transformOp<MatrixOperation>(TransformMatrix3D::Identity())}})},
|
|
||||||
};
|
|
||||||
|
|
||||||
const InterpolatorFactoriesRecord VIEW_INTERPOLATORS = mergeInterpolators(
|
|
||||||
{FLEX_INTERPOLATORS,
|
|
||||||
SHADOW_INTERPOLATORS_IOS,
|
|
||||||
TRANSFORMS_INTERPOLATORS,
|
|
||||||
InterpolatorFactoriesRecord{
|
|
||||||
{"backfaceVisibility", value<CSSKeyword>("visible")},
|
|
||||||
{"backgroundColor", value<CSSColor>(TRANSPARENT)},
|
|
||||||
{"borderBlockColor", value<CSSColor>(BLACK)},
|
|
||||||
{"borderBlockEndColor", value<CSSColor>(BLACK)},
|
|
||||||
{"borderBlockStartColor", value<CSSColor>(BLACK)},
|
|
||||||
{"borderBottomColor", value<CSSColor>(BLACK)},
|
|
||||||
{"borderBottomEndRadius",
|
|
||||||
value<CSSLength>(RelativeTo::Self, "width", 0)},
|
|
||||||
{"borderBottomLeftRadius",
|
|
||||||
value<CSSLength>(RelativeTo::Self, "width", 0)},
|
|
||||||
{"borderBottomRightRadius",
|
|
||||||
value<CSSLength>(RelativeTo::Self, "width", 0)},
|
|
||||||
{"borderBottomStartRadius",
|
|
||||||
value<CSSLength>(RelativeTo::Self, "width", 0)},
|
|
||||||
{"borderColor", value<CSSColor>(BLACK)},
|
|
||||||
{"borderCurve", value<CSSKeyword>("circular")},
|
|
||||||
{"borderEndColor", value<CSSColor>(BLACK)},
|
|
||||||
{"borderEndEndRadius", value<CSSLength>(RelativeTo::Self, "width", 0)},
|
|
||||||
{"borderEndStartRadius",
|
|
||||||
value<CSSLength>(RelativeTo::Self, "width", 0)},
|
|
||||||
{"borderLeftColor", value<CSSColor>(BLACK)},
|
|
||||||
{"borderRadius", value<CSSLength>(RelativeTo::Self, "width", 0)},
|
|
||||||
{"borderRightColor", value<CSSColor>(BLACK)},
|
|
||||||
{"borderStartColor", value<CSSColor>(BLACK)},
|
|
||||||
{"borderStartEndRadius",
|
|
||||||
value<CSSLength>(RelativeTo::Self, "width", 0)},
|
|
||||||
{"borderStartStartRadius",
|
|
||||||
value<CSSLength>(RelativeTo::Self, "width", 0)},
|
|
||||||
{"borderStyle", value<CSSKeyword>("solid")},
|
|
||||||
{"borderTopColor", value<CSSColor>(BLACK)},
|
|
||||||
{"borderTopEndRadius", value<CSSLength>(RelativeTo::Self, "width", 0)},
|
|
||||||
{"borderTopLeftRadius",
|
|
||||||
value<CSSLength>(RelativeTo::Self, "width", 0)},
|
|
||||||
{"borderTopRightRadius",
|
|
||||||
value<CSSLength>(RelativeTo::Self, "width", 0)},
|
|
||||||
{"borderTopStartRadius",
|
|
||||||
value<CSSLength>(RelativeTo::Self, "width", 0)},
|
|
||||||
{"outlineColor", value<CSSColor>(BLACK)},
|
|
||||||
{"outlineOffset", value<CSSDouble>(0)},
|
|
||||||
{"outlineStyle", value<CSSKeyword>("solid")},
|
|
||||||
{"outlineWidth", value<CSSDouble>(0)},
|
|
||||||
{"opacity", value<CSSDouble>(1)},
|
|
||||||
{"elevation", value<CSSDouble>(0)},
|
|
||||||
{"pointerEvents", value<CSSKeyword>("auto")},
|
|
||||||
{"isolation", value<CSSKeyword>("auto")},
|
|
||||||
{"cursor", value<CSSKeyword>("auto")},
|
|
||||||
{"boxShadow",
|
|
||||||
array({record({
|
|
||||||
{"offsetX", value<CSSDouble>(0)},
|
|
||||||
{"offsetY", value<CSSDouble>(0)},
|
|
||||||
#ifdef ANDROID
|
|
||||||
// For some reason Android crashes when blurRadius is smaller
|
|
||||||
// than 1, so we use a custom value type that will never be
|
|
||||||
// smaller than 1
|
|
||||||
{"blurRadius", value<CSSShadowRadiusAndroid>(1)},
|
|
||||||
#else
|
|
||||||
{"blurRadius", value<CSSDouble>(0)},
|
|
||||||
#endif
|
|
||||||
{"spreadDistance", value<CSSDouble>(0)},
|
|
||||||
{"color", value<CSSColor>(TRANSPARENT)},
|
|
||||||
{"inset", value<CSSBoolean>(false)},
|
|
||||||
})})},
|
|
||||||
{"mixBlendMode", value<CSSKeyword>("normal")}}});
|
|
||||||
|
|
||||||
const InterpolatorFactoriesRecord TEXT_INTERPOLATORS_IOS = {
|
|
||||||
{"fontVariant",
|
|
||||||
value<CSSDiscreteArray<CSSKeyword>>(std::vector<CSSKeyword>{})},
|
|
||||||
{"textDecorationColor", value<CSSColor>(BLACK)},
|
|
||||||
{"textDecorationStyle", value<CSSKeyword>("solid")},
|
|
||||||
{"writingDirection", value<CSSKeyword>("auto")},
|
|
||||||
};
|
|
||||||
|
|
||||||
const InterpolatorFactoriesRecord TEXT_INTERPOLATORS_ANDROID = {
|
|
||||||
{"textAlignVertical", value<CSSKeyword>("auto")},
|
|
||||||
{"verticalAlign", value<CSSKeyword>("auto")},
|
|
||||||
{"includeFontPadding", value<CSSBoolean>(false)},
|
|
||||||
};
|
|
||||||
|
|
||||||
const InterpolatorFactoriesRecord TEXT_INTERPOLATORS = mergeInterpolators(
|
|
||||||
{VIEW_INTERPOLATORS,
|
|
||||||
TEXT_INTERPOLATORS_IOS,
|
|
||||||
TEXT_INTERPOLATORS_ANDROID,
|
|
||||||
InterpolatorFactoriesRecord{
|
|
||||||
{"color", value<CSSColor>(BLACK)},
|
|
||||||
{"fontFamily", value<CSSKeyword>("inherit")},
|
|
||||||
{"fontSize", value<CSSDouble>(14)},
|
|
||||||
{"fontStyle", value<CSSKeyword>("normal")},
|
|
||||||
{"fontWeight", value<CSSKeyword>("normal")},
|
|
||||||
{"letterSpacing", value<CSSDouble>(0)},
|
|
||||||
{"lineHeight",
|
|
||||||
value<CSSDouble>(14)}, // TODO - should inherit from fontSize
|
|
||||||
{"textAlign", value<CSSKeyword>("auto")},
|
|
||||||
{"textDecorationLine", value<CSSKeyword>("none")},
|
|
||||||
{"textShadowColor", value<CSSColor>(BLACK)},
|
|
||||||
{"textShadowOffset",
|
|
||||||
record(
|
|
||||||
{{"width", value<CSSDouble>(0)},
|
|
||||||
{"height", value<CSSDouble>(0)}})},
|
|
||||||
{"textShadowRadius", value<CSSDouble>(0)},
|
|
||||||
{"textTransform", value<CSSKeyword>("none")},
|
|
||||||
{"userSelect", value<CSSKeyword>("auto")},
|
|
||||||
}});
|
|
||||||
|
|
||||||
const InterpolatorFactoriesRecord IMAGE_INTERPOLATORS = mergeInterpolators(
|
|
||||||
{VIEW_INTERPOLATORS,
|
|
||||||
InterpolatorFactoriesRecord{
|
|
||||||
{"resizeMode", value<CSSKeyword>("cover")},
|
|
||||||
{"overlayColor", value<CSSColor>(BLACK)},
|
|
||||||
{"tintColor", value<CSSColor>(BLACK)},
|
|
||||||
}});
|
|
||||||
|
|
||||||
// =================
|
|
||||||
// SVG INTERPOLATORS
|
|
||||||
// =================
|
|
||||||
|
|
||||||
const InterpolatorFactoriesRecord SVG_COLOR_INTERPOLATORS = {
|
|
||||||
{"color", value<CSSColor>(BLACK)},
|
|
||||||
};
|
|
||||||
|
|
||||||
const InterpolatorFactoriesRecord SVG_FILL_INTERPOLATORS = {
|
|
||||||
{"fill", value<CSSColor>(BLACK)},
|
|
||||||
{"fillOpacity", value<CSSDouble>(1)},
|
|
||||||
{"fillRule", value<CSSInteger>(0)},
|
|
||||||
};
|
|
||||||
|
|
||||||
const InterpolatorFactoriesRecord SVG_STROKE_INTERPOLATORS = {
|
|
||||||
{"stroke", value<CSSColor>(BLACK)},
|
|
||||||
{"strokeWidth", value<SVGLength>(1)},
|
|
||||||
{"strokeOpacity", value<CSSDouble>(1)},
|
|
||||||
{"strokeDasharray",
|
|
||||||
value<SVGStrokeDashArray, CSSKeyword>(SVGStrokeDashArray())},
|
|
||||||
{"strokeDashoffset", value<SVGLength>(0)},
|
|
||||||
{"strokeLinecap", value<CSSInteger>(0)},
|
|
||||||
{"strokeLinejoin", value<CSSInteger>(0)},
|
|
||||||
{"strokeMiterlimit", value<CSSDouble>(4)},
|
|
||||||
{"vectorEffect", value<CSSInteger>(0)},
|
|
||||||
};
|
|
||||||
|
|
||||||
const InterpolatorFactoriesRecord SVG_CLIP_INTERPOLATORS = {
|
|
||||||
{"clipRule", value<CSSKeyword>("nonzero")},
|
|
||||||
{"clipPath", value<CSSKeyword>("none")},
|
|
||||||
};
|
|
||||||
|
|
||||||
const InterpolatorFactoriesRecord SVG_TRANSFORM_INTERPOLATORS = {
|
|
||||||
{"translateX", value<SVGLength>(0)},
|
|
||||||
{"translateY", value<SVGLength>(0)},
|
|
||||||
{"originX", value<SVGLength>(0)},
|
|
||||||
{"originY", value<SVGLength>(0)},
|
|
||||||
{"scaleX", value<CSSDouble>(1)},
|
|
||||||
{"scaleY", value<CSSDouble>(1)},
|
|
||||||
{"skewX", value<CSSAngle>(0)},
|
|
||||||
{"skewY", value<CSSAngle>(0)},
|
|
||||||
{"rotation", value<CSSAngle>(0)},
|
|
||||||
};
|
|
||||||
|
|
||||||
const InterpolatorFactoriesRecord SVG_COMMON_INTERPOLATORS =
|
|
||||||
mergeInterpolators({
|
|
||||||
SVG_COLOR_INTERPOLATORS,
|
|
||||||
SVG_FILL_INTERPOLATORS,
|
|
||||||
SVG_STROKE_INTERPOLATORS,
|
|
||||||
});
|
|
||||||
|
|
||||||
const InterpolatorFactoriesRecord SVG_CIRCLE_INTERPOLATORS = mergeInterpolators(
|
|
||||||
{SVG_COMMON_INTERPOLATORS,
|
|
||||||
InterpolatorFactoriesRecord{
|
|
||||||
{"cx", value<SVGLength, CSSKeyword>(0)},
|
|
||||||
{"cy", value<SVGLength, CSSKeyword>(0)},
|
|
||||||
{"r", value<SVGLength, CSSKeyword>(0)},
|
|
||||||
{"opacity", value<CSSDouble>(1)},
|
|
||||||
}});
|
|
||||||
|
|
||||||
const InterpolatorFactoriesRecord SVG_ELLIPSE_INTERPOLATORS =
|
|
||||||
mergeInterpolators(
|
|
||||||
{SVG_COMMON_INTERPOLATORS,
|
|
||||||
InterpolatorFactoriesRecord{
|
|
||||||
{"cx", value<SVGLength, CSSKeyword>(0)},
|
|
||||||
{"cy", value<SVGLength, CSSKeyword>(0)},
|
|
||||||
{"rx", value<SVGLength, CSSKeyword>(0)},
|
|
||||||
{"ry", value<SVGLength, CSSKeyword>(0)},
|
|
||||||
{"opacity", value<CSSDouble>(1)},
|
|
||||||
}});
|
|
||||||
|
|
||||||
const InterpolatorFactoriesRecord SVG_LINE_INTERPOLATORS = mergeInterpolators(
|
|
||||||
{SVG_COMMON_INTERPOLATORS,
|
|
||||||
InterpolatorFactoriesRecord{
|
|
||||||
{"x1", value<SVGLength, CSSKeyword>(0)},
|
|
||||||
{"y1", value<SVGLength, CSSKeyword>(0)},
|
|
||||||
{"x2", value<SVGLength, CSSKeyword>(0)},
|
|
||||||
{"y2", value<SVGLength, CSSKeyword>(0)},
|
|
||||||
{"opacity", value<CSSDouble>(1)},
|
|
||||||
}});
|
|
||||||
|
|
||||||
const InterpolatorFactoriesRecord SVG_RECT_INTERPOLATORS = mergeInterpolators(
|
|
||||||
{SVG_COMMON_INTERPOLATORS,
|
|
||||||
InterpolatorFactoriesRecord{
|
|
||||||
{"x", value<SVGLength, CSSKeyword>(0)},
|
|
||||||
{"y", value<SVGLength, CSSKeyword>(0)},
|
|
||||||
{"width", value<SVGLength, CSSKeyword>(0)},
|
|
||||||
{"height", value<SVGLength, CSSKeyword>(0)},
|
|
||||||
{"rx", value<SVGLength, CSSKeyword>(0)},
|
|
||||||
{"ry", value<SVGLength, CSSKeyword>(0)},
|
|
||||||
{"opacity", value<CSSDouble>(1)},
|
|
||||||
}});
|
|
||||||
|
|
||||||
const InterpolatorFactoriesRecord SVG_PATH_INTERPOLATORS = mergeInterpolators(
|
|
||||||
{SVG_COMMON_INTERPOLATORS,
|
|
||||||
InterpolatorFactoriesRecord{
|
|
||||||
// TODO - add more properties
|
|
||||||
}});
|
|
||||||
|
|
||||||
// ==================
|
|
||||||
// COMPONENT REGISTRY
|
|
||||||
// ==================
|
|
||||||
|
|
||||||
ComponentInterpolatorsMap initializeRegistry() {
|
|
||||||
ComponentInterpolatorsMap registry = {
|
|
||||||
// React Native Components
|
|
||||||
{"View", VIEW_INTERPOLATORS},
|
|
||||||
{"Paragraph", TEXT_INTERPOLATORS},
|
|
||||||
{"Image", IMAGE_INTERPOLATORS},
|
|
||||||
};
|
|
||||||
|
|
||||||
if (StaticFeatureFlags::getFlag(
|
|
||||||
"EXPERIMENTAL_CSS_ANIMATIONS_FOR_SVG_COMPONENTS")) {
|
|
||||||
// SVG Components
|
|
||||||
registry["RNSVGCircle"] = SVG_CIRCLE_INTERPOLATORS;
|
|
||||||
registry["RNSVGEllipse"] = SVG_ELLIPSE_INTERPOLATORS;
|
|
||||||
registry["RNSVGLine"] = SVG_LINE_INTERPOLATORS;
|
|
||||||
registry["RNSVGPath"] = SVG_PATH_INTERPOLATORS;
|
|
||||||
registry["RNSVGRect"] = SVG_RECT_INTERPOLATORS;
|
|
||||||
}
|
|
||||||
|
|
||||||
return registry;
|
|
||||||
}
|
|
||||||
|
|
||||||
ComponentInterpolatorsMap registry = initializeRegistry();
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
const InterpolatorFactoriesRecord &getComponentInterpolators(
|
|
||||||
const std::string &componentName) {
|
|
||||||
if (auto it = registry.find(componentName); it != registry.end()) {
|
|
||||||
return it->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Use View interpolators as a fallback for unknown components
|
|
||||||
// (e.g. we get the ScrollView component name for the ScrollView component
|
|
||||||
// but it should be styled in the same way as a View)
|
|
||||||
return VIEW_INTERPOLATORS;
|
|
||||||
}
|
|
||||||
|
|
||||||
void registerComponentInterpolators(
|
|
||||||
const std::string &componentName,
|
|
||||||
const InterpolatorFactoriesRecord &interpolators) {
|
|
||||||
registry[componentName] = interpolators;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace reanimated::css
|
|
||||||
frontend-admin/node_modules/react-native-reanimated/Common/cpp/reanimated/CSS/InterpolatorRegistry.h
Generated
Vendored
-20
@@ -1,20 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <reanimated/CSS/interpolation/PropertyInterpolator.h>
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <unordered_map>
|
|
||||||
|
|
||||||
namespace reanimated::css {
|
|
||||||
|
|
||||||
using ComponentInterpolatorsMap =
|
|
||||||
std::unordered_map<std::string, InterpolatorFactoriesRecord>;
|
|
||||||
|
|
||||||
const InterpolatorFactoriesRecord &getComponentInterpolators(
|
|
||||||
const std::string &componentName);
|
|
||||||
|
|
||||||
void registerComponentInterpolators(
|
|
||||||
const std::string &componentName,
|
|
||||||
const InterpolatorFactoriesRecord &interpolators);
|
|
||||||
|
|
||||||
} // namespace reanimated::css
|
|
||||||
Generated
Vendored
-23
@@ -1,23 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <jsi/jsi.h>
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace reanimated::css {
|
|
||||||
|
|
||||||
using namespace facebook;
|
|
||||||
|
|
||||||
using PropertyNames = std::vector<std::string>;
|
|
||||||
using PropertyPath = std::vector<std::string>;
|
|
||||||
/**
|
|
||||||
* If nullopt - all style properties can trigger transition
|
|
||||||
* If empty vector - no style property can trigger transition
|
|
||||||
* Otherwise - only specified style properties can trigger transition
|
|
||||||
*/
|
|
||||||
using TransitionProperties = std::optional<PropertyNames>;
|
|
||||||
|
|
||||||
using EasingFunction = std::function<double(double)>;
|
|
||||||
using ColorChannels = std::array<uint8_t, 4>;
|
|
||||||
|
|
||||||
} // namespace reanimated::css
|
|
||||||
Generated
Vendored
-57
@@ -1,57 +0,0 @@
|
|||||||
#include <reanimated/CSS/common/transforms/Quaternion.h>
|
|
||||||
|
|
||||||
#include <cmath>
|
|
||||||
|
|
||||||
namespace reanimated::css {
|
|
||||||
|
|
||||||
bool Quaternion::operator==(const Quaternion &other) const {
|
|
||||||
return x == other.x && y == other.y && z == other.z && w == other.w;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
|
||||||
|
|
||||||
std::ostream &operator<<(std::ostream &os, const Quaternion &quaternion) {
|
|
||||||
os << "Quaternion(" << quaternion.x << ", " << quaternion.y << ", "
|
|
||||||
<< quaternion.z << ", " << quaternion.w << ")";
|
|
||||||
return os;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // NDEBUG
|
|
||||||
|
|
||||||
Quaternion Quaternion::interpolate(const double t, const Quaternion &other)
|
|
||||||
const {
|
|
||||||
const double kEpsilon = 1e-5;
|
|
||||||
Quaternion copy = *this;
|
|
||||||
|
|
||||||
double cosHalfAngle =
|
|
||||||
copy.x * other.x + copy.y * other.y + copy.z * other.z + copy.w * other.w;
|
|
||||||
|
|
||||||
if (cosHalfAngle < 0.0) {
|
|
||||||
copy.x = -copy.x;
|
|
||||||
copy.y = -copy.y;
|
|
||||||
copy.z = -copy.z;
|
|
||||||
copy.w = -copy.w;
|
|
||||||
cosHalfAngle = -cosHalfAngle;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cosHalfAngle > 1)
|
|
||||||
cosHalfAngle = 1;
|
|
||||||
|
|
||||||
double sinHalfAngle = std::sqrt(1.0 - cosHalfAngle * cosHalfAngle);
|
|
||||||
if (sinHalfAngle < kEpsilon) {
|
|
||||||
// Quaternions share common axis and angle.
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
double halfAngle = std::acos(cosHalfAngle);
|
|
||||||
double scale = std::sin((1 - t) * halfAngle) / sinHalfAngle;
|
|
||||||
double invscale = std::sin(t * halfAngle) / sinHalfAngle;
|
|
||||||
|
|
||||||
return {
|
|
||||||
copy.x * scale + other.x * invscale,
|
|
||||||
copy.y * scale + other.y * invscale,
|
|
||||||
copy.z * scale + other.z * invscale,
|
|
||||||
copy.w * scale + other.w * invscale};
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace reanimated::css
|
|
||||||
Generated
Vendored
-23
@@ -1,23 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
|
||||||
#include <iostream>
|
|
||||||
#endif // NDEBUG
|
|
||||||
|
|
||||||
namespace reanimated::css {
|
|
||||||
|
|
||||||
struct Quaternion {
|
|
||||||
double x, y, z, w;
|
|
||||||
|
|
||||||
bool operator==(const Quaternion &other) const;
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
|
||||||
friend std::ostream &operator<<(
|
|
||||||
std::ostream &os,
|
|
||||||
const Quaternion &quaternion);
|
|
||||||
#endif // NDEBUG
|
|
||||||
|
|
||||||
Quaternion interpolate(double progress, const Quaternion &other) const;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace reanimated::css
|
|
||||||
Generated
Vendored
-147
@@ -1,147 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <reanimated/CSS/common/definitions.h>
|
|
||||||
|
|
||||||
#include <folly/dynamic.h>
|
|
||||||
#include <string>
|
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
namespace reanimated::css {
|
|
||||||
|
|
||||||
class TransformMatrix {
|
|
||||||
public:
|
|
||||||
virtual ~TransformMatrix() = default;
|
|
||||||
|
|
||||||
virtual double determinant() const = 0;
|
|
||||||
|
|
||||||
virtual double &operator[](size_t index) = 0;
|
|
||||||
virtual const double &operator[](size_t index) const = 0;
|
|
||||||
|
|
||||||
virtual size_t getDimension() const = 0;
|
|
||||||
|
|
||||||
virtual std::string toString() const = 0;
|
|
||||||
virtual folly::dynamic toDynamic() const = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename TDerived, size_t TDimension>
|
|
||||||
class TransformMatrixBase : public TransformMatrix {
|
|
||||||
public:
|
|
||||||
static constexpr size_t SIZE = TDimension * TDimension;
|
|
||||||
using MatrixArray = std::array<double, SIZE>;
|
|
||||||
|
|
||||||
explicit TransformMatrixBase(MatrixArray matrix)
|
|
||||||
: matrix_(std::move(matrix)) {}
|
|
||||||
|
|
||||||
explicit TransformMatrixBase(jsi::Runtime &rt, const jsi::Value &value) {
|
|
||||||
const auto array = value.asObject(rt).asArray(rt);
|
|
||||||
if (array.size(rt) != SIZE) {
|
|
||||||
throw std::invalid_argument(
|
|
||||||
"[Reanimated] Matrix array should have " + std::to_string(SIZE) +
|
|
||||||
" elements");
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i = 0; i < SIZE; ++i) {
|
|
||||||
matrix_[i] = array.getValueAtIndex(rt, i).asNumber();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
explicit TransformMatrixBase(const folly::dynamic &array) {
|
|
||||||
if (!array.isArray() || array.size() != SIZE) {
|
|
||||||
throw std::invalid_argument(
|
|
||||||
"[Reanimated] Matrix array should have " + std::to_string(SIZE) +
|
|
||||||
" elements");
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i = 0; i < SIZE; ++i) {
|
|
||||||
matrix_[i] = array[i].asDouble();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual bool operator==(const TDerived &other) const = 0;
|
|
||||||
|
|
||||||
double &operator[](size_t index) override {
|
|
||||||
return matrix_[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
const double &operator[](size_t index) const override {
|
|
||||||
return matrix_[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
TDerived operator*(const TDerived &rhs) const {
|
|
||||||
return TDerived(multiply(rhs));
|
|
||||||
}
|
|
||||||
|
|
||||||
TDerived &operator*=(const TDerived &rhs) {
|
|
||||||
matrix_ = multiply(rhs);
|
|
||||||
return static_cast<TDerived &>(*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string toString() const override {
|
|
||||||
std::string result = "[";
|
|
||||||
for (size_t i = 0; i < SIZE; ++i) {
|
|
||||||
result += std::to_string(matrix_[i]);
|
|
||||||
if (i < SIZE - 1) {
|
|
||||||
result += ", ";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
result += "]";
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
folly::dynamic toDynamic() const override {
|
|
||||||
folly::dynamic result = folly::dynamic::array;
|
|
||||||
for (size_t i = 0; i < SIZE; ++i) {
|
|
||||||
result.push_back(matrix_[i]);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t getDimension() const override {
|
|
||||||
return TDimension;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isSingular() const {
|
|
||||||
return determinant() == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool normalize() {
|
|
||||||
const auto last = matrix_[SIZE - 1];
|
|
||||||
if (last == 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (last == 1) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i = 0; i < SIZE; ++i) {
|
|
||||||
matrix_[i] /= last;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void transpose() {
|
|
||||||
for (size_t i = 0; i < TDimension; ++i) {
|
|
||||||
for (size_t j = i + 1; j < TDimension; ++j) {
|
|
||||||
std::swap(matrix_[i * TDimension + j], matrix_[j * TDimension + i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
std::array<double, SIZE> matrix_;
|
|
||||||
|
|
||||||
MatrixArray multiply(const TDerived &rhs) const {
|
|
||||||
std::array<double, SIZE> result{};
|
|
||||||
for (size_t i = 0; i < TDimension; ++i) {
|
|
||||||
for (size_t j = 0; j < TDimension; ++j) {
|
|
||||||
for (size_t k = 0; k < TDimension; ++k) {
|
|
||||||
result[i * TDimension + j] +=
|
|
||||||
matrix_[i * TDimension + k] * rhs[k * TDimension + j];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace reanimated::css
|
|
||||||
Generated
Vendored
-259
@@ -1,259 +0,0 @@
|
|||||||
#include <reanimated/CSS/common/transforms/TransformMatrix2D.h>
|
|
||||||
|
|
||||||
namespace reanimated::css {
|
|
||||||
|
|
||||||
TransformMatrix2D::Decomposed TransformMatrix2D::Decomposed::interpolate(
|
|
||||||
const double progress,
|
|
||||||
const TransformMatrix2D::Decomposed &other) const {
|
|
||||||
return {
|
|
||||||
.scale = scale.interpolate(progress, other.scale),
|
|
||||||
.skew = skew + (other.skew - skew) * progress,
|
|
||||||
.rotation = rotation + (other.rotation - rotation) * progress,
|
|
||||||
.translation = translation.interpolate(progress, other.translation)};
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
|
||||||
|
|
||||||
std::ostream &operator<<(
|
|
||||||
std::ostream &os,
|
|
||||||
const TransformMatrix2D::Decomposed &decomposed) {
|
|
||||||
os << "TransformMatrix2D::Decomposed(scale=" << decomposed.scale
|
|
||||||
<< ", skew=" << decomposed.skew << ", rotation=" << decomposed.rotation
|
|
||||||
<< ", translation=" << decomposed.translation << ")";
|
|
||||||
return os;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // NDEBUG
|
|
||||||
|
|
||||||
TransformMatrix2D TransformMatrix2D::Identity() {
|
|
||||||
// clang-format off
|
|
||||||
return TransformMatrix2D({
|
|
||||||
1, 0, 0,
|
|
||||||
0, 1, 0,
|
|
||||||
0, 0, 1
|
|
||||||
});
|
|
||||||
// clang-format on
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
TransformMatrix2D TransformMatrix2D::create<TransformOp::Rotate>(double v) {
|
|
||||||
const auto cosVal = std::cos(v);
|
|
||||||
const auto sinVal = std::sin(v);
|
|
||||||
// clang-format off
|
|
||||||
return TransformMatrix2D({
|
|
||||||
cosVal, -sinVal, 0,
|
|
||||||
sinVal, cosVal, 0,
|
|
||||||
0, 0, 1
|
|
||||||
});
|
|
||||||
// clang-format on
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
TransformMatrix2D TransformMatrix2D::create<TransformOp::Scale>(double v) {
|
|
||||||
// clang-format off
|
|
||||||
return TransformMatrix2D({
|
|
||||||
v, 0, 0,
|
|
||||||
0, v, 0,
|
|
||||||
0, 0, 1
|
|
||||||
});
|
|
||||||
// clang-format on
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
TransformMatrix2D TransformMatrix2D::create<TransformOp::ScaleX>(double v) {
|
|
||||||
// clang-format off
|
|
||||||
return TransformMatrix2D({
|
|
||||||
v, 0, 0,
|
|
||||||
0, 1, 0,
|
|
||||||
0, 0, 1
|
|
||||||
});
|
|
||||||
// clang-format on
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
TransformMatrix2D TransformMatrix2D::create<TransformOp::ScaleY>(double v) {
|
|
||||||
// clang-format off
|
|
||||||
return TransformMatrix2D({
|
|
||||||
1, 0, 0,
|
|
||||||
0, v, 0,
|
|
||||||
0, 0, 1
|
|
||||||
});
|
|
||||||
// clang-format on
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
TransformMatrix2D TransformMatrix2D::create<TransformOp::TranslateX>(double v) {
|
|
||||||
// clang-format off
|
|
||||||
return TransformMatrix2D({
|
|
||||||
1, 0, 0,
|
|
||||||
0, 1, 0,
|
|
||||||
v, 0, 1
|
|
||||||
});
|
|
||||||
// clang-format on
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
TransformMatrix2D TransformMatrix2D::create<TransformOp::TranslateY>(double v) {
|
|
||||||
// clang-format off
|
|
||||||
return TransformMatrix2D({
|
|
||||||
1, 0, 0,
|
|
||||||
0, 1, 0,
|
|
||||||
0, v, 1
|
|
||||||
});
|
|
||||||
// clang-format on
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
TransformMatrix2D TransformMatrix2D::create<TransformOp::SkewX>(double v) {
|
|
||||||
const auto tanVal = std::tan(v);
|
|
||||||
// clang-format off
|
|
||||||
return TransformMatrix2D({
|
|
||||||
1, 0, 0,
|
|
||||||
tanVal, 1, 0,
|
|
||||||
0, 0, 1
|
|
||||||
});
|
|
||||||
// clang-format on
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
TransformMatrix2D TransformMatrix2D::create<TransformOp::SkewY>(double v) {
|
|
||||||
const auto tanVal = std::tan(v);
|
|
||||||
// clang-format off
|
|
||||||
return TransformMatrix2D({
|
|
||||||
1, tanVal, 0,
|
|
||||||
0, 1, 0,
|
|
||||||
0, 0, 1
|
|
||||||
});
|
|
||||||
// clang-format on
|
|
||||||
}
|
|
||||||
|
|
||||||
template <TransformOp TOperation>
|
|
||||||
TransformMatrix2D TransformMatrix2D::create(double value) {
|
|
||||||
throw std::invalid_argument(
|
|
||||||
"[Reanimated] Cannot create TransformMatrix2D from: " +
|
|
||||||
getOperationNameFromType(TOperation));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TransformMatrix2D::operator==(const TransformMatrix2D &other) const {
|
|
||||||
return matrix_ == other.matrix_;
|
|
||||||
}
|
|
||||||
|
|
||||||
double TransformMatrix2D::determinant() const {
|
|
||||||
return (matrix_[0] * matrix_[4] * matrix_[8]) +
|
|
||||||
(matrix_[1] * matrix_[5] * matrix_[6]) +
|
|
||||||
(matrix_[2] * matrix_[3] * matrix_[7]) -
|
|
||||||
(matrix_[2] * matrix_[4] * matrix_[6]) -
|
|
||||||
(matrix_[1] * matrix_[3] * matrix_[8]) -
|
|
||||||
(matrix_[0] * matrix_[5] * matrix_[7]);
|
|
||||||
}
|
|
||||||
|
|
||||||
void TransformMatrix2D::translate2d(const Vector2D &translation) {
|
|
||||||
for (size_t i = 0; i < 3; ++i) {
|
|
||||||
matrix_[6 + i] +=
|
|
||||||
translation[0] * matrix_[i] + translation[1] * matrix_[3 + i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void TransformMatrix2D::scale2d(const Vector2D &scale) {
|
|
||||||
for (size_t i = 0; i < 3; ++i) {
|
|
||||||
matrix_[i] *= scale[0];
|
|
||||||
matrix_[3 + i] *= scale[1];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::optional<TransformMatrix2D::Decomposed> TransformMatrix2D::decompose()
|
|
||||||
const {
|
|
||||||
auto matrixCp = *this;
|
|
||||||
|
|
||||||
if (!matrixCp.normalize()) {
|
|
||||||
return std::nullopt;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto translation = matrixCp.getTranslation();
|
|
||||||
|
|
||||||
// Take the 2×2 linear part into two column vectors (col-major)
|
|
||||||
std::array<Vector2D, 2> rows;
|
|
||||||
for (size_t i = 0; i < 2; ++i) {
|
|
||||||
rows[i] = Vector2D(matrixCp[i * 3], matrixCp[i * 3 + 1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto [scale, skew] = computeScaleAndSkew(rows);
|
|
||||||
|
|
||||||
// At this point, the matrix (in rows) is orthonormal.
|
|
||||||
// Check for a coordinate system flip. If the determinant
|
|
||||||
// is negative, then negate the matrix and the scaling factors.
|
|
||||||
if (rows[0].cross(rows[1]) < 0) {
|
|
||||||
scale *= -1;
|
|
||||||
for (auto &row : rows) {
|
|
||||||
row *= -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto rotation = computeRotation(rows);
|
|
||||||
|
|
||||||
return TransformMatrix2D::Decomposed{
|
|
||||||
.scale = scale,
|
|
||||||
.skew = skew,
|
|
||||||
.rotation = rotation,
|
|
||||||
.translation = translation};
|
|
||||||
}
|
|
||||||
|
|
||||||
TransformMatrix2D TransformMatrix2D::recompose(
|
|
||||||
const TransformMatrix2D::Decomposed &decomposed) {
|
|
||||||
auto result = TransformMatrix2D::Identity();
|
|
||||||
|
|
||||||
// Apply Translation
|
|
||||||
result.translate2d(decomposed.translation);
|
|
||||||
|
|
||||||
// Apply Rotation
|
|
||||||
const auto rotationMatrix =
|
|
||||||
TransformMatrix2D::create<TransformOp::Rotate>(decomposed.rotation);
|
|
||||||
result = rotationMatrix * result;
|
|
||||||
|
|
||||||
// Apply XY shear
|
|
||||||
if (decomposed.skew != 0) {
|
|
||||||
auto tmp = TransformMatrix2D::Identity();
|
|
||||||
tmp[3] = decomposed.skew;
|
|
||||||
result = tmp * result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Apply Scale
|
|
||||||
result.scale2d(decomposed.scale);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector2D TransformMatrix2D::getTranslation() const {
|
|
||||||
return Vector2D(matrix_[6], matrix_[7]);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::pair<Vector2D, double> TransformMatrix2D::computeScaleAndSkew(
|
|
||||||
std::array<Vector2D, 2> &rows) {
|
|
||||||
Vector2D scale;
|
|
||||||
|
|
||||||
// Compute X scale and normalize first row
|
|
||||||
scale[0] = rows[0].length();
|
|
||||||
rows[0].normalize();
|
|
||||||
|
|
||||||
// Compute XY shear and orthogonalize second row against first
|
|
||||||
double skew = rows[0].dot(rows[1]);
|
|
||||||
rows[1] = rows[1].addScaled(rows[0], -skew);
|
|
||||||
|
|
||||||
// Now, compute Y scale and normalize second row
|
|
||||||
scale[1] = rows[1].length();
|
|
||||||
rows[1].normalize();
|
|
||||||
|
|
||||||
// Next, Normalize shear by Y scale
|
|
||||||
skew /= scale[1];
|
|
||||||
|
|
||||||
return {scale, skew};
|
|
||||||
}
|
|
||||||
|
|
||||||
double TransformMatrix2D::computeRotation(std::array<Vector2D, 2> &rows) {
|
|
||||||
// For 2D, we can compute rotation directly from the orthonormal matrix
|
|
||||||
// The rotation angle is atan2(m10, m00) where m10 is rows[1][0] and m00 is
|
|
||||||
// rows[0][0]
|
|
||||||
return std::atan2(rows[1][0], rows[0][0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace reanimated::css
|
|
||||||
Generated
Vendored
-58
@@ -1,58 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <reanimated/CSS/common/transforms/TransformMatrix.h>
|
|
||||||
#include <reanimated/CSS/common/transforms/TransformOp.h>
|
|
||||||
#include <reanimated/CSS/common/transforms/vectors.h>
|
|
||||||
|
|
||||||
#include <folly/dynamic.h>
|
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
namespace reanimated::css {
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
static constexpr size_t MATRIX_2D_DIMENSION = 3; // 3x3 matrix
|
|
||||||
}
|
|
||||||
|
|
||||||
class TransformMatrix2D
|
|
||||||
: public TransformMatrixBase<TransformMatrix2D, MATRIX_2D_DIMENSION> {
|
|
||||||
public:
|
|
||||||
struct Decomposed {
|
|
||||||
Vector2D scale;
|
|
||||||
double skew;
|
|
||||||
double rotation;
|
|
||||||
Vector2D translation;
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
|
||||||
friend std::ostream &operator<<(
|
|
||||||
std::ostream &os,
|
|
||||||
const Decomposed &decomposed);
|
|
||||||
#endif // NDEBUG
|
|
||||||
|
|
||||||
Decomposed interpolate(double progress, const Decomposed &other) const;
|
|
||||||
};
|
|
||||||
|
|
||||||
using TransformMatrixBase<TransformMatrix2D, MATRIX_2D_DIMENSION>::
|
|
||||||
TransformMatrixBase;
|
|
||||||
|
|
||||||
static TransformMatrix2D Identity();
|
|
||||||
|
|
||||||
template <TransformOp TOperation>
|
|
||||||
static TransformMatrix2D create(double value);
|
|
||||||
|
|
||||||
bool operator==(const TransformMatrix2D &other) const override;
|
|
||||||
|
|
||||||
double determinant() const override;
|
|
||||||
void translate2d(const Vector2D &translation);
|
|
||||||
void scale2d(const Vector2D &scale);
|
|
||||||
|
|
||||||
std::optional<Decomposed> decompose() const;
|
|
||||||
static TransformMatrix2D recompose(const Decomposed &decomposed);
|
|
||||||
|
|
||||||
private:
|
|
||||||
Vector2D getTranslation() const;
|
|
||||||
static std::pair<Vector2D, double> computeScaleAndSkew(
|
|
||||||
std::array<Vector2D, 2> &rows);
|
|
||||||
static double computeRotation(std::array<Vector2D, 2> &rows);
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace reanimated::css
|
|
||||||
Generated
Vendored
-583
@@ -1,583 +0,0 @@
|
|||||||
#include <reanimated/CSS/common/transforms/TransformMatrix3D.h>
|
|
||||||
#include <reanimated/CSS/interpolation/transforms/TransformOperation.h>
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
namespace reanimated::css {
|
|
||||||
|
|
||||||
TransformMatrix3D::Decomposed TransformMatrix3D::Decomposed::interpolate(
|
|
||||||
const double progress,
|
|
||||||
const TransformMatrix3D::Decomposed &other) const {
|
|
||||||
return {
|
|
||||||
.scale = scale.interpolate(progress, other.scale),
|
|
||||||
.skew = skew.interpolate(progress, other.skew),
|
|
||||||
.quaternion = quaternion.interpolate(progress, other.quaternion),
|
|
||||||
.translation = translation.interpolate(progress, other.translation),
|
|
||||||
.perspective = perspective.interpolate(progress, other.perspective)};
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
|
||||||
|
|
||||||
std::ostream &operator<<(
|
|
||||||
std::ostream &os,
|
|
||||||
const TransformMatrix3D::Decomposed &decomposed) {
|
|
||||||
os << "TransformMatrix3D::Decomposed(scale=" << decomposed.scale
|
|
||||||
<< ", skew=" << decomposed.skew << ", quaternion=" << decomposed.quaternion
|
|
||||||
<< ", translation=" << decomposed.translation
|
|
||||||
<< ", perspective=" << decomposed.perspective << ")";
|
|
||||||
return os;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // NDEBUG
|
|
||||||
|
|
||||||
TransformMatrix3D TransformMatrix3D::Identity() {
|
|
||||||
// clang-format off
|
|
||||||
return TransformMatrix3D({
|
|
||||||
1, 0, 0, 0,
|
|
||||||
0, 1, 0, 0,
|
|
||||||
0, 0, 1, 0,
|
|
||||||
0, 0, 0, 1
|
|
||||||
});
|
|
||||||
// clang-format on
|
|
||||||
}
|
|
||||||
|
|
||||||
// Template specializations for TransformMatrix3D::create
|
|
||||||
template <>
|
|
||||||
TransformMatrix3D TransformMatrix3D::create<TransformOp::Perspective>(
|
|
||||||
double v) {
|
|
||||||
if (v == 0) {
|
|
||||||
// Ignore perspective if it is invalid
|
|
||||||
return TransformMatrix3D::Identity();
|
|
||||||
}
|
|
||||||
// clang-format off
|
|
||||||
return TransformMatrix3D({
|
|
||||||
1, 0, 0, 0,
|
|
||||||
0, 1, 0, 0,
|
|
||||||
0, 0, 1, -1.0 / v,
|
|
||||||
0, 0, 0, 1
|
|
||||||
});
|
|
||||||
// clang-format on
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
TransformMatrix3D TransformMatrix3D::create<TransformOp::RotateX>(double v) {
|
|
||||||
const auto cosVal = std::cos(v);
|
|
||||||
const auto sinVal = std::sin(v);
|
|
||||||
// clang-format off
|
|
||||||
return TransformMatrix3D({
|
|
||||||
1, 0, 0, 0,
|
|
||||||
0, cosVal, sinVal, 0,
|
|
||||||
0, -sinVal, cosVal, 0,
|
|
||||||
0, 0, 0, 1
|
|
||||||
});
|
|
||||||
// clang-format on
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
TransformMatrix3D TransformMatrix3D::create<TransformOp::RotateY>(double v) {
|
|
||||||
const auto cosVal = std::cos(v);
|
|
||||||
const auto sinVal = std::sin(v);
|
|
||||||
// clang-format off
|
|
||||||
return TransformMatrix3D({
|
|
||||||
cosVal, 0, -sinVal, 0,
|
|
||||||
0, 1, 0, 0,
|
|
||||||
sinVal, 0, cosVal, 0,
|
|
||||||
0, 0, 0, 1
|
|
||||||
});
|
|
||||||
// clang-format on
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
TransformMatrix3D TransformMatrix3D::create<TransformOp::RotateZ>(double v) {
|
|
||||||
const auto cosVal = std::cos(v);
|
|
||||||
const auto sinVal = std::sin(v);
|
|
||||||
// clang-format off
|
|
||||||
return TransformMatrix3D({
|
|
||||||
cosVal, sinVal, 0, 0,
|
|
||||||
-sinVal, cosVal, 0, 0,
|
|
||||||
0, 0, 1, 0,
|
|
||||||
0, 0, 0, 1
|
|
||||||
});
|
|
||||||
// clang-format on
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
TransformMatrix3D TransformMatrix3D::create<TransformOp::Rotate>(double v) {
|
|
||||||
return TransformMatrix3D::create<TransformOp::RotateZ>(v);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
TransformMatrix3D TransformMatrix3D::create<TransformOp::Scale>(double v) {
|
|
||||||
// clang-format off
|
|
||||||
return TransformMatrix3D({
|
|
||||||
v, 0, 0, 0,
|
|
||||||
0, v, 0, 0,
|
|
||||||
0, 0, v, 0,
|
|
||||||
0, 0, 0, 1
|
|
||||||
});
|
|
||||||
// clang-format on
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
TransformMatrix3D TransformMatrix3D::create<TransformOp::ScaleX>(double v) {
|
|
||||||
// clang-format off
|
|
||||||
return TransformMatrix3D({
|
|
||||||
v, 0, 0, 0,
|
|
||||||
0, 1, 0, 0,
|
|
||||||
0, 0, 1, 0,
|
|
||||||
0, 0, 0, 1
|
|
||||||
});
|
|
||||||
// clang-format on
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
TransformMatrix3D TransformMatrix3D::create<TransformOp::ScaleY>(double v) {
|
|
||||||
// clang-format off
|
|
||||||
return TransformMatrix3D({
|
|
||||||
1, 0, 0, 0,
|
|
||||||
0, v, 0, 0,
|
|
||||||
0, 0, 1, 0,
|
|
||||||
0, 0, 0, 1
|
|
||||||
});
|
|
||||||
// clang-format on
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
TransformMatrix3D TransformMatrix3D::create<TransformOp::TranslateX>(double v) {
|
|
||||||
// clang-format off
|
|
||||||
return TransformMatrix3D({
|
|
||||||
1, 0, 0, 0,
|
|
||||||
0, 1, 0, 0,
|
|
||||||
0, 0, 1, 0,
|
|
||||||
v, 0, 0, 1
|
|
||||||
});
|
|
||||||
// clang-format on
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
TransformMatrix3D TransformMatrix3D::create<TransformOp::TranslateY>(double v) {
|
|
||||||
// clang-format off
|
|
||||||
return TransformMatrix3D({
|
|
||||||
1, 0, 0, 0,
|
|
||||||
0, 1, 0, 0,
|
|
||||||
0, 0, 1, 0,
|
|
||||||
0, v, 0, 1
|
|
||||||
});
|
|
||||||
// clang-format on
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
TransformMatrix3D TransformMatrix3D::create<TransformOp::SkewX>(double v) {
|
|
||||||
const auto tanVal = std::tan(v);
|
|
||||||
// clang-format off
|
|
||||||
return TransformMatrix3D({
|
|
||||||
1, 0, 0, 0,
|
|
||||||
tanVal, 1, 0, 0,
|
|
||||||
0, 0, 1, 0,
|
|
||||||
0, 0, 0, 1
|
|
||||||
});
|
|
||||||
// clang-format on
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
TransformMatrix3D TransformMatrix3D::create<TransformOp::SkewY>(double v) {
|
|
||||||
const auto tanVal = std::tan(v);
|
|
||||||
// clang-format off
|
|
||||||
return TransformMatrix3D({
|
|
||||||
1, tanVal, 0, 0,
|
|
||||||
0, 1, 0, 0,
|
|
||||||
0, 0, 1, 0,
|
|
||||||
0, 0, 0, 1
|
|
||||||
});
|
|
||||||
// clang-format on
|
|
||||||
}
|
|
||||||
|
|
||||||
template <TransformOp TOperation>
|
|
||||||
TransformMatrix3D TransformMatrix3D::create(double value) {
|
|
||||||
throw std::invalid_argument(
|
|
||||||
"[Reanimated] Cannot create TransformMatrix3D from: " +
|
|
||||||
getOperationNameFromType(TOperation));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TransformMatrix3D::operator==(const TransformMatrix3D &other) const {
|
|
||||||
return matrix_ == other.matrix_;
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector4D operator*(const Vector4D &v, const TransformMatrix3D &m) {
|
|
||||||
Vector4D result;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < 4; ++i) {
|
|
||||||
for (size_t j = 0; j < 4; ++j) {
|
|
||||||
result[i] += v[j] * m[j * 4 + i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
|
||||||
|
|
||||||
std::ostream &operator<<(std::ostream &os, const TransformMatrix3D &matrix) {
|
|
||||||
std::string result = "TransformMatrix3D{";
|
|
||||||
for (size_t i = 0; i < 16; ++i) {
|
|
||||||
result += std::to_string(matrix[i]);
|
|
||||||
if (i < 15) {
|
|
||||||
result += ", ";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
result += "}";
|
|
||||||
return os << result;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // NDEBUG
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Calculates the determinant of the 4x4 matrix using the minor (Laplace
|
|
||||||
* expansion) method.
|
|
||||||
*
|
|
||||||
* | a1 a2 a3 a4 |
|
|
||||||
* | b1 b2 b3 b4 |
|
|
||||||
* | c1 c2 c3 c4 |
|
|
||||||
* | d1 d2 d3 d4 |
|
|
||||||
*/
|
|
||||||
double TransformMatrix3D::determinant() const {
|
|
||||||
const double a1 = matrix_[0];
|
|
||||||
const double b1 = matrix_[1];
|
|
||||||
const double c1 = matrix_[2];
|
|
||||||
const double d1 = matrix_[3];
|
|
||||||
|
|
||||||
const double a2 = matrix_[4];
|
|
||||||
const double b2 = matrix_[5];
|
|
||||||
const double c2 = matrix_[6];
|
|
||||||
const double d2 = matrix_[7];
|
|
||||||
|
|
||||||
const double a3 = matrix_[8];
|
|
||||||
const double b3 = matrix_[9];
|
|
||||||
const double c3 = matrix_[10];
|
|
||||||
const double d3 = matrix_[11];
|
|
||||||
|
|
||||||
const double a4 = matrix_[12];
|
|
||||||
const double b4 = matrix_[13];
|
|
||||||
const double c4 = matrix_[14];
|
|
||||||
const double d4 = matrix_[15];
|
|
||||||
|
|
||||||
return a1 * determinant3x3(b2, b3, b4, c2, c3, c4, d2, d3, d4) -
|
|
||||||
b1 * determinant3x3(a2, a3, a4, c2, c3, c4, d2, d3, d4) +
|
|
||||||
c1 * determinant3x3(a2, a3, a4, b2, b3, b4, d2, d3, d4) -
|
|
||||||
d1 * determinant3x3(a2, a3, a4, b2, b3, b4, c2, c3, c4);
|
|
||||||
}
|
|
||||||
|
|
||||||
void TransformMatrix3D::adjugate() {
|
|
||||||
const double a1 = matrix_[0];
|
|
||||||
const double b1 = matrix_[1];
|
|
||||||
const double c1 = matrix_[2];
|
|
||||||
const double d1 = matrix_[3];
|
|
||||||
|
|
||||||
const double a2 = matrix_[4];
|
|
||||||
const double b2 = matrix_[5];
|
|
||||||
const double c2 = matrix_[6];
|
|
||||||
const double d2 = matrix_[7];
|
|
||||||
|
|
||||||
const double a3 = matrix_[8];
|
|
||||||
const double b3 = matrix_[9];
|
|
||||||
const double c3 = matrix_[10];
|
|
||||||
const double d3 = matrix_[11];
|
|
||||||
|
|
||||||
const double a4 = matrix_[12];
|
|
||||||
const double b4 = matrix_[13];
|
|
||||||
const double c4 = matrix_[14];
|
|
||||||
const double d4 = matrix_[15];
|
|
||||||
|
|
||||||
matrix_[0] = determinant3x3(b2, b3, b4, c2, c3, c4, d2, d3, d4);
|
|
||||||
matrix_[4] = -determinant3x3(a2, a3, a4, c2, c3, c4, d2, d3, d4);
|
|
||||||
matrix_[8] = determinant3x3(a2, a3, a4, b2, b3, b4, d2, d3, d4);
|
|
||||||
matrix_[12] = -determinant3x3(a2, a3, a4, b2, b3, b4, c2, c3, c4);
|
|
||||||
|
|
||||||
matrix_[1] = -determinant3x3(b1, b3, b4, c1, c3, c4, d1, d3, d4);
|
|
||||||
matrix_[5] = determinant3x3(a1, a3, a4, c1, c3, c4, d1, d3, d4);
|
|
||||||
matrix_[9] = -determinant3x3(a1, a3, a4, b1, b3, b4, d1, d3, d4);
|
|
||||||
matrix_[13] = determinant3x3(a1, a3, a4, b1, b3, b4, c1, c3, c4);
|
|
||||||
|
|
||||||
matrix_[2] = determinant3x3(b1, b2, b4, c1, c2, c4, d1, d2, d4);
|
|
||||||
matrix_[6] = -determinant3x3(a1, a2, a4, c1, c2, c4, d1, d2, d4);
|
|
||||||
matrix_[10] = determinant3x3(a1, a2, a4, b1, b2, b4, d1, d2, d4);
|
|
||||||
matrix_[14] = -determinant3x3(a1, a2, a4, b1, b2, b4, c1, c2, c4);
|
|
||||||
|
|
||||||
matrix_[3] = -determinant3x3(b1, b2, b3, c1, c2, c3, d1, d2, d3);
|
|
||||||
matrix_[7] = determinant3x3(a1, a2, a3, c1, c2, c3, d1, d2, d3);
|
|
||||||
matrix_[11] = -determinant3x3(a1, a2, a3, b1, b2, b3, d1, d2, d3);
|
|
||||||
matrix_[15] = determinant3x3(a1, a2, a3, b1, b2, b3, c1, c2, c3);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TransformMatrix3D::invert() {
|
|
||||||
const auto det = determinant();
|
|
||||||
|
|
||||||
// If the determinant is invalid (zero, very small number, etc.), then the
|
|
||||||
// matrix is not invertible
|
|
||||||
if (!std::isnormal(det)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
adjugate();
|
|
||||||
for (size_t i = 0; i < 16; ++i) {
|
|
||||||
matrix_[i] /= det;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TransformMatrix3D::translate3d(const Vector3D &translation) {
|
|
||||||
for (size_t i = 0; i < 4; ++i) {
|
|
||||||
matrix_[12 + i] += translation[0] * matrix_[i] +
|
|
||||||
translation[1] * matrix_[4 + i] + translation[2] * matrix_[8 + i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void TransformMatrix3D::scale3d(const Vector3D &scale) {
|
|
||||||
for (size_t i = 0; i < 4; ++i) {
|
|
||||||
matrix_[i] *= scale[0];
|
|
||||||
matrix_[4 + i] *= scale[1];
|
|
||||||
matrix_[8 + i] *= scale[2];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::optional<TransformMatrix3D::Decomposed> TransformMatrix3D::decompose()
|
|
||||||
const {
|
|
||||||
auto matrixCp = *this;
|
|
||||||
|
|
||||||
if (!matrixCp.normalize()) {
|
|
||||||
return std::nullopt;
|
|
||||||
}
|
|
||||||
const auto perspective = matrixCp.computePerspective();
|
|
||||||
if (!perspective) {
|
|
||||||
return std::nullopt;
|
|
||||||
}
|
|
||||||
const auto translation = matrixCp.getTranslation();
|
|
||||||
|
|
||||||
// Move the remaining matrix to 3 separate column vectors for easier
|
|
||||||
// processing
|
|
||||||
std::array<Vector3D, 3> rows;
|
|
||||||
for (size_t i = 0; i < 3; ++i) {
|
|
||||||
rows[i] =
|
|
||||||
Vector3D(matrixCp[i * 4], matrixCp[i * 4 + 1], matrixCp[i * 4 + 2]);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto [scale, skew] = computeScaleAndSkew(rows);
|
|
||||||
|
|
||||||
// At this point, the matrix (in rows) is orthonormal.
|
|
||||||
// Check for a coordinate system flip. If the determinant
|
|
||||||
// is negative, then negate the matrix and the scaling factors.
|
|
||||||
if (rows[0].dot(rows[1].cross(rows[2])) < 0) {
|
|
||||||
scale *= -1;
|
|
||||||
for (auto &row : rows) {
|
|
||||||
row *= -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const auto rotation = computeQuaternion(rows);
|
|
||||||
|
|
||||||
return TransformMatrix3D::Decomposed{
|
|
||||||
.scale = scale,
|
|
||||||
.skew = skew,
|
|
||||||
.quaternion = rotation,
|
|
||||||
.translation = translation,
|
|
||||||
.perspective = perspective.value()};
|
|
||||||
}
|
|
||||||
|
|
||||||
TransformMatrix3D TransformMatrix3D::recompose(
|
|
||||||
const TransformMatrix3D::Decomposed &decomposed) {
|
|
||||||
auto result = TransformMatrix3D::Identity();
|
|
||||||
|
|
||||||
// Start from applying perspective
|
|
||||||
for (size_t i = 0; i < 4; ++i) {
|
|
||||||
result[3 + i * 4] = decomposed.perspective[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Apply translation
|
|
||||||
result.translate3d(decomposed.translation);
|
|
||||||
|
|
||||||
// Apply rotation
|
|
||||||
result = fromQuaternion(decomposed.quaternion) * result;
|
|
||||||
|
|
||||||
// Apply skew
|
|
||||||
auto hasSkewYZ = decomposed.skew[2] != 0;
|
|
||||||
auto hasSkewXZ = decomposed.skew[1] != 0;
|
|
||||||
auto hasSkewXY = decomposed.skew[0] != 0;
|
|
||||||
|
|
||||||
if (hasSkewYZ || hasSkewXZ || hasSkewXY) {
|
|
||||||
auto tmp = TransformMatrix3D::Identity();
|
|
||||||
if (hasSkewYZ) { // YZ
|
|
||||||
tmp[9] = decomposed.skew[2];
|
|
||||||
result = tmp * result;
|
|
||||||
}
|
|
||||||
if (hasSkewXZ) { // XZ
|
|
||||||
tmp[8] = decomposed.skew[1];
|
|
||||||
result = tmp * result;
|
|
||||||
}
|
|
||||||
if (hasSkewXY) { // XY
|
|
||||||
tmp[4] = decomposed.skew[0];
|
|
||||||
result = tmp * result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Apply scale
|
|
||||||
result.scale3d(decomposed.scale);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
TransformMatrix3D TransformMatrix3D::fromQuaternion(const Quaternion &q) {
|
|
||||||
const double xx = q.x * q.x;
|
|
||||||
const double yy = q.y * q.y;
|
|
||||||
const double zz = q.z * q.z;
|
|
||||||
const double xz = q.x * q.z;
|
|
||||||
const double xy = q.x * q.y;
|
|
||||||
const double yz = q.y * q.z;
|
|
||||||
const double xw = q.w * q.x;
|
|
||||||
const double yw = q.w * q.y;
|
|
||||||
const double zw = q.w * q.z;
|
|
||||||
|
|
||||||
// clang-format off
|
|
||||||
return TransformMatrix3D({
|
|
||||||
1 - 2 * (yy + zz), 2 * (xy - zw), 2 * (xz + yw), 0,
|
|
||||||
2 * (xy + zw), 1 - 2 * (xx + zz), 2 * (yz - xw), 0,
|
|
||||||
2 * (xz - yw), 2 * (yz + xw), 1 - 2 * (xx + yy), 0,
|
|
||||||
0, 0, 0, 1
|
|
||||||
});
|
|
||||||
// clang-format on
|
|
||||||
}
|
|
||||||
|
|
||||||
std::optional<Vector4D> TransformMatrix3D::computePerspective() const {
|
|
||||||
auto perspectiveMatrix = *this;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < 3; ++i) {
|
|
||||||
perspectiveMatrix[3 + i * 4] = 0;
|
|
||||||
}
|
|
||||||
perspectiveMatrix[15] = 1;
|
|
||||||
|
|
||||||
if (perspectiveMatrix.isSingular()) {
|
|
||||||
return std::nullopt;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (matrix_[3] == 0 && matrix_[7] == 0 && matrix_[11] == 0) {
|
|
||||||
// No perspective
|
|
||||||
return Vector4D{0, 0, 0, 1};
|
|
||||||
}
|
|
||||||
|
|
||||||
// Invert and transpose the perspective matrix (we will solve the equation
|
|
||||||
// by multiplying the rhs vector by the inverse of the perspective matrix)
|
|
||||||
if (!perspectiveMatrix.invert()) {
|
|
||||||
return std::nullopt;
|
|
||||||
}
|
|
||||||
perspectiveMatrix.transpose();
|
|
||||||
|
|
||||||
// rhs is the right hand side of the equation we are trying to solve
|
|
||||||
const Vector4D rhs(matrix_[3], matrix_[7], matrix_[11], matrix_[15]);
|
|
||||||
// Solve the equation
|
|
||||||
return rhs * perspectiveMatrix;
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector3D TransformMatrix3D::getTranslation() const {
|
|
||||||
return Vector3D(matrix_[12], matrix_[13], matrix_[14]);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::pair<Vector3D, Vector3D> TransformMatrix3D::computeScaleAndSkew(
|
|
||||||
std::array<Vector3D, 3> &rows) {
|
|
||||||
Vector3D scale, skew;
|
|
||||||
|
|
||||||
// Compute X scale factor and normalize first row
|
|
||||||
scale[0] = rows[0].length();
|
|
||||||
rows[0].normalize();
|
|
||||||
|
|
||||||
// Compute XY shear factor and make 2nd row orthogonal to 1st.
|
|
||||||
skew[0] = rows[0].dot(rows[1]);
|
|
||||||
rows[1] = rows[1].addScaled(rows[0], -skew[0]);
|
|
||||||
|
|
||||||
// Now, compute Y scale and normalize 2nd row.
|
|
||||||
scale[1] = rows[1].length();
|
|
||||||
rows[1].normalize();
|
|
||||||
skew[0] /= scale[1]; // normalize XY shear
|
|
||||||
|
|
||||||
// Compute XZ and YZ shears, orthogonalize 3rd row
|
|
||||||
skew[1] = rows[0].dot(rows[2]);
|
|
||||||
rows[2] = rows[2].addScaled(rows[0], -skew[1]);
|
|
||||||
skew[2] = rows[1].dot(rows[2]);
|
|
||||||
rows[2] = rows[2].addScaled(rows[1], -skew[2]);
|
|
||||||
|
|
||||||
// Next, get Z scale and normalize 3rd row
|
|
||||||
scale[2] = rows[2].length();
|
|
||||||
rows[2].normalize();
|
|
||||||
skew[1] /= scale[2]; // normalize XZ shear
|
|
||||||
skew[2] /= scale[2]; // normalize YZ shear
|
|
||||||
|
|
||||||
return {scale, skew};
|
|
||||||
}
|
|
||||||
|
|
||||||
Quaternion TransformMatrix3D::computeQuaternion(std::array<Vector3D, 3> &rows) {
|
|
||||||
double m00 = rows[0][0];
|
|
||||||
double m01 = rows[0][1];
|
|
||||||
double m02 = rows[0][2];
|
|
||||||
|
|
||||||
double m10 = rows[1][0];
|
|
||||||
double m11 = rows[1][1];
|
|
||||||
double m12 = rows[1][2];
|
|
||||||
|
|
||||||
double m20 = rows[2][0];
|
|
||||||
double m21 = rows[2][1];
|
|
||||||
double m22 = rows[2][2];
|
|
||||||
|
|
||||||
Quaternion q;
|
|
||||||
double trace = m00 + m11 + m22; // Trace of the matrix
|
|
||||||
|
|
||||||
if (trace > 0.0) {
|
|
||||||
double s = 0.5 / sqrt(trace + 1.0);
|
|
||||||
q.w = 0.25 / s;
|
|
||||||
q.x = (m21 - m12) * s;
|
|
||||||
q.y = (m02 - m20) * s;
|
|
||||||
q.z = (m10 - m01) * s;
|
|
||||||
} else {
|
|
||||||
if (m00 > m11 && m00 > m22) {
|
|
||||||
double s = 2.0 * sqrt(1.0 + m00 - m11 - m22);
|
|
||||||
q.w = (m21 - m12) / s;
|
|
||||||
q.x = 0.25 * s;
|
|
||||||
q.y = (m01 + m10) / s;
|
|
||||||
q.z = (m02 + m20) / s;
|
|
||||||
} else if (m11 > m22) {
|
|
||||||
double s = 2.0 * sqrt(1.0 + m11 - m00 - m22);
|
|
||||||
q.w = (m02 - m20) / s;
|
|
||||||
q.x = (m01 + m10) / s;
|
|
||||||
q.y = 0.25 * s;
|
|
||||||
q.z = (m12 + m21) / s;
|
|
||||||
} else {
|
|
||||||
double s = 2.0 * sqrt(1.0 + m22 - m00 - m11);
|
|
||||||
q.w = (m10 - m01) / s;
|
|
||||||
q.x = (m02 + m20) / s;
|
|
||||||
q.y = (m12 + m21) / s;
|
|
||||||
q.z = 0.25 * s;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return q;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Calculate the determinant of a 3x3 matrix
|
|
||||||
*
|
|
||||||
* | a b c |
|
|
||||||
* | d e f |
|
|
||||||
* | g h i |
|
|
||||||
*/
|
|
||||||
double TransformMatrix3D::determinant3x3(
|
|
||||||
const double a,
|
|
||||||
const double b,
|
|
||||||
const double c,
|
|
||||||
const double d,
|
|
||||||
const double e,
|
|
||||||
const double f,
|
|
||||||
const double g,
|
|
||||||
const double h,
|
|
||||||
const double i) {
|
|
||||||
return (a * e * i) + (b * f * g) + (c * d * h) - (c * e * g) - (b * d * i) -
|
|
||||||
(a * f * h);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace reanimated::css
|
|
||||||
Generated
Vendored
-84
@@ -1,84 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <reanimated/CSS/common/transforms/Quaternion.h>
|
|
||||||
#include <reanimated/CSS/common/transforms/TransformMatrix.h>
|
|
||||||
#include <reanimated/CSS/common/transforms/TransformOp.h>
|
|
||||||
#include <reanimated/CSS/common/transforms/vectors.h>
|
|
||||||
|
|
||||||
#include <folly/dynamic.h>
|
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
namespace reanimated::css {
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
static constexpr size_t MATRIX_3D_DIMENSION = 4; // 4x4 matrix
|
|
||||||
}
|
|
||||||
|
|
||||||
class TransformMatrix3D
|
|
||||||
: public TransformMatrixBase<TransformMatrix3D, MATRIX_3D_DIMENSION> {
|
|
||||||
public:
|
|
||||||
struct Decomposed {
|
|
||||||
Vector3D scale;
|
|
||||||
Vector3D skew;
|
|
||||||
Quaternion quaternion;
|
|
||||||
Vector3D translation;
|
|
||||||
Vector4D perspective;
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
|
||||||
friend std::ostream &operator<<(
|
|
||||||
std::ostream &os,
|
|
||||||
const Decomposed &decomposed);
|
|
||||||
#endif // NDEBUG
|
|
||||||
|
|
||||||
Decomposed interpolate(double progress, const Decomposed &other) const;
|
|
||||||
};
|
|
||||||
|
|
||||||
using TransformMatrixBase<TransformMatrix3D, MATRIX_3D_DIMENSION>::
|
|
||||||
TransformMatrixBase;
|
|
||||||
|
|
||||||
static TransformMatrix3D Identity();
|
|
||||||
|
|
||||||
template <TransformOp TOperation>
|
|
||||||
static TransformMatrix3D create(double value);
|
|
||||||
|
|
||||||
bool operator==(const TransformMatrix3D &other) const override;
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
|
||||||
friend std::ostream &operator<<(
|
|
||||||
std::ostream &os,
|
|
||||||
const TransformMatrix3D &matrix);
|
|
||||||
#endif // NDEBUG
|
|
||||||
|
|
||||||
double determinant() const override;
|
|
||||||
void adjugate();
|
|
||||||
bool invert();
|
|
||||||
void translate3d(const Vector3D &translation);
|
|
||||||
void scale3d(const Vector3D &scale);
|
|
||||||
|
|
||||||
std::optional<Decomposed> decompose() const;
|
|
||||||
static TransformMatrix3D recompose(const Decomposed &decomposed);
|
|
||||||
static TransformMatrix3D fromQuaternion(const Quaternion &q);
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::optional<Vector4D> computePerspective() const;
|
|
||||||
|
|
||||||
Vector3D getTranslation() const;
|
|
||||||
static std::pair<Vector3D, Vector3D> computeScaleAndSkew(
|
|
||||||
std::array<Vector3D, 3> &rows);
|
|
||||||
static Quaternion computeQuaternion(std::array<Vector3D, 3> &columns);
|
|
||||||
|
|
||||||
inline static double determinant3x3(
|
|
||||||
double a,
|
|
||||||
double b,
|
|
||||||
double c,
|
|
||||||
double d,
|
|
||||||
double e,
|
|
||||||
double f,
|
|
||||||
double g,
|
|
||||||
double h,
|
|
||||||
double i);
|
|
||||||
};
|
|
||||||
|
|
||||||
Vector4D operator*(const Vector4D &v, const TransformMatrix3D &m);
|
|
||||||
|
|
||||||
} // namespace reanimated::css
|
|
||||||
Generated
Vendored
-52
@@ -1,52 +0,0 @@
|
|||||||
#include <reanimated/CSS/common/transforms/TransformOp.h>
|
|
||||||
|
|
||||||
#include <array>
|
|
||||||
#include <unordered_map>
|
|
||||||
|
|
||||||
namespace reanimated::css {
|
|
||||||
|
|
||||||
constexpr std::array<const char *, 13> transformOperationStrings = {
|
|
||||||
"perspective",
|
|
||||||
"rotate",
|
|
||||||
"rotateX",
|
|
||||||
"rotateY",
|
|
||||||
"rotateZ",
|
|
||||||
"scale",
|
|
||||||
"scaleX",
|
|
||||||
"scaleY",
|
|
||||||
"translateX",
|
|
||||||
"translateY",
|
|
||||||
"skewX",
|
|
||||||
"skewY",
|
|
||||||
"matrix"};
|
|
||||||
|
|
||||||
TransformOp getTransformOperationType(const std::string &property) {
|
|
||||||
static const std::unordered_map<std::string, TransformOp> stringToEnumMap = {
|
|
||||||
{"perspective", TransformOp::Perspective},
|
|
||||||
{"rotate", TransformOp::Rotate},
|
|
||||||
{"rotateX", TransformOp::RotateX},
|
|
||||||
{"rotateY", TransformOp::RotateY},
|
|
||||||
{"rotateZ", TransformOp::RotateZ},
|
|
||||||
{"scale", TransformOp::Scale},
|
|
||||||
{"scaleX", TransformOp::ScaleX},
|
|
||||||
{"scaleY", TransformOp::ScaleY},
|
|
||||||
{"translateX", TransformOp::TranslateX},
|
|
||||||
{"translateY", TransformOp::TranslateY},
|
|
||||||
{"skewX", TransformOp::SkewX},
|
|
||||||
{"skewY", TransformOp::SkewY},
|
|
||||||
{"matrix", TransformOp::Matrix}};
|
|
||||||
|
|
||||||
auto it = stringToEnumMap.find(property);
|
|
||||||
if (it != stringToEnumMap.end()) {
|
|
||||||
return it->second;
|
|
||||||
} else {
|
|
||||||
throw std::invalid_argument(
|
|
||||||
"[Reanimated] Unknown transform operation: " + property);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string getOperationNameFromType(const TransformOp type) {
|
|
||||||
return transformOperationStrings[static_cast<size_t>(type)];
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace reanimated::css
|
|
||||||
Generated
Vendored
-27
@@ -1,27 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
namespace reanimated::css {
|
|
||||||
|
|
||||||
enum class TransformOp {
|
|
||||||
Perspective,
|
|
||||||
Rotate,
|
|
||||||
RotateX,
|
|
||||||
RotateY,
|
|
||||||
RotateZ,
|
|
||||||
Scale,
|
|
||||||
ScaleX,
|
|
||||||
ScaleY,
|
|
||||||
TranslateX,
|
|
||||||
TranslateY,
|
|
||||||
SkewX,
|
|
||||||
SkewY,
|
|
||||||
Matrix,
|
|
||||||
};
|
|
||||||
|
|
||||||
TransformOp getTransformOperationType(const std::string &property);
|
|
||||||
|
|
||||||
std::string getOperationNameFromType(const TransformOp type);
|
|
||||||
|
|
||||||
} // namespace reanimated::css
|
|
||||||
Generated
Vendored
-166
@@ -1,166 +0,0 @@
|
|||||||
#include <reanimated/CSS/common/transforms/vectors.h>
|
|
||||||
|
|
||||||
namespace reanimated::css {
|
|
||||||
|
|
||||||
// Vector2D
|
|
||||||
|
|
||||||
double &Vector2D::operator[](const size_t idx) {
|
|
||||||
return vec[idx];
|
|
||||||
}
|
|
||||||
|
|
||||||
const double &Vector2D::operator[](const size_t idx) const {
|
|
||||||
return vec[idx];
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector2D &Vector2D::operator*=(const double scalar) {
|
|
||||||
vec[0] *= scalar;
|
|
||||||
vec[1] *= scalar;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
|
||||||
|
|
||||||
std::ostream &operator<<(std::ostream &os, const Vector2D &vector) {
|
|
||||||
os << "Vector2D(" << vector.vec[0] << ", " << vector.vec[1] << ")";
|
|
||||||
return os;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // NDEBUG
|
|
||||||
|
|
||||||
double Vector2D::length() const {
|
|
||||||
return std::hypot(vec[0], vec[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Vector2D::scaleToLength(double targetLength) {
|
|
||||||
double currentLength = length();
|
|
||||||
if (currentLength != 0) {
|
|
||||||
double factor = targetLength / currentLength;
|
|
||||||
vec[0] *= factor;
|
|
||||||
vec[1] *= factor;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Vector2D::normalize() {
|
|
||||||
scaleToLength(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
double Vector2D::dot(const Vector2D &other) const {
|
|
||||||
return vec[0] * other.vec[0] + vec[1] * other.vec[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
double Vector2D::cross(const Vector2D &other) const {
|
|
||||||
return vec[0] * other.vec[1] - vec[1] * other.vec[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector2D Vector2D::addScaled(const Vector2D &other, const double scale) const {
|
|
||||||
return Vector2D{vec[0] + scale * other.vec[0], vec[1] + scale * other.vec[1]};
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector2D Vector2D::interpolate(const double progress, const Vector2D &other)
|
|
||||||
const {
|
|
||||||
return Vector2D{
|
|
||||||
vec[0] + progress * (other.vec[0] - vec[0]),
|
|
||||||
vec[1] + progress * (other.vec[1] - vec[1])};
|
|
||||||
}
|
|
||||||
|
|
||||||
// Vector3D
|
|
||||||
|
|
||||||
double &Vector3D::operator[](const size_t idx) {
|
|
||||||
return vec[idx];
|
|
||||||
}
|
|
||||||
|
|
||||||
const double &Vector3D::operator[](const size_t idx) const {
|
|
||||||
return vec[idx];
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector3D &Vector3D::operator*=(const double scalar) {
|
|
||||||
vec[0] *= scalar;
|
|
||||||
vec[1] *= scalar;
|
|
||||||
vec[2] *= scalar;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
|
||||||
|
|
||||||
std::ostream &operator<<(std::ostream &os, const Vector3D &vector) {
|
|
||||||
os << "Vector3D(" << vector.vec[0] << ", " << vector.vec[1] << ", "
|
|
||||||
<< vector.vec[2] << ")";
|
|
||||||
return os;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // NDEBUG
|
|
||||||
|
|
||||||
double Vector3D::length() const {
|
|
||||||
return std::hypot(vec[0], vec[1], vec[2]);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Vector3D::scaleToLength(double targetLength) {
|
|
||||||
double currentLength = length();
|
|
||||||
if (currentLength != 0) {
|
|
||||||
double factor = targetLength / currentLength;
|
|
||||||
vec[0] *= factor;
|
|
||||||
vec[1] *= factor;
|
|
||||||
vec[2] *= factor;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Vector3D::normalize() {
|
|
||||||
scaleToLength(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
double Vector3D::dot(const Vector3D &other) const {
|
|
||||||
return vec[0] * other.vec[0] + vec[1] * other.vec[1] + vec[2] * other.vec[2];
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector3D Vector3D::cross(const Vector3D &other) const {
|
|
||||||
return Vector3D{
|
|
||||||
vec[1] * other.vec[2] - vec[2] * other.vec[1],
|
|
||||||
vec[2] * other.vec[0] - vec[0] * other.vec[2],
|
|
||||||
vec[0] * other.vec[1] - vec[1] * other.vec[0]};
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector3D Vector3D::addScaled(const Vector3D &other, const double scale) const {
|
|
||||||
return Vector3D{
|
|
||||||
vec[0] + scale * other.vec[0],
|
|
||||||
vec[1] + scale * other.vec[1],
|
|
||||||
vec[2] + scale * other.vec[2]};
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector3D Vector3D::interpolate(const double progress, const Vector3D &other)
|
|
||||||
const {
|
|
||||||
return Vector3D{
|
|
||||||
vec[0] + progress * (other.vec[0] - vec[0]),
|
|
||||||
vec[1] + progress * (other.vec[1] - vec[1]),
|
|
||||||
vec[2] + progress * (other.vec[2] - vec[2])};
|
|
||||||
}
|
|
||||||
|
|
||||||
// Vector4D
|
|
||||||
|
|
||||||
double &Vector4D::operator[](const size_t idx) {
|
|
||||||
return vec[idx];
|
|
||||||
}
|
|
||||||
|
|
||||||
const double &Vector4D::operator[](const size_t idx) const {
|
|
||||||
return vec[idx];
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector4D Vector4D::interpolate(const double progress, const Vector4D &other)
|
|
||||||
const {
|
|
||||||
return Vector4D{
|
|
||||||
vec[0] + progress * (other.vec[0] - vec[0]),
|
|
||||||
vec[1] + progress * (other.vec[1] - vec[1]),
|
|
||||||
vec[2] + progress * (other.vec[2] - vec[2]),
|
|
||||||
vec[3] + progress * (other.vec[3] - vec[3])};
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
|
||||||
|
|
||||||
std::ostream &operator<<(std::ostream &os, const Vector4D &vector) {
|
|
||||||
os << "Vector4D(" << vector.vec[0] << ", " << vector.vec[1] << ", "
|
|
||||||
<< vector.vec[2] << ", " << vector.vec[3] << ")";
|
|
||||||
return os;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // NDEBUG
|
|
||||||
|
|
||||||
} // namespace reanimated::css
|
|
||||||
Generated
Vendored
-77
@@ -1,77 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <array>
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
|
||||||
#include <iostream>
|
|
||||||
#endif // NDEBUG
|
|
||||||
|
|
||||||
namespace reanimated::css {
|
|
||||||
|
|
||||||
struct Vector2D {
|
|
||||||
std::array<double, 2> vec;
|
|
||||||
|
|
||||||
Vector2D() : vec({0, 0}) {}
|
|
||||||
explicit Vector2D(double x, double y) : vec({x, y}) {}
|
|
||||||
explicit Vector2D(std::array<double, 2> vec) : vec(vec) {}
|
|
||||||
|
|
||||||
double &operator[](size_t idx);
|
|
||||||
const double &operator[](size_t idx) const;
|
|
||||||
Vector2D &operator*=(double scalar);
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
|
||||||
friend std::ostream &operator<<(std::ostream &os, const Vector2D &vector);
|
|
||||||
#endif // NDEBUG
|
|
||||||
|
|
||||||
double length() const;
|
|
||||||
void scaleToLength(double targetLength);
|
|
||||||
void normalize();
|
|
||||||
double dot(const Vector2D &other) const;
|
|
||||||
double cross(const Vector2D &other) const;
|
|
||||||
Vector2D addScaled(const Vector2D &other, double scale) const;
|
|
||||||
Vector2D interpolate(double progress, const Vector2D &other) const;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Vector3D {
|
|
||||||
std::array<double, 3> vec;
|
|
||||||
|
|
||||||
Vector3D() : vec({0, 0, 0}) {}
|
|
||||||
explicit Vector3D(double x, double y, double z) : vec({x, y, z}) {}
|
|
||||||
explicit Vector3D(std::array<double, 3> vec) : vec(vec) {}
|
|
||||||
|
|
||||||
double &operator[](size_t idx);
|
|
||||||
const double &operator[](size_t idx) const;
|
|
||||||
Vector3D &operator*=(double scalar);
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
|
||||||
friend std::ostream &operator<<(std::ostream &os, const Vector3D &vector);
|
|
||||||
#endif // NDEBUG
|
|
||||||
|
|
||||||
double length() const;
|
|
||||||
void scaleToLength(double targetLength);
|
|
||||||
void normalize();
|
|
||||||
double dot(const Vector3D &other) const;
|
|
||||||
Vector3D cross(const Vector3D &other) const;
|
|
||||||
Vector3D addScaled(const Vector3D &other, double scale) const;
|
|
||||||
Vector3D interpolate(double progress, const Vector3D &other) const;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Vector4D {
|
|
||||||
std::array<double, 4> vec;
|
|
||||||
|
|
||||||
Vector4D() : vec({0, 0, 0, 0}) {}
|
|
||||||
explicit Vector4D(double x, double y, double z, double w)
|
|
||||||
: vec({x, y, z, w}) {}
|
|
||||||
explicit Vector4D(std::array<double, 4> vec) : vec(vec) {}
|
|
||||||
|
|
||||||
double &operator[](size_t idx);
|
|
||||||
const double &operator[](size_t idx) const;
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
|
||||||
friend std::ostream &operator<<(std::ostream &os, const Vector4D &vector);
|
|
||||||
#endif // NDEBUG
|
|
||||||
|
|
||||||
Vector4D interpolate(double progress, const Vector4D &other) const;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace reanimated::css
|
|
||||||
Generated
Vendored
-107
@@ -1,107 +0,0 @@
|
|||||||
#include <reanimated/CSS/common/values/CSSAngle.h>
|
|
||||||
|
|
||||||
#include <iomanip>
|
|
||||||
#include <regex>
|
|
||||||
#include <unordered_map>
|
|
||||||
|
|
||||||
namespace reanimated::css {
|
|
||||||
|
|
||||||
CSSAngle::CSSAngle() : value(0) {}
|
|
||||||
|
|
||||||
CSSAngle::CSSAngle(const double value) : value(value) {}
|
|
||||||
|
|
||||||
CSSAngle::CSSAngle(const std::string &rotationString) {
|
|
||||||
static const std::regex validNumberRegex(R"(^[-+]?\d*\.?\d+$)");
|
|
||||||
static const std::unordered_map<std::string, double> unitFactors = {
|
|
||||||
{"rad", 1},
|
|
||||||
{"deg", M_PI / 180},
|
|
||||||
};
|
|
||||||
|
|
||||||
// Find position of the first non-numeric character (first character
|
|
||||||
// of the unit, e.g. "deg" or "rad")
|
|
||||||
size_t pos = rotationString.find_first_not_of("0123456789.-+");
|
|
||||||
|
|
||||||
if (pos == std::string::npos) {
|
|
||||||
throw std::invalid_argument(
|
|
||||||
"[Reanimated] CSSAngle: Invalid angle value: " + rotationString);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string numericPart = rotationString.substr(0, pos);
|
|
||||||
std::string unitPart = rotationString.substr(pos);
|
|
||||||
|
|
||||||
if (!std::regex_match(numericPart, validNumberRegex)) {
|
|
||||||
throw std::invalid_argument(
|
|
||||||
"[Reanimated] CSSAngle: Invalid angle value: " + rotationString);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Lookup the unit and convert to radians
|
|
||||||
auto it = unitFactors.find(unitPart);
|
|
||||||
if (it == unitFactors.cend()) {
|
|
||||||
throw std::invalid_argument(
|
|
||||||
"[Reanimated] CSSAngle: Invalid angle unit: " + unitPart);
|
|
||||||
}
|
|
||||||
|
|
||||||
double numericValue = std::stod(numericPart);
|
|
||||||
|
|
||||||
this->value = numericValue * it->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
CSSAngle::CSSAngle(const char *cstr) : CSSAngle(std::string_view{cstr}) {}
|
|
||||||
|
|
||||||
CSSAngle::CSSAngle(jsi::Runtime &rt, const jsi::Value &jsiValue) {
|
|
||||||
if (!jsiValue.isString()) {
|
|
||||||
throw std::invalid_argument(
|
|
||||||
"[Reanimated] CSSAngle: Invalid value type: " +
|
|
||||||
stringifyJSIValue(rt, jsiValue));
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string strValue = jsiValue.asString(rt).utf8(rt);
|
|
||||||
*this = CSSAngle(strValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
CSSAngle::CSSAngle(const folly::dynamic &value) {
|
|
||||||
if (!value.isString()) {
|
|
||||||
throw std::invalid_argument(
|
|
||||||
"[Reanimated] CSSAngle: Invalid value type: " + folly::toJson(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
*this = CSSAngle(value.asString());
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CSSAngle::canConstruct(jsi::Runtime &rt, const jsi::Value &jsiValue) {
|
|
||||||
// TODO - improve canConstruct check and add check for string correctness
|
|
||||||
return jsiValue.isString() || jsiValue.isNumber();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CSSAngle::canConstruct(const folly::dynamic &value) {
|
|
||||||
return value.isString() || value.isNumber();
|
|
||||||
}
|
|
||||||
|
|
||||||
folly::dynamic CSSAngle::toDynamic() const {
|
|
||||||
return folly::dynamic(toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string CSSAngle::toString() const {
|
|
||||||
std::ostringstream stream;
|
|
||||||
stream << std::fixed << std::setprecision(4) << value;
|
|
||||||
return stream.str() + "rad";
|
|
||||||
}
|
|
||||||
|
|
||||||
CSSAngle CSSAngle::interpolate(double progress, const CSSAngle &to) const {
|
|
||||||
return CSSAngle(value + (to.value - value) * progress);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CSSAngle::operator==(const CSSAngle &other) const {
|
|
||||||
return value == other.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
|
||||||
|
|
||||||
std::ostream &operator<<(std::ostream &os, const CSSAngle &angleValue) {
|
|
||||||
os << "CSSAngle(" << angleValue.value << ")";
|
|
||||||
return os;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // NDEBUG
|
|
||||||
|
|
||||||
} // namespace reanimated::css
|
|
||||||
Generated
Vendored
-38
@@ -1,38 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <reanimated/CSS/common/values/CSSValue.h>
|
|
||||||
|
|
||||||
#include <worklets/Tools/JSISerializer.h>
|
|
||||||
|
|
||||||
#include <folly/json.h>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
namespace reanimated::css {
|
|
||||||
|
|
||||||
using namespace worklets;
|
|
||||||
|
|
||||||
struct CSSAngle : public CSSSimpleValue<CSSAngle> {
|
|
||||||
double value;
|
|
||||||
|
|
||||||
CSSAngle();
|
|
||||||
explicit CSSAngle(double value);
|
|
||||||
explicit CSSAngle(const std::string &rotationString);
|
|
||||||
explicit CSSAngle(const char *cstr);
|
|
||||||
explicit CSSAngle(jsi::Runtime &rt, const jsi::Value &jsiValue);
|
|
||||||
explicit CSSAngle(const folly::dynamic &value);
|
|
||||||
|
|
||||||
static bool canConstruct(jsi::Runtime &rt, const jsi::Value &jsiValue);
|
|
||||||
static bool canConstruct(const folly::dynamic &value);
|
|
||||||
|
|
||||||
folly::dynamic toDynamic() const override;
|
|
||||||
std::string toString() const override;
|
|
||||||
CSSAngle interpolate(double progress, const CSSAngle &to) const override;
|
|
||||||
|
|
||||||
bool operator==(const CSSAngle &other) const;
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
|
||||||
friend std::ostream &operator<<(std::ostream &os, const CSSAngle &angleValue);
|
|
||||||
#endif // NDEBUG
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace reanimated::css
|
|
||||||
Generated
Vendored
-48
@@ -1,48 +0,0 @@
|
|||||||
#include <reanimated/CSS/common/values/CSSBoolean.h>
|
|
||||||
|
|
||||||
namespace reanimated::css {
|
|
||||||
|
|
||||||
CSSBoolean::CSSBoolean() : value(false) {}
|
|
||||||
|
|
||||||
CSSBoolean::CSSBoolean(bool value) : value(value) {}
|
|
||||||
|
|
||||||
CSSBoolean::CSSBoolean(jsi::Runtime &rt, const jsi::Value &jsiValue)
|
|
||||||
: value(jsiValue.asBool()) {}
|
|
||||||
|
|
||||||
CSSBoolean::CSSBoolean(const folly::dynamic &value) : value(value.asBool()) {}
|
|
||||||
|
|
||||||
bool CSSBoolean::canConstruct(jsi::Runtime &rt, const jsi::Value &jsiValue) {
|
|
||||||
return jsiValue.isBool();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CSSBoolean::canConstruct(const folly::dynamic &value) {
|
|
||||||
return value.isBool();
|
|
||||||
}
|
|
||||||
|
|
||||||
folly::dynamic CSSBoolean::toDynamic() const {
|
|
||||||
return {value};
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string CSSBoolean::toString() const {
|
|
||||||
return value ? "true" : "false";
|
|
||||||
}
|
|
||||||
|
|
||||||
CSSBoolean CSSBoolean::interpolate(double progress, const CSSBoolean &to)
|
|
||||||
const {
|
|
||||||
return CSSBoolean(progress < 0.5 ? value : to.value);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CSSBoolean::operator==(const CSSBoolean &other) const {
|
|
||||||
return value == other.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
|
||||||
|
|
||||||
std::ostream &operator<<(std::ostream &os, const CSSBoolean &boolValue) {
|
|
||||||
os << boolValue.toString();
|
|
||||||
return os;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // NDEBUG
|
|
||||||
|
|
||||||
} // namespace reanimated::css
|
|
||||||
Generated
Vendored
-33
@@ -1,33 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <reanimated/CSS/common/values/CSSValue.h>
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
namespace reanimated::css {
|
|
||||||
|
|
||||||
struct CSSBoolean : public CSSSimpleValue<CSSBoolean> {
|
|
||||||
bool value;
|
|
||||||
|
|
||||||
CSSBoolean();
|
|
||||||
explicit CSSBoolean(bool value);
|
|
||||||
explicit CSSBoolean(jsi::Runtime &rt, const jsi::Value &jsiValue);
|
|
||||||
explicit CSSBoolean(const folly::dynamic &value);
|
|
||||||
|
|
||||||
static bool canConstruct(jsi::Runtime &rt, const jsi::Value &jsiValue);
|
|
||||||
static bool canConstruct(const folly::dynamic &value);
|
|
||||||
|
|
||||||
folly::dynamic toDynamic() const override;
|
|
||||||
std::string toString() const override;
|
|
||||||
CSSBoolean interpolate(double progress, const CSSBoolean &to) const override;
|
|
||||||
|
|
||||||
bool operator==(const CSSBoolean &other) const;
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
|
||||||
friend std::ostream &operator<<(
|
|
||||||
std::ostream &os,
|
|
||||||
const CSSBoolean &boolValue);
|
|
||||||
#endif // NDEBUG
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace reanimated::css
|
|
||||||
Generated
Vendored
-173
@@ -1,173 +0,0 @@
|
|||||||
#include <reanimated/CSS/common/values/CSSColor.h>
|
|
||||||
|
|
||||||
namespace reanimated::css {
|
|
||||||
|
|
||||||
CSSColor::CSSColor()
|
|
||||||
: channels{0, 0, 0, 0}, colorType(ColorType::Transparent) {}
|
|
||||||
|
|
||||||
CSSColor::CSSColor(ColorType colorType)
|
|
||||||
: channels{0, 0, 0, 0}, colorType(colorType) {}
|
|
||||||
|
|
||||||
CSSColor::CSSColor(int64_t numberValue)
|
|
||||||
: channels{0, 0, 0, 0}, colorType(ColorType::Rgba) {
|
|
||||||
uint32_t color;
|
|
||||||
// On Android, colors are represented as signed 32-bit integers. In JS, we use
|
|
||||||
// a bitwise operation (normalizedColor = normalizedColor | 0x0) to ensure the
|
|
||||||
// value is treated as a signed int, causing numbers above 2^31 to become
|
|
||||||
// negative. To correctly interpret these in C++, we cast negative values to
|
|
||||||
// int32_t to preserve their bit pattern, then assign to uint32_t. This wraps
|
|
||||||
// the bits (modulo 2^32), effectively reversing the JS-side bit shift.
|
|
||||||
if (numberValue < 0) {
|
|
||||||
color = static_cast<int32_t>(numberValue);
|
|
||||||
} else {
|
|
||||||
color = static_cast<uint32_t>(numberValue);
|
|
||||||
}
|
|
||||||
channels[0] = (color >> 16) & 0xFF; // Red
|
|
||||||
channels[1] = (color >> 8) & 0xFF; // Green
|
|
||||||
channels[2] = color & 0xFF; // Blue
|
|
||||||
channels[3] = (color >> 24) & 0xFF; // Alpha
|
|
||||||
colorType = ColorType::Rgba;
|
|
||||||
}
|
|
||||||
|
|
||||||
CSSColor::CSSColor(const std::string &colorString)
|
|
||||||
: channels{0, 0, 0, 0}, colorType(ColorType::Transparent) {
|
|
||||||
if (colorString == "transparent") {
|
|
||||||
colorType = ColorType::Transparent;
|
|
||||||
} else if (colorString == "currentColor") {
|
|
||||||
colorType = ColorType::CurrentColor;
|
|
||||||
} else {
|
|
||||||
throw std::invalid_argument(
|
|
||||||
"[Reanimated] CSSColor: Invalid string value: " + colorString);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CSSColor::CSSColor(const uint8_t r, const uint8_t g, const uint8_t b)
|
|
||||||
: channels{r, g, b, 255}, colorType(ColorType::Rgba) {}
|
|
||||||
|
|
||||||
CSSColor::CSSColor(
|
|
||||||
const uint8_t r,
|
|
||||||
const uint8_t g,
|
|
||||||
const uint8_t b,
|
|
||||||
const uint8_t a)
|
|
||||||
: channels{r, g, b, a}, colorType(ColorType::Rgba) {}
|
|
||||||
|
|
||||||
CSSColor::CSSColor(const ColorChannels &colorChannels)
|
|
||||||
: channels{colorChannels[0], colorChannels[1], colorChannels[2], colorChannels[3]},
|
|
||||||
colorType(ColorType::Rgba) {}
|
|
||||||
|
|
||||||
CSSColor::CSSColor(jsi::Runtime &rt, const jsi::Value &jsiValue)
|
|
||||||
: channels{0, 0, 0, 0}, colorType(ColorType::Transparent) {
|
|
||||||
if (jsiValue.isNumber()) {
|
|
||||||
*this = CSSColor(jsiValue.getNumber());
|
|
||||||
} else if (jsiValue.isString()) {
|
|
||||||
*this = CSSColor(jsiValue.getString(rt).utf8(rt));
|
|
||||||
} else if (jsiValue.isUndefined()) {
|
|
||||||
*this = Transparent;
|
|
||||||
} else {
|
|
||||||
throw std::invalid_argument(
|
|
||||||
"[Reanimated] CSSColor: Invalid value: " +
|
|
||||||
stringifyJSIValue(rt, jsiValue));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CSSColor::CSSColor(const folly::dynamic &value)
|
|
||||||
: channels{0, 0, 0, 0}, colorType(ColorType::Transparent) {
|
|
||||||
if (value.isNumber()) {
|
|
||||||
*this = CSSColor(value.asInt());
|
|
||||||
} else if (value.isString()) {
|
|
||||||
*this = CSSColor(value.getString());
|
|
||||||
} else if (value.empty()) {
|
|
||||||
*this = Transparent;
|
|
||||||
} else {
|
|
||||||
throw std::invalid_argument(
|
|
||||||
"[Reanimated] CSSColor: Invalid value: " + folly::toJson(value));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CSSColor::canConstruct(jsi::Runtime &rt, const jsi::Value &jsiValue) {
|
|
||||||
return jsiValue.isNumber() || jsiValue.isUndefined() ||
|
|
||||||
(jsiValue.isString() &&
|
|
||||||
isValidColorString(jsiValue.getString(rt).utf8(rt)));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CSSColor::canConstruct(const folly::dynamic &value) {
|
|
||||||
return value.isNumber() || value.empty() ||
|
|
||||||
(value.isString() && isValidColorString(value.getString()));
|
|
||||||
}
|
|
||||||
|
|
||||||
folly::dynamic CSSColor::toDynamic() const {
|
|
||||||
if (colorType == ColorType::Transparent) {
|
|
||||||
return 0x00000000;
|
|
||||||
}
|
|
||||||
return (channels[3] << 24) | (channels[0] << 16) | (channels[1] << 8) |
|
|
||||||
channels[2];
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string CSSColor::toString() const {
|
|
||||||
if (colorType == ColorType::Rgba) {
|
|
||||||
return "rgba(" + std::to_string(channels[0]) + "," +
|
|
||||||
std::to_string(channels[1]) + "," + std::to_string(channels[2]) + "," +
|
|
||||||
std::to_string(channels[3]) + ")";
|
|
||||||
}
|
|
||||||
if (colorType == ColorType::CurrentColor) {
|
|
||||||
return "currentColor";
|
|
||||||
}
|
|
||||||
return "transparent";
|
|
||||||
}
|
|
||||||
|
|
||||||
CSSColor CSSColor::interpolate(const double progress, const CSSColor &to)
|
|
||||||
const {
|
|
||||||
if ((to.colorType == ColorType::Transparent &&
|
|
||||||
colorType == ColorType::Transparent) ||
|
|
||||||
colorType == ColorType::CurrentColor ||
|
|
||||||
to.colorType == ColorType::CurrentColor) {
|
|
||||||
return progress < 0.5 ? *this : to;
|
|
||||||
}
|
|
||||||
|
|
||||||
ColorChannels fromChannels = channels;
|
|
||||||
ColorChannels toChannels = to.channels;
|
|
||||||
if (colorType == ColorType::Transparent) {
|
|
||||||
fromChannels = {toChannels[0], toChannels[1], toChannels[2], 0};
|
|
||||||
} else if (to.colorType == ColorType::Transparent) {
|
|
||||||
toChannels = {fromChannels[0], fromChannels[1], fromChannels[2], 0};
|
|
||||||
}
|
|
||||||
|
|
||||||
ColorChannels resultChannels;
|
|
||||||
for (size_t i = 0; i < 4; ++i) {
|
|
||||||
resultChannels[i] =
|
|
||||||
interpolateChannel(fromChannels[i], toChannels[i], progress);
|
|
||||||
}
|
|
||||||
|
|
||||||
return CSSColor(resultChannels);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t CSSColor::interpolateChannel(
|
|
||||||
const uint8_t from,
|
|
||||||
const uint8_t to,
|
|
||||||
const double progress) {
|
|
||||||
// Cast one of operands to double to avoid unsigned int subtraction overflow
|
|
||||||
// (when from > to)
|
|
||||||
double interpolated = (static_cast<double>(to) - from) * progress + from;
|
|
||||||
return static_cast<uint8_t>(std::round(std::clamp(interpolated, 0.0, 255.0)));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CSSColor::operator==(const CSSColor &other) const {
|
|
||||||
return colorType == other.colorType && channels[0] == other.channels[0] &&
|
|
||||||
channels[1] == other.channels[1] && channels[2] == other.channels[2] &&
|
|
||||||
channels[3] == other.channels[3];
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
|
||||||
|
|
||||||
std::ostream &operator<<(std::ostream &os, const CSSColor &colorValue) {
|
|
||||||
os << "CSSColor(" << colorValue.toString() << ")";
|
|
||||||
return os;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // NDEBUG
|
|
||||||
|
|
||||||
bool CSSColor::isValidColorString(const std::string &colorString) {
|
|
||||||
return colorString == "transparent" || colorString == "currentColor";
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace reanimated::css
|
|
||||||
Generated
Vendored
-60
@@ -1,60 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <reanimated/CSS/common/definitions.h>
|
|
||||||
#include <reanimated/CSS/common/values/CSSValue.h>
|
|
||||||
|
|
||||||
#include <worklets/Tools/JSISerializer.h>
|
|
||||||
|
|
||||||
#include <folly/json.h>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
namespace reanimated::css {
|
|
||||||
|
|
||||||
using namespace worklets;
|
|
||||||
|
|
||||||
enum class ColorType {
|
|
||||||
Rgba,
|
|
||||||
Transparent,
|
|
||||||
CurrentColor, // for SVG
|
|
||||||
};
|
|
||||||
|
|
||||||
struct CSSColor : public CSSSimpleValue<CSSColor> {
|
|
||||||
ColorChannels channels;
|
|
||||||
ColorType colorType;
|
|
||||||
|
|
||||||
static const CSSColor Transparent;
|
|
||||||
|
|
||||||
CSSColor();
|
|
||||||
explicit CSSColor(ColorType colorType);
|
|
||||||
explicit CSSColor(int64_t numberValue);
|
|
||||||
explicit CSSColor(const std::string &colorString);
|
|
||||||
|
|
||||||
explicit CSSColor(uint8_t r, uint8_t g, uint8_t b);
|
|
||||||
explicit CSSColor(uint8_t r, uint8_t g, uint8_t b, uint8_t a);
|
|
||||||
explicit CSSColor(const ColorChannels &colorChannels);
|
|
||||||
|
|
||||||
explicit CSSColor(jsi::Runtime &rt, const jsi::Value &jsiValue);
|
|
||||||
explicit CSSColor(const folly::dynamic &value);
|
|
||||||
|
|
||||||
static bool canConstruct(jsi::Runtime &rt, const jsi::Value &jsiValue);
|
|
||||||
static bool canConstruct(const folly::dynamic &value);
|
|
||||||
|
|
||||||
folly::dynamic toDynamic() const override;
|
|
||||||
std::string toString() const override;
|
|
||||||
CSSColor interpolate(double progress, const CSSColor &to) const override;
|
|
||||||
|
|
||||||
static uint8_t interpolateChannel(uint8_t from, uint8_t to, double progress);
|
|
||||||
|
|
||||||
bool operator==(const CSSColor &other) const;
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
|
||||||
friend std::ostream &operator<<(std::ostream &os, const CSSColor &colorValue);
|
|
||||||
#endif // NDEBUG
|
|
||||||
|
|
||||||
private:
|
|
||||||
static bool isValidColorString(const std::string &colorString);
|
|
||||||
};
|
|
||||||
|
|
||||||
inline const CSSColor CSSColor::Transparent(ColorType::Transparent);
|
|
||||||
|
|
||||||
} // namespace reanimated::css
|
|
||||||
Generated
Vendored
-120
@@ -1,120 +0,0 @@
|
|||||||
#include <folly/json.h>
|
|
||||||
#include <reanimated/CSS/common/values/CSSDiscreteArray.h>
|
|
||||||
|
|
||||||
namespace reanimated::css {
|
|
||||||
|
|
||||||
template <CSSValueDerived TValue>
|
|
||||||
CSSDiscreteArray<TValue>::CSSDiscreteArray() : values() {}
|
|
||||||
|
|
||||||
template <CSSValueDerived TValue>
|
|
||||||
CSSDiscreteArray<TValue>::CSSDiscreteArray(const std::vector<TValue> &values)
|
|
||||||
: values(values) {}
|
|
||||||
|
|
||||||
template <CSSValueDerived TValue>
|
|
||||||
CSSDiscreteArray<TValue>::CSSDiscreteArray(
|
|
||||||
jsi::Runtime &rt,
|
|
||||||
const jsi::Value &jsiValue) {
|
|
||||||
if (!canConstruct(rt, jsiValue)) {
|
|
||||||
throw std::invalid_argument(
|
|
||||||
"[Reanimated] CSSDiscreteArray: Invalid value type: " +
|
|
||||||
stringifyJSIValue(rt, jsiValue));
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto &array = jsiValue.asObject(rt).asArray(rt);
|
|
||||||
values.reserve(array.size(rt));
|
|
||||||
|
|
||||||
for (size_t i = 0; i < array.size(rt); i++) {
|
|
||||||
values.emplace_back(rt, array.getValueAtIndex(rt, i));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <CSSValueDerived TValue>
|
|
||||||
CSSDiscreteArray<TValue>::CSSDiscreteArray(const folly::dynamic &value) {
|
|
||||||
if (!canConstruct(value)) {
|
|
||||||
throw std::invalid_argument(
|
|
||||||
"[Reanimated] CSSDiscreteArray: Invalid value type: " +
|
|
||||||
folly::toJson(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto &array = value;
|
|
||||||
values.reserve(array.size());
|
|
||||||
|
|
||||||
for (size_t i = 0; i < array.size(); i++) {
|
|
||||||
values.emplace_back(array[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <CSSValueDerived TValue>
|
|
||||||
bool CSSDiscreteArray<TValue>::canConstruct(
|
|
||||||
jsi::Runtime &rt,
|
|
||||||
const jsi::Value &jsiValue) {
|
|
||||||
// TODO - maybe add better validation
|
|
||||||
return jsiValue.isObject() && jsiValue.asObject(rt).isArray(rt);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <CSSValueDerived TValue>
|
|
||||||
bool CSSDiscreteArray<TValue>::canConstruct(const folly::dynamic &value) {
|
|
||||||
return value.isArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <CSSValueDerived TValue>
|
|
||||||
folly::dynamic CSSDiscreteArray<TValue>::toDynamic() const {
|
|
||||||
folly::dynamic array = folly::dynamic::array;
|
|
||||||
for (const auto &value : values) {
|
|
||||||
array.push_back(value.toDynamic());
|
|
||||||
}
|
|
||||||
return array;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <CSSValueDerived TValue>
|
|
||||||
std::string CSSDiscreteArray<TValue>::toString() const {
|
|
||||||
std::stringstream ss;
|
|
||||||
|
|
||||||
ss << "{";
|
|
||||||
for (size_t i = 0; i < values.size(); i++) {
|
|
||||||
ss << values[i].toString();
|
|
||||||
if (i < values.size() - 1) {
|
|
||||||
ss << ", ";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ss << "}";
|
|
||||||
|
|
||||||
return ss.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <CSSValueDerived TValue>
|
|
||||||
CSSDiscreteArray<TValue> CSSDiscreteArray<TValue>::interpolate(
|
|
||||||
double progress,
|
|
||||||
const CSSDiscreteArray<TValue> &other) const {
|
|
||||||
return CSSDiscreteArray<TValue>(progress < 0.5 ? values : other.values);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <CSSValueDerived TValue>
|
|
||||||
bool CSSDiscreteArray<TValue>::operator==(
|
|
||||||
const CSSDiscreteArray<TValue> &other) const {
|
|
||||||
if (values.size() != other.values.size()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
for (size_t i = 0; i < values.size(); i++) {
|
|
||||||
if (values[i] != other.values[i]) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
|
||||||
|
|
||||||
template <CSSValueDerived TValue>
|
|
||||||
std::ostream &operator<<(
|
|
||||||
std::ostream &os,
|
|
||||||
const CSSDiscreteArray<TValue> &arrayValue) {
|
|
||||||
os << "CSSDiscreteArray(" << arrayValue.toString() << ")";
|
|
||||||
return os;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // NDEBUG
|
|
||||||
|
|
||||||
template struct CSSDiscreteArray<CSSKeyword>;
|
|
||||||
|
|
||||||
} // namespace reanimated::css
|
|
||||||
Generated
Vendored
-49
@@ -1,49 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <reanimated/CSS/common/values/CSSKeyword.h>
|
|
||||||
|
|
||||||
#include <worklets/Tools/JSISerializer.h>
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace reanimated::css {
|
|
||||||
|
|
||||||
using namespace worklets;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* CSSDiscreteArray is used for array interpolation when arrays need to be
|
|
||||||
* treated as discrete values. Instead of interpolating between corresponding
|
|
||||||
* elements of two arrays, this type interpolates between entire arrays
|
|
||||||
* treated as single discrete values.
|
|
||||||
*/
|
|
||||||
template <CSSValueDerived TValue>
|
|
||||||
struct CSSDiscreteArray : public CSSSimpleValue<CSSDiscreteArray<TValue>> {
|
|
||||||
static constexpr bool is_discrete_value = true;
|
|
||||||
|
|
||||||
std::vector<TValue> values;
|
|
||||||
|
|
||||||
CSSDiscreteArray();
|
|
||||||
explicit CSSDiscreteArray(const std::vector<TValue> &values);
|
|
||||||
explicit CSSDiscreteArray(jsi::Runtime &rt, const jsi::Value &jsiValue);
|
|
||||||
explicit CSSDiscreteArray(const folly::dynamic &value);
|
|
||||||
|
|
||||||
static bool canConstruct(jsi::Runtime &rt, const jsi::Value &jsiValue);
|
|
||||||
static bool canConstruct(const folly::dynamic &value);
|
|
||||||
|
|
||||||
folly::dynamic toDynamic() const override;
|
|
||||||
std::string toString() const override;
|
|
||||||
CSSDiscreteArray<TValue> interpolate(
|
|
||||||
double progress,
|
|
||||||
const CSSDiscreteArray<TValue> &other) const override;
|
|
||||||
|
|
||||||
bool operator==(const CSSDiscreteArray<TValue> &other) const;
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
|
||||||
friend std::ostream &operator<<(
|
|
||||||
std::ostream &os,
|
|
||||||
const CSSDiscreteArray<TValue> &arrayValue);
|
|
||||||
#endif // NDEBUG
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace reanimated::css
|
|
||||||
Generated
Vendored
-101
@@ -1,101 +0,0 @@
|
|||||||
#include <folly/json.h>
|
|
||||||
#include <reanimated/CSS/common/values/CSSKeyword.h>
|
|
||||||
|
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
namespace reanimated::css {
|
|
||||||
|
|
||||||
template <typename TValue>
|
|
||||||
CSSKeywordBase<TValue>::CSSKeywordBase(const char *value) : value(value) {}
|
|
||||||
|
|
||||||
template <typename TValue>
|
|
||||||
CSSKeywordBase<TValue>::CSSKeywordBase(
|
|
||||||
jsi::Runtime &rt,
|
|
||||||
const jsi::Value &jsiValue) {
|
|
||||||
if (jsiValue.isString()) {
|
|
||||||
value = jsiValue.getString(rt).utf8(rt);
|
|
||||||
} else {
|
|
||||||
throw std::invalid_argument(
|
|
||||||
"[Reanimated] CSSKeywordBase: Invalid value type: " +
|
|
||||||
stringifyJSIValue(rt, jsiValue));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename TValue>
|
|
||||||
CSSKeywordBase<TValue>::CSSKeywordBase(const folly::dynamic &value) {
|
|
||||||
if (value.isString()) {
|
|
||||||
this->value = value.getString();
|
|
||||||
} else {
|
|
||||||
throw std::invalid_argument(
|
|
||||||
"[Reanimated] CSSKeywordBase: Invalid value type: " +
|
|
||||||
folly::toJson(value));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename TValue>
|
|
||||||
bool CSSKeywordBase<TValue>::canConstruct(
|
|
||||||
jsi::Runtime &rt,
|
|
||||||
const jsi::Value &jsiValue) {
|
|
||||||
return jsiValue.isString();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename TValue>
|
|
||||||
bool CSSKeywordBase<TValue>::canConstruct(const folly::dynamic &value) {
|
|
||||||
return value.isString();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename TValue>
|
|
||||||
folly::dynamic CSSKeywordBase<TValue>::toDynamic() const {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename TValue>
|
|
||||||
std::string CSSKeywordBase<TValue>::toString() const {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename TValue>
|
|
||||||
bool CSSKeywordBase<TValue>::operator==(
|
|
||||||
const CSSKeywordBase<TValue> &other) const {
|
|
||||||
return value == other.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
CSSKeyword CSSKeyword::interpolate(double progress, const CSSKeyword &to)
|
|
||||||
const {
|
|
||||||
return CSSKeyword(progress < 0.5 ? value : to.value);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
|
||||||
|
|
||||||
std::ostream &operator<<(std::ostream &os, const CSSKeyword &keywordValue) {
|
|
||||||
os << "CSSKeyword(" << keywordValue.toString() << ")";
|
|
||||||
return os;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // NDEBUG
|
|
||||||
|
|
||||||
CSSDisplay CSSDisplay::interpolate(double progress, const CSSDisplay &to)
|
|
||||||
const {
|
|
||||||
if (value == "none" && progress > 0) {
|
|
||||||
return CSSDisplay(to.value);
|
|
||||||
}
|
|
||||||
if (to.value == "none" && progress < 1) {
|
|
||||||
return CSSDisplay(value);
|
|
||||||
}
|
|
||||||
return CSSDisplay(progress < 0.5 ? value : to.value);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
|
||||||
|
|
||||||
std::ostream &operator<<(std::ostream &os, const CSSDisplay &displayValue) {
|
|
||||||
os << "CSSDisplay(" << displayValue.toString() << ")";
|
|
||||||
return os;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // NDEBUG
|
|
||||||
|
|
||||||
// Explicit template instantiations
|
|
||||||
template class CSSKeywordBase<CSSKeyword>;
|
|
||||||
template class CSSKeywordBase<CSSDisplay>;
|
|
||||||
|
|
||||||
} // namespace reanimated::css
|
|
||||||
Generated
Vendored
-61
@@ -1,61 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <reanimated/CSS/common/values/CSSValue.h>
|
|
||||||
|
|
||||||
#include <worklets/Tools/JSISerializer.h>
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
namespace reanimated::css {
|
|
||||||
|
|
||||||
using namespace worklets;
|
|
||||||
|
|
||||||
template <typename TValue>
|
|
||||||
class CSSKeywordBase : public CSSSimpleValue<TValue> {
|
|
||||||
public:
|
|
||||||
static constexpr bool is_discrete_value = true;
|
|
||||||
|
|
||||||
CSSKeywordBase() = default;
|
|
||||||
explicit CSSKeywordBase(const char *value);
|
|
||||||
explicit CSSKeywordBase(jsi::Runtime &rt, const jsi::Value &jsiValue);
|
|
||||||
explicit CSSKeywordBase(const folly::dynamic &value);
|
|
||||||
|
|
||||||
static bool canConstruct(jsi::Runtime &rt, const jsi::Value &jsiValue);
|
|
||||||
static bool canConstruct(const folly::dynamic &value);
|
|
||||||
|
|
||||||
folly::dynamic toDynamic() const override;
|
|
||||||
std::string toString() const override;
|
|
||||||
|
|
||||||
bool operator==(const CSSKeywordBase &other) const;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
std::string value;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct CSSKeyword : public CSSKeywordBase<CSSKeyword> {
|
|
||||||
using CSSKeywordBase<CSSKeyword>::CSSKeywordBase;
|
|
||||||
using CSSKeywordBase<CSSKeyword>::canConstruct;
|
|
||||||
|
|
||||||
CSSKeyword interpolate(double progress, const CSSKeyword &to) const override;
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
|
||||||
friend std::ostream &operator<<(
|
|
||||||
std::ostream &os,
|
|
||||||
const CSSKeyword &keywordValue);
|
|
||||||
#endif // NDEBUG
|
|
||||||
};
|
|
||||||
|
|
||||||
struct CSSDisplay : public CSSKeywordBase<CSSDisplay> {
|
|
||||||
using CSSKeywordBase<CSSDisplay>::CSSKeywordBase;
|
|
||||||
using CSSKeywordBase<CSSDisplay>::canConstruct;
|
|
||||||
|
|
||||||
CSSDisplay interpolate(double progress, const CSSDisplay &to) const override;
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
|
||||||
friend std::ostream &operator<<(
|
|
||||||
std::ostream &os,
|
|
||||||
const CSSDisplay &displayValue);
|
|
||||||
#endif // NDEBUG
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace reanimated::css
|
|
||||||
Generated
Vendored
-140
@@ -1,140 +0,0 @@
|
|||||||
#include <reanimated/CSS/common/values/CSSLength.h>
|
|
||||||
|
|
||||||
namespace reanimated::css {
|
|
||||||
|
|
||||||
CSSLength::CSSLength() : value(0), isRelative(false) {}
|
|
||||||
|
|
||||||
CSSLength::CSSLength(const double value) : value(value), isRelative(false) {}
|
|
||||||
|
|
||||||
CSSLength::CSSLength(const double value, const bool isRelative)
|
|
||||||
: value(value), isRelative(isRelative) {}
|
|
||||||
|
|
||||||
CSSLength::CSSLength(const char *value) {
|
|
||||||
if (!canConstruct(value)) {
|
|
||||||
throw std::invalid_argument(
|
|
||||||
"[Reanimated] CSSLength: Invalid value: " + std::string(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string str = value;
|
|
||||||
str.pop_back();
|
|
||||||
this->value = std::stod(str) / 100;
|
|
||||||
this->isRelative = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
CSSLength::CSSLength(jsi::Runtime &rt, const jsi::Value &jsiValue) {
|
|
||||||
if (jsiValue.isNumber()) {
|
|
||||||
this->value = jsiValue.asNumber();
|
|
||||||
this->isRelative = false;
|
|
||||||
} else if (jsiValue.isString()) {
|
|
||||||
std::string strValue = jsiValue.asString(rt).utf8(rt);
|
|
||||||
*this = CSSLength(strValue); // Delegate to the string constructor
|
|
||||||
} else {
|
|
||||||
throw std::runtime_error("[Reanimated] CSSLength: Unsupported value type");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CSSLength::CSSLength(const folly::dynamic &value) {
|
|
||||||
if (value.isNumber()) {
|
|
||||||
this->value = value.getDouble();
|
|
||||||
this->isRelative = false;
|
|
||||||
} else if (value.isString()) {
|
|
||||||
std::string strValue = value.getString();
|
|
||||||
*this = CSSLength(strValue.c_str()); // Delegate to the string constructor
|
|
||||||
} else {
|
|
||||||
throw std::runtime_error("[Reanimated] CSSLength: Unsupported value type");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CSSLength::canConstruct(const std::string &value) {
|
|
||||||
return !value.empty() && value.back() == '%';
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CSSLength::canConstruct(const char *value) {
|
|
||||||
return canConstruct(std::string(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CSSLength::canConstruct(jsi::Runtime &rt, const jsi::Value &jsiValue) {
|
|
||||||
return jsiValue.isNumber() ||
|
|
||||||
(jsiValue.isString() && canConstruct(jsiValue.getString(rt).utf8(rt)));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CSSLength::canConstruct(const folly::dynamic &value) {
|
|
||||||
return value.isNumber() ||
|
|
||||||
(value.isString() && canConstruct(value.getString()));
|
|
||||||
}
|
|
||||||
|
|
||||||
folly::dynamic CSSLength::toDynamic() const {
|
|
||||||
if (isRelative) {
|
|
||||||
return std::to_string(value * 100) + "%";
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string CSSLength::toString() const {
|
|
||||||
if (isRelative) {
|
|
||||||
return std::to_string(value * 100) + "%";
|
|
||||||
}
|
|
||||||
return std::to_string(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
CSSLength CSSLength::interpolate(
|
|
||||||
const double progress,
|
|
||||||
const CSSLength &to,
|
|
||||||
const CSSResolvableValueInterpolationContext &context) const {
|
|
||||||
// If both value types are the same, we can interpolate without reading the
|
|
||||||
// relative value from the shadow node
|
|
||||||
// (also, when one of the values is 0, and the other is relative)
|
|
||||||
if ((isRelative == to.isRelative) || (isRelative && to.value == 0) ||
|
|
||||||
(to.isRelative && value == 0)) {
|
|
||||||
return CSSLength(
|
|
||||||
value + (to.value - value) * progress, isRelative || to.isRelative);
|
|
||||||
}
|
|
||||||
// Otherwise, we need to read the relative value from the shadow node and
|
|
||||||
// interpolate values as numbers
|
|
||||||
const auto resolvedFrom = resolve(context);
|
|
||||||
const auto resolvedTo = to.resolve(context);
|
|
||||||
|
|
||||||
if (!resolvedFrom.has_value() || !resolvedTo.has_value()) {
|
|
||||||
return progress < 0.5 ? *this : to;
|
|
||||||
}
|
|
||||||
return CSSLength(
|
|
||||||
resolvedFrom.value() +
|
|
||||||
(resolvedTo.value() - resolvedFrom.value()) * progress);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::optional<double> CSSLength::resolve(
|
|
||||||
const CSSResolvableValueInterpolationContext &context) const {
|
|
||||||
if (!isRelative) {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
jsi::Value relativeValue;
|
|
||||||
if (context.relativeTo == RelativeTo::Self) {
|
|
||||||
relativeValue = context.viewStylesRepository->getNodeProp(
|
|
||||||
context.node, context.relativeProperty);
|
|
||||||
} else {
|
|
||||||
relativeValue = context.viewStylesRepository->getParentNodeProp(
|
|
||||||
context.node, context.relativeProperty);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!relativeValue.isNumber()) {
|
|
||||||
return std::nullopt;
|
|
||||||
}
|
|
||||||
|
|
||||||
return value * relativeValue.getNumber();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CSSLength::operator==(const CSSLength &other) const {
|
|
||||||
return value == other.value && isRelative == other.isRelative;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
|
||||||
|
|
||||||
std::ostream &operator<<(std::ostream &os, const CSSLength &value) {
|
|
||||||
os << "CSSLength(" << value.toString() << ")";
|
|
||||||
return os;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // NDEBUG
|
|
||||||
|
|
||||||
} // namespace reanimated::css
|
|
||||||
Generated
Vendored
-41
@@ -1,41 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <reanimated/CSS/common/values/CSSValue.h>
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
namespace reanimated::css {
|
|
||||||
|
|
||||||
struct CSSLength : public CSSResolvableValue<CSSLength, double> {
|
|
||||||
double value;
|
|
||||||
bool isRelative;
|
|
||||||
|
|
||||||
CSSLength();
|
|
||||||
explicit CSSLength(double value);
|
|
||||||
explicit CSSLength(double value, bool isRelative);
|
|
||||||
explicit CSSLength(const char *value);
|
|
||||||
explicit CSSLength(jsi::Runtime &rt, const jsi::Value &jsiValue);
|
|
||||||
explicit CSSLength(const folly::dynamic &value);
|
|
||||||
|
|
||||||
static bool canConstruct(const std::string &value);
|
|
||||||
static bool canConstruct(const char *value);
|
|
||||||
static bool canConstruct(jsi::Runtime &rt, const jsi::Value &jsiValue);
|
|
||||||
static bool canConstruct(const folly::dynamic &value);
|
|
||||||
|
|
||||||
folly::dynamic toDynamic() const override;
|
|
||||||
std::string toString() const override;
|
|
||||||
CSSLength interpolate(
|
|
||||||
double progress,
|
|
||||||
const CSSLength &to,
|
|
||||||
const CSSResolvableValueInterpolationContext &context) const override;
|
|
||||||
std::optional<double> resolve(
|
|
||||||
const CSSResolvableValueInterpolationContext &context) const override;
|
|
||||||
|
|
||||||
bool operator==(const CSSLength &other) const;
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
|
||||||
friend std::ostream &operator<<(std::ostream &os, const CSSLength &dimension);
|
|
||||||
#endif // NDEBUG
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace reanimated::css
|
|
||||||
Generated
Vendored
-107
@@ -1,107 +0,0 @@
|
|||||||
#include <folly/json.h>
|
|
||||||
#include <reanimated/CSS/common/values/CSSNumber.h>
|
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
namespace reanimated::css {
|
|
||||||
|
|
||||||
template <typename TDerived, typename TValue>
|
|
||||||
CSSNumberBase<TDerived, TValue>::CSSNumberBase() : value(0) {}
|
|
||||||
|
|
||||||
template <typename TDerived, typename TValue>
|
|
||||||
CSSNumberBase<TDerived, TValue>::CSSNumberBase(TValue value) : value(value) {}
|
|
||||||
|
|
||||||
template <typename TDerived, typename TValue>
|
|
||||||
CSSNumberBase<TDerived, TValue>::CSSNumberBase(
|
|
||||||
jsi::Runtime &rt,
|
|
||||||
const jsi::Value &jsiValue) {
|
|
||||||
if (jsiValue.isNumber()) {
|
|
||||||
value = static_cast<TValue>(jsiValue.asNumber());
|
|
||||||
} else {
|
|
||||||
throw std::invalid_argument(
|
|
||||||
"[Reanimated] CSSNumberBase: Invalid value type: " +
|
|
||||||
stringifyJSIValue(rt, jsiValue));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename TDerived, typename TValue>
|
|
||||||
CSSNumberBase<TDerived, TValue>::CSSNumberBase(const folly::dynamic &value) {
|
|
||||||
if (value.isInt() || value.isDouble()) {
|
|
||||||
this->value = static_cast<TValue>(value.getDouble());
|
|
||||||
} else {
|
|
||||||
throw std::invalid_argument(
|
|
||||||
"[Reanimated] CSSNumberBase: Invalid value type: " +
|
|
||||||
folly::toJson(value));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename TDerived, typename TValue>
|
|
||||||
bool CSSNumberBase<TDerived, TValue>::canConstruct(
|
|
||||||
jsi::Runtime &rt,
|
|
||||||
const jsi::Value &jsiValue) {
|
|
||||||
return jsiValue.isNumber();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename TDerived, typename TValue>
|
|
||||||
bool CSSNumberBase<TDerived, TValue>::canConstruct(
|
|
||||||
const folly::dynamic &value) {
|
|
||||||
return value.isInt() || value.isDouble();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename TDerived, typename TValue>
|
|
||||||
folly::dynamic CSSNumberBase<TDerived, TValue>::toDynamic() const {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename TDerived, typename TValue>
|
|
||||||
std::string CSSNumberBase<TDerived, TValue>::toString() const {
|
|
||||||
return std::to_string(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename TDerived, typename TValue>
|
|
||||||
TDerived CSSNumberBase<TDerived, TValue>::interpolate(
|
|
||||||
double progress,
|
|
||||||
const TDerived &other) const {
|
|
||||||
return TDerived(value + progress * (other.value - value));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename TDerived, typename TValue>
|
|
||||||
bool CSSNumberBase<TDerived, TValue>::operator==(
|
|
||||||
const CSSNumberBase<TDerived, TValue> &other) const {
|
|
||||||
return value == other.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
CSSInteger CSSInteger::interpolate(double progress, const CSSInteger &other)
|
|
||||||
const {
|
|
||||||
return CSSInteger(
|
|
||||||
static_cast<int>(std::round(value + progress * (other.value - value))));
|
|
||||||
}
|
|
||||||
|
|
||||||
template struct CSSNumberBase<CSSDouble, double>;
|
|
||||||
template struct CSSNumberBase<CSSInteger, int>;
|
|
||||||
|
|
||||||
#ifdef ANDROID
|
|
||||||
|
|
||||||
CSSShadowRadiusAndroid::CSSShadowRadiusAndroid()
|
|
||||||
: CSSNumberBase<CSSShadowRadiusAndroid, double>(1.0) {}
|
|
||||||
|
|
||||||
CSSShadowRadiusAndroid::CSSShadowRadiusAndroid(const double value)
|
|
||||||
: CSSNumberBase<CSSShadowRadiusAndroid, double>(std::max(1.0, value)) {}
|
|
||||||
|
|
||||||
CSSShadowRadiusAndroid::CSSShadowRadiusAndroid(
|
|
||||||
jsi::Runtime &rt,
|
|
||||||
const jsi::Value &jsiValue)
|
|
||||||
: CSSNumberBase<CSSShadowRadiusAndroid, double>(rt, jsiValue) {
|
|
||||||
value = std::max(1.0, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
CSSShadowRadiusAndroid::CSSShadowRadiusAndroid(const folly::dynamic &value)
|
|
||||||
: CSSNumberBase<CSSShadowRadiusAndroid, double>(value) {
|
|
||||||
this->value = std::max(1.0, value.getDouble());
|
|
||||||
}
|
|
||||||
|
|
||||||
template struct CSSNumberBase<CSSShadowRadiusAndroid, double>;
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
} // namespace reanimated::css
|
|
||||||
Generated
Vendored
-71
@@ -1,71 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <reanimated/CSS/common/values/CSSValue.h>
|
|
||||||
|
|
||||||
#include <worklets/Tools/JSISerializer.h>
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
namespace reanimated::css {
|
|
||||||
|
|
||||||
using namespace worklets;
|
|
||||||
|
|
||||||
template <typename TDerived, typename TValue>
|
|
||||||
struct CSSNumberBase : public CSSSimpleValue<TDerived> {
|
|
||||||
TValue value;
|
|
||||||
|
|
||||||
CSSNumberBase();
|
|
||||||
explicit CSSNumberBase(TValue value);
|
|
||||||
explicit CSSNumberBase(jsi::Runtime &rt, const jsi::Value &jsiValue);
|
|
||||||
explicit CSSNumberBase(const folly::dynamic &value);
|
|
||||||
|
|
||||||
static bool canConstruct(jsi::Runtime &rt, const jsi::Value &jsiValue);
|
|
||||||
static bool canConstruct(const folly::dynamic &value);
|
|
||||||
|
|
||||||
folly::dynamic toDynamic() const override;
|
|
||||||
std::string toString() const override;
|
|
||||||
TDerived interpolate(double progress, const TDerived &other) const override;
|
|
||||||
|
|
||||||
bool operator==(const CSSNumberBase<TDerived, TValue> &other) const;
|
|
||||||
};
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
|
||||||
|
|
||||||
template <typename TDerived, typename TValue>
|
|
||||||
std::ostream &operator<<(
|
|
||||||
std::ostream &os,
|
|
||||||
const CSSNumberBase<TDerived, TValue> &numberValue) {
|
|
||||||
os << "CSSNumberBase(" << numberValue.toString() << ")";
|
|
||||||
return os;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // NDEBUG
|
|
||||||
|
|
||||||
struct CSSDouble : public CSSNumberBase<CSSDouble, double> {
|
|
||||||
// Inherit all constructors from the base class
|
|
||||||
using CSSNumberBase::CSSNumberBase;
|
|
||||||
};
|
|
||||||
struct CSSInteger : public CSSNumberBase<CSSInteger, int> {
|
|
||||||
// Inherit all constructors from the base class
|
|
||||||
using CSSNumberBase::CSSNumberBase;
|
|
||||||
|
|
||||||
CSSInteger interpolate(double progress, const CSSInteger &other)
|
|
||||||
const override;
|
|
||||||
};
|
|
||||||
|
|
||||||
#ifdef ANDROID
|
|
||||||
|
|
||||||
// For some reason Android crashes when blurRadius is smaller than 1 so we use a
|
|
||||||
// custom value that will never be smaller than 1
|
|
||||||
|
|
||||||
struct CSSShadowRadiusAndroid
|
|
||||||
: public CSSNumberBase<CSSShadowRadiusAndroid, double> {
|
|
||||||
CSSShadowRadiusAndroid();
|
|
||||||
explicit CSSShadowRadiusAndroid(double value);
|
|
||||||
explicit CSSShadowRadiusAndroid(jsi::Runtime &rt, const jsi::Value &jsiValue);
|
|
||||||
explicit CSSShadowRadiusAndroid(const folly::dynamic &value);
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
} // namespace reanimated::css
|
|
||||||
Generated
Vendored
-79
@@ -1,79 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <reanimated/CSS/misc/ViewStylesRepository.h>
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <string>
|
|
||||||
#include <type_traits>
|
|
||||||
|
|
||||||
namespace reanimated::css {
|
|
||||||
|
|
||||||
using namespace facebook;
|
|
||||||
|
|
||||||
struct ValueInterpolatorUpdateContext {
|
|
||||||
const std::shared_ptr<const ShadowNode> &node;
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class RelativeTo {
|
|
||||||
Parent,
|
|
||||||
Self,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct CSSResolvableValueInterpolationContext {
|
|
||||||
const std::shared_ptr<const ShadowNode> &node;
|
|
||||||
const std::shared_ptr<ViewStylesRepository> &viewStylesRepository;
|
|
||||||
const std::string &relativeProperty;
|
|
||||||
const RelativeTo relativeTo;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct CSSValue {
|
|
||||||
// This field should be overridden in discrete value types
|
|
||||||
static constexpr bool is_discrete_value = false;
|
|
||||||
|
|
||||||
virtual ~CSSValue() = default;
|
|
||||||
|
|
||||||
virtual folly::dynamic toDynamic() const = 0;
|
|
||||||
virtual std::string toString() const = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Base for leaf values that can be interpolated without resolution
|
|
||||||
template <typename TDerived>
|
|
||||||
struct CSSSimpleValue : public CSSValue {
|
|
||||||
static constexpr bool is_resolvable_value = false;
|
|
||||||
|
|
||||||
virtual TDerived interpolate(double progress, const TDerived &to) const = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Base for leaf values that need resolution before interpolation
|
|
||||||
template <typename TDerived, typename TResolved = TDerived>
|
|
||||||
struct CSSResolvableValue : public CSSValue {
|
|
||||||
static constexpr bool is_resolvable_value = true;
|
|
||||||
|
|
||||||
virtual TDerived interpolate(
|
|
||||||
double progress,
|
|
||||||
const TDerived &to,
|
|
||||||
const CSSResolvableValueInterpolationContext &context) const = 0;
|
|
||||||
virtual std::optional<TResolved> resolve(
|
|
||||||
const CSSResolvableValueInterpolationContext &context) const = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Checks if a type is a resolvable value that needs resolution before
|
|
||||||
// interpolation
|
|
||||||
template <typename TCSSValue>
|
|
||||||
concept Resolvable = requires {
|
|
||||||
{ TCSSValue::is_resolvable_value } -> std::convertible_to<bool>;
|
|
||||||
requires TCSSValue::is_resolvable_value == true;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Checks if a type is a discrete value
|
|
||||||
template <typename TCSSValue>
|
|
||||||
concept Discrete = requires {
|
|
||||||
{ TCSSValue::is_discrete_value } -> std::convertible_to<bool>;
|
|
||||||
requires TCSSValue::is_discrete_value == true;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Check if a type is derived from CSSValue
|
|
||||||
template <typename TCSSValue>
|
|
||||||
concept CSSValueDerived = std::is_base_of_v<CSSValue, TCSSValue>;
|
|
||||||
|
|
||||||
} // namespace reanimated::css
|
|
||||||
Generated
Vendored
-179
@@ -1,179 +0,0 @@
|
|||||||
#include <reanimated/CSS/common/values/CSSAngle.h>
|
|
||||||
#include <reanimated/CSS/common/values/CSSBoolean.h>
|
|
||||||
#include <reanimated/CSS/common/values/CSSColor.h>
|
|
||||||
#include <reanimated/CSS/common/values/CSSDiscreteArray.h>
|
|
||||||
#include <reanimated/CSS/common/values/CSSKeyword.h>
|
|
||||||
#include <reanimated/CSS/common/values/CSSLength.h>
|
|
||||||
#include <reanimated/CSS/common/values/CSSNumber.h>
|
|
||||||
#include <reanimated/CSS/common/values/CSSValueVariant.h>
|
|
||||||
#include <reanimated/CSS/svg/values/SVGLength.h>
|
|
||||||
#include <reanimated/CSS/svg/values/SVGStrokeDashArray.h>
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace reanimated::css {
|
|
||||||
|
|
||||||
template <typename... AllowedTypes>
|
|
||||||
CSSValueVariant<AllowedTypes...>::CSSValueVariant(
|
|
||||||
std::variant<AllowedTypes...> &&storage)
|
|
||||||
: storage_(std::move(storage)) {}
|
|
||||||
|
|
||||||
template <typename... AllowedTypes>
|
|
||||||
CSSValueVariant<AllowedTypes...>::CSSValueVariant(
|
|
||||||
jsi::Runtime &rt,
|
|
||||||
const jsi::Value &jsiValue) {
|
|
||||||
auto tryOne = [&]<typename TCSSValue>() -> bool {
|
|
||||||
// We have to check in a runtime if the type can be constructed from the
|
|
||||||
// provided jsi::Value. The first match will be used to construct the
|
|
||||||
// CSS value.
|
|
||||||
if (!TCSSValue::canConstruct(rt, jsiValue)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
storage_ = TCSSValue(rt, jsiValue);
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Try constructing with each allowed type until one succeeds
|
|
||||||
if (!(tryOne.template operator()<AllowedTypes>() || ...)) {
|
|
||||||
throw std::runtime_error(
|
|
||||||
"[Reanimated] No compatible type found for construction from: " +
|
|
||||||
stringifyJSIValue(rt, jsiValue));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename... AllowedTypes>
|
|
||||||
CSSValueVariant<AllowedTypes...>::CSSValueVariant(const folly::dynamic &value) {
|
|
||||||
auto tryOne = [&]<typename TCSSValue>() -> bool {
|
|
||||||
// We have to check in a runtime if the type can be constructed from the
|
|
||||||
// provided folly::dynamic. The first match will be used to construct the
|
|
||||||
// CSS value.
|
|
||||||
if (!TCSSValue::canConstruct(value)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
storage_ = TCSSValue(value);
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Try constructing with each allowed type until one succeeds
|
|
||||||
if (!(tryOne.template operator()<AllowedTypes>() || ...)) {
|
|
||||||
throw std::runtime_error(
|
|
||||||
"[Reanimated] No compatible type found for construction from: " +
|
|
||||||
folly::toJson(value));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename... AllowedTypes>
|
|
||||||
bool CSSValueVariant<AllowedTypes...>::operator==(
|
|
||||||
const CSSValueVariant &other) const {
|
|
||||||
if (storage_.index() != other.storage_.index()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return std::visit(
|
|
||||||
[](const auto &lhs, const auto &rhs) {
|
|
||||||
REA_IF_SAME_TYPE(lhs, rhs) {
|
|
||||||
return lhs == rhs;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
storage_,
|
|
||||||
other.storage_);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename... AllowedTypes>
|
|
||||||
bool CSSValueVariant<AllowedTypes...>::operator==(const CSSValue &other) const {
|
|
||||||
if (auto *o = dynamic_cast<const CSSValueVariant *>(&other)) {
|
|
||||||
return *this == *o;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename... AllowedTypes>
|
|
||||||
folly::dynamic CSSValueVariant<AllowedTypes...>::toDynamic() const {
|
|
||||||
return std::visit([](const auto &v) { return v.toDynamic(); }, storage_);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename... AllowedTypes>
|
|
||||||
std::string CSSValueVariant<AllowedTypes...>::toString() const {
|
|
||||||
return std::visit([](const auto &v) { return v.toString(); }, storage_);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename... AllowedTypes>
|
|
||||||
CSSValueVariant<AllowedTypes...> CSSValueVariant<AllowedTypes...>::interpolate(
|
|
||||||
const double progress,
|
|
||||||
const CSSValueVariant &to,
|
|
||||||
const ValueInterpolatorUpdateContext &context) const {
|
|
||||||
if (storage_.index() != to.storage_.index()) {
|
|
||||||
return fallbackInterpolate(progress, to);
|
|
||||||
}
|
|
||||||
|
|
||||||
return std::visit(
|
|
||||||
[&](const auto &fromValue, const auto &toValue) -> CSSValueVariant {
|
|
||||||
REA_IF_SAME_TYPE(fromValue, toValue) {
|
|
||||||
if constexpr (Resolvable<L>) {
|
|
||||||
throw std::runtime_error(
|
|
||||||
"[Reanimated] Resolvable value cannot be interpolated as non-resolvable");
|
|
||||||
} else {
|
|
||||||
return CSSValueVariant(fromValue.interpolate(progress, toValue));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return fallbackInterpolate(progress, to);
|
|
||||||
},
|
|
||||||
storage_,
|
|
||||||
to.storage_);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename... AllowedTypes>
|
|
||||||
CSSValueVariant<AllowedTypes...> CSSValueVariant<AllowedTypes...>::interpolate(
|
|
||||||
const double progress,
|
|
||||||
const CSSValueVariant &to,
|
|
||||||
const CSSResolvableValueInterpolationContext &context) const {
|
|
||||||
if (storage_.index() != to.storage_.index()) {
|
|
||||||
return fallbackInterpolate(progress, to);
|
|
||||||
}
|
|
||||||
|
|
||||||
return std::visit(
|
|
||||||
[&](const auto &fromValue, const auto &toValue) -> CSSValueVariant {
|
|
||||||
REA_IF_SAME_TYPE(fromValue, toValue) {
|
|
||||||
if constexpr (Resolvable<L>) {
|
|
||||||
return CSSValueVariant(
|
|
||||||
fromValue.interpolate(progress, toValue, context));
|
|
||||||
} else {
|
|
||||||
throw std::runtime_error(
|
|
||||||
"[Reanimated] Non-resolvable value cannot be interpolated as resolvable");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return fallbackInterpolate(progress, to);
|
|
||||||
},
|
|
||||||
storage_,
|
|
||||||
to.storage_);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename... AllowedTypes>
|
|
||||||
CSSValueVariant<AllowedTypes...>
|
|
||||||
CSSValueVariant<AllowedTypes...>::fallbackInterpolate(
|
|
||||||
const double progress,
|
|
||||||
const CSSValueVariant &to) const {
|
|
||||||
return progress < 0.5 ? *this : to;
|
|
||||||
}
|
|
||||||
|
|
||||||
template class CSSValueVariant<CSSLength>;
|
|
||||||
template class CSSValueVariant<CSSLength, CSSKeyword>;
|
|
||||||
template class CSSValueVariant<CSSDouble>;
|
|
||||||
template class CSSValueVariant<CSSDouble, CSSKeyword>;
|
|
||||||
template class CSSValueVariant<CSSInteger>;
|
|
||||||
template class CSSValueVariant<CSSKeyword>;
|
|
||||||
template class CSSValueVariant<CSSAngle>;
|
|
||||||
template class CSSValueVariant<CSSBoolean>;
|
|
||||||
template class CSSValueVariant<CSSColor>;
|
|
||||||
template class CSSValueVariant<CSSDisplay>;
|
|
||||||
template class CSSValueVariant<CSSDiscreteArray<CSSKeyword>>;
|
|
||||||
#ifdef ANDROID
|
|
||||||
template class CSSValueVariant<CSSShadowRadiusAndroid>;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
template class CSSValueVariant<SVGLength>;
|
|
||||||
template class CSSValueVariant<SVGLength, CSSKeyword>;
|
|
||||||
template class CSSValueVariant<SVGStrokeDashArray, CSSKeyword>;
|
|
||||||
|
|
||||||
} // namespace reanimated::css
|
|
||||||
Generated
Vendored
-123
@@ -1,123 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <reanimated/CSS/common/values/CSSValue.h>
|
|
||||||
#include <worklets/Tools/JSISerializer.h>
|
|
||||||
|
|
||||||
#include <folly/json.h>
|
|
||||||
|
|
||||||
#include <stdexcept>
|
|
||||||
#include <string>
|
|
||||||
#include <type_traits>
|
|
||||||
#include <utility>
|
|
||||||
#include <variant>
|
|
||||||
|
|
||||||
namespace reanimated::css {
|
|
||||||
|
|
||||||
using namespace worklets;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Macro to check if two lambda parameters have the same reference-removed type.
|
|
||||||
*
|
|
||||||
* Usage:
|
|
||||||
* REA_IF_SAME_TYPE(lhs, rhs) {
|
|
||||||
* // same-type block
|
|
||||||
* } else {
|
|
||||||
* // mismatch block
|
|
||||||
* }
|
|
||||||
*/
|
|
||||||
#define REA_IF_SAME_TYPE(lhs, rhs) \
|
|
||||||
using L = std::remove_reference_t<decltype(lhs)>; \
|
|
||||||
using R = std::remove_reference_t<decltype(rhs)>; \
|
|
||||||
if constexpr (std::is_same_v<L, R>) // NOLINT(readability/braces)
|
|
||||||
|
|
||||||
// Checks whether a type has canConstruct(...) for a generic value
|
|
||||||
template <typename TCSSValue, typename TValue>
|
|
||||||
concept ValueConstructibleCSSValue = requires(TValue &&value) {
|
|
||||||
{
|
|
||||||
TCSSValue::canConstruct(std::forward<TValue>(value))
|
|
||||||
} -> std::same_as<bool>;
|
|
||||||
}; // NOLINT(readability/braces)
|
|
||||||
|
|
||||||
// Checks whether a type can be constructed from a jsi::Value
|
|
||||||
template <typename TCSSValue>
|
|
||||||
concept JSIConstructibleCSSValue =
|
|
||||||
requires(jsi::Runtime &rt, const jsi::Value &value) {
|
|
||||||
{ TCSSValue::canConstruct(rt, value) } -> std::same_as<bool>;
|
|
||||||
{ TCSSValue(rt, value) } -> std::same_as<TCSSValue>;
|
|
||||||
}; // NOLINT(readability/braces)
|
|
||||||
|
|
||||||
// Checks whether a type can be constructed from a folly::dynamic
|
|
||||||
template <typename TCSSValue>
|
|
||||||
concept DynamicConstructibleCSSValue = requires(const folly::dynamic &value) {
|
|
||||||
{ TCSSValue::canConstruct(value) } -> std::same_as<bool>;
|
|
||||||
{ TCSSValue(value) } -> std::same_as<TCSSValue>;
|
|
||||||
}; // NOLINT(readability/braces)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* CSSValueVariant
|
|
||||||
*
|
|
||||||
* A std::variant-based container for multiple CSSValue-derived types.
|
|
||||||
*/
|
|
||||||
template <typename... AllowedTypes>
|
|
||||||
class CSSValueVariant final : public CSSValue {
|
|
||||||
static_assert(
|
|
||||||
(CSSValueDerived<AllowedTypes> && ...),
|
|
||||||
"CSSValueVariant accepts only CSSValue-derived types");
|
|
||||||
static_assert(
|
|
||||||
(JSIConstructibleCSSValue<AllowedTypes> && ...),
|
|
||||||
"CSSValueVariant accepts only types that can be constructed from a jsi::Value");
|
|
||||||
static_assert(
|
|
||||||
(DynamicConstructibleCSSValue<AllowedTypes> && ...),
|
|
||||||
"CSSValueVariant accepts only types that can be constructed from a folly::dynamic");
|
|
||||||
|
|
||||||
public:
|
|
||||||
CSSValueVariant() = default;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Construct from std::variant storage directly
|
|
||||||
*/
|
|
||||||
explicit CSSValueVariant(std::variant<AllowedTypes...> &&storage);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Construct from jsi::Value if it matches any AllowedType's constructor
|
|
||||||
* (chooses the first one that matches)
|
|
||||||
*/
|
|
||||||
explicit CSSValueVariant(jsi::Runtime &rt, const jsi::Value &jsiValue);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Construct from folly::dynamic if it matches any AllowedType's constructor
|
|
||||||
* (chooses the first one that matches)
|
|
||||||
*/
|
|
||||||
explicit CSSValueVariant(const folly::dynamic &value);
|
|
||||||
|
|
||||||
bool operator==(const CSSValueVariant &other) const;
|
|
||||||
bool operator==(const CSSValue &other) const;
|
|
||||||
|
|
||||||
folly::dynamic toDynamic() const override;
|
|
||||||
std::string toString() const override;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Interpolate (non-resolvable)
|
|
||||||
*/
|
|
||||||
CSSValueVariant interpolate(
|
|
||||||
const double progress,
|
|
||||||
const CSSValueVariant &to,
|
|
||||||
const ValueInterpolatorUpdateContext &context) const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Interpolate (resolvable)
|
|
||||||
*/
|
|
||||||
CSSValueVariant interpolate(
|
|
||||||
const double progress,
|
|
||||||
const CSSValueVariant &to,
|
|
||||||
const CSSResolvableValueInterpolationContext &context) const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::variant<AllowedTypes...> storage_;
|
|
||||||
|
|
||||||
CSSValueVariant fallbackInterpolate(
|
|
||||||
const double progress,
|
|
||||||
const CSSValueVariant &to) const;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace reanimated::css
|
|
||||||
Generated
Vendored
-196
@@ -1,196 +0,0 @@
|
|||||||
#include <reanimated/CSS/configs/CSSAnimationConfig.h>
|
|
||||||
|
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
namespace reanimated::css {
|
|
||||||
|
|
||||||
double getIterationCount(jsi::Runtime &rt, const jsi::Object &settings) {
|
|
||||||
return settings.getProperty(rt, "iterationCount").asNumber();
|
|
||||||
}
|
|
||||||
|
|
||||||
AnimationDirection getDirection(jsi::Runtime &rt, const jsi::Object &settings) {
|
|
||||||
static const std::unordered_map<std::string, AnimationDirection>
|
|
||||||
strToEnumMap = {
|
|
||||||
{"normal", AnimationDirection::Normal},
|
|
||||||
{"reverse", AnimationDirection::Reverse},
|
|
||||||
{"alternate", AnimationDirection::Alternate},
|
|
||||||
{"alternate-reverse", AnimationDirection::AlternateReverse}};
|
|
||||||
|
|
||||||
const auto str = settings.getProperty(rt, "direction").asString(rt).utf8(rt);
|
|
||||||
auto it = strToEnumMap.find(str);
|
|
||||||
if (it == strToEnumMap.cend()) {
|
|
||||||
throw std::invalid_argument(
|
|
||||||
"[Reanimated] Invalid animationDirection: " + str);
|
|
||||||
}
|
|
||||||
return it->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
AnimationFillMode getFillMode(jsi::Runtime &rt, const jsi::Object &settings) {
|
|
||||||
static const std::unordered_map<std::string, AnimationFillMode> strToEnumMap =
|
|
||||||
{{"none", AnimationFillMode::None},
|
|
||||||
{"forwards", AnimationFillMode::Forwards},
|
|
||||||
{"backwards", AnimationFillMode::Backwards},
|
|
||||||
{"both", AnimationFillMode::Both}};
|
|
||||||
|
|
||||||
const auto str = settings.getProperty(rt, "fillMode").asString(rt).utf8(rt);
|
|
||||||
auto it = strToEnumMap.find(str);
|
|
||||||
if (it == strToEnumMap.cend()) {
|
|
||||||
throw std::invalid_argument(
|
|
||||||
"[Reanimated] Invalid animationFillMode: " + str);
|
|
||||||
}
|
|
||||||
return it->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
AnimationPlayState getPlayState(jsi::Runtime &rt, const jsi::Object &settings) {
|
|
||||||
static const std::unordered_map<std::string, AnimationPlayState>
|
|
||||||
strToEnumMap = {
|
|
||||||
{"running", AnimationPlayState::Running},
|
|
||||||
{"paused", AnimationPlayState::Paused}};
|
|
||||||
|
|
||||||
const auto str = settings.getProperty(rt, "playState").asString(rt).utf8(rt);
|
|
||||||
auto it = strToEnumMap.find(str);
|
|
||||||
if (it == strToEnumMap.cend()) {
|
|
||||||
throw std::invalid_argument(
|
|
||||||
"[Reanimated] Invalid animationPlayState: " + str);
|
|
||||||
}
|
|
||||||
return it->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
CSSAnimationSettings parseCSSAnimationSettings(
|
|
||||||
jsi::Runtime &rt,
|
|
||||||
const jsi::Value &settings) {
|
|
||||||
const auto &settingsObj = settings.asObject(rt);
|
|
||||||
|
|
||||||
return {
|
|
||||||
getDuration(rt, settingsObj),
|
|
||||||
getTimingFunction(rt, settingsObj),
|
|
||||||
getDelay(rt, settingsObj),
|
|
||||||
getIterationCount(rt, settingsObj),
|
|
||||||
getDirection(rt, settingsObj),
|
|
||||||
getFillMode(rt, settingsObj),
|
|
||||||
getPlayState(rt, settingsObj)};
|
|
||||||
}
|
|
||||||
|
|
||||||
PartialCSSAnimationSettings parsePartialCSSAnimationSettings(
|
|
||||||
jsi::Runtime &rt,
|
|
||||||
const jsi::Value &partialSettings) {
|
|
||||||
const auto &partialObj = partialSettings.asObject(rt);
|
|
||||||
|
|
||||||
PartialCSSAnimationSettings result;
|
|
||||||
|
|
||||||
if (partialObj.hasProperty(rt, "duration")) {
|
|
||||||
result.duration = getDuration(rt, partialObj);
|
|
||||||
}
|
|
||||||
if (partialObj.hasProperty(rt, "timingFunction")) {
|
|
||||||
result.easingFunction = getTimingFunction(rt, partialObj);
|
|
||||||
}
|
|
||||||
if (partialObj.hasProperty(rt, "delay")) {
|
|
||||||
result.delay = getDelay(rt, partialObj);
|
|
||||||
}
|
|
||||||
if (partialObj.hasProperty(rt, "iterationCount")) {
|
|
||||||
result.iterationCount = getIterationCount(rt, partialObj);
|
|
||||||
}
|
|
||||||
if (partialObj.hasProperty(rt, "direction")) {
|
|
||||||
result.direction = getDirection(rt, partialObj);
|
|
||||||
}
|
|
||||||
if (partialObj.hasProperty(rt, "fillMode")) {
|
|
||||||
result.fillMode = getFillMode(rt, partialObj);
|
|
||||||
}
|
|
||||||
if (partialObj.hasProperty(rt, "playState")) {
|
|
||||||
result.playState = getPlayState(rt, partialObj);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<std::string> parseAnimationNames(
|
|
||||||
jsi::Runtime &rt,
|
|
||||||
const jsi::Value &animationNames) {
|
|
||||||
std::vector<std::string> result;
|
|
||||||
|
|
||||||
const auto &namesArray = animationNames.asObject(rt).asArray(rt);
|
|
||||||
const auto animationNamesCount = namesArray.size(rt);
|
|
||||||
result.reserve(animationNamesCount);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < animationNamesCount; i++) {
|
|
||||||
result.emplace_back(
|
|
||||||
namesArray.getValueAtIndex(rt, i).asString(rt).utf8(rt));
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename TResult>
|
|
||||||
std::unordered_map<size_t, TResult> parseHelper(
|
|
||||||
jsi::Runtime &rt,
|
|
||||||
const jsi::Object &settingsObj,
|
|
||||||
std::function<TResult(jsi::Runtime &, const jsi::Value &)> parseFunction) {
|
|
||||||
std::unordered_map<size_t, TResult> result;
|
|
||||||
|
|
||||||
const auto animationIndices = settingsObj.getPropertyNames(rt);
|
|
||||||
const auto animationIndicesCount = animationIndices.size(rt);
|
|
||||||
result.reserve(animationIndicesCount);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < animationIndicesCount; i++) {
|
|
||||||
const auto &indexStr = animationIndices.getValueAtIndex(rt, i).toString(rt);
|
|
||||||
const auto &animationSettings = settingsObj.getProperty(rt, indexStr);
|
|
||||||
|
|
||||||
const auto index = std::stoul(indexStr.utf8(rt));
|
|
||||||
result[index] = parseFunction(rt, animationSettings);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
CSSAnimationSettingsMap parseNewAnimationSettings(
|
|
||||||
jsi::Runtime &rt,
|
|
||||||
const std::vector<std::string> &animationNames,
|
|
||||||
const jsi::Value &newSettings) {
|
|
||||||
return parseHelper<CSSAnimationSettings>(
|
|
||||||
rt,
|
|
||||||
newSettings.asObject(rt),
|
|
||||||
[&](jsi::Runtime &rt, const jsi::Value &settings) {
|
|
||||||
return parseCSSAnimationSettings(rt, settings);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
CSSAnimationSettingsUpdatesMap parseSettingsUpdates(
|
|
||||||
jsi::Runtime &rt,
|
|
||||||
const jsi::Value &settingsUpdates) {
|
|
||||||
return parseHelper<PartialCSSAnimationSettings>(
|
|
||||||
rt,
|
|
||||||
settingsUpdates.asObject(rt),
|
|
||||||
[](jsi::Runtime &rt, const jsi::Value &settings) {
|
|
||||||
return parsePartialCSSAnimationSettings(rt, settings);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
CSSAnimationUpdates parseCSSAnimationUpdates(
|
|
||||||
jsi::Runtime &rt,
|
|
||||||
const jsi::Value &config) {
|
|
||||||
const auto &configObj = config.asObject(rt);
|
|
||||||
|
|
||||||
CSSAnimationUpdates result;
|
|
||||||
|
|
||||||
if (configObj.hasProperty(rt, "animationNames")) {
|
|
||||||
const auto animationNames =
|
|
||||||
parseAnimationNames(rt, configObj.getProperty(rt, "animationNames"));
|
|
||||||
result.animationNames = std::move(animationNames);
|
|
||||||
|
|
||||||
if (configObj.hasProperty(rt, "newAnimationSettings")) {
|
|
||||||
result.newAnimationSettings = parseNewAnimationSettings(
|
|
||||||
rt,
|
|
||||||
animationNames,
|
|
||||||
configObj.getProperty(rt, "newAnimationSettings"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (configObj.hasProperty(rt, "settingsUpdates")) {
|
|
||||||
result.settingsUpdates =
|
|
||||||
parseSettingsUpdates(rt, configObj.getProperty(rt, "settingsUpdates"));
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace reanimated::css
|
|
||||||
Generated
Vendored
-53
@@ -1,53 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <reanimated/CSS/configs/CSSKeyframesConfig.h>
|
|
||||||
#include <reanimated/CSS/configs/common.h>
|
|
||||||
#include <reanimated/CSS/easing/EasingFunctions.h>
|
|
||||||
|
|
||||||
#include <optional>
|
|
||||||
#include <string>
|
|
||||||
#include <unordered_map>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace reanimated::css {
|
|
||||||
|
|
||||||
enum class AnimationDirection { Normal, Reverse, Alternate, AlternateReverse };
|
|
||||||
enum class AnimationFillMode { None, Forwards, Backwards, Both };
|
|
||||||
enum class AnimationPlayState { Running, Paused };
|
|
||||||
|
|
||||||
struct CSSAnimationSettings {
|
|
||||||
double duration;
|
|
||||||
EasingFunction easingFunction;
|
|
||||||
double delay;
|
|
||||||
double iterationCount;
|
|
||||||
AnimationDirection direction;
|
|
||||||
AnimationFillMode fillMode;
|
|
||||||
AnimationPlayState playState;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct PartialCSSAnimationSettings {
|
|
||||||
std::optional<double> duration;
|
|
||||||
std::optional<EasingFunction> easingFunction;
|
|
||||||
std::optional<double> delay;
|
|
||||||
std::optional<double> iterationCount;
|
|
||||||
std::optional<AnimationDirection> direction;
|
|
||||||
std::optional<AnimationFillMode> fillMode;
|
|
||||||
std::optional<AnimationPlayState> playState;
|
|
||||||
};
|
|
||||||
|
|
||||||
using CSSAnimationSettingsMap =
|
|
||||||
std::unordered_map<size_t, CSSAnimationSettings>;
|
|
||||||
using CSSAnimationSettingsUpdatesMap =
|
|
||||||
std::unordered_map<size_t, PartialCSSAnimationSettings>;
|
|
||||||
|
|
||||||
struct CSSAnimationUpdates {
|
|
||||||
std::optional<std::vector<std::string>> animationNames;
|
|
||||||
CSSAnimationSettingsMap newAnimationSettings;
|
|
||||||
CSSAnimationSettingsUpdatesMap settingsUpdates;
|
|
||||||
};
|
|
||||||
|
|
||||||
CSSAnimationUpdates parseCSSAnimationUpdates(
|
|
||||||
jsi::Runtime &rt,
|
|
||||||
const jsi::Value &config);
|
|
||||||
|
|
||||||
} // namespace reanimated::css
|
|
||||||
Generated
Vendored
-52
@@ -1,52 +0,0 @@
|
|||||||
#include <reanimated/CSS/configs/CSSKeyframesConfig.h>
|
|
||||||
|
|
||||||
namespace reanimated::css {
|
|
||||||
|
|
||||||
std::shared_ptr<AnimationStyleInterpolator> createStyleInterpolator(
|
|
||||||
jsi::Runtime &rt,
|
|
||||||
const jsi::Object &config,
|
|
||||||
const std::string &componentName,
|
|
||||||
const std::shared_ptr<ViewStylesRepository> &viewStylesRepository) {
|
|
||||||
return std::make_shared<AnimationStyleInterpolator>(
|
|
||||||
rt,
|
|
||||||
config.getProperty(rt, "keyframesStyle"),
|
|
||||||
componentName,
|
|
||||||
viewStylesRepository);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<KeyframeEasingFunctions> getKeyframeTimingFunctions(
|
|
||||||
jsi::Runtime &rt,
|
|
||||||
const jsi::Object &config) {
|
|
||||||
KeyframeEasingFunctions result;
|
|
||||||
const auto &keyframeTimingFunctions =
|
|
||||||
config.getProperty(rt, "keyframeTimingFunctions").asObject(rt);
|
|
||||||
const auto timingFunctionOffsets =
|
|
||||||
keyframeTimingFunctions.getPropertyNames(rt);
|
|
||||||
const auto timingFunctionsCount = timingFunctionOffsets.size(rt);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < timingFunctionsCount; ++i) {
|
|
||||||
const auto offset =
|
|
||||||
timingFunctionOffsets.getValueAtIndex(rt, i).asString(rt).utf8(rt);
|
|
||||||
const auto easingFunction = createEasingFunction(
|
|
||||||
rt, keyframeTimingFunctions.getProperty(rt, offset.c_str()));
|
|
||||||
|
|
||||||
result[std::stod(offset)] = easingFunction;
|
|
||||||
}
|
|
||||||
|
|
||||||
return std::make_shared<KeyframeEasingFunctions>(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
CSSKeyframesConfig parseCSSAnimationKeyframesConfig(
|
|
||||||
jsi::Runtime &rt,
|
|
||||||
const jsi::Value &config,
|
|
||||||
const std::string &componentName,
|
|
||||||
const std::shared_ptr<ViewStylesRepository> &viewStylesRepository) {
|
|
||||||
const auto &configObj = config.asObject(rt);
|
|
||||||
|
|
||||||
return {
|
|
||||||
createStyleInterpolator(
|
|
||||||
rt, configObj, componentName, viewStylesRepository),
|
|
||||||
getKeyframeTimingFunctions(rt, configObj)};
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace reanimated::css
|
|
||||||
Generated
Vendored
-26
@@ -1,26 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <reanimated/CSS/easing/EasingFunctions.h>
|
|
||||||
#include <reanimated/CSS/interpolation/styles/AnimationStyleInterpolator.h>
|
|
||||||
#include <reanimated/CSS/misc/ViewStylesRepository.h>
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <string>
|
|
||||||
#include <unordered_map>
|
|
||||||
|
|
||||||
namespace reanimated::css {
|
|
||||||
|
|
||||||
using KeyframeEasingFunctions = std::unordered_map<double, EasingFunction>;
|
|
||||||
|
|
||||||
struct CSSKeyframesConfig {
|
|
||||||
std::shared_ptr<AnimationStyleInterpolator> styleInterpolator;
|
|
||||||
std::shared_ptr<KeyframeEasingFunctions> keyframeEasingFunctions;
|
|
||||||
};
|
|
||||||
|
|
||||||
CSSKeyframesConfig parseCSSAnimationKeyframesConfig(
|
|
||||||
jsi::Runtime &rt,
|
|
||||||
const jsi::Value &config,
|
|
||||||
const std::string &componentName,
|
|
||||||
const std::shared_ptr<ViewStylesRepository> &viewStylesRepository);
|
|
||||||
|
|
||||||
} // namespace reanimated::css
|
|
||||||
Generated
Vendored
-102
@@ -1,102 +0,0 @@
|
|||||||
#include <reanimated/CSS/configs/CSSTransitionConfig.h>
|
|
||||||
|
|
||||||
namespace reanimated::css {
|
|
||||||
|
|
||||||
std::optional<CSSTransitionPropertySettings> getTransitionPropertySettings(
|
|
||||||
const CSSTransitionPropertiesSettings &propertiesSettings,
|
|
||||||
const std::string &propName) {
|
|
||||||
// Try to use property specific settings first
|
|
||||||
const auto &propIt = propertiesSettings.find(propName);
|
|
||||||
if (propIt != propertiesSettings.end()) {
|
|
||||||
return propIt->second;
|
|
||||||
}
|
|
||||||
// Fallback to "all" settings if no property specific settings are available
|
|
||||||
const auto &allIt = propertiesSettings.find("all");
|
|
||||||
if (allIt != propertiesSettings.end()) {
|
|
||||||
return allIt->second;
|
|
||||||
}
|
|
||||||
// Or return nullopt if no settings are available
|
|
||||||
return std::nullopt;
|
|
||||||
}
|
|
||||||
|
|
||||||
TransitionProperties getProperties(
|
|
||||||
jsi::Runtime &rt,
|
|
||||||
const jsi::Object &config) {
|
|
||||||
const auto transitionProperty = config.getProperty(rt, "properties");
|
|
||||||
|
|
||||||
if (transitionProperty.isObject()) {
|
|
||||||
PropertyNames properties;
|
|
||||||
|
|
||||||
const auto propertiesArray = transitionProperty.asObject(rt).asArray(rt);
|
|
||||||
const auto propertiesCount = propertiesArray.size(rt);
|
|
||||||
for (size_t i = 0; i < propertiesCount; ++i) {
|
|
||||||
properties.emplace_back(
|
|
||||||
propertiesArray.getValueAtIndex(rt, i).asString(rt).utf8(rt));
|
|
||||||
}
|
|
||||||
|
|
||||||
return properties;
|
|
||||||
}
|
|
||||||
|
|
||||||
return std::nullopt;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool getAllowDiscrete(jsi::Runtime &rt, const jsi::Object &config) {
|
|
||||||
return config.getProperty(rt, "allowDiscrete").asBool();
|
|
||||||
}
|
|
||||||
|
|
||||||
CSSTransitionPropertiesSettings parseCSSTransitionPropertiesSettings(
|
|
||||||
jsi::Runtime &rt,
|
|
||||||
const jsi::Object &settings) {
|
|
||||||
CSSTransitionPropertiesSettings result;
|
|
||||||
|
|
||||||
const auto propertyNames = settings.getPropertyNames(rt);
|
|
||||||
const auto propertiesCount = propertyNames.size(rt);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < propertiesCount; ++i) {
|
|
||||||
const auto propertyName =
|
|
||||||
propertyNames.getValueAtIndex(rt, i).asString(rt).utf8(rt);
|
|
||||||
const auto propertySettings =
|
|
||||||
settings.getProperty(rt, jsi::PropNameID::forUtf8(rt, propertyName))
|
|
||||||
.asObject(rt);
|
|
||||||
|
|
||||||
result.emplace(
|
|
||||||
propertyName,
|
|
||||||
CSSTransitionPropertySettings{
|
|
||||||
getDuration(rt, propertySettings),
|
|
||||||
getTimingFunction(rt, propertySettings),
|
|
||||||
getDelay(rt, propertySettings),
|
|
||||||
getAllowDiscrete(rt, propertySettings)});
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
CSSTransitionConfig parseCSSTransitionConfig(
|
|
||||||
jsi::Runtime &rt,
|
|
||||||
const jsi::Value &config) {
|
|
||||||
const auto configObj = config.asObject(rt);
|
|
||||||
return CSSTransitionConfig{
|
|
||||||
getProperties(rt, configObj),
|
|
||||||
parseCSSTransitionPropertiesSettings(
|
|
||||||
rt, configObj.getProperty(rt, "settings").asObject(rt))};
|
|
||||||
}
|
|
||||||
|
|
||||||
PartialCSSTransitionConfig parsePartialCSSTransitionConfig(
|
|
||||||
jsi::Runtime &rt,
|
|
||||||
const jsi::Value &partialConfig) {
|
|
||||||
const auto partialObj = partialConfig.asObject(rt);
|
|
||||||
|
|
||||||
PartialCSSTransitionConfig result;
|
|
||||||
|
|
||||||
if (partialObj.hasProperty(rt, "properties")) {
|
|
||||||
result.properties = getProperties(rt, partialObj);
|
|
||||||
}
|
|
||||||
if (partialObj.hasProperty(rt, "settings")) {
|
|
||||||
result.settings = parseCSSTransitionPropertiesSettings(
|
|
||||||
rt, partialObj.getProperty(rt, "settings").asObject(rt));
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace reanimated::css
|
|
||||||
Generated
Vendored
-50
@@ -1,50 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <reanimated/CSS/common/definitions.h>
|
|
||||||
#include <reanimated/CSS/configs/common.h>
|
|
||||||
#include <reanimated/CSS/easing/EasingFunctions.h>
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <unordered_map>
|
|
||||||
|
|
||||||
namespace reanimated::css {
|
|
||||||
|
|
||||||
struct CSSTransitionPropertySettings {
|
|
||||||
double duration;
|
|
||||||
EasingFunction easingFunction;
|
|
||||||
double delay;
|
|
||||||
bool allowDiscrete;
|
|
||||||
};
|
|
||||||
|
|
||||||
using CSSTransitionPropertiesSettings =
|
|
||||||
std::unordered_map<std::string, CSSTransitionPropertySettings>;
|
|
||||||
|
|
||||||
struct CSSTransitionConfig {
|
|
||||||
TransitionProperties properties;
|
|
||||||
CSSTransitionPropertiesSettings settings;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct PartialCSSTransitionConfig {
|
|
||||||
std::optional<TransitionProperties> properties;
|
|
||||||
std::optional<CSSTransitionPropertiesSettings> settings;
|
|
||||||
};
|
|
||||||
|
|
||||||
std::optional<CSSTransitionPropertySettings> getTransitionPropertySettings(
|
|
||||||
const CSSTransitionPropertiesSettings &propertiesSettings,
|
|
||||||
const std::string &propName);
|
|
||||||
|
|
||||||
TransitionProperties getProperties(jsi::Runtime &rt, const jsi::Object &config);
|
|
||||||
|
|
||||||
CSSTransitionPropertiesSettings parseCSSTransitionPropertiesSettings(
|
|
||||||
jsi::Runtime &rt,
|
|
||||||
const jsi::Object &settings);
|
|
||||||
|
|
||||||
CSSTransitionConfig parseCSSTransitionConfig(
|
|
||||||
jsi::Runtime &rt,
|
|
||||||
const jsi::Value &config);
|
|
||||||
|
|
||||||
PartialCSSTransitionConfig parsePartialCSSTransitionConfig(
|
|
||||||
jsi::Runtime &rt,
|
|
||||||
const jsi::Value &partialConfig);
|
|
||||||
|
|
||||||
} // namespace reanimated::css
|
|
||||||
Generated
Vendored
-17
@@ -1,17 +0,0 @@
|
|||||||
#include <reanimated/CSS/configs/common.h>
|
|
||||||
|
|
||||||
namespace reanimated::css {
|
|
||||||
|
|
||||||
double getDuration(jsi::Runtime &rt, const jsi::Object &config) {
|
|
||||||
return config.getProperty(rt, "duration").asNumber();
|
|
||||||
}
|
|
||||||
|
|
||||||
EasingFunction getTimingFunction(jsi::Runtime &rt, const jsi::Object &config) {
|
|
||||||
return createEasingFunction(rt, config.getProperty(rt, "timingFunction"));
|
|
||||||
}
|
|
||||||
|
|
||||||
double getDelay(jsi::Runtime &rt, const jsi::Object &config) {
|
|
||||||
return config.getProperty(rt, "delay").asNumber();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace reanimated::css
|
|
||||||
Generated
Vendored
-13
@@ -1,13 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <reanimated/CSS/easing/EasingFunctions.h>
|
|
||||||
|
|
||||||
namespace reanimated::css {
|
|
||||||
|
|
||||||
double getDuration(jsi::Runtime &rt, const jsi::Object &config);
|
|
||||||
|
|
||||||
EasingFunction getTimingFunction(jsi::Runtime &rt, const jsi::Object &config);
|
|
||||||
|
|
||||||
double getDelay(jsi::Runtime &rt, const jsi::Object &config);
|
|
||||||
|
|
||||||
} // namespace reanimated::css
|
|
||||||
Generated
Vendored
-135
@@ -1,135 +0,0 @@
|
|||||||
#include <reanimated/CSS/core/CSSAnimation.h>
|
|
||||||
|
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
namespace reanimated::css {
|
|
||||||
|
|
||||||
CSSAnimation::CSSAnimation(
|
|
||||||
jsi::Runtime &rt,
|
|
||||||
std::shared_ptr<const ShadowNode> shadowNode,
|
|
||||||
std::string animationName,
|
|
||||||
const CSSKeyframesConfig &cssKeyframesConfig,
|
|
||||||
const CSSAnimationSettings &settings,
|
|
||||||
const double timestamp)
|
|
||||||
: name_(std::move(animationName)),
|
|
||||||
shadowNode_(std::move(shadowNode)),
|
|
||||||
fillMode_(settings.fillMode),
|
|
||||||
styleInterpolator_(cssKeyframesConfig.styleInterpolator),
|
|
||||||
progressProvider_(std::make_shared<AnimationProgressProvider>(
|
|
||||||
timestamp,
|
|
||||||
settings.duration,
|
|
||||||
settings.delay,
|
|
||||||
settings.iterationCount,
|
|
||||||
settings.direction,
|
|
||||||
settings.easingFunction,
|
|
||||||
cssKeyframesConfig.keyframeEasingFunctions)) {
|
|
||||||
if (settings.playState == AnimationPlayState::Paused) {
|
|
||||||
progressProvider_->pause(timestamp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::string &CSSAnimation::getName() const {
|
|
||||||
return name_;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<const ShadowNode> CSSAnimation::getShadowNode() const {
|
|
||||||
return shadowNode_;
|
|
||||||
}
|
|
||||||
|
|
||||||
double CSSAnimation::getStartTimestamp(const double timestamp) const {
|
|
||||||
return progressProvider_->getStartTimestamp(timestamp);
|
|
||||||
}
|
|
||||||
|
|
||||||
AnimationProgressState CSSAnimation::getState(double timestamp) const {
|
|
||||||
return progressProvider_->getState(timestamp);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CSSAnimation::isReversed() const {
|
|
||||||
const auto direction = progressProvider_->getDirection();
|
|
||||||
return direction == AnimationDirection::Reverse ||
|
|
||||||
direction == AnimationDirection::AlternateReverse;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CSSAnimation::hasForwardsFillMode() const {
|
|
||||||
return fillMode_ == AnimationFillMode::Forwards ||
|
|
||||||
fillMode_ == AnimationFillMode::Both;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CSSAnimation::hasBackwardsFillMode() const {
|
|
||||||
return fillMode_ == AnimationFillMode::Backwards ||
|
|
||||||
fillMode_ == AnimationFillMode::Both;
|
|
||||||
}
|
|
||||||
|
|
||||||
folly::dynamic CSSAnimation::getCurrentInterpolationStyle() const {
|
|
||||||
return styleInterpolator_->interpolate(shadowNode_, progressProvider_);
|
|
||||||
}
|
|
||||||
|
|
||||||
folly::dynamic CSSAnimation::getBackwardsFillStyle() const {
|
|
||||||
return isReversed() ? styleInterpolator_->getLastKeyframeValue()
|
|
||||||
: styleInterpolator_->getFirstKeyframeValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
folly::dynamic CSSAnimation::getResetStyle() const {
|
|
||||||
return styleInterpolator_->getResetStyle(shadowNode_);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CSSAnimation::run(const double timestamp) {
|
|
||||||
if (progressProvider_->getState(timestamp) ==
|
|
||||||
AnimationProgressState::Finished) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
progressProvider_->play(timestamp);
|
|
||||||
}
|
|
||||||
|
|
||||||
folly::dynamic CSSAnimation::update(const double timestamp) {
|
|
||||||
progressProvider_->update(timestamp);
|
|
||||||
|
|
||||||
// Check if the animation has not started yet because of the delay
|
|
||||||
// (In general, it shouldn't be activated until the delay has passed but we
|
|
||||||
// add this check to make sure that animation doesn't start with the negative
|
|
||||||
// progress)
|
|
||||||
if (progressProvider_->getState(timestamp) ==
|
|
||||||
AnimationProgressState::Pending) {
|
|
||||||
return hasBackwardsFillMode() ? getBackwardsFillStyle() : folly::dynamic();
|
|
||||||
}
|
|
||||||
|
|
||||||
return styleInterpolator_->interpolate(shadowNode_, progressProvider_);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CSSAnimation::updateSettings(
|
|
||||||
const PartialCSSAnimationSettings &updatedSettings,
|
|
||||||
const double timestamp) {
|
|
||||||
progressProvider_->resetProgress();
|
|
||||||
|
|
||||||
if (updatedSettings.duration.has_value()) {
|
|
||||||
progressProvider_->setDuration(updatedSettings.duration.value());
|
|
||||||
}
|
|
||||||
if (updatedSettings.easingFunction.has_value()) {
|
|
||||||
progressProvider_->setEasingFunction(
|
|
||||||
updatedSettings.easingFunction.value());
|
|
||||||
}
|
|
||||||
if (updatedSettings.delay.has_value()) {
|
|
||||||
progressProvider_->setDelay(updatedSettings.delay.value());
|
|
||||||
}
|
|
||||||
if (updatedSettings.iterationCount.has_value()) {
|
|
||||||
progressProvider_->setIterationCount(
|
|
||||||
updatedSettings.iterationCount.value());
|
|
||||||
}
|
|
||||||
if (updatedSettings.direction.has_value()) {
|
|
||||||
progressProvider_->setDirection(updatedSettings.direction.value());
|
|
||||||
}
|
|
||||||
if (updatedSettings.fillMode.has_value()) {
|
|
||||||
fillMode_ = updatedSettings.fillMode.value();
|
|
||||||
}
|
|
||||||
if (updatedSettings.playState.has_value()) {
|
|
||||||
if (updatedSettings.playState.value() == AnimationPlayState::Paused) {
|
|
||||||
progressProvider_->pause(timestamp);
|
|
||||||
} else {
|
|
||||||
progressProvider_->play(timestamp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
progressProvider_->update(timestamp);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace reanimated::css
|
|
||||||
Generated
Vendored
-51
@@ -1,51 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <reanimated/CSS/configs/CSSAnimationConfig.h>
|
|
||||||
#include <reanimated/CSS/configs/CSSKeyframesConfig.h>
|
|
||||||
#include <reanimated/CSS/progress/AnimationProgressProvider.h>
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
namespace reanimated::css {
|
|
||||||
|
|
||||||
class CSSAnimation {
|
|
||||||
public:
|
|
||||||
CSSAnimation(
|
|
||||||
jsi::Runtime &rt,
|
|
||||||
std::shared_ptr<const ShadowNode> shadowNode,
|
|
||||||
std::string animationName,
|
|
||||||
const CSSKeyframesConfig &cssKeyframesConfig,
|
|
||||||
const CSSAnimationSettings &settings,
|
|
||||||
double timestamp);
|
|
||||||
|
|
||||||
const std::string &getName() const;
|
|
||||||
std::shared_ptr<const ShadowNode> getShadowNode() const;
|
|
||||||
|
|
||||||
double getStartTimestamp(double timestamp) const;
|
|
||||||
AnimationProgressState getState(double timestamp) const;
|
|
||||||
bool isReversed() const;
|
|
||||||
|
|
||||||
bool hasForwardsFillMode() const;
|
|
||||||
bool hasBackwardsFillMode() const;
|
|
||||||
|
|
||||||
folly::dynamic getCurrentInterpolationStyle() const;
|
|
||||||
folly::dynamic getBackwardsFillStyle() const;
|
|
||||||
folly::dynamic getResetStyle() const;
|
|
||||||
|
|
||||||
void run(double timestamp);
|
|
||||||
folly::dynamic update(double timestamp);
|
|
||||||
void updateSettings(
|
|
||||||
const PartialCSSAnimationSettings &updatedSettings,
|
|
||||||
double timestamp);
|
|
||||||
|
|
||||||
private:
|
|
||||||
const std::string name_;
|
|
||||||
const std::shared_ptr<const ShadowNode> shadowNode_;
|
|
||||||
AnimationFillMode fillMode_;
|
|
||||||
|
|
||||||
const std::shared_ptr<AnimationStyleInterpolator> styleInterpolator_;
|
|
||||||
const std::shared_ptr<AnimationProgressProvider> progressProvider_;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace reanimated::css
|
|
||||||
frontend-admin/node_modules/react-native-reanimated/Common/cpp/reanimated/CSS/core/CSSTransition.cpp
Generated
Vendored
-145
@@ -1,145 +0,0 @@
|
|||||||
#include <reanimated/CSS/core/CSSTransition.h>
|
|
||||||
|
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
namespace reanimated::css {
|
|
||||||
|
|
||||||
CSSTransition::CSSTransition(
|
|
||||||
std::shared_ptr<const ShadowNode> shadowNode,
|
|
||||||
const CSSTransitionConfig &config,
|
|
||||||
const std::shared_ptr<ViewStylesRepository> &viewStylesRepository)
|
|
||||||
: shadowNode_(std::move(shadowNode)),
|
|
||||||
viewStylesRepository_(viewStylesRepository),
|
|
||||||
properties_(config.properties),
|
|
||||||
settings_(config.settings),
|
|
||||||
styleInterpolator_(TransitionStyleInterpolator(
|
|
||||||
shadowNode_->getComponentName(),
|
|
||||||
viewStylesRepository)),
|
|
||||||
progressProvider_(TransitionProgressProvider()) {}
|
|
||||||
|
|
||||||
Tag CSSTransition::getViewTag() const {
|
|
||||||
return shadowNode_->getTag();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<const ShadowNode> CSSTransition::getShadowNode() const {
|
|
||||||
return shadowNode_;
|
|
||||||
}
|
|
||||||
|
|
||||||
double CSSTransition::getMinDelay(double timestamp) const {
|
|
||||||
return progressProvider_.getMinDelay(timestamp);
|
|
||||||
}
|
|
||||||
|
|
||||||
TransitionProgressState CSSTransition::getState() const {
|
|
||||||
return progressProvider_.getState();
|
|
||||||
}
|
|
||||||
|
|
||||||
folly::dynamic CSSTransition::getCurrentInterpolationStyle() const {
|
|
||||||
return styleInterpolator_.interpolate(shadowNode_, progressProvider_);
|
|
||||||
}
|
|
||||||
|
|
||||||
TransitionProperties CSSTransition::getProperties() const {
|
|
||||||
return properties_;
|
|
||||||
}
|
|
||||||
|
|
||||||
PropertyNames CSSTransition::getAllowedProperties(
|
|
||||||
const folly::dynamic &oldProps,
|
|
||||||
const folly::dynamic &newProps) {
|
|
||||||
if (!oldProps.isObject() || !newProps.isObject()) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
// If specific properties are set, process only those
|
|
||||||
if (properties_.has_value()) {
|
|
||||||
PropertyNames allowedProps;
|
|
||||||
const auto &properties = properties_.value();
|
|
||||||
allowedProps.reserve(properties.size());
|
|
||||||
|
|
||||||
for (const auto &prop : properties) {
|
|
||||||
if (isAllowedProperty(prop)) {
|
|
||||||
allowedProps.push_back(prop);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return allowedProps;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Process all properties from both old and new props
|
|
||||||
std::unordered_set<std::string> allAllowedProps;
|
|
||||||
|
|
||||||
for (const auto &props : {oldProps, newProps}) {
|
|
||||||
for (const auto &propertyName : props.keys()) {
|
|
||||||
if (isAllowedProperty(propertyName.asString())) {
|
|
||||||
allAllowedProps.insert(propertyName.asString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return {allAllowedProps.begin(), allAllowedProps.end()};
|
|
||||||
}
|
|
||||||
|
|
||||||
void CSSTransition::updateSettings(const PartialCSSTransitionConfig &config) {
|
|
||||||
if (config.properties.has_value()) {
|
|
||||||
updateTransitionProperties(config.properties.value());
|
|
||||||
}
|
|
||||||
if (config.settings.has_value()) {
|
|
||||||
settings_ = config.settings.value();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
folly::dynamic CSSTransition::run(
|
|
||||||
const ChangedProps &changedProps,
|
|
||||||
const folly::dynamic &lastUpdateValue,
|
|
||||||
const double timestamp) {
|
|
||||||
progressProvider_.runProgressProviders(
|
|
||||||
timestamp,
|
|
||||||
settings_,
|
|
||||||
changedProps.changedPropertyNames,
|
|
||||||
styleInterpolator_.getReversedPropertyNames(changedProps.newProps));
|
|
||||||
styleInterpolator_.updateInterpolatedProperties(
|
|
||||||
changedProps, lastUpdateValue);
|
|
||||||
return update(timestamp);
|
|
||||||
}
|
|
||||||
|
|
||||||
folly::dynamic CSSTransition::update(const double timestamp) {
|
|
||||||
progressProvider_.update(timestamp);
|
|
||||||
auto result = styleInterpolator_.interpolate(shadowNode_, progressProvider_);
|
|
||||||
// Remove interpolators for which interpolation has finished
|
|
||||||
// (we won't need them anymore in the current transition)
|
|
||||||
styleInterpolator_.discardFinishedInterpolators(progressProvider_);
|
|
||||||
// And remove finished progress providers after they were used to calculate
|
|
||||||
// the last frame of the transition
|
|
||||||
progressProvider_.discardFinishedProgressProviders();
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CSSTransition::updateTransitionProperties(
|
|
||||||
const TransitionProperties &properties) {
|
|
||||||
properties_ = properties;
|
|
||||||
|
|
||||||
const auto isAllPropertiesTransition = !properties_.has_value();
|
|
||||||
if (isAllPropertiesTransition) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::unordered_set<std::string> transitionPropertyNames(
|
|
||||||
properties_->begin(), properties_->end());
|
|
||||||
|
|
||||||
styleInterpolator_.discardIrrelevantInterpolators(transitionPropertyNames);
|
|
||||||
progressProvider_.discardIrrelevantProgressProviders(transitionPropertyNames);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CSSTransition::isAllowedProperty(const std::string &propertyName) const {
|
|
||||||
if (!isDiscreteProperty(propertyName, shadowNode_->getComponentName())) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto &propertySettings =
|
|
||||||
getTransitionPropertySettings(settings_, propertyName);
|
|
||||||
|
|
||||||
if (!propertySettings.has_value()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return propertySettings.value().allowDiscrete;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace reanimated::css
|
|
||||||
Generated
Vendored
-50
@@ -1,50 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <reanimated/CSS/configs/CSSTransitionConfig.h>
|
|
||||||
#include <reanimated/CSS/easing/EasingFunctions.h>
|
|
||||||
#include <reanimated/CSS/interpolation/styles/TransitionStyleInterpolator.h>
|
|
||||||
#include <reanimated/CSS/progress/TransitionProgressProvider.h>
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <string>
|
|
||||||
#include <unordered_set>
|
|
||||||
|
|
||||||
namespace reanimated::css {
|
|
||||||
|
|
||||||
class CSSTransition {
|
|
||||||
public:
|
|
||||||
CSSTransition(
|
|
||||||
std::shared_ptr<const ShadowNode> shadowNode,
|
|
||||||
const CSSTransitionConfig &config,
|
|
||||||
const std::shared_ptr<ViewStylesRepository> &viewStylesRepository);
|
|
||||||
|
|
||||||
Tag getViewTag() const;
|
|
||||||
std::shared_ptr<const ShadowNode> getShadowNode() const;
|
|
||||||
double getMinDelay(double timestamp) const;
|
|
||||||
TransitionProgressState getState() const;
|
|
||||||
folly::dynamic getCurrentInterpolationStyle() const;
|
|
||||||
TransitionProperties getProperties() const;
|
|
||||||
PropertyNames getAllowedProperties(
|
|
||||||
const folly::dynamic &oldProps,
|
|
||||||
const folly::dynamic &newProps);
|
|
||||||
|
|
||||||
void updateSettings(const PartialCSSTransitionConfig &config);
|
|
||||||
folly::dynamic run(
|
|
||||||
const ChangedProps &changedProps,
|
|
||||||
const folly::dynamic &lastUpdateValue,
|
|
||||||
double timestamp);
|
|
||||||
folly::dynamic update(double timestamp);
|
|
||||||
|
|
||||||
private:
|
|
||||||
const std::shared_ptr<const ShadowNode> shadowNode_;
|
|
||||||
const std::shared_ptr<ViewStylesRepository> viewStylesRepository_;
|
|
||||||
TransitionProperties properties_;
|
|
||||||
CSSTransitionPropertiesSettings settings_;
|
|
||||||
TransitionStyleInterpolator styleInterpolator_;
|
|
||||||
TransitionProgressProvider progressProvider_;
|
|
||||||
|
|
||||||
void updateTransitionProperties(const TransitionProperties &properties);
|
|
||||||
bool isAllowedProperty(const std::string &propertyName) const;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace reanimated::css
|
|
||||||
Generated
Vendored
-76
@@ -1,76 +0,0 @@
|
|||||||
#include <reanimated/CSS/easing/EasingFunctions.h>
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace reanimated::css {
|
|
||||||
|
|
||||||
inline const std::unordered_map<std::string, EasingFunction>
|
|
||||||
PREDEFINED_EASING_MAP = {
|
|
||||||
{"linear", [](double x) { return x; }},
|
|
||||||
{"ease", cubicBezier(0.25, 0.1, 0.25, 0.1)},
|
|
||||||
{"ease-in", cubicBezier(0.42, 0.0, 1.0, 1.0)},
|
|
||||||
{"ease-out", cubicBezier(0.0, 0.0, 0.58, 1.0)},
|
|
||||||
{"ease-in-out", cubicBezier(0.42, 0.0, 0.58, 1.0)},
|
|
||||||
{"step-start", steps(std::vector<double>{0}, std::vector<double>{1})},
|
|
||||||
{"step-end",
|
|
||||||
steps(std::vector<double>{0, 1}, std::vector<double>{0, 1})}};
|
|
||||||
|
|
||||||
EasingFunction createEasingFunction(
|
|
||||||
jsi::Runtime &rt,
|
|
||||||
const jsi::Value &easingConfig) {
|
|
||||||
if (easingConfig.isString()) {
|
|
||||||
return getPredefinedEasingFunction(easingConfig.asString(rt).utf8(rt));
|
|
||||||
} else if (easingConfig.isObject()) {
|
|
||||||
return createParametrizedEasingFunction(rt, easingConfig.asObject(rt));
|
|
||||||
} else {
|
|
||||||
throw std::runtime_error(
|
|
||||||
std::string("[Reanimated] Invalid easing function"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
EasingFunction getPredefinedEasingFunction(const std::string &name) {
|
|
||||||
auto it = PREDEFINED_EASING_MAP.find(name);
|
|
||||||
if (it != PREDEFINED_EASING_MAP.end()) {
|
|
||||||
return it->second;
|
|
||||||
} else {
|
|
||||||
throw std::runtime_error(std::string(
|
|
||||||
"[Reanimated] Easing function with name '" + name +
|
|
||||||
"' is not defined."));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
EasingFunction createParametrizedEasingFunction(
|
|
||||||
jsi::Runtime &rt,
|
|
||||||
const jsi::Object &easingConfig) {
|
|
||||||
const auto easingName =
|
|
||||||
easingConfig.getProperty(rt, "name").asString(rt).utf8(rt);
|
|
||||||
|
|
||||||
if (easingName == "cubicBezier") {
|
|
||||||
return cubicBezier(rt, easingConfig);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<double> pointsX;
|
|
||||||
std::vector<double> pointsY;
|
|
||||||
|
|
||||||
const auto points =
|
|
||||||
easingConfig.getProperty(rt, "points").asObject(rt).asArray(rt);
|
|
||||||
const auto pointsCount = points.size(rt);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < pointsCount; i++) {
|
|
||||||
const auto pointObj = points.getValueAtIndex(rt, i).asObject(rt);
|
|
||||||
pointsX.push_back(pointObj.getProperty(rt, "x").asNumber());
|
|
||||||
pointsY.push_back(pointObj.getProperty(rt, "y").asNumber());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (easingName == "linear") {
|
|
||||||
return linear(pointsX, pointsY);
|
|
||||||
} else if (easingName == "steps") {
|
|
||||||
return steps(pointsX, pointsY);
|
|
||||||
} else {
|
|
||||||
throw std::runtime_error(std::string(
|
|
||||||
"[Reanimated] Parametrized easing function with name '" + easingName +
|
|
||||||
"' is not defined."));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace reanimated::css
|
|
||||||
Generated
Vendored
-27
@@ -1,27 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <reanimated/CSS/easing/cubicBezier.h>
|
|
||||||
#include <reanimated/CSS/easing/linear.h>
|
|
||||||
#include <reanimated/CSS/easing/steps.h>
|
|
||||||
|
|
||||||
#include <jsi/jsi.h>
|
|
||||||
#include <string>
|
|
||||||
#include <unordered_map>
|
|
||||||
|
|
||||||
namespace reanimated::css {
|
|
||||||
|
|
||||||
using namespace facebook;
|
|
||||||
|
|
||||||
extern const std::unordered_map<std::string, EasingFunction>
|
|
||||||
PREDEFINED_EASING_MAP;
|
|
||||||
|
|
||||||
EasingFunction getPredefinedEasingFunction(const std::string &name);
|
|
||||||
EasingFunction createParametrizedEasingFunction(
|
|
||||||
jsi::Runtime &rt,
|
|
||||||
const jsi::Object &easingConfig);
|
|
||||||
|
|
||||||
EasingFunction createEasingFunction(
|
|
||||||
jsi::Runtime &rt,
|
|
||||||
const jsi::Value &easingConfig);
|
|
||||||
|
|
||||||
} // namespace reanimated::css
|
|
||||||
frontend-admin/node_modules/react-native-reanimated/Common/cpp/reanimated/CSS/easing/cubicBezier.cpp
Generated
Vendored
-76
@@ -1,76 +0,0 @@
|
|||||||
#include <reanimated/CSS/easing/cubicBezier.h>
|
|
||||||
|
|
||||||
namespace reanimated::css {
|
|
||||||
|
|
||||||
double sampleCurveX(const double t, const double x1, const double x2) {
|
|
||||||
return 3 * (1 - t) * (1 - t) * t * x1 + 3 * (1 - t) * t * t * x2 + t * t * t;
|
|
||||||
}
|
|
||||||
|
|
||||||
double sampleCurveY(const double t, const double y1, const double y2) {
|
|
||||||
return 3 * (1 - t) * (1 - t) * t * y1 + 3 * (1 - t) * t * t * y2 + t * t * t;
|
|
||||||
}
|
|
||||||
|
|
||||||
double
|
|
||||||
sampleCurveDerivativeX(const double t, const double x1, const double x2) {
|
|
||||||
return -6 * (1 - t) * t * x1 + 3 * (1 - t) * (1 - t) * x1 +
|
|
||||||
6 * (1 - t) * t * x2 - 6 * t * t * x2 + 3 * t * t;
|
|
||||||
}
|
|
||||||
|
|
||||||
double solveCurveX(
|
|
||||||
const double x,
|
|
||||||
const double x1,
|
|
||||||
const double x2,
|
|
||||||
const double epsilon) {
|
|
||||||
double t0 = 0.0, t1 = 1.0, t2 = x, xValue, dX;
|
|
||||||
int iterations = 0;
|
|
||||||
|
|
||||||
while (iterations < 8) {
|
|
||||||
xValue = sampleCurveX(t2, x1, x2) - x;
|
|
||||||
if (std::abs(xValue) < epsilon) {
|
|
||||||
return t2;
|
|
||||||
}
|
|
||||||
dX = sampleCurveDerivativeX(t2, x1, x2);
|
|
||||||
if (std::abs(dX) < epsilon) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
t2 = t2 - xValue / dX;
|
|
||||||
iterations++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fallback: Use binary search
|
|
||||||
while (t0 < t1) {
|
|
||||||
t2 = (t0 + t1) / 2.0;
|
|
||||||
xValue = sampleCurveX(t2, x1, x2);
|
|
||||||
if (std::abs(xValue - x) < epsilon) {
|
|
||||||
return t2;
|
|
||||||
}
|
|
||||||
if (x > xValue) {
|
|
||||||
t0 = t2;
|
|
||||||
} else {
|
|
||||||
t1 = t2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return t2;
|
|
||||||
}
|
|
||||||
|
|
||||||
EasingFunction cubicBezier(
|
|
||||||
const double x1,
|
|
||||||
const double y1,
|
|
||||||
const double x2,
|
|
||||||
const double y2) {
|
|
||||||
return [=](double x) {
|
|
||||||
double t = solveCurveX(x, x1, x2);
|
|
||||||
return sampleCurveY(t, y1, y2);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
EasingFunction cubicBezier(jsi::Runtime &rt, const jsi::Object &easingConfig) {
|
|
||||||
const auto x1 = easingConfig.getProperty(rt, "x1").asNumber();
|
|
||||||
const auto y1 = easingConfig.getProperty(rt, "y1").asNumber();
|
|
||||||
const auto x2 = easingConfig.getProperty(rt, "x2").asNumber();
|
|
||||||
const auto y2 = easingConfig.getProperty(rt, "y2").asNumber();
|
|
||||||
return cubicBezier(x1, y1, x2, y2);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace reanimated::css
|
|
||||||
Generated
Vendored
-15
@@ -1,15 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <reanimated/CSS/common/definitions.h>
|
|
||||||
|
|
||||||
namespace reanimated::css {
|
|
||||||
|
|
||||||
double sampleCurveX(double t, double x1, double x2);
|
|
||||||
double sampleCurveY(double t, double y1, double y2);
|
|
||||||
double sampleCurveDerivativeX(double t, double x1, double x2);
|
|
||||||
double solveCurveX(double x, double x1, double x2, double epsilon = 1e-6);
|
|
||||||
|
|
||||||
EasingFunction cubicBezier(double x1, double y1, double x2, double y2);
|
|
||||||
EasingFunction cubicBezier(jsi::Runtime &rt, const jsi::Object &easingConfig);
|
|
||||||
|
|
||||||
} // namespace reanimated::css
|
|
||||||
Generated
Vendored
-32
@@ -1,32 +0,0 @@
|
|||||||
#include <reanimated/CSS/easing/linear.h>
|
|
||||||
|
|
||||||
namespace reanimated::css {
|
|
||||||
|
|
||||||
double interpolateValue(
|
|
||||||
double x,
|
|
||||||
size_t leftIdx,
|
|
||||||
const std::vector<double> &pointsX,
|
|
||||||
const std::vector<double> &pointsY) {
|
|
||||||
if (leftIdx == pointsX.size() - 1) {
|
|
||||||
// We are exactly on the last point of the curve, we just return its y
|
|
||||||
// coordinate
|
|
||||||
return pointsY[leftIdx];
|
|
||||||
}
|
|
||||||
const auto rightIdx = leftIdx + 1;
|
|
||||||
// Calculate the line equation for the line between leftIdx and rightIdx
|
|
||||||
// points
|
|
||||||
const auto a = (pointsY[rightIdx] - pointsY[leftIdx]) /
|
|
||||||
(pointsX[rightIdx] - pointsX[leftIdx]);
|
|
||||||
return pointsY[leftIdx] + a * (x - pointsX[leftIdx]);
|
|
||||||
}
|
|
||||||
|
|
||||||
EasingFunction linear(
|
|
||||||
const std::vector<double> &pointsX,
|
|
||||||
const std::vector<double> &pointsY) {
|
|
||||||
return [=](double x) {
|
|
||||||
size_t leftIdx = firstSmallerOrEqual(x, pointsX);
|
|
||||||
return interpolateValue(x, leftIdx, pointsX, pointsY);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace reanimated::css
|
|
||||||
Generated
Vendored
-20
@@ -1,20 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <reanimated/CSS/common/definitions.h>
|
|
||||||
#include <reanimated/CSS/utils/algorithms.h>
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace reanimated::css {
|
|
||||||
|
|
||||||
double interpolateValue(
|
|
||||||
double x,
|
|
||||||
std::size_t leftIdx,
|
|
||||||
const std::vector<double> &arrX,
|
|
||||||
const std::vector<double> &arrY);
|
|
||||||
|
|
||||||
EasingFunction linear(
|
|
||||||
const std::vector<double> &pointsX,
|
|
||||||
const std::vector<double> &pointsY);
|
|
||||||
|
|
||||||
} // namespace reanimated::css
|
|
||||||
Generated
Vendored
-13
@@ -1,13 +0,0 @@
|
|||||||
#include <reanimated/CSS/easing/steps.h>
|
|
||||||
|
|
||||||
namespace reanimated::css {
|
|
||||||
EasingFunction steps(
|
|
||||||
const std::vector<double> &pointsX,
|
|
||||||
const std::vector<double> &pointsY) {
|
|
||||||
return [=](double x) {
|
|
||||||
size_t stepIdx = firstSmallerOrEqual(x, pointsX);
|
|
||||||
return pointsY[stepIdx];
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace reanimated::css
|
|
||||||
Generated
Vendored
-14
@@ -1,14 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <reanimated/CSS/common/definitions.h>
|
|
||||||
#include <reanimated/CSS/utils/algorithms.h>
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace reanimated::css {
|
|
||||||
|
|
||||||
EasingFunction steps(
|
|
||||||
const std::vector<double> &pointsX,
|
|
||||||
const std::vector<double> &pointsY);
|
|
||||||
|
|
||||||
} // namespace reanimated::css
|
|
||||||
Generated
Vendored
-134
@@ -1,134 +0,0 @@
|
|||||||
#include <reanimated/CSS/interpolation/InterpolatorFactory.h>
|
|
||||||
|
|
||||||
namespace reanimated::css {
|
|
||||||
|
|
||||||
class RecordInterpolatorFactory : public PropertyInterpolatorFactory {
|
|
||||||
public:
|
|
||||||
explicit RecordInterpolatorFactory(
|
|
||||||
const InterpolatorFactoriesRecord &factories)
|
|
||||||
: PropertyInterpolatorFactory(), factories_(factories) {}
|
|
||||||
|
|
||||||
const CSSValue &getDefaultValue() const override {
|
|
||||||
static EmptyObjectValue emptyObjectValue;
|
|
||||||
return emptyObjectValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<PropertyInterpolator> create(
|
|
||||||
const PropertyPath &propertyPath,
|
|
||||||
const std::shared_ptr<ViewStylesRepository> &viewStylesRepository)
|
|
||||||
const override {
|
|
||||||
return std::make_shared<RecordPropertiesInterpolator>(
|
|
||||||
factories_, propertyPath, viewStylesRepository);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
// Helper private type just for a default value
|
|
||||||
struct EmptyObjectValue : public CSSValue {
|
|
||||||
folly::dynamic toDynamic() const override {
|
|
||||||
return folly::dynamic::object;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string toString() const override {
|
|
||||||
return "{}";
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const InterpolatorFactoriesRecord factories_;
|
|
||||||
};
|
|
||||||
|
|
||||||
class ArrayInterpolatorFactory : public PropertyInterpolatorFactory {
|
|
||||||
public:
|
|
||||||
explicit ArrayInterpolatorFactory(const InterpolatorFactoriesArray &factories)
|
|
||||||
: PropertyInterpolatorFactory(), factories_(factories) {}
|
|
||||||
|
|
||||||
const CSSValue &getDefaultValue() const override {
|
|
||||||
static EmptyArrayValue emptyArrayValue;
|
|
||||||
return emptyArrayValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<PropertyInterpolator> create(
|
|
||||||
const PropertyPath &propertyPath,
|
|
||||||
const std::shared_ptr<ViewStylesRepository> &viewStylesRepository)
|
|
||||||
const override {
|
|
||||||
return std::make_shared<ArrayPropertiesInterpolator>(
|
|
||||||
factories_, propertyPath, viewStylesRepository);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
// Helper private type just for a default value
|
|
||||||
struct EmptyArrayValue : public CSSValue {
|
|
||||||
folly::dynamic toDynamic() const override {
|
|
||||||
return folly::dynamic::array;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string toString() const override {
|
|
||||||
return "[]";
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const InterpolatorFactoriesArray factories_;
|
|
||||||
};
|
|
||||||
|
|
||||||
class TransformsInterpolatorFactory : public PropertyInterpolatorFactory {
|
|
||||||
public:
|
|
||||||
explicit TransformsInterpolatorFactory(
|
|
||||||
const std::shared_ptr<TransformInterpolators> &interpolators)
|
|
||||||
: PropertyInterpolatorFactory(), interpolators_(interpolators) {}
|
|
||||||
|
|
||||||
const CSSValue &getDefaultValue() const override {
|
|
||||||
static EmptyTransformsValue emptyTransformsValue;
|
|
||||||
return emptyTransformsValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<PropertyInterpolator> create(
|
|
||||||
const PropertyPath &propertyPath,
|
|
||||||
const std::shared_ptr<ViewStylesRepository> &viewStylesRepository)
|
|
||||||
const override {
|
|
||||||
return std::make_shared<TransformsStyleInterpolator>(
|
|
||||||
propertyPath, interpolators_, viewStylesRepository);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
static TransformMatrix3D &getIdentityMatrix() {
|
|
||||||
static TransformMatrix3D identityMatrix = TransformMatrix3D::Identity();
|
|
||||||
return identityMatrix;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Helper private type just for a default value
|
|
||||||
struct EmptyTransformsValue : public CSSValue {
|
|
||||||
folly::dynamic toDynamic() const override {
|
|
||||||
return getIdentityMatrix().toDynamic();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string toString() const override {
|
|
||||||
return getIdentityMatrix().toString();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const std::shared_ptr<TransformInterpolators> interpolators_;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Non-template function implementations
|
|
||||||
std::shared_ptr<PropertyInterpolatorFactory> record(
|
|
||||||
const InterpolatorFactoriesRecord &factories) {
|
|
||||||
return std::make_shared<RecordInterpolatorFactory>(factories);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<PropertyInterpolatorFactory> array(
|
|
||||||
const InterpolatorFactoriesArray &factories) {
|
|
||||||
return std::make_shared<ArrayInterpolatorFactory>(factories);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<PropertyInterpolatorFactory> transforms(
|
|
||||||
const std::unordered_map<
|
|
||||||
std::string,
|
|
||||||
std::shared_ptr<TransformInterpolator>> &interpolators) {
|
|
||||||
TransformInterpolators result;
|
|
||||||
for (const auto &[property, interpolator] : interpolators) {
|
|
||||||
result[getTransformOperationType(property)] = interpolator;
|
|
||||||
}
|
|
||||||
return std::make_shared<TransformsInterpolatorFactory>(
|
|
||||||
std::make_shared<TransformInterpolators>(result));
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace reanimated::css
|
|
||||||
Generated
Vendored
-194
@@ -1,194 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <reanimated/CSS/interpolation/PropertyInterpolator.h>
|
|
||||||
|
|
||||||
#include <reanimated/CSS/interpolation/groups/ArrayPropertiesInterpolator.h>
|
|
||||||
#include <reanimated/CSS/interpolation/groups/RecordPropertiesInterpolator.h>
|
|
||||||
|
|
||||||
#include <reanimated/CSS/interpolation/transforms/TransformOperation.h>
|
|
||||||
#include <reanimated/CSS/interpolation/transforms/TransformOperationInterpolator.h>
|
|
||||||
#include <reanimated/CSS/interpolation/transforms/TransformsStyleInterpolator.h>
|
|
||||||
#include <reanimated/CSS/interpolation/values/ResolvableValueInterpolator.h>
|
|
||||||
#include <reanimated/CSS/interpolation/values/SimpleValueInterpolator.h>
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <string>
|
|
||||||
#include <unordered_map>
|
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
namespace reanimated::css {
|
|
||||||
|
|
||||||
// Template class implementations
|
|
||||||
template <typename... AllowedTypes>
|
|
||||||
class SimpleValueInterpolatorFactory : public PropertyInterpolatorFactory {
|
|
||||||
public:
|
|
||||||
template <typename TValue>
|
|
||||||
explicit SimpleValueInterpolatorFactory(const TValue &defaultValue)
|
|
||||||
: PropertyInterpolatorFactory(), defaultValue_(defaultValue) {}
|
|
||||||
|
|
||||||
bool isDiscreteProperty() const override {
|
|
||||||
// The property is considered discrete if all of the allowed types are
|
|
||||||
// discrete
|
|
||||||
return (Discrete<AllowedTypes> && ...);
|
|
||||||
}
|
|
||||||
|
|
||||||
const CSSValue &getDefaultValue() const override {
|
|
||||||
return defaultValue_;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<PropertyInterpolator> create(
|
|
||||||
const PropertyPath &propertyPath,
|
|
||||||
const std::shared_ptr<ViewStylesRepository> &viewStylesRepository)
|
|
||||||
const override {
|
|
||||||
return std::make_shared<SimpleValueInterpolator<AllowedTypes...>>(
|
|
||||||
propertyPath, defaultValue_, viewStylesRepository);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
const CSSValueVariant<AllowedTypes...> defaultValue_;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename... AllowedTypes>
|
|
||||||
class ResolvableValueInterpolatorFactory : public PropertyInterpolatorFactory {
|
|
||||||
public:
|
|
||||||
template <typename TValue>
|
|
||||||
explicit ResolvableValueInterpolatorFactory(
|
|
||||||
RelativeTo relativeTo,
|
|
||||||
const std::string &relativeProperty,
|
|
||||||
const TValue &defaultValue)
|
|
||||||
: PropertyInterpolatorFactory(),
|
|
||||||
relativeTo_(relativeTo),
|
|
||||||
relativeProperty_(relativeProperty),
|
|
||||||
defaultValue_(defaultValue) {}
|
|
||||||
|
|
||||||
const CSSValue &getDefaultValue() const override {
|
|
||||||
return defaultValue_;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<PropertyInterpolator> create(
|
|
||||||
const PropertyPath &propertyPath,
|
|
||||||
const std::shared_ptr<ViewStylesRepository> &viewStylesRepository)
|
|
||||||
const override {
|
|
||||||
return std::make_shared<ResolvableValueInterpolator<AllowedTypes...>>(
|
|
||||||
propertyPath,
|
|
||||||
defaultValue_,
|
|
||||||
viewStylesRepository,
|
|
||||||
relativeTo_,
|
|
||||||
relativeProperty_);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
const RelativeTo relativeTo_;
|
|
||||||
const std::string relativeProperty_;
|
|
||||||
const CSSValueVariant<AllowedTypes...> defaultValue_;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper function to create a concrete CSSValue from defaultValue
|
|
||||||
*/
|
|
||||||
template <typename... AllowedTypes>
|
|
||||||
CSSValueVariant<AllowedTypes...> createCSSValue(const auto &defaultValue) {
|
|
||||||
using ValueType = decltype(defaultValue);
|
|
||||||
CSSValueVariant<AllowedTypes...> result;
|
|
||||||
|
|
||||||
auto tryOne = [&]<typename TCSSValue>() -> bool {
|
|
||||||
if constexpr (std::is_constructible_v<TCSSValue, ValueType>) {
|
|
||||||
if constexpr (ValueConstructibleCSSValue<TCSSValue, ValueType>) {
|
|
||||||
// For construction from a non-jsi::Value, we perform a runtime
|
|
||||||
// canConstruct check only if the type has a canConstruct method.
|
|
||||||
// (this is needed e.g. when different CSS value types can be
|
|
||||||
// constructed from the same value type, like CSSLength and CSSKeyword)
|
|
||||||
if (!TCSSValue::canConstruct(defaultValue)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
result = CSSValueVariant<AllowedTypes...>(
|
|
||||||
std::variant<AllowedTypes...>(TCSSValue(defaultValue)));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Try constructing with each allowed type until one succeeds
|
|
||||||
if (!(tryOne.template operator()<AllowedTypes>() || ...)) {
|
|
||||||
throw std::runtime_error(
|
|
||||||
"[Reanimated] No compatible type found for construction from defaultValue");
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Value interpolator factories
|
|
||||||
*/
|
|
||||||
template <typename... AllowedTypes>
|
|
||||||
auto value(const auto &defaultValue) -> std::enable_if_t<
|
|
||||||
(std::is_constructible_v<AllowedTypes, decltype(defaultValue)> || ...),
|
|
||||||
std::shared_ptr<PropertyInterpolatorFactory>> {
|
|
||||||
// Create a concrete CSSValue from the defaultValue
|
|
||||||
auto cssValue = createCSSValue<AllowedTypes...>(defaultValue);
|
|
||||||
return std::make_shared<SimpleValueInterpolatorFactory<AllowedTypes...>>(
|
|
||||||
std::move(cssValue));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename... AllowedTypes>
|
|
||||||
auto value(
|
|
||||||
RelativeTo relativeTo,
|
|
||||||
const std::string &relativeProperty,
|
|
||||||
const auto &defaultValue)
|
|
||||||
-> std::enable_if_t<
|
|
||||||
(std::is_constructible_v<AllowedTypes, decltype(defaultValue)> || ...),
|
|
||||||
std::shared_ptr<PropertyInterpolatorFactory>> {
|
|
||||||
// Create a concrete CSSValue from the defaultValue
|
|
||||||
auto cssValue = createCSSValue<AllowedTypes...>(defaultValue);
|
|
||||||
return std::make_shared<ResolvableValueInterpolatorFactory<AllowedTypes...>>(
|
|
||||||
relativeTo, relativeProperty, std::move(cssValue));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Transform operation interpolator factories
|
|
||||||
*/
|
|
||||||
template <typename TOperation>
|
|
||||||
auto transformOp(const auto &defaultValue) -> std::enable_if_t<
|
|
||||||
std::is_base_of_v<TransformOperation, TOperation> &&
|
|
||||||
std::is_constructible_v<TOperation, decltype(defaultValue)>,
|
|
||||||
std::shared_ptr<TransformInterpolator>> {
|
|
||||||
return std::make_shared<TransformOperationInterpolator<TOperation>>(
|
|
||||||
std::make_shared<TOperation>(defaultValue));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename TOperation>
|
|
||||||
auto transformOp(
|
|
||||||
RelativeTo relativeTo,
|
|
||||||
const std::string &relativeProperty,
|
|
||||||
const auto &defaultValue)
|
|
||||||
-> std::enable_if_t<
|
|
||||||
std::is_base_of_v<TransformOperation, TOperation> &&
|
|
||||||
std::is_constructible_v<TOperation, decltype(defaultValue)> &&
|
|
||||||
ResolvableOperation<TOperation>,
|
|
||||||
std::shared_ptr<TransformInterpolator>> {
|
|
||||||
return std::make_shared<TransformOperationInterpolator<TOperation>>(
|
|
||||||
std::make_shared<TOperation>(defaultValue), relativeTo, relativeProperty);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Record property interpolator factory
|
|
||||||
*/
|
|
||||||
std::shared_ptr<PropertyInterpolatorFactory> record(
|
|
||||||
const InterpolatorFactoriesRecord &factories);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Array property interpolator factory
|
|
||||||
*/
|
|
||||||
std::shared_ptr<PropertyInterpolatorFactory> array(
|
|
||||||
const InterpolatorFactoriesArray &factories);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Transform interpolators
|
|
||||||
*/
|
|
||||||
std::shared_ptr<PropertyInterpolatorFactory> transforms(
|
|
||||||
const std::unordered_map<
|
|
||||||
std::string,
|
|
||||||
std::shared_ptr<TransformInterpolator>> &interpolators);
|
|
||||||
|
|
||||||
} // namespace reanimated::css
|
|
||||||
Generated
Vendored
-17
@@ -1,17 +0,0 @@
|
|||||||
#include <reanimated/CSS/interpolation/PropertyInterpolator.h>
|
|
||||||
|
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
namespace reanimated::css {
|
|
||||||
|
|
||||||
PropertyInterpolator::PropertyInterpolator(
|
|
||||||
PropertyPath propertyPath,
|
|
||||||
const std::shared_ptr<ViewStylesRepository> &viewStylesRepository)
|
|
||||||
: propertyPath_(std::move(propertyPath)),
|
|
||||||
viewStylesRepository_(viewStylesRepository) {}
|
|
||||||
|
|
||||||
bool PropertyInterpolatorFactory::isDiscreteProperty() const {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace reanimated::css
|
|
||||||
Generated
Vendored
-72
@@ -1,72 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <reanimated/CSS/common/definitions.h>
|
|
||||||
#include <reanimated/CSS/common/values/CSSValue.h>
|
|
||||||
#include <reanimated/CSS/misc/ViewStylesRepository.h>
|
|
||||||
#include <reanimated/CSS/progress/KeyframeProgressProvider.h>
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <string>
|
|
||||||
#include <unordered_map>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace reanimated::css {
|
|
||||||
|
|
||||||
class PropertyInterpolator {
|
|
||||||
public:
|
|
||||||
explicit PropertyInterpolator(
|
|
||||||
PropertyPath propertyPath,
|
|
||||||
const std::shared_ptr<ViewStylesRepository> &viewStylesRepository);
|
|
||||||
|
|
||||||
virtual folly::dynamic getStyleValue(
|
|
||||||
const std::shared_ptr<const ShadowNode> &shadowNode) const = 0;
|
|
||||||
virtual folly::dynamic getResetStyle(
|
|
||||||
const std::shared_ptr<const ShadowNode> &shadowNode) const = 0;
|
|
||||||
virtual folly::dynamic getFirstKeyframeValue() const = 0;
|
|
||||||
virtual folly::dynamic getLastKeyframeValue() const = 0;
|
|
||||||
virtual bool equalsReversingAdjustedStartValue(
|
|
||||||
const folly::dynamic &propertyValue) const = 0;
|
|
||||||
|
|
||||||
virtual void updateKeyframes(
|
|
||||||
jsi::Runtime &rt,
|
|
||||||
const jsi::Value &keyframes) = 0;
|
|
||||||
virtual void updateKeyframesFromStyleChange(
|
|
||||||
const folly::dynamic &oldStyleValue,
|
|
||||||
const folly::dynamic &newStyleValue,
|
|
||||||
const folly::dynamic &lastUpdateValue) = 0;
|
|
||||||
|
|
||||||
virtual folly::dynamic interpolate(
|
|
||||||
const std::shared_ptr<const ShadowNode> &shadowNode,
|
|
||||||
const std::shared_ptr<KeyframeProgressProvider> &progressProvider)
|
|
||||||
const = 0;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
const PropertyPath propertyPath_;
|
|
||||||
const std::shared_ptr<ViewStylesRepository> viewStylesRepository_;
|
|
||||||
};
|
|
||||||
|
|
||||||
class PropertyInterpolatorFactory {
|
|
||||||
public:
|
|
||||||
PropertyInterpolatorFactory() = default;
|
|
||||||
virtual ~PropertyInterpolatorFactory() = default;
|
|
||||||
|
|
||||||
virtual bool isDiscreteProperty() const;
|
|
||||||
virtual const CSSValue &getDefaultValue() const = 0;
|
|
||||||
|
|
||||||
virtual std::shared_ptr<PropertyInterpolator> create(
|
|
||||||
const PropertyPath &propertyPath,
|
|
||||||
const std::shared_ptr<ViewStylesRepository> &viewStylesRepository)
|
|
||||||
const = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
using PropertyInterpolatorsRecord =
|
|
||||||
std::unordered_map<std::string, std::shared_ptr<PropertyInterpolator>>;
|
|
||||||
using InterpolatorFactoriesRecord = std::
|
|
||||||
unordered_map<std::string, std::shared_ptr<PropertyInterpolatorFactory>>;
|
|
||||||
|
|
||||||
using PropertyInterpolatorsArray =
|
|
||||||
std::vector<std::shared_ptr<PropertyInterpolator>>;
|
|
||||||
using InterpolatorFactoriesArray =
|
|
||||||
std::vector<std::shared_ptr<PropertyInterpolatorFactory>>;
|
|
||||||
|
|
||||||
} // namespace reanimated::css
|
|
||||||
Generated
Vendored
-107
@@ -1,107 +0,0 @@
|
|||||||
#include <reanimated/CSS/interpolation/groups/ArrayPropertiesInterpolator.h>
|
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
namespace reanimated::css {
|
|
||||||
|
|
||||||
ArrayPropertiesInterpolator::ArrayPropertiesInterpolator(
|
|
||||||
const InterpolatorFactoriesArray &factories,
|
|
||||||
const PropertyPath &propertyPath,
|
|
||||||
const std::shared_ptr<ViewStylesRepository> &viewStylesRepository)
|
|
||||||
: GroupPropertiesInterpolator(propertyPath, viewStylesRepository),
|
|
||||||
factories_(factories) {}
|
|
||||||
|
|
||||||
bool ArrayPropertiesInterpolator::equalsReversingAdjustedStartValue(
|
|
||||||
const folly::dynamic &propertyValue) const {
|
|
||||||
if (!propertyValue.isArray()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto valuesCount = propertyValue.size();
|
|
||||||
if (valuesCount != interpolators_.size()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i = 0; i < valuesCount; ++i) {
|
|
||||||
if (!interpolators_[i]->equalsReversingAdjustedStartValue(
|
|
||||||
propertyValue[i])) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ArrayPropertiesInterpolator::updateKeyframes(
|
|
||||||
jsi::Runtime &rt,
|
|
||||||
const jsi::Value &keyframes) {
|
|
||||||
const jsi::Array keyframesArray = keyframes.asObject(rt).asArray(rt);
|
|
||||||
const size_t valuesCount = keyframesArray.size(rt);
|
|
||||||
|
|
||||||
resizeInterpolators(valuesCount);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < valuesCount; ++i) {
|
|
||||||
interpolators_[i]->updateKeyframes(
|
|
||||||
rt, keyframesArray.getValueAtIndex(rt, i));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ArrayPropertiesInterpolator::updateKeyframesFromStyleChange(
|
|
||||||
const folly::dynamic &oldStyleValue,
|
|
||||||
const folly::dynamic &newStyleValue,
|
|
||||||
const folly::dynamic &lastUpdateValue) {
|
|
||||||
const auto emptyArray = folly::dynamic::array();
|
|
||||||
const auto null = folly::dynamic();
|
|
||||||
|
|
||||||
const auto &oldStyleArray =
|
|
||||||
oldStyleValue.empty() ? emptyArray : oldStyleValue;
|
|
||||||
const auto &newStyleArray =
|
|
||||||
newStyleValue.empty() ? emptyArray : newStyleValue;
|
|
||||||
const auto &lastUpdateArray =
|
|
||||||
lastUpdateValue.empty() ? emptyArray : lastUpdateValue;
|
|
||||||
|
|
||||||
const size_t oldSize = oldStyleArray.size();
|
|
||||||
const size_t newSize = newStyleArray.size();
|
|
||||||
const size_t lastSize = lastUpdateArray.size();
|
|
||||||
const size_t valuesCount = std::max(oldSize, newSize);
|
|
||||||
|
|
||||||
resizeInterpolators(valuesCount);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < valuesCount; ++i) {
|
|
||||||
// These index checks ensure that interpolation works between 2 arrays
|
|
||||||
// with different lengths
|
|
||||||
interpolators_[i]->updateKeyframesFromStyleChange(
|
|
||||||
i < oldSize ? oldStyleArray[i] : null,
|
|
||||||
i < newSize ? newStyleArray[i] : null,
|
|
||||||
i < lastSize ? lastUpdateArray[i] : null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
folly::dynamic ArrayPropertiesInterpolator::mapInterpolators(
|
|
||||||
const std::function<folly::dynamic(PropertyInterpolator &)> &callback)
|
|
||||||
const {
|
|
||||||
auto result = folly::dynamic::array();
|
|
||||||
|
|
||||||
for (size_t i = 0; i < interpolators_.size(); ++i) {
|
|
||||||
result.push_back(callback(*interpolators_[i]));
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ArrayPropertiesInterpolator::resizeInterpolators(size_t valuesCount) {
|
|
||||||
// Remove excess interpolators if the array size has decreased
|
|
||||||
if (interpolators_.size() > valuesCount) {
|
|
||||||
interpolators_.resize(valuesCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
while (interpolators_.size() < valuesCount) {
|
|
||||||
interpolators_.emplace_back(createPropertyInterpolator(
|
|
||||||
interpolators_.size(),
|
|
||||||
propertyPath_,
|
|
||||||
factories_,
|
|
||||||
viewStylesRepository_));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace reanimated::css
|
|
||||||
Generated
Vendored
-39
@@ -1,39 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <reanimated/CSS/interpolation/groups/GroupPropertiesInterpolator.h>
|
|
||||||
#include <reanimated/CSS/utils/interpolators.h>
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
namespace reanimated::css {
|
|
||||||
|
|
||||||
class ArrayPropertiesInterpolator : public GroupPropertiesInterpolator {
|
|
||||||
public:
|
|
||||||
ArrayPropertiesInterpolator(
|
|
||||||
const InterpolatorFactoriesArray &factories,
|
|
||||||
const PropertyPath &propertyPath,
|
|
||||||
const std::shared_ptr<ViewStylesRepository> &viewStylesRepository);
|
|
||||||
virtual ~ArrayPropertiesInterpolator() = default;
|
|
||||||
|
|
||||||
bool equalsReversingAdjustedStartValue(
|
|
||||||
const folly::dynamic &propertyValue) const override;
|
|
||||||
|
|
||||||
void updateKeyframes(jsi::Runtime &rt, const jsi::Value &keyframes) override;
|
|
||||||
void updateKeyframesFromStyleChange(
|
|
||||||
const folly::dynamic &oldStyleValue,
|
|
||||||
const folly::dynamic &newStyleValue,
|
|
||||||
const folly::dynamic &lastUpdateValue) override;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
folly::dynamic mapInterpolators(
|
|
||||||
const std::function<folly::dynamic(PropertyInterpolator &)> &callback)
|
|
||||||
const override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
const InterpolatorFactoriesArray &factories_;
|
|
||||||
PropertyInterpolatorsArray interpolators_;
|
|
||||||
|
|
||||||
void resizeInterpolators(size_t valuesCount);
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace reanimated::css
|
|
||||||
Generated
Vendored
-49
@@ -1,49 +0,0 @@
|
|||||||
#include <reanimated/CSS/interpolation/groups/GroupPropertiesInterpolator.h>
|
|
||||||
|
|
||||||
namespace reanimated::css {
|
|
||||||
|
|
||||||
GroupPropertiesInterpolator::GroupPropertiesInterpolator(
|
|
||||||
const PropertyPath &propertyPath,
|
|
||||||
const std::shared_ptr<ViewStylesRepository> &viewStylesRepository)
|
|
||||||
: PropertyInterpolator(propertyPath, viewStylesRepository) {}
|
|
||||||
|
|
||||||
folly::dynamic GroupPropertiesInterpolator::getStyleValue(
|
|
||||||
const std::shared_ptr<const ShadowNode> &shadowNode) const {
|
|
||||||
return mapInterpolators(
|
|
||||||
[&](PropertyInterpolator &interpolator) -> folly::dynamic {
|
|
||||||
return interpolator.getStyleValue(shadowNode);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
folly::dynamic GroupPropertiesInterpolator::getResetStyle(
|
|
||||||
const std::shared_ptr<const ShadowNode> &shadowNode) const {
|
|
||||||
return mapInterpolators(
|
|
||||||
[&](PropertyInterpolator &interpolator) -> folly::dynamic {
|
|
||||||
return interpolator.getResetStyle(shadowNode);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
folly::dynamic GroupPropertiesInterpolator::getFirstKeyframeValue() const {
|
|
||||||
return mapInterpolators(
|
|
||||||
[&](PropertyInterpolator &interpolator) -> folly::dynamic {
|
|
||||||
return interpolator.getFirstKeyframeValue();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
folly::dynamic GroupPropertiesInterpolator::getLastKeyframeValue() const {
|
|
||||||
return mapInterpolators(
|
|
||||||
[&](PropertyInterpolator &interpolator) -> folly::dynamic {
|
|
||||||
return interpolator.getLastKeyframeValue();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
folly::dynamic GroupPropertiesInterpolator::interpolate(
|
|
||||||
const std::shared_ptr<const ShadowNode> &shadowNode,
|
|
||||||
const std::shared_ptr<KeyframeProgressProvider> &progressProvider) const {
|
|
||||||
return mapInterpolators(
|
|
||||||
[&](PropertyInterpolator &interpolator) -> folly::dynamic {
|
|
||||||
return interpolator.interpolate(shadowNode, progressProvider);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace reanimated::css
|
|
||||||
Generated
Vendored
-35
@@ -1,35 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <reanimated/CSS/interpolation/PropertyInterpolator.h>
|
|
||||||
#include <reanimated/CSS/misc/ViewStylesRepository.h>
|
|
||||||
#include <reanimated/CSS/progress/KeyframeProgressProvider.h>
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
namespace reanimated::css {
|
|
||||||
|
|
||||||
class GroupPropertiesInterpolator : public PropertyInterpolator {
|
|
||||||
public:
|
|
||||||
GroupPropertiesInterpolator(
|
|
||||||
const PropertyPath &propertyPath,
|
|
||||||
const std::shared_ptr<ViewStylesRepository> &viewStylesRepository);
|
|
||||||
|
|
||||||
folly::dynamic getStyleValue(
|
|
||||||
const std::shared_ptr<const ShadowNode> &shadowNode) const override;
|
|
||||||
folly::dynamic getResetStyle(
|
|
||||||
const std::shared_ptr<const ShadowNode> &shadowNode) const override;
|
|
||||||
folly::dynamic getFirstKeyframeValue() const override;
|
|
||||||
folly::dynamic getLastKeyframeValue() const override;
|
|
||||||
|
|
||||||
folly::dynamic interpolate(
|
|
||||||
const std::shared_ptr<const ShadowNode> &shadowNode,
|
|
||||||
const std::shared_ptr<KeyframeProgressProvider> &progressProvider)
|
|
||||||
const override;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual folly::dynamic mapInterpolators(
|
|
||||||
const std::function<folly::dynamic(PropertyInterpolator &)> &callback)
|
|
||||||
const = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace reanimated::css
|
|
||||||
Generated
Vendored
-102
@@ -1,102 +0,0 @@
|
|||||||
#include <reanimated/CSS/interpolation/groups/RecordPropertiesInterpolator.h>
|
|
||||||
|
|
||||||
#include <unordered_set>
|
|
||||||
|
|
||||||
namespace reanimated::css {
|
|
||||||
|
|
||||||
RecordPropertiesInterpolator::RecordPropertiesInterpolator(
|
|
||||||
const InterpolatorFactoriesRecord &factories,
|
|
||||||
const PropertyPath &propertyPath,
|
|
||||||
const std::shared_ptr<ViewStylesRepository> &viewStylesRepository)
|
|
||||||
: GroupPropertiesInterpolator(propertyPath, viewStylesRepository),
|
|
||||||
factories_(factories) {}
|
|
||||||
|
|
||||||
bool RecordPropertiesInterpolator::equalsReversingAdjustedStartValue(
|
|
||||||
const folly::dynamic &propertyValue) const {
|
|
||||||
return std::ranges::all_of(propertyValue.items(), [this](const auto &item) {
|
|
||||||
const auto &[propName, propValue] = item;
|
|
||||||
const auto it = interpolators_.find(propName.getString());
|
|
||||||
return it != interpolators_.end() &&
|
|
||||||
it->second->equalsReversingAdjustedStartValue(propValue);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void RecordPropertiesInterpolator::updateKeyframes(
|
|
||||||
jsi::Runtime &rt,
|
|
||||||
const jsi::Value &keyframes) {
|
|
||||||
// TODO - maybe add a possibility to remove interpolators that are no longer
|
|
||||||
// used (for now, for simplicity, we only add new ones)
|
|
||||||
const jsi::Object keyframesObject = keyframes.asObject(rt);
|
|
||||||
|
|
||||||
jsi::Array propertyNames = keyframesObject.getPropertyNames(rt);
|
|
||||||
size_t propertiesCount = propertyNames.size(rt);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < propertiesCount; ++i) {
|
|
||||||
const std::string propertyName =
|
|
||||||
propertyNames.getValueAtIndex(rt, i).asString(rt).utf8(rt);
|
|
||||||
const jsi::Value &propertyKeyframes = keyframesObject.getProperty(
|
|
||||||
rt, jsi::PropNameID::forUtf8(rt, propertyName));
|
|
||||||
|
|
||||||
maybeCreateInterpolator(propertyName);
|
|
||||||
interpolators_[propertyName]->updateKeyframes(rt, propertyKeyframes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void RecordPropertiesInterpolator::updateKeyframesFromStyleChange(
|
|
||||||
const folly::dynamic &oldStyleValue,
|
|
||||||
const folly::dynamic &newStyleValue,
|
|
||||||
const folly::dynamic &lastUpdateValue) {
|
|
||||||
// TODO - maybe add a possibility to remove interpolators that are no longer
|
|
||||||
// used (for now, for simplicity, we only add new ones)
|
|
||||||
const folly::dynamic emptyObject = folly::dynamic::object();
|
|
||||||
const auto null = folly::dynamic();
|
|
||||||
|
|
||||||
const auto &oldStyleObject =
|
|
||||||
oldStyleValue.empty() ? emptyObject : oldStyleValue;
|
|
||||||
const auto &newStyleObject =
|
|
||||||
newStyleValue.empty() ? emptyObject : newStyleValue;
|
|
||||||
const auto &lastUpdateObject =
|
|
||||||
lastUpdateValue.empty() ? emptyObject : lastUpdateValue;
|
|
||||||
|
|
||||||
std::unordered_set<std::string> propertyNamesSet;
|
|
||||||
for (const auto &key : oldStyleObject.keys()) {
|
|
||||||
propertyNamesSet.insert(key.asString());
|
|
||||||
}
|
|
||||||
for (const auto &key : newStyleObject.keys()) {
|
|
||||||
propertyNamesSet.insert(key.asString());
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const auto &propertyName : propertyNamesSet) {
|
|
||||||
maybeCreateInterpolator(propertyName);
|
|
||||||
interpolators_[propertyName]->updateKeyframesFromStyleChange(
|
|
||||||
oldStyleObject.getDefault(propertyName, null),
|
|
||||||
newStyleObject.getDefault(propertyName, null),
|
|
||||||
lastUpdateObject.getDefault(propertyName, null));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
folly::dynamic RecordPropertiesInterpolator::mapInterpolators(
|
|
||||||
const std::function<folly::dynamic(PropertyInterpolator &)> &callback)
|
|
||||||
const {
|
|
||||||
folly::dynamic result = folly::dynamic::object;
|
|
||||||
|
|
||||||
for (const auto &[propertyName, interpolator] : interpolators_) {
|
|
||||||
const auto value = callback(*interpolator);
|
|
||||||
if (!value.isNull()) {
|
|
||||||
result[propertyName] = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void RecordPropertiesInterpolator::maybeCreateInterpolator(
|
|
||||||
const std::string &propertyName) {
|
|
||||||
if (interpolators_.find(propertyName) == interpolators_.end()) {
|
|
||||||
const auto newInterpolator = createPropertyInterpolator(
|
|
||||||
propertyName, propertyPath_, factories_, viewStylesRepository_);
|
|
||||||
interpolators_.emplace(propertyName, newInterpolator);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace reanimated::css
|
|
||||||
Generated
Vendored
-40
@@ -1,40 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <reanimated/CSS/interpolation/groups/GroupPropertiesInterpolator.h>
|
|
||||||
#include <reanimated/CSS/utils/interpolators.h>
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
namespace reanimated::css {
|
|
||||||
|
|
||||||
class RecordPropertiesInterpolator : public GroupPropertiesInterpolator {
|
|
||||||
public:
|
|
||||||
RecordPropertiesInterpolator(
|
|
||||||
const InterpolatorFactoriesRecord &factories,
|
|
||||||
const PropertyPath &propertyPath,
|
|
||||||
const std::shared_ptr<ViewStylesRepository> &viewStylesRepository);
|
|
||||||
virtual ~RecordPropertiesInterpolator() = default;
|
|
||||||
|
|
||||||
bool equalsReversingAdjustedStartValue(
|
|
||||||
const folly::dynamic &propertyValue) const override;
|
|
||||||
|
|
||||||
void updateKeyframes(jsi::Runtime &rt, const jsi::Value &keyframes) override;
|
|
||||||
void updateKeyframesFromStyleChange(
|
|
||||||
const folly::dynamic &oldStyleValue,
|
|
||||||
const folly::dynamic &newStyleValue,
|
|
||||||
const folly::dynamic &lastUpdateValue) override;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
folly::dynamic mapInterpolators(
|
|
||||||
const std::function<folly::dynamic(PropertyInterpolator &)> &callback)
|
|
||||||
const override;
|
|
||||||
|
|
||||||
void maybeCreateInterpolator(const std::string &propertyName);
|
|
||||||
|
|
||||||
private:
|
|
||||||
const InterpolatorFactoriesRecord &factories_;
|
|
||||||
PropertyInterpolatorsRecord interpolators_;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace reanimated::css
|
|
||||||
Generated
Vendored
-29
@@ -1,29 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <reanimated/CSS/InterpolatorRegistry.h>
|
|
||||||
#include <reanimated/CSS/interpolation/groups/RecordPropertiesInterpolator.h>
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
namespace reanimated::css {
|
|
||||||
|
|
||||||
// We can just re-use the logic from the RecordPropertiesInterpolator class as
|
|
||||||
// interpolating multiple properties from the view style during animation is the
|
|
||||||
// same as interpolating record properties
|
|
||||||
class AnimationStyleInterpolator : public RecordPropertiesInterpolator {
|
|
||||||
public:
|
|
||||||
explicit AnimationStyleInterpolator(
|
|
||||||
jsi::Runtime &rt,
|
|
||||||
const jsi::Value &keyframes,
|
|
||||||
const std::string &componentName,
|
|
||||||
const std::shared_ptr<ViewStylesRepository> &viewStylesRepository)
|
|
||||||
: RecordPropertiesInterpolator(
|
|
||||||
getComponentInterpolators(componentName),
|
|
||||||
{},
|
|
||||||
viewStylesRepository) {
|
|
||||||
updateKeyframes(rt, keyframes);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace reanimated::css
|
|
||||||
Generated
Vendored
-115
@@ -1,115 +0,0 @@
|
|||||||
#include <reanimated/CSS/interpolation/styles/TransitionStyleInterpolator.h>
|
|
||||||
|
|
||||||
namespace reanimated::css {
|
|
||||||
|
|
||||||
TransitionStyleInterpolator::TransitionStyleInterpolator(
|
|
||||||
const std::string &componentName,
|
|
||||||
const std::shared_ptr<ViewStylesRepository> &viewStylesRepository)
|
|
||||||
: componentName_(componentName),
|
|
||||||
viewStylesRepository_(viewStylesRepository) {}
|
|
||||||
|
|
||||||
std::unordered_set<std::string>
|
|
||||||
TransitionStyleInterpolator::getReversedPropertyNames(
|
|
||||||
const folly::dynamic &newPropertyValues) const {
|
|
||||||
std::unordered_set<std::string> reversedProperties;
|
|
||||||
|
|
||||||
if (!newPropertyValues.isObject()) {
|
|
||||||
return reversedProperties;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const auto &[propertyName, propertyValue] : newPropertyValues.items()) {
|
|
||||||
const auto propertyNameStr = propertyName.getString();
|
|
||||||
const auto it = interpolators_.find(propertyNameStr);
|
|
||||||
if (it != interpolators_.end() &&
|
|
||||||
// First keyframe value of the previous transition is the reversing
|
|
||||||
// adjusted start value
|
|
||||||
it->second->equalsReversingAdjustedStartValue(propertyValue)) {
|
|
||||||
reversedProperties.insert(propertyNameStr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return reversedProperties;
|
|
||||||
}
|
|
||||||
|
|
||||||
folly::dynamic TransitionStyleInterpolator::interpolate(
|
|
||||||
const std::shared_ptr<const ShadowNode> &shadowNode,
|
|
||||||
const TransitionProgressProvider &transitionProgressProvider) const {
|
|
||||||
return mapInterpolators(
|
|
||||||
transitionProgressProvider,
|
|
||||||
[&](const std::shared_ptr<PropertyInterpolator> &interpolator,
|
|
||||||
const std::shared_ptr<KeyframeProgressProvider> &progressProvider) {
|
|
||||||
return interpolator->interpolate(shadowNode, progressProvider);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void TransitionStyleInterpolator::discardFinishedInterpolators(
|
|
||||||
const TransitionProgressProvider &transitionProgressProvider) {
|
|
||||||
for (const auto &propertyName :
|
|
||||||
transitionProgressProvider.getRemovedProperties()) {
|
|
||||||
interpolators_.erase(propertyName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void TransitionStyleInterpolator::discardIrrelevantInterpolators(
|
|
||||||
const std::unordered_set<std::string> &transitionPropertyNames) {
|
|
||||||
for (auto it = interpolators_.begin(); it != interpolators_.end();) {
|
|
||||||
// Remove property interpolators for properties not specified in the
|
|
||||||
// transition property names
|
|
||||||
if (transitionPropertyNames.find(it->first) ==
|
|
||||||
transitionPropertyNames.end()) {
|
|
||||||
it = interpolators_.erase(it);
|
|
||||||
} else {
|
|
||||||
++it;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void TransitionStyleInterpolator::updateInterpolatedProperties(
|
|
||||||
const ChangedProps &changedProps,
|
|
||||||
const folly::dynamic &lastUpdateValue) {
|
|
||||||
const auto &oldPropsObj = changedProps.oldProps;
|
|
||||||
const auto &newPropsObj = changedProps.newProps;
|
|
||||||
|
|
||||||
const auto empty = folly::dynamic();
|
|
||||||
|
|
||||||
for (const auto &propertyName : changedProps.changedPropertyNames) {
|
|
||||||
auto it = interpolators_.find(propertyName);
|
|
||||||
const auto shouldCreateInterpolator = it == interpolators_.end();
|
|
||||||
|
|
||||||
if (shouldCreateInterpolator) {
|
|
||||||
const auto newInterpolator = createPropertyInterpolator(
|
|
||||||
propertyName,
|
|
||||||
{},
|
|
||||||
getComponentInterpolators(componentName_),
|
|
||||||
viewStylesRepository_);
|
|
||||||
it = interpolators_.emplace(propertyName, newInterpolator).first;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto &oldValue = oldPropsObj.getDefault(propertyName, empty);
|
|
||||||
const auto &newValue = newPropsObj.getDefault(propertyName, empty);
|
|
||||||
// Pass lastValue only if the interpolator is updated (no new interpolator
|
|
||||||
// was created), otherwise pass an empty value
|
|
||||||
const auto &lastValue =
|
|
||||||
(shouldCreateInterpolator || lastUpdateValue.empty())
|
|
||||||
? empty
|
|
||||||
: lastUpdateValue.getDefault(propertyName, empty);
|
|
||||||
|
|
||||||
it->second->updateKeyframesFromStyleChange(oldValue, newValue, lastValue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
folly::dynamic TransitionStyleInterpolator::mapInterpolators(
|
|
||||||
const TransitionProgressProvider &transitionProgressProvider,
|
|
||||||
const MapInterpolatorsCallback &callback) const {
|
|
||||||
folly::dynamic result = folly::dynamic::object;
|
|
||||||
|
|
||||||
for (const auto &[propertyName, progressProvider] :
|
|
||||||
transitionProgressProvider.getPropertyProgressProviders()) {
|
|
||||||
result[propertyName] =
|
|
||||||
callback(interpolators_.at(propertyName), progressProvider);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace reanimated::css
|
|
||||||
Generated
Vendored
-51
@@ -1,51 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <reanimated/CSS/InterpolatorRegistry.h>
|
|
||||||
#include <reanimated/CSS/common/definitions.h>
|
|
||||||
#include <reanimated/CSS/interpolation/groups/RecordPropertiesInterpolator.h>
|
|
||||||
#include <reanimated/CSS/progress/TransitionProgressProvider.h>
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <string>
|
|
||||||
#include <unordered_map>
|
|
||||||
#include <unordered_set>
|
|
||||||
|
|
||||||
namespace reanimated::css {
|
|
||||||
|
|
||||||
class TransitionStyleInterpolator {
|
|
||||||
public:
|
|
||||||
TransitionStyleInterpolator(
|
|
||||||
const std::string &componentName,
|
|
||||||
const std::shared_ptr<ViewStylesRepository> &viewStylesRepository);
|
|
||||||
|
|
||||||
std::unordered_set<std::string> getReversedPropertyNames(
|
|
||||||
const folly::dynamic &newPropertyValues) const;
|
|
||||||
|
|
||||||
folly::dynamic interpolate(
|
|
||||||
const std::shared_ptr<const ShadowNode> &shadowNode,
|
|
||||||
const TransitionProgressProvider &transitionProgressProvider) const;
|
|
||||||
|
|
||||||
void discardFinishedInterpolators(
|
|
||||||
const TransitionProgressProvider &transitionProgressProvider);
|
|
||||||
void discardIrrelevantInterpolators(
|
|
||||||
const std::unordered_set<std::string> &transitionPropertyNames);
|
|
||||||
void updateInterpolatedProperties(
|
|
||||||
const ChangedProps &changedProps,
|
|
||||||
const folly::dynamic &lastUpdateValue);
|
|
||||||
|
|
||||||
private:
|
|
||||||
using MapInterpolatorsCallback = std::function<folly::dynamic(
|
|
||||||
const std::shared_ptr<PropertyInterpolator> &,
|
|
||||||
const std::shared_ptr<KeyframeProgressProvider> &)>;
|
|
||||||
|
|
||||||
const std::string componentName_;
|
|
||||||
const std::shared_ptr<ViewStylesRepository> viewStylesRepository_;
|
|
||||||
|
|
||||||
PropertyInterpolatorsRecord interpolators_;
|
|
||||||
|
|
||||||
folly::dynamic mapInterpolators(
|
|
||||||
const TransitionProgressProvider &transitionProgressProvider,
|
|
||||||
const MapInterpolatorsCallback &callback) const;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace reanimated::css
|
|
||||||
Generated
Vendored
-85
@@ -1,85 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <reanimated/CSS/interpolation/transforms/TransformOperation.h>
|
|
||||||
#include <reanimated/CSS/misc/ViewStylesRepository.h>
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <unordered_map>
|
|
||||||
|
|
||||||
namespace reanimated::css {
|
|
||||||
|
|
||||||
class TransformInterpolator {
|
|
||||||
public:
|
|
||||||
using Interpolators =
|
|
||||||
std::unordered_map<TransformOp, std::shared_ptr<TransformInterpolator>>;
|
|
||||||
|
|
||||||
struct UpdateContext {
|
|
||||||
const std::shared_ptr<const ShadowNode> &node;
|
|
||||||
const std::shared_ptr<ViewStylesRepository> &viewStylesRepository;
|
|
||||||
const std::shared_ptr<Interpolators> &interpolators;
|
|
||||||
};
|
|
||||||
|
|
||||||
virtual ~TransformInterpolator() = default;
|
|
||||||
|
|
||||||
virtual std::shared_ptr<TransformOperation> getDefaultOperation() const = 0;
|
|
||||||
virtual std::shared_ptr<TransformOperation> interpolate(
|
|
||||||
double progress,
|
|
||||||
const std::shared_ptr<TransformOperation> &from,
|
|
||||||
const std::shared_ptr<TransformOperation> &to,
|
|
||||||
const UpdateContext &context) const = 0;
|
|
||||||
virtual std::shared_ptr<TransformOperation> resolveOperation(
|
|
||||||
const std::shared_ptr<TransformOperation> &operation,
|
|
||||||
const UpdateContext &context) const = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename TOperation>
|
|
||||||
class TransformInterpolatorBase : public TransformInterpolator {
|
|
||||||
public:
|
|
||||||
explicit TransformInterpolatorBase(
|
|
||||||
std::shared_ptr<TOperation> defaultOperation)
|
|
||||||
: defaultOperation_(defaultOperation) {}
|
|
||||||
|
|
||||||
std::shared_ptr<TransformOperation> getDefaultOperation() const override {
|
|
||||||
return defaultOperation_;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<TransformOperation> interpolate(
|
|
||||||
double progress,
|
|
||||||
const std::shared_ptr<TransformOperation> &from,
|
|
||||||
const std::shared_ptr<TransformOperation> &to,
|
|
||||||
const UpdateContext &context) const override {
|
|
||||||
return std::make_shared<TOperation>(interpolate(
|
|
||||||
progress,
|
|
||||||
*std::static_pointer_cast<TOperation>(from),
|
|
||||||
*std::static_pointer_cast<TOperation>(to),
|
|
||||||
context));
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<TransformOperation> resolveOperation(
|
|
||||||
const std::shared_ptr<TransformOperation> &operation,
|
|
||||||
const UpdateContext &context) const override {
|
|
||||||
return std::make_shared<TOperation>(resolveOperation(
|
|
||||||
*std::static_pointer_cast<TOperation>(operation), context));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual TOperation interpolate(
|
|
||||||
double progress,
|
|
||||||
const TOperation &from,
|
|
||||||
const TOperation &to,
|
|
||||||
const UpdateContext &context) const = 0;
|
|
||||||
|
|
||||||
virtual TOperation resolveOperation(
|
|
||||||
const TOperation &operation,
|
|
||||||
const UpdateContext &context) const {
|
|
||||||
return operation;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::shared_ptr<TOperation> defaultOperation_;
|
|
||||||
};
|
|
||||||
|
|
||||||
using TransformInterpolators = TransformInterpolator::Interpolators;
|
|
||||||
using TransformInterpolatorUpdateContext = TransformInterpolator::UpdateContext;
|
|
||||||
|
|
||||||
} // namespace reanimated::css
|
|
||||||
Generated
Vendored
-225
@@ -1,225 +0,0 @@
|
|||||||
#include <reanimated/CSS/interpolation/transforms/TransformOperation.h>
|
|
||||||
|
|
||||||
#include <reanimated/CSS/interpolation/transforms/operations/matrix.h>
|
|
||||||
#include <reanimated/CSS/interpolation/transforms/operations/perspective.h>
|
|
||||||
#include <reanimated/CSS/interpolation/transforms/operations/rotate.h>
|
|
||||||
#include <reanimated/CSS/interpolation/transforms/operations/scale.h>
|
|
||||||
#include <reanimated/CSS/interpolation/transforms/operations/skew.h>
|
|
||||||
#include <reanimated/CSS/interpolation/transforms/operations/translate.h>
|
|
||||||
|
|
||||||
namespace reanimated::css {
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
|
||||||
|
|
||||||
std::ostream &operator<<(
|
|
||||||
std::ostream &os,
|
|
||||||
const TransformOperation &operation) {
|
|
||||||
os << operation.getOperationName() << "("
|
|
||||||
<< operation.stringifyOperationValue() << ")";
|
|
||||||
return os;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // NDEBUG
|
|
||||||
|
|
||||||
bool TransformOperation::canConvertTo(const TransformOp targetType) const {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TransformOperation::assertCanConvertTo(
|
|
||||||
const TransformOp targetType) const {
|
|
||||||
if (!canConvertTo(targetType)) {
|
|
||||||
throw std::invalid_argument(
|
|
||||||
"[Reanimated] Cannot convert transform operation to type: " +
|
|
||||||
getOperationNameFromType(targetType));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TransformOperations TransformOperation::convertTo(
|
|
||||||
const TransformOp targetType) const {
|
|
||||||
throw std::invalid_argument(
|
|
||||||
"[Reanimated] Cannot convert transform operation to type: " +
|
|
||||||
getOperationNameFromType(targetType));
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string TransformOperation::getOperationName() const {
|
|
||||||
return getOperationNameFromType(type());
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TransformOperation::isRelative() const {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<TransformOperation> TransformOperation::fromJSIValue(
|
|
||||||
jsi::Runtime &rt,
|
|
||||||
const jsi::Value &value) {
|
|
||||||
if (!value.isObject()) {
|
|
||||||
throw std::invalid_argument(
|
|
||||||
"[Reanimated] TransformOperation must be an object.");
|
|
||||||
}
|
|
||||||
|
|
||||||
jsi::Object obj = value.asObject(rt);
|
|
||||||
auto propertyNames = obj.getPropertyNames(rt);
|
|
||||||
|
|
||||||
if (propertyNames.size(rt) != 1) {
|
|
||||||
throw std::invalid_argument(
|
|
||||||
"[Reanimated] TransformOperation must have exactly one property.");
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto propertyName =
|
|
||||||
propertyNames.getValueAtIndex(rt, 0).asString(rt).utf8(rt);
|
|
||||||
const auto propertyValue =
|
|
||||||
obj.getProperty(rt, jsi::PropNameID::forUtf8(rt, propertyName));
|
|
||||||
TransformOp operationType = getTransformOperationType(propertyName);
|
|
||||||
|
|
||||||
switch (operationType) {
|
|
||||||
case TransformOp::Perspective:
|
|
||||||
return std::make_shared<PerspectiveOperation>(propertyValue.asNumber());
|
|
||||||
case TransformOp::Rotate:
|
|
||||||
return std::make_shared<RotateOperation>(
|
|
||||||
propertyValue.asString(rt).utf8(rt));
|
|
||||||
case TransformOp::RotateX:
|
|
||||||
return std::make_shared<RotateXOperation>(
|
|
||||||
propertyValue.asString(rt).utf8(rt));
|
|
||||||
case TransformOp::RotateY:
|
|
||||||
return std::make_shared<RotateYOperation>(
|
|
||||||
propertyValue.asString(rt).utf8(rt));
|
|
||||||
case TransformOp::RotateZ:
|
|
||||||
return std::make_shared<RotateZOperation>(
|
|
||||||
propertyValue.asString(rt).utf8(rt));
|
|
||||||
case TransformOp::Scale:
|
|
||||||
return std::make_shared<ScaleOperation>(propertyValue.asNumber());
|
|
||||||
case TransformOp::ScaleX:
|
|
||||||
return std::make_shared<ScaleXOperation>(propertyValue.asNumber());
|
|
||||||
case TransformOp::ScaleY:
|
|
||||||
return std::make_shared<ScaleYOperation>(propertyValue.asNumber());
|
|
||||||
case TransformOp::TranslateX: {
|
|
||||||
if (propertyValue.isNumber()) {
|
|
||||||
return std::make_shared<TranslateXOperation>(propertyValue.asNumber());
|
|
||||||
}
|
|
||||||
return std::make_shared<TranslateXOperation>(
|
|
||||||
propertyValue.asString(rt).utf8(rt));
|
|
||||||
}
|
|
||||||
case TransformOp::TranslateY: {
|
|
||||||
if (propertyValue.isNumber()) {
|
|
||||||
return std::make_shared<TranslateYOperation>(propertyValue.asNumber());
|
|
||||||
}
|
|
||||||
return std::make_shared<TranslateYOperation>(
|
|
||||||
propertyValue.asString(rt).utf8(rt));
|
|
||||||
}
|
|
||||||
case TransformOp::SkewX:
|
|
||||||
return std::make_shared<SkewXOperation>(
|
|
||||||
propertyValue.asString(rt).utf8(rt));
|
|
||||||
case TransformOp::SkewY:
|
|
||||||
return std::make_shared<SkewYOperation>(
|
|
||||||
propertyValue.asString(rt).utf8(rt));
|
|
||||||
case TransformOp::Matrix:
|
|
||||||
return std::make_shared<MatrixOperation>(
|
|
||||||
TransformMatrix3D(rt, propertyValue));
|
|
||||||
default:
|
|
||||||
throw std::invalid_argument(
|
|
||||||
"[Reanimated] Unknown transform operation: " + propertyName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<TransformOperation> TransformOperation::fromDynamic(
|
|
||||||
const folly::dynamic &value) {
|
|
||||||
if (!value.isObject()) {
|
|
||||||
throw std::invalid_argument(
|
|
||||||
"[Reanimated] TransformOperation must be an object.");
|
|
||||||
}
|
|
||||||
|
|
||||||
auto &obj = value;
|
|
||||||
if (obj.size() != 1) {
|
|
||||||
throw std::invalid_argument(
|
|
||||||
"[Reanimated] TransformOperation must have exactly one property.");
|
|
||||||
}
|
|
||||||
|
|
||||||
auto propertyName = obj.items().begin()->first.getString();
|
|
||||||
auto propertyValue = obj.items().begin()->second;
|
|
||||||
TransformOp operationType = getTransformOperationType(propertyName);
|
|
||||||
|
|
||||||
switch (operationType) {
|
|
||||||
case TransformOp::Perspective:
|
|
||||||
return std::make_shared<PerspectiveOperation>(propertyValue.getDouble());
|
|
||||||
case TransformOp::Rotate:
|
|
||||||
return std::make_shared<RotateOperation>(propertyValue.getString());
|
|
||||||
case TransformOp::RotateX:
|
|
||||||
return std::make_shared<RotateXOperation>(propertyValue.getString());
|
|
||||||
case TransformOp::RotateY:
|
|
||||||
return std::make_shared<RotateYOperation>(propertyValue.getString());
|
|
||||||
case TransformOp::RotateZ:
|
|
||||||
return std::make_shared<RotateZOperation>(propertyValue.getString());
|
|
||||||
case TransformOp::Scale:
|
|
||||||
return std::make_shared<ScaleOperation>(propertyValue.getDouble());
|
|
||||||
case TransformOp::ScaleX:
|
|
||||||
return std::make_shared<ScaleXOperation>(propertyValue.getDouble());
|
|
||||||
case TransformOp::ScaleY:
|
|
||||||
return std::make_shared<ScaleYOperation>(propertyValue.getDouble());
|
|
||||||
case TransformOp::TranslateX: {
|
|
||||||
if (propertyValue.isNumber()) {
|
|
||||||
return std::make_shared<TranslateXOperation>(propertyValue.getDouble());
|
|
||||||
}
|
|
||||||
return std::make_shared<TranslateXOperation>(propertyValue.getString());
|
|
||||||
}
|
|
||||||
case TransformOp::TranslateY: {
|
|
||||||
if (propertyValue.isNumber()) {
|
|
||||||
return std::make_shared<TranslateYOperation>(propertyValue.getDouble());
|
|
||||||
}
|
|
||||||
return std::make_shared<TranslateYOperation>(propertyValue.getString());
|
|
||||||
}
|
|
||||||
case TransformOp::SkewX:
|
|
||||||
return std::make_shared<SkewXOperation>(propertyValue.getString());
|
|
||||||
case TransformOp::SkewY:
|
|
||||||
return std::make_shared<SkewYOperation>(propertyValue.getString());
|
|
||||||
case TransformOp::Matrix:
|
|
||||||
return std::make_shared<MatrixOperation>(
|
|
||||||
TransformMatrix3D(propertyValue));
|
|
||||||
default:
|
|
||||||
throw std::invalid_argument(
|
|
||||||
"[Reanimated] Unknown transform operation: " + propertyName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
folly::dynamic TransformOperation::toDynamic() const {
|
|
||||||
return folly::dynamic::object(getOperationName(), valueToDynamic());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Specialization for the matrix operation
|
|
||||||
#ifndef NDEBUG
|
|
||||||
|
|
||||||
template <TransformOp TOperation, typename TValue>
|
|
||||||
std::string
|
|
||||||
TransformOperationBase<TOperation, TValue>::stringifyOperationValue() const {
|
|
||||||
std::ostringstream ss;
|
|
||||||
ss << value;
|
|
||||||
return ss.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
std::string TransformOperationBase<
|
|
||||||
TransformOp::Matrix,
|
|
||||||
std::variant<TransformMatrix3D, TransformOperations>>::
|
|
||||||
stringifyOperationValue() const {
|
|
||||||
std::ostringstream ss;
|
|
||||||
|
|
||||||
if (std::holds_alternative<TransformMatrix3D>(value)) {
|
|
||||||
ss << std::get<TransformMatrix3D>(value);
|
|
||||||
} else {
|
|
||||||
const auto &operations = std::get<TransformOperations>(value);
|
|
||||||
std::ostringstream ss;
|
|
||||||
for (const auto &operation : operations) {
|
|
||||||
ss << operation->getOperationName() << "("
|
|
||||||
<< operation->stringifyOperationValue() << "), ";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ss.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // NDEBUG
|
|
||||||
|
|
||||||
template struct TransformOperationBase<
|
|
||||||
TransformOp::Matrix,
|
|
||||||
std::variant<TransformMatrix3D, TransformOperations>>;
|
|
||||||
|
|
||||||
} // namespace reanimated::css
|
|
||||||
Generated
Vendored
-87
@@ -1,87 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <reanimated/CSS/common/definitions.h>
|
|
||||||
#include <reanimated/CSS/common/transforms/TransformMatrix3D.h>
|
|
||||||
#include <reanimated/CSS/common/transforms/TransformOp.h>
|
|
||||||
#include <reanimated/CSS/common/values/CSSAngle.h>
|
|
||||||
#include <reanimated/CSS/common/values/CSSLength.h>
|
|
||||||
#include <reanimated/CSS/common/values/CSSNumber.h>
|
|
||||||
|
|
||||||
#include <react/renderer/core/ShadowNode.h>
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <string>
|
|
||||||
#include <unordered_map>
|
|
||||||
#include <variant>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
|
||||||
#include <iostream>
|
|
||||||
#include <sstream>
|
|
||||||
#endif // NDEBUG
|
|
||||||
|
|
||||||
namespace reanimated::css {
|
|
||||||
|
|
||||||
using namespace facebook;
|
|
||||||
using namespace react;
|
|
||||||
|
|
||||||
// Base struct for TransformOperation
|
|
||||||
struct TransformOperation {
|
|
||||||
virtual bool operator==(const TransformOperation &other) const = 0;
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
|
||||||
friend std::ostream &operator<<(
|
|
||||||
std::ostream &os,
|
|
||||||
const TransformOperation &operation);
|
|
||||||
virtual std::string stringifyOperationValue() const = 0;
|
|
||||||
#endif // NDEBUG
|
|
||||||
|
|
||||||
std::string getOperationName() const;
|
|
||||||
virtual TransformOp type() const = 0;
|
|
||||||
virtual bool isRelative() const;
|
|
||||||
|
|
||||||
static std::shared_ptr<TransformOperation> fromJSIValue(
|
|
||||||
jsi::Runtime &rt,
|
|
||||||
const jsi::Value &value);
|
|
||||||
static std::shared_ptr<TransformOperation> fromDynamic(
|
|
||||||
const folly::dynamic &value);
|
|
||||||
folly::dynamic toDynamic() const;
|
|
||||||
virtual folly::dynamic valueToDynamic() const = 0;
|
|
||||||
|
|
||||||
virtual bool canConvertTo(TransformOp type) const;
|
|
||||||
virtual std::vector<std::shared_ptr<TransformOperation>> convertTo(
|
|
||||||
TransformOp type) const;
|
|
||||||
|
|
||||||
virtual TransformMatrix3D toMatrix() const = 0;
|
|
||||||
void assertCanConvertTo(TransformOp type) const;
|
|
||||||
};
|
|
||||||
|
|
||||||
using TransformOperations = std::vector<std::shared_ptr<TransformOperation>>;
|
|
||||||
|
|
||||||
// Template overload to inherit from in final operation structs
|
|
||||||
template <TransformOp TOperation, typename TValue>
|
|
||||||
struct TransformOperationBase : public TransformOperation {
|
|
||||||
const TValue value;
|
|
||||||
|
|
||||||
explicit TransformOperationBase(const TValue &value) : value(value) {}
|
|
||||||
virtual ~TransformOperationBase() = default;
|
|
||||||
|
|
||||||
TransformOp type() const override {
|
|
||||||
return TOperation;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator==(const TransformOperation &other) const override {
|
|
||||||
if (type() != other.type()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
const auto &otherOperation =
|
|
||||||
static_cast<const TransformOperationBase<TOperation, TValue> &>(other);
|
|
||||||
return value == otherOperation.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
|
||||||
std::string stringifyOperationValue() const override;
|
|
||||||
#endif // NDEBUG
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace reanimated::css
|
|
||||||
Generated
Vendored
-64
@@ -1,64 +0,0 @@
|
|||||||
#include <reanimated/CSS/interpolation/transforms/TransformOperationInterpolator.h>
|
|
||||||
|
|
||||||
namespace reanimated::css {
|
|
||||||
|
|
||||||
PerspectiveOperation
|
|
||||||
TransformOperationInterpolator<PerspectiveOperation>::interpolate(
|
|
||||||
double progress,
|
|
||||||
const PerspectiveOperation &from,
|
|
||||||
const PerspectiveOperation &to,
|
|
||||||
const TransformInterpolatorUpdateContext &context) const {
|
|
||||||
if (to.value.value == 0)
|
|
||||||
return PerspectiveOperation(0);
|
|
||||||
if (from.value.value == 0)
|
|
||||||
return PerspectiveOperation(to.value);
|
|
||||||
|
|
||||||
return PerspectiveOperation(from.value.interpolate(progress, to.value));
|
|
||||||
}
|
|
||||||
|
|
||||||
MatrixOperation TransformOperationInterpolator<MatrixOperation>::interpolate(
|
|
||||||
double progress,
|
|
||||||
const MatrixOperation &from,
|
|
||||||
const MatrixOperation &to,
|
|
||||||
const TransformInterpolatorUpdateContext &context) const {
|
|
||||||
const auto fromMatrix = matrixFromOperation(from, context);
|
|
||||||
const auto toMatrix = matrixFromOperation(to, context);
|
|
||||||
const auto decomposedFrom = fromMatrix.decompose();
|
|
||||||
const auto decomposedTo = toMatrix.decompose();
|
|
||||||
|
|
||||||
if (!decomposedFrom.has_value() || !decomposedTo.has_value()) {
|
|
||||||
return MatrixOperation(progress < 0.5 ? fromMatrix : toMatrix);
|
|
||||||
}
|
|
||||||
|
|
||||||
return MatrixOperation(TransformMatrix3D::recompose(
|
|
||||||
decomposedFrom->interpolate(progress, decomposedTo.value())));
|
|
||||||
}
|
|
||||||
|
|
||||||
TransformMatrix3D
|
|
||||||
TransformOperationInterpolator<MatrixOperation>::matrixFromOperation(
|
|
||||||
const MatrixOperation &matrixOperation,
|
|
||||||
const TransformInterpolatorUpdateContext &context) const {
|
|
||||||
if (std::holds_alternative<TransformOperations>(matrixOperation.value)) {
|
|
||||||
const auto &operations =
|
|
||||||
std::get<TransformOperations>(matrixOperation.value);
|
|
||||||
|
|
||||||
TransformMatrix3D matrix = TransformMatrix3D::Identity();
|
|
||||||
|
|
||||||
for (int i = static_cast<int>(operations.size()) - 1; i >= 0; i--) {
|
|
||||||
auto operation = operations[i];
|
|
||||||
|
|
||||||
if (operation->isRelative()) {
|
|
||||||
const auto &interpolator = context.interpolators->at(operation->type());
|
|
||||||
operation = interpolator->resolveOperation(operation, context);
|
|
||||||
}
|
|
||||||
|
|
||||||
matrix *= operation->toMatrix();
|
|
||||||
}
|
|
||||||
|
|
||||||
return matrix;
|
|
||||||
}
|
|
||||||
|
|
||||||
return std::get<TransformMatrix3D>(matrixOperation.value);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace reanimated::css
|
|
||||||
Generated
Vendored
-124
@@ -1,124 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <reanimated/CSS/common/values/CSSValue.h>
|
|
||||||
#include <reanimated/CSS/interpolation/transforms/TransformInterpolator.h>
|
|
||||||
#include <reanimated/CSS/interpolation/transforms/operations/matrix.h>
|
|
||||||
#include <reanimated/CSS/interpolation/transforms/operations/perspective.h>
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
namespace reanimated::css {
|
|
||||||
|
|
||||||
template <typename TOperation>
|
|
||||||
concept ResolvableOperation = requires(TOperation operation) {
|
|
||||||
{
|
|
||||||
operation.value
|
|
||||||
} -> std::convertible_to<
|
|
||||||
typename std::remove_reference_t<decltype(operation.value)>>;
|
|
||||||
requires Resolvable<std::remove_reference_t<decltype(operation.value)>>;
|
|
||||||
}; // NOLINT(readability/braces)
|
|
||||||
|
|
||||||
// Base implementation for simple operations
|
|
||||||
template <typename OperationType>
|
|
||||||
class TransformOperationInterpolator
|
|
||||||
: public TransformInterpolatorBase<OperationType> {
|
|
||||||
public:
|
|
||||||
TransformOperationInterpolator(
|
|
||||||
std::shared_ptr<OperationType> defaultOperation)
|
|
||||||
: TransformInterpolatorBase<OperationType>(defaultOperation) {}
|
|
||||||
|
|
||||||
OperationType interpolate(
|
|
||||||
double progress,
|
|
||||||
const OperationType &from,
|
|
||||||
const OperationType &to,
|
|
||||||
const TransformInterpolatorUpdateContext &context) const override {
|
|
||||||
return OperationType{from.value.interpolate(progress, to.value)};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Specialization for PerspectiveOperation
|
|
||||||
template <>
|
|
||||||
class TransformOperationInterpolator<PerspectiveOperation>
|
|
||||||
: public TransformInterpolatorBase<PerspectiveOperation> {
|
|
||||||
public:
|
|
||||||
using TransformInterpolatorBase<
|
|
||||||
PerspectiveOperation>::TransformInterpolatorBase;
|
|
||||||
|
|
||||||
PerspectiveOperation interpolate(
|
|
||||||
double progress,
|
|
||||||
const PerspectiveOperation &from,
|
|
||||||
const PerspectiveOperation &to,
|
|
||||||
const TransformInterpolatorUpdateContext &context) const override;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Specialization for MatrixOperation
|
|
||||||
template <>
|
|
||||||
class TransformOperationInterpolator<MatrixOperation>
|
|
||||||
: public TransformInterpolatorBase<MatrixOperation> {
|
|
||||||
public:
|
|
||||||
using TransformInterpolatorBase<MatrixOperation>::TransformInterpolatorBase;
|
|
||||||
|
|
||||||
MatrixOperation interpolate(
|
|
||||||
double progress,
|
|
||||||
const MatrixOperation &from,
|
|
||||||
const MatrixOperation &to,
|
|
||||||
const TransformInterpolatorUpdateContext &context) const override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
TransformMatrix3D matrixFromOperation(
|
|
||||||
const MatrixOperation &matrixOperation,
|
|
||||||
const TransformInterpolatorUpdateContext &context) const;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Specialization for resolvable operations
|
|
||||||
template <ResolvableOperation TOperation>
|
|
||||||
class TransformOperationInterpolator<TOperation>
|
|
||||||
: public TransformInterpolatorBase<TOperation> {
|
|
||||||
public:
|
|
||||||
TransformOperationInterpolator(
|
|
||||||
const std::shared_ptr<TOperation> &defaultOperation,
|
|
||||||
RelativeTo relativeTo,
|
|
||||||
const std::string &relativeProperty)
|
|
||||||
: TransformInterpolatorBase<TOperation>(defaultOperation),
|
|
||||||
relativeTo_(relativeTo),
|
|
||||||
relativeProperty_(relativeProperty) {}
|
|
||||||
|
|
||||||
TOperation interpolate(
|
|
||||||
double progress,
|
|
||||||
const TOperation &from,
|
|
||||||
const TOperation &to,
|
|
||||||
const TransformInterpolatorUpdateContext &context) const override {
|
|
||||||
return TOperation{from.value.interpolate(
|
|
||||||
progress, to.value, getResolvableValueContext(context))};
|
|
||||||
}
|
|
||||||
|
|
||||||
TOperation resolveOperation(
|
|
||||||
const TOperation &operation,
|
|
||||||
const TransformInterpolatorUpdateContext &context) const override {
|
|
||||||
const auto &resolved =
|
|
||||||
operation.value.resolve(getResolvableValueContext(context));
|
|
||||||
|
|
||||||
if (!resolved.has_value()) {
|
|
||||||
return TOperation{operation.value};
|
|
||||||
}
|
|
||||||
|
|
||||||
return TOperation{resolved.value()};
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
const RelativeTo relativeTo_;
|
|
||||||
const std::string relativeProperty_;
|
|
||||||
|
|
||||||
CSSResolvableValueInterpolationContext getResolvableValueContext(
|
|
||||||
const TransformInterpolatorUpdateContext &context) const {
|
|
||||||
return {
|
|
||||||
.node = context.node,
|
|
||||||
.viewStylesRepository = context.viewStylesRepository,
|
|
||||||
.relativeProperty = relativeProperty_,
|
|
||||||
.relativeTo = relativeTo_,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace reanimated::css
|
|
||||||
Generated
Vendored
-405
@@ -1,405 +0,0 @@
|
|||||||
#include <reanimated/CSS/interpolation/transforms/TransformsStyleInterpolator.h>
|
|
||||||
|
|
||||||
namespace reanimated::css {
|
|
||||||
|
|
||||||
const TransformOperations TransformsStyleInterpolator::defaultStyleValue_ = {
|
|
||||||
std::make_shared<MatrixOperation>(TransformMatrix3D::Identity())};
|
|
||||||
|
|
||||||
TransformsStyleInterpolator::TransformsStyleInterpolator(
|
|
||||||
const PropertyPath &propertyPath,
|
|
||||||
const std::shared_ptr<TransformInterpolators> &interpolators,
|
|
||||||
const std::shared_ptr<ViewStylesRepository> &viewStylesRepository)
|
|
||||||
: PropertyInterpolator(propertyPath, viewStylesRepository),
|
|
||||||
interpolators_(interpolators) {}
|
|
||||||
|
|
||||||
folly::dynamic TransformsStyleInterpolator::getStyleValue(
|
|
||||||
const std::shared_ptr<const ShadowNode> &shadowNode) const {
|
|
||||||
return viewStylesRepository_->getStyleProp(
|
|
||||||
shadowNode->getTag(), propertyPath_);
|
|
||||||
}
|
|
||||||
|
|
||||||
folly::dynamic TransformsStyleInterpolator::getResetStyle(
|
|
||||||
const std::shared_ptr<const ShadowNode> &shadowNode) const {
|
|
||||||
auto styleValue = getStyleValue(shadowNode);
|
|
||||||
|
|
||||||
if (!styleValue.isArray()) {
|
|
||||||
return convertResultToDynamic(defaultStyleValue_);
|
|
||||||
}
|
|
||||||
|
|
||||||
return styleValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
folly::dynamic TransformsStyleInterpolator::getFirstKeyframeValue() const {
|
|
||||||
return convertResultToDynamic(
|
|
||||||
keyframes_.front()->fromOperations.value_or(defaultStyleValue_));
|
|
||||||
}
|
|
||||||
|
|
||||||
folly::dynamic TransformsStyleInterpolator::getLastKeyframeValue() const {
|
|
||||||
return convertResultToDynamic(
|
|
||||||
keyframes_.back()->toOperations.value_or(defaultStyleValue_));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TransformsStyleInterpolator::equalsReversingAdjustedStartValue(
|
|
||||||
const folly::dynamic &propertyValue) const {
|
|
||||||
const auto propertyOperations = parseTransformOperations(propertyValue);
|
|
||||||
|
|
||||||
if (!reversingAdjustedStartValue_.has_value()) {
|
|
||||||
return !propertyOperations.has_value();
|
|
||||||
} else if (!propertyOperations.has_value()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto &reversingAdjustedOperationsValue =
|
|
||||||
reversingAdjustedStartValue_.value();
|
|
||||||
const auto &propertyOperationsValue = propertyOperations.value();
|
|
||||||
|
|
||||||
if (reversingAdjustedOperationsValue.size() !=
|
|
||||||
propertyOperationsValue.size()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i = 0; i < reversingAdjustedOperationsValue.size(); ++i) {
|
|
||||||
if (*reversingAdjustedOperationsValue[i] != *propertyOperationsValue[i]) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
folly::dynamic TransformsStyleInterpolator::interpolate(
|
|
||||||
const std::shared_ptr<const ShadowNode> &shadowNode,
|
|
||||||
const std::shared_ptr<KeyframeProgressProvider> &progressProvider) const {
|
|
||||||
const auto currentIndex = getIndexOfCurrentKeyframe(progressProvider);
|
|
||||||
|
|
||||||
// Get or create the current keyframe
|
|
||||||
auto keyframe = keyframes_[currentIndex];
|
|
||||||
if (!keyframe->fromOperations.has_value() ||
|
|
||||||
!keyframe->toOperations.has_value()) {
|
|
||||||
// If the value is nullopt, we would have to read it from the view style
|
|
||||||
// and build the keyframe again
|
|
||||||
const auto fallbackValue = getFallbackValue(shadowNode);
|
|
||||||
keyframe = createTransformKeyframe(
|
|
||||||
keyframe->fromOffset,
|
|
||||||
keyframe->toOffset,
|
|
||||||
keyframe->fromOperations.value_or(fallbackValue),
|
|
||||||
keyframe->toOperations.value_or(fallbackValue));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Interpolate the current keyframe
|
|
||||||
TransformOperations result = interpolateOperations(
|
|
||||||
shadowNode,
|
|
||||||
progressProvider->getKeyframeProgress(
|
|
||||||
keyframe->fromOffset, keyframe->toOffset),
|
|
||||||
keyframe->fromOperations.value(),
|
|
||||||
keyframe->toOperations.value());
|
|
||||||
|
|
||||||
return convertResultToDynamic(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
void TransformsStyleInterpolator::updateKeyframes(
|
|
||||||
jsi::Runtime &rt,
|
|
||||||
const jsi::Value &keyframes) {
|
|
||||||
// Step 1: Parse keyframes
|
|
||||||
const auto parsedKeyframes = parseJSIKeyframes(rt, keyframes);
|
|
||||||
|
|
||||||
// Step 2: Convert keyframes to TransformOperations
|
|
||||||
std::vector<std::pair<double, std::optional<TransformOperations>>> operations;
|
|
||||||
operations.reserve(parsedKeyframes.size());
|
|
||||||
for (const auto &[offset, value] : parsedKeyframes) {
|
|
||||||
operations.emplace_back(offset, parseTransformOperations(rt, value));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Step 3: Prepare keyframe interpolation pairs (convert keyframe values in
|
|
||||||
// both keyframes to the same type)
|
|
||||||
// There will be one less keyframe than the number of keyframes in the jsi
|
|
||||||
// array as we create interpolation pairs
|
|
||||||
const auto keyframesCount = operations.size() - 1;
|
|
||||||
keyframes_.clear();
|
|
||||||
keyframes_.reserve(keyframesCount);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < keyframesCount; ++i) {
|
|
||||||
keyframes_.push_back(createTransformKeyframe(
|
|
||||||
operations[i].first,
|
|
||||||
operations[i + 1].first,
|
|
||||||
operations[i].second,
|
|
||||||
operations[i + 1].second));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void TransformsStyleInterpolator::updateKeyframesFromStyleChange(
|
|
||||||
const folly::dynamic &oldStyleValue,
|
|
||||||
const folly::dynamic &newStyleValue,
|
|
||||||
const folly::dynamic &lastUpdateValue) {
|
|
||||||
if (oldStyleValue.isNull()) {
|
|
||||||
reversingAdjustedStartValue_ = std::nullopt;
|
|
||||||
} else {
|
|
||||||
reversingAdjustedStartValue_ = parseTransformOperations(oldStyleValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto &prevStyleValue =
|
|
||||||
lastUpdateValue.isNull() ? oldStyleValue : lastUpdateValue;
|
|
||||||
|
|
||||||
keyframes_.clear();
|
|
||||||
keyframes_.reserve(1);
|
|
||||||
keyframes_.emplace_back(createTransformKeyframe(
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
parseTransformOperations(prevStyleValue).value_or(TransformOperations{}),
|
|
||||||
parseTransformOperations(newStyleValue).value_or(TransformOperations{})));
|
|
||||||
}
|
|
||||||
|
|
||||||
std::optional<TransformOperations>
|
|
||||||
TransformsStyleInterpolator::parseTransformOperations(
|
|
||||||
jsi::Runtime &rt,
|
|
||||||
const jsi::Value &values) {
|
|
||||||
if (values.isUndefined()) {
|
|
||||||
return std::nullopt;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto transformsArray = values.asObject(rt).asArray(rt);
|
|
||||||
const auto transformsCount = transformsArray.size(rt);
|
|
||||||
|
|
||||||
TransformOperations transformOperations;
|
|
||||||
transformOperations.reserve(transformsCount);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < transformsCount; ++i) {
|
|
||||||
const auto transform = transformsArray.getValueAtIndex(rt, i);
|
|
||||||
transformOperations.emplace_back(
|
|
||||||
TransformOperation::fromJSIValue(rt, transform));
|
|
||||||
}
|
|
||||||
return transformOperations;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::optional<TransformOperations>
|
|
||||||
TransformsStyleInterpolator::parseTransformOperations(
|
|
||||||
const folly::dynamic &values) {
|
|
||||||
if (values.empty()) {
|
|
||||||
return std::nullopt;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto &transformsArray = values;
|
|
||||||
const auto transformsCount = transformsArray.size();
|
|
||||||
|
|
||||||
TransformOperations transformOperations;
|
|
||||||
transformOperations.reserve(transformsCount);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < transformsCount; ++i) {
|
|
||||||
const auto &transform = transformsArray[i];
|
|
||||||
transformOperations.emplace_back(
|
|
||||||
TransformOperation::fromDynamic(transform));
|
|
||||||
}
|
|
||||||
return transformOperations;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<TransformKeyframe>
|
|
||||||
TransformsStyleInterpolator::createTransformKeyframe(
|
|
||||||
const double fromOffset,
|
|
||||||
const double toOffset,
|
|
||||||
const std::optional<TransformOperations> &fromOperationsOptional,
|
|
||||||
const std::optional<TransformOperations> &toOperationsOptional) const {
|
|
||||||
// If nullopt is passed, return values as is (we will have to read the
|
|
||||||
// transform value from the view style later on and create the new keyframe
|
|
||||||
// then)
|
|
||||||
if (!fromOperationsOptional.has_value() ||
|
|
||||||
!toOperationsOptional.has_value()) {
|
|
||||||
return std::make_shared<TransformKeyframe>(TransformKeyframe{
|
|
||||||
fromOffset, toOffset, fromOperationsOptional, toOperationsOptional});
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto [fromOperations, toOperations] = createTransformInterpolationPair(
|
|
||||||
fromOperationsOptional.value(), toOperationsOptional.value());
|
|
||||||
return std::make_shared<TransformKeyframe>(
|
|
||||||
TransformKeyframe{fromOffset, toOffset, fromOperations, toOperations});
|
|
||||||
}
|
|
||||||
|
|
||||||
void TransformsStyleInterpolator::addConvertedOperations(
|
|
||||||
const std::shared_ptr<TransformOperation> &sourceOperation,
|
|
||||||
const std::shared_ptr<TransformOperation> &targetOperation,
|
|
||||||
TransformOperations &sourceResult,
|
|
||||||
TransformOperations &targetResult) const {
|
|
||||||
const auto convertedOps = sourceOperation->convertTo(targetOperation->type());
|
|
||||||
|
|
||||||
targetResult.emplace_back(targetOperation);
|
|
||||||
for (size_t k = 0; k < convertedOps.size(); ++k) {
|
|
||||||
sourceResult.emplace_back(convertedOps[k]);
|
|
||||||
// Converted operations will contain one operation with the same type and
|
|
||||||
// can contain more operations derived from the source operation (we need
|
|
||||||
// to pair them with operations of the same type with default values)
|
|
||||||
if (k > 0) {
|
|
||||||
targetResult.emplace_back(
|
|
||||||
getDefaultOperationOfType(convertedOps[k]->type()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::pair<TransformOperations, TransformOperations>
|
|
||||||
TransformsStyleInterpolator::createTransformInterpolationPair(
|
|
||||||
const TransformOperations &fromOperations,
|
|
||||||
const TransformOperations &toOperations) const {
|
|
||||||
TransformOperations fromOperationsResult, toOperationsResult;
|
|
||||||
size_t i = 0, j = 0;
|
|
||||||
bool shouldInterpolateMatrices = false;
|
|
||||||
|
|
||||||
// Build index maps and check for matrix operation
|
|
||||||
std::unordered_map<TransformOp, size_t> lastIndexInFrom, lastIndexInTo;
|
|
||||||
for (size_t idx = 0; idx < fromOperations.size(); ++idx) {
|
|
||||||
if (fromOperations[idx]->type() == TransformOp::Matrix) {
|
|
||||||
shouldInterpolateMatrices = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
lastIndexInFrom[fromOperations[idx]->type()] = idx;
|
|
||||||
}
|
|
||||||
for (size_t idx = 0; idx < toOperations.size() && !shouldInterpolateMatrices;
|
|
||||||
++idx) {
|
|
||||||
if (toOperations[idx]->type() == TransformOp::Matrix) {
|
|
||||||
shouldInterpolateMatrices = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
lastIndexInTo[toOperations[idx]->type()] = idx;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (!shouldInterpolateMatrices && i < fromOperations.size() &&
|
|
||||||
j < toOperations.size()) {
|
|
||||||
const auto &fromOperation = fromOperations[i];
|
|
||||||
const auto &toOperation = toOperations[j];
|
|
||||||
|
|
||||||
// Case 1: Types match directly
|
|
||||||
if (fromOperation->type() == toOperation->type()) {
|
|
||||||
fromOperationsResult.emplace_back(fromOperation);
|
|
||||||
toOperationsResult.emplace_back(toOperation);
|
|
||||||
i++;
|
|
||||||
j++;
|
|
||||||
} else if (fromOperation->canConvertTo(toOperation->type())) {
|
|
||||||
// Case 2: Operations can be converted to each other's type
|
|
||||||
addConvertedOperations(
|
|
||||||
fromOperation, toOperation, fromOperationsResult, toOperationsResult);
|
|
||||||
i++;
|
|
||||||
j++;
|
|
||||||
} else if (toOperation->canConvertTo(fromOperation->type())) {
|
|
||||||
addConvertedOperations(
|
|
||||||
toOperation, fromOperation, toOperationsResult, fromOperationsResult);
|
|
||||||
i++;
|
|
||||||
j++;
|
|
||||||
} else {
|
|
||||||
// Case 3: Use default values if no conversion possible
|
|
||||||
bool toExistsLaterInFrom = lastIndexInFrom.count(toOperation->type()) &&
|
|
||||||
lastIndexInFrom[toOperation->type()] > i;
|
|
||||||
bool fromExistsLaterInTo = lastIndexInTo.count(fromOperation->type()) &&
|
|
||||||
lastIndexInTo[fromOperation->type()] > j;
|
|
||||||
|
|
||||||
if (toExistsLaterInFrom == fromExistsLaterInTo) {
|
|
||||||
// If neither exists later, or both exist later (were reordered), we
|
|
||||||
// cannot interpolate the operations directly and we need to convert
|
|
||||||
// these operations to matrices
|
|
||||||
shouldInterpolateMatrices = true;
|
|
||||||
break;
|
|
||||||
} else if (!fromExistsLaterInTo) {
|
|
||||||
// If fromOperation does not exist later in toOperations, we can
|
|
||||||
// interpolate it to the default value
|
|
||||||
fromOperationsResult.emplace_back(fromOperation);
|
|
||||||
toOperationsResult.emplace_back(
|
|
||||||
getDefaultOperationOfType(fromOperation->type()));
|
|
||||||
i++;
|
|
||||||
} else {
|
|
||||||
// If toOperation does not exist later in fromOperations, we can
|
|
||||||
// interpolate it from the default value
|
|
||||||
fromOperationsResult.emplace_back(
|
|
||||||
getDefaultOperationOfType(toOperation->type()));
|
|
||||||
toOperationsResult.emplace_back(toOperation);
|
|
||||||
j++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert all operations to matrices if matrix interpolation is required
|
|
||||||
if (shouldInterpolateMatrices) {
|
|
||||||
return std::make_pair(
|
|
||||||
TransformOperations{
|
|
||||||
std::make_shared<MatrixOperation>(MatrixOperation(fromOperations))},
|
|
||||||
TransformOperations{
|
|
||||||
std::make_shared<MatrixOperation>(MatrixOperation(toOperations))});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add remaining operations with default values
|
|
||||||
for (; i < fromOperations.size(); ++i) {
|
|
||||||
fromOperationsResult.emplace_back(fromOperations[i]);
|
|
||||||
toOperationsResult.emplace_back(
|
|
||||||
getDefaultOperationOfType(fromOperations[i]->type()));
|
|
||||||
}
|
|
||||||
for (; j < toOperations.size(); ++j) {
|
|
||||||
fromOperationsResult.emplace_back(
|
|
||||||
getDefaultOperationOfType(toOperations[j]->type()));
|
|
||||||
toOperationsResult.emplace_back(toOperations[j]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return std::make_pair(fromOperationsResult, toOperationsResult);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t TransformsStyleInterpolator::getIndexOfCurrentKeyframe(
|
|
||||||
const std::shared_ptr<KeyframeProgressProvider> &progressProvider) const {
|
|
||||||
const auto progress = progressProvider->getGlobalProgress();
|
|
||||||
|
|
||||||
const auto it = std::lower_bound(
|
|
||||||
keyframes_.begin(),
|
|
||||||
keyframes_.end(),
|
|
||||||
progress,
|
|
||||||
[](const std::shared_ptr<TransformKeyframe> &keyframe, double progress) {
|
|
||||||
return keyframe->toOffset < progress;
|
|
||||||
});
|
|
||||||
|
|
||||||
// If we're at the end, return the last valid keyframe index
|
|
||||||
if (it == keyframes_.end()) {
|
|
||||||
return keyframes_.size() - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return std::distance(keyframes_.begin(), it);
|
|
||||||
}
|
|
||||||
|
|
||||||
TransformOperations TransformsStyleInterpolator::getFallbackValue(
|
|
||||||
const std::shared_ptr<const ShadowNode> &shadowNode) const {
|
|
||||||
const auto &styleValue = getStyleValue(shadowNode);
|
|
||||||
return parseTransformOperations(styleValue).value_or(TransformOperations{});
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<TransformOperation>
|
|
||||||
TransformsStyleInterpolator::getDefaultOperationOfType(
|
|
||||||
const TransformOp type) const {
|
|
||||||
return interpolators_->at(type)->getDefaultOperation();
|
|
||||||
}
|
|
||||||
|
|
||||||
TransformOperations TransformsStyleInterpolator::interpolateOperations(
|
|
||||||
const std::shared_ptr<const ShadowNode> &shadowNode,
|
|
||||||
const double keyframeProgress,
|
|
||||||
const TransformOperations &fromOperations,
|
|
||||||
const TransformOperations &toOperations) const {
|
|
||||||
TransformOperations result;
|
|
||||||
result.reserve(fromOperations.size());
|
|
||||||
const auto transformUpdateContext = TransformInterpolatorUpdateContext{
|
|
||||||
shadowNode, viewStylesRepository_, interpolators_};
|
|
||||||
|
|
||||||
for (size_t i = 0; i < fromOperations.size(); ++i) {
|
|
||||||
const auto &fromOperation = fromOperations[i];
|
|
||||||
const auto &toOperation = toOperations[i];
|
|
||||||
|
|
||||||
// fromOperation and toOperation have the same type
|
|
||||||
const auto &interpolator = interpolators_->at(fromOperation->type());
|
|
||||||
result.emplace_back(interpolator->interpolate(
|
|
||||||
keyframeProgress, fromOperation, toOperation, transformUpdateContext));
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
folly::dynamic TransformsStyleInterpolator::convertResultToDynamic(
|
|
||||||
const TransformOperations &operations) {
|
|
||||||
auto result = folly::dynamic::array();
|
|
||||||
|
|
||||||
for (const auto &operation : operations) {
|
|
||||||
result.push_back(operation->toDynamic());
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace reanimated::css
|
|
||||||
Generated
Vendored
-98
@@ -1,98 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <reanimated/CSS/interpolation/PropertyInterpolator.h>
|
|
||||||
#include <reanimated/CSS/interpolation/transforms/TransformInterpolator.h>
|
|
||||||
#include <reanimated/CSS/interpolation/transforms/operations/matrix.h>
|
|
||||||
#include <reanimated/CSS/utils/keyframes.h>
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <unordered_map>
|
|
||||||
#include <utility>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace reanimated::css {
|
|
||||||
|
|
||||||
struct TransformKeyframe {
|
|
||||||
const double fromOffset;
|
|
||||||
const double toOffset;
|
|
||||||
// If the value is nullopt, we would have to read it from the view style
|
|
||||||
// (in all other cases, both vectors will have the same number of elements of
|
|
||||||
// corresponding types - elements from the same index will form interpolation
|
|
||||||
// pairs)
|
|
||||||
const std::optional<TransformOperations> fromOperations;
|
|
||||||
const std::optional<TransformOperations> toOperations;
|
|
||||||
};
|
|
||||||
|
|
||||||
class TransformsStyleInterpolator final : public PropertyInterpolator {
|
|
||||||
public:
|
|
||||||
TransformsStyleInterpolator(
|
|
||||||
const PropertyPath &propertyPath,
|
|
||||||
const std::shared_ptr<TransformInterpolators> &interpolators,
|
|
||||||
const std::shared_ptr<ViewStylesRepository> &viewStylesRepository);
|
|
||||||
|
|
||||||
folly::dynamic getStyleValue(
|
|
||||||
const std::shared_ptr<const ShadowNode> &shadowNode) const override;
|
|
||||||
folly::dynamic getResetStyle(
|
|
||||||
const std::shared_ptr<const ShadowNode> &shadowNode) const override;
|
|
||||||
folly::dynamic getFirstKeyframeValue() const override;
|
|
||||||
folly::dynamic getLastKeyframeValue() const override;
|
|
||||||
bool equalsReversingAdjustedStartValue(
|
|
||||||
const folly::dynamic &propertyValue) const override;
|
|
||||||
|
|
||||||
folly::dynamic interpolate(
|
|
||||||
const std::shared_ptr<const ShadowNode> &shadowNode,
|
|
||||||
const std::shared_ptr<KeyframeProgressProvider> &progressProvider)
|
|
||||||
const override;
|
|
||||||
|
|
||||||
void updateKeyframes(jsi::Runtime &rt, const jsi::Value &keyframes) override;
|
|
||||||
void updateKeyframesFromStyleChange(
|
|
||||||
const folly::dynamic &oldStyleValue,
|
|
||||||
const folly::dynamic &newStyleValue,
|
|
||||||
const folly::dynamic &lastUpdateValue) override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
const std::shared_ptr<TransformInterpolators> interpolators_;
|
|
||||||
static const TransformOperations defaultStyleValue_;
|
|
||||||
|
|
||||||
std::vector<std::shared_ptr<TransformKeyframe>> keyframes_;
|
|
||||||
std::optional<TransformOperations> reversingAdjustedStartValue_;
|
|
||||||
|
|
||||||
static std::optional<TransformOperations> parseTransformOperations(
|
|
||||||
jsi::Runtime &rt,
|
|
||||||
const jsi::Value &values);
|
|
||||||
static std::optional<TransformOperations> parseTransformOperations(
|
|
||||||
const folly::dynamic &values);
|
|
||||||
std::shared_ptr<TransformKeyframe> createTransformKeyframe(
|
|
||||||
double fromOffset,
|
|
||||||
double toOffset,
|
|
||||||
const std::optional<TransformOperations> &fromOperationsOptional,
|
|
||||||
const std::optional<TransformOperations> &toOperationsOptional) const;
|
|
||||||
std::pair<TransformOperations, TransformOperations>
|
|
||||||
createTransformInterpolationPair(
|
|
||||||
const TransformOperations &fromOperations,
|
|
||||||
const TransformOperations &toOperations) const;
|
|
||||||
void addConvertedOperations(
|
|
||||||
const std::shared_ptr<TransformOperation> &sourceOperation,
|
|
||||||
const std::shared_ptr<TransformOperation> &targetOperation,
|
|
||||||
TransformOperations &sourceResult,
|
|
||||||
TransformOperations &targetResult) const;
|
|
||||||
std::shared_ptr<TransformOperation> getDefaultOperationOfType(
|
|
||||||
TransformOp type) const;
|
|
||||||
|
|
||||||
size_t getIndexOfCurrentKeyframe(
|
|
||||||
const std::shared_ptr<KeyframeProgressProvider> &progressProvider) const;
|
|
||||||
TransformOperations getFallbackValue(
|
|
||||||
const std::shared_ptr<const ShadowNode> &shadowNode) const;
|
|
||||||
TransformOperations interpolateOperations(
|
|
||||||
const std::shared_ptr<const ShadowNode> &shadowNode,
|
|
||||||
double keyframeProgress,
|
|
||||||
const TransformOperations &fromOperations,
|
|
||||||
const TransformOperations &toOperations) const;
|
|
||||||
|
|
||||||
static folly::dynamic convertResultToDynamic(
|
|
||||||
const TransformOperations &operations);
|
|
||||||
TransformInterpolatorUpdateContext createUpdateContext(
|
|
||||||
const std::shared_ptr<const ShadowNode> &shadowNode) const;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace reanimated::css
|
|
||||||
Generated
Vendored
-136
@@ -1,136 +0,0 @@
|
|||||||
#include <reanimated/CSS/interpolation/transforms/operations/matrix.h>
|
|
||||||
|
|
||||||
namespace reanimated::css {
|
|
||||||
|
|
||||||
// Matrix
|
|
||||||
std::variant<TransformMatrix3D, TransformOperations> simplifyOperations(
|
|
||||||
const TransformOperations &operations) {
|
|
||||||
// Initialize the stack with the reversed list of operations
|
|
||||||
std::vector<std::shared_ptr<TransformOperation>> operationsStack(
|
|
||||||
operations.begin(), operations.end());
|
|
||||||
TransformOperations reversedOperations;
|
|
||||||
TransformMatrix3D simplifiedMatrix = TransformMatrix3D::Identity();
|
|
||||||
bool hasSimplifications = false;
|
|
||||||
|
|
||||||
while (!operationsStack.empty()) {
|
|
||||||
auto operation = operationsStack.back();
|
|
||||||
operationsStack.pop_back();
|
|
||||||
|
|
||||||
if (operation->type() == TransformOp::Matrix) {
|
|
||||||
const auto matrixOperation =
|
|
||||||
std::static_pointer_cast<MatrixOperation>(operation);
|
|
||||||
if (std::holds_alternative<TransformOperations>(matrixOperation->value)) {
|
|
||||||
// If the current operation is a matrix created from other operations,
|
|
||||||
// add all of these operations to the stack
|
|
||||||
for (auto &op : std::get<TransformOperations>(matrixOperation->value)) {
|
|
||||||
operationsStack.push_back(op);
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!operation->isRelative()) {
|
|
||||||
// If the operation is not relative, it can be simplified (converted to
|
|
||||||
// the matrix and multiplied)
|
|
||||||
const auto operationMatrix = operation->toMatrix();
|
|
||||||
simplifiedMatrix = hasSimplifications
|
|
||||||
? (simplifiedMatrix * operationMatrix)
|
|
||||||
: operationMatrix;
|
|
||||||
hasSimplifications = true;
|
|
||||||
} else {
|
|
||||||
// If the current operation is relative, we need to add the current
|
|
||||||
// simplified matrix to the list of operations before adding the
|
|
||||||
// relative operation
|
|
||||||
if (hasSimplifications) {
|
|
||||||
reversedOperations.emplace_back(
|
|
||||||
std::make_shared<MatrixOperation>(simplifiedMatrix));
|
|
||||||
simplifiedMatrix = TransformMatrix3D::Identity();
|
|
||||||
hasSimplifications = false;
|
|
||||||
}
|
|
||||||
reversedOperations.emplace_back(operation);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hasSimplifications) {
|
|
||||||
// We can return just a single matrix if there are no operations or the
|
|
||||||
// only operation is a simplified matrix (when hasSimplifications is true)
|
|
||||||
if (reversedOperations.size() <= 1) {
|
|
||||||
return simplifiedMatrix;
|
|
||||||
}
|
|
||||||
// Otherwise, add the last simplified matrix to the list of operations
|
|
||||||
reversedOperations.emplace_back(
|
|
||||||
std::make_shared<MatrixOperation>(simplifiedMatrix));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reverse the list of operations to maintain the order
|
|
||||||
std::reverse(reversedOperations.begin(), reversedOperations.end());
|
|
||||||
return reversedOperations;
|
|
||||||
}
|
|
||||||
|
|
||||||
MatrixOperation::MatrixOperation(const TransformMatrix3D &value)
|
|
||||||
: TransformOperationBase<
|
|
||||||
TransformOp::Matrix,
|
|
||||||
std::variant<TransformMatrix3D, TransformOperations>>(value) {}
|
|
||||||
|
|
||||||
MatrixOperation::MatrixOperation(const TransformOperations &operations)
|
|
||||||
// Simplify operations to reduce the number of matrix multiplications
|
|
||||||
// during matrix keyframe interpolation
|
|
||||||
: TransformOperationBase<
|
|
||||||
TransformOp::Matrix,
|
|
||||||
std::variant<TransformMatrix3D, TransformOperations>>(
|
|
||||||
simplifyOperations(operations)) {}
|
|
||||||
|
|
||||||
bool MatrixOperation::operator==(const TransformOperation &other) const {
|
|
||||||
if (type() != other.type()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto *otherOperation = dynamic_cast<const MatrixOperation *>(&other);
|
|
||||||
if (otherOperation == nullptr) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto hasOperations = std::holds_alternative<TransformOperations>(value);
|
|
||||||
const auto otherHasOperations =
|
|
||||||
std::holds_alternative<TransformOperations>(otherOperation->value);
|
|
||||||
|
|
||||||
if (hasOperations != otherHasOperations) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!hasOperations) {
|
|
||||||
return std::get<TransformMatrix3D>(value) ==
|
|
||||||
std::get<TransformMatrix3D>(otherOperation->value);
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto &operations = std::get<TransformOperations>(value);
|
|
||||||
const auto &otherOperations =
|
|
||||||
std::get<TransformOperations>(otherOperation->value);
|
|
||||||
|
|
||||||
if (operations.size() != otherOperations.size()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
for (size_t i = 0; i < operations.size(); ++i) {
|
|
||||||
if (*operations[i] != *otherOperations[i]) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
folly::dynamic MatrixOperation::valueToDynamic() const {
|
|
||||||
if (!std::holds_alternative<TransformMatrix3D>(value)) {
|
|
||||||
throw std::invalid_argument(
|
|
||||||
"[Reanimated] Cannot convert unprocessed transform operations to the dynamic value.");
|
|
||||||
}
|
|
||||||
return std::get<TransformMatrix3D>(value).toDynamic();
|
|
||||||
}
|
|
||||||
|
|
||||||
TransformMatrix3D MatrixOperation::toMatrix() const {
|
|
||||||
if (!std::holds_alternative<TransformMatrix3D>(value)) {
|
|
||||||
throw std::invalid_argument(
|
|
||||||
"[Reanimated] Cannot convert unprocessed transform operations to the matrix.");
|
|
||||||
}
|
|
||||||
return std::get<TransformMatrix3D>(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace reanimated::css
|
|
||||||
Generated
Vendored
-29
@@ -1,29 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <reanimated/CSS/interpolation/transforms/TransformOperation.h>
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace reanimated::css {
|
|
||||||
|
|
||||||
// Matrix
|
|
||||||
struct MatrixOperation final
|
|
||||||
: public TransformOperationBase<
|
|
||||||
TransformOp::Matrix,
|
|
||||||
std::variant<TransformMatrix3D, TransformOperations>> {
|
|
||||||
using TransformOperationBase<
|
|
||||||
TransformOp::Matrix,
|
|
||||||
std::variant<TransformMatrix3D, TransformOperations>>::
|
|
||||||
TransformOperationBase;
|
|
||||||
|
|
||||||
explicit MatrixOperation(const TransformMatrix3D &value);
|
|
||||||
explicit MatrixOperation(const TransformOperations &operations);
|
|
||||||
|
|
||||||
bool operator==(const TransformOperation &other) const override;
|
|
||||||
|
|
||||||
folly::dynamic valueToDynamic() const override;
|
|
||||||
TransformMatrix3D toMatrix() const override;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace reanimated::css
|
|
||||||
Generated
Vendored
-25
@@ -1,25 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <reanimated/CSS/interpolation/transforms/TransformOperation.h>
|
|
||||||
|
|
||||||
namespace reanimated::css {
|
|
||||||
|
|
||||||
struct PerspectiveOperation final
|
|
||||||
: public TransformOperationBase<TransformOp::Perspective, CSSDouble> {
|
|
||||||
using TransformOperationBase<TransformOp::Perspective, CSSDouble>::
|
|
||||||
TransformOperationBase;
|
|
||||||
|
|
||||||
explicit PerspectiveOperation(double value)
|
|
||||||
: TransformOperationBase<TransformOp::Perspective, CSSDouble>(
|
|
||||||
CSSDouble(value)) {}
|
|
||||||
|
|
||||||
folly::dynamic valueToDynamic() const override {
|
|
||||||
return value.value != 0 ? value.toDynamic() : folly::dynamic();
|
|
||||||
}
|
|
||||||
|
|
||||||
TransformMatrix3D toMatrix() const override {
|
|
||||||
return TransformMatrix3D::create<TransformOp::Perspective>(value.value);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace reanimated::css
|
|
||||||
Generated
Vendored
-47
@@ -1,47 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <reanimated/CSS/interpolation/transforms/TransformOperation.h>
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
namespace reanimated::css {
|
|
||||||
|
|
||||||
template <TransformOp TOperation>
|
|
||||||
struct RotateOperationBase
|
|
||||||
: public TransformOperationBase<TOperation, CSSAngle> {
|
|
||||||
using TransformOperationBase<TOperation, CSSAngle>::TransformOperationBase;
|
|
||||||
|
|
||||||
explicit RotateOperationBase(const std::string &value)
|
|
||||||
: TransformOperationBase<TOperation, CSSAngle>(CSSAngle(value)) {}
|
|
||||||
|
|
||||||
folly::dynamic valueToDynamic() const override {
|
|
||||||
return this->value.toDynamic();
|
|
||||||
}
|
|
||||||
|
|
||||||
TransformMatrix3D toMatrix() const override {
|
|
||||||
return TransformMatrix3D::create<TOperation>(this->value.value);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
using RotateOperation = RotateOperationBase<TransformOp::Rotate>;
|
|
||||||
|
|
||||||
using RotateXOperation = RotateOperationBase<TransformOp::RotateX>;
|
|
||||||
|
|
||||||
using RotateYOperation = RotateOperationBase<TransformOp::RotateY>;
|
|
||||||
|
|
||||||
struct RotateZOperation final
|
|
||||||
: public RotateOperationBase<TransformOp::RotateZ> {
|
|
||||||
using RotateOperationBase<TransformOp::RotateZ>::RotateOperationBase;
|
|
||||||
|
|
||||||
bool canConvertTo(TransformOp type) const override {
|
|
||||||
return type == TransformOp::Rotate;
|
|
||||||
}
|
|
||||||
|
|
||||||
TransformOperations convertTo(TransformOp type) const override {
|
|
||||||
assertCanConvertTo(type);
|
|
||||||
return {std::make_shared<RotateOperation>(value)};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace reanimated::css
|
|
||||||
Generated
Vendored
-51
@@ -1,51 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <reanimated/CSS/interpolation/transforms/TransformOperation.h>
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
namespace reanimated::css {
|
|
||||||
|
|
||||||
template <TransformOp TOperation>
|
|
||||||
struct ScaleOperationBase
|
|
||||||
: public TransformOperationBase<TOperation, CSSDouble> {
|
|
||||||
using TransformOperationBase<TOperation, CSSDouble>::TransformOperationBase;
|
|
||||||
|
|
||||||
explicit ScaleOperationBase(const double value)
|
|
||||||
: TransformOperationBase<TOperation, CSSDouble>(CSSDouble(value)) {}
|
|
||||||
|
|
||||||
folly::dynamic valueToDynamic() const override {
|
|
||||||
return this->value.toDynamic();
|
|
||||||
}
|
|
||||||
|
|
||||||
TransformMatrix3D toMatrix() const override {
|
|
||||||
return TransformMatrix3D::create<TOperation>(this->value.value);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
using ScaleXOperation = ScaleOperationBase<TransformOp::ScaleX>;
|
|
||||||
|
|
||||||
using ScaleYOperation = ScaleOperationBase<TransformOp::ScaleY>;
|
|
||||||
|
|
||||||
struct ScaleOperation final : public ScaleOperationBase<TransformOp::Scale> {
|
|
||||||
using ScaleOperationBase<TransformOp::Scale>::ScaleOperationBase;
|
|
||||||
|
|
||||||
bool canConvertTo(TransformOp type) const override {
|
|
||||||
return type == TransformOp::ScaleX || type == TransformOp::ScaleY;
|
|
||||||
}
|
|
||||||
|
|
||||||
TransformOperations convertTo(TransformOp type) const override {
|
|
||||||
assertCanConvertTo(type);
|
|
||||||
if (type == TransformOp::ScaleX) {
|
|
||||||
return {
|
|
||||||
std::make_shared<ScaleXOperation>(value),
|
|
||||||
std::make_shared<ScaleYOperation>(value)};
|
|
||||||
} else {
|
|
||||||
return {
|
|
||||||
std::make_shared<ScaleYOperation>(value),
|
|
||||||
std::make_shared<ScaleXOperation>(value)};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace reanimated::css
|
|
||||||
Generated
Vendored
-29
@@ -1,29 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <reanimated/CSS/interpolation/transforms/TransformOperation.h>
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
namespace reanimated::css {
|
|
||||||
|
|
||||||
template <TransformOp TOperation>
|
|
||||||
struct SkewOperationBase : public TransformOperationBase<TOperation, CSSAngle> {
|
|
||||||
using TransformOperationBase<TOperation, CSSAngle>::TransformOperationBase;
|
|
||||||
|
|
||||||
explicit SkewOperationBase(const std::string &value)
|
|
||||||
: TransformOperationBase<TOperation, CSSAngle>(CSSAngle(value)) {}
|
|
||||||
|
|
||||||
folly::dynamic valueToDynamic() const override {
|
|
||||||
return this->value.toDynamic();
|
|
||||||
}
|
|
||||||
|
|
||||||
TransformMatrix3D toMatrix() const override {
|
|
||||||
return TransformMatrix3D::create<TOperation>(this->value.value);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
using SkewXOperation = SkewOperationBase<TransformOp::SkewX>;
|
|
||||||
|
|
||||||
using SkewYOperation = SkewOperationBase<TransformOp::SkewY>;
|
|
||||||
|
|
||||||
} // namespace reanimated::css
|
|
||||||
Generated
Vendored
-40
@@ -1,40 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <reanimated/CSS/interpolation/transforms/TransformOperation.h>
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
namespace reanimated::css {
|
|
||||||
|
|
||||||
template <TransformOp TOperation>
|
|
||||||
struct TranslateOperationBase
|
|
||||||
: public TransformOperationBase<TOperation, CSSLength> {
|
|
||||||
using TransformOperationBase<TOperation, CSSLength>::TransformOperationBase;
|
|
||||||
|
|
||||||
explicit TranslateOperationBase(double value)
|
|
||||||
: TransformOperationBase<TOperation, CSSLength>(CSSLength(value)) {}
|
|
||||||
explicit TranslateOperationBase(const std::string &value)
|
|
||||||
: TransformOperationBase<TOperation, CSSLength>(CSSLength(value)) {}
|
|
||||||
|
|
||||||
bool isRelative() const override {
|
|
||||||
return this->value.isRelative;
|
|
||||||
}
|
|
||||||
|
|
||||||
folly::dynamic valueToDynamic() const override {
|
|
||||||
return this->value.toDynamic();
|
|
||||||
}
|
|
||||||
|
|
||||||
TransformMatrix3D toMatrix() const override {
|
|
||||||
if (this->value.isRelative) {
|
|
||||||
throw std::invalid_argument(
|
|
||||||
"[Reanimated] Cannot convert relative translate to the matrix.");
|
|
||||||
}
|
|
||||||
return TransformMatrix3D::create<TOperation>(this->value.value);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
using TranslateXOperation = TranslateOperationBase<TransformOp::TranslateX>;
|
|
||||||
|
|
||||||
using TranslateYOperation = TranslateOperationBase<TransformOp::TranslateY>;
|
|
||||||
|
|
||||||
} // namespace reanimated::css
|
|
||||||
Generated
Vendored
-49
@@ -1,49 +0,0 @@
|
|||||||
#include <reanimated/CSS/interpolation/values/ResolvableValueInterpolator.h>
|
|
||||||
|
|
||||||
#include <reanimated/CSS/common/values/CSSAngle.h>
|
|
||||||
#include <reanimated/CSS/common/values/CSSKeyword.h>
|
|
||||||
#include <reanimated/CSS/common/values/CSSLength.h>
|
|
||||||
#include <reanimated/CSS/common/values/CSSNumber.h>
|
|
||||||
|
|
||||||
#include <folly/dynamic.h>
|
|
||||||
#include <jsi/jsi.h>
|
|
||||||
|
|
||||||
namespace reanimated::css {
|
|
||||||
|
|
||||||
template <typename... AllowedTypes>
|
|
||||||
ResolvableValueInterpolator<AllowedTypes...>::ResolvableValueInterpolator(
|
|
||||||
const PropertyPath &propertyPath,
|
|
||||||
const ValueType &defaultStyleValue,
|
|
||||||
const std::shared_ptr<ViewStylesRepository> &viewStylesRepository,
|
|
||||||
RelativeTo relativeTo,
|
|
||||||
std::string relativeProperty)
|
|
||||||
: SimpleValueInterpolator<AllowedTypes...>(
|
|
||||||
propertyPath,
|
|
||||||
defaultStyleValue,
|
|
||||||
viewStylesRepository),
|
|
||||||
relativeTo_(relativeTo),
|
|
||||||
relativeProperty_(relativeProperty) {}
|
|
||||||
|
|
||||||
template <typename... AllowedTypes>
|
|
||||||
folly::dynamic ResolvableValueInterpolator<AllowedTypes...>::interpolateValue(
|
|
||||||
double progress,
|
|
||||||
const std::shared_ptr<CSSValue> &fromValue,
|
|
||||||
const std::shared_ptr<CSSValue> &toValue,
|
|
||||||
const ValueInterpolatorUpdateContext &context) const {
|
|
||||||
const auto &from = std::static_pointer_cast<ValueType>(fromValue);
|
|
||||||
const auto &to = std::static_pointer_cast<ValueType>(toValue);
|
|
||||||
return from
|
|
||||||
->interpolate(
|
|
||||||
progress,
|
|
||||||
*to,
|
|
||||||
{.node = context.node,
|
|
||||||
.viewStylesRepository = this->viewStylesRepository_,
|
|
||||||
.relativeProperty = relativeProperty_,
|
|
||||||
.relativeTo = relativeTo_})
|
|
||||||
.toDynamic();
|
|
||||||
}
|
|
||||||
|
|
||||||
template class ResolvableValueInterpolator<CSSLength>;
|
|
||||||
template class ResolvableValueInterpolator<CSSLength, CSSKeyword>;
|
|
||||||
|
|
||||||
} // namespace reanimated::css
|
|
||||||
Generated
Vendored
-49
@@ -1,49 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <reanimated/CSS/common/values/CSSLength.h>
|
|
||||||
#include <reanimated/CSS/interpolation/values/SimpleValueInterpolator.h>
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <string>
|
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
namespace reanimated::css {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Concrete implementation of ValueInterpolator for CSS values that require
|
|
||||||
* resolution before interpolation. This class handles interpolation of relative
|
|
||||||
* values (e.g., percentage length values) that need to be resolved to absolute
|
|
||||||
* values using the context describing the ShadowNode before the interpolation
|
|
||||||
* can occur.
|
|
||||||
*/
|
|
||||||
template <typename... AllowedTypes>
|
|
||||||
class ResolvableValueInterpolator final
|
|
||||||
: public SimpleValueInterpolator<AllowedTypes...> {
|
|
||||||
static_assert(
|
|
||||||
(... && std::is_base_of<CSSValue, AllowedTypes>::value),
|
|
||||||
"[Reanimated] ResolvableValueInterpolator: All interpolated types must inherit from CSSValue");
|
|
||||||
|
|
||||||
public:
|
|
||||||
using ValueType =
|
|
||||||
typename SimpleValueInterpolator<AllowedTypes...>::ValueType;
|
|
||||||
|
|
||||||
explicit ResolvableValueInterpolator(
|
|
||||||
const PropertyPath &propertyPath,
|
|
||||||
const ValueType &defaultStyleValue,
|
|
||||||
const std::shared_ptr<ViewStylesRepository> &viewStylesRepository,
|
|
||||||
RelativeTo relativeTo,
|
|
||||||
std::string relativeProperty);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
folly::dynamic interpolateValue(
|
|
||||||
double progress,
|
|
||||||
const std::shared_ptr<CSSValue> &fromValue,
|
|
||||||
const std::shared_ptr<CSSValue> &toValue,
|
|
||||||
const ValueInterpolatorUpdateContext &context) const override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
RelativeTo relativeTo_;
|
|
||||||
std::string relativeProperty_;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace reanimated::css
|
|
||||||
Generated
Vendored
-71
@@ -1,71 +0,0 @@
|
|||||||
#include <reanimated/CSS/interpolation/values/SimpleValueInterpolator.h>
|
|
||||||
|
|
||||||
#include <folly/dynamic.h>
|
|
||||||
#include <jsi/jsi.h>
|
|
||||||
|
|
||||||
#include <reanimated/CSS/common/values/CSSAngle.h>
|
|
||||||
#include <reanimated/CSS/common/values/CSSBoolean.h>
|
|
||||||
#include <reanimated/CSS/common/values/CSSColor.h>
|
|
||||||
#include <reanimated/CSS/common/values/CSSDiscreteArray.h>
|
|
||||||
#include <reanimated/CSS/common/values/CSSKeyword.h>
|
|
||||||
#include <reanimated/CSS/common/values/CSSLength.h>
|
|
||||||
#include <reanimated/CSS/common/values/CSSNumber.h>
|
|
||||||
#include <reanimated/CSS/svg/values/SVGLength.h>
|
|
||||||
#include <reanimated/CSS/svg/values/SVGStrokeDashArray.h>
|
|
||||||
|
|
||||||
namespace reanimated::css {
|
|
||||||
|
|
||||||
template <typename... AllowedTypes>
|
|
||||||
SimpleValueInterpolator<AllowedTypes...>::SimpleValueInterpolator(
|
|
||||||
const PropertyPath &propertyPath,
|
|
||||||
const ValueType &defaultStyleValue,
|
|
||||||
const std::shared_ptr<ViewStylesRepository> &viewStylesRepository)
|
|
||||||
: ValueInterpolator(
|
|
||||||
propertyPath,
|
|
||||||
std::make_shared<ValueType>(defaultStyleValue),
|
|
||||||
viewStylesRepository) {}
|
|
||||||
|
|
||||||
template <typename... AllowedTypes>
|
|
||||||
std::shared_ptr<CSSValue> SimpleValueInterpolator<AllowedTypes...>::createValue(
|
|
||||||
jsi::Runtime &rt,
|
|
||||||
const jsi::Value &value) const {
|
|
||||||
return std::make_shared<ValueType>(rt, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename... AllowedTypes>
|
|
||||||
std::shared_ptr<CSSValue> SimpleValueInterpolator<AllowedTypes...>::createValue(
|
|
||||||
const folly::dynamic &value) const {
|
|
||||||
return std::make_shared<ValueType>(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename... AllowedTypes>
|
|
||||||
folly::dynamic SimpleValueInterpolator<AllowedTypes...>::interpolateValue(
|
|
||||||
double progress,
|
|
||||||
const std::shared_ptr<CSSValue> &fromValue,
|
|
||||||
const std::shared_ptr<CSSValue> &toValue,
|
|
||||||
const ValueInterpolatorUpdateContext &context) const {
|
|
||||||
const auto &from = std::static_pointer_cast<ValueType>(fromValue);
|
|
||||||
const auto &to = std::static_pointer_cast<ValueType>(toValue);
|
|
||||||
return from->interpolate(progress, *to, context).toDynamic();
|
|
||||||
}
|
|
||||||
|
|
||||||
template class SimpleValueInterpolator<CSSLength>;
|
|
||||||
template class SimpleValueInterpolator<CSSLength, CSSKeyword>;
|
|
||||||
template class SimpleValueInterpolator<CSSDouble>;
|
|
||||||
template class SimpleValueInterpolator<CSSDouble, CSSKeyword>;
|
|
||||||
template class SimpleValueInterpolator<CSSInteger>;
|
|
||||||
template class SimpleValueInterpolator<CSSAngle>;
|
|
||||||
template class SimpleValueInterpolator<CSSColor>;
|
|
||||||
template class SimpleValueInterpolator<CSSBoolean>;
|
|
||||||
template class SimpleValueInterpolator<CSSDisplay>;
|
|
||||||
template class SimpleValueInterpolator<CSSKeyword>;
|
|
||||||
template class SimpleValueInterpolator<CSSDiscreteArray<CSSKeyword>>;
|
|
||||||
#ifdef ANDROID
|
|
||||||
template class SimpleValueInterpolator<CSSShadowRadiusAndroid>;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
template class SimpleValueInterpolator<SVGLength>;
|
|
||||||
template class SimpleValueInterpolator<SVGLength, CSSKeyword>;
|
|
||||||
template class SimpleValueInterpolator<SVGStrokeDashArray, CSSKeyword>;
|
|
||||||
|
|
||||||
} // namespace reanimated::css
|
|
||||||
Generated
Vendored
-43
@@ -1,43 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <reanimated/CSS/interpolation/values/ValueInterpolator.h>
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
namespace reanimated::css {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Concrete implementation of ValueInterpolator for simple CSS values that don't
|
|
||||||
* require resolution before interpolation. This class handles direct
|
|
||||||
* interpolation between values without any additional processing or resolution.
|
|
||||||
*/
|
|
||||||
template <typename... AllowedTypes>
|
|
||||||
class SimpleValueInterpolator : public ValueInterpolator {
|
|
||||||
static_assert(
|
|
||||||
(... && std::is_base_of<CSSValue, AllowedTypes>::value),
|
|
||||||
"[Reanimated] SimpleValueInterpolator: All interpolated types must inherit from CSSValue");
|
|
||||||
|
|
||||||
public:
|
|
||||||
using ValueType = CSSValueVariant<AllowedTypes...>;
|
|
||||||
|
|
||||||
explicit SimpleValueInterpolator(
|
|
||||||
const PropertyPath &propertyPath,
|
|
||||||
const ValueType &defaultStyleValue,
|
|
||||||
const std::shared_ptr<ViewStylesRepository> &viewStylesRepository);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
std::shared_ptr<CSSValue> createValue(
|
|
||||||
jsi::Runtime &rt,
|
|
||||||
const jsi::Value &value) const override;
|
|
||||||
|
|
||||||
std::shared_ptr<CSSValue> createValue(
|
|
||||||
const folly::dynamic &value) const override;
|
|
||||||
|
|
||||||
folly::dynamic interpolateValue(
|
|
||||||
double progress,
|
|
||||||
const std::shared_ptr<CSSValue> &fromValue,
|
|
||||||
const std::shared_ptr<CSSValue> &toValue,
|
|
||||||
const ValueInterpolatorUpdateContext &context) const override;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace reanimated::css
|
|
||||||
Generated
Vendored
-153
@@ -1,153 +0,0 @@
|
|||||||
#include <reanimated/CSS/interpolation/values/ValueInterpolator.h>
|
|
||||||
|
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
namespace reanimated::css {
|
|
||||||
|
|
||||||
ValueInterpolator::ValueInterpolator(
|
|
||||||
const PropertyPath &propertyPath,
|
|
||||||
const std::shared_ptr<CSSValue> &defaultValue,
|
|
||||||
const std::shared_ptr<ViewStylesRepository> &viewStylesRepository)
|
|
||||||
: PropertyInterpolator(propertyPath, viewStylesRepository),
|
|
||||||
defaultStyleValue_(defaultValue),
|
|
||||||
defaultStyleValueDynamic_(defaultValue->toDynamic()) {}
|
|
||||||
|
|
||||||
folly::dynamic ValueInterpolator::getStyleValue(
|
|
||||||
const std::shared_ptr<const ShadowNode> &shadowNode) const {
|
|
||||||
return viewStylesRepository_->getStyleProp(
|
|
||||||
shadowNode->getTag(), propertyPath_);
|
|
||||||
}
|
|
||||||
|
|
||||||
folly::dynamic ValueInterpolator::getResetStyle(
|
|
||||||
const std::shared_ptr<const ShadowNode> &shadowNode) const {
|
|
||||||
auto styleValue = getStyleValue(shadowNode);
|
|
||||||
|
|
||||||
if (styleValue.isNull()) {
|
|
||||||
return defaultStyleValueDynamic_;
|
|
||||||
}
|
|
||||||
|
|
||||||
return styleValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
folly::dynamic ValueInterpolator::getFirstKeyframeValue() const {
|
|
||||||
return convertOptionalToDynamic(keyframes_.front().value);
|
|
||||||
}
|
|
||||||
|
|
||||||
folly::dynamic ValueInterpolator::getLastKeyframeValue() const {
|
|
||||||
return convertOptionalToDynamic(keyframes_.back().value);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ValueInterpolator::equalsReversingAdjustedStartValue(
|
|
||||||
const folly::dynamic &propertyValue) const {
|
|
||||||
if (reversingAdjustedStartValue_.isNull()) {
|
|
||||||
return propertyValue.isNull();
|
|
||||||
}
|
|
||||||
return reversingAdjustedStartValue_ == propertyValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ValueInterpolator::updateKeyframes(
|
|
||||||
jsi::Runtime &rt,
|
|
||||||
const jsi::Value &keyframes) {
|
|
||||||
const auto parsedKeyframes = parseJSIKeyframes(rt, keyframes);
|
|
||||||
|
|
||||||
keyframes_.clear();
|
|
||||||
keyframes_.reserve(parsedKeyframes.size());
|
|
||||||
|
|
||||||
for (const auto &[offset, value] : parsedKeyframes) {
|
|
||||||
if (value.isUndefined()) {
|
|
||||||
keyframes_.emplace_back(offset, std::nullopt);
|
|
||||||
} else {
|
|
||||||
keyframes_.emplace_back(
|
|
||||||
offset, std::make_optional(createValue(rt, value)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ValueInterpolator::updateKeyframesFromStyleChange(
|
|
||||||
const folly::dynamic &oldStyleValue,
|
|
||||||
const folly::dynamic &newStyleValue,
|
|
||||||
const folly::dynamic &lastUpdateValue) {
|
|
||||||
ValueKeyframe firstKeyframe, lastKeyframe;
|
|
||||||
|
|
||||||
if (!lastUpdateValue.isNull()) {
|
|
||||||
firstKeyframe = ValueKeyframe{0, createValue(lastUpdateValue)};
|
|
||||||
} else if (!oldStyleValue.isNull()) {
|
|
||||||
firstKeyframe = ValueKeyframe{0, createValue(oldStyleValue)};
|
|
||||||
} else {
|
|
||||||
firstKeyframe = ValueKeyframe{0, defaultStyleValue_};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (newStyleValue.isNull()) {
|
|
||||||
lastKeyframe = ValueKeyframe{1, defaultStyleValue_};
|
|
||||||
} else {
|
|
||||||
lastKeyframe = ValueKeyframe{1, createValue(newStyleValue)};
|
|
||||||
}
|
|
||||||
|
|
||||||
keyframes_ = {std::move(firstKeyframe), std::move(lastKeyframe)};
|
|
||||||
reversingAdjustedStartValue_ = oldStyleValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
folly::dynamic ValueInterpolator::interpolate(
|
|
||||||
const std::shared_ptr<const ShadowNode> &shadowNode,
|
|
||||||
const std::shared_ptr<KeyframeProgressProvider> &progressProvider) const {
|
|
||||||
const auto toIndex = getToKeyframeIndex(progressProvider);
|
|
||||||
const auto fromIndex = toIndex - 1;
|
|
||||||
|
|
||||||
const auto &fromKeyframe = keyframes_[fromIndex];
|
|
||||||
const auto &toKeyframe = keyframes_[toIndex];
|
|
||||||
|
|
||||||
// clang-format off
|
|
||||||
const auto &fromValue = fromKeyframe.value
|
|
||||||
? fromKeyframe.value.value()
|
|
||||||
: getFallbackValue(shadowNode);
|
|
||||||
const auto &toValue = toKeyframe.value
|
|
||||||
? toKeyframe.value.value()
|
|
||||||
: getFallbackValue(shadowNode);
|
|
||||||
// clang-format on
|
|
||||||
|
|
||||||
const auto keyframeProgress = progressProvider->getKeyframeProgress(
|
|
||||||
fromKeyframe.offset, toKeyframe.offset);
|
|
||||||
|
|
||||||
if (keyframeProgress == 1.0) {
|
|
||||||
return toValue->toDynamic();
|
|
||||||
}
|
|
||||||
if (keyframeProgress == 0.0) {
|
|
||||||
return fromValue->toDynamic();
|
|
||||||
}
|
|
||||||
|
|
||||||
return interpolateValue(
|
|
||||||
keyframeProgress, fromValue, toValue, {.node = shadowNode});
|
|
||||||
}
|
|
||||||
|
|
||||||
folly::dynamic ValueInterpolator::convertOptionalToDynamic(
|
|
||||||
const std::optional<std::shared_ptr<CSSValue>> &value) const {
|
|
||||||
return value ? value.value()->toDynamic() : folly::dynamic();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<CSSValue> ValueInterpolator::getFallbackValue(
|
|
||||||
const std::shared_ptr<const ShadowNode> &shadowNode) const {
|
|
||||||
const auto styleValue = getStyleValue(shadowNode);
|
|
||||||
return styleValue.isNull() ? defaultStyleValue_ : createValue(styleValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t ValueInterpolator::getToKeyframeIndex(
|
|
||||||
const std::shared_ptr<KeyframeProgressProvider> &progressProvider) const {
|
|
||||||
const auto progress = progressProvider->getGlobalProgress();
|
|
||||||
|
|
||||||
const auto it = std::upper_bound(
|
|
||||||
keyframes_.begin(),
|
|
||||||
keyframes_.end(),
|
|
||||||
progress,
|
|
||||||
[](double progress, const ValueKeyframe &keyframe) {
|
|
||||||
return progress < keyframe.offset;
|
|
||||||
});
|
|
||||||
|
|
||||||
// If we're at the end, return the last valid keyframe index
|
|
||||||
if (it == keyframes_.end()) {
|
|
||||||
return keyframes_.size() - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return std::distance(keyframes_.begin(), it);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace reanimated::css
|
|
||||||
Generated
Vendored
-78
@@ -1,78 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <reanimated/CSS/common/values/CSSValueVariant.h>
|
|
||||||
#include <reanimated/CSS/interpolation/PropertyInterpolator.h>
|
|
||||||
#include <reanimated/CSS/utils/keyframes.h>
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <optional>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace reanimated::css {
|
|
||||||
|
|
||||||
struct ValueKeyframe {
|
|
||||||
double offset;
|
|
||||||
std::optional<std::shared_ptr<CSSValue>> value;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Base class for CSS value interpolators that provides common functionality
|
|
||||||
* for interpolating CSS values during animations. This class should be extended
|
|
||||||
* by concrete implementations for specific CSS value types to provide
|
|
||||||
* type-specific interpolation logic.
|
|
||||||
*/
|
|
||||||
class ValueInterpolator : public PropertyInterpolator {
|
|
||||||
public:
|
|
||||||
explicit ValueInterpolator(
|
|
||||||
const PropertyPath &propertyPath,
|
|
||||||
const std::shared_ptr<CSSValue> &defaultValue,
|
|
||||||
const std::shared_ptr<ViewStylesRepository> &viewStylesRepository);
|
|
||||||
virtual ~ValueInterpolator() = default;
|
|
||||||
|
|
||||||
folly::dynamic getStyleValue(
|
|
||||||
const std::shared_ptr<const ShadowNode> &shadowNode) const override;
|
|
||||||
folly::dynamic getResetStyle(
|
|
||||||
const std::shared_ptr<const ShadowNode> &shadowNode) const override;
|
|
||||||
folly::dynamic getFirstKeyframeValue() const override;
|
|
||||||
folly::dynamic getLastKeyframeValue() const override;
|
|
||||||
bool equalsReversingAdjustedStartValue(
|
|
||||||
const folly::dynamic &propertyValue) const override;
|
|
||||||
|
|
||||||
void updateKeyframes(jsi::Runtime &rt, const jsi::Value &keyframes) override;
|
|
||||||
void updateKeyframesFromStyleChange(
|
|
||||||
const folly::dynamic &oldStyleValue,
|
|
||||||
const folly::dynamic &newStyleValue,
|
|
||||||
const folly::dynamic &lastUpdateValue) override;
|
|
||||||
|
|
||||||
folly::dynamic interpolate(
|
|
||||||
const std::shared_ptr<const ShadowNode> &shadowNode,
|
|
||||||
const std::shared_ptr<KeyframeProgressProvider> &progressProvider)
|
|
||||||
const override;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
std::vector<ValueKeyframe> keyframes_;
|
|
||||||
std::shared_ptr<CSSValue> defaultStyleValue_;
|
|
||||||
folly::dynamic defaultStyleValueDynamic_;
|
|
||||||
folly::dynamic reversingAdjustedStartValue_;
|
|
||||||
|
|
||||||
virtual std::shared_ptr<CSSValue> createValue(
|
|
||||||
jsi::Runtime &rt,
|
|
||||||
const jsi::Value &value) const = 0;
|
|
||||||
virtual std::shared_ptr<CSSValue> createValue(
|
|
||||||
const folly::dynamic &value) const = 0;
|
|
||||||
virtual folly::dynamic interpolateValue(
|
|
||||||
double progress,
|
|
||||||
const std::shared_ptr<CSSValue> &fromValue,
|
|
||||||
const std::shared_ptr<CSSValue> &toValue,
|
|
||||||
const ValueInterpolatorUpdateContext &context) const = 0;
|
|
||||||
|
|
||||||
private:
|
|
||||||
folly::dynamic convertOptionalToDynamic(
|
|
||||||
const std::optional<std::shared_ptr<CSSValue>> &value) const;
|
|
||||||
std::shared_ptr<CSSValue> getFallbackValue(
|
|
||||||
const std::shared_ptr<const ShadowNode> &shadowNode) const;
|
|
||||||
size_t getToKeyframeIndex(
|
|
||||||
const std::shared_ptr<KeyframeProgressProvider> &progressProvider) const;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace reanimated::css
|
|
||||||
Generated
Vendored
-164
@@ -1,164 +0,0 @@
|
|||||||
#include <reanimated/CSS/misc/ViewStylesRepository.h>
|
|
||||||
|
|
||||||
namespace reanimated::css {
|
|
||||||
|
|
||||||
ViewStylesRepository::ViewStylesRepository(
|
|
||||||
const std::shared_ptr<StaticPropsRegistry> &staticPropsRegistry,
|
|
||||||
const std::shared_ptr<AnimatedPropsRegistry> &animatedPropsRegistry)
|
|
||||||
: staticPropsRegistry_(staticPropsRegistry),
|
|
||||||
animatedPropsRegistry_(animatedPropsRegistry) {}
|
|
||||||
|
|
||||||
jsi::Value ViewStylesRepository::getNodeProp(
|
|
||||||
const std::shared_ptr<const ShadowNode> &shadowNode,
|
|
||||||
const std::string &propName) {
|
|
||||||
int tag = shadowNode->getTag();
|
|
||||||
|
|
||||||
auto &cachedNode = shadowNodeCache_[tag];
|
|
||||||
updateCacheIfNeeded(cachedNode, shadowNode);
|
|
||||||
|
|
||||||
if (propName == "width" || propName == "height" || propName == "top" ||
|
|
||||||
propName == "left") {
|
|
||||||
const auto &layoutMetrics = cachedNode.layoutMetrics;
|
|
||||||
|
|
||||||
if (propName == "width") {
|
|
||||||
return {layoutMetrics.frame.size.width};
|
|
||||||
} else if (propName == "height") {
|
|
||||||
return {layoutMetrics.frame.size.height};
|
|
||||||
} else if (propName == "top") {
|
|
||||||
return {layoutMetrics.frame.origin.y};
|
|
||||||
} else if (propName == "left") {
|
|
||||||
return {layoutMetrics.frame.origin.x};
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
const auto &viewProps = cachedNode.viewProps;
|
|
||||||
|
|
||||||
if (propName == "opacity") {
|
|
||||||
return {viewProps->opacity};
|
|
||||||
} else if (propName == "zIndex") {
|
|
||||||
return viewProps->zIndex.has_value() ? jsi::Value(*viewProps->zIndex)
|
|
||||||
: jsi::Value(0);
|
|
||||||
} else if (propName == "backgroundColor") {
|
|
||||||
return {static_cast<int32_t>(*viewProps->backgroundColor)};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
throw std::runtime_error("[Reanimated] Unsupported property: " + propName);
|
|
||||||
}
|
|
||||||
|
|
||||||
jsi::Value ViewStylesRepository::getParentNodeProp(
|
|
||||||
const std::shared_ptr<const ShadowNode> &shadowNode,
|
|
||||||
const std::string &propName) {
|
|
||||||
const auto surfaceId = shadowNode->getSurfaceId();
|
|
||||||
const auto &shadowTreeRegistry = uiManager_->getShadowTreeRegistry();
|
|
||||||
|
|
||||||
std::shared_ptr<const ShadowNode> parentNode = nullptr;
|
|
||||||
|
|
||||||
shadowTreeRegistry.visit(surfaceId, [&](ShadowTree const &shadowTree) {
|
|
||||||
auto currentRevision = shadowTree.getCurrentRevision();
|
|
||||||
parentNode =
|
|
||||||
dom::getParentNode(currentRevision.rootShadowNode, *shadowNode);
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!parentNode) {
|
|
||||||
return jsi::Value::undefined();
|
|
||||||
}
|
|
||||||
|
|
||||||
return getNodeProp(parentNode, propName);
|
|
||||||
}
|
|
||||||
|
|
||||||
folly::dynamic ViewStylesRepository::getStyleProp(
|
|
||||||
const Tag tag,
|
|
||||||
const PropertyPath &propertyPath) {
|
|
||||||
auto animatedValue =
|
|
||||||
getPropertyValue(animatedPropsRegistry_->get(tag), propertyPath);
|
|
||||||
if (!animatedValue.isNull()) {
|
|
||||||
return animatedValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
return getPropertyValue(staticPropsRegistry_->get(tag), propertyPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ViewStylesRepository::clearNodesCache() {
|
|
||||||
shadowNodeCache_.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ViewStylesRepository::updateCacheIfNeeded(
|
|
||||||
CachedShadowNode &cachedNode,
|
|
||||||
const std::shared_ptr<const ShadowNode> &shadowNode) {
|
|
||||||
auto newestCloneOfShadowNode =
|
|
||||||
uiManager_->getNewestCloneOfShadowNode(*shadowNode);
|
|
||||||
|
|
||||||
// Check if newestCloneOfShadowNode is valid (is already mounted / not
|
|
||||||
// yet unmounted)
|
|
||||||
if (!newestCloneOfShadowNode) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto layoutableShadowNode =
|
|
||||||
dynamic_cast<const LayoutableShadowNode *>(newestCloneOfShadowNode.get());
|
|
||||||
if (!layoutableShadowNode) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
cachedNode.layoutMetrics = layoutableShadowNode->layoutMetrics_;
|
|
||||||
cachedNode.viewProps = std::static_pointer_cast<const ViewProps>(
|
|
||||||
newestCloneOfShadowNode->getProps());
|
|
||||||
}
|
|
||||||
|
|
||||||
folly::dynamic ViewStylesRepository::getPropertyValue(
|
|
||||||
const folly::dynamic &value,
|
|
||||||
const PropertyPath &propertyPath) {
|
|
||||||
const folly::dynamic *currentValue = &value;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < propertyPath.size(); ++i) {
|
|
||||||
if (currentValue->isNull() || currentValue->empty()) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto &propName = propertyPath[i];
|
|
||||||
|
|
||||||
if (!currentValue->isObject()) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (propName == "transform") {
|
|
||||||
auto transformIt = currentValue->find("transform");
|
|
||||||
if (transformIt == currentValue->items().end()) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto &transform = transformIt->second;
|
|
||||||
if (!transform.isArray()) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i + 1 >= propertyPath.size()) {
|
|
||||||
return transform;
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::string &transformPropName = propertyPath[i + 1];
|
|
||||||
|
|
||||||
for (const auto &transformEntry : transform) {
|
|
||||||
if (transformEntry.isObject()) {
|
|
||||||
auto transformPropIt = transformEntry.find(transformPropName);
|
|
||||||
if (transformPropIt != transformEntry.items().end()) {
|
|
||||||
return transformPropIt->second;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
auto propIt = currentValue->find(propName);
|
|
||||||
if (propIt == currentValue->items().end()) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
currentValue = &propIt->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
return *currentValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace reanimated::css
|
|
||||||
Generated
Vendored
-61
@@ -1,61 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <reanimated/CSS/common/definitions.h>
|
|
||||||
#include <reanimated/CSS/registries/StaticPropsRegistry.h>
|
|
||||||
#include <reanimated/Fabric/updates/AnimatedPropsRegistry.h>
|
|
||||||
|
|
||||||
#include <react/renderer/components/view/ViewProps.h>
|
|
||||||
#include <react/renderer/core/LayoutableShadowNode.h>
|
|
||||||
#include <react/renderer/dom/DOM.h>
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <string>
|
|
||||||
#include <unordered_map>
|
|
||||||
|
|
||||||
namespace reanimated::css {
|
|
||||||
|
|
||||||
using namespace facebook;
|
|
||||||
using namespace react;
|
|
||||||
|
|
||||||
struct CachedShadowNode {
|
|
||||||
LayoutMetrics layoutMetrics;
|
|
||||||
std::shared_ptr<const ViewProps> viewProps;
|
|
||||||
};
|
|
||||||
|
|
||||||
class ViewStylesRepository {
|
|
||||||
public:
|
|
||||||
ViewStylesRepository(
|
|
||||||
const std::shared_ptr<StaticPropsRegistry> &staticPropsRegistry,
|
|
||||||
const std::shared_ptr<AnimatedPropsRegistry> &animatedPropsRegistry);
|
|
||||||
|
|
||||||
void setUIManager(const std::shared_ptr<UIManager> &uiManager) {
|
|
||||||
uiManager_ = uiManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
jsi::Value getNodeProp(
|
|
||||||
const std::shared_ptr<const ShadowNode> &shadowNode,
|
|
||||||
const std::string &propName);
|
|
||||||
jsi::Value getParentNodeProp(
|
|
||||||
const std::shared_ptr<const ShadowNode> &shadowNode,
|
|
||||||
const std::string &propName);
|
|
||||||
folly::dynamic getStyleProp(Tag tag, const PropertyPath &propertyPath);
|
|
||||||
|
|
||||||
void clearNodesCache();
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::shared_ptr<UIManager> uiManager_;
|
|
||||||
std::shared_ptr<StaticPropsRegistry> staticPropsRegistry_;
|
|
||||||
std::shared_ptr<AnimatedPropsRegistry> animatedPropsRegistry_;
|
|
||||||
|
|
||||||
std::unordered_map<int, CachedShadowNode> shadowNodeCache_;
|
|
||||||
|
|
||||||
void updateCacheIfNeeded(
|
|
||||||
CachedShadowNode &cachedNode,
|
|
||||||
const std::shared_ptr<const ShadowNode> &shadowNode);
|
|
||||||
|
|
||||||
static folly::dynamic getPropertyValue(
|
|
||||||
const folly::dynamic &value,
|
|
||||||
const PropertyPath &propertyPath);
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace reanimated::css
|
|
||||||
Generated
Vendored
-194
@@ -1,194 +0,0 @@
|
|||||||
#include <reanimated/CSS/progress/AnimationProgressProvider.h>
|
|
||||||
|
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
namespace reanimated::css {
|
|
||||||
|
|
||||||
AnimationProgressProvider::AnimationProgressProvider(
|
|
||||||
const double timestamp,
|
|
||||||
const double duration,
|
|
||||||
const double delay,
|
|
||||||
const double iterationCount,
|
|
||||||
const AnimationDirection direction,
|
|
||||||
EasingFunction easingFunction,
|
|
||||||
const std::shared_ptr<KeyframeEasingFunctions> &keyframeEasingFunctions)
|
|
||||||
: RawProgressProvider(timestamp, duration, delay),
|
|
||||||
iterationCount_(iterationCount),
|
|
||||||
direction_(direction),
|
|
||||||
easingFunction_(std::move(easingFunction)),
|
|
||||||
keyframeEasingFunctions_(keyframeEasingFunctions) {}
|
|
||||||
|
|
||||||
void AnimationProgressProvider::setIterationCount(double iterationCount) {
|
|
||||||
iterationCount_ = iterationCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AnimationProgressProvider::setDirection(AnimationDirection direction) {
|
|
||||||
direction_ = direction;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AnimationProgressProvider::setEasingFunction(
|
|
||||||
const EasingFunction &easingFunction) {
|
|
||||||
easingFunction_ = easingFunction;
|
|
||||||
}
|
|
||||||
|
|
||||||
AnimationDirection AnimationProgressProvider::getDirection() const {
|
|
||||||
return direction_;
|
|
||||||
}
|
|
||||||
|
|
||||||
double AnimationProgressProvider::getGlobalProgress() const {
|
|
||||||
return applyAnimationDirection(rawProgress_.value_or(0));
|
|
||||||
}
|
|
||||||
|
|
||||||
AnimationProgressState AnimationProgressProvider::getState(
|
|
||||||
const double timestamp) const {
|
|
||||||
if (shouldFinish(timestamp)) {
|
|
||||||
return AnimationProgressState::Finished;
|
|
||||||
}
|
|
||||||
if (pauseTimestamp_ > 0) {
|
|
||||||
return AnimationProgressState::Paused;
|
|
||||||
}
|
|
||||||
if (timestamp < getStartTimestamp(timestamp) || !rawProgress_.has_value()) {
|
|
||||||
return AnimationProgressState::Pending;
|
|
||||||
}
|
|
||||||
const auto rawProgress = rawProgress_.value();
|
|
||||||
if (rawProgress >= 1) {
|
|
||||||
return AnimationProgressState::Finished;
|
|
||||||
}
|
|
||||||
return AnimationProgressState::Running;
|
|
||||||
}
|
|
||||||
|
|
||||||
double AnimationProgressProvider::getPauseTimestamp() const {
|
|
||||||
return pauseTimestamp_;
|
|
||||||
}
|
|
||||||
|
|
||||||
double AnimationProgressProvider::getTotalPausedTime(
|
|
||||||
const double timestamp) const {
|
|
||||||
return pauseTimestamp_ > 0
|
|
||||||
? (totalPausedTime_ + (timestamp - pauseTimestamp_))
|
|
||||||
: totalPausedTime_;
|
|
||||||
}
|
|
||||||
|
|
||||||
double AnimationProgressProvider::getStartTimestamp(
|
|
||||||
const double timestamp) const {
|
|
||||||
// Start timestamp is the timestamp when the first animation keyframe
|
|
||||||
// should be applied (it depends on the animation delay and the total
|
|
||||||
// time when the animation was paused)
|
|
||||||
return creationTimestamp_ + delay_ + getTotalPausedTime(timestamp);
|
|
||||||
}
|
|
||||||
|
|
||||||
double AnimationProgressProvider::getKeyframeProgress(
|
|
||||||
const double fromOffset,
|
|
||||||
const double toOffset) const {
|
|
||||||
if (fromOffset == toOffset) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto keyframeProgress =
|
|
||||||
(getGlobalProgress() - fromOffset) / (toOffset - fromOffset);
|
|
||||||
|
|
||||||
// Use the overridden easing function if it was overridden for the
|
|
||||||
// current keyframe
|
|
||||||
const auto easingFunctionIt = keyframeEasingFunctions_->find(fromOffset);
|
|
||||||
if (easingFunctionIt != keyframeEasingFunctions_->end()) {
|
|
||||||
return easingFunctionIt->second(keyframeProgress);
|
|
||||||
}
|
|
||||||
|
|
||||||
return easingFunction_(keyframeProgress);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AnimationProgressProvider::pause(const double timestamp) {
|
|
||||||
pauseTimestamp_ = timestamp;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AnimationProgressProvider::play(const double timestamp) {
|
|
||||||
if (pauseTimestamp_ > 0) {
|
|
||||||
totalPausedTime_ += timestamp - pauseTimestamp_;
|
|
||||||
}
|
|
||||||
pauseTimestamp_ = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AnimationProgressProvider::resetProgress() {
|
|
||||||
RawProgressProvider::resetProgress();
|
|
||||||
currentIteration_ = 1;
|
|
||||||
previousIterationsDuration_ = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AnimationProgressProvider::shouldFinish(const double timestamp) const {
|
|
||||||
if (iterationCount_ == 0) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (iterationCount_ == -1) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
const auto elapsedDuration = timestamp - getStartTimestamp(timestamp);
|
|
||||||
return elapsedDuration >= duration_ * iterationCount_;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::optional<double> AnimationProgressProvider::calculateRawProgress(
|
|
||||||
const double timestamp) {
|
|
||||||
const double currentIterationElapsedTime = timestamp -
|
|
||||||
(creationTimestamp_ + delay_ + previousIterationsDuration_ +
|
|
||||||
getTotalPausedTime(timestamp));
|
|
||||||
|
|
||||||
if (currentIterationElapsedTime < 0) {
|
|
||||||
return std::nullopt;
|
|
||||||
}
|
|
||||||
|
|
||||||
const double iterationProgress =
|
|
||||||
updateIterationProgress(currentIterationElapsedTime);
|
|
||||||
|
|
||||||
if (shouldFinish(timestamp)) {
|
|
||||||
// Override current progress for the last update in the last iteration to
|
|
||||||
// ensure that animation finishes exactly at the specified iteration
|
|
||||||
const double intPart = std::floor(iterationCount_);
|
|
||||||
return intPart == iterationCount_ ? 1 : iterationCount_ - intPart;
|
|
||||||
}
|
|
||||||
|
|
||||||
return iterationProgress;
|
|
||||||
}
|
|
||||||
|
|
||||||
double AnimationProgressProvider::updateIterationProgress(
|
|
||||||
const double currentIterationElapsedTime) {
|
|
||||||
if (duration_ == 0) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
// We can increase curentIteration by more than just one iteration if the
|
|
||||||
// animation delay is negative, thus we are using this division to get the
|
|
||||||
// number of iterations that have passed since the previous animation update
|
|
||||||
// (deltaIterations can be greater than for the first update of the
|
|
||||||
// animation with the negative delay)
|
|
||||||
const double progress = currentIterationElapsedTime / duration_;
|
|
||||||
const auto deltaIterations = static_cast<unsigned>(progress);
|
|
||||||
|
|
||||||
if (deltaIterations > 0) {
|
|
||||||
// Return 1 if the current iteration is the last one
|
|
||||||
if (iterationCount_ != -1 &&
|
|
||||||
currentIteration_ + deltaIterations > iterationCount_) {
|
|
||||||
currentIteration_ = iterationCount_;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
currentIteration_ += deltaIterations;
|
|
||||||
previousIterationsDuration_ = (currentIteration_ - 1) * duration_;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the current iteration changes, the progress must be updated
|
|
||||||
// respectively not to contain the progress of the previous iteration
|
|
||||||
return progress - deltaIterations;
|
|
||||||
}
|
|
||||||
|
|
||||||
double AnimationProgressProvider::applyAnimationDirection(
|
|
||||||
const double progress) const {
|
|
||||||
switch (direction_) {
|
|
||||||
case AnimationDirection::Normal:
|
|
||||||
return progress;
|
|
||||||
case AnimationDirection::Reverse:
|
|
||||||
return 1.0 - progress;
|
|
||||||
case AnimationDirection::Alternate:
|
|
||||||
return currentIteration_ % 2 == 0 ? 1.0 - progress : progress;
|
|
||||||
case AnimationDirection::AlternateReverse:
|
|
||||||
return currentIteration_ % 2 == 0 ? progress : 1.0 - progress;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace reanimated::css
|
|
||||||
Generated
Vendored
-68
@@ -1,68 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <reanimated/CSS/configs/CSSAnimationConfig.h>
|
|
||||||
#include <reanimated/CSS/configs/CSSKeyframesConfig.h>
|
|
||||||
#include <reanimated/CSS/easing/EasingFunctions.h>
|
|
||||||
#include <reanimated/CSS/progress/KeyframeProgressProvider.h>
|
|
||||||
#include <reanimated/CSS/progress/RawProgressProvider.h>
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
namespace reanimated::css {
|
|
||||||
|
|
||||||
enum class AnimationProgressState {
|
|
||||||
Pending, // When the animation is waiting for the delay to pass
|
|
||||||
Running,
|
|
||||||
Paused,
|
|
||||||
Finished
|
|
||||||
};
|
|
||||||
|
|
||||||
class AnimationProgressProvider final : public KeyframeProgressProvider,
|
|
||||||
public RawProgressProvider {
|
|
||||||
public:
|
|
||||||
AnimationProgressProvider(
|
|
||||||
double timestamp,
|
|
||||||
double duration,
|
|
||||||
double delay,
|
|
||||||
double iterationCount,
|
|
||||||
AnimationDirection direction,
|
|
||||||
EasingFunction easingFunction,
|
|
||||||
const std::shared_ptr<KeyframeEasingFunctions> &keyframeEasingFunctions);
|
|
||||||
|
|
||||||
void setIterationCount(double iterationCount);
|
|
||||||
void setDirection(AnimationDirection direction);
|
|
||||||
void setEasingFunction(const EasingFunction &easingFunction);
|
|
||||||
|
|
||||||
AnimationDirection getDirection() const;
|
|
||||||
double getGlobalProgress() const override;
|
|
||||||
double getKeyframeProgress(double fromOffset, double toOffset) const override;
|
|
||||||
AnimationProgressState getState(double timestamp) const;
|
|
||||||
double getPauseTimestamp() const;
|
|
||||||
double getTotalPausedTime(double timestamp) const;
|
|
||||||
double getStartTimestamp(double timestamp) const;
|
|
||||||
|
|
||||||
void pause(double timestamp);
|
|
||||||
void play(double timestamp);
|
|
||||||
void resetProgress() override;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
std::optional<double> calculateRawProgress(double timestamp) override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
double iterationCount_;
|
|
||||||
AnimationDirection direction_;
|
|
||||||
EasingFunction easingFunction_;
|
|
||||||
std::shared_ptr<KeyframeEasingFunctions> keyframeEasingFunctions_;
|
|
||||||
|
|
||||||
unsigned currentIteration_ = 1;
|
|
||||||
double previousIterationsDuration_ = 0;
|
|
||||||
double pauseTimestamp_ = 0;
|
|
||||||
double totalPausedTime_ = 0;
|
|
||||||
|
|
||||||
bool shouldFinish(double timestamp) const;
|
|
||||||
|
|
||||||
double updateIterationProgress(double currentIterationElapsedTime);
|
|
||||||
double applyAnimationDirection(double iterationProgress) const;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace reanimated::css
|
|
||||||
Generated
Vendored
-13
@@ -1,13 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
namespace reanimated::css {
|
|
||||||
|
|
||||||
class KeyframeProgressProvider {
|
|
||||||
public:
|
|
||||||
virtual double getGlobalProgress() const = 0;
|
|
||||||
|
|
||||||
virtual double getKeyframeProgress(double fromOffset, double toOffset)
|
|
||||||
const = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace reanimated::css
|
|
||||||
Generated
Vendored
-44
@@ -1,44 +0,0 @@
|
|||||||
#include <reanimated/CSS/progress/RawProgressProvider.h>
|
|
||||||
|
|
||||||
namespace reanimated::css {
|
|
||||||
|
|
||||||
RawProgressProvider::RawProgressProvider(
|
|
||||||
const double timestamp,
|
|
||||||
const double duration,
|
|
||||||
const double delay)
|
|
||||||
: duration_(duration), delay_(delay), creationTimestamp_(timestamp) {}
|
|
||||||
|
|
||||||
void RawProgressProvider::setDuration(double duration) {
|
|
||||||
duration_ = duration;
|
|
||||||
}
|
|
||||||
|
|
||||||
void RawProgressProvider::setDelay(double delay) {
|
|
||||||
delay_ = delay;
|
|
||||||
}
|
|
||||||
|
|
||||||
void RawProgressProvider::resetProgress() {
|
|
||||||
rawProgress_.reset();
|
|
||||||
previousRawProgress_.reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
void RawProgressProvider::update(const double timestamp) {
|
|
||||||
previousRawProgress_ = rawProgress_;
|
|
||||||
|
|
||||||
if (timestamp - creationTimestamp_ < delay_) {
|
|
||||||
rawProgress_.reset();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
rawProgress_ = calculateRawProgress(timestamp);
|
|
||||||
if (!rawProgress_.has_value()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rawProgress_.value() < 0) {
|
|
||||||
rawProgress_.reset();
|
|
||||||
} else if (rawProgress_.value() >= 1) {
|
|
||||||
rawProgress_ = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace reanimated::css
|
|
||||||
Generated
Vendored
-31
@@ -1,31 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <optional>
|
|
||||||
namespace reanimated::css {
|
|
||||||
|
|
||||||
class RawProgressProvider {
|
|
||||||
public:
|
|
||||||
RawProgressProvider(double timestamp, double duration, double delay);
|
|
||||||
|
|
||||||
void setDuration(double duration);
|
|
||||||
void setDelay(double delay);
|
|
||||||
|
|
||||||
virtual void resetProgress();
|
|
||||||
void update(double timestamp);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
double duration_;
|
|
||||||
double delay_;
|
|
||||||
double creationTimestamp_;
|
|
||||||
|
|
||||||
std::optional<double> rawProgress_;
|
|
||||||
std::optional<double> previousRawProgress_;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Calculates the progress of the animation at the given timestamp without
|
|
||||||
* applying any decorations (e.g. animation direction, easing)
|
|
||||||
*/
|
|
||||||
virtual std::optional<double> calculateRawProgress(double timestamp) = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace reanimated::css
|
|
||||||
Generated
Vendored
-220
@@ -1,220 +0,0 @@
|
|||||||
#include <reanimated/CSS/progress/TransitionProgressProvider.h>
|
|
||||||
|
|
||||||
#include <limits>
|
|
||||||
|
|
||||||
namespace reanimated::css {
|
|
||||||
|
|
||||||
// TransitionPropertyProgressProvider
|
|
||||||
|
|
||||||
TransitionPropertyProgressProvider::TransitionPropertyProgressProvider(
|
|
||||||
const double timestamp,
|
|
||||||
const double duration,
|
|
||||||
const double delay,
|
|
||||||
const EasingFunction &easingFunction)
|
|
||||||
: RawProgressProvider(timestamp, duration, delay),
|
|
||||||
easingFunction_(easingFunction) {}
|
|
||||||
|
|
||||||
TransitionPropertyProgressProvider::TransitionPropertyProgressProvider(
|
|
||||||
const double timestamp,
|
|
||||||
const double duration,
|
|
||||||
const double delay,
|
|
||||||
const EasingFunction &easingFunction,
|
|
||||||
const double reversingShorteningFactor)
|
|
||||||
: RawProgressProvider(timestamp, duration, delay),
|
|
||||||
easingFunction_(easingFunction),
|
|
||||||
reversingShorteningFactor_(reversingShorteningFactor) {}
|
|
||||||
|
|
||||||
double TransitionPropertyProgressProvider::getGlobalProgress() const {
|
|
||||||
return rawProgress_.value_or(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
double TransitionPropertyProgressProvider::getKeyframeProgress(
|
|
||||||
const double fromOffset,
|
|
||||||
const double toOffset) const {
|
|
||||||
if (fromOffset == toOffset) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return easingFunction_(getGlobalProgress());
|
|
||||||
}
|
|
||||||
|
|
||||||
double TransitionPropertyProgressProvider::getRemainingDelay(
|
|
||||||
const double timestamp) const {
|
|
||||||
return delay_ - (timestamp - creationTimestamp_);
|
|
||||||
}
|
|
||||||
|
|
||||||
double TransitionPropertyProgressProvider::getReversingShorteningFactor()
|
|
||||||
const {
|
|
||||||
return reversingShorteningFactor_;
|
|
||||||
}
|
|
||||||
|
|
||||||
TransitionProgressState TransitionPropertyProgressProvider::getState() const {
|
|
||||||
if (!rawProgress_.has_value()) {
|
|
||||||
return TransitionProgressState::Pending;
|
|
||||||
}
|
|
||||||
const auto rawProgress = rawProgress_.value();
|
|
||||||
if (rawProgress >= 1) {
|
|
||||||
return TransitionProgressState::Finished;
|
|
||||||
}
|
|
||||||
return TransitionProgressState::Running;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::optional<double> TransitionPropertyProgressProvider::calculateRawProgress(
|
|
||||||
const double timestamp) {
|
|
||||||
if (duration_ == 0) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return getElapsedTime(timestamp) / duration_;
|
|
||||||
}
|
|
||||||
|
|
||||||
double TransitionPropertyProgressProvider::getElapsedTime(
|
|
||||||
const double timestamp) const {
|
|
||||||
return timestamp - (creationTimestamp_ + delay_);
|
|
||||||
}
|
|
||||||
|
|
||||||
// TransitionProgressProvider
|
|
||||||
|
|
||||||
TransitionProgressState TransitionProgressProvider::getState() const {
|
|
||||||
for (const auto &[_, propertyProgressProvider] : propertyProgressProviders_) {
|
|
||||||
if (propertyProgressProvider->getState() ==
|
|
||||||
TransitionProgressState::Running) {
|
|
||||||
return TransitionProgressState::Running;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return TransitionProgressState::Pending;
|
|
||||||
}
|
|
||||||
|
|
||||||
double TransitionProgressProvider::getMinDelay(const double timestamp) const {
|
|
||||||
if (propertyProgressProviders_.empty()) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
auto minDelay = std::numeric_limits<double>::max();
|
|
||||||
|
|
||||||
for (const auto &[_, propertyProgressProvider] : propertyProgressProviders_) {
|
|
||||||
const auto remainingDelay =
|
|
||||||
propertyProgressProvider->getRemainingDelay(timestamp);
|
|
||||||
if (remainingDelay < minDelay) {
|
|
||||||
minDelay = remainingDelay;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return minDelay;
|
|
||||||
}
|
|
||||||
|
|
||||||
TransitionPropertyProgressProviders
|
|
||||||
TransitionProgressProvider::getPropertyProgressProviders() const {
|
|
||||||
return propertyProgressProviders_;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::unordered_set<std::string>
|
|
||||||
TransitionProgressProvider::getRemovedProperties() const {
|
|
||||||
return removedProperties_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TransitionProgressProvider::discardFinishedProgressProviders() {
|
|
||||||
for (auto it = propertyProgressProviders_.begin();
|
|
||||||
it != propertyProgressProviders_.end();) {
|
|
||||||
if (it->second->getState() == TransitionProgressState::Finished) {
|
|
||||||
it = propertyProgressProviders_.erase(it);
|
|
||||||
} else {
|
|
||||||
++it;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void TransitionProgressProvider::discardIrrelevantProgressProviders(
|
|
||||||
const std::unordered_set<std::string> &transitionPropertyNames) {
|
|
||||||
for (auto it = propertyProgressProviders_.begin();
|
|
||||||
it != propertyProgressProviders_.end();) {
|
|
||||||
// Remove property progress providers for properties not specified in the
|
|
||||||
// transition property names
|
|
||||||
if (transitionPropertyNames.find(it->first) ==
|
|
||||||
transitionPropertyNames.end()) {
|
|
||||||
it = propertyProgressProviders_.erase(it);
|
|
||||||
} else {
|
|
||||||
++it;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void TransitionProgressProvider::runProgressProviders(
|
|
||||||
const double timestamp,
|
|
||||||
const CSSTransitionPropertiesSettings &propertiesSettings,
|
|
||||||
const PropertyNames &changedPropertyNames,
|
|
||||||
const std::unordered_set<std::string> &reversedPropertyNames) {
|
|
||||||
for (const auto &propertyName : changedPropertyNames) {
|
|
||||||
const auto propertySettingsOptional =
|
|
||||||
getTransitionPropertySettings(propertiesSettings, propertyName);
|
|
||||||
|
|
||||||
if (!propertySettingsOptional.has_value()) {
|
|
||||||
throw std::invalid_argument(
|
|
||||||
"[Reanimated] Property '" + propertyName +
|
|
||||||
"' is not a valid transition property");
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto &propertySettings = propertySettingsOptional.value();
|
|
||||||
const auto it = propertyProgressProviders_.find(propertyName);
|
|
||||||
|
|
||||||
if (it != propertyProgressProviders_.end()) {
|
|
||||||
const auto &progressProvider = it->second;
|
|
||||||
progressProvider->update(timestamp);
|
|
||||||
|
|
||||||
if (reversedPropertyNames.find(propertyName) !=
|
|
||||||
reversedPropertyNames.end() &&
|
|
||||||
progressProvider->getState() != TransitionProgressState::Finished) {
|
|
||||||
// Create reversing shortening progress provider for interrupted
|
|
||||||
// reversing transition
|
|
||||||
propertyProgressProviders_.insert_or_assign(
|
|
||||||
propertyName,
|
|
||||||
createReversingShorteningProgressProvider(
|
|
||||||
timestamp, propertySettings, *progressProvider));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create progress provider with the new settings
|
|
||||||
propertyProgressProviders_.insert_or_assign(
|
|
||||||
propertyName,
|
|
||||||
std::make_shared<TransitionPropertyProgressProvider>(
|
|
||||||
timestamp,
|
|
||||||
propertySettings.duration,
|
|
||||||
propertySettings.delay,
|
|
||||||
propertySettings.easingFunction));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void TransitionProgressProvider::update(const double timestamp) {
|
|
||||||
removedProperties_.clear();
|
|
||||||
|
|
||||||
for (const auto &[propertyName, propertyProgressProvider] :
|
|
||||||
propertyProgressProviders_) {
|
|
||||||
propertyProgressProvider->update(timestamp);
|
|
||||||
if (propertyProgressProvider->getState() ==
|
|
||||||
TransitionProgressState::Finished) {
|
|
||||||
removedProperties_.insert(propertyName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<TransitionPropertyProgressProvider>
|
|
||||||
TransitionProgressProvider::createReversingShorteningProgressProvider(
|
|
||||||
const double timestamp,
|
|
||||||
const CSSTransitionPropertySettings &propertySettings,
|
|
||||||
const TransitionPropertyProgressProvider &existingProgressProvider) {
|
|
||||||
const auto oldProgress = existingProgressProvider.getKeyframeProgress(0, 1);
|
|
||||||
const auto oldReversingShorteningFactor =
|
|
||||||
existingProgressProvider.getReversingShorteningFactor();
|
|
||||||
auto newReversingShorteningFactor =
|
|
||||||
oldProgress * oldReversingShorteningFactor +
|
|
||||||
(1 - oldReversingShorteningFactor);
|
|
||||||
|
|
||||||
return std::make_shared<TransitionPropertyProgressProvider>(
|
|
||||||
timestamp,
|
|
||||||
propertySettings.duration * newReversingShorteningFactor,
|
|
||||||
propertySettings.delay < 0
|
|
||||||
? newReversingShorteningFactor * propertySettings.delay
|
|
||||||
: propertySettings.delay,
|
|
||||||
propertySettings.easingFunction,
|
|
||||||
newReversingShorteningFactor);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace reanimated::css
|
|
||||||
Generated
Vendored
-82
@@ -1,82 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <reanimated/CSS/configs/CSSTransitionConfig.h>
|
|
||||||
#include <reanimated/CSS/progress/KeyframeProgressProvider.h>
|
|
||||||
#include <reanimated/CSS/progress/RawProgressProvider.h>
|
|
||||||
#include <reanimated/CSS/utils/props.h>
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <string>
|
|
||||||
#include <unordered_map>
|
|
||||||
#include <unordered_set>
|
|
||||||
|
|
||||||
namespace reanimated::css {
|
|
||||||
|
|
||||||
enum class TransitionProgressState { Pending, Running, Finished };
|
|
||||||
|
|
||||||
class TransitionPropertyProgressProvider final
|
|
||||||
: public KeyframeProgressProvider,
|
|
||||||
public RawProgressProvider {
|
|
||||||
public:
|
|
||||||
TransitionPropertyProgressProvider(
|
|
||||||
double timestamp,
|
|
||||||
double duration,
|
|
||||||
double delay,
|
|
||||||
const EasingFunction &easingFunction);
|
|
||||||
TransitionPropertyProgressProvider(
|
|
||||||
double timestamp,
|
|
||||||
double duration,
|
|
||||||
double delay,
|
|
||||||
const EasingFunction &easingFunction,
|
|
||||||
double reversingShorteningFactor);
|
|
||||||
|
|
||||||
double getGlobalProgress() const override;
|
|
||||||
double getKeyframeProgress(double fromOffset, double toOffset) const override;
|
|
||||||
double getRemainingDelay(double timestamp) const;
|
|
||||||
double getReversingShorteningFactor() const;
|
|
||||||
TransitionProgressState getState() const;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
std::optional<double> calculateRawProgress(double timestamp) override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
EasingFunction easingFunction_;
|
|
||||||
double reversingShorteningFactor_ = 1;
|
|
||||||
|
|
||||||
double getElapsedTime(double timestamp) const;
|
|
||||||
};
|
|
||||||
|
|
||||||
using TransitionPropertyProgressProviders = std::unordered_map<
|
|
||||||
std::string,
|
|
||||||
std::shared_ptr<TransitionPropertyProgressProvider>>;
|
|
||||||
|
|
||||||
class TransitionProgressProvider final {
|
|
||||||
public:
|
|
||||||
TransitionProgressState getState() const;
|
|
||||||
double getMinDelay(double timestamp) const;
|
|
||||||
TransitionPropertyProgressProviders getPropertyProgressProviders() const;
|
|
||||||
std::unordered_set<std::string> getRemovedProperties() const;
|
|
||||||
|
|
||||||
void discardFinishedProgressProviders();
|
|
||||||
void discardIrrelevantProgressProviders(
|
|
||||||
const std::unordered_set<std::string> &transitionPropertyNames);
|
|
||||||
void runProgressProviders(
|
|
||||||
double timestamp,
|
|
||||||
const CSSTransitionPropertiesSettings &propertiesSettings,
|
|
||||||
const PropertyNames &changedPropertyNames,
|
|
||||||
const std::unordered_set<std::string> &reversedPropertyNames);
|
|
||||||
void update(double timestamp);
|
|
||||||
|
|
||||||
private:
|
|
||||||
TransitionPropertyProgressProviders propertyProgressProviders_;
|
|
||||||
|
|
||||||
std::unordered_set<std::string> removedProperties_;
|
|
||||||
|
|
||||||
std::shared_ptr<TransitionPropertyProgressProvider>
|
|
||||||
createReversingShorteningProgressProvider(
|
|
||||||
double timestamp,
|
|
||||||
const CSSTransitionPropertySettings &propertySettings,
|
|
||||||
const TransitionPropertyProgressProvider &existingProgressProvider);
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace reanimated::css
|
|
||||||
Generated
Vendored
-349
@@ -1,349 +0,0 @@
|
|||||||
#include <reanimated/CSS/registries/CSSAnimationsRegistry.h>
|
|
||||||
|
|
||||||
namespace reanimated::css {
|
|
||||||
|
|
||||||
bool CSSAnimationsRegistry::isEmpty() const {
|
|
||||||
// The registry is empty if has no registered animations and no updates
|
|
||||||
// stored in the updates registry
|
|
||||||
return UpdatesRegistry::isEmpty() && registry_.empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CSSAnimationsRegistry::hasUpdates() const {
|
|
||||||
return !runningAnimationIndicesMap_.empty() ||
|
|
||||||
!delayedAnimationsManager_.empty() || !animationsToRevertMap_.empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CSSAnimationsRegistry::apply(
|
|
||||||
jsi::Runtime &rt,
|
|
||||||
const std::shared_ptr<const ShadowNode> &shadowNode,
|
|
||||||
const std::optional<std::vector<std::string>> &animationNames,
|
|
||||||
const CSSAnimationsMap &newAnimations,
|
|
||||||
const CSSAnimationSettingsUpdatesMap &settingsUpdates,
|
|
||||||
double timestamp) {
|
|
||||||
const auto animationsVector =
|
|
||||||
buildAnimationsVector(rt, shadowNode, animationNames, newAnimations);
|
|
||||||
|
|
||||||
const auto viewTag = shadowNode->getTag();
|
|
||||||
if (animationsVector.empty()) {
|
|
||||||
remove(viewTag);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
registry_.erase(viewTag);
|
|
||||||
registry_.emplace(
|
|
||||||
viewTag,
|
|
||||||
RegistryEntry{
|
|
||||||
std::move(animationsVector),
|
|
||||||
buildAnimationToIndexMap(animationsVector)});
|
|
||||||
runningAnimationIndicesMap_[viewTag].clear();
|
|
||||||
|
|
||||||
std::vector<size_t> updatedIndices;
|
|
||||||
for (const auto &[index, _] : newAnimations) {
|
|
||||||
updatedIndices.push_back(index);
|
|
||||||
}
|
|
||||||
for (const auto &[index, _] : settingsUpdates) {
|
|
||||||
updatedIndices.push_back(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
updateAnimationSettings(animationsVector, settingsUpdates, timestamp);
|
|
||||||
for (size_t i = 0; i < animationsVector.size(); ++i) {
|
|
||||||
scheduleOrActivateAnimation(i, animationsVector[i], timestamp);
|
|
||||||
}
|
|
||||||
updateViewAnimations(viewTag, updatedIndices, timestamp, false);
|
|
||||||
applyViewAnimationsStyle(viewTag, timestamp);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CSSAnimationsRegistry::remove(const Tag viewTag) {
|
|
||||||
removeViewAnimations(viewTag);
|
|
||||||
removeFromUpdatesRegistry(viewTag);
|
|
||||||
registry_.erase(viewTag);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CSSAnimationsRegistry::update(const double timestamp) {
|
|
||||||
// Activate all delayed animations that should start now
|
|
||||||
activateDelayedAnimations(timestamp);
|
|
||||||
// Update styles in the registry for views which animations were reverted
|
|
||||||
handleAnimationsToRevert(timestamp);
|
|
||||||
|
|
||||||
// Iterate over active animations and update them
|
|
||||||
for (auto it = runningAnimationIndicesMap_.begin();
|
|
||||||
it != runningAnimationIndicesMap_.end();) {
|
|
||||||
const auto viewTag = it->first;
|
|
||||||
const std::vector<size_t> animationIndices = {
|
|
||||||
it->second.begin(), it->second.end()};
|
|
||||||
updateViewAnimations(viewTag, animationIndices, timestamp, true);
|
|
||||||
|
|
||||||
if (runningAnimationIndicesMap_[viewTag].empty()) {
|
|
||||||
it = runningAnimationIndicesMap_.erase(it);
|
|
||||||
} else {
|
|
||||||
++it;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CSSAnimationsVector CSSAnimationsRegistry::buildAnimationsVector(
|
|
||||||
jsi::Runtime &rt,
|
|
||||||
const std::shared_ptr<const ShadowNode> &shadowNode,
|
|
||||||
const std::optional<std::vector<std::string>> &animationNames,
|
|
||||||
const std::optional<CSSAnimationsMap> &newAnimations) const {
|
|
||||||
const auto registryIt = registry_.find(shadowNode->getTag());
|
|
||||||
|
|
||||||
// If animationNames has no value, that means no animations were added,
|
|
||||||
// removed or reordered, so we can return the current animations vector from
|
|
||||||
// the registry
|
|
||||||
if (!animationNames.has_value()) {
|
|
||||||
if (registryIt != registry_.end()) {
|
|
||||||
return std::move(registryIt->second.animationsVector);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CSSAnimationsVector animationsVector;
|
|
||||||
const auto &animationNamesVector = animationNames.value();
|
|
||||||
const auto animationNamesSize = animationNamesVector.size();
|
|
||||||
animationsVector.reserve(animationNamesSize);
|
|
||||||
|
|
||||||
std::unordered_map<std::string, CSSAnimationsVector> oldAnimationsMap;
|
|
||||||
CSSAnimationsMap emptyAnimationsMap;
|
|
||||||
const auto &newAnimationsMap = newAnimations.value_or(emptyAnimationsMap);
|
|
||||||
|
|
||||||
if (registryIt != registry_.end()) {
|
|
||||||
const auto &oldAnimations = registryIt->second.animationsVector;
|
|
||||||
|
|
||||||
// Fill the map while maintaining reverse order (for quick pop from the end)
|
|
||||||
for (auto it = oldAnimations.rbegin(); it != oldAnimations.rend(); ++it) {
|
|
||||||
oldAnimationsMap[(*it)->getName()].emplace_back(*it);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i = 0; i < animationNamesSize; ++i) {
|
|
||||||
const auto &newAnimationIt = newAnimationsMap.find(i);
|
|
||||||
if (newAnimationIt != newAnimationsMap.end()) {
|
|
||||||
animationsVector.emplace_back(newAnimationIt->second);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto &name = animationNamesVector[i];
|
|
||||||
const auto &oldAnimationIt = oldAnimationsMap.find(name);
|
|
||||||
|
|
||||||
if (oldAnimationIt == oldAnimationsMap.end()) {
|
|
||||||
throw std::runtime_error(
|
|
||||||
"[Reanimated] There is no animation with name " + name +
|
|
||||||
" available to use at index " + std::to_string(i));
|
|
||||||
}
|
|
||||||
|
|
||||||
animationsVector.emplace_back(oldAnimationIt->second.back());
|
|
||||||
oldAnimationIt->second.pop_back();
|
|
||||||
|
|
||||||
if (oldAnimationIt->second.empty()) {
|
|
||||||
oldAnimationsMap.erase(oldAnimationIt);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return animationsVector;
|
|
||||||
}
|
|
||||||
|
|
||||||
CSSAnimationsRegistry::AnimationToIndexMap
|
|
||||||
CSSAnimationsRegistry::buildAnimationToIndexMap(
|
|
||||||
const CSSAnimationsVector &animationsVector) const {
|
|
||||||
AnimationToIndexMap animationToIndexMap;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < animationsVector.size(); ++i) {
|
|
||||||
animationToIndexMap[animationsVector[i]] = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
return animationToIndexMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CSSAnimationsRegistry::updateAnimationSettings(
|
|
||||||
const CSSAnimationsVector &animationsVector,
|
|
||||||
const CSSAnimationSettingsUpdatesMap &settingsUpdates,
|
|
||||||
const double timestamp) {
|
|
||||||
for (size_t i = 0; i < animationsVector.size(); ++i) {
|
|
||||||
const auto &animation = animationsVector[i];
|
|
||||||
const auto it = settingsUpdates.find(i);
|
|
||||||
if (it != settingsUpdates.end()) {
|
|
||||||
animation->updateSettings(it->second, timestamp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CSSAnimationsRegistry::updateViewAnimations(
|
|
||||||
const Tag viewTag,
|
|
||||||
const std::vector<size_t> &animationIndices,
|
|
||||||
const double timestamp,
|
|
||||||
const bool addToBatch) {
|
|
||||||
folly::dynamic result = folly::dynamic::object;
|
|
||||||
std::shared_ptr<const ShadowNode> shadowNode = nullptr;
|
|
||||||
bool hasUpdates = false;
|
|
||||||
|
|
||||||
for (const auto animationIndex : animationIndices) {
|
|
||||||
const auto &animation = registry_[viewTag].animationsVector[animationIndex];
|
|
||||||
if (!shadowNode) {
|
|
||||||
shadowNode = animation->getShadowNode();
|
|
||||||
}
|
|
||||||
if (animation->getState(timestamp) == AnimationProgressState::Pending) {
|
|
||||||
animation->run(timestamp);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool updatesAddedToBatch = false;
|
|
||||||
const auto updates = animation->update(timestamp);
|
|
||||||
const auto newState = animation->getState(timestamp);
|
|
||||||
|
|
||||||
if (newState == AnimationProgressState::Finished) {
|
|
||||||
// Revert changes applied during animation if there is no forwards fill
|
|
||||||
// mode
|
|
||||||
if (addToBatch && !animation->hasForwardsFillMode()) {
|
|
||||||
// We also have to manually commit style values
|
|
||||||
// reverting the changes applied by the animation.
|
|
||||||
hasUpdates =
|
|
||||||
addStyleUpdates(result, animation->getResetStyle(), false) ||
|
|
||||||
hasUpdates;
|
|
||||||
updatesAddedToBatch = true;
|
|
||||||
// We want to remove style changes applied by the animation that is
|
|
||||||
// finished and has no forwards fill mode. We cannot simply remove
|
|
||||||
// properties from the style in the registry as it may be overridden
|
|
||||||
// by the next animation. Instead, we are creating the new style
|
|
||||||
// object without reverted (finished without forwards fill mode)
|
|
||||||
// animations.
|
|
||||||
animationsToRevertMap_[viewTag].insert(animationIndex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (addToBatch && !updatesAddedToBatch) {
|
|
||||||
hasUpdates = addStyleUpdates(result, updates, true) || hasUpdates;
|
|
||||||
}
|
|
||||||
if (newState != AnimationProgressState::Running) {
|
|
||||||
runningAnimationIndicesMap_[viewTag].erase(animationIndex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hasUpdates) {
|
|
||||||
addUpdatesToBatch(shadowNode, result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CSSAnimationsRegistry::scheduleOrActivateAnimation(
|
|
||||||
const size_t animationIndex,
|
|
||||||
const std::shared_ptr<CSSAnimation> &animation,
|
|
||||||
const double timestamp) {
|
|
||||||
// Remove the animation from delayed (if it is already added to
|
|
||||||
// delayed animations)
|
|
||||||
delayedAnimationsManager_.remove(animation);
|
|
||||||
|
|
||||||
const auto startTimestamp = animation->getStartTimestamp(timestamp);
|
|
||||||
|
|
||||||
if (startTimestamp > timestamp) {
|
|
||||||
// If the animation is delayed, schedule it for activation
|
|
||||||
// (Only if it isn't paused)
|
|
||||||
if (animation->getState(timestamp) != AnimationProgressState::Paused) {
|
|
||||||
delayedAnimationsManager_.add(startTimestamp, animation);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
const auto viewTag = animation->getShadowNode()->getTag();
|
|
||||||
runningAnimationIndicesMap_[viewTag].insert(animationIndex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CSSAnimationsRegistry::removeViewAnimations(const Tag viewTag) {
|
|
||||||
const auto it = registry_.find(viewTag);
|
|
||||||
if (it == registry_.end()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const auto &animation : it->second.animationsVector) {
|
|
||||||
delayedAnimationsManager_.remove(animation);
|
|
||||||
}
|
|
||||||
runningAnimationIndicesMap_.erase(viewTag);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CSSAnimationsRegistry::applyViewAnimationsStyle(
|
|
||||||
const Tag viewTag,
|
|
||||||
const double timestamp) {
|
|
||||||
const auto it = registry_.find(viewTag);
|
|
||||||
// Remove the style from the registry if there are no animations for the view
|
|
||||||
if (it == registry_.end() || it->second.animationsVector.empty()) {
|
|
||||||
removeFromUpdatesRegistry(viewTag);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
folly::dynamic updatedStyle = folly::dynamic::object;
|
|
||||||
std::shared_ptr<const ShadowNode> shadowNode = nullptr;
|
|
||||||
|
|
||||||
for (const auto &animation : it->second.animationsVector) {
|
|
||||||
const auto startTimestamp = animation->getStartTimestamp(timestamp);
|
|
||||||
|
|
||||||
folly::dynamic style;
|
|
||||||
const auto ¤tState = animation->getState(timestamp);
|
|
||||||
if (startTimestamp > timestamp && animation->hasBackwardsFillMode()) {
|
|
||||||
style = animation->getBackwardsFillStyle();
|
|
||||||
} else if (
|
|
||||||
currentState == AnimationProgressState::Running ||
|
|
||||||
// Animation is paused after start (was running before)
|
|
||||||
(currentState == AnimationProgressState::Paused &&
|
|
||||||
timestamp >= animation->getStartTimestamp(timestamp)) ||
|
|
||||||
// Animation is finished and has fill forwards fill mode
|
|
||||||
(currentState == AnimationProgressState::Finished &&
|
|
||||||
animation->hasForwardsFillMode())) {
|
|
||||||
style = animation->getCurrentInterpolationStyle();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!shadowNode) {
|
|
||||||
shadowNode = animation->getShadowNode();
|
|
||||||
}
|
|
||||||
if (style.isObject()) {
|
|
||||||
updatedStyle.update(style);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
setInUpdatesRegistry(shadowNode, updatedStyle);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CSSAnimationsRegistry::activateDelayedAnimations(const double timestamp) {
|
|
||||||
while (!delayedAnimationsManager_.empty() &&
|
|
||||||
delayedAnimationsManager_.top().timestamp <= timestamp) {
|
|
||||||
const auto [_, animation] = delayedAnimationsManager_.pop();
|
|
||||||
const auto viewTag = animation->getShadowNode()->getTag();
|
|
||||||
|
|
||||||
// Add only these animations which weren't removed in the meantime
|
|
||||||
if (registry_.find(viewTag) == registry_.end()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto &animationToIndexMap = registry_[viewTag].animationToIndexMap;
|
|
||||||
if (animationToIndexMap.find(animation) == animationToIndexMap.end()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto animationIndex = animationToIndexMap.at(animation);
|
|
||||||
runningAnimationIndicesMap_[viewTag].insert(animationIndex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CSSAnimationsRegistry::handleAnimationsToRevert(const double timestamp) {
|
|
||||||
for (const auto &[viewTag, _] : animationsToRevertMap_) {
|
|
||||||
applyViewAnimationsStyle(viewTag, timestamp);
|
|
||||||
}
|
|
||||||
animationsToRevertMap_.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CSSAnimationsRegistry::addStyleUpdates(
|
|
||||||
folly::dynamic &target,
|
|
||||||
const folly::dynamic &updates,
|
|
||||||
bool shouldOverride) {
|
|
||||||
if (!updates.isObject()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool hasUpdates = false;
|
|
||||||
for (const auto &[propertyName, propertyValue] : updates.items()) {
|
|
||||||
if (shouldOverride || !target.count(propertyName) ||
|
|
||||||
target[propertyName].isNull()) {
|
|
||||||
target[propertyName] = propertyValue;
|
|
||||||
hasUpdates = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return hasUpdates;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace reanimated::css
|
|
||||||
Generated
Vendored
-95
@@ -1,95 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <reanimated/CSS/configs/CSSAnimationConfig.h>
|
|
||||||
#include <reanimated/CSS/core/CSSAnimation.h>
|
|
||||||
#include <reanimated/CSS/utils/DelayedItemsManager.h>
|
|
||||||
#include <reanimated/CSS/utils/props.h>
|
|
||||||
#include <reanimated/Fabric/updates/UpdatesRegistry.h>
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <set>
|
|
||||||
#include <string>
|
|
||||||
#include <unordered_map>
|
|
||||||
#include <unordered_set>
|
|
||||||
#include <utility>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace reanimated::css {
|
|
||||||
|
|
||||||
using CSSAnimationsMap =
|
|
||||||
std::unordered_map<size_t, std::shared_ptr<CSSAnimation>>;
|
|
||||||
using CSSAnimationsVector = std::vector<std::shared_ptr<CSSAnimation>>;
|
|
||||||
|
|
||||||
class CSSAnimationsRegistry
|
|
||||||
: public UpdatesRegistry,
|
|
||||||
std::enable_shared_from_this<CSSAnimationsRegistry> {
|
|
||||||
public:
|
|
||||||
using SettingsUpdates =
|
|
||||||
std::vector<std::pair<size_t, PartialCSSAnimationSettings>>;
|
|
||||||
|
|
||||||
bool isEmpty() const override;
|
|
||||||
bool hasUpdates() const;
|
|
||||||
|
|
||||||
void apply(
|
|
||||||
jsi::Runtime &rt,
|
|
||||||
const std::shared_ptr<const ShadowNode> &shadowNode,
|
|
||||||
const std::optional<std::vector<std::string>> &animationNames,
|
|
||||||
const CSSAnimationsMap &newAnimations,
|
|
||||||
const CSSAnimationSettingsUpdatesMap &settingsUpdates,
|
|
||||||
double timestamp);
|
|
||||||
void remove(Tag viewTag) override;
|
|
||||||
|
|
||||||
void update(double timestamp);
|
|
||||||
|
|
||||||
private:
|
|
||||||
using AnimationToIndexMap =
|
|
||||||
std::unordered_map<std::shared_ptr<CSSAnimation>, size_t>;
|
|
||||||
using RunningAnimationIndicesMap = std::unordered_map<Tag, std::set<size_t>>;
|
|
||||||
using AnimationsToRevertMap =
|
|
||||||
std::unordered_map<Tag, std::unordered_set<size_t>>;
|
|
||||||
struct RegistryEntry {
|
|
||||||
const CSSAnimationsVector animationsVector;
|
|
||||||
const AnimationToIndexMap animationToIndexMap;
|
|
||||||
};
|
|
||||||
|
|
||||||
using Registry = std::unordered_map<Tag, RegistryEntry>;
|
|
||||||
|
|
||||||
Registry registry_;
|
|
||||||
|
|
||||||
RunningAnimationIndicesMap runningAnimationIndicesMap_;
|
|
||||||
AnimationsToRevertMap animationsToRevertMap_;
|
|
||||||
DelayedItemsManager<std::shared_ptr<CSSAnimation>> delayedAnimationsManager_;
|
|
||||||
|
|
||||||
CSSAnimationsVector buildAnimationsVector(
|
|
||||||
jsi::Runtime &rt,
|
|
||||||
const std::shared_ptr<const ShadowNode> &shadowNode,
|
|
||||||
const std::optional<std::vector<std::string>> &animationNames,
|
|
||||||
const std::optional<CSSAnimationsMap> &newAnimations) const;
|
|
||||||
AnimationToIndexMap buildAnimationToIndexMap(
|
|
||||||
const CSSAnimationsVector &animationsVector) const;
|
|
||||||
void updateAnimationSettings(
|
|
||||||
const CSSAnimationsVector &animationsVector,
|
|
||||||
const CSSAnimationSettingsUpdatesMap &settingsUpdates,
|
|
||||||
double timestamp);
|
|
||||||
|
|
||||||
void updateViewAnimations(
|
|
||||||
Tag viewTag,
|
|
||||||
const std::vector<size_t> &animationIndices,
|
|
||||||
double timestamp,
|
|
||||||
bool addToBatch);
|
|
||||||
void scheduleOrActivateAnimation(
|
|
||||||
size_t animationIndex,
|
|
||||||
const std::shared_ptr<CSSAnimation> &animation,
|
|
||||||
double timestamp);
|
|
||||||
void removeViewAnimations(Tag viewTag);
|
|
||||||
void applyViewAnimationsStyle(Tag viewTag, double timestamp);
|
|
||||||
void activateDelayedAnimations(double timestamp);
|
|
||||||
void handleAnimationsToRevert(double timestamp);
|
|
||||||
|
|
||||||
static bool addStyleUpdates(
|
|
||||||
folly::dynamic &target,
|
|
||||||
const folly::dynamic &updates,
|
|
||||||
bool shouldOverride);
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace reanimated::css
|
|
||||||
Generated
Vendored
-47
@@ -1,47 +0,0 @@
|
|||||||
#include <reanimated/CSS/registries/CSSKeyframesRegistry.h>
|
|
||||||
|
|
||||||
namespace reanimated::css {
|
|
||||||
|
|
||||||
CSSKeyframesRegistry::CSSKeyframesRegistry(
|
|
||||||
const std::shared_ptr<ViewStylesRepository> &viewStylesRepository)
|
|
||||||
: viewStylesRepository_(viewStylesRepository) {}
|
|
||||||
|
|
||||||
const CSSKeyframesConfig &CSSKeyframesRegistry::get(
|
|
||||||
const std::string &animationName,
|
|
||||||
const std::string &componentName) {
|
|
||||||
const auto ®istryIt = registry_.find(animationName);
|
|
||||||
if (registryIt == registry_.end()) {
|
|
||||||
throw std::runtime_error(
|
|
||||||
"[Reanimated] No keyframes with name `" + animationName +
|
|
||||||
"` were registered");
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto &keyframesByComponentName = registryIt->second;
|
|
||||||
const auto &keyframesByComponentNameIt =
|
|
||||||
keyframesByComponentName.find(componentName);
|
|
||||||
if (keyframesByComponentNameIt == keyframesByComponentName.end()) {
|
|
||||||
throw std::runtime_error(
|
|
||||||
"[Reanimated] No keyframes with name `" + animationName +
|
|
||||||
"` were registered for component `" + componentName + "`");
|
|
||||||
}
|
|
||||||
|
|
||||||
return keyframesByComponentNameIt->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CSSKeyframesRegistry::set(
|
|
||||||
const std::string &animationName,
|
|
||||||
const std::string &componentName,
|
|
||||||
CSSKeyframesConfig &&config) {
|
|
||||||
registry_[animationName][componentName] = std::move(config);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CSSKeyframesRegistry::remove(
|
|
||||||
const std::string &animationName,
|
|
||||||
const std::string &componentName) {
|
|
||||||
registry_[animationName].erase(componentName);
|
|
||||||
if (registry_[animationName].empty()) {
|
|
||||||
registry_.erase(animationName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace reanimated::css
|
|
||||||
Generated
Vendored
-38
@@ -1,38 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <reanimated/CSS/configs/CSSKeyframesConfig.h>
|
|
||||||
#include <reanimated/CSS/interpolation/styles/AnimationStyleInterpolator.h>
|
|
||||||
#include <reanimated/CSS/misc/ViewStylesRepository.h>
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <string>
|
|
||||||
#include <unordered_map>
|
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
namespace reanimated::css {
|
|
||||||
|
|
||||||
class CSSKeyframesRegistry {
|
|
||||||
public:
|
|
||||||
CSSKeyframesRegistry(
|
|
||||||
const std::shared_ptr<ViewStylesRepository> &viewStylesRepository);
|
|
||||||
|
|
||||||
const CSSKeyframesConfig &get(
|
|
||||||
const std::string &animationName,
|
|
||||||
const std::string &componentName);
|
|
||||||
void set(
|
|
||||||
const std::string &animationName,
|
|
||||||
const std::string &componentName,
|
|
||||||
CSSKeyframesConfig &&config);
|
|
||||||
void remove(
|
|
||||||
const std::string &animationName,
|
|
||||||
const std::string &componentName);
|
|
||||||
|
|
||||||
private:
|
|
||||||
using ConfigsByComponentName =
|
|
||||||
std::unordered_map<std::string, CSSKeyframesConfig>;
|
|
||||||
|
|
||||||
std::unordered_map<std::string, ConfigsByComponentName> registry_;
|
|
||||||
const std::shared_ptr<ViewStylesRepository> viewStylesRepository_;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace reanimated::css
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user