add our own shadow code
This commit is contained in:
parent
943ddb17bd
commit
30178d48ab
|
@ -8,14 +8,9 @@
|
||||||
|
|
||||||
#include <QskTextLabel.h>
|
#include <QskTextLabel.h>
|
||||||
|
|
||||||
QSK_SUBCONTROL( Box, Panel )
|
|
||||||
|
|
||||||
Box::Box( const QString& title, QQuickItem* parent )
|
Box::Box( const QString& title, QQuickItem* parent )
|
||||||
: QskLinearBox( Qt::Vertical, parent )
|
: ShadowedBox( Qt::Vertical, parent )
|
||||||
{
|
{
|
||||||
setPanel( true );
|
|
||||||
setSubcontrolProxy( QskBox::Panel, Box::Panel );
|
|
||||||
|
|
||||||
if ( !title.isEmpty() )
|
if ( !title.isEmpty() )
|
||||||
{
|
{
|
||||||
auto label = new QskTextLabel( title, this );
|
auto label = new QskTextLabel( title, this );
|
||||||
|
|
|
@ -5,16 +5,12 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <QskLinearBox.h>
|
#include "ShadowedBox.h"
|
||||||
|
|
||||||
class QskTextLabel;
|
class Box : public ShadowedBox
|
||||||
|
|
||||||
class Box : public QskLinearBox
|
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
QSK_SUBCONTROLS( Panel )
|
|
||||||
|
|
||||||
Box( const QString& title, QQuickItem* parent = nullptr );
|
Box( const QString& title, QQuickItem* parent = nullptr );
|
||||||
};
|
};
|
||||||
|
|
|
@ -36,7 +36,6 @@ BoxWithButtons::BoxWithButtons( const QString& title, const QString& value,
|
||||||
bool isBright, QQuickItem* parent )
|
bool isBright, QQuickItem* parent )
|
||||||
: Box( QString(), parent )
|
: Box( QString(), parent )
|
||||||
{
|
{
|
||||||
setPanel( true );
|
|
||||||
setSubcontrolProxy( QskBox::Panel, Panel );
|
setSubcontrolProxy( QskBox::Panel, Panel );
|
||||||
|
|
||||||
setSizePolicy( Qt::Vertical, QskSizePolicy::Maximum );
|
setSizePolicy( Qt::Vertical, QskSizePolicy::Maximum );
|
||||||
|
|
|
@ -0,0 +1,179 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* QSkinny - Copyright (C) 2016 Uwe Rathmann
|
||||||
|
* This file may be used under the terms of the 3-clause BSD License
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#include "ShadowedBox.h"
|
||||||
|
#include "nodes/BoxShadowNode.h"
|
||||||
|
|
||||||
|
#include <QskBoxNode.h>
|
||||||
|
#include <QskBoxBorderMetrics.h>
|
||||||
|
#include <QskBoxBorderColors.h>
|
||||||
|
#include <QskGradient.h>
|
||||||
|
#include <QskSkinlet.h>
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
class Skinlet : public QskSkinlet
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum NodeRole { ShadowRole, PanelRole };
|
||||||
|
|
||||||
|
Skinlet()
|
||||||
|
{
|
||||||
|
setNodeRoles( { ShadowRole, PanelRole } );
|
||||||
|
}
|
||||||
|
|
||||||
|
QRectF subControlRect( const QskSkinnable*,
|
||||||
|
const QRectF& contentsRect, QskAspect::Subcontrol subControl ) const override
|
||||||
|
{
|
||||||
|
if ( subControl == ShadowedBox::Panel )
|
||||||
|
{
|
||||||
|
return contentsRect;
|
||||||
|
}
|
||||||
|
|
||||||
|
return QRectF();
|
||||||
|
}
|
||||||
|
|
||||||
|
QSGNode* updateSubNode( const QskSkinnable* skinnable,
|
||||||
|
quint8 nodeRole, QSGNode* node ) const override
|
||||||
|
{
|
||||||
|
const auto box = static_cast< const ShadowedBox* >( skinnable );
|
||||||
|
|
||||||
|
const auto r = box->subControlRect( ShadowedBox::Panel );
|
||||||
|
if ( r.isEmpty() )
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
switch ( nodeRole )
|
||||||
|
{
|
||||||
|
case ShadowRole:
|
||||||
|
{
|
||||||
|
auto shadowNode = static_cast< BoxShadowNode* >( node );
|
||||||
|
if ( shadowNode == nullptr )
|
||||||
|
shadowNode = new BoxShadowNode();
|
||||||
|
|
||||||
|
const auto& shadowMetrics = box->shadow();
|
||||||
|
|
||||||
|
shadowNode->setRect( shadowMetrics.shadowRect( r ) );
|
||||||
|
shadowNode->setShape( box->shape() );
|
||||||
|
shadowNode->setBlurRadius( shadowMetrics.blurRadius() );
|
||||||
|
shadowNode->setColor( box->shadowColor() );
|
||||||
|
shadowNode->setClipRect( r );
|
||||||
|
|
||||||
|
shadowNode->updateGeometry();
|
||||||
|
|
||||||
|
return shadowNode;
|
||||||
|
}
|
||||||
|
case PanelRole:
|
||||||
|
{
|
||||||
|
auto boxNode = static_cast< QskBoxNode* >( node );
|
||||||
|
if ( boxNode == nullptr )
|
||||||
|
boxNode = new QskBoxNode();
|
||||||
|
|
||||||
|
const auto r = box->subControlRect( ShadowedBox::Panel );
|
||||||
|
|
||||||
|
boxNode->setBoxData( r, box->shape(), box->borderWidth(),
|
||||||
|
box->borderColor(), box->gradient() );
|
||||||
|
|
||||||
|
return boxNode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
QSK_SUBCONTROL( ShadowedBox, Panel )
|
||||||
|
|
||||||
|
ShadowedBox::ShadowedBox(Qt::Orientation orientation, QQuickItem* parentItem )
|
||||||
|
: QskLinearBox( orientation, parentItem )
|
||||||
|
{
|
||||||
|
setFlag( QQuickItem::ItemHasContents, true );
|
||||||
|
setSkinlet( new Skinlet() );
|
||||||
|
|
||||||
|
// ### move to Skin:
|
||||||
|
setGradient( Qt::white );
|
||||||
|
setShadow( { 0, 10 } );
|
||||||
|
setShadowColor( 0xe5e5e5 );
|
||||||
|
setShape( 6 );
|
||||||
|
}
|
||||||
|
|
||||||
|
ShadowedBox::~ShadowedBox()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShadowedBox::setShadow( const QskShadowMetrics& shadow )
|
||||||
|
{
|
||||||
|
m_shadow = shadow;
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
const QskShadowMetrics& ShadowedBox::shadow() const
|
||||||
|
{
|
||||||
|
return m_shadow;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShadowedBox::setShadowColor( const QColor& color )
|
||||||
|
{
|
||||||
|
m_shadowColor = color;
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
QColor ShadowedBox::shadowColor() const
|
||||||
|
{
|
||||||
|
return m_shadowColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
QRectF ShadowedBox::layoutRectForSize( const QSizeF &size ) const
|
||||||
|
{
|
||||||
|
auto padding = paddingHint( Panel );
|
||||||
|
return { padding.left() / 2, padding.top() / 2,
|
||||||
|
size.width() - padding.right(), size.height() - padding.bottom() };
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShadowedBox::setGradient( const QskGradient& gradient )
|
||||||
|
{
|
||||||
|
m_gradient = gradient;
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
const QskGradient& ShadowedBox::gradient() const
|
||||||
|
{
|
||||||
|
return m_gradient;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShadowedBox::setShape( const QskBoxShapeMetrics& shape )
|
||||||
|
{
|
||||||
|
m_shape = shape;
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
const QskBoxShapeMetrics& ShadowedBox::shape() const
|
||||||
|
{
|
||||||
|
return m_shape;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShadowedBox::setBorderWidth( qreal width )
|
||||||
|
{
|
||||||
|
m_borderWidth = qMax( width, 0.0 );
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
qreal ShadowedBox::borderWidth() const
|
||||||
|
{
|
||||||
|
return m_borderWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShadowedBox::setBorderColor( const QColor& color )
|
||||||
|
{
|
||||||
|
m_borderColor = color;
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
QColor ShadowedBox::borderColor() const
|
||||||
|
{
|
||||||
|
return m_borderColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "moc_ShadowedBox.cpp"
|
|
@ -0,0 +1,53 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* QSkinny - Copyright (C) 2016 Uwe Rathmann
|
||||||
|
* This file may be used under the terms of the 3-clause BSD License
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QskLinearBox.h>
|
||||||
|
#include <QskBoxShapeMetrics.h>
|
||||||
|
#include <QskShadowMetrics.h>
|
||||||
|
|
||||||
|
class QskGradient;
|
||||||
|
|
||||||
|
class ShadowedBox : public QskLinearBox
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
QSK_SUBCONTROLS( Panel )
|
||||||
|
|
||||||
|
ShadowedBox( Qt::Orientation orientation, QQuickItem* parent = nullptr );
|
||||||
|
~ShadowedBox() override;
|
||||||
|
|
||||||
|
void setShadow( const QskShadowMetrics& );
|
||||||
|
const QskShadowMetrics& shadow() const;
|
||||||
|
|
||||||
|
void setGradient( const QskGradient& );
|
||||||
|
const QskGradient& gradient() const;
|
||||||
|
|
||||||
|
void setShadowColor( const QColor& );
|
||||||
|
QColor shadowColor() const;
|
||||||
|
|
||||||
|
QRectF layoutRectForSize( const QSizeF& size ) const override;
|
||||||
|
|
||||||
|
void setShape( const QskBoxShapeMetrics& );
|
||||||
|
const QskBoxShapeMetrics& shape() const;
|
||||||
|
|
||||||
|
void setBorderWidth( qreal width );
|
||||||
|
qreal borderWidth() const;
|
||||||
|
|
||||||
|
void setBorderColor( const QColor& );
|
||||||
|
QColor borderColor() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QskShadowMetrics m_shadow;
|
||||||
|
QColor m_shadowColor = Qt::black;
|
||||||
|
|
||||||
|
QskGradient m_gradient;
|
||||||
|
QskBoxShapeMetrics m_shape;
|
||||||
|
|
||||||
|
qreal m_borderWidth = 0.0;
|
||||||
|
QColor m_borderColor = Qt::black;
|
||||||
|
};
|
|
@ -16,8 +16,9 @@
|
||||||
#include "MenuBar.h"
|
#include "MenuBar.h"
|
||||||
#include "PieChartPainted.h"
|
#include "PieChartPainted.h"
|
||||||
#include "RoundedIcon.h"
|
#include "RoundedIcon.h"
|
||||||
#include "TopBar.h"
|
|
||||||
#include "RoundButton.h"
|
#include "RoundButton.h"
|
||||||
|
#include "ShadowedBox.h"
|
||||||
|
#include "TopBar.h"
|
||||||
#include "UsageBox.h"
|
#include "UsageBox.h"
|
||||||
#include "UsageDiagram.h"
|
#include "UsageDiagram.h"
|
||||||
|
|
||||||
|
@ -125,10 +126,8 @@ void Skin::initHints( const Palette& palette )
|
||||||
ed.setFontRole( TimeLabel::Text, QskSkin::HugeFont );
|
ed.setFontRole( TimeLabel::Text, QskSkin::HugeFont );
|
||||||
ed.setColor( TimeLabel::Text, "#6776FF" );
|
ed.setColor( TimeLabel::Text, "#6776FF" );
|
||||||
|
|
||||||
|
|
||||||
// boxes (including shadow):
|
// boxes (including shadow):
|
||||||
ed.setPadding( Box::Panel, 15 );
|
ed.setPadding( ShadowedBox::Panel, 15 );
|
||||||
|
|
||||||
|
|
||||||
// content in boxes (indoor temperature, humidity etc.):
|
// content in boxes (indoor temperature, humidity etc.):
|
||||||
ed.setFontRole( UsageBox::Separator, QskSkin::SmallFont );
|
ed.setFontRole( UsageBox::Separator, QskSkin::SmallFont );
|
||||||
|
|
|
@ -18,6 +18,7 @@ SOURCES += \
|
||||||
PieChartPainted.cpp \
|
PieChartPainted.cpp \
|
||||||
PieChartSkinlet.cpp \
|
PieChartSkinlet.cpp \
|
||||||
RoundedIcon.cpp \
|
RoundedIcon.cpp \
|
||||||
|
ShadowedBox.cpp \
|
||||||
Skin.cpp \
|
Skin.cpp \
|
||||||
TopBar.cpp \
|
TopBar.cpp \
|
||||||
RoundButton.cpp \
|
RoundButton.cpp \
|
||||||
|
@ -28,7 +29,8 @@ SOURCES += \
|
||||||
|
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
nodes/DiagramDataNode.cpp \
|
nodes/DiagramDataNode.cpp \
|
||||||
nodes/DiagramSegmentsNode.cpp
|
nodes/DiagramSegmentsNode.cpp \
|
||||||
|
nodes/BoxShadowNode.cpp
|
||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
Box.h \
|
Box.h \
|
||||||
|
@ -47,6 +49,7 @@ HEADERS += \
|
||||||
PieChartPainted.h \
|
PieChartPainted.h \
|
||||||
PieChartSkinlet.h \
|
PieChartSkinlet.h \
|
||||||
RoundedIcon.h \
|
RoundedIcon.h \
|
||||||
|
ShadowedBox.h \
|
||||||
Skin.h \
|
Skin.h \
|
||||||
TopBar.h \
|
TopBar.h \
|
||||||
RoundButton.h \
|
RoundButton.h \
|
||||||
|
@ -55,21 +58,8 @@ HEADERS += \
|
||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
nodes/DiagramDataNode.h \
|
nodes/DiagramDataNode.h \
|
||||||
nodes/DiagramSegmentsNode.h
|
nodes/DiagramSegmentsNode.h \
|
||||||
|
nodes/BoxShadowNode.h
|
||||||
HEADERS += \
|
|
||||||
kirigami/shadowedrectangle.h \
|
|
||||||
kirigami/scenegraph/paintedrectangleitem.h \
|
|
||||||
kirigami/scenegraph/shadowedborderrectanglematerial.h \
|
|
||||||
kirigami/scenegraph/shadowedrectanglematerial.h \
|
|
||||||
kirigami/scenegraph/shadowedrectanglenode.h
|
|
||||||
|
|
||||||
SOURCES += \
|
|
||||||
kirigami/shadowedrectangle.cpp \
|
|
||||||
kirigami/scenegraph/paintedrectangleitem.cpp \
|
|
||||||
kirigami/scenegraph/shadowedborderrectanglematerial.cpp \
|
|
||||||
kirigami/scenegraph/shadowedrectanglematerial.cpp \
|
|
||||||
kirigami/scenegraph/shadowedrectanglenode.cpp
|
|
||||||
|
|
||||||
RESOURCES += \
|
RESOURCES += \
|
||||||
images.qrc \
|
images.qrc \
|
||||||
|
|
|
@ -0,0 +1,257 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* QSkinny - Copyright (C) 2016 Uwe Rathmann
|
||||||
|
* This file may be used under the terms of the 3-clause BSD License
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#include "BoxShadowNode.h"
|
||||||
|
#include "QskBoxShapeMetrics.h"
|
||||||
|
|
||||||
|
#include <QColor>
|
||||||
|
#include <QSGMaterialShader>
|
||||||
|
#include <QSGMaterial>
|
||||||
|
|
||||||
|
#include <private/qsgnode_p.h>
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
class Shader final : public QSGMaterialShader
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Shader();
|
||||||
|
|
||||||
|
char const* const* attributeNames() const override;
|
||||||
|
|
||||||
|
void initialize() override;
|
||||||
|
|
||||||
|
void updateState( const QSGMaterialShader::RenderState& state,
|
||||||
|
QSGMaterial* newMaterial, QSGMaterial* oldMaterial) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
int m_matrixId = -1;
|
||||||
|
int m_opacityId = -1;
|
||||||
|
int m_aspectId = -1;
|
||||||
|
int m_blurExtentId = -1;
|
||||||
|
int m_radiusId = -1;
|
||||||
|
int m_colorId = -1;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Material final : public QSGMaterial
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Material();
|
||||||
|
|
||||||
|
QSGMaterialShader* createShader() const override;
|
||||||
|
|
||||||
|
QSGMaterialType* type() const override;
|
||||||
|
|
||||||
|
int compare( const QSGMaterial* other ) const override;
|
||||||
|
|
||||||
|
QVector2D aspect = QVector2D{1.0, 1.0};
|
||||||
|
float blurExtent = 0.0;
|
||||||
|
QVector4D radius = QVector4D{0.0, 0.0, 0.0, 0.0};
|
||||||
|
QColor color = Qt::black;
|
||||||
|
};
|
||||||
|
|
||||||
|
Shader::Shader()
|
||||||
|
{
|
||||||
|
const QString root( ":/iotdashboard/shaders/" );
|
||||||
|
|
||||||
|
setShaderSourceFile( QOpenGLShader::Vertex, root + "boxshadow.vert" );
|
||||||
|
setShaderSourceFile( QOpenGLShader::Fragment, root + "boxshadow.frag" );
|
||||||
|
}
|
||||||
|
|
||||||
|
char const* const* Shader::attributeNames() const
|
||||||
|
{
|
||||||
|
static char const* const names[] = { "in_vertex", "in_coord", nullptr };
|
||||||
|
return names;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Shader::initialize()
|
||||||
|
{
|
||||||
|
QSGMaterialShader::initialize();
|
||||||
|
|
||||||
|
auto p = program();
|
||||||
|
|
||||||
|
m_matrixId = p->uniformLocation( "matrix" );
|
||||||
|
m_aspectId = p->uniformLocation( "aspect" );
|
||||||
|
m_opacityId = p->uniformLocation( "opacity" );
|
||||||
|
m_blurExtentId = p->uniformLocation( "blurExtent" );
|
||||||
|
m_radiusId = p->uniformLocation( "radius" );
|
||||||
|
m_colorId = p->uniformLocation( "color" );
|
||||||
|
}
|
||||||
|
|
||||||
|
void Shader::updateState( const QSGMaterialShader::RenderState& state,
|
||||||
|
QSGMaterial* newMaterial, QSGMaterial* oldMaterial )
|
||||||
|
{
|
||||||
|
auto p = program();
|
||||||
|
|
||||||
|
if ( state.isMatrixDirty() )
|
||||||
|
p->setUniformValue( m_matrixId, state.combinedMatrix() );
|
||||||
|
|
||||||
|
if ( state.isOpacityDirty() )
|
||||||
|
p->setUniformValue( m_opacityId, state.opacity() );
|
||||||
|
|
||||||
|
if ( oldMaterial == nullptr || newMaterial->compare( oldMaterial ) != 0
|
||||||
|
|| state.isCachedMaterialDataDirty( ))
|
||||||
|
{
|
||||||
|
auto material = static_cast< const Material* >( newMaterial );
|
||||||
|
|
||||||
|
p->setUniformValue( m_aspectId, material->aspect );
|
||||||
|
p->setUniformValue( m_blurExtentId, material->blurExtent);
|
||||||
|
p->setUniformValue( m_radiusId, material->radius );
|
||||||
|
p->setUniformValue( m_colorId, material->color );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Material::Material()
|
||||||
|
{
|
||||||
|
setFlag( QSGMaterial::Blending, true );
|
||||||
|
}
|
||||||
|
|
||||||
|
QSGMaterialShader* Material::createShader() const
|
||||||
|
{
|
||||||
|
return new Shader();
|
||||||
|
}
|
||||||
|
|
||||||
|
QSGMaterialType* Material::type() const
|
||||||
|
{
|
||||||
|
static QSGMaterialType staticType;
|
||||||
|
return &staticType;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Material::compare( const QSGMaterial* other ) const
|
||||||
|
{
|
||||||
|
auto material = static_cast< const Material* >( other );
|
||||||
|
|
||||||
|
if ( material->color == color
|
||||||
|
&& material->aspect == aspect
|
||||||
|
&& qFuzzyCompare(material->blurExtent, blurExtent)
|
||||||
|
&& qFuzzyCompare(material->radius, radius) )
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return QSGMaterial::compare(other);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class BoxShadowNodePrivate final : public QSGGeometryNodePrivate
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
BoxShadowNodePrivate()
|
||||||
|
: geometry( QSGGeometry::defaultAttributes_TexturedPoint2D(), 4 )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
QSGGeometry geometry;
|
||||||
|
Material material;
|
||||||
|
|
||||||
|
QRectF rect;
|
||||||
|
};
|
||||||
|
|
||||||
|
BoxShadowNode::BoxShadowNode()
|
||||||
|
: QSGGeometryNode( *new BoxShadowNodePrivate )
|
||||||
|
{
|
||||||
|
Q_D( BoxShadowNode );
|
||||||
|
|
||||||
|
setGeometry( &d->geometry );
|
||||||
|
setMaterial( &d->material );
|
||||||
|
}
|
||||||
|
|
||||||
|
BoxShadowNode::~BoxShadowNode()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void BoxShadowNode::setRect( const QRectF& rect )
|
||||||
|
{
|
||||||
|
Q_D( BoxShadowNode );
|
||||||
|
|
||||||
|
if ( rect == d->rect )
|
||||||
|
return;
|
||||||
|
|
||||||
|
d->rect = rect;
|
||||||
|
|
||||||
|
QVector2D aspect( 1.0, 1.0 );
|
||||||
|
|
||||||
|
if ( rect.width() >= rect.height() )
|
||||||
|
aspect.setX( rect.width() / rect.height() );
|
||||||
|
else
|
||||||
|
aspect.setY( rect.height() / rect.width() );
|
||||||
|
|
||||||
|
if ( d->material.aspect != aspect )
|
||||||
|
{
|
||||||
|
d->material.aspect = aspect;
|
||||||
|
markDirty( QSGNode::DirtyMaterial );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BoxShadowNode::setShape( const QskBoxShapeMetrics& shape )
|
||||||
|
{
|
||||||
|
Q_D( BoxShadowNode );
|
||||||
|
|
||||||
|
const float t = std::min( d->rect.width(), d->rect.height() );
|
||||||
|
|
||||||
|
const float r1 = shape.radius( Qt::BottomRightCorner ).width();
|
||||||
|
const float r2 = shape.radius( Qt::TopRightCorner ).width();
|
||||||
|
const float r3 = shape.radius( Qt::BottomLeftCorner ).width();
|
||||||
|
const float r4 = shape.radius( Qt::TopLeftCorner ).width();
|
||||||
|
|
||||||
|
const auto uniformRadius = QVector4D(
|
||||||
|
std::min( r1 / t, 1.0f ), std::min( r2 / t, 1.0f ),
|
||||||
|
std::min( r3 / t, 1.0f ), std::min( r4 / t, 1.0f ) );
|
||||||
|
|
||||||
|
if ( d->material.radius != uniformRadius )
|
||||||
|
{
|
||||||
|
d->material.radius = uniformRadius;
|
||||||
|
|
||||||
|
markDirty( QSGNode::DirtyMaterial );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BoxShadowNode::setColor( const QColor& color )
|
||||||
|
{
|
||||||
|
Q_D( BoxShadowNode );
|
||||||
|
|
||||||
|
const auto a = color.alphaF();
|
||||||
|
|
||||||
|
const auto c = QColor::fromRgbF(
|
||||||
|
color.redF() * a, color.greenF() * a, color.blueF() * a, a );
|
||||||
|
|
||||||
|
if ( d->material.color != c )
|
||||||
|
{
|
||||||
|
d->material.color = c;
|
||||||
|
markDirty( QSGNode::DirtyMaterial );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BoxShadowNode::setBlurRadius( qreal blurRadius )
|
||||||
|
{
|
||||||
|
Q_D( BoxShadowNode );
|
||||||
|
|
||||||
|
if ( blurRadius <= 0.0 )
|
||||||
|
blurRadius = 0.0;
|
||||||
|
|
||||||
|
const float t = 0.5 * std::min( d->rect.width(), d->rect.height() );
|
||||||
|
const float uniformExtent = blurRadius / t;
|
||||||
|
|
||||||
|
if ( !qFuzzyCompare( d->material.blurExtent, uniformExtent ) )
|
||||||
|
{
|
||||||
|
d->material.blurExtent = uniformExtent;
|
||||||
|
markDirty( QSGNode::DirtyMaterial );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BoxShadowNode::setClipRect( const QRectF& rect )
|
||||||
|
{
|
||||||
|
Q_UNUSED( rect )
|
||||||
|
}
|
||||||
|
|
||||||
|
void BoxShadowNode::updateGeometry()
|
||||||
|
{
|
||||||
|
Q_D( BoxShadowNode );
|
||||||
|
|
||||||
|
QSGGeometry::updateTexturedRectGeometry(
|
||||||
|
&d->geometry, d->rect, QRectF( -0.5, -0.5, 1.0, 1.0 ) );
|
||||||
|
|
||||||
|
markDirty( QSGNode::DirtyGeometry );
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* QSkinny - Copyright (C) 2016 Uwe Rathmann
|
||||||
|
* This file may be used under the terms of the 3-clause BSD License
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QSGGeometryNode>
|
||||||
|
|
||||||
|
class QColor;
|
||||||
|
class QskBoxShapeMetrics;
|
||||||
|
|
||||||
|
class BoxShadowNodePrivate;
|
||||||
|
|
||||||
|
class BoxShadowNode : public QSGGeometryNode
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
BoxShadowNode();
|
||||||
|
~BoxShadowNode() override;
|
||||||
|
|
||||||
|
void setRect( const QRectF& );
|
||||||
|
void setShape( const QskBoxShapeMetrics& );
|
||||||
|
void setColor( const QColor& );
|
||||||
|
void setBlurRadius( qreal );
|
||||||
|
|
||||||
|
void setClipRect( const QRectF& );
|
||||||
|
|
||||||
|
void updateGeometry();
|
||||||
|
|
||||||
|
private:
|
||||||
|
Q_DECLARE_PRIVATE( BoxShadowNode )
|
||||||
|
};
|
|
@ -0,0 +1,7 @@
|
||||||
|
<!DOCTYPE RCC>
|
||||||
|
<RCC version="1.0">
|
||||||
|
<qresource prefix="/iotdashboard">
|
||||||
|
<file>shaders/boxshadow.vert</file>
|
||||||
|
<file>shaders/boxshadow.frag</file>
|
||||||
|
</qresource>
|
||||||
|
</RCC>
|
|
@ -0,0 +1,42 @@
|
||||||
|
uniform lowp float opacity;
|
||||||
|
uniform lowp float blurExtent;
|
||||||
|
uniform lowp vec4 radius;
|
||||||
|
uniform lowp vec4 color;
|
||||||
|
uniform lowp vec2 aspect;
|
||||||
|
|
||||||
|
varying lowp vec2 coord;
|
||||||
|
|
||||||
|
lowp float effectiveRadius( in lowp vec4 radii, in lowp vec2 point )
|
||||||
|
{
|
||||||
|
if ( point.x > 0.0 )
|
||||||
|
return ( point.y > 0.0) ? radii.x : radii.y;
|
||||||
|
else
|
||||||
|
return ( point.y > 0.0) ? radii.z : radii.w;
|
||||||
|
}
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
lowp vec4 col = vec4(0.0);
|
||||||
|
|
||||||
|
if ( opacity > 0.0 )
|
||||||
|
{
|
||||||
|
const lowp float minRadius = 0.05;
|
||||||
|
|
||||||
|
lowp float e2 = 0.5 * blurExtent;
|
||||||
|
lowp float r = 2.0 * effectiveRadius( radius, coord );
|
||||||
|
|
||||||
|
lowp float f = minRadius / max( r, minRadius );
|
||||||
|
|
||||||
|
r += e2 * f;
|
||||||
|
|
||||||
|
lowp vec2 d = r + blurExtent - aspect * ( 1.0 - abs( 2.0 * coord ) );
|
||||||
|
lowp float l = min( max(d.x, d.y), 0.0) + length( max(d, 0.0) );
|
||||||
|
|
||||||
|
lowp float shadow = l - r;
|
||||||
|
|
||||||
|
lowp float v = smoothstep( -e2, e2, shadow );
|
||||||
|
col = mix( color, vec4(0.0), v ) * opacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
gl_FragColor = col;
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
uniform highp mat4 matrix;
|
||||||
|
uniform lowp vec2 aspect;
|
||||||
|
|
||||||
|
attribute highp vec4 in_vertex;
|
||||||
|
attribute mediump vec2 in_coord;
|
||||||
|
|
||||||
|
varying mediump vec2 coord;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
coord = in_coord;
|
||||||
|
gl_Position = matrix * in_vertex;
|
||||||
|
}
|
Loading…
Reference in New Issue