@@ -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}
0 commit comments