qskinny/src/nodes/QskBoxNode.cpp

148 lines
4.5 KiB
C++
Raw Normal View History

2017-07-21 16:21:34 +00:00
/******************************************************************************
2024-01-17 13:31:45 +00:00
* QSkinny - Copyright (C) The authors
2023-04-06 07:23:37 +00:00
* SPDX-License-Identifier: BSD-3-Clause
2017-07-21 16:21:34 +00:00
*****************************************************************************/
#include "QskBoxNode.h"
#include "QskBoxShadowNode.h"
#include "QskBoxRectangleNode.h"
#include "QskSGNode.h"
2017-10-20 11:09:30 +00:00
#include "QskGradient.h"
#include "QskGradientDirection.h"
#include "QskShadowMetrics.h"
#include "QskBoxBorderMetrics.h"
#include "QskBoxBorderColors.h"
2024-10-24 08:16:51 +00:00
#include "QskBoxShapeMetrics.h"
2024-09-24 08:14:26 +00:00
#include "QskRgbValue.h"
2017-10-20 11:09:30 +00:00
namespace
{
2024-12-09 13:53:59 +00:00
enum NodeRole : quint8
{
ShadowRole,
ShadowFillRole,
BoxRole,
FillRole
};
}
2023-04-04 06:49:11 +00:00
static void qskUpdateChildren( QSGNode* parentNode, quint8 role, QSGNode* node )
{
static const QVector< quint8 > roles =
{ ShadowRole, ShadowFillRole, BoxRole, FillRole };
auto oldNode = QskSGNode::findChildNode( parentNode, role );
QskSGNode::replaceChildNode( roles, role, parentNode, oldNode, node );
}
2017-07-21 16:21:34 +00:00
template< typename Node >
static inline Node* qskNode( QSGNode* parentNode, quint8 role )
{
using namespace QskSGNode;
2017-07-21 16:21:34 +00:00
auto node = static_cast< Node* > ( findChildNode( parentNode, role ) );
2022-10-31 13:42:08 +00:00
if ( node == nullptr )
{
node = new Node();
setNodeRole( node, role );
}
return node;
}
2022-10-31 13:42:08 +00:00
2018-08-03 06:15:28 +00:00
QskBoxNode::QskBoxNode()
2017-07-21 16:21:34 +00:00
{
}
QskBoxNode::~QskBoxNode()
{
}
void QskBoxNode::updateNode( const QQuickWindow* window, const QRectF& rect,
2024-10-24 08:16:51 +00:00
const QskBoxShapeMetrics& shapeMetrics, const QskBoxBorderMetrics& borderMetrics,
const QskBoxBorderColors& borderColors, const QskGradient& gradient,
const QskShadowMetrics& shadowMetrics, const QColor& shadowColor )
2017-07-21 16:21:34 +00:00
{
using namespace QskSGNode;
2017-07-21 16:21:34 +00:00
QskBoxShadowNode* shadowNode = nullptr;
QskBoxRectangleNode* shadowFillNode = nullptr;
QskBoxRectangleNode* rectNode = nullptr;
QskBoxRectangleNode* fillNode = nullptr;
2024-09-23 13:55:00 +00:00
if ( !rect.isEmpty() )
2017-07-21 16:21:34 +00:00
{
2024-09-24 08:17:10 +00:00
const auto hasFilling = gradient.isVisible();
const auto hasBorder = !borderMetrics.isNull() && borderColors.isVisible();
2024-10-24 08:16:51 +00:00
const auto hasShadow = !shadowMetrics.isNull() && QskRgb::isVisible( shadowColor );
2024-09-24 08:14:26 +00:00
if ( hasShadow )
2024-09-23 13:55:00 +00:00
{
2024-10-24 08:16:51 +00:00
const auto shadow = shadowMetrics.toAbsolute( rect.size() );
const auto shadowRect = shadow.shadowRect( rect );
2024-10-25 16:54:04 +00:00
auto shadowShape = shapeMetrics;
switch( static_cast< int >( shadow.shapeMode() ) )
{
case QskShadowMetrics::Ellipse:
shadowShape.setRadius( 100.0, Qt::RelativeSize );
break;
case QskShadowMetrics::Rectangle:
shadowShape.setRadius( 0.0, Qt::AbsoluteSize );
break;
}
2024-10-24 08:16:51 +00:00
if ( shadow.blurRadius() <= 0.0 )
{
// QskBoxRectangleNode allows scene graph batching
shadowFillNode = qskNode< QskBoxRectangleNode >( this, ShadowFillRole );
shadowFillNode->updateFilling( window,
shadowRect, shadowShape, shadowColor );
}
else
{
shadowNode = qskNode< QskBoxShadowNode >( this, ShadowRole );
2024-10-24 08:16:51 +00:00
shadowNode->setShadowData( shadowRect,
2024-10-25 16:54:04 +00:00
shadowShape, shadow.blurRadius(), shadowColor );
}
2024-09-23 13:55:00 +00:00
}
2024-09-24 08:17:10 +00:00
if ( hasBorder || hasFilling )
{
rectNode = qskNode< QskBoxRectangleNode >( this, BoxRole );
2024-09-24 08:17:10 +00:00
if ( hasBorder && hasFilling )
2024-09-23 13:55:00 +00:00
{
2024-09-24 08:17:10 +00:00
const bool doCombine = rectNode->hasHint( QskFillNode::PreferColoredGeometry )
&& QskBoxRectangleNode::isCombinedGeometrySupported( gradient );
2024-09-23 13:55:00 +00:00
2024-09-24 08:17:10 +00:00
if ( !doCombine )
fillNode = qskNode< QskBoxRectangleNode >( this, FillRole );
}
2024-09-24 08:17:10 +00:00
if ( fillNode )
2024-09-23 13:55:00 +00:00
{
rectNode->updateBorder( window, rect,
shapeMetrics, borderMetrics, borderColors );
fillNode->updateFilling( window, rect,
shapeMetrics, borderMetrics, gradient );
2024-09-23 13:55:00 +00:00
}
2024-09-24 08:17:10 +00:00
else
{
rectNode->updateBox( window, rect,
shapeMetrics, borderMetrics, borderColors, gradient );
2024-09-24 08:17:10 +00:00
}
}
2017-07-21 16:21:34 +00:00
}
qskUpdateChildren( this, ShadowRole, shadowNode );
qskUpdateChildren( this, ShadowFillRole, shadowFillNode );
qskUpdateChildren( this, BoxRole, rectNode );
qskUpdateChildren( this, FillRole, fillNode );
2017-07-21 16:21:34 +00:00
}