init
Some checks failed
Docker. / Ubuntu (push) Has been cancelled
User-agent updater. / User-agent (push) Failing after 15s
Lock Threads / lock (push) Failing after 10s
Waiting for answer. / waiting-for-answer (push) Failing after 22s
Needs user action. / needs-user-action (push) Failing after 8s
Can't reproduce. / cant-reproduce (push) Failing after 8s
Close stale issues and PRs / stale (push) Has been cancelled
Some checks failed
Docker. / Ubuntu (push) Has been cancelled
User-agent updater. / User-agent (push) Failing after 15s
Lock Threads / lock (push) Failing after 10s
Waiting for answer. / waiting-for-answer (push) Failing after 22s
Needs user action. / needs-user-action (push) Failing after 8s
Can't reproduce. / cant-reproduce (push) Failing after 8s
Close stale issues and PRs / stale (push) Has been cancelled
This commit is contained in:
244
Telegram/lib_ui/ui/paint/blob.cpp
Normal file
244
Telegram/lib_ui/ui/paint/blob.cpp
Normal file
@@ -0,0 +1,244 @@
|
||||
// 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/blob.h"
|
||||
|
||||
#include "base/random.h"
|
||||
#include "ui/painter.h"
|
||||
|
||||
#include <QtGui/QPainterPath>
|
||||
#include <QtCore/QtMath>
|
||||
|
||||
namespace Ui::Paint {
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr auto kMaxSpeed = 8.2;
|
||||
constexpr auto kMinSpeed = 0.8;
|
||||
|
||||
constexpr auto kMinSegmentSpeed = 0.017;
|
||||
constexpr auto kSegmentSpeedDiff = 0.003;
|
||||
|
||||
[[nodiscard]] float64 RandomAdditional() {
|
||||
return (base::RandomValue<int>() % 100 / 100.);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
Blob::Blob(int n, float minSpeed, float maxSpeed)
|
||||
: _segmentsCount(n)
|
||||
, _minSpeed(minSpeed ? minSpeed : kMinSpeed)
|
||||
, _maxSpeed(maxSpeed ? maxSpeed : kMaxSpeed)
|
||||
, _pen(Qt::NoBrush, 0, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin) {
|
||||
}
|
||||
|
||||
void Blob::generateBlob() {
|
||||
for (auto i = 0; i < _segmentsCount; i++) {
|
||||
generateSingleValues(i);
|
||||
// Fill nexts.
|
||||
generateTwoValues(i);
|
||||
// Fill currents.
|
||||
generateTwoValues(i);
|
||||
}
|
||||
}
|
||||
|
||||
void Blob::generateSingleValues(int i) {
|
||||
auto &segment = segmentAt(i);
|
||||
segment.progress = 0.;
|
||||
segment.speed = kMinSegmentSpeed
|
||||
+ kSegmentSpeedDiff * std::abs(RandomAdditional());
|
||||
}
|
||||
|
||||
void Blob::update(float level, float speedScale, float64 rate) {
|
||||
for (auto i = 0; i < _segmentsCount; i++) {
|
||||
auto &segment = segmentAt(i);
|
||||
segment.progress += (_minSpeed + level * _maxSpeed * speedScale)
|
||||
* segment.speed
|
||||
* rate;
|
||||
if (segment.progress >= 1) {
|
||||
generateSingleValues(i);
|
||||
generateTwoValues(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Blob::setRadiuses(Radiuses values) {
|
||||
_radiuses = values;
|
||||
}
|
||||
|
||||
Blob::Radiuses Blob::radiuses() const {
|
||||
return _radiuses;
|
||||
}
|
||||
|
||||
RadialBlob::RadialBlob(int n, float minScale, float minSpeed, float maxSpeed)
|
||||
: Blob(n, minSpeed, maxSpeed)
|
||||
, _segmentLength((4.0 / 3.0) * std::tan(M_PI / (2 * n)))
|
||||
, _minScale(minScale)
|
||||
, _segmentAngle(360. / n)
|
||||
, _angleDiff(_segmentAngle * 0.05)
|
||||
, _segments(n) {
|
||||
}
|
||||
|
||||
void RadialBlob::paint(QPainter &p, const QBrush &brush, float outerScale) {
|
||||
auto path = QPainterPath();
|
||||
auto m = QTransform();
|
||||
|
||||
const auto scale = (_minScale + (1. - _minScale) * _scale) * outerScale;
|
||||
if (scale == 0.) {
|
||||
return;
|
||||
}
|
||||
p.save();
|
||||
if (scale != 1.) {
|
||||
p.scale(scale, scale);
|
||||
}
|
||||
|
||||
for (auto i = 0; i < _segmentsCount; i++) {
|
||||
const auto &segment = _segments[i];
|
||||
|
||||
const auto nextIndex = i + 1 < _segmentsCount ? (i + 1) : 0;
|
||||
const auto nextSegment = _segments[nextIndex];
|
||||
|
||||
const auto progress = segment.progress;
|
||||
const auto progressNext = nextSegment.progress;
|
||||
|
||||
const auto r1 = segment.radius.current * (1. - progress)
|
||||
+ segment.radius.next * progress;
|
||||
const auto r2 = nextSegment.radius.current * (1. - progressNext)
|
||||
+ nextSegment.radius.next * progressNext;
|
||||
const auto angle1 = segment.angle.current * (1. - progress)
|
||||
+ segment.angle.next * progress;
|
||||
const auto angle2 = nextSegment.angle.current * (1. - progressNext)
|
||||
+ nextSegment.angle.next * progressNext;
|
||||
|
||||
const auto l = _segmentLength * (std::min(r1, r2)
|
||||
+ (std::max(r1, r2) - std::min(r1, r2)) / 2.);
|
||||
|
||||
m.reset();
|
||||
m.rotate(angle1);
|
||||
|
||||
const auto pointStart1 = m.map(QPointF(0, -r1));
|
||||
const auto pointStart2 = m.map(QPointF(l, -r1));
|
||||
|
||||
m.reset();
|
||||
m.rotate(angle2);
|
||||
const auto pointEnd1 = m.map(QPointF(0, -r2));
|
||||
const auto pointEnd2 = m.map(QPointF(-l, -r2));
|
||||
|
||||
if (i == 0) {
|
||||
path.moveTo(pointStart1);
|
||||
}
|
||||
|
||||
path.cubicTo(pointStart2, pointEnd2, pointEnd1);
|
||||
}
|
||||
|
||||
p.setBrush(Qt::NoBrush);
|
||||
|
||||
p.setPen(_pen);
|
||||
p.fillPath(path, brush);
|
||||
p.drawPath(path);
|
||||
|
||||
p.restore();
|
||||
}
|
||||
|
||||
void RadialBlob::generateTwoValues(int i) {
|
||||
auto &radius = _segments[i].radius;
|
||||
auto &angle = _segments[i].angle;
|
||||
|
||||
const auto radDiff = _radiuses.max - _radiuses.min;
|
||||
|
||||
angle.setNext(_segmentAngle * i + RandomAdditional() * _angleDiff);
|
||||
radius.setNext(_radiuses.min + std::abs(RandomAdditional()) * radDiff);
|
||||
}
|
||||
|
||||
void RadialBlob::update(float level, float speedScale, float64 rate) {
|
||||
_scale = level;
|
||||
Blob::update(level, speedScale, rate);
|
||||
}
|
||||
|
||||
Blob::Segment &RadialBlob::segmentAt(int i) {
|
||||
return _segments[i];
|
||||
};
|
||||
|
||||
LinearBlob::LinearBlob(
|
||||
int n,
|
||||
Direction direction,
|
||||
float minSpeed,
|
||||
float maxSpeed)
|
||||
: Blob(n + 1)
|
||||
, _topDown(direction == Direction::TopDown ? 1 : -1)
|
||||
, _segments(_segmentsCount) {
|
||||
}
|
||||
|
||||
void LinearBlob::paint(QPainter &p, const QBrush &brush, int width) {
|
||||
if (!width) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto path = QPainterPath();
|
||||
|
||||
const auto left = 0;
|
||||
const auto right = width;
|
||||
|
||||
path.moveTo(right, 0);
|
||||
path.lineTo(left, 0);
|
||||
|
||||
const auto n = float(_segmentsCount - 1);
|
||||
|
||||
p.save();
|
||||
|
||||
for (auto i = 0; i < _segmentsCount; i++) {
|
||||
const auto &segment = _segments[i];
|
||||
|
||||
if (!i) {
|
||||
const auto &progress = segment.progress;
|
||||
const auto r1 = segment.radius.current * (1. - progress)
|
||||
+ segment.radius.next * progress;
|
||||
const auto y = r1 * _topDown;
|
||||
path.lineTo(left, y);
|
||||
} else {
|
||||
const auto &prevSegment = _segments[i - 1];
|
||||
const auto &progress = prevSegment.progress;
|
||||
const auto r1 = prevSegment.radius.current * (1. - progress)
|
||||
+ prevSegment.radius.next * progress;
|
||||
|
||||
const auto &progressNext = segment.progress;
|
||||
const auto r2 = segment.radius.current * (1. - progressNext)
|
||||
+ segment.radius.next * progressNext;
|
||||
|
||||
const auto x1 = (right - left) / n * (i - 1);
|
||||
const auto x2 = (right - left) / n * i;
|
||||
const auto cx = x1 + (x2 - x1) / 2;
|
||||
|
||||
const auto y1 = r1 * _topDown;
|
||||
const auto y2 = r2 * _topDown;
|
||||
path.cubicTo(
|
||||
QPointF(cx, y1),
|
||||
QPointF(cx, y2),
|
||||
QPointF(x2, y2)
|
||||
);
|
||||
}
|
||||
}
|
||||
path.lineTo(right, 0);
|
||||
|
||||
p.setBrush(Qt::NoBrush);
|
||||
p.setPen(_pen);
|
||||
p.fillPath(path, brush);
|
||||
p.drawPath(path);
|
||||
|
||||
p.restore();
|
||||
}
|
||||
|
||||
void LinearBlob::generateTwoValues(int i) {
|
||||
auto &radius = _segments[i].radius;
|
||||
const auto radDiff = _radiuses.max - _radiuses.min;
|
||||
radius.setNext(_radiuses.min + std::abs(RandomAdditional()) * radDiff);
|
||||
}
|
||||
|
||||
Blob::Segment &LinearBlob::segmentAt(int i) {
|
||||
return _segments[i];
|
||||
};
|
||||
|
||||
} // namespace Ui::Paint
|
||||
Reference in New Issue
Block a user