diff --git a/playground/parrots/BlurringNode.cpp b/playground/parrots/BlurringNode.cpp index e2083875..63030672 100644 --- a/playground/parrots/BlurringNode.cpp +++ b/playground/parrots/BlurringNode.cpp @@ -174,8 +174,3 @@ void BlurringNode::setRect( const QRectF& rect ) markDirty( QSGNode::DirtyGeometry ); } } - -QRectF BlurringNode::rect() const -{ - return d_func()->rect; -} diff --git a/playground/parrots/BlurringNode.h b/playground/parrots/BlurringNode.h index 4ba89267..918373ab 100644 --- a/playground/parrots/BlurringNode.h +++ b/playground/parrots/BlurringNode.h @@ -9,6 +9,7 @@ class QRect; class QSGTexture; + class BlurringNodePrivate; class BlurringNode : public QSGGeometryNode @@ -23,7 +24,6 @@ class BlurringNode : public QSGGeometryNode QSGTexture* texture(); void setRect( const QRectF& ); - QRectF rect() const; private: Q_DECLARE_PRIVATE( BlurringNode ) diff --git a/playground/parrots/Overlay.cpp b/playground/parrots/Overlay.cpp index 080feca0..00f3bfa1 100644 --- a/playground/parrots/Overlay.cpp +++ b/playground/parrots/Overlay.cpp @@ -13,6 +13,8 @@ #include #include #include +#include +#include namespace { @@ -28,6 +30,12 @@ namespace setNodeRoles( { EffectRole, BorderRole } ); } + QRectF subControlRect( const QskSkinnable*, + const QRectF& contentsRect, QskAspect::Subcontrol ) const override + { + return contentsRect; + } + QSGNode* updateSubNode( const QskSkinnable* skinnable, quint8 nodeRole, QSGNode* node ) const { @@ -36,11 +44,10 @@ namespace switch ( nodeRole ) { case EffectRole: - return updateEffectNode( overlay, node ); + return updateClippedEffectNode( overlay, node ); case BorderRole: - return updateBoxNode( overlay, node, overlay->contentsRect(), - QskBoxShapeMetrics(), 1, Qt::darkGray, QskGradient() ); + return updateBoxNode( skinnable, node, Overlay::Panel ); break; }; @@ -48,6 +55,47 @@ namespace } private: + QSGNode* updateClippedEffectNode( const Overlay* overlay, QSGNode* node ) const + { + /* + There should be a way to avoid the clip node by passing the + vertex list directly to the effect node. TODO ... + */ + using Q = Overlay; + + QSGNode* clipNode = nullptr; + QSGNode* effectNode = nullptr; + + if ( node ) + { + if ( node->firstChild() ) + { + clipNode = node; + effectNode = node->firstChild(); + } + else + { + effectNode = node; + } + } + + effectNode = updateEffectNode( overlay, effectNode ); + + if ( overlay->boxShapeHint( Q::Panel ).isRectangle() ) + { + delete clipNode; + clipNode = nullptr; + } + else + { + clipNode = updateBoxClipNode( overlay, clipNode, Q::Panel ); + } + + QskSGNode::setParentNode( effectNode, clipNode ); + + return clipNode ? clipNode : effectNode; + } + QSGNode* updateEffectNode( const Overlay* overlay, QSGNode* node ) const { const auto window = overlay->window(); @@ -71,31 +119,48 @@ namespace effectNode->setTexture( texture ); } - auto texture = qobject_cast< QskSceneTexture* >( effectNode->texture() ); - Q_ASSERT( texture ); + { + auto texture = qobject_cast< QskSceneTexture* >( effectNode->texture() ); + Q_ASSERT( texture ); - texture->setFiltering( overlay->smooth() ? QSGTexture::Linear : QSGTexture::Nearest ); + texture->setFiltering( + overlay->smooth() ? QSGTexture::Linear : QSGTexture::Nearest ); - auto finalNode = const_cast< QSGTransformNode* >( qskItemNode( overlay ) ); - texture->render( rootNode, finalNode, overlay->geometry() ); + auto finalNode = const_cast< QSGTransformNode* >( qskItemNode( overlay ) ); + texture->render( rootNode, finalNode, overlay->geometry() ); + } - effectNode->setRect( overlay->rect() ); + { + const auto rect = overlay->subControlRect( Overlay::Panel ); + effectNode->setRect( rect ); + } return effectNode; } }; } +QSK_SUBCONTROL( Overlay, Panel ) + Overlay::Overlay( QQuickItem* parent ) : Inherited( parent ) { setSkinlet( new Skinlet() ); + + setBoxBorderMetricsHint( Panel, 1 ); + setBoxBorderColorsHint( Panel, QskRgb::toTransparent( QskRgb::DarkGrey, 100 ) ); + setBoxShapeHint( Panel, QskBoxShapeMetrics( 25, Qt::RelativeSize ) ); } Overlay::~Overlay() { } +QRectF Overlay::layoutRectForSize( const QSizeF& size ) const +{ + return subControlContentsRect( size, Panel ); +} + void Overlay::geometryChange( const QRectF& newGeometry, const QRectF& oldGeometry ) { diff --git a/playground/parrots/Overlay.h b/playground/parrots/Overlay.h index 1536def2..f3fb4667 100644 --- a/playground/parrots/Overlay.h +++ b/playground/parrots/Overlay.h @@ -14,9 +14,13 @@ class Overlay : public QskControl using Inherited = QskControl; public: + QSK_SUBCONTROLS( Panel ) + Overlay( QQuickItem* = nullptr ); ~Overlay() override; + QRectF layoutRectForSize( const QSizeF& ) const override; + protected: void geometryChange( const QRectF&, const QRectF& ) override; }; diff --git a/playground/parrots/main.cpp b/playground/parrots/main.cpp index 6b79869e..713f9c42 100644 --- a/playground/parrots/main.cpp +++ b/playground/parrots/main.cpp @@ -57,36 +57,6 @@ class ForegroundItem : public QskLinearBox } }; -class OverlayBox : public Overlay -{ - using Inherited = Overlay; - - public: - OverlayBox( QQuickItem* parent = nullptr ) - : Inherited( parent ) - { - setObjectName( "overlay" ); - } - - protected: - void geometryChange( const QRectF& newRect, const QRectF& oldRect ) override - { - Inherited::geometryChange( newRect, oldRect ); - - const auto rect = qskItemRect( this ); - - const auto children = childItems(); - for ( auto child : children ) - { - if ( qskIsAdjustableByLayout( child ) ) - { - const auto r = qskConstrainedItemRect( child, rect ); - qskSetItemGeometry( child, r ); - } - } - } -}; - class BackgroundItem : public QskControl { using Inherited = QskControl; @@ -97,15 +67,11 @@ class BackgroundItem : public QskControl { setObjectName( "background" ); -#if 1 m_label = new Image( this ); m_label->setFillMode( QskGraphicLabel::Stretch ); m_label->setObjectName( "parrots" ); -#endif -#if 1 startTimer( 20 ); -#endif } protected: @@ -162,7 +128,10 @@ class MainView : public QskControl box->setObjectName( "redBox" ); } #endif - m_overlay = new OverlayBox( m_background ); + m_overlay = new Overlay( m_background ); + m_overlay->setAutoLayoutChildren( true ); + m_overlay->setObjectName( "overlay" ); + (void )new ForegroundItem( m_overlay ); #if 0 diff --git a/playground/parrots/shaders/blur.frag.qsb b/playground/parrots/shaders/blur.frag.qsb index 140daf7c..40d031bc 100644 Binary files a/playground/parrots/shaders/blur.frag.qsb and b/playground/parrots/shaders/blur.frag.qsb differ diff --git a/playground/parrots/shaders/blur.vert.qsb b/playground/parrots/shaders/blur.vert.qsb index bcc17615..f530ee4d 100644 Binary files a/playground/parrots/shaders/blur.vert.qsb and b/playground/parrots/shaders/blur.vert.qsb differ diff --git a/playground/parrots/shaders/rgbswap.frag.qsb b/playground/parrots/shaders/rgbswap.frag.qsb index 85e03f20..7ce873e7 100644 Binary files a/playground/parrots/shaders/rgbswap.frag.qsb and b/playground/parrots/shaders/rgbswap.frag.qsb differ diff --git a/src/nodes/QskBoxNode.cpp b/src/nodes/QskBoxNode.cpp index 58329d1b..4de2242c 100644 --- a/src/nodes/QskBoxNode.cpp +++ b/src/nodes/QskBoxNode.cpp @@ -78,11 +78,9 @@ void QskBoxNode::updateNode( const QRectF& rect, } /* - QskBoxRectangleNode supports vertical/horizontal and many tilted - linear gradients. If our gradient doesn't fall into this category - we use a QskBoxFillNode. - - However the border is always done with a QskBoxRectangleNode + QskBoxRectangleNode is more efficient and creates batchable geometries. + So we prefer using it where possible. + Note, that the border is always done with a QskBoxRectangleNode */ if ( QskBoxRenderer::isGradientSupported( shape, gradient ) )