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 {
|
- (UIImage * _Nullable)renderForSize:(CGSize)size useReferenceRendering:(bool)useReferenceRendering {
|
||||||
LottieAnimation *animation = _animationContainer.animation;
|
if (!useReferenceRendering) {
|
||||||
std::shared_ptr<lottie::RenderTreeNode> renderNode = [_animationContainer internalGetRootRenderTreeNode];
|
|
||||||
if (!renderNode) {
|
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!useReferenceRendering) {
|
LottieAnimation *animation = _animationContainer.animation;
|
||||||
|
std::shared_ptr<lottie::RenderTreeNode> renderNode = [_animationContainer internalGetRootRenderTreeNode];
|
||||||
|
if (!renderNode) {
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,7 +119,7 @@ public final class ViewController: UIViewController {
|
|||||||
|
|
||||||
self.view.layer.addSublayer(MetalEngine.shared.rootLayer)
|
self.view.layer.addSublayer(MetalEngine.shared.rootLayer)
|
||||||
|
|
||||||
if !"".isEmpty {
|
if "".isEmpty {
|
||||||
if #available(iOS 13.0, *) {
|
if #available(iOS 13.0, *) {
|
||||||
self.test = ReferenceCompareTest(view: self.view)
|
self.test = ReferenceCompareTest(view: self.view)
|
||||||
}
|
}
|
||||||
|
@ -802,11 +802,14 @@ final class ChatSendMessageContextScreenComponent: Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let standaloneReactionAnimation: AnimatedStickerNode
|
let standaloneReactionAnimation: AnimatedStickerNode
|
||||||
|
var effectiveScale: CGFloat = 1.0
|
||||||
#if targetEnvironment(simulator)
|
#if targetEnvironment(simulator)
|
||||||
standaloneReactionAnimation = DirectAnimatedStickerNode()
|
standaloneReactionAnimation = DirectAnimatedStickerNode()
|
||||||
|
effectiveScale = 1.4
|
||||||
#else
|
#else
|
||||||
if "".isEmpty {
|
if "".isEmpty {
|
||||||
standaloneReactionAnimation = DirectAnimatedStickerNode()
|
standaloneReactionAnimation = DirectAnimatedStickerNode()
|
||||||
|
effectiveScale = 1.4
|
||||||
} else {
|
} else {
|
||||||
standaloneReactionAnimation = LottieMetalAnimatedStickerNode()
|
standaloneReactionAnimation = LottieMetalAnimatedStickerNode()
|
||||||
}
|
}
|
||||||
@ -823,7 +826,7 @@ final class ChatSendMessageContextScreenComponent: Component {
|
|||||||
|
|
||||||
let pathPrefix = component.context.account.postbox.mediaBox.shortLivedResourceCachePathPrefix(customEffectResource.id)
|
let pathPrefix = component.context.account.postbox.mediaBox.shortLivedResourceCachePathPrefix(customEffectResource.id)
|
||||||
let source = AnimatedStickerResourceSource(account: component.context.account, resource: customEffectResource, fitzModifier: nil)
|
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
|
standaloneReactionAnimation.completed = { [weak self, weak standaloneReactionAnimation] _ in
|
||||||
guard let self else {
|
guard let self else {
|
||||||
return
|
return
|
||||||
|
@ -5922,17 +5922,20 @@ public class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewI
|
|||||||
let pathPrefix = item.context.account.postbox.mediaBox.shortLivedResourceCachePathPrefix(resource.id)
|
let pathPrefix = item.context.account.postbox.mediaBox.shortLivedResourceCachePathPrefix(resource.id)
|
||||||
|
|
||||||
let additionalAnimationNode: AnimatedStickerNode
|
let additionalAnimationNode: AnimatedStickerNode
|
||||||
|
var effectiveScale: CGFloat = 1.0
|
||||||
#if targetEnvironment(simulator)
|
#if targetEnvironment(simulator)
|
||||||
additionalAnimationNode = DirectAnimatedStickerNode()
|
additionalAnimationNode = DirectAnimatedStickerNode()
|
||||||
|
effectiveScale = 1.4
|
||||||
#else
|
#else
|
||||||
if "".isEmpty {
|
if "".isEmpty {
|
||||||
additionalAnimationNode = DirectAnimatedStickerNode()
|
additionalAnimationNode = DirectAnimatedStickerNode()
|
||||||
|
effectiveScale = 1.4
|
||||||
} else {
|
} else {
|
||||||
additionalAnimationNode = LottieMetalAnimatedStickerNode()
|
additionalAnimationNode = LottieMetalAnimatedStickerNode()
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
additionalAnimationNode.updateLayout(size: animationSize)
|
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
|
var animationFrame: CGRect
|
||||||
if isStickerEffect {
|
if isStickerEffect {
|
||||||
let offsetScale: CGFloat = 0.3
|
let offsetScale: CGFloat = 0.3
|
||||||
|
@ -7,7 +7,6 @@ namespace lottie {
|
|||||||
InvertedMatteLayer::InvertedMatteLayer(std::shared_ptr<CompositionLayer> inputMatte) :
|
InvertedMatteLayer::InvertedMatteLayer(std::shared_ptr<CompositionLayer> inputMatte) :
|
||||||
_inputMatte(inputMatte) {
|
_inputMatte(inputMatte) {
|
||||||
setBounds(inputMatte->bounds());
|
setBounds(inputMatte->bounds());
|
||||||
setNeedsDisplay(true);
|
|
||||||
|
|
||||||
addSublayer(_inputMatte);
|
addSublayer(_inputMatte);
|
||||||
}
|
}
|
||||||
|
@ -83,13 +83,15 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void displayWithFrame(double frame, bool forceUpdates, BezierPathsBoundingBoxContext &boundingBoxContext) {
|
void displayWithFrame(double frame, bool forceUpdates, BezierPathsBoundingBoxContext &boundingBoxContext) {
|
||||||
_transformNode->updateTree(frame, forceUpdates);
|
|
||||||
|
|
||||||
bool layerVisible = isInRangeOrEqual(frame, _inFrame, _outFrame);
|
bool layerVisible = isInRangeOrEqual(frame, _inFrame, _outFrame);
|
||||||
|
|
||||||
_contentsLayer->setTransform(_transformNode->globalTransform());
|
if (_transformNode->updateTree(frame, forceUpdates) || _contentsLayer->isHidden() != !layerVisible) {
|
||||||
_contentsLayer->setOpacity(_transformNode->opacity());
|
_contentsLayer->setTransform(_transformNode->globalTransform());
|
||||||
_contentsLayer->setIsHidden(!layerVisible);
|
_contentsLayer->setOpacity(_transformNode->opacity());
|
||||||
|
_contentsLayer->setIsHidden(!layerVisible);
|
||||||
|
|
||||||
|
updateContentsLayerParameters();
|
||||||
|
}
|
||||||
|
|
||||||
/// Only update contents if current time is within the layers time bounds.
|
/// Only update contents if current time is within the layers time bounds.
|
||||||
if (layerVisible) {
|
if (layerVisible) {
|
||||||
@ -100,6 +102,9 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual void updateContentsLayerParameters() {
|
||||||
|
}
|
||||||
|
|
||||||
virtual void displayContentsWithFrame(double frame, bool forceUpdates, BezierPathsBoundingBoxContext &boundingBoxContext) {
|
virtual void displayContentsWithFrame(double frame, bool forceUpdates, BezierPathsBoundingBoxContext &boundingBoxContext) {
|
||||||
/// To be overridden by subclass
|
/// To be overridden by subclass
|
||||||
}
|
}
|
||||||
@ -155,9 +160,6 @@ public:
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void updateRenderTree(BezierPathsBoundingBoxContext &boundingBoxContext) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
std::shared_ptr<LayerTransformNode> const transformNode() const {
|
std::shared_ptr<LayerTransformNode> const transformNode() const {
|
||||||
return _transformNode;
|
return _transformNode;
|
||||||
|
@ -174,39 +174,9 @@ public:
|
|||||||
_contentsTreeNode->_subnodes = renderTreeValue;
|
_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->_bounds = _contentsLayer->bounds();
|
||||||
_contentsTreeNode->_position = _contentsLayer->position();
|
_contentsTreeNode->_position = _contentsLayer->position();
|
||||||
_contentsTreeNode->_transform = _contentsLayer->transform();
|
|
||||||
_contentsTreeNode->_alpha = _contentsLayer->opacity();
|
|
||||||
_contentsTreeNode->_masksToBounds = _contentsLayer->masksToBounds();
|
_contentsTreeNode->_masksToBounds = _contentsLayer->masksToBounds();
|
||||||
_contentsTreeNode->_isHidden = _contentsLayer->isHidden();
|
|
||||||
|
|
||||||
_renderTreeNode->_bounds = bounds();
|
_renderTreeNode->_bounds = bounds();
|
||||||
_renderTreeNode->_position = position();
|
_renderTreeNode->_position = position();
|
||||||
@ -214,6 +184,14 @@ public:
|
|||||||
_renderTreeNode->_alpha = opacity();
|
_renderTreeNode->_alpha = opacity();
|
||||||
_renderTreeNode->_masksToBounds = masksToBounds();
|
_renderTreeNode->_masksToBounds = masksToBounds();
|
||||||
_renderTreeNode->_isHidden = isHidden();
|
_renderTreeNode->_isHidden = isHidden();
|
||||||
|
|
||||||
|
return _renderTreeNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void updateContentsLayerParameters() override {
|
||||||
|
_contentsTreeNode->_transform = _contentsLayer->transform();
|
||||||
|
_contentsTreeNode->_alpha = _contentsLayer->opacity();
|
||||||
|
_contentsTreeNode->_isHidden = _contentsLayer->isHidden();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
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->_bounds = _contentsLayer->bounds();
|
||||||
_contentRenderTreeNode->_position = _contentsLayer->position();
|
_contentRenderTreeNode->_position = _contentsLayer->position();
|
||||||
_contentRenderTreeNode->_transform = _contentsLayer->transform();
|
|
||||||
_contentRenderTreeNode->_alpha = _contentsLayer->opacity();
|
|
||||||
_contentRenderTreeNode->_masksToBounds = _contentsLayer->masksToBounds();
|
_contentRenderTreeNode->_masksToBounds = _contentsLayer->masksToBounds();
|
||||||
_contentRenderTreeNode->_isHidden = _contentsLayer->isHidden();
|
|
||||||
|
_renderTreeNode->_masksToBounds = masksToBounds();
|
||||||
|
|
||||||
_renderTreeNode->_bounds = bounds();
|
_renderTreeNode->_bounds = bounds();
|
||||||
_renderTreeNode->_position = position();
|
_renderTreeNode->_position = position();
|
||||||
_renderTreeNode->_transform = transform();
|
|
||||||
_renderTreeNode->_alpha = opacity();
|
return _renderTreeNode;
|
||||||
_renderTreeNode->_masksToBounds = masksToBounds();
|
}
|
||||||
_renderTreeNode->_isHidden = isHidden();
|
|
||||||
|
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 void displayContentsWithFrame(double frame, bool forceUpdates, BezierPathsBoundingBoxContext &boundingBoxContext) override;
|
||||||
virtual std::shared_ptr<RenderTreeNode> renderTreeNode(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:
|
private:
|
||||||
std::shared_ptr<ShapeLayerPresentationTree> _contentTree;
|
std::shared_ptr<ShapeLayerPresentationTree> _contentTree;
|
||||||
|
@ -90,7 +90,7 @@ public:
|
|||||||
_layerFontProvider->addTextLayers(textLayers);
|
_layerFontProvider->addTextLayers(textLayers);
|
||||||
_layerFontProvider->reloadTexts();
|
_layerFontProvider->reloadTexts();
|
||||||
|
|
||||||
setNeedsDisplay(true);
|
renderTreeNode();
|
||||||
}
|
}
|
||||||
|
|
||||||
void setRespectAnimationFrameRate(bool respectAnimationFrameRate) {
|
void setRespectAnimationFrameRate(bool respectAnimationFrameRate) {
|
||||||
@ -249,26 +249,9 @@ public:
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
updateRenderTree();
|
|
||||||
|
|
||||||
return _renderTreeNode;
|
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:
|
private:
|
||||||
// MARK: Internal
|
// MARK: Internal
|
||||||
|
|
||||||
|
@ -185,9 +185,12 @@ public:
|
|||||||
return localUpdatesPermeateDownstream() ? hasUpstreamUpdates() || hasLocalUpdates() : hasUpstreamUpdates();
|
return localUpdatesPermeateDownstream() ? hasUpstreamUpdates() || hasLocalUpdates() : hasUpstreamUpdates();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void updateTree(double frame, bool forceUpdates) {
|
bool updateTree(double frame, bool forceUpdates) {
|
||||||
updateContents(frame, forceUpdates);
|
if (updateContents(frame, forceUpdates)) {
|
||||||
updateOutputs(frame, forceUpdates);
|
return updateOutputs(frame, forceUpdates);
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The name of the Keypath
|
/// 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 {
|
virtual bool implementsDraw() const {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -148,7 +141,6 @@ private:
|
|||||||
private:
|
private:
|
||||||
CALayer *_superlayer = nullptr;
|
CALayer *_superlayer = nullptr;
|
||||||
std::vector<std::shared_ptr<CALayer>> _sublayers;
|
std::vector<std::shared_ptr<CALayer>> _sublayers;
|
||||||
bool _needsDisplay = false;
|
|
||||||
bool _isHidden = false;
|
bool _isHidden = false;
|
||||||
float _opacity = 1.0;
|
float _opacity = 1.0;
|
||||||
Vector2D _position = Vector2D(0.0, 0.0);
|
Vector2D _position = Vector2D(0.0, 0.0);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user