Added ability to set direction of Linear Blobs.
This commit is contained in:
parent
a02c8923dc
commit
9735510195
4 changed files with 39 additions and 74 deletions
|
|
@ -10,7 +10,6 @@
|
|||
#include "ui/painter.h"
|
||||
|
||||
#include <QtGui/QPainterPath>
|
||||
#include <QtCore/QtMath>
|
||||
|
||||
namespace Ui::Paint {
|
||||
|
||||
|
|
@ -27,34 +26,25 @@ float64 RandomAdditional() {
|
|||
|
||||
LinearBlobBezier::LinearBlobBezier(
|
||||
int n,
|
||||
float minScale,
|
||||
Direction direction,
|
||||
float minSpeed,
|
||||
float maxSpeed)
|
||||
: _segmentsCount(n)
|
||||
, _minSpeed(minSpeed ? minSpeed : kMinSpeed)
|
||||
, _maxSpeed(maxSpeed ? maxSpeed : kMaxSpeed)
|
||||
, _pen(Qt::NoBrush, 0, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin)
|
||||
, _topDown(direction == Direction::TopDown ? 1 : -1)
|
||||
, _segments(n + 1) {
|
||||
}
|
||||
|
||||
void LinearBlobBezier::paint(
|
||||
Painter &p,
|
||||
const QBrush &brush,
|
||||
const QRect &rect,
|
||||
float pinnedTop,
|
||||
float progressToPinned) {
|
||||
void LinearBlobBezier::paint(Painter &p, const QBrush &brush, int width) {
|
||||
auto path = QPainterPath();
|
||||
auto m = QMatrix();
|
||||
|
||||
const auto left = rect.x();
|
||||
const auto top = rect.y();
|
||||
const auto right = rect.x() + rect.width();
|
||||
const auto bottom = rect.y() + rect.height();
|
||||
const auto left = 0;
|
||||
const auto right = width;
|
||||
|
||||
// path.moveTo(right, bottom);
|
||||
// path.lineTo(left, bottom);
|
||||
path.moveTo(right, top);
|
||||
path.lineTo(left, top);
|
||||
path.moveTo(right, 0);
|
||||
path.lineTo(left, 0);
|
||||
|
||||
const auto &n = _segmentsCount;
|
||||
|
||||
|
|
@ -67,17 +57,15 @@ void LinearBlobBezier::paint(
|
|||
const auto progress = segment.progress;
|
||||
const auto r1 = segment.radius * (1. - progress)
|
||||
+ segment.radiusNext * progress;
|
||||
const auto y = (bottom + r1);// * progressToPinned
|
||||
// const auto y = (top - r1) * progressToPinned
|
||||
// + pinnedTop * (1. - progressToPinned);
|
||||
const auto y = r1 * _topDown;
|
||||
path.lineTo(left, y);
|
||||
} else {
|
||||
const auto &prevSegment = _segments[i - 1];
|
||||
const auto progress = prevSegment.progress;
|
||||
const auto &progress = prevSegment.progress;
|
||||
const auto r1 = prevSegment.radius * (1. - progress)
|
||||
+ prevSegment.radiusNext * progress;
|
||||
|
||||
const auto progressNext = segment.progress;
|
||||
const auto &progressNext = segment.progress;
|
||||
const auto r2 = segment.radius * (1. - progressNext)
|
||||
+ segment.radiusNext * progressNext;
|
||||
|
||||
|
|
@ -85,26 +73,18 @@ void LinearBlobBezier::paint(
|
|||
const auto x2 = (right - left) / n * i;
|
||||
const auto cx = x1 + (x2 - x1) / 2;
|
||||
|
||||
const auto y1 = (bottom + r1);// * progressToPinned
|
||||
// const auto y1 = (top - r1) * progressToPinned
|
||||
// + pinnedTop * (1. - progressToPinned);
|
||||
const auto y2 = (bottom + r2);// * progressToPinned
|
||||
// const auto y2 = (top - r2) * progressToPinned
|
||||
// + pinnedTop * (1. - progressToPinned);
|
||||
const auto y1 = r1 * _topDown;
|
||||
const auto y2 = r2 * _topDown;
|
||||
path.cubicTo(
|
||||
QPointF(cx, y1),
|
||||
QPointF(cx, y2),
|
||||
QPointF(x2, y2)
|
||||
);
|
||||
if (i == n) {
|
||||
path.lineTo(right, top);
|
||||
// path.lineTo(right, bottom);
|
||||
}
|
||||
}
|
||||
}
|
||||
path.lineTo(right, 0);
|
||||
|
||||
p.setBrush(Qt::NoBrush);
|
||||
|
||||
p.setPen(_pen);
|
||||
p.fillPath(path, brush);
|
||||
p.drawPath(path);
|
||||
|
|
@ -129,7 +109,6 @@ void LinearBlobBezier::generateBlob(float &radius, int i) {
|
|||
}
|
||||
|
||||
void LinearBlobBezier::update(float level, float speedScale) {
|
||||
_scale = level;
|
||||
for (auto i = 0; i < _segmentsCount; i++) {
|
||||
auto &segment = _segments[i];
|
||||
segment.progress += (segment.speed * _minSpeed)
|
||||
|
|
|
|||
|
|
@ -12,6 +12,11 @@ namespace Ui::Paint {
|
|||
|
||||
class LinearBlobBezier final {
|
||||
public:
|
||||
enum class Direction {
|
||||
TopDown,
|
||||
BottomUp,
|
||||
};
|
||||
|
||||
struct Radiuses {
|
||||
float min = 0.;
|
||||
float max = 0.;
|
||||
|
|
@ -26,16 +31,11 @@ public:
|
|||
|
||||
LinearBlobBezier(
|
||||
int n,
|
||||
float minScale,
|
||||
Direction direction = Direction::TopDown,
|
||||
float minSpeed = 0,
|
||||
float maxSpeed = 0);
|
||||
|
||||
void paint(
|
||||
Painter &p,
|
||||
const QBrush &brush,
|
||||
const QRect &rect,
|
||||
float pinnedTop,
|
||||
float progressToPinned);
|
||||
void paint(Painter &p, const QBrush &brush, int width);
|
||||
void update(float level, float speedScale);
|
||||
void generateBlob();
|
||||
|
||||
|
|
@ -56,10 +56,10 @@ private:
|
|||
const float _minSpeed;
|
||||
const float _maxSpeed;
|
||||
const QPen _pen;
|
||||
const int _topDown;
|
||||
|
||||
std::vector<Segment> _segments;
|
||||
|
||||
float64 _scale = 0;
|
||||
Radiuses _radiuses;
|
||||
|
||||
};
|
||||
|
|
|
|||
|
|
@ -13,12 +13,12 @@ namespace Ui::Paint {
|
|||
LinearBlobs::LinearBlobs(
|
||||
std::vector<BlobData> blobDatas,
|
||||
float levelDuration,
|
||||
float levelDuration2,
|
||||
float maxLevel)
|
||||
float maxLevel,
|
||||
LinearBlobBezier::Direction direction)
|
||||
: _maxLevel(maxLevel)
|
||||
, _direction(direction)
|
||||
, _blobDatas(std::move(blobDatas))
|
||||
, _levelValue(levelDuration)
|
||||
, _levelValue2(levelDuration2) {
|
||||
, _levelValue(levelDuration) {
|
||||
init();
|
||||
}
|
||||
|
||||
|
|
@ -26,16 +26,16 @@ void LinearBlobs::init() {
|
|||
for (const auto &data : _blobDatas) {
|
||||
auto blob = Paint::LinearBlobBezier(
|
||||
data.segmentsCount,
|
||||
data.minScale);
|
||||
blob.setRadiuses({ 0, data.minRadius });
|
||||
_direction);
|
||||
blob.setRadiuses({ data.minRadius, data.idleRadius });
|
||||
blob.generateBlob();
|
||||
_blobs.push_back(std::move(blob));
|
||||
}
|
||||
}
|
||||
|
||||
float LinearBlobs::maxRadius() const {
|
||||
const auto maxOfRadiuses = [](const BlobData data) {
|
||||
return std::max(data.maxRadius, data.minRadius);
|
||||
const auto maxOfRadiuses = [](const BlobData &d) {
|
||||
return std::max(d.idleRadius, std::max(d.maxRadius, d.minRadius));
|
||||
};
|
||||
const auto max = *ranges::max_element(
|
||||
_blobDatas,
|
||||
|
|
@ -67,27 +67,18 @@ LinearBlobBezier::Radiuses LinearBlobs::radiusesAt(int index) {
|
|||
void LinearBlobs::setLevel(float value) {
|
||||
const auto to = std::min(_maxLevel, value) / _maxLevel;
|
||||
_levelValue.start(to);
|
||||
_levelValue2.start(to);
|
||||
}
|
||||
|
||||
void LinearBlobs::paint(
|
||||
Painter &p,
|
||||
const QBrush &brush,
|
||||
const QRect &rect,
|
||||
float pinnedTop,
|
||||
float progressToPinned) {
|
||||
void LinearBlobs::paint(Painter &p, const QBrush &brush, int width) {
|
||||
PainterHighQualityEnabler hq(p);
|
||||
const auto opacity = p.opacity();
|
||||
for (auto i = 0; i < _blobs.size(); i++) {
|
||||
auto r = rect;
|
||||
r.setTop(r.top() - _blobDatas[i].topOffset * _levelValue2.current());
|
||||
|
||||
_blobs[i].update(_levelValue.current(), _blobDatas[i].speedScale);
|
||||
const auto alpha = _blobDatas[i].alpha;
|
||||
if (alpha != 1.) {
|
||||
p.setOpacity(opacity * alpha);
|
||||
}
|
||||
_blobs[i].paint(p, brush, r, pinnedTop, progressToPinned);
|
||||
_blobs[i].paint(p, brush, width);
|
||||
if (alpha != 1.) {
|
||||
p.setOpacity(opacity);
|
||||
}
|
||||
|
|
@ -97,13 +88,13 @@ void LinearBlobs::paint(
|
|||
void LinearBlobs::updateLevel(crl::time dt) {
|
||||
const auto d = (dt > 20) ? 17 : dt;
|
||||
_levelValue.update(d);
|
||||
_levelValue2.update(d);
|
||||
|
||||
const auto level = (float)currentLevel();
|
||||
for (auto i = 0; i < _blobs.size(); i++) {
|
||||
const auto &data = _blobDatas[i];
|
||||
_blobs[i].setRadiuses({
|
||||
0,
|
||||
data.minRadius + data.maxRadius * (float)currentLevel() });
|
||||
data.minRadius,
|
||||
data.idleRadius + (data.maxRadius - data.idleRadius) * level });
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -17,9 +17,9 @@ class LinearBlobs final {
|
|||
public:
|
||||
struct BlobData {
|
||||
int segmentsCount = 0;
|
||||
float minScale = 0;
|
||||
float minRadius = 0;
|
||||
float maxRadius = 0;
|
||||
float idleRadius = 0;
|
||||
float speedScale = 0;
|
||||
float alpha = 0;
|
||||
int topOffset = 0;
|
||||
|
|
@ -28,8 +28,8 @@ public:
|
|||
LinearBlobs(
|
||||
std::vector<BlobData> blobDatas,
|
||||
float levelDuration,
|
||||
float levelDuration2,
|
||||
float maxLevel);
|
||||
float maxLevel,
|
||||
LinearBlobBezier::Direction direction);
|
||||
|
||||
void setRadiusesAt(
|
||||
rpl::producer<LinearBlobBezier::Radiuses> &&radiuses,
|
||||
|
|
@ -37,12 +37,7 @@ public:
|
|||
LinearBlobBezier::Radiuses radiusesAt(int index);
|
||||
|
||||
void setLevel(float value);
|
||||
void paint(
|
||||
Painter &p,
|
||||
const QBrush &brush,
|
||||
const QRect &rect,
|
||||
float pinnedTop,
|
||||
float progressToPinned);
|
||||
void paint(Painter &p, const QBrush &brush, int width);
|
||||
void updateLevel(crl::time dt);
|
||||
|
||||
[[nodiscard]] float maxRadius() const;
|
||||
|
|
@ -55,12 +50,12 @@ private:
|
|||
void init();
|
||||
|
||||
const float _maxLevel;
|
||||
const LinearBlobBezier::Direction _direction;
|
||||
|
||||
std::vector<BlobData> _blobDatas;
|
||||
std::vector<LinearBlobBezier> _blobs;
|
||||
|
||||
anim::continuous_value _levelValue;
|
||||
anim::continuous_value _levelValue2;
|
||||
|
||||
rpl::lifetime _lifetime;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue