mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2026-07-25 06:54:43 +00:00
Added ministar particles to premium bubbles with Credits type.
This commit is contained in:
@@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "base/object_ptr.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "ui/effects/gradient.h"
|
||||
#include "ui/effects/ministar_particles.h"
|
||||
#include "ui/effects/premium_graphics.h"
|
||||
#include "ui/wrap/padding_wrap.h"
|
||||
#include "ui/wrap/vertical_layout.h"
|
||||
@@ -151,53 +152,72 @@ void Bubble::setFlipHorizontal(bool value) {
|
||||
_flipHorizontal = value;
|
||||
}
|
||||
|
||||
QRect Bubble::bubbleGeometry(const QRect &r) const {
|
||||
const auto penWidth = _st.penWidth;
|
||||
const auto penWidthHalf = penWidth / 2;
|
||||
return r - style::margins(
|
||||
penWidthHalf,
|
||||
penWidthHalf,
|
||||
penWidthHalf,
|
||||
_st.tailSize.height() + penWidthHalf);
|
||||
}
|
||||
|
||||
QPainterPath Bubble::bubblePath(const QRect &r) const {
|
||||
const auto bubbleRect = bubbleGeometry(r);
|
||||
const auto radius = bubbleRadius();
|
||||
auto pathTail = QPainterPath();
|
||||
|
||||
const auto tailWHalf = _st.tailSize.width() / 2.;
|
||||
const auto progress = _tailEdge;
|
||||
|
||||
const auto tailTop = bubbleRect.y() + bubbleRect.height();
|
||||
const auto tailLeftFull = bubbleRect.x()
|
||||
+ (bubbleRect.width() * 0.5)
|
||||
- tailWHalf;
|
||||
const auto tailLeft = bubbleRect.x()
|
||||
+ (bubbleRect.width() * 0.5 * (progress + 1.))
|
||||
- tailWHalf;
|
||||
const auto tailCenter = tailLeft + tailWHalf;
|
||||
const auto tailRight = [&] {
|
||||
const auto max = bubbleRect.x() + bubbleRect.width();
|
||||
const auto right = tailLeft + _st.tailSize.width();
|
||||
const auto bottomMax = max - radius;
|
||||
return (right > bottomMax)
|
||||
? std::max(float64(tailCenter), float64(bottomMax))
|
||||
: right;
|
||||
}();
|
||||
if (_hasTail) {
|
||||
pathTail.moveTo(tailLeftFull, tailTop);
|
||||
pathTail.lineTo(tailLeft, tailTop);
|
||||
pathTail.lineTo(tailCenter, tailTop + _st.tailSize.height());
|
||||
pathTail.lineTo(tailRight, tailTop);
|
||||
pathTail.lineTo(tailRight, tailTop - radius);
|
||||
pathTail.moveTo(tailLeftFull, tailTop);
|
||||
}
|
||||
auto pathBubble = QPainterPath();
|
||||
pathBubble.setFillRule(Qt::WindingFill);
|
||||
pathBubble.addRoundedRect(bubbleRect, radius, radius);
|
||||
|
||||
auto result = pathTail + pathBubble;
|
||||
if (_flipHorizontal) {
|
||||
auto m = QTransform();
|
||||
const auto center = QRectF(bubbleRect).center();
|
||||
m.translate(center.x(), center.y());
|
||||
m.scale(-1., 1.);
|
||||
m.translate(-center.x(), -center.y());
|
||||
return m.map(result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void Bubble::paintBubble(QPainter &p, const QRect &r, const QBrush &brush) {
|
||||
if (!_counter.has_value()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto bubbleRect = bubbleGeometry(r);
|
||||
const auto penWidth = _st.penWidth;
|
||||
const auto penWidthHalf = penWidth / 2;
|
||||
const auto bubbleRect = r - style::margins(
|
||||
penWidthHalf,
|
||||
penWidthHalf,
|
||||
penWidthHalf,
|
||||
_st.tailSize.height() + penWidthHalf);
|
||||
{
|
||||
const auto radius = bubbleRadius();
|
||||
auto pathTail = QPainterPath();
|
||||
|
||||
const auto tailWHalf = _st.tailSize.width() / 2.;
|
||||
const auto progress = _tailEdge;
|
||||
|
||||
const auto tailTop = bubbleRect.y() + bubbleRect.height();
|
||||
const auto tailLeftFull = bubbleRect.x()
|
||||
+ (bubbleRect.width() * 0.5)
|
||||
- tailWHalf;
|
||||
const auto tailLeft = bubbleRect.x()
|
||||
+ (bubbleRect.width() * 0.5 * (progress + 1.))
|
||||
- tailWHalf;
|
||||
const auto tailCenter = tailLeft + tailWHalf;
|
||||
const auto tailRight = [&] {
|
||||
const auto max = bubbleRect.x() + bubbleRect.width();
|
||||
const auto right = tailLeft + _st.tailSize.width();
|
||||
const auto bottomMax = max - radius;
|
||||
return (right > bottomMax)
|
||||
? std::max(float64(tailCenter), float64(bottomMax))
|
||||
: right;
|
||||
}();
|
||||
if (_hasTail) {
|
||||
pathTail.moveTo(tailLeftFull, tailTop);
|
||||
pathTail.lineTo(tailLeft, tailTop);
|
||||
pathTail.lineTo(tailCenter, tailTop + _st.tailSize.height());
|
||||
pathTail.lineTo(tailRight, tailTop);
|
||||
pathTail.lineTo(tailRight, tailTop - radius);
|
||||
pathTail.moveTo(tailLeftFull, tailTop);
|
||||
}
|
||||
auto pathBubble = QPainterPath();
|
||||
pathBubble.setFillRule(Qt::WindingFill);
|
||||
pathBubble.addRoundedRect(bubbleRect, radius, radius);
|
||||
|
||||
auto hq = PainterHighQualityEnabler(p);
|
||||
p.setPen(QPen(
|
||||
brush,
|
||||
@@ -206,16 +226,7 @@ void Bubble::paintBubble(QPainter &p, const QRect &r, const QBrush &brush) {
|
||||
Qt::RoundCap,
|
||||
Qt::RoundJoin));
|
||||
p.setBrush(brush);
|
||||
if (_flipHorizontal) {
|
||||
auto m = QTransform();
|
||||
const auto center = QRectF(bubbleRect).center();
|
||||
m.translate(center.x(), center.y());
|
||||
m.scale(-1., 1.);
|
||||
m.translate(-center.x(), -center.y());
|
||||
p.drawPath(m.map(pathTail + pathBubble));
|
||||
} else {
|
||||
p.drawPath(pathTail + pathBubble);
|
||||
}
|
||||
p.drawPath(bubblePath(r));
|
||||
}
|
||||
p.setPen(st::activeButtonFg);
|
||||
p.setFont(_st.font);
|
||||
@@ -268,6 +279,9 @@ BubbleWidget::BubbleWidget(
|
||||
, _deflection(kDeflection)
|
||||
, _stepBeforeDeflection(kStepBeforeDeflection)
|
||||
, _stepAfterDeflection(kStepAfterDeflection) {
|
||||
if (_type == BubbleType::Credits) {
|
||||
setupParticles(parent);
|
||||
}
|
||||
const auto resizeTo = [=](int w, int h) {
|
||||
_deflection = (w > _st.widthLimit)
|
||||
? kDeflectionSmall
|
||||
@@ -303,6 +317,65 @@ BubbleWidget::BubbleWidget(
|
||||
}, lifetime());
|
||||
}
|
||||
|
||||
void BubbleWidget::setupParticles(not_null<Ui::RpWidget*> parent) {
|
||||
_particles.emplace(StarParticles::Type::Radial, 50, st::lineWidth * 4);
|
||||
_particles->setSpeed(0.1);
|
||||
|
||||
_particlesWidget = Ui::CreateChild<Ui::RpWidget>(parent);
|
||||
_particlesWidget->setAttribute(Qt::WA_TransparentForMouseEvents);
|
||||
_particlesWidget->show();
|
||||
_particlesWidget->raise();
|
||||
|
||||
_particlesAnimation.init([=] { _particlesWidget->update(); });
|
||||
|
||||
_particlesWidget->paintRequest() | rpl::start_with_next([=] {
|
||||
if (!_particlesAnimation.animating()) {
|
||||
_particlesAnimation.start();
|
||||
}
|
||||
auto p = QPainter(_particlesWidget);
|
||||
auto hq = PainterHighQualityEnabler(p);
|
||||
|
||||
const auto offset = QPoint(
|
||||
(_particlesWidget->width() - width()) / 2,
|
||||
(_particlesWidget->height() - height()) / 2);
|
||||
const auto bubbleRect = rect().translated(offset)
|
||||
- QMargins(
|
||||
_spaceForDeflection.width(),
|
||||
_spaceForDeflection.height(),
|
||||
_spaceForDeflection.width(),
|
||||
_spaceForDeflection.height());
|
||||
|
||||
p.save();
|
||||
p.translate(offset);
|
||||
const auto bubblePath = _bubble.bubblePath(bubbleRect);
|
||||
p.restore();
|
||||
|
||||
auto fullRect = QPainterPath();
|
||||
fullRect.addRect(QRectF(_particlesWidget->rect()));
|
||||
|
||||
p.setClipPath(bubblePath);
|
||||
_particles->setColor(st::premiumButtonFg->c);
|
||||
_particles->paint(p, _particlesWidget->rect(), crl::now());
|
||||
p.setClipping(false);
|
||||
|
||||
p.setClipPath(fullRect.subtracted(bubblePath));
|
||||
_particles->setColor(st::creditsBg3->c);
|
||||
_particles->paint(p, _particlesWidget->rect(), crl::now());
|
||||
}, _particlesWidget->lifetime());
|
||||
|
||||
geometryValue() | rpl::start_with_next([=](QRect geometry) {
|
||||
const auto particlesSize = QSize(
|
||||
int(geometry.width() * 1.5),
|
||||
int(geometry.height() * 1.5));
|
||||
const auto center = geometry.center();
|
||||
_particlesWidget->setGeometry(
|
||||
center.x() - particlesSize.width() / 2,
|
||||
center.y() - particlesSize.height() / 2,
|
||||
particlesSize.width(),
|
||||
particlesSize.height());
|
||||
}, lifetime());
|
||||
}
|
||||
|
||||
void BubbleWidget::animateTo(BubbleRowState state) {
|
||||
const auto targetWidth = _bubble.countTargetWidth(state.counter);
|
||||
const auto parent = parentWidget();
|
||||
@@ -399,6 +472,11 @@ void BubbleWidget::animateTo(BubbleRowState state) {
|
||||
+ counterProgress * (state.counter - _animatingFrom.counter);
|
||||
_bubble.setCounter(int(base::SafeRound(now)));
|
||||
|
||||
if (_particles) {
|
||||
const auto progress = now / float(state.counter);
|
||||
_particles->setSpeed(0.01 + progress * 0.25);
|
||||
}
|
||||
|
||||
_bubble.setFlipHorizontal(nowBubbleEdge < 0);
|
||||
_bubble.setTailEdge(std::abs(nowBubbleEdge));
|
||||
update();
|
||||
@@ -479,6 +557,10 @@ void BubbleWidget::paintEvent(QPaintEvent *e) {
|
||||
}());
|
||||
}
|
||||
|
||||
void BubbleWidget::resizeEvent(QResizeEvent *e) {
|
||||
RpWidget::resizeEvent(e);
|
||||
}
|
||||
|
||||
void AddBubbleRow(
|
||||
not_null<Ui::VerticalLayout*> parent,
|
||||
const style::PremiumBubble &st,
|
||||
|
||||
@@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#pragma once
|
||||
|
||||
#include "ui/effects/numbers_animation.h"
|
||||
#include "ui/effects/ministar_particles.h"
|
||||
#include "ui/rp_widget.h"
|
||||
|
||||
enum lngtag_count : int;
|
||||
@@ -56,11 +57,13 @@ public:
|
||||
[[nodiscard]] int bubbleRadius() const;
|
||||
[[nodiscard]] int countMaxWidth(int maxPossibleCounter) const;
|
||||
[[nodiscard]] int countTargetWidth(int targetCounter) const;
|
||||
[[nodiscard]] QRect bubbleGeometry(const QRect &r) const;
|
||||
|
||||
void setCounter(int value);
|
||||
void setTailEdge(EdgeProgress edge);
|
||||
void setFlipHorizontal(bool value);
|
||||
void paintBubble(QPainter &p, const QRect &r, const QBrush &brush);
|
||||
[[nodiscard]] QPainterPath bubblePath(const QRect &r) const;
|
||||
|
||||
[[nodiscard]] rpl::producer<> widthChanges() const;
|
||||
|
||||
@@ -117,8 +120,11 @@ public:
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *e) override;
|
||||
void resizeEvent(QResizeEvent *e) override;
|
||||
|
||||
private:
|
||||
void setupParticles(not_null<Ui::RpWidget*> parent);
|
||||
|
||||
struct GradientParams {
|
||||
int left = 0;
|
||||
int width = 0;
|
||||
@@ -151,6 +157,10 @@ private:
|
||||
float64 _stepBeforeDeflection;
|
||||
float64 _stepAfterDeflection;
|
||||
|
||||
RpWidget *_particlesWidget = nullptr;
|
||||
std::optional<StarParticles> _particles;
|
||||
Ui::Animations::Basic _particlesAnimation;
|
||||
|
||||
};
|
||||
|
||||
void AddBubbleRow(
|
||||
|
||||
Reference in New Issue
Block a user