187 lines
6.5 KiB
C++
187 lines
6.5 KiB
C++
/*
|
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
*
|
|
* This source code is licensed under the MIT license found in the
|
|
* LICENSE file in the root directory of this source tree.
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <ReactCommon/RuntimeExecutor.h>
|
|
#include <react/renderer/animations/LayoutAnimationCallbackWrapper.h>
|
|
#include <react/renderer/animations/primitives.h>
|
|
#include <react/renderer/core/RawValue.h>
|
|
#include <react/renderer/debug/flags.h>
|
|
#include <react/renderer/mounting/MountingOverrideDelegate.h>
|
|
#include <react/renderer/mounting/MountingTransaction.h>
|
|
#include <react/renderer/mounting/ShadowViewMutation.h>
|
|
#include <react/renderer/uimanager/LayoutAnimationStatusDelegate.h>
|
|
#include <react/renderer/uimanager/UIManagerAnimationDelegate.h>
|
|
|
|
#include <optional>
|
|
#include <unordered_set>
|
|
|
|
namespace facebook::react {
|
|
|
|
#ifdef LAYOUT_ANIMATION_VERBOSE_LOGGING
|
|
void PrintMutationInstruction(
|
|
std::string message,
|
|
const ShadowViewMutation& mutation);
|
|
void PrintMutationInstructionRelative(
|
|
std::string message,
|
|
const ShadowViewMutation& mutation,
|
|
const ShadowViewMutation& relativeMutation);
|
|
#else
|
|
#define PrintMutationInstruction(a, b)
|
|
#define PrintMutationInstructionRelative(a, b, c)
|
|
#endif
|
|
|
|
class LayoutAnimationKeyFrameManager : public UIManagerAnimationDelegate,
|
|
public MountingOverrideDelegate {
|
|
public:
|
|
LayoutAnimationKeyFrameManager(
|
|
RuntimeExecutor runtimeExecutor,
|
|
ContextContainer::Shared& contextContainer,
|
|
LayoutAnimationStatusDelegate* delegate);
|
|
|
|
#pragma mark - UIManagerAnimationDelegate methods
|
|
|
|
void uiManagerDidConfigureNextLayoutAnimation(
|
|
jsi::Runtime& runtime,
|
|
const RawValue& config,
|
|
const jsi::Value& successCallbackValue,
|
|
const jsi::Value& failureCallbackValue) const override;
|
|
|
|
void setComponentDescriptorRegistry(const SharedComponentDescriptorRegistry&
|
|
componentDescriptorRegistry) override;
|
|
|
|
// TODO: add SurfaceId to this API as well
|
|
bool shouldAnimateFrame() const override;
|
|
|
|
void stopSurface(SurfaceId surfaceId) override;
|
|
|
|
#pragma mark - MountingOverrideDelegate methods
|
|
|
|
bool shouldOverridePullTransaction() const override;
|
|
|
|
// This is used to "hijack" the diffing process to figure out which mutations
|
|
// should be animated. The mutations returned by this function will be
|
|
// executed immediately.
|
|
std::optional<MountingTransaction> pullTransaction(
|
|
SurfaceId surfaceId,
|
|
MountingTransaction::Number number,
|
|
const TransactionTelemetry& telemetry,
|
|
ShadowViewMutationList mutations) const override;
|
|
|
|
// Exposed for testing.
|
|
void uiManagerDidConfigureNextLayoutAnimation(
|
|
LayoutAnimation layoutAnimation) const;
|
|
|
|
// LayoutAnimationStatusDelegate - this is for the platform to get
|
|
// signal when animations start and complete. Setting and resetting this
|
|
// delegate is protected by a mutex; ALL method calls into this delegate are
|
|
// also protected by the mutex! The only way to set this without a mutex is
|
|
// via a constructor.
|
|
void setLayoutAnimationStatusDelegate(
|
|
LayoutAnimationStatusDelegate* delegate) const;
|
|
|
|
void setClockNow(std::function<uint64_t()> now);
|
|
|
|
protected:
|
|
SharedComponentDescriptorRegistry componentDescriptorRegistry_;
|
|
mutable std::optional<LayoutAnimation> currentAnimation_{};
|
|
mutable std::mutex currentAnimationMutex_;
|
|
|
|
/**
|
|
* All mutations of inflightAnimations_ are thread-safe as long as
|
|
* we keep the contract of: only mutate it within the context of
|
|
* `pullTransaction`. If that contract is held, this is implicitly protected
|
|
* by the MountingCoordinator's mutex.
|
|
*/
|
|
mutable std::vector<LayoutAnimation> inflightAnimations_{};
|
|
|
|
bool hasComponentDescriptorForShadowView(const ShadowView& shadowView) const;
|
|
const ComponentDescriptor& getComponentDescriptorForShadowView(
|
|
const ShadowView& shadowView) const;
|
|
|
|
/**
|
|
* Given a `progress` between 0 and 1, a mutation and LayoutAnimation config,
|
|
* return a ShadowView with mutated props and/or LayoutMetrics.
|
|
*
|
|
* @param progress the current progress for the animation
|
|
* @param startingView the initial configuration of the ShadowView
|
|
* @param finalView the final configuration of the ShadowView
|
|
* @return the current ShadowView
|
|
*/
|
|
ShadowView createInterpolatedShadowView(
|
|
Float progress,
|
|
const ShadowView& startingView,
|
|
const ShadowView& finalView) const;
|
|
|
|
void callCallback(const LayoutAnimationCallbackWrapper& callback) const;
|
|
|
|
virtual void animationMutationsForFrame(
|
|
SurfaceId surfaceId,
|
|
ShadowViewMutation::List& mutationsList,
|
|
uint64_t now) const = 0;
|
|
|
|
/**
|
|
* Queue (and potentially synthesize) final mutations for a finished keyframe.
|
|
* Keyframe animation may have timed-out, or be canceled due to a conflict.
|
|
*/
|
|
void queueFinalMutationsForCompletedKeyFrame(
|
|
const AnimationKeyFrame& keyframe,
|
|
ShadowViewMutation::List& mutationsList,
|
|
bool interrupted,
|
|
const std::string& logPrefix) const;
|
|
|
|
private:
|
|
RuntimeExecutor runtimeExecutor_;
|
|
ContextContainer::Shared contextContainer_;
|
|
|
|
mutable std::mutex layoutAnimationStatusDelegateMutex_;
|
|
mutable LayoutAnimationStatusDelegate* layoutAnimationStatusDelegate_{};
|
|
mutable std::mutex surfaceIdsToStopMutex_;
|
|
mutable std::unordered_set<SurfaceId> surfaceIdsToStop_{};
|
|
|
|
// Function that returns current time in milliseconds
|
|
std::function<uint64_t()> now_;
|
|
|
|
void adjustImmediateMutationIndicesForDelayedMutations(
|
|
SurfaceId surfaceId,
|
|
ShadowViewMutation& mutation,
|
|
bool skipLastAnimation = false,
|
|
bool lastAnimationOnly = false) const;
|
|
|
|
void adjustDelayedMutationIndicesForMutation(
|
|
SurfaceId surfaceId,
|
|
const ShadowViewMutation& mutation,
|
|
bool skipLastAnimation = false) const;
|
|
|
|
void getAndEraseConflictingAnimations(
|
|
SurfaceId surfaceId,
|
|
const ShadowViewMutationList& mutations,
|
|
std::vector<AnimationKeyFrame>& conflictingAnimations) const;
|
|
|
|
/*
|
|
* Removes animations from `inflightAnimations_` for stopped surfaces.
|
|
*/
|
|
void deleteAnimationsForStoppedSurfaces() const;
|
|
|
|
void simulateImagePropsMemoryAccess(
|
|
const ShadowViewMutationList& mutations) const;
|
|
|
|
/**
|
|
* Interpolates the props values.
|
|
*/
|
|
Props::Shared interpolateProps(
|
|
const ComponentDescriptor& componentDescriptor,
|
|
const PropsParserContext& context,
|
|
Float animationProgress,
|
|
const Props::Shared& props,
|
|
const Props::Shared& newProps,
|
|
const Size& size) const;
|
|
};
|
|
|
|
} // namespace facebook::react
|