#pragma once #include "blobmaterial.hpp" #include #include #include #include #include #include #include #include #include class BlobShape2; class BlobInvertedRect2; struct BlobGroupData { static constexpr int kMaxRects = 16; QVector rects; bool hasInverted = false; float invertedRadius = 0; float invertedOuter[4] = {}; float invertedInner[4] = {}; float invertedOuterRadii[4] = {}; }; class BlobGroup2 : public QQuickItem { Q_OBJECT QML_ELEMENT Q_PROPERTY( qreal smoothing READ smoothing WRITE setSmoothing NOTIFY smoothingChanged) Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged) Q_PROPERTY( bool cornerFill READ cornerFill WRITE setCornerFill NOTIFY cornerFillChanged) Q_PROPERTY( QColor shadowColor READ shadowColor WRITE setShadowColor NOTIFY shadowColorChanged) Q_PROPERTY( qreal shadowRadius READ shadowRadius WRITE setShadowRadius NOTIFY shadowRadiusChanged) friend class BlobShape2; public: explicit BlobGroup2(QQuickItem* parent = nullptr); ~BlobGroup2() override; [[nodiscard]] qreal smoothing() const { return m_smoothing; } void setSmoothing(qreal s); [[nodiscard]] QColor color() const { return m_color; } void setColor(const QColor& c); [[nodiscard]] bool cornerFill() const { return m_cornerFill; } void setCornerFill(bool e); [[nodiscard]] QColor shadowColor() const { return m_shadowColor; } void setShadowColor(const QColor& c); [[nodiscard]] qreal shadowRadius() const { return m_shadowRadius; } void setShadowRadius(qreal r); void addShape(BlobShape2* shape); void removeShape(BlobShape2* shape); void setInvertedRect(BlobInvertedRect2* rect); void clearInvertedRect(BlobInvertedRect2* rect); [[nodiscard]] const QList& shapes() const { return m_shapes; } [[nodiscard]] BlobInvertedRect2* invertedRect() const { return m_invertedRect; } [[nodiscard]] const BlobGroupData& data() const { return m_data; } void markDirty(); void requestPhysics(); signals: void smoothingChanged(); void colorChanged(); void cornerFillChanged(); void shadowColorChanged(); void shadowRadiusChanged(); protected: void updatePolish() override; QSGNode* updatePaintNode(QSGNode* oldNode, UpdatePaintNodeData*) override; private: void ensurePhysicsUpdated(); void ensureDataBuilt(); void fillMaterial(BlobMaterial* material); void pumpPhysics(); qreal m_smoothing = 32.0; QColor m_color{0x44, 0x88, 0xff}; bool m_cornerFill = true; QColor m_shadowColor{0, 0, 0, 128}; qreal m_shadowRadius = 0.0; QList m_shapes; BlobInvertedRect2* m_invertedRect = nullptr; bool m_physicsUpdated = false; bool m_dataBuilt = false; QTimer m_physicsPump; BlobGroupData m_data; QRectF m_bounds; };