mirror of https://github.com/procxx/kepka.git
				
				
				
			Use Lottie::MultiPlayer in StickersListWidget.
This commit is contained in:
		
							parent
							
								
									09c9f4ef9a
								
							
						
					
					
						commit
						ad1816cb7c
					
				|  | @ -20,6 +20,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL | ||||||
| #include "ui/toast/toast.h" | #include "ui/toast/toast.h" | ||||||
| #include "ui/emoji_config.h" | #include "ui/emoji_config.h" | ||||||
| #include "lottie/lottie_single_player.h" | #include "lottie/lottie_single_player.h" | ||||||
|  | #include "lottie/lottie_multi_player.h" | ||||||
| #include "styles/style_chat_helpers.h" | #include "styles/style_chat_helpers.h" | ||||||
| 
 | 
 | ||||||
| namespace Stickers { | namespace Stickers { | ||||||
|  | @ -1092,7 +1093,9 @@ RecentStickerPack &GetRecentPack() { | ||||||
| 	return cRefRecentStickers(); | 	return cRefRecentStickers(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| std::unique_ptr<Lottie::SinglePlayer> LottiePlayerFromDocument( | template <typename Method> | ||||||
|  | auto LottieFromDocument( | ||||||
|  | 		Method &&method, | ||||||
| 		not_null<DocumentData*> document, | 		not_null<DocumentData*> document, | ||||||
| 		LottieSize sizeTag, | 		LottieSize sizeTag, | ||||||
| 		QSize box) { | 		QSize box) { | ||||||
|  | @ -1100,7 +1103,7 @@ std::unique_ptr<Lottie::SinglePlayer> LottiePlayerFromDocument( | ||||||
| 	const auto filepath = document->filepath(); | 	const auto filepath = document->filepath(); | ||||||
| 	if (box.width() & box.height() > kDontCacheLottieAfterArea) { | 	if (box.width() & box.height() > kDontCacheLottieAfterArea) { | ||||||
| 		// Don't use frame caching for large stickers.
 | 		// Don't use frame caching for large stickers.
 | ||||||
| 		return std::make_unique<Lottie::SinglePlayer>( | 		return method( | ||||||
| 			Lottie::ReadContent(data, filepath), | 			Lottie::ReadContent(data, filepath), | ||||||
| 			Lottie::FrameRequest{ box }); | 			Lottie::FrameRequest{ box }); | ||||||
| 	} | 	} | ||||||
|  | @ -1120,15 +1123,37 @@ std::unique_ptr<Lottie::SinglePlayer> LottiePlayerFromDocument( | ||||||
| 				weak->data().cacheBigFile().put(key, std::move(data)); | 				weak->data().cacheBigFile().put(key, std::move(data)); | ||||||
| 			}); | 			}); | ||||||
| 		}; | 		}; | ||||||
| 		return std::make_unique<Lottie::SinglePlayer>( | 		return method( | ||||||
| 			get, | 			get, | ||||||
| 			put, | 			put, | ||||||
| 			Lottie::ReadContent(data, filepath), | 			Lottie::ReadContent(data, filepath), | ||||||
| 			Lottie::FrameRequest{ box }); | 			Lottie::FrameRequest{ box }); | ||||||
| 	} | 	} | ||||||
| 	return std::make_unique<Lottie::SinglePlayer>( | 	return method( | ||||||
| 		Lottie::ReadContent(data, filepath), | 		Lottie::ReadContent(data, filepath), | ||||||
| 		Lottie::FrameRequest{ box }); | 		Lottie::FrameRequest{ box }); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | std::unique_ptr<Lottie::SinglePlayer> LottiePlayerFromDocument( | ||||||
|  | 		not_null<DocumentData*> document, | ||||||
|  | 		LottieSize sizeTag, | ||||||
|  | 		QSize box) { | ||||||
|  | 	const auto method = [](auto &&...args) { | ||||||
|  | 		return std::make_unique<Lottie::SinglePlayer>( | ||||||
|  | 			std::forward<decltype(args)>(args)...); | ||||||
|  | 	}; | ||||||
|  | 	return LottieFromDocument(method, document, sizeTag, box); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | not_null<Lottie::Animation*> LottieAnimationFromDocument( | ||||||
|  | 		not_null<Lottie::MultiPlayer*> player, | ||||||
|  | 		not_null<DocumentData*> document, | ||||||
|  | 		LottieSize sizeTag, | ||||||
|  | 		QSize box) { | ||||||
|  | 	const auto method = [&](auto &&...args) { | ||||||
|  | 		return player->append(std::forward<decltype(args)>(args)...); | ||||||
|  | 	}; | ||||||
|  | 	return LottieFromDocument(method, document, sizeTag, box); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| } // namespace Stickers
 | } // namespace Stickers
 | ||||||
|  |  | ||||||
|  | @ -13,6 +13,8 @@ class DocumentData; | ||||||
| 
 | 
 | ||||||
| namespace Lottie { | namespace Lottie { | ||||||
| class SinglePlayer; | class SinglePlayer; | ||||||
|  | class MultiPlayer; | ||||||
|  | class Animation; | ||||||
| } // namespace Lottie
 | } // namespace Lottie
 | ||||||
| 
 | 
 | ||||||
| namespace Stickers { | namespace Stickers { | ||||||
|  | @ -119,5 +121,10 @@ std::unique_ptr<Lottie::SinglePlayer> LottiePlayerFromDocument( | ||||||
| 	not_null<DocumentData*> document, | 	not_null<DocumentData*> document, | ||||||
| 	LottieSize sizeTag, | 	LottieSize sizeTag, | ||||||
| 	QSize box); | 	QSize box); | ||||||
|  | not_null<Lottie::Animation*> LottieAnimationFromDocument( | ||||||
|  | 	not_null<Lottie::MultiPlayer*> player, | ||||||
|  | 	not_null<DocumentData*> document, | ||||||
|  | 	LottieSize sizeTag, | ||||||
|  | 	QSize box); | ||||||
| 
 | 
 | ||||||
| } // namespace Stickers
 | } // namespace Stickers
 | ||||||
|  |  | ||||||
|  | @ -14,7 +14,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL | ||||||
| #include "ui/effects/animations.h" | #include "ui/effects/animations.h" | ||||||
| #include "ui/effects/ripple_animation.h" | #include "ui/effects/ripple_animation.h" | ||||||
| #include "ui/image/image.h" | #include "ui/image/image.h" | ||||||
| #include "lottie/lottie_single_player.h" | #include "lottie/lottie_multi_player.h" | ||||||
|  | #include "lottie/lottie_animation.h" | ||||||
| #include "boxes/stickers_box.h" | #include "boxes/stickers_box.h" | ||||||
| #include "inline_bots/inline_bot_result.h" | #include "inline_bots/inline_bot_result.h" | ||||||
| #include "chat_helpers/stickers.h" | #include "chat_helpers/stickers.h" | ||||||
|  | @ -839,6 +840,7 @@ bool StickersListWidget::enumerateSections(Callback callback) const { | ||||||
| 
 | 
 | ||||||
| StickersListWidget::SectionInfo StickersListWidget::sectionInfo(int section) const { | StickersListWidget::SectionInfo StickersListWidget::sectionInfo(int section) const { | ||||||
| 	Expects(section >= 0 && section < shownSets().size()); | 	Expects(section >= 0 && section < shownSets().size()); | ||||||
|  | 
 | ||||||
| 	auto result = SectionInfo(); | 	auto result = SectionInfo(); | ||||||
| 	enumerateSections([searchForSection = section, &result](const SectionInfo &info) { | 	enumerateSections([searchForSection = section, &result](const SectionInfo &info) { | ||||||
| 		if (info.section == searchForSection) { | 		if (info.section == searchForSection) { | ||||||
|  | @ -1200,6 +1202,13 @@ void StickersListWidget::paintStickers(Painter &p, QRect clip) { | ||||||
| 			return false; | 			return false; | ||||||
| 		} | 		} | ||||||
| 		auto &set = sets[info.section]; | 		auto &set = sets[info.section]; | ||||||
|  | 		if (const auto player = set.lottiePlayer.get()) { | ||||||
|  | 			const auto paused = controller()->isGifPausedAtLeastFor( | ||||||
|  | 				Window::GifPauseReason::SavedGifs); | ||||||
|  | 			if (!paused) { | ||||||
|  | 				player->markFrameShown(); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
| 		if (set.externalLayout) { | 		if (set.externalLayout) { | ||||||
| 			const auto size = (set.flags | 			const auto size = (set.flags | ||||||
| 				& MTPDstickerSet_ClientFlag::f_not_loaded) | 				& MTPDstickerSet_ClientFlag::f_not_loaded) | ||||||
|  | @ -1364,21 +1373,41 @@ void StickersListWidget::paintMegagroupEmptySet(Painter &p, int y, bool buttonSe | ||||||
| 	p.drawTextLeft(button.x() - (st::stickerGroupCategoryAdd.width / 2), button.y() + st::stickerGroupCategoryAdd.textTop, width(), _megagroupSetButtonText, _megagroupSetButtonTextWidth); | 	p.drawTextLeft(button.x() - (st::stickerGroupCategoryAdd.width / 2), button.y() + st::stickerGroupCategoryAdd.textTop, width(), _megagroupSetButtonText, _megagroupSetButtonTextWidth); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void StickersListWidget::ensureLottiePlayer(Set &set) { | ||||||
|  | 	if (set.lottiePlayer) { | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  | 	set.lottiePlayer = std::make_unique<Lottie::MultiPlayer>( | ||||||
|  | 		getLottieRenderer()); | ||||||
|  | 	const auto raw = set.lottiePlayer.get(); | ||||||
|  | 	set.lottiePlayer->updates( | ||||||
|  | 	) | rpl::start_with_next([=] { | ||||||
|  | 		const auto &sets = shownSets(); | ||||||
|  | 
 | ||||||
|  | 		enumerateSections([&](const SectionInfo &info) { | ||||||
|  | 			if (shownSets()[info.section].lottiePlayer.get() == raw) { | ||||||
|  | 				update( | ||||||
|  | 					0, | ||||||
|  | 					info.rowsTop, | ||||||
|  | 					width(), | ||||||
|  | 					info.rowsBottom - info.rowsTop); | ||||||
|  | 				return false; | ||||||
|  | 			} | ||||||
|  | 			return true; | ||||||
|  | 		}); | ||||||
|  | 	}, lifetime()); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void StickersListWidget::setupLottie(Set &set, int section, int index) { | void StickersListWidget::setupLottie(Set &set, int section, int index) { | ||||||
| 	auto &sticker = set.stickers[index]; | 	auto &sticker = set.stickers[index]; | ||||||
| 	const auto document = sticker.document; | 	const auto document = sticker.document; | ||||||
| 
 | 
 | ||||||
| 	sticker.animated = Stickers::LottiePlayerFromDocument( | 	ensureLottiePlayer(set); | ||||||
|  | 	sticker.animated = Stickers::LottieAnimationFromDocument( | ||||||
|  | 		set.lottiePlayer.get(), | ||||||
| 		document, | 		document, | ||||||
| 		Stickers::LottieSize::StickersPanel, | 		Stickers::LottieSize::StickersPanel, | ||||||
| 		boundingBoxSize() * cIntRetinaFactor()); | 		boundingBoxSize() * cIntRetinaFactor()); | ||||||
| 	const auto animation = sticker.animated.get(); |  | ||||||
| 
 |  | ||||||
| 	animation->updates( |  | ||||||
| 	) | rpl::start_with_next_error([=](Lottie::Update update) { |  | ||||||
| 		rtlupdate(stickerRect(section, index)); |  | ||||||
| 	}, [=](Lottie::Error error) { |  | ||||||
| 	}, lifetime()); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| QSize StickersListWidget::boundingBoxSize() const { | QSize StickersListWidget::boundingBoxSize() const { | ||||||
|  | @ -1419,11 +1448,6 @@ void StickersListWidget::paintSticker(Painter &p, Set &set, int y, int section, | ||||||
| 	if (sticker.animated && sticker.animated->ready()) { | 	if (sticker.animated && sticker.animated->ready()) { | ||||||
| 		auto request = Lottie::FrameRequest(); | 		auto request = Lottie::FrameRequest(); | ||||||
| 		request.box = boundingBoxSize() * cIntRetinaFactor(); | 		request.box = boundingBoxSize() * cIntRetinaFactor(); | ||||||
| 		const auto paused = controller()->isGifPausedAtLeastFor( |  | ||||||
| 			Window::GifPauseReason::SavedGifs); |  | ||||||
| 		if (!paused) { |  | ||||||
| 			sticker.animated->markFrameShown(); |  | ||||||
| 		} |  | ||||||
| 		const auto frame = sticker.animated->frame(request); | 		const auto frame = sticker.animated->frame(request); | ||||||
| 		p.drawImage( | 		p.drawImage( | ||||||
| 			QRect(ppos, frame.size() / cIntRetinaFactor()), | 			QRect(ppos, frame.size() / cIntRetinaFactor()), | ||||||
|  | @ -1787,7 +1811,7 @@ void StickersListWidget::refreshStickers() { | ||||||
| 	refreshFavedStickers(); | 	refreshFavedStickers(); | ||||||
| 	refreshRecentStickers(false); | 	refreshRecentStickers(false); | ||||||
| 	refreshMegagroupStickers(GroupStickersPlace::Visible); | 	refreshMegagroupStickers(GroupStickersPlace::Visible); | ||||||
| 	for_const (auto setId, Auth().data().stickerSetsOrder()) { | 	for (const auto setId : Auth().data().stickerSetsOrder()) { | ||||||
| 		const auto externalLayout = false; | 		const auto externalLayout = false; | ||||||
| 		appendSet(_mySets, setId, externalLayout, AppendSkip::Archived); | 		appendSet(_mySets, setId, externalLayout, AppendSkip::Archived); | ||||||
| 	} | 	} | ||||||
|  | @ -1796,7 +1820,7 @@ void StickersListWidget::refreshStickers() { | ||||||
| 	_featuredSets.clear(); | 	_featuredSets.clear(); | ||||||
| 	_featuredSets.reserve(Auth().data().featuredStickerSetsOrder().size()); | 	_featuredSets.reserve(Auth().data().featuredStickerSetsOrder().size()); | ||||||
| 
 | 
 | ||||||
| 	for_const (auto setId, Auth().data().featuredStickerSetsOrder()) { | 	for (const auto setId : Auth().data().featuredStickerSetsOrder()) { | ||||||
| 		const auto externalLayout = true; | 		const auto externalLayout = true; | ||||||
| 		appendSet(_featuredSets, setId, externalLayout, AppendSkip::Installed); | 		appendSet(_featuredSets, setId, externalLayout, AppendSkip::Installed); | ||||||
| 	} | 	} | ||||||
|  | @ -2311,6 +2335,16 @@ void StickersListWidget::showPreview() { | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | auto StickersListWidget::getLottieRenderer() | ||||||
|  | -> std::shared_ptr<Lottie::FrameRenderer> { | ||||||
|  | 	if (auto result = _lottieRenderer.lock()) { | ||||||
|  | 		return result; | ||||||
|  | 	} | ||||||
|  | 	auto result = Lottie::MakeFrameRenderer(); | ||||||
|  | 	_lottieRenderer = result; | ||||||
|  | 	return result; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void StickersListWidget::showStickerSet(uint64 setId) { | void StickersListWidget::showStickerSet(uint64 setId) { | ||||||
| 	clearSelection(); | 	clearSelection(); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -22,7 +22,9 @@ class RippleAnimation; | ||||||
| } // namespace Ui
 | } // namespace Ui
 | ||||||
| 
 | 
 | ||||||
| namespace Lottie { | namespace Lottie { | ||||||
| class SinglePlayer; | class Animation; | ||||||
|  | class MultiPlayer; | ||||||
|  | class FrameRenderer; | ||||||
| } // namespace Lottie
 | } // namespace Lottie
 | ||||||
| 
 | 
 | ||||||
| namespace ChatHelpers { | namespace ChatHelpers { | ||||||
|  | @ -141,7 +143,7 @@ private: | ||||||
| 
 | 
 | ||||||
| 	struct Sticker { | 	struct Sticker { | ||||||
| 		not_null<DocumentData*> document; | 		not_null<DocumentData*> document; | ||||||
| 		std::unique_ptr<Lottie::SinglePlayer> animated; | 		Lottie::Animation *animated = nullptr; | ||||||
| 	}; | 	}; | ||||||
| 
 | 
 | ||||||
| 	struct Set { | 	struct Set { | ||||||
|  | @ -165,6 +167,7 @@ private: | ||||||
| 		ImagePtr thumbnail; | 		ImagePtr thumbnail; | ||||||
| 		std::vector<Sticker> stickers; | 		std::vector<Sticker> stickers; | ||||||
| 		std::unique_ptr<Ui::RippleAnimation> ripple; | 		std::unique_ptr<Ui::RippleAnimation> ripple; | ||||||
|  | 		std::unique_ptr<Lottie::MultiPlayer> lottiePlayer; | ||||||
| 		bool externalLayout = false; | 		bool externalLayout = false; | ||||||
| 		int count = 0; | 		int count = 0; | ||||||
| 	}; | 	}; | ||||||
|  | @ -223,6 +226,8 @@ private: | ||||||
| 	void paintMegagroupEmptySet(Painter &p, int y, bool buttonSelected); | 	void paintMegagroupEmptySet(Painter &p, int y, bool buttonSelected); | ||||||
| 	void paintSticker(Painter &p, Set &set, int y, int section, int index, bool selected, bool deleteSelected); | 	void paintSticker(Painter &p, Set &set, int y, int section, int index, bool selected, bool deleteSelected); | ||||||
| 	void paintEmptySearchResults(Painter &p); | 	void paintEmptySearchResults(Painter &p); | ||||||
|  | 
 | ||||||
|  | 	void ensureLottiePlayer(Set &set); | ||||||
| 	void setupLottie(Set &set, int section, int index); | 	void setupLottie(Set &set, int section, int index); | ||||||
| 
 | 
 | ||||||
| 	int stickersRight() const; | 	int stickersRight() const; | ||||||
|  | @ -265,6 +270,8 @@ private: | ||||||
| 
 | 
 | ||||||
| 	void showPreview(); | 	void showPreview(); | ||||||
| 
 | 
 | ||||||
|  | 	std::shared_ptr<Lottie::FrameRenderer> getLottieRenderer(); | ||||||
|  | 
 | ||||||
| 	ChannelData *_megagroupSet = nullptr; | 	ChannelData *_megagroupSet = nullptr; | ||||||
| 	uint64 _megagroupSetIdRequested = 0; | 	uint64 _megagroupSetIdRequested = 0; | ||||||
| 	std::vector<Set> _mySets; | 	std::vector<Set> _mySets; | ||||||
|  | @ -273,6 +280,7 @@ private: | ||||||
| 	base::flat_set<uint64> _installedLocallySets; | 	base::flat_set<uint64> _installedLocallySets; | ||||||
| 	std::vector<bool> _custom; | 	std::vector<bool> _custom; | ||||||
| 	base::flat_set<not_null<DocumentData*>> _favedStickersMap; | 	base::flat_set<not_null<DocumentData*>> _favedStickersMap; | ||||||
|  | 	std::weak_ptr<Lottie::FrameRenderer> _lottieRenderer; | ||||||
| 
 | 
 | ||||||
| 	Section _section = Section::Stickers; | 	Section _section = Section::Stickers; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue