mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-16 14:17:12 +02:00
Show premium effects in sticker preview.
This commit is contained in:
parent
af9a252b64
commit
877be8e6cb
2 changed files with 98 additions and 24 deletions
|
@ -25,7 +25,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
namespace Window {
|
||||
namespace {
|
||||
|
||||
constexpr int kStickerPreviewEmojiLimit = 10;
|
||||
constexpr auto kStickerPreviewEmojiLimit = 10;
|
||||
constexpr auto kPremiumMultiplier = 2.25;
|
||||
constexpr auto kPremiumDownscale = 1.5;
|
||||
|
||||
} // namespace
|
||||
|
||||
|
@ -44,25 +46,34 @@ MediaPreviewWidget::MediaPreviewWidget(
|
|||
|
||||
QRect MediaPreviewWidget::updateArea() const {
|
||||
const auto size = currentDimensions();
|
||||
return QRect(
|
||||
QPoint((width() - size.width()) / 2, (height() - size.height()) / 2),
|
||||
size);
|
||||
const auto position = QPoint(
|
||||
(width() - size.width()) / 2,
|
||||
(height() - size.height()) / 2);
|
||||
const auto premium = _document && _document->isPremiumSticker();
|
||||
const auto adjusted = position
|
||||
- (premium
|
||||
? QPoint(size.width() - (size.width() / 2), size.height() / 2)
|
||||
: QPoint());
|
||||
return QRect(adjusted, size * (premium ? 2 : 1));
|
||||
}
|
||||
|
||||
void MediaPreviewWidget::paintEvent(QPaintEvent *e) {
|
||||
Painter p(this);
|
||||
QRect r(e->rect());
|
||||
|
||||
const auto image = [&] {
|
||||
if (!_lottie || !_lottie->ready()) {
|
||||
return QImage();
|
||||
}
|
||||
_lottie->markFrameShown();
|
||||
return _lottie->frame();
|
||||
}();
|
||||
const auto r = e->rect();
|
||||
const auto factor = cIntRetinaFactor();
|
||||
const auto dimensions = currentDimensions();
|
||||
const auto frame = (_lottie && _lottie->ready())
|
||||
? _lottie->frameInfo({ dimensions * factor })
|
||||
: Lottie::Animation::FrameInfo();
|
||||
const auto effect = (_effect && _effect->ready())
|
||||
? _effect->frameInfo({ dimensions * kPremiumMultiplier * factor })
|
||||
: Lottie::Animation::FrameInfo();
|
||||
const auto image = frame.image;
|
||||
const auto effectImage = effect.image;
|
||||
const auto pixmap = image.isNull() ? currentImage() : QPixmap();
|
||||
const auto size = image.isNull() ? pixmap.size() : image.size();
|
||||
int w = size.width() / cIntRetinaFactor(), h = size.height() / cIntRetinaFactor();
|
||||
int w = size.width() / factor, h = size.height() / factor;
|
||||
auto shown = _a_shown.value(_hiding ? 0. : 1.);
|
||||
if (!_a_shown.animating()) {
|
||||
if (_hiding) {
|
||||
|
@ -76,12 +87,14 @@ void MediaPreviewWidget::paintEvent(QPaintEvent *e) {
|
|||
// h = qMax(qRound(h * (st::stickerPreviewMin + ((1. - st::stickerPreviewMin) * shown)) / 2.) * 2 + int(h % 2), 1);
|
||||
}
|
||||
p.fillRect(r, st::stickerPreviewBg);
|
||||
const auto position = innerPosition({ w, h });
|
||||
if (image.isNull()) {
|
||||
p.drawPixmap((width() - w) / 2, (height() - h) / 2, pixmap);
|
||||
p.drawPixmap(position, pixmap);
|
||||
} else {
|
||||
p.drawImage(
|
||||
QRect((width() - w) / 2, (height() - h) / 2, w, h),
|
||||
image);
|
||||
p.drawImage(QRect(position, QSize(w, h)), image);
|
||||
}
|
||||
if (!effectImage.isNull()) {
|
||||
p.drawImage(outerPosition({ w, h }), effectImage);
|
||||
}
|
||||
if (!_emojiList.empty()) {
|
||||
const auto emojiCount = _emojiList.size();
|
||||
|
@ -98,12 +111,39 @@ void MediaPreviewWidget::paintEvent(QPaintEvent *e) {
|
|||
emojiLeft += _emojiSize + st::stickerEmojiSkip;
|
||||
}
|
||||
}
|
||||
if (!frame.image.isNull() && frame.index <= effect.index) {
|
||||
_lottie->markFrameShown();
|
||||
}
|
||||
if (!effect.image.isNull() && effect.index <= frame.index) {
|
||||
_effect->markFrameShown();
|
||||
}
|
||||
}
|
||||
|
||||
void MediaPreviewWidget::resizeEvent(QResizeEvent *e) {
|
||||
update();
|
||||
}
|
||||
|
||||
QPoint MediaPreviewWidget::innerPosition(QSize size) const {
|
||||
if (!_document || !_document->isPremiumSticker()) {
|
||||
return QPoint(
|
||||
(width() - size.width()) / 2,
|
||||
(height() - size.height()) / 2);
|
||||
}
|
||||
const auto outer = size * kPremiumMultiplier;
|
||||
const auto shift = outer.width() / 40;
|
||||
return outerPosition(size)
|
||||
+ QPoint(
|
||||
outer.width() - size.width() - shift,
|
||||
(outer.height() - size.height()) / 2);
|
||||
}
|
||||
|
||||
QPoint MediaPreviewWidget::outerPosition(QSize size) const {
|
||||
const auto outer = size * kPremiumMultiplier;
|
||||
return QPoint(
|
||||
(width() - outer.width()) / 2,
|
||||
(height() - outer.height()) / 2);
|
||||
}
|
||||
|
||||
void MediaPreviewWidget::showPreview(
|
||||
Data::FileOrigin origin,
|
||||
not_null<DocumentData*> document) {
|
||||
|
@ -189,6 +229,7 @@ void MediaPreviewWidget::fillEmojiString() {
|
|||
|
||||
void MediaPreviewWidget::resetGifAndCache() {
|
||||
_lottie = nullptr;
|
||||
_effect = nullptr;
|
||||
_gif.reset();
|
||||
_gifThumbnail.reset();
|
||||
_gifLastPosition = 0;
|
||||
|
@ -220,6 +261,9 @@ QSize MediaPreviewWidget::currentDimensions() const {
|
|||
}
|
||||
if (_document->sticker()) {
|
||||
box = QSize(st::maxStickerSize, st::maxStickerSize);
|
||||
if (_document->isPremiumSticker()) {
|
||||
result = (box /= kPremiumDownscale);
|
||||
}
|
||||
} else {
|
||||
box = QSize(2 * st::maxStickerSize, 2 * st::maxStickerSize);
|
||||
}
|
||||
|
@ -239,22 +283,49 @@ QSize MediaPreviewWidget::currentDimensions() const {
|
|||
return result;
|
||||
}
|
||||
|
||||
void MediaPreviewWidget::createLottieIfReady(
|
||||
not_null<DocumentData*> document) {
|
||||
const auto sticker = document->sticker();
|
||||
if (!sticker
|
||||
|| !sticker->isLottie()
|
||||
|| _lottie
|
||||
|| !_documentMedia->loaded()) {
|
||||
return;
|
||||
} else if (document->isPremiumSticker()
|
||||
&& _documentMedia->videoThumbnailContent().isEmpty()) {
|
||||
return;
|
||||
}
|
||||
const_cast<MediaPreviewWidget*>(this)->setupLottie();
|
||||
}
|
||||
|
||||
void MediaPreviewWidget::setupLottie() {
|
||||
Expects(_document != nullptr);
|
||||
|
||||
const auto factor = cIntRetinaFactor();
|
||||
const auto size = currentDimensions();
|
||||
_lottie = std::make_unique<Lottie::SinglePlayer>(
|
||||
Lottie::ReadContent(_documentMedia->bytes(), _document->filepath()),
|
||||
Lottie::FrameRequest{ currentDimensions() * cIntRetinaFactor() },
|
||||
Lottie::FrameRequest{ size * factor },
|
||||
Lottie::Quality::High);
|
||||
if (_document->isPremiumSticker()) {
|
||||
_effect = std::make_unique<Lottie::SinglePlayer>(
|
||||
Lottie::ReadContent(_documentMedia->videoThumbnailContent(), {}),
|
||||
Lottie::FrameRequest{ size * kPremiumMultiplier * factor },
|
||||
Lottie::Quality::High);
|
||||
}
|
||||
|
||||
_lottie->updates(
|
||||
) | rpl::start_with_next([=](Lottie::Update update) {
|
||||
const auto handler = [=](Lottie::Update update) {
|
||||
v::match(update.data, [&](const Lottie::Information &) {
|
||||
this->update();
|
||||
}, [&](const Lottie::DisplayFrameRequest &) {
|
||||
this->update(updateArea());
|
||||
});
|
||||
}, lifetime());
|
||||
};
|
||||
|
||||
_lottie->updates() | rpl::start_with_next(handler, lifetime());
|
||||
if (_effect) {
|
||||
_effect->updates() | rpl::start_with_next(handler, lifetime());
|
||||
}
|
||||
}
|
||||
|
||||
QPixmap MediaPreviewWidget::currentImage() const {
|
||||
|
@ -264,9 +335,8 @@ QPixmap MediaPreviewWidget::currentImage() const {
|
|||
const auto webm = sticker && sticker->isWebm();
|
||||
if (sticker && !webm) {
|
||||
if (_cacheStatus != CacheLoaded) {
|
||||
if (sticker->isLottie() && !_lottie && _documentMedia->loaded()) {
|
||||
const_cast<MediaPreviewWidget*>(this)->setupLottie();
|
||||
}
|
||||
const_cast<MediaPreviewWidget*>(this)->createLottieIfReady(
|
||||
_document);
|
||||
if (_lottie && _lottie->ready()) {
|
||||
return QPixmap();
|
||||
} else if (const auto image = _documentMedia->getStickerLarge()) {
|
||||
|
|
|
@ -50,10 +50,13 @@ private:
|
|||
void startGifAnimation(const Media::Clip::ReaderPointer &gif);
|
||||
QSize currentDimensions() const;
|
||||
QPixmap currentImage() const;
|
||||
void createLottieIfReady(not_null<DocumentData*> document);
|
||||
void setupLottie();
|
||||
void startShow();
|
||||
void fillEmojiString();
|
||||
void resetGifAndCache();
|
||||
[[nodiscard]] QPoint innerPosition(QSize size) const;
|
||||
[[nodiscard]] QPoint outerPosition(QSize size) const;
|
||||
[[nodiscard]] QRect updateArea() const;
|
||||
|
||||
not_null<Window::SessionController*> _controller;
|
||||
|
@ -69,6 +72,7 @@ private:
|
|||
bool _gifWithAlpha = false;
|
||||
crl::time _gifLastPosition = 0;
|
||||
std::unique_ptr<Lottie::SinglePlayer> _lottie;
|
||||
std::unique_ptr<Lottie::SinglePlayer> _effect;
|
||||
|
||||
int _emojiSize;
|
||||
std::vector<not_null<EmojiPtr>> _emojiList;
|
||||
|
|
Loading…
Add table
Reference in a new issue