Skip to content

Commit 59d351d

Browse files
committed
Better spoiler animation
1 parent 3f7b92a commit 59d351d

File tree

2 files changed

+106
-18
lines changed

2 files changed

+106
-18
lines changed

Telegram.Native/ParticlesAnimation.cpp

Lines changed: 79 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -992,6 +992,9 @@ namespace winrt::Telegram::Native::implementation
992992

993993
void ParticlesAnimation::RenderSync(IBuffer bitmap)
994994
{
995+
const float fps = 30;
996+
const float lsec = 1.2f;
997+
995998
auto add = 0.04;
996999
auto pixels = (int32_t*)bitmap.data();
9971000

@@ -1000,12 +1003,6 @@ namespace winrt::Telegram::Native::implementation
10001003
for (int i = 0, length = m_particles.size(); i < length; ++i)
10011004
{
10021005
auto dot = &m_particles[i];
1003-
auto addOpacity = dot->Adding ? add : -add;
1004-
1005-
dot->Opacity += addOpacity;
1006-
// if(dot.mOpacity <= 0) dot.mOpacity = dot.opacity;
1007-
1008-
// const easedOpacity = easing(dot.mOpacity);
10091006
auto easedOpacity = (byte)(std::clamp(dot->Opacity, 0., 1.) * m_foreground.A);
10101007
auto color = premultiply_color(m_foreground.R, m_foreground.G, m_foreground.B, easedOpacity);
10111008

@@ -1018,15 +1015,12 @@ namespace winrt::Telegram::Native::implementation
10181015
draw_circle_scaled(pixels, m_width, m_height, dot, color, m_scalePercent, m_rasterizationScale);
10191016
}
10201017

1021-
if (dot->Opacity <= 0)
1018+
if (++dot->t >= fps * lsec)
10221019
{
1023-
dot->Adding = true;
1024-
m_particles[i] = GenerateParticle(dot->Adding, NextPoint(m_width, m_height));
1025-
}
1026-
else if (dot->Opacity >= 1)
1027-
{
1028-
dot->Adding = false;
1020+
dot->t = 0;
1021+
ResetPoint(*dot);
10291022
}
1023+
UpdatePoint(*dot);
10301024
}
10311025
}
10321026

@@ -1166,12 +1160,33 @@ namespace winrt::Telegram::Native::implementation
11661160
count *= m_type == ParticlesType::Text ? 4 : m_type == ParticlesType::Premium ? 0.5 : 1;
11671161
count = min(/*!liteMode.isAvailable('chat_spoilers') ? 400 :*/ IS_MOBILE ? 1000 : 2200, count);
11681162

1169-
auto particles = NextPoints(count, m_width, m_height);
11701163
m_particles.reserve(count);
11711164

1172-
for (const auto& particle : particles)
1165+
auto el_w = m_width;
1166+
auto el_h = m_height;
1167+
const float max_d = 5;
1168+
const float fps = 30;
1169+
const float lsec = 1.2f;
1170+
1171+
const auto threshold = m_type == ParticlesType::Status || m_type == ParticlesType::Premium ? .2f : .8f;
1172+
const auto small = m_type == ParticlesType::Premium ? 2 : 0.5f;
1173+
const auto large = m_type == ParticlesType::Premium ? 3 : 1.0f;
1174+
1175+
for (int i = 0; i < count; i++)
11731176
{
1174-
m_particles.emplace_back(GenerateParticle(-1, particle));
1177+
Particle point;
1178+
point.mx = el_w;
1179+
point.my = el_h;
1180+
point.md = max_d;
1181+
point.cnt = count;
1182+
point.fps = fps;
1183+
point.lsec = lsec;
1184+
point.t = random(0, fps * lsec);
1185+
point.Radius = (NextDouble() >= threshold ? large : small);
1186+
ResetPoint(point);
1187+
UpdatePoint(point);
1188+
1189+
m_particles.emplace_back(point);
11751190
}
11761191
}
11771192

@@ -1196,4 +1211,52 @@ namespace winrt::Telegram::Native::implementation
11961211
opacity,
11971212
adding);
11981213
}
1214+
1215+
void ParticlesAnimation::ResetPoint(Particle& particle)
1216+
{
1217+
auto v = GenerateVector(particle.cnt);
1218+
particle.x = random(particle.md, particle.mx - particle.md);
1219+
particle.y = random(particle.md, particle.my - particle.md);
1220+
particle.dx = v.X;
1221+
particle.dy = v.Y;
1222+
particle.s = random(60, 80) * particle.my / 3600;
1223+
}
1224+
1225+
void ParticlesAnimation::UpdatePoint(Particle& particle)
1226+
{
1227+
float t = particle.t;
1228+
float d = particle.fps * particle.lsec / 3;
1229+
float k = 360 / particle.lsec / particle.fps;
1230+
particle.X = particle.x + k * t * particle.dx;
1231+
particle.Y = particle.y + k * t * particle.dy;
1232+
particle.Opacity = (t < d ? (t / d) : (t < d * 2 ? 1 : (d * 3 - t) / d)) * 0.95;
1233+
}
1234+
1235+
Point ParticlesAnimation::GenerateVector(int count)
1236+
{
1237+
float speedMax = 8;
1238+
float speedMin = 4;
1239+
float lifetime = 600;
1240+
float value = random(0, 2 * count + 2);
1241+
float negative = (value < count + 1);
1242+
float mod = (negative ? value : (value - count - 1));
1243+
float speed = speedMin + (((speedMax - speedMin) * mod) / count);
1244+
float max = std::ceilf(speedMax * lifetime);
1245+
float k = speed / lifetime;
1246+
float x = (random(0, 2 * max + 1) - max) / max;
1247+
float y = std::sqrtf(1 - x * x) * (negative ? -1 : 1);
1248+
return {
1249+
k * x,
1250+
k * y,
1251+
};
1252+
}
1253+
1254+
float ParticlesAnimation::random(float x, float y)
1255+
{
1256+
static std::random_device rd; // Will be used to obtain a seed for the random number engine
1257+
static std::mt19937 gen(rd()); // Standard mersenne_twister_engine seeded with rd()
1258+
static std::uniform_real_distribution<> dis(0.0f, 1.0f);
1259+
1260+
return x + std::floorf(dis(gen) * (y + 1 - x));
1261+
}
11991262
}

Telegram.Native/ParticlesAnimation.h

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@ using namespace winrt::Windows::UI::Xaml::Media::Imaging;
88

99
namespace winrt::Telegram::Native::implementation
1010
{
11-
struct Particle
11+
struct Particle2
1212
{
13-
Particle(float x, float y, float radius, double opacity, bool adding)
13+
Particle2(float x, float y, float radius, double opacity, bool adding)
1414
: X(x)
1515
, Y(y)
1616
, Radius(radius)
@@ -25,6 +25,26 @@ namespace winrt::Telegram::Native::implementation
2525
bool Adding;
2626
};
2727

28+
struct Particle
29+
{
30+
float mx,
31+
my,
32+
md,
33+
cnt,
34+
fps,
35+
lsec,
36+
t,
37+
x,
38+
y,
39+
dx,
40+
dy,
41+
s;
42+
43+
float X, Y;
44+
float Radius;
45+
double Opacity;
46+
};
47+
2848
struct Point
2949
{
3050
float X, Y;
@@ -93,6 +113,11 @@ namespace winrt::Telegram::Native::implementation
93113
std::vector<Point> NextPoints(int count, float width, float height, float noiseFactor = 0.1f);
94114
Point NextPoint(float width, float height, float noiseFactor = 0.1f);
95115

116+
void ResetPoint(Particle& particle);
117+
void UpdatePoint(Particle& particle);
118+
Point GenerateVector(int count);
119+
float random(float x, float y);
120+
96121
int32_t m_width;
97122
int32_t m_height;
98123
int32_t m_scalePercent;

0 commit comments

Comments
 (0)