qskinny/playground/parrots/Overlay.cpp

172 lines
4.7 KiB
C++
Raw Normal View History

2023-12-07 10:24:47 +00:00
/******************************************************************************
* QSkinny - Copyright (C) 2016 Uwe Rathmann
* SPDX-License-Identifier: BSD-3-Clause
*****************************************************************************/
2023-12-08 14:47:32 +00:00
#include "Overlay.h"
2023-12-18 08:39:17 +00:00
#include "TextureFilterNode.h"
2023-12-07 10:24:47 +00:00
2023-12-17 11:33:23 +00:00
#include <QskSkinlet.h>
2023-12-16 11:27:09 +00:00
#include <QskSceneTexture.h>
2023-12-17 11:33:23 +00:00
#include <QskQuick.h>
#include <QskBoxShapeMetrics.h>
#include <QskBoxBorderMetrics.h>
#include <QskBoxBorderColors.h>
#include <QskGradient.h>
2023-12-18 08:02:45 +00:00
#include <QskSGNode.h>
#include <QskRgbValue.h>
2023-12-17 11:33:23 +00:00
namespace
2023-12-07 10:24:47 +00:00
{
2023-12-17 11:33:23 +00:00
class Skinlet : public QskSkinlet
2023-12-07 10:24:47 +00:00
{
2023-12-17 11:33:23 +00:00
using Inherited = QskSkinlet;
2023-12-07 10:24:47 +00:00
2023-12-17 11:33:23 +00:00
public:
2023-12-18 08:39:17 +00:00
enum NodeRole { FillRole, BorderRole };
2023-12-17 11:33:23 +00:00
Skinlet()
2023-12-07 10:24:47 +00:00
{
2023-12-18 08:39:17 +00:00
setNodeRoles( { FillRole, BorderRole } );
2023-12-17 11:33:23 +00:00
}
2023-12-07 10:24:47 +00:00
2023-12-18 08:02:45 +00:00
QRectF subControlRect( const QskSkinnable*,
const QRectF& contentsRect, QskAspect::Subcontrol ) const override
{
return contentsRect;
}
2023-12-17 11:33:23 +00:00
QSGNode* updateSubNode(
const QskSkinnable* skinnable, quint8 nodeRole, QSGNode* node ) const
{
const auto overlay = static_cast< const Overlay* >( skinnable );
switch ( nodeRole )
2023-12-07 10:24:47 +00:00
{
2023-12-18 08:39:17 +00:00
case FillRole:
return updateFillNode( overlay, node );
2023-12-07 10:24:47 +00:00
2023-12-17 11:33:23 +00:00
case BorderRole:
2023-12-18 08:02:45 +00:00
return updateBoxNode( skinnable, node, Overlay::Panel );
2023-12-17 11:33:23 +00:00
break;
};
2023-12-07 10:24:47 +00:00
2023-12-17 11:33:23 +00:00
return nullptr;
2023-12-12 09:55:30 +00:00
}
2023-12-17 11:33:23 +00:00
private:
2023-12-18 08:39:17 +00:00
QSGNode* updateFillNode( const Overlay* overlay, QSGNode* node ) const
2023-12-18 08:02:45 +00:00
{
/*
There should be a way to avoid the clip node by passing the
2023-12-18 08:39:17 +00:00
vertex list directly to the texture node. TODO ...
2023-12-18 08:02:45 +00:00
*/
using Q = Overlay;
QSGNode* clipNode = nullptr;
2023-12-18 08:39:17 +00:00
QSGNode* textureNode = nullptr;
2023-12-18 08:02:45 +00:00
if ( node )
{
if ( node->firstChild() )
{
clipNode = node;
2023-12-18 08:39:17 +00:00
textureNode = node->firstChild();
2023-12-18 08:02:45 +00:00
}
else
{
2023-12-18 08:39:17 +00:00
textureNode = node;
2023-12-18 08:02:45 +00:00
}
}
2023-12-18 08:39:17 +00:00
textureNode = updateTextureNode( overlay, textureNode );
2023-12-18 08:02:45 +00:00
if ( overlay->boxShapeHint( Q::Panel ).isRectangle() )
{
delete clipNode;
clipNode = nullptr;
}
else
{
clipNode = updateBoxClipNode( overlay, clipNode, Q::Panel );
}
2023-12-18 08:39:17 +00:00
QskSGNode::setParentNode( textureNode, clipNode );
2023-12-18 08:02:45 +00:00
2023-12-18 08:39:17 +00:00
return clipNode ? clipNode : textureNode;
2023-12-18 08:02:45 +00:00
}
2023-12-18 08:39:17 +00:00
QSGNode* updateTextureNode( const Overlay* overlay, QSGNode* node ) const
2023-12-17 11:33:23 +00:00
{
const auto window = overlay->window();
2023-12-07 10:24:47 +00:00
2023-12-17 11:33:23 +00:00
if ( overlay->size().isEmpty() )
return nullptr;
2023-12-17 11:33:23 +00:00
auto rootNode = qskScenegraphAnchorNode( window );
if ( rootNode == nullptr )
return nullptr;
2023-12-07 10:24:47 +00:00
2023-12-18 08:39:17 +00:00
auto textureNode = static_cast< TextureFilterNode* >( node );
2023-12-07 10:24:47 +00:00
2023-12-18 08:39:17 +00:00
if ( textureNode == nullptr )
2023-12-17 11:33:23 +00:00
{
auto texture = new QskSceneTexture( window );
QObject::connect( texture, &QskSceneTexture::updateRequested,
overlay, &QQuickItem::update );
2023-12-07 10:24:47 +00:00
2023-12-18 08:39:17 +00:00
textureNode = new TextureFilterNode();
textureNode->setTexture( texture );
2023-12-17 11:33:23 +00:00
}
2023-12-18 08:02:45 +00:00
{
2023-12-18 08:39:17 +00:00
auto texture = qobject_cast< QskSceneTexture* >( textureNode->texture() );
2023-12-18 08:02:45 +00:00
Q_ASSERT( texture );
2023-12-17 11:33:23 +00:00
2023-12-18 08:02:45 +00:00
texture->setFiltering(
overlay->smooth() ? QSGTexture::Linear : QSGTexture::Nearest );
2023-12-17 11:33:23 +00:00
2023-12-18 08:02:45 +00:00
auto finalNode = const_cast< QSGTransformNode* >( qskItemNode( overlay ) );
texture->render( rootNode, finalNode, overlay->geometry() );
}
2023-12-17 11:33:23 +00:00
2023-12-18 08:02:45 +00:00
{
const auto rect = overlay->subControlRect( Overlay::Panel );
2023-12-18 08:39:17 +00:00
textureNode->setRect( rect );
2023-12-18 08:02:45 +00:00
}
2023-12-17 11:33:23 +00:00
2023-12-18 08:39:17 +00:00
return textureNode;
2023-12-17 11:33:23 +00:00
}
};
2023-12-07 10:24:47 +00:00
}
2023-12-18 08:02:45 +00:00
QSK_SUBCONTROL( Overlay, Panel )
2023-12-17 11:33:23 +00:00
Overlay::Overlay( QQuickItem* parent )
: Inherited( parent )
2023-12-07 10:24:47 +00:00
{
2023-12-17 11:33:23 +00:00
setSkinlet( new Skinlet() );
2023-12-18 08:02:45 +00:00
setBoxBorderMetricsHint( Panel, 1 );
setBoxBorderColorsHint( Panel, QskRgb::toTransparent( QskRgb::DarkGrey, 100 ) );
setBoxShapeHint( Panel, QskBoxShapeMetrics( 25, Qt::RelativeSize ) );
2023-12-07 10:24:47 +00:00
}
2023-12-17 11:33:23 +00:00
Overlay::~Overlay()
2023-12-07 10:24:47 +00:00
{
}
2023-12-18 08:02:45 +00:00
QRectF Overlay::layoutRectForSize( const QSizeF& size ) const
{
return subControlContentsRect( size, Panel );
}
2023-12-08 14:47:32 +00:00
void Overlay::geometryChange(
2023-12-07 10:24:47 +00:00
const QRectF& newGeometry, const QRectF& oldGeometry )
{
Inherited::geometryChange( newGeometry, oldGeometry );
2023-12-12 09:55:30 +00:00
update();
2023-12-07 10:24:47 +00:00
}
2023-12-08 14:47:32 +00:00
#include "moc_Overlay.cpp"