Files
z-bar-qt/Plugins/ZShell/Blobs/blobgroup.cpp
zach c5608dc9b9
C++ / fmt (pull_request) Failing after 5s
C++ / build (pull_request) Failing after 10s
C++ / clang-tidy (pull_request) Failing after 10s
JS/TS / fmt (pull_request) Successful in 9s
JS/TS / lint (pull_request) Successful in 25s
Python / static (pull_request) Successful in 34s
Rust / build (pull_request) Successful in 51s
Python / verify (pull_request) Failing after 1m25s
Rust / fmt (pull_request) Successful in 39s
Rust / clippy (pull_request) Successful in 59s
fix: blobs now allow to be drawn in device pixels to stay sharp
2026-10-30 01:52:33 +01:00

146 lines
3.4 KiB
C++

#include "blobgroup.hpp"
#include "blobinvertedrect.hpp"
#include "blobshape.hpp"
#include <algorithm>
namespace {
constexpr int k_pumpMs = 16;
} // namespace
BlobGroup::BlobGroup(QObject* parent) : QObject(parent) {
m_physicsPump.setInterval(k_pumpMs);
m_physicsPump.setTimerType(Qt::CoarseTimer);
connect(&m_physicsPump, &QTimer::timeout, this, &BlobGroup::pumpPhysics);
}
BlobGroup::~BlobGroup() {
for (auto* shape : std::as_const(m_shapes))
shape->m_group = nullptr;
if (m_invertedRect)
static_cast<BlobShape*>(m_invertedRect)->m_group = nullptr;
}
void BlobGroup::setSmoothing(qreal s) {
if (s < 0.5) s = 0.5;
if (qFuzzyCompare(m_smoothing, s)) return;
m_smoothing = s;
emit smoothingChanged();
markDirty();
}
void BlobGroup::setColor(const QColor& c) {
if (m_color == c) return;
m_color = c;
emit colorChanged();
markDirty();
}
void BlobGroup::setCornerFill(bool e) {
if (m_cornerFill == e) return;
m_cornerFill = e;
emit cornerFillChanged();
markDirty();
}
void BlobGroup::addShape(BlobShape* shape) {
if (!shape || m_shapes.contains(shape)) return;
m_shapes.append(shape);
markDirty();
}
void BlobGroup::removeShape(BlobShape* shape) {
m_shapes.removeOne(shape);
markDirty();
}
void BlobGroup::setInvertedRect(BlobInvertedRect* rect) {
if (m_invertedRect == rect) return;
m_invertedRect = rect;
markDirty();
}
void BlobGroup::clearInvertedRect(BlobInvertedRect* rect) {
if (m_invertedRect != rect) return;
m_invertedRect = nullptr;
markDirty();
}
void BlobGroup::markDirty() {
m_physicsUpdated = false;
for (auto* shape : std::as_const(m_shapes)) {
shape->polish();
shape->update();
}
if (m_invertedRect) {
static_cast<BlobShape*>(m_invertedRect)->polish();
static_cast<BlobShape*>(m_invertedRect)->update();
}
}
void BlobGroup::markShapeDirty(BlobShape* source) {
m_physicsUpdated = false;
source->polish();
source->update();
const float pad = static_cast<float>(m_smoothing) * 2.0f;
const QRectF srcRect(
static_cast<double>(source->m_cachedPaddedX - pad),
static_cast<double>(source->m_cachedPaddedY - pad),
static_cast<double>(source->m_cachedPaddedW + pad * 2.0f),
static_cast<double>(source->m_cachedPaddedH + pad * 2.0f));
for (auto* shape : std::as_const(m_shapes)) {
if (shape == source) continue;
const QRectF otherRect(
static_cast<double>(shape->m_cachedPaddedX),
static_cast<double>(shape->m_cachedPaddedY),
static_cast<double>(shape->m_cachedPaddedW),
static_cast<double>(shape->m_cachedPaddedH));
if (srcRect.intersects(otherRect)) {
shape->polish();
shape->update();
}
}
if (m_invertedRect && static_cast<BlobShape*>(m_invertedRect) != source) {
static_cast<BlobShape*>(m_invertedRect)->polish();
static_cast<BlobShape*>(m_invertedRect)->update();
}
}
void BlobGroup::ensurePhysicsUpdated() {
if (m_physicsUpdated) return;
m_physicsUpdated = true;
for (auto* shape : std::as_const(m_shapes)) {
shape->updatePhysics();
if (shape->needsFrame()) {
shape->polish();
shape->update();
}
}
}
void BlobGroup::requestPhysics() {
if (!m_physicsPump.isActive()) m_physicsPump.start();
}
void BlobGroup::pumpPhysics() {
for (auto* shape : std::as_const(m_shapes))
shape->updatePhysics();
const bool anyMoving = std::any_of(
m_shapes.cbegin(), m_shapes.cend(), [](const BlobShape* shape) {
return shape->needsFrame();
});
if (!anyMoving) {
m_physicsPump.stop();
return;
}
markDirty();
m_physicsUpdated = true;
}