mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
Added stars animation to box for premium gifts.
This commit is contained in:
parent
c7c8ebed13
commit
032372f150
5 changed files with 316 additions and 188 deletions
|
@ -21,6 +21,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "settings/settings_premium.h"
|
#include "settings/settings_premium.h"
|
||||||
#include "ui/basic_click_handlers.h" // UrlClickHandler::Open.
|
#include "ui/basic_click_handlers.h" // UrlClickHandler::Open.
|
||||||
#include "ui/effects/premium_graphics.h"
|
#include "ui/effects/premium_graphics.h"
|
||||||
|
#include "ui/effects/premium_stars.h"
|
||||||
#include "ui/layers/generic_box.h"
|
#include "ui/layers/generic_box.h"
|
||||||
#include "ui/special_buttons.h"
|
#include "ui/special_buttons.h"
|
||||||
#include "ui/text/format_values.h"
|
#include "ui/text/format_values.h"
|
||||||
|
@ -89,6 +90,76 @@ GiftOptions GiftOptionFromTL(
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class ColoredMiniStars final {
|
||||||
|
public:
|
||||||
|
ColoredMiniStars(not_null<Ui::RpWidget*> parent);
|
||||||
|
|
||||||
|
void setSize(const QSize &size);
|
||||||
|
void setPosition(QPoint position);
|
||||||
|
void paint(Painter &p);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Ui::Premium::MiniStars _ministars;
|
||||||
|
QRectF _ministarsRect;
|
||||||
|
QImage _frame;
|
||||||
|
QImage _mask;
|
||||||
|
QSize _size;
|
||||||
|
QPoint _position;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
ColoredMiniStars::ColoredMiniStars(not_null<Ui::RpWidget*> parent)
|
||||||
|
: _ministars([=](const QRect &r) {
|
||||||
|
parent->update(r.translated(_position));
|
||||||
|
}, true) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void ColoredMiniStars::setSize(const QSize &size) {
|
||||||
|
_frame = QImage(
|
||||||
|
size * style::DevicePixelRatio(),
|
||||||
|
QImage::Format_ARGB32_Premultiplied);
|
||||||
|
_frame.setDevicePixelRatio(style::DevicePixelRatio());
|
||||||
|
|
||||||
|
_mask = _frame;
|
||||||
|
_mask.fill(Qt::transparent);
|
||||||
|
{
|
||||||
|
Painter p(&_mask);
|
||||||
|
auto gradient = QLinearGradient(0, 0, size.width(), 0);
|
||||||
|
gradient.setStops(Ui::Premium::GiftGradientStops());
|
||||||
|
p.setPen(Qt::NoPen);
|
||||||
|
p.setBrush(gradient);
|
||||||
|
p.drawRect(0, 0, size.width(), size.height());
|
||||||
|
}
|
||||||
|
|
||||||
|
_size = size;
|
||||||
|
|
||||||
|
{
|
||||||
|
const auto s = _size / Ui::Premium::MiniStars::kSizeFactor;
|
||||||
|
const auto margins = QMarginsF(
|
||||||
|
s.width() / 2.,
|
||||||
|
s.height() / 2.,
|
||||||
|
s.width() / 2.,
|
||||||
|
s.height() / 2.);
|
||||||
|
_ministarsRect = QRectF(QPointF(), _size) - margins;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ColoredMiniStars::setPosition(QPoint position) {
|
||||||
|
_position = std::move(position);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ColoredMiniStars::paint(Painter &p) {
|
||||||
|
_frame.fill(Qt::transparent);
|
||||||
|
{
|
||||||
|
Painter q(&_frame);
|
||||||
|
_ministars.paint(q, _ministarsRect);
|
||||||
|
q.setCompositionMode(QPainter::CompositionMode_SourceIn);
|
||||||
|
q.drawImage(0, 0, _mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
p.drawImage(_position, _frame);
|
||||||
|
}
|
||||||
|
|
||||||
void GiftBox(
|
void GiftBox(
|
||||||
not_null<Ui::GenericBox*> box,
|
not_null<Ui::GenericBox*> box,
|
||||||
not_null<Window::SessionController*> controller,
|
not_null<Window::SessionController*> controller,
|
||||||
|
@ -111,6 +182,8 @@ void GiftBox(
|
||||||
+ userpicPadding.bottom()
|
+ userpicPadding.bottom()
|
||||||
+ st::defaultUserpicButton.size.height()));
|
+ st::defaultUserpicButton.size.height()));
|
||||||
|
|
||||||
|
const auto stars = box->lifetime().make_state<ColoredMiniStars>(top);
|
||||||
|
|
||||||
const auto userpic = Ui::CreateChild<Ui::UserpicButton>(
|
const auto userpic = Ui::CreateChild<Ui::UserpicButton>(
|
||||||
top,
|
top,
|
||||||
user,
|
user,
|
||||||
|
@ -122,8 +195,26 @@ void GiftBox(
|
||||||
userpic->moveToLeft(
|
userpic->moveToLeft(
|
||||||
(width - userpic->width()) / 2,
|
(width - userpic->width()) / 2,
|
||||||
userpicPadding.top());
|
userpicPadding.top());
|
||||||
|
|
||||||
|
const auto center = top->rect().center();
|
||||||
|
const auto size = QSize(
|
||||||
|
userpic->width() * Ui::Premium::MiniStars::kSizeFactor,
|
||||||
|
userpic->height());
|
||||||
|
const auto ministarsRect = QRect(
|
||||||
|
QPoint(center.x() - size.width(), center.y() - size.height()),
|
||||||
|
QPoint(center.x() + size.width(), center.y() + size.height()));
|
||||||
|
stars->setPosition(ministarsRect.topLeft());
|
||||||
|
stars->setSize(ministarsRect.size());
|
||||||
}, userpic->lifetime());
|
}, userpic->lifetime());
|
||||||
|
|
||||||
|
top->paintRequest(
|
||||||
|
) | rpl::start_with_next([=](const QRect &r) {
|
||||||
|
Painter p(top);
|
||||||
|
|
||||||
|
p.fillRect(r, Qt::transparent);
|
||||||
|
stars->paint(p);
|
||||||
|
}, top->lifetime());
|
||||||
|
|
||||||
const auto close = Ui::CreateChild<Ui::IconButton>(
|
const auto close = Ui::CreateChild<Ui::IconButton>(
|
||||||
buttonsParent,
|
buttonsParent,
|
||||||
st::infoTopBarClose);
|
st::infoTopBarClose);
|
||||||
|
|
|
@ -7,7 +7,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
*/
|
*/
|
||||||
#include "settings/settings_premium.h"
|
#include "settings/settings_premium.h"
|
||||||
|
|
||||||
#include "base/random.h"
|
|
||||||
#include "core/application.h"
|
#include "core/application.h"
|
||||||
#include "core/click_handler_types.h"
|
#include "core/click_handler_types.h"
|
||||||
#include "data/data_peer_values.h"
|
#include "data/data_peer_values.h"
|
||||||
|
@ -19,9 +18,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "settings/settings_premium.h"
|
#include "settings/settings_premium.h"
|
||||||
#include "ui/abstract_button.h"
|
#include "ui/abstract_button.h"
|
||||||
#include "ui/basic_click_handlers.h"
|
#include "ui/basic_click_handlers.h"
|
||||||
#include "ui/effects/animation_value_f.h"
|
|
||||||
#include "ui/effects/gradient.h"
|
#include "ui/effects/gradient.h"
|
||||||
#include "ui/effects/premium_graphics.h"
|
#include "ui/effects/premium_graphics.h"
|
||||||
|
#include "ui/effects/premium_stars.h"
|
||||||
#include "ui/text/text_utilities.h"
|
#include "ui/text/text_utilities.h"
|
||||||
#include "ui/text/format_values.h"
|
#include "ui/text/format_values.h"
|
||||||
#include "ui/layers/generic_box.h"
|
#include "ui/layers/generic_box.h"
|
||||||
|
@ -46,8 +45,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "styles/style_layers.h"
|
#include "styles/style_layers.h"
|
||||||
#include "styles/style_settings.h"
|
#include "styles/style_settings.h"
|
||||||
|
|
||||||
#include <QSvgRenderer>
|
|
||||||
|
|
||||||
namespace Settings {
|
namespace Settings {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
@ -58,8 +55,6 @@ constexpr auto kTitleAnimationPart = 0.15;
|
||||||
|
|
||||||
constexpr auto kTitleAdditionalScale = 0.15;
|
constexpr auto kTitleAdditionalScale = 0.15;
|
||||||
|
|
||||||
constexpr auto kDeformationMax = 0.1;
|
|
||||||
|
|
||||||
struct Entry {
|
struct Entry {
|
||||||
const style::icon *icon;
|
const style::icon *icon;
|
||||||
rpl::producer<QString> title;
|
rpl::producer<QString> title;
|
||||||
|
@ -230,187 +225,6 @@ void SendScreenAccept(not_null<Window::SessionController*> controller) {
|
||||||
MTP_jsonNull());
|
MTP_jsonNull());
|
||||||
}
|
}
|
||||||
|
|
||||||
class MiniStars final {
|
|
||||||
public:
|
|
||||||
MiniStars(Fn<void(const QRect &r)> updateCallback);
|
|
||||||
|
|
||||||
void paint(Painter &p, const QRectF &rect);
|
|
||||||
void setPaused(bool paused);
|
|
||||||
|
|
||||||
private:
|
|
||||||
struct MiniStar {
|
|
||||||
crl::time birthTime = 0;
|
|
||||||
crl::time deathTime = 0;
|
|
||||||
int angle = 0;
|
|
||||||
float64 size = 0.;
|
|
||||||
float64 alpha = 0.;
|
|
||||||
float64 sinFactor = 0.;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Interval {
|
|
||||||
int from = 0;
|
|
||||||
int length = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
void createStar(crl::time now);
|
|
||||||
[[nodiscard]] int angle() const;
|
|
||||||
[[nodiscard]] crl::time timeNow() const;
|
|
||||||
[[nodiscard]] int randomInterval(const Interval &interval) const;
|
|
||||||
|
|
||||||
const std::vector<Interval> _availableAngles;
|
|
||||||
const Interval _lifeLength;
|
|
||||||
const Interval _deathTime;
|
|
||||||
const Interval _size;
|
|
||||||
const Interval _alpha;
|
|
||||||
const Interval _sinFactor;
|
|
||||||
|
|
||||||
const float64 _appearProgressTill;
|
|
||||||
const float64 _disappearProgressAfter;
|
|
||||||
const float64 _distanceProgressStart;
|
|
||||||
|
|
||||||
QSvgRenderer _sprite;
|
|
||||||
|
|
||||||
Ui::Animations::Basic _animation;
|
|
||||||
|
|
||||||
std::vector<MiniStar> _ministars;
|
|
||||||
|
|
||||||
crl::time _nextBirthTime = 0;
|
|
||||||
bool _paused = false;
|
|
||||||
|
|
||||||
QRect _rectToUpdate;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
MiniStars::MiniStars(Fn<void(const QRect &r)> updateCallback)
|
|
||||||
: _availableAngles({
|
|
||||||
Interval{ -10, 40 },
|
|
||||||
Interval{ 180 + 10 - 40, 40 },
|
|
||||||
Interval{ 180 + 15, 50 },
|
|
||||||
Interval{ -15 - 50, 50 },
|
|
||||||
})
|
|
||||||
, _lifeLength({ 150, 200 })
|
|
||||||
, _deathTime({ 1500, 2000 })
|
|
||||||
, _size({ 10, 20 })
|
|
||||||
, _alpha({ 40, 60 })
|
|
||||||
, _sinFactor({ 10, 190 })
|
|
||||||
, _appearProgressTill(0.2)
|
|
||||||
, _disappearProgressAfter(0.8)
|
|
||||||
, _distanceProgressStart(0.5)
|
|
||||||
, _sprite(u":/gui/icons/settings/starmini.svg"_q)
|
|
||||||
, _animation([=](crl::time now) {
|
|
||||||
if (now > _nextBirthTime && !_paused) {
|
|
||||||
createStar(now);
|
|
||||||
_nextBirthTime = now + randomInterval(_lifeLength);
|
|
||||||
}
|
|
||||||
if (_rectToUpdate.isValid()) {
|
|
||||||
updateCallback(base::take(_rectToUpdate));
|
|
||||||
}
|
|
||||||
}) {
|
|
||||||
if (anim::Disabled()) {
|
|
||||||
const auto from = _deathTime.from + _deathTime.length;
|
|
||||||
for (auto i = -from; i < 0; i += randomInterval(_lifeLength)) {
|
|
||||||
createStar(i);
|
|
||||||
}
|
|
||||||
updateCallback(_rectToUpdate);
|
|
||||||
} else {
|
|
||||||
_animation.start();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int MiniStars::randomInterval(const Interval &interval) const {
|
|
||||||
return interval.from + base::RandomIndex(interval.length);
|
|
||||||
}
|
|
||||||
|
|
||||||
crl::time MiniStars::timeNow() const {
|
|
||||||
return anim::Disabled() ? 0 : crl::now();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MiniStars::paint(Painter &p, const QRectF &rect) {
|
|
||||||
const auto center = rect.center();
|
|
||||||
const auto opacity = p.opacity();
|
|
||||||
for (const auto &ministar : _ministars) {
|
|
||||||
const auto progress = (timeNow() - ministar.birthTime)
|
|
||||||
/ float64(ministar.deathTime - ministar.birthTime);
|
|
||||||
if (progress > 1.) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
const auto appearProgress = std::clamp(
|
|
||||||
progress / _appearProgressTill,
|
|
||||||
0.,
|
|
||||||
1.);
|
|
||||||
const auto rsin = float(std::sin(ministar.angle * M_PI / 180.));
|
|
||||||
const auto rcos = float(std::cos(ministar.angle * M_PI / 180.));
|
|
||||||
const auto end = QPointF(
|
|
||||||
rect.width() / 1.5 * rcos,
|
|
||||||
rect.height() / 1.5 * rsin);
|
|
||||||
|
|
||||||
const auto alphaProgress = 1.
|
|
||||||
- (std::clamp(progress - _disappearProgressAfter, 0., 1.)
|
|
||||||
/ (1. - _disappearProgressAfter));
|
|
||||||
p.setOpacity(ministar.alpha
|
|
||||||
* alphaProgress
|
|
||||||
* appearProgress
|
|
||||||
* opacity);
|
|
||||||
|
|
||||||
const auto deformResult = progress * 360;
|
|
||||||
const auto rsinDeform = float(
|
|
||||||
std::sin(ministar.sinFactor * deformResult * M_PI / 180.));
|
|
||||||
const auto deformH = 1. + kDeformationMax * rsinDeform;
|
|
||||||
const auto deformW = 1. / deformH;
|
|
||||||
|
|
||||||
const auto distanceProgress = _distanceProgressStart + progress;
|
|
||||||
const auto starSide = ministar.size * appearProgress;
|
|
||||||
const auto widthFade = (std::abs(rcos) >= std::abs(rsin));
|
|
||||||
const auto starWidth = starSide
|
|
||||||
* (widthFade ? alphaProgress : 1.)
|
|
||||||
* deformW;
|
|
||||||
const auto starHeight = starSide
|
|
||||||
* (!widthFade ? alphaProgress : 1.)
|
|
||||||
* deformH;
|
|
||||||
const auto renderRect = QRectF(
|
|
||||||
center.x()
|
|
||||||
+ anim::interpolateF(0, end.x(), distanceProgress)
|
|
||||||
- starWidth / 2.,
|
|
||||||
center.y()
|
|
||||||
+ anim::interpolateF(0, end.y(), distanceProgress)
|
|
||||||
- starHeight / 2.,
|
|
||||||
starWidth,
|
|
||||||
starHeight);
|
|
||||||
_sprite.render(&p, renderRect);
|
|
||||||
_rectToUpdate |= renderRect.toRect();
|
|
||||||
}
|
|
||||||
p.setOpacity(opacity);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MiniStars::setPaused(bool paused) {
|
|
||||||
_paused = paused;
|
|
||||||
}
|
|
||||||
|
|
||||||
int MiniStars::angle() const {
|
|
||||||
const auto &interval = _availableAngles[
|
|
||||||
base::RandomIndex(_availableAngles.size())];
|
|
||||||
return base::RandomIndex(interval.length) + interval.from;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MiniStars::createStar(crl::time now) {
|
|
||||||
auto ministar = MiniStar{
|
|
||||||
.birthTime = now,
|
|
||||||
.deathTime = now + randomInterval(_deathTime),
|
|
||||||
.angle = angle(),
|
|
||||||
.size = float64(randomInterval(_size)),
|
|
||||||
.alpha = float64(randomInterval(_alpha)) / 100.,
|
|
||||||
.sinFactor = randomInterval(_sinFactor) / 100.
|
|
||||||
* (base::RandomIndex(2) == 1 ? 1. : -1.),
|
|
||||||
};
|
|
||||||
for (auto i = 0; i < _ministars.size(); i++) {
|
|
||||||
if (ministar.birthTime > _ministars[i].deathTime) {
|
|
||||||
_ministars[i] = ministar;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ministars.push_back(ministar);
|
|
||||||
}
|
|
||||||
|
|
||||||
class TopBar final : public Ui::RpWidget {
|
class TopBar final : public Ui::RpWidget {
|
||||||
public:
|
public:
|
||||||
TopBar(
|
TopBar(
|
||||||
|
@ -435,7 +249,7 @@ private:
|
||||||
const style::font &_titleFont;
|
const style::font &_titleFont;
|
||||||
const style::margins &_titlePadding;
|
const style::margins &_titlePadding;
|
||||||
object_ptr<Ui::FlatLabel> _about;
|
object_ptr<Ui::FlatLabel> _about;
|
||||||
MiniStars _ministars;
|
Ui::Premium::MiniStars _ministars;
|
||||||
QSvgRenderer _star;
|
QSvgRenderer _star;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
|
|
150
Telegram/SourceFiles/ui/effects/premium_stars.cpp
Normal file
150
Telegram/SourceFiles/ui/effects/premium_stars.cpp
Normal file
|
@ -0,0 +1,150 @@
|
||||||
|
/*
|
||||||
|
This file is part of Telegram Desktop,
|
||||||
|
the official desktop application for the Telegram messaging service.
|
||||||
|
|
||||||
|
For license and copyright information please follow this link:
|
||||||
|
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
|
*/
|
||||||
|
#include "ui/effects/premium_stars.h"
|
||||||
|
|
||||||
|
#include "base/random.h"
|
||||||
|
#include "ui/effects/animation_value_f.h"
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
namespace Premium {
|
||||||
|
|
||||||
|
constexpr auto kDeformationMax = 0.1;
|
||||||
|
|
||||||
|
MiniStars::MiniStars(Fn<void(const QRect &r)> updateCallback, bool opaque)
|
||||||
|
: _availableAngles({
|
||||||
|
Interval{ -10, 40 },
|
||||||
|
Interval{ 180 + 10 - 40, 40 },
|
||||||
|
Interval{ 180 + 15, 50 },
|
||||||
|
Interval{ -15 - 50, 50 },
|
||||||
|
})
|
||||||
|
, _lifeLength({ 150, 200 })
|
||||||
|
, _deathTime({ 1500, 2000 })
|
||||||
|
, _size({ 10, 20 })
|
||||||
|
, _alpha({ opaque ? 100 : 40, opaque ? 100 : 60 })
|
||||||
|
, _sinFactor({ 10, 190 })
|
||||||
|
, _appearProgressTill(0.2)
|
||||||
|
, _disappearProgressAfter(0.8)
|
||||||
|
, _distanceProgressStart(0.5)
|
||||||
|
, _sprite(u":/gui/icons/settings/starmini.svg"_q)
|
||||||
|
, _animation([=](crl::time now) {
|
||||||
|
if (now > _nextBirthTime && !_paused) {
|
||||||
|
createStar(now);
|
||||||
|
_nextBirthTime = now + randomInterval(_lifeLength);
|
||||||
|
}
|
||||||
|
if (_rectToUpdate.isValid()) {
|
||||||
|
updateCallback(base::take(_rectToUpdate));
|
||||||
|
}
|
||||||
|
}) {
|
||||||
|
if (anim::Disabled()) {
|
||||||
|
const auto from = _deathTime.from + _deathTime.length;
|
||||||
|
for (auto i = -from; i < 0; i += randomInterval(_lifeLength)) {
|
||||||
|
createStar(i);
|
||||||
|
}
|
||||||
|
updateCallback(_rectToUpdate);
|
||||||
|
} else {
|
||||||
|
_animation.start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int MiniStars::randomInterval(const Interval &interval) const {
|
||||||
|
return interval.from + base::RandomIndex(interval.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
crl::time MiniStars::timeNow() const {
|
||||||
|
return anim::Disabled() ? 0 : crl::now();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MiniStars::paint(Painter &p, const QRectF &rect) {
|
||||||
|
const auto center = rect.center();
|
||||||
|
const auto opacity = p.opacity();
|
||||||
|
for (const auto &ministar : _ministars) {
|
||||||
|
const auto progress = (timeNow() - ministar.birthTime)
|
||||||
|
/ float64(ministar.deathTime - ministar.birthTime);
|
||||||
|
if (progress > 1.) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const auto appearProgress = std::clamp(
|
||||||
|
progress / _appearProgressTill,
|
||||||
|
0.,
|
||||||
|
1.);
|
||||||
|
const auto rsin = float(std::sin(ministar.angle * M_PI / 180.));
|
||||||
|
const auto rcos = float(std::cos(ministar.angle * M_PI / 180.));
|
||||||
|
const auto end = QPointF(
|
||||||
|
rect.width() / kSizeFactor * rcos,
|
||||||
|
rect.height() / kSizeFactor * rsin);
|
||||||
|
|
||||||
|
const auto alphaProgress = 1.
|
||||||
|
- (std::clamp(progress - _disappearProgressAfter, 0., 1.)
|
||||||
|
/ (1. - _disappearProgressAfter));
|
||||||
|
p.setOpacity(ministar.alpha
|
||||||
|
* alphaProgress
|
||||||
|
* appearProgress
|
||||||
|
* opacity);
|
||||||
|
|
||||||
|
const auto deformResult = progress * 360;
|
||||||
|
const auto rsinDeform = float(
|
||||||
|
std::sin(ministar.sinFactor * deformResult * M_PI / 180.));
|
||||||
|
const auto deformH = 1. + kDeformationMax * rsinDeform;
|
||||||
|
const auto deformW = 1. / deformH;
|
||||||
|
|
||||||
|
const auto distanceProgress = _distanceProgressStart + progress;
|
||||||
|
const auto starSide = ministar.size * appearProgress;
|
||||||
|
const auto widthFade = (std::abs(rcos) >= std::abs(rsin));
|
||||||
|
const auto starWidth = starSide
|
||||||
|
* (widthFade ? alphaProgress : 1.)
|
||||||
|
* deformW;
|
||||||
|
const auto starHeight = starSide
|
||||||
|
* (!widthFade ? alphaProgress : 1.)
|
||||||
|
* deformH;
|
||||||
|
const auto renderRect = QRectF(
|
||||||
|
center.x()
|
||||||
|
+ anim::interpolateF(0, end.x(), distanceProgress)
|
||||||
|
- starWidth / 2.,
|
||||||
|
center.y()
|
||||||
|
+ anim::interpolateF(0, end.y(), distanceProgress)
|
||||||
|
- starHeight / 2.,
|
||||||
|
starWidth,
|
||||||
|
starHeight);
|
||||||
|
_sprite.render(&p, renderRect);
|
||||||
|
_rectToUpdate |= renderRect.toRect();
|
||||||
|
}
|
||||||
|
p.setOpacity(opacity);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MiniStars::setPaused(bool paused) {
|
||||||
|
_paused = paused;
|
||||||
|
}
|
||||||
|
|
||||||
|
int MiniStars::angle() const {
|
||||||
|
const auto &interval = _availableAngles[
|
||||||
|
base::RandomIndex(_availableAngles.size())];
|
||||||
|
return base::RandomIndex(interval.length) + interval.from;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MiniStars::createStar(crl::time now) {
|
||||||
|
auto ministar = MiniStar{
|
||||||
|
.birthTime = now,
|
||||||
|
.deathTime = now + randomInterval(_deathTime),
|
||||||
|
.angle = angle(),
|
||||||
|
.size = float64(randomInterval(_size)),
|
||||||
|
.alpha = float64(randomInterval(_alpha)) / 100.,
|
||||||
|
.sinFactor = randomInterval(_sinFactor) / 100.
|
||||||
|
* (base::RandomIndex(2) == 1 ? 1. : -1.),
|
||||||
|
};
|
||||||
|
for (auto i = 0; i < _ministars.size(); i++) {
|
||||||
|
if (ministar.birthTime > _ministars[i].deathTime) {
|
||||||
|
_ministars[i] = ministar;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ministars.push_back(ministar);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace Premium
|
||||||
|
} // namespace Ui
|
71
Telegram/SourceFiles/ui/effects/premium_stars.h
Normal file
71
Telegram/SourceFiles/ui/effects/premium_stars.h
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
/*
|
||||||
|
This file is part of Telegram Desktop,
|
||||||
|
the official desktop application for the Telegram messaging service.
|
||||||
|
|
||||||
|
For license and copyright information please follow this link:
|
||||||
|
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "ui/effects/animations.h"
|
||||||
|
|
||||||
|
#include <QSvgRenderer>
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
namespace Premium {
|
||||||
|
|
||||||
|
class MiniStars final {
|
||||||
|
public:
|
||||||
|
MiniStars(Fn<void(const QRect &r)> updateCallback, bool opaque = false);
|
||||||
|
|
||||||
|
void paint(Painter &p, const QRectF &rect);
|
||||||
|
void setPaused(bool paused);
|
||||||
|
|
||||||
|
static constexpr auto kSizeFactor = 1.5;
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct MiniStar {
|
||||||
|
crl::time birthTime = 0;
|
||||||
|
crl::time deathTime = 0;
|
||||||
|
int angle = 0;
|
||||||
|
float64 size = 0.;
|
||||||
|
float64 alpha = 0.;
|
||||||
|
float64 sinFactor = 0.;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Interval {
|
||||||
|
int from = 0;
|
||||||
|
int length = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
void createStar(crl::time now);
|
||||||
|
[[nodiscard]] int angle() const;
|
||||||
|
[[nodiscard]] crl::time timeNow() const;
|
||||||
|
[[nodiscard]] int randomInterval(const Interval &interval) const;
|
||||||
|
|
||||||
|
const std::vector<Interval> _availableAngles;
|
||||||
|
const Interval _lifeLength;
|
||||||
|
const Interval _deathTime;
|
||||||
|
const Interval _size;
|
||||||
|
const Interval _alpha;
|
||||||
|
const Interval _sinFactor;
|
||||||
|
|
||||||
|
const float64 _appearProgressTill;
|
||||||
|
const float64 _disappearProgressAfter;
|
||||||
|
const float64 _distanceProgressStart;
|
||||||
|
|
||||||
|
QSvgRenderer _sprite;
|
||||||
|
|
||||||
|
Ui::Animations::Basic _animation;
|
||||||
|
|
||||||
|
std::vector<MiniStar> _ministars;
|
||||||
|
|
||||||
|
crl::time _nextBirthTime = 0;
|
||||||
|
bool _paused = false;
|
||||||
|
|
||||||
|
QRect _rectToUpdate;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Premium
|
||||||
|
} // namespace Ui
|
|
@ -229,6 +229,8 @@ PRIVATE
|
||||||
ui/effects/fireworks_animation.h
|
ui/effects/fireworks_animation.h
|
||||||
ui/effects/premium_graphics.cpp
|
ui/effects/premium_graphics.cpp
|
||||||
ui/effects/premium_graphics.h
|
ui/effects/premium_graphics.h
|
||||||
|
ui/effects/premium_stars.cpp
|
||||||
|
ui/effects/premium_stars.h
|
||||||
ui/effects/round_checkbox.cpp
|
ui/effects/round_checkbox.cpp
|
||||||
ui/effects/round_checkbox.h
|
ui/effects/round_checkbox.h
|
||||||
ui/effects/scroll_content_shadow.cpp
|
ui/effects/scroll_content_shadow.cpp
|
||||||
|
|
Loading…
Add table
Reference in a new issue