mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Lottie
This commit is contained in:
parent
5545bdd978
commit
8b20aea99b
@ -651,13 +651,13 @@ CGRect getPathNativeBoundingBox(CGPathRef _Nonnull path) {
|
||||
}
|
||||
|
||||
- (UIImage * _Nullable)renderForSize:(CGSize)size useReferenceRendering:(bool)useReferenceRendering {
|
||||
LottieAnimation *animation = _animationContainer.animation;
|
||||
std::shared_ptr<lottie::RenderTreeNode> renderNode = [_animationContainer internalGetRootRenderTreeNode];
|
||||
if (!renderNode) {
|
||||
if (!useReferenceRendering) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
if (!useReferenceRendering) {
|
||||
LottieAnimation *animation = _animationContainer.animation;
|
||||
std::shared_ptr<lottie::RenderTreeNode> renderNode = [_animationContainer internalGetRootRenderTreeNode];
|
||||
if (!renderNode) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
|
@ -119,7 +119,7 @@ public final class ViewController: UIViewController {
|
||||
|
||||
self.view.layer.addSublayer(MetalEngine.shared.rootLayer)
|
||||
|
||||
if !"".isEmpty {
|
||||
if "".isEmpty {
|
||||
if #available(iOS 13.0, *) {
|
||||
self.test = ReferenceCompareTest(view: self.view)
|
||||
}
|
||||
|
@ -802,11 +802,14 @@ final class ChatSendMessageContextScreenComponent: Component {
|
||||
}
|
||||
|
||||
let standaloneReactionAnimation: AnimatedStickerNode
|
||||
var effectiveScale: CGFloat = 1.0
|
||||
#if targetEnvironment(simulator)
|
||||
standaloneReactionAnimation = DirectAnimatedStickerNode()
|
||||
effectiveScale = 1.4
|
||||
#else
|
||||
if "".isEmpty {
|
||||
standaloneReactionAnimation = DirectAnimatedStickerNode()
|
||||
effectiveScale = 1.4
|
||||
} else {
|
||||
standaloneReactionAnimation = LottieMetalAnimatedStickerNode()
|
||||
}
|
||||
@ -823,7 +826,7 @@ final class ChatSendMessageContextScreenComponent: Component {
|
||||
|
||||
let pathPrefix = component.context.account.postbox.mediaBox.shortLivedResourceCachePathPrefix(customEffectResource.id)
|
||||
let source = AnimatedStickerResourceSource(account: component.context.account, resource: customEffectResource, fitzModifier: nil)
|
||||
standaloneReactionAnimation.setup(source: source, width: Int(effectSize.width), height: Int(effectSize.height), playbackMode: .once, mode: .direct(cachePathPrefix: pathPrefix))
|
||||
standaloneReactionAnimation.setup(source: source, width: Int(effectSize.width * effectiveScale), height: Int(effectSize.height * effectiveScale), playbackMode: .once, mode: .direct(cachePathPrefix: pathPrefix))
|
||||
standaloneReactionAnimation.completed = { [weak self, weak standaloneReactionAnimation] _ in
|
||||
guard let self else {
|
||||
return
|
||||
|
@ -5922,17 +5922,20 @@ public class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewI
|
||||
let pathPrefix = item.context.account.postbox.mediaBox.shortLivedResourceCachePathPrefix(resource.id)
|
||||
|
||||
let additionalAnimationNode: AnimatedStickerNode
|
||||
var effectiveScale: CGFloat = 1.0
|
||||
#if targetEnvironment(simulator)
|
||||
additionalAnimationNode = DirectAnimatedStickerNode()
|
||||
effectiveScale = 1.4
|
||||
#else
|
||||
if "".isEmpty {
|
||||
additionalAnimationNode = DirectAnimatedStickerNode()
|
||||
effectiveScale = 1.4
|
||||
} else {
|
||||
additionalAnimationNode = LottieMetalAnimatedStickerNode()
|
||||
}
|
||||
#endif
|
||||
additionalAnimationNode.updateLayout(size: animationSize)
|
||||
additionalAnimationNode.setup(source: source, width: Int(animationSize.width), height: Int(animationSize.height), playbackMode: .once, mode: .direct(cachePathPrefix: pathPrefix))
|
||||
additionalAnimationNode.setup(source: source, width: Int(animationSize.width * effectiveScale), height: Int(animationSize.height * effectiveScale), playbackMode: .once, mode: .direct(cachePathPrefix: pathPrefix))
|
||||
var animationFrame: CGRect
|
||||
if isStickerEffect {
|
||||
let offsetScale: CGFloat = 0.3
|
||||
|
@ -7,7 +7,6 @@ namespace lottie {
|
||||
InvertedMatteLayer::InvertedMatteLayer(std::shared_ptr<CompositionLayer> inputMatte) :
|
||||
_inputMatte(inputMatte) {
|
||||
setBounds(inputMatte->bounds());
|
||||
setNeedsDisplay(true);
|
||||
|
||||
addSublayer(_inputMatte);
|
||||
}
|
||||
|
@ -83,14 +83,16 @@ public:
|
||||
}
|
||||
|
||||
void displayWithFrame(double frame, bool forceUpdates, BezierPathsBoundingBoxContext &boundingBoxContext) {
|
||||
_transformNode->updateTree(frame, forceUpdates);
|
||||
|
||||
bool layerVisible = isInRangeOrEqual(frame, _inFrame, _outFrame);
|
||||
|
||||
if (_transformNode->updateTree(frame, forceUpdates) || _contentsLayer->isHidden() != !layerVisible) {
|
||||
_contentsLayer->setTransform(_transformNode->globalTransform());
|
||||
_contentsLayer->setOpacity(_transformNode->opacity());
|
||||
_contentsLayer->setIsHidden(!layerVisible);
|
||||
|
||||
updateContentsLayerParameters();
|
||||
}
|
||||
|
||||
/// Only update contents if current time is within the layers time bounds.
|
||||
if (layerVisible) {
|
||||
displayContentsWithFrame(frame, forceUpdates, boundingBoxContext);
|
||||
@ -100,6 +102,9 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
virtual void updateContentsLayerParameters() {
|
||||
}
|
||||
|
||||
virtual void displayContentsWithFrame(double frame, bool forceUpdates, BezierPathsBoundingBoxContext &boundingBoxContext) {
|
||||
/// To be overridden by subclass
|
||||
}
|
||||
@ -155,9 +160,6 @@ public:
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
virtual void updateRenderTree(BezierPathsBoundingBoxContext &boundingBoxContext) {
|
||||
}
|
||||
|
||||
public:
|
||||
std::shared_ptr<LayerTransformNode> const transformNode() const {
|
||||
return _transformNode;
|
||||
|
@ -174,39 +174,9 @@ public:
|
||||
_contentsTreeNode->_subnodes = renderTreeValue;
|
||||
}
|
||||
|
||||
return _renderTreeNode;
|
||||
}
|
||||
|
||||
virtual void updateRenderTree(BezierPathsBoundingBoxContext &boundingBoxContext) override {
|
||||
if (_matteLayer) {
|
||||
_matteLayer->updateRenderTree(boundingBoxContext);
|
||||
}
|
||||
|
||||
for (const auto &animationLayer : _animationLayers) {
|
||||
bool found = false;
|
||||
for (const auto &sublayer : contentsLayer()->sublayers()) {
|
||||
if (animationLayer == sublayer) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found) {
|
||||
animationLayer->updateRenderTree(boundingBoxContext);
|
||||
}
|
||||
}
|
||||
|
||||
assert(opacity() == 1.0);
|
||||
assert(!isHidden());
|
||||
assert(!masksToBounds());
|
||||
assert(transform().isIdentity());
|
||||
assert(position() == Vector2D::Zero());
|
||||
|
||||
_contentsTreeNode->_bounds = _contentsLayer->bounds();
|
||||
_contentsTreeNode->_position = _contentsLayer->position();
|
||||
_contentsTreeNode->_transform = _contentsLayer->transform();
|
||||
_contentsTreeNode->_alpha = _contentsLayer->opacity();
|
||||
_contentsTreeNode->_masksToBounds = _contentsLayer->masksToBounds();
|
||||
_contentsTreeNode->_isHidden = _contentsLayer->isHidden();
|
||||
|
||||
_renderTreeNode->_bounds = bounds();
|
||||
_renderTreeNode->_position = position();
|
||||
@ -214,6 +184,14 @@ public:
|
||||
_renderTreeNode->_alpha = opacity();
|
||||
_renderTreeNode->_masksToBounds = masksToBounds();
|
||||
_renderTreeNode->_isHidden = isHidden();
|
||||
|
||||
return _renderTreeNode;
|
||||
}
|
||||
|
||||
virtual void updateContentsLayerParameters() override {
|
||||
_contentsTreeNode->_transform = _contentsLayer->transform();
|
||||
_contentsTreeNode->_alpha = _contentsLayer->opacity();
|
||||
_contentsTreeNode->_isHidden = _contentsLayer->isHidden();
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -1388,27 +1388,22 @@ std::shared_ptr<RenderTreeNode> ShapeCompositionLayer::renderTreeNode(BezierPath
|
||||
);
|
||||
}
|
||||
|
||||
return _renderTreeNode;
|
||||
}
|
||||
|
||||
void ShapeCompositionLayer::updateRenderTree(BezierPathsBoundingBoxContext &boundingBoxContext) {
|
||||
if (_matteLayer) {
|
||||
_matteLayer->updateRenderTree(boundingBoxContext);
|
||||
}
|
||||
|
||||
_contentRenderTreeNode->_bounds = _contentsLayer->bounds();
|
||||
_contentRenderTreeNode->_position = _contentsLayer->position();
|
||||
_contentRenderTreeNode->_transform = _contentsLayer->transform();
|
||||
_contentRenderTreeNode->_alpha = _contentsLayer->opacity();
|
||||
_contentRenderTreeNode->_masksToBounds = _contentsLayer->masksToBounds();
|
||||
_contentRenderTreeNode->_isHidden = _contentsLayer->isHidden();
|
||||
|
||||
_renderTreeNode->_masksToBounds = masksToBounds();
|
||||
|
||||
_renderTreeNode->_bounds = bounds();
|
||||
_renderTreeNode->_position = position();
|
||||
_renderTreeNode->_transform = transform();
|
||||
_renderTreeNode->_alpha = opacity();
|
||||
_renderTreeNode->_masksToBounds = masksToBounds();
|
||||
_renderTreeNode->_isHidden = isHidden();
|
||||
|
||||
return _renderTreeNode;
|
||||
}
|
||||
|
||||
void ShapeCompositionLayer::updateContentsLayerParameters() {
|
||||
_contentRenderTreeNode->_transform = _contentsLayer->transform();
|
||||
_contentRenderTreeNode->_alpha = _contentsLayer->opacity();
|
||||
_contentRenderTreeNode->_isHidden = _contentsLayer->isHidden();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -18,7 +18,8 @@ public:
|
||||
|
||||
virtual void displayContentsWithFrame(double frame, bool forceUpdates, BezierPathsBoundingBoxContext &boundingBoxContext) override;
|
||||
virtual std::shared_ptr<RenderTreeNode> renderTreeNode(BezierPathsBoundingBoxContext &boundingBoxContext) override;
|
||||
virtual void updateRenderTree(BezierPathsBoundingBoxContext &boundingBoxContext) override;
|
||||
void initializeContentsLayerParameters();
|
||||
virtual void updateContentsLayerParameters() override;
|
||||
|
||||
private:
|
||||
std::shared_ptr<ShapeLayerPresentationTree> _contentTree;
|
||||
|
@ -90,7 +90,7 @@ public:
|
||||
_layerFontProvider->addTextLayers(textLayers);
|
||||
_layerFontProvider->reloadTexts();
|
||||
|
||||
setNeedsDisplay(true);
|
||||
renderTreeNode();
|
||||
}
|
||||
|
||||
void setRespectAnimationFrameRate(bool respectAnimationFrameRate) {
|
||||
@ -249,26 +249,9 @@ public:
|
||||
);
|
||||
}
|
||||
|
||||
updateRenderTree();
|
||||
|
||||
return _renderTreeNode;
|
||||
}
|
||||
|
||||
void updateRenderTree() {
|
||||
for (const auto &animationLayer : _animationLayers) {
|
||||
bool found = false;
|
||||
for (const auto &sublayer : sublayers()) {
|
||||
if (animationLayer == sublayer) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found) {
|
||||
animationLayer->updateRenderTree(_boundingBoxContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
// MARK: Internal
|
||||
|
||||
|
@ -185,9 +185,12 @@ public:
|
||||
return localUpdatesPermeateDownstream() ? hasUpstreamUpdates() || hasLocalUpdates() : hasUpstreamUpdates();
|
||||
}
|
||||
|
||||
virtual void updateTree(double frame, bool forceUpdates) {
|
||||
updateContents(frame, forceUpdates);
|
||||
updateOutputs(frame, forceUpdates);
|
||||
bool updateTree(double frame, bool forceUpdates) {
|
||||
if (updateContents(frame, forceUpdates)) {
|
||||
return updateOutputs(frame, forceUpdates);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// The name of the Keypath
|
||||
|
@ -45,13 +45,6 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
bool needsDisplay() const {
|
||||
return _needsDisplay;
|
||||
}
|
||||
void setNeedsDisplay(bool needsDisplay) {
|
||||
_needsDisplay = true;
|
||||
}
|
||||
|
||||
virtual bool implementsDraw() const {
|
||||
return false;
|
||||
}
|
||||
@ -148,7 +141,6 @@ private:
|
||||
private:
|
||||
CALayer *_superlayer = nullptr;
|
||||
std::vector<std::shared_ptr<CALayer>> _sublayers;
|
||||
bool _needsDisplay = false;
|
||||
bool _isHidden = false;
|
||||
float _opacity = 1.0;
|
||||
Vector2D _position = Vector2D(0.0, 0.0);
|
||||
|
Loading…
x
Reference in New Issue
Block a user