From 0df5775e3e1162a659eb26fea8563e8afc44290c Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Mon, 18 Dec 2023 09:02:45 +0100 Subject: [PATCH] Overlay supports the box model now --- playground/parrots/BlurringNode.cpp | 5 -- playground/parrots/BlurringNode.h | 2 +- playground/parrots/Overlay.cpp | 83 +++++++++++++++++--- playground/parrots/Overlay.h | 4 + playground/parrots/main.cpp | 39 +-------- playground/parrots/shaders/blur.frag.qsb | Bin 1697 -> 1696 bytes playground/parrots/shaders/blur.vert.qsb | Bin 1382 -> 1378 bytes playground/parrots/shaders/rgbswap.frag.qsb | Bin 1208 -> 1206 bytes src/nodes/QskBoxNode.cpp | 8 +- 9 files changed, 86 insertions(+), 55 deletions(-) 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 140daf7c1f31f77e50278daa126a1bc5e309b771..40d031bc0d94bffb458704834af81c09be3d8c19 100644 GIT binary patch literal 1696 zcmV;R24DFA02$VJob6dla~nkv9?Nz_ln|4IyaNmF0Lp#9 zv6v0CN^Vc>q&Vp~K;JEyHJwN&(S8czzeU`m5Hlhkf_419d8d9S8-%T_QP4zy(?gHv zSdxc@vu8T4SZC}c!yTFC{3P0dC*;3N7)T$7@AEPG9N9(sq$Ga}=xg*m%jwx6ogT`J zcu6KsB;rkx+%mU4&3OsJS&8|vLVn;l4pIqDPxGh~Jho}RnF`EPAfKeoO>o`}&*CJ_ zOF-jV3g_?Xr3LUO$wUUFXrhh7WMhVGybj-phx`iBM~D~MoWsLh|Ezk39ptedU|TaK zqR)cnQQ8xBjbcFjW!lecgpc$J@lF8!A?<(U57Mhdqy8GnqP-&Q zd4i3~5BKmd;LMV3JgFTEc&yY+sP@=ZTMJ`8DxA zAiw4%pE5C@E|O1??MozcQL?>2d{wf2nd~n}wzDzYS7PyMv3PUDJ4berr;}bz@+nWY zb;&1#_;S1j^2?BXD#m;&#e6Eqd|D*lY00Onq_-&fR3Y0}C7+gvKPUNACBJZO1$da> z*O{n^Rq_LK{RZ(PTQ^A;`Iy^Bi1#;CN?CM=8S2|ewAip^B>qf4vi-pETqUPzsZHOu z98NuSIuAFMcGok*$`-cc0y7nae%}g}jea}zB&ERUnW2FnzB8zB23J?SP1AD1$CcDm zQ0lu*+w*&ezP_deUf;KD5O`$zj~%z8JhClau{_UjA=7hO3I?TS z2%ayu>~3f(RZgf{R?`;6D3yvvSud1zZBf_DgLY#ziHc&6RU#T+fvj%O$O-6^vrJRLEpt5wHvSvIZkpGBl$A zfF;Ao85#mBmy}5Wa@l+_j{rrztQAXIu2|HB=K>)Qq441JypcBy2++`T!h!7pgsN_U zEf~61&;X)T*7On>*+mzZ_SHEV;Munq1u(g?qtr{KVnr}u!;$!PR0O*A;uHH-O210! zmyyyxj8Eyp%SmakA7Y9cN*gk7)$4kGCFQvLmEl8>SaR=kYVUJmKYLp5b5j2wDV?BO z9F3XZED&znKF`Oiif?zEAhdmTLyMBh_r7fQ%+Dbycs3gYg99{0o`Vhmec`p+fgP%r zmXQ;m%aJ27K_er|;eJ%#OTv1Ma$oi(M5}dC9QDu)ZKWxMnp82eaDc*4nr7%&<<#D# zp4yp-@pdWvJy@Ek5xhXpC+Q56oJ`aknsRU0nzrIyvZWRjD4mYobnrP!P~l!xUdmEU zMR`aWEf{0KgsR60AtZCMawsvI?Afk_DW25G68z!`n$ZcauVd1=K)O7>d7d#K zAYK#Pp#>$nm9<3I9yaYpBYL$7xu`#jlo;)L$HqixWBDW{I4?U;bW8t3TP_|x> qq+a5Q7J@xwmS-g0m}0jk@jn$DWB$t!YdSm1GNR);eEbVPS!)2bY)*#& literal 1697 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 kBj#eVMj%?mf0|oP-UPRsq$>_C4>rd1&py# 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 WY{CB&xo&%{Eh9OPQP)4UaqvhBx?K?f 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 ) )