blobs_linear.cpp 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  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_linear.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. LinearBlobs::LinearBlobs(
  15. std::vector<BlobData> blobDatas,
  16. float levelDuration,
  17. float maxLevel,
  18. LinearBlob::Direction direction)
  19. : _maxLevel(maxLevel)
  20. , _direction(direction)
  21. , _blobDatas(std::move(blobDatas))
  22. , _levelValue(levelDuration) {
  23. init();
  24. }
  25. void LinearBlobs::init() {
  26. for (const auto &data : _blobDatas) {
  27. auto blob = Paint::LinearBlob(
  28. data.segmentsCount,
  29. _direction,
  30. data.minSpeed,
  31. data.maxSpeed);
  32. blob.setRadiuses({ data.minRadius, data.idleRadius });
  33. blob.generateBlob();
  34. _blobs.push_back(std::move(blob));
  35. }
  36. }
  37. float LinearBlobs::maxRadius() const {
  38. const auto maxOfRadiuses = [](const BlobData &d) {
  39. return std::max(d.idleRadius, std::max(d.maxRadius, d.minRadius));
  40. };
  41. const auto max = *ranges::max_element(
  42. _blobDatas,
  43. std::less<>(),
  44. maxOfRadiuses);
  45. return maxOfRadiuses(max);
  46. }
  47. int LinearBlobs::size() const {
  48. return _blobs.size();
  49. }
  50. void LinearBlobs::setRadiusesAt(
  51. rpl::producer<Blob::Radiuses> &&radiuses,
  52. int index) {
  53. Expects(index >= 0 && index < size());
  54. std::move(
  55. radiuses
  56. ) | rpl::start_with_next([=](Blob::Radiuses r) {
  57. _blobs[index].setRadiuses(std::move(r));
  58. }, _lifetime);
  59. }
  60. Blob::Radiuses LinearBlobs::radiusesAt(int index) {
  61. Expects(index >= 0 && index < size());
  62. return _blobs[index].radiuses();
  63. }
  64. void LinearBlobs::setLevel(float value) {
  65. const auto to = std::min(_maxLevel, value) / _maxLevel;
  66. _levelValue.start(to);
  67. }
  68. void LinearBlobs::paint(QPainter &p, const QBrush &brush, int width) {
  69. PainterHighQualityEnabler hq(p);
  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, width);
  77. if (alpha != 1.) {
  78. p.setOpacity(opacity);
  79. }
  80. }
  81. }
  82. void LinearBlobs::updateLevel(crl::time dt) {
  83. const auto limitedDt = (dt > 20) ? kRateLimit : dt;
  84. _levelValue.update(limitedDt);
  85. const auto level = (float)currentLevel();
  86. for (auto i = 0; i < _blobs.size(); i++) {
  87. const auto &data = _blobDatas[i];
  88. _blobs[i].setRadiuses({
  89. data.minRadius,
  90. data.idleRadius + (data.maxRadius - data.idleRadius) * level });
  91. _blobs[i].update(
  92. _levelValue.current(),
  93. data.speedScale,
  94. limitedDt / kRateLimitF);
  95. }
  96. }
  97. float64 LinearBlobs::currentLevel() const {
  98. return _levelValue.current();
  99. }
  100. } // namespace Ui::Paint