blobs.cpp 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. // This file is part of Desktop App Toolkit,
  2. // a set of libraries for developing nice desktop applications.
  3. //
  4. // For license and copyright information please follow this link:
  5. // https://github.com/desktop-app/legal/blob/master/LEGAL
  6. //
  7. #include "ui/paint/blobs.h"
  8. #include "ui/painter.h"
  9. namespace Ui::Paint {
  10. namespace {
  11. constexpr auto kRateLimitF = 1000. / 60.;
  12. constexpr auto kRateLimit = int(kRateLimitF + 0.5); // Round.
  13. } // namespace
  14. Blobs::Blobs(
  15. std::vector<BlobData> blobDatas,
  16. float levelDuration,
  17. float maxLevel)
  18. : _maxLevel(maxLevel)
  19. , _blobDatas(std::move(blobDatas))
  20. , _levelValue(levelDuration) {
  21. init();
  22. }
  23. void Blobs::init() {
  24. for (const auto &data : _blobDatas) {
  25. auto blob = Paint::RadialBlob(
  26. data.segmentsCount,
  27. data.minScale,
  28. data.minSpeed,
  29. data.maxSpeed);
  30. blob.setRadiuses({ data.minRadius, data.maxRadius });
  31. blob.generateBlob();
  32. _blobs.push_back(std::move(blob));
  33. }
  34. }
  35. float Blobs::maxRadius() const {
  36. const auto maxOfRadiuses = [](const BlobData data) {
  37. return std::max(data.maxRadius, data.minRadius);
  38. };
  39. const auto max = *ranges::max_element(
  40. _blobDatas,
  41. std::less<>(),
  42. maxOfRadiuses);
  43. return maxOfRadiuses(max);
  44. }
  45. int Blobs::size() const {
  46. return _blobs.size();
  47. }
  48. void Blobs::setRadiusesAt(
  49. rpl::producer<Blob::Radiuses> &&radiuses,
  50. int index) {
  51. Expects(index >= 0 && index < size());
  52. std::move(
  53. radiuses
  54. ) | rpl::start_with_next([=](Blob::Radiuses r) {
  55. _blobs[index].setRadiuses(std::move(r));
  56. }, _lifetime);
  57. }
  58. Blob::Radiuses Blobs::radiusesAt(int index) {
  59. Expects(index >= 0 && index < size());
  60. return _blobs[index].radiuses();
  61. }
  62. void Blobs::setLevel(float value) {
  63. const auto to = std::min(_maxLevel, value) / _maxLevel;
  64. _levelValue.start(to);
  65. }
  66. void Blobs::resetLevel() {
  67. _levelValue.reset();
  68. }
  69. void Blobs::paint(QPainter &p, const QBrush &brush, float outerScale) {
  70. const auto opacity = p.opacity();
  71. for (auto i = 0; i < _blobs.size(); i++) {
  72. const auto alpha = _blobDatas[i].alpha;
  73. if (alpha != 1.) {
  74. p.setOpacity(opacity * alpha);
  75. }
  76. _blobs[i].paint(p, brush, outerScale);
  77. if (alpha != 1.) {
  78. p.setOpacity(opacity);
  79. }
  80. }
  81. }
  82. void Blobs::updateLevel(crl::time dt) {
  83. const auto limitedDt = (dt > 20) ? kRateLimit : dt;
  84. _levelValue.update(limitedDt);
  85. for (auto i = 0; i < _blobs.size(); i++) {
  86. _blobs[i].update(
  87. _levelValue.current(),
  88. _blobDatas[i].speedScale,
  89. limitedDt / kRateLimitF);
  90. }
  91. }
  92. float64 Blobs::currentLevel() const {
  93. return _levelValue.current();
  94. }
  95. } // namespace Ui::Paint