117 lines
2.8 KiB
C++
117 lines
2.8 KiB
C++
// This file is part of Desktop App Toolkit,
|
|
// a set of libraries for developing nice desktop applications.
|
|
//
|
|
// For license and copyright information please follow this link:
|
|
// https://github.com/desktop-app/legal/blob/master/LEGAL
|
|
//
|
|
#include "ui/paint/blobs_linear.h"
|
|
|
|
#include "ui/painter.h"
|
|
|
|
namespace Ui::Paint {
|
|
|
|
namespace {
|
|
|
|
constexpr auto kRateLimitF = 1000. / 60.;
|
|
constexpr auto kRateLimit = int(kRateLimitF + 0.5); // Round.
|
|
|
|
} // namespace
|
|
|
|
LinearBlobs::LinearBlobs(
|
|
std::vector<BlobData> blobDatas,
|
|
float levelDuration,
|
|
float maxLevel,
|
|
LinearBlob::Direction direction)
|
|
: _maxLevel(maxLevel)
|
|
, _direction(direction)
|
|
, _blobDatas(std::move(blobDatas))
|
|
, _levelValue(levelDuration) {
|
|
init();
|
|
}
|
|
|
|
void LinearBlobs::init() {
|
|
for (const auto &data : _blobDatas) {
|
|
auto blob = Paint::LinearBlob(
|
|
data.segmentsCount,
|
|
_direction,
|
|
data.minSpeed,
|
|
data.maxSpeed);
|
|
blob.setRadiuses({ data.minRadius, data.idleRadius });
|
|
blob.generateBlob();
|
|
_blobs.push_back(std::move(blob));
|
|
}
|
|
}
|
|
|
|
float LinearBlobs::maxRadius() const {
|
|
const auto maxOfRadiuses = [](const BlobData &d) {
|
|
return std::max(d.idleRadius, std::max(d.maxRadius, d.minRadius));
|
|
};
|
|
const auto max = *ranges::max_element(
|
|
_blobDatas,
|
|
std::less<>(),
|
|
maxOfRadiuses);
|
|
return maxOfRadiuses(max);
|
|
}
|
|
|
|
int LinearBlobs::size() const {
|
|
return _blobs.size();
|
|
}
|
|
|
|
void LinearBlobs::setRadiusesAt(
|
|
rpl::producer<Blob::Radiuses> &&radiuses,
|
|
int index) {
|
|
Expects(index >= 0 && index < size());
|
|
std::move(
|
|
radiuses
|
|
) | rpl::start_with_next([=](Blob::Radiuses r) {
|
|
_blobs[index].setRadiuses(std::move(r));
|
|
}, _lifetime);
|
|
}
|
|
|
|
Blob::Radiuses LinearBlobs::radiusesAt(int index) {
|
|
Expects(index >= 0 && index < size());
|
|
return _blobs[index].radiuses();
|
|
}
|
|
|
|
void LinearBlobs::setLevel(float value) {
|
|
const auto to = std::min(_maxLevel, value) / _maxLevel;
|
|
_levelValue.start(to);
|
|
}
|
|
|
|
void LinearBlobs::paint(QPainter &p, const QBrush &brush, int width) {
|
|
PainterHighQualityEnabler hq(p);
|
|
const auto opacity = p.opacity();
|
|
for (auto i = 0; i < _blobs.size(); i++) {
|
|
const auto alpha = _blobDatas[i].alpha;
|
|
if (alpha != 1.) {
|
|
p.setOpacity(opacity * alpha);
|
|
}
|
|
_blobs[i].paint(p, brush, width);
|
|
if (alpha != 1.) {
|
|
p.setOpacity(opacity);
|
|
}
|
|
}
|
|
}
|
|
|
|
void LinearBlobs::updateLevel(crl::time dt) {
|
|
const auto limitedDt = (dt > 20) ? kRateLimit : dt;
|
|
_levelValue.update(limitedDt);
|
|
|
|
const auto level = (float)currentLevel();
|
|
for (auto i = 0; i < _blobs.size(); i++) {
|
|
const auto &data = _blobDatas[i];
|
|
_blobs[i].setRadiuses({
|
|
data.minRadius,
|
|
data.idleRadius + (data.maxRadius - data.idleRadius) * level });
|
|
_blobs[i].update(
|
|
_levelValue.current(),
|
|
data.speedScale,
|
|
limitedDt / kRateLimitF);
|
|
}
|
|
}
|
|
|
|
float64 LinearBlobs::currentLevel() const {
|
|
return _levelValue.current();
|
|
}
|
|
|
|
} // namespace Ui::Paint
|