Files
Schnappix/node_modules/react-native-reanimated/Common/cpp/reanimated/CSS/progress/TransitionProgressProvider.cpp
T

221 lines
7.1 KiB
C++

#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