#include "blobgroup.hpp" #include "blobinvertedrect.hpp" #include "blobshape.hpp" BlobGroup::BlobGroup(QObject* parent) : QObject(parent) { } BlobGroup::~BlobGroup() { for (auto* shape : std::as_const(m_shapes)) shape->m_group = nullptr; if (m_invertedRect) static_cast(m_invertedRect)->m_group = nullptr; } void BlobGroup::setSmoothing(qreal s) { 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::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(m_invertedRect)->polish(); static_cast(m_invertedRect)->update(); } } void BlobGroup::markShapeDirty(BlobShape* source) { m_physicsUpdated = false; source->polish(); source->update(); // Use cached padded rects to find spatial neighbors const float pad = static_cast(m_smoothing) * 2.0f; const QRectF srcRect(static_cast(source->m_cachedPaddedX - pad), static_cast(source->m_cachedPaddedY - pad), static_cast(source->m_cachedPaddedW + pad * 2.0f), static_cast(source->m_cachedPaddedH + pad * 2.0f)); for (auto* shape : std::as_const(m_shapes)) { if (shape == source) continue; const QRectF otherRect(static_cast(shape->m_cachedPaddedX), static_cast(shape->m_cachedPaddedY), static_cast(shape->m_cachedPaddedW), static_cast(shape->m_cachedPaddedH)); if (srcRect.intersects(otherRect)) { shape->polish(); shape->update(); } } if (m_invertedRect && static_cast(m_invertedRect) != source) { static_cast(m_invertedRect)->polish(); static_cast(m_invertedRect)->update(); } } void BlobGroup::ensurePhysicsUpdated() { if (m_physicsUpdated) return; m_physicsUpdated = true; for (auto* shape : std::as_const(m_shapes)) shape->updatePhysics(); }