QskArcShadowNode introduced ( kudos to Rick )
This commit is contained in:
parent
a420407a56
commit
e63b064f5a
|
|
@ -0,0 +1,109 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* QSkinny - Copyright (C) 2016 Uwe Rathmann
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#include "ArcPage.h"
|
||||||
|
#include "ShadowedArc.h"
|
||||||
|
#include "Slider.h"
|
||||||
|
|
||||||
|
#include <QskGridBox.h>
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
class ControlPanel : public QskGridBox
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
ControlPanel( ShadowedArc* arc, QQuickItem* parent = nullptr )
|
||||||
|
: QskGridBox( parent )
|
||||||
|
{
|
||||||
|
setMargins( 5 );
|
||||||
|
setSpacing( 10 );
|
||||||
|
|
||||||
|
{
|
||||||
|
auto slider = new Slider( "Start", 0, 360, 10, arc->startAngle() );
|
||||||
|
connect( slider, &Slider::valueChanged, arc, &ShadowedArc::setStartAngle );
|
||||||
|
|
||||||
|
addItem( slider, 0, 0 );
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto slider = new Slider( "Span", -360, 360, 10, arc->spanAngle() );
|
||||||
|
connect( slider, &Slider::valueChanged, arc, &ShadowedArc::setSpanAngle );
|
||||||
|
|
||||||
|
addItem( slider, 0, 1 );
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto slider = new Slider( "Extent", 0, 100, 1, arc->thickness() );
|
||||||
|
connect( slider, &Slider::valueChanged, arc, &ShadowedArc::setThickness );
|
||||||
|
|
||||||
|
addItem( slider, 1, 0 );
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto slider = new Slider( "Border", 0, 10, 1, arc->borderWidth() );
|
||||||
|
connect( slider, &Slider::valueChanged, arc, &ShadowedArc::setBorderWidth );
|
||||||
|
|
||||||
|
addItem( slider, 1, 1);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto slider = new Slider( "Spread Radius", -10, 50, 1, arc->spreadRadius() );
|
||||||
|
connect( slider, &Slider::valueChanged, arc, &ShadowedArc::setSpreadRadius );
|
||||||
|
|
||||||
|
addItem( slider, 2, 0 );
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto slider = new Slider( "Blur Radius", 0, 50, 1, arc->blurRadius() );
|
||||||
|
connect( slider, &Slider::valueChanged, arc, &ShadowedArc::setBlurRadius );
|
||||||
|
|
||||||
|
addItem( slider, 2, 1 );
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto slider = new Slider( "Offset X", -50, 50, 1, arc->offsetX() );
|
||||||
|
connect( slider, &Slider::valueChanged, arc, &ShadowedArc::setOffsetX );
|
||||||
|
|
||||||
|
addItem( slider, 3, 0 );
|
||||||
|
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto slider = new Slider( "Offset Y", -50, 50, 1, arc->offsetY() );
|
||||||
|
connect( slider, &Slider::valueChanged, arc, &ShadowedArc::setOffsetY );
|
||||||
|
|
||||||
|
addItem( slider, 3, 1 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
ArcPage::ArcPage( QQuickItem* parent )
|
||||||
|
: QskLinearBox( Qt::Vertical, parent )
|
||||||
|
{
|
||||||
|
auto arc = new ShadowedArc();
|
||||||
|
arc->setMargins( 40 ); // some extra space for testing the offsets
|
||||||
|
|
||||||
|
{
|
||||||
|
// initial settings
|
||||||
|
arc->setStartAngle( 45.0 );
|
||||||
|
arc->setSpanAngle( 270.0 );
|
||||||
|
arc->setThickness( 10.0 );
|
||||||
|
|
||||||
|
arc->setFillColor( Qt::darkRed );
|
||||||
|
|
||||||
|
arc->setBorderWidth( 0 );
|
||||||
|
arc->setBorderColor( Qt::darkYellow );
|
||||||
|
|
||||||
|
arc->setShadowColor( Qt::black );
|
||||||
|
arc->setSpreadRadius( 0.0 );
|
||||||
|
arc->setBlurRadius( 4.0 );
|
||||||
|
arc->setOffsetX( 2.0 );
|
||||||
|
arc->setOffsetY( 2.0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
auto panel = new ControlPanel( arc );
|
||||||
|
panel->setSizePolicy( Qt::Vertical, QskSizePolicy::Fixed );
|
||||||
|
|
||||||
|
addItem( panel );
|
||||||
|
addItem( arc );
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "ArcPage.moc"
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* QSkinny - Copyright (C) 2016 Uwe Rathmann
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QskLinearBox.h>
|
||||||
|
|
||||||
|
class ArcPage : public QskLinearBox
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ArcPage( QQuickItem* parent = nullptr );
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,73 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* QSkinny - Copyright (C) 2016 Uwe Rathmann
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#include "BoxPage.h"
|
||||||
|
#include "ShadowedBox.h"
|
||||||
|
#include "Slider.h"
|
||||||
|
|
||||||
|
#include <QskRgbValue.h>
|
||||||
|
#include <QFontMetrics>
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
class ControlPanel : public QskLinearBox
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ControlPanel( ShadowedBox* box, QQuickItem* parent = nullptr )
|
||||||
|
: QskLinearBox( Qt::Vertical, parent )
|
||||||
|
{
|
||||||
|
{
|
||||||
|
auto slider = new Slider( "Offset X", -50, 50, 1, box->offsetX() );
|
||||||
|
connect( slider, &Slider::valueChanged, box, &ShadowedBox::setOffsetX );
|
||||||
|
|
||||||
|
addItem( slider );
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto slider = new Slider( "Offset Y", -50, 50, 1, box->offsetY() );
|
||||||
|
connect( slider, &Slider::valueChanged, box, &ShadowedBox::setOffsetY );
|
||||||
|
|
||||||
|
addItem( slider );
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto slider = new Slider( "Spread Radius", -10, 50, 1, box->spreadRadius() );
|
||||||
|
connect( slider, &Slider::valueChanged, box, &ShadowedBox::setSpreadRadius );
|
||||||
|
|
||||||
|
addItem( slider );
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto slider = new Slider( "Blur Radius", 0, 50, 1, box->blurRadius() );
|
||||||
|
connect( slider, &Slider::valueChanged, box, &ShadowedBox::setBlurRadius );
|
||||||
|
|
||||||
|
addItem( slider );
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto slider = new Slider( "Opacity", 0, 1, 0.01, box->opacity() );
|
||||||
|
connect( slider, &Slider::valueChanged, box, &ShadowedBox::setOpacity );
|
||||||
|
|
||||||
|
addItem( slider );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
BoxPage::BoxPage( QQuickItem* parent )
|
||||||
|
: QskLinearBox( Qt::Vertical, parent )
|
||||||
|
{
|
||||||
|
auto box = new ShadowedBox();
|
||||||
|
box->setMargins( 40 ); // some extra space for testing the offsets
|
||||||
|
|
||||||
|
{
|
||||||
|
box->setOffsetX( 10 );
|
||||||
|
box->setOffsetY( 10 );
|
||||||
|
box->setSpreadRadius( 0 );
|
||||||
|
box->setBlurRadius( 5 );
|
||||||
|
}
|
||||||
|
|
||||||
|
auto panel = new ControlPanel( box );
|
||||||
|
panel->setSizePolicy( Qt::Vertical, QskSizePolicy::Fixed );
|
||||||
|
|
||||||
|
addItem( panel );
|
||||||
|
addItem( box );
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* QSkinny - Copyright (C) 2016 Uwe Rathmann
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QskLinearBox.h>
|
||||||
|
|
||||||
|
class QskSlider;
|
||||||
|
|
||||||
|
class BoxPage : public QskLinearBox
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
BoxPage( QQuickItem* parent = nullptr );
|
||||||
|
|
||||||
|
private:
|
||||||
|
void addSlider( int row, const QString&, QskSlider* );
|
||||||
|
};
|
||||||
|
|
@ -3,4 +3,7 @@
|
||||||
# SPDX-License-Identifier: BSD-3-Clause
|
# SPDX-License-Identifier: BSD-3-Clause
|
||||||
############################################################################
|
############################################################################
|
||||||
|
|
||||||
qsk_add_example(shadows ShadowedBox.h ShadowedBox.cpp main.cpp)
|
qsk_add_example(shadows
|
||||||
|
BoxPage.h BoxPage.cpp ShadowedBox.h ShadowedBox.cpp
|
||||||
|
ArcPage.h ArcPage.cpp ShadowedArc.h ShadowedArc.cpp
|
||||||
|
Slider.h Slider.cpp main.cpp)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,269 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* QSkinny - Copyright (C) 2016 Uwe Rathmann
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#include "ShadowedArc.h"
|
||||||
|
|
||||||
|
#include <QskSkinlet.h>
|
||||||
|
#include <QskArcNode.h>
|
||||||
|
#include <QskArcMetrics.h>
|
||||||
|
#include <QskShadowMetrics.h>
|
||||||
|
|
||||||
|
#include <QskArcNode.h>
|
||||||
|
#include <QskSGNode.h>
|
||||||
|
|
||||||
|
QSK_SUBCONTROL( ShadowedArc, Arc )
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
class Skinlet : public QskSkinlet
|
||||||
|
{
|
||||||
|
using Inherited = QskSkinlet;
|
||||||
|
|
||||||
|
public:
|
||||||
|
enum NodeRoles { ArcRole };
|
||||||
|
|
||||||
|
Skinlet( QskSkin* skin = nullptr );
|
||||||
|
|
||||||
|
QRectF subControlRect( const QskSkinnable*,
|
||||||
|
const QRectF&, QskAspect::Subcontrol ) const override;
|
||||||
|
|
||||||
|
QSGNode* updateSubNode( const QskSkinnable*,
|
||||||
|
quint8 nodeRole, QSGNode* ) const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QSGNode* updateArcNode( const ShadowedArc*, QSGNode* node ) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
Skinlet::Skinlet( QskSkin* skin )
|
||||||
|
: QskSkinlet( skin )
|
||||||
|
{
|
||||||
|
setNodeRoles( { ArcRole } );
|
||||||
|
}
|
||||||
|
|
||||||
|
QRectF Skinlet::subControlRect( const QskSkinnable* skinnable,
|
||||||
|
const QRectF& contentsRect, QskAspect::Subcontrol subControl ) const
|
||||||
|
{
|
||||||
|
if ( subControl == ShadowedArc::Arc )
|
||||||
|
return contentsRect;
|
||||||
|
|
||||||
|
return Inherited::subControlRect( skinnable, contentsRect, subControl );
|
||||||
|
}
|
||||||
|
|
||||||
|
QSGNode* Skinlet::updateSubNode(
|
||||||
|
const QskSkinnable* skinnable, quint8 nodeRole, QSGNode* node ) const
|
||||||
|
{
|
||||||
|
if ( nodeRole == ArcRole )
|
||||||
|
{
|
||||||
|
auto arc = static_cast< const ShadowedArc* >( skinnable );
|
||||||
|
return updateArcNode( arc, node );
|
||||||
|
}
|
||||||
|
|
||||||
|
return Inherited::updateSubNode( skinnable, nodeRole, node );
|
||||||
|
}
|
||||||
|
|
||||||
|
QSGNode* Skinlet::updateArcNode( const ShadowedArc* arc, QSGNode* node ) const
|
||||||
|
{
|
||||||
|
using Q = ShadowedArc;
|
||||||
|
|
||||||
|
const auto rect = arc->subControlRect( Q::Arc );
|
||||||
|
if ( rect.isEmpty() )
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
auto arcNode = QskSGNode::ensureNode< QskArcNode >( node );
|
||||||
|
|
||||||
|
const auto metrics = arc->arcMetricsHint( Q::Arc );
|
||||||
|
const auto fillGradient = arc->gradientHint( Q::Arc );
|
||||||
|
|
||||||
|
const auto borderColor = arc->color( Q::Arc | QskAspect::Border );
|
||||||
|
const auto borderWidth = arc->metric( Q::Arc | QskAspect::Border );
|
||||||
|
|
||||||
|
const auto shadowColor = arc->shadowColorHint( Q::Arc );
|
||||||
|
const auto shadowMetrics = arc->shadowMetricsHint( Q::Arc );
|
||||||
|
|
||||||
|
arcNode->setArcData( rect, metrics, borderWidth, borderColor,
|
||||||
|
fillGradient, shadowColor, shadowMetrics);
|
||||||
|
|
||||||
|
return arcNode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ShadowedArc::ShadowedArc( QQuickItem* parent )
|
||||||
|
: Inherited( parent )
|
||||||
|
{
|
||||||
|
auto skinlet = new Skinlet();
|
||||||
|
skinlet->setOwnedBySkinnable( true );
|
||||||
|
|
||||||
|
setSkinlet( skinlet );
|
||||||
|
|
||||||
|
// initial settings
|
||||||
|
|
||||||
|
setArcMetrics( { 0.0, 360.0, 1.0, Qt::RelativeSize } );
|
||||||
|
|
||||||
|
setFillColor( Qt::darkRed );
|
||||||
|
|
||||||
|
setBorderWidth( 0 );
|
||||||
|
setBorderColor( Qt::gray );
|
||||||
|
|
||||||
|
setShadowColor( Qt::black );
|
||||||
|
setShadowMetrics( { 0, 0, QPointF( 0, 0 ), Qt::AbsoluteSize } );
|
||||||
|
}
|
||||||
|
|
||||||
|
ShadowedArc::~ShadowedArc()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShadowedArc::setThickness( qreal thickness )
|
||||||
|
{
|
||||||
|
auto metrics = arcMetrics();
|
||||||
|
metrics.setThickness( thickness );
|
||||||
|
|
||||||
|
setArcMetrics( metrics );
|
||||||
|
}
|
||||||
|
|
||||||
|
qreal ShadowedArc::thickness() const
|
||||||
|
{
|
||||||
|
return arcMetrics().thickness();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShadowedArc::setBorderWidth( qreal width )
|
||||||
|
{
|
||||||
|
width = std::max( width, 0.0 );
|
||||||
|
setMetric( Arc | QskAspect::Border, width );
|
||||||
|
}
|
||||||
|
|
||||||
|
qreal ShadowedArc::borderWidth() const
|
||||||
|
{
|
||||||
|
return metric( Arc | QskAspect::Border );
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShadowedArc::setStartAngle( qreal degrees )
|
||||||
|
{
|
||||||
|
auto metrics = arcMetrics();
|
||||||
|
metrics.setStartAngle( degrees );
|
||||||
|
|
||||||
|
setArcMetrics( metrics );
|
||||||
|
}
|
||||||
|
|
||||||
|
qreal ShadowedArc::startAngle() const
|
||||||
|
{
|
||||||
|
return arcMetrics().startAngle();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShadowedArc::setSpanAngle( qreal degrees )
|
||||||
|
{
|
||||||
|
auto metrics = arcMetrics();
|
||||||
|
metrics.setSpanAngle( degrees );
|
||||||
|
|
||||||
|
setArcMetrics( metrics );
|
||||||
|
}
|
||||||
|
|
||||||
|
qreal ShadowedArc::spanAngle() const
|
||||||
|
{
|
||||||
|
return arcMetrics().spanAngle();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShadowedArc::setOffsetX( qreal dx )
|
||||||
|
{
|
||||||
|
auto metrics = shadowMetrics();
|
||||||
|
metrics.setOffsetX( dx );
|
||||||
|
|
||||||
|
setShadowMetrics( metrics );
|
||||||
|
}
|
||||||
|
|
||||||
|
qreal ShadowedArc::offsetX() const
|
||||||
|
{
|
||||||
|
return shadowMetrics().offset().x();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShadowedArc::setOffsetY( qreal dy )
|
||||||
|
{
|
||||||
|
auto metrics = shadowMetrics();
|
||||||
|
metrics.setOffsetY( dy );
|
||||||
|
|
||||||
|
setShadowMetrics( metrics );
|
||||||
|
}
|
||||||
|
|
||||||
|
qreal ShadowedArc::offsetY() const
|
||||||
|
{
|
||||||
|
return shadowMetrics().offset().y();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShadowedArc::setSpreadRadius( qreal radius )
|
||||||
|
{
|
||||||
|
auto metrics = shadowMetrics();
|
||||||
|
metrics.setSpreadRadius( radius );
|
||||||
|
|
||||||
|
setShadowMetrics( metrics );
|
||||||
|
}
|
||||||
|
|
||||||
|
qreal ShadowedArc::spreadRadius() const
|
||||||
|
{
|
||||||
|
return shadowMetrics().spreadRadius();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShadowedArc::setBlurRadius( qreal radius )
|
||||||
|
{
|
||||||
|
auto metrics = shadowMetrics();
|
||||||
|
metrics.setBlurRadius( radius );
|
||||||
|
|
||||||
|
setShadowMetrics( metrics );
|
||||||
|
}
|
||||||
|
|
||||||
|
qreal ShadowedArc::blurRadius() const
|
||||||
|
{
|
||||||
|
return shadowMetrics().blurRadius();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShadowedArc::setFillColor( const QColor& color )
|
||||||
|
{
|
||||||
|
setColor( Arc, color );
|
||||||
|
}
|
||||||
|
|
||||||
|
QColor ShadowedArc::fillColor() const
|
||||||
|
{
|
||||||
|
return color( Arc );
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShadowedArc::setShadowColor( const QColor& color )
|
||||||
|
{
|
||||||
|
setShadowColorHint( Arc, color );
|
||||||
|
}
|
||||||
|
|
||||||
|
QColor ShadowedArc::shadowColor() const
|
||||||
|
{
|
||||||
|
return shadowColorHint( Arc );
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShadowedArc::setBorderColor( const QColor& color )
|
||||||
|
{
|
||||||
|
setColor( Arc | QskAspect::Border, color );
|
||||||
|
}
|
||||||
|
|
||||||
|
QColor ShadowedArc::borderColor() const
|
||||||
|
{
|
||||||
|
return color( Arc | QskAspect::Border );
|
||||||
|
}
|
||||||
|
|
||||||
|
QskShadowMetrics ShadowedArc::shadowMetrics() const
|
||||||
|
{
|
||||||
|
return shadowMetricsHint( Arc );
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShadowedArc::setShadowMetrics( const QskShadowMetrics& metrics )
|
||||||
|
{
|
||||||
|
setShadowMetricsHint( Arc, metrics );
|
||||||
|
}
|
||||||
|
|
||||||
|
QskArcMetrics ShadowedArc::arcMetrics() const
|
||||||
|
{
|
||||||
|
return arcMetricsHint( Arc );
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShadowedArc::setArcMetrics( const QskArcMetrics& metrics )
|
||||||
|
{
|
||||||
|
setArcMetricsHint( Arc, metrics );
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "moc_ShadowedArc.cpp"
|
||||||
|
|
@ -0,0 +1,64 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* QSkinny - Copyright (C) 2016 Uwe Rathmann
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QskControl.h>
|
||||||
|
|
||||||
|
class QskShadowMetrics;
|
||||||
|
class QskArcMetrics;
|
||||||
|
|
||||||
|
class ShadowedArc : public QskControl
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
using Inherited = QskControl;
|
||||||
|
|
||||||
|
public:
|
||||||
|
QSK_SUBCONTROLS( Arc )
|
||||||
|
|
||||||
|
ShadowedArc( QQuickItem* parent = nullptr );
|
||||||
|
~ShadowedArc() override;
|
||||||
|
|
||||||
|
qreal thickness() const;
|
||||||
|
qreal borderWidth() const;
|
||||||
|
|
||||||
|
qreal startAngle() const;
|
||||||
|
qreal spanAngle() const;
|
||||||
|
|
||||||
|
qreal offsetX() const;
|
||||||
|
qreal offsetY() const;
|
||||||
|
|
||||||
|
qreal spreadRadius() const;
|
||||||
|
qreal blurRadius() const;
|
||||||
|
|
||||||
|
QColor borderColor() const;
|
||||||
|
QColor fillColor() const;
|
||||||
|
QColor shadowColor() const;
|
||||||
|
|
||||||
|
public Q_SLOTS:
|
||||||
|
void setThickness( qreal );
|
||||||
|
void setBorderWidth( qreal );
|
||||||
|
|
||||||
|
void setStartAngle( qreal );
|
||||||
|
void setSpanAngle( qreal );
|
||||||
|
|
||||||
|
void setOffsetX( qreal );
|
||||||
|
void setOffsetY( qreal );
|
||||||
|
|
||||||
|
void setSpreadRadius( qreal );
|
||||||
|
void setBlurRadius( qreal );
|
||||||
|
|
||||||
|
void setBorderColor( const QColor& );
|
||||||
|
void setFillColor( const QColor& );
|
||||||
|
void setShadowColor( const QColor& );
|
||||||
|
|
||||||
|
private:
|
||||||
|
QskShadowMetrics shadowMetrics() const;
|
||||||
|
void setShadowMetrics( const QskShadowMetrics& );
|
||||||
|
|
||||||
|
QskArcMetrics arcMetrics() const;
|
||||||
|
void setArcMetrics( const QskArcMetrics& );
|
||||||
|
};
|
||||||
|
|
@ -14,21 +14,10 @@
|
||||||
ShadowedBox::ShadowedBox( QQuickItem* parentItem )
|
ShadowedBox::ShadowedBox( QQuickItem* parentItem )
|
||||||
: QskBox( true, parentItem )
|
: QskBox( true, parentItem )
|
||||||
{
|
{
|
||||||
QColor c( Qt::darkRed );
|
setGradientHint( Panel, Qt::darkRed );
|
||||||
#if 0
|
|
||||||
c.setAlpha( 100 );
|
|
||||||
#endif
|
|
||||||
|
|
||||||
setGradientHint( Panel, c );
|
|
||||||
setBoxShapeHint( Panel, QskBoxShapeMetrics( 40, 0, 15, 0 ) );
|
setBoxShapeHint( Panel, QskBoxShapeMetrics( 40, 0, 15, 0 ) );
|
||||||
|
|
||||||
setBoxBorderMetricsHint( Panel, 0 );
|
setBoxBorderMetricsHint( Panel, 0 );
|
||||||
|
|
||||||
#if 0
|
|
||||||
setBoxBorderMetricsHint( Panel, 10 );
|
|
||||||
setBoxBorderColorsHint( Panel, Qt::blue );
|
|
||||||
#endif
|
|
||||||
|
|
||||||
setShadowColorHint( Panel, Qt::black );
|
setShadowColorHint( Panel, Qt::black );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,47 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* QSkinny - Copyright (C) 2016 Uwe Rathmann
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#include "Slider.h"
|
||||||
|
|
||||||
|
#include <QskSlider.h>
|
||||||
|
#include <QskTextLabel.h>
|
||||||
|
|
||||||
|
#include <qfontmetrics.h>
|
||||||
|
|
||||||
|
Slider::Slider( const QString& text, qreal min, qreal max,
|
||||||
|
qreal step, qreal value, QQuickItem* parent )
|
||||||
|
: QskLinearBox( Qt::Horizontal, parent )
|
||||||
|
{
|
||||||
|
m_label = new QskTextLabel( text, this );
|
||||||
|
m_label->setSizePolicy( Qt::Horizontal, QskSizePolicy::Fixed );
|
||||||
|
|
||||||
|
m_slider = new QskSlider( this );
|
||||||
|
m_slider->setBoundaries( min, max );
|
||||||
|
m_slider->setStepSize( step );
|
||||||
|
m_slider->setSnap( true );
|
||||||
|
m_slider->setValue( value );
|
||||||
|
|
||||||
|
m_valueLabel = new QskTextLabel( this );
|
||||||
|
m_valueLabel->setAlignment( Qt::AlignLeft | Qt::AlignVCenter );
|
||||||
|
updateLabel( value );
|
||||||
|
|
||||||
|
const QFontMetricsF fm( m_valueLabel->font() );
|
||||||
|
m_valueLabel->setFixedWidth( fm.horizontalAdvance( "-100" ) );
|
||||||
|
|
||||||
|
connect( m_slider, &QskSlider::valueChanged, this, &Slider::updateLabel );
|
||||||
|
connect( m_slider, &QskSlider::valueChanged, this, &Slider::valueChanged );
|
||||||
|
}
|
||||||
|
|
||||||
|
void Slider::updateLabel( qreal value )
|
||||||
|
{
|
||||||
|
m_valueLabel->setText( QString::number( value ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
void Slider::setValue( qreal value )
|
||||||
|
{
|
||||||
|
m_slider->setValue( value );
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "moc_Slider.cpp"
|
||||||
|
|
@ -0,0 +1,37 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* QSkinny - Copyright (C) 2016 Uwe Rathmann
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QskLinearBox.h>
|
||||||
|
|
||||||
|
class QskSlider;
|
||||||
|
class QskTextLabel;
|
||||||
|
|
||||||
|
class Slider : public QskLinearBox
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
using Inherited = QskLinearBox;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Slider( const QString&, qreal min, qreal max, qreal step,
|
||||||
|
qreal value, QQuickItem* parent = nullptr );
|
||||||
|
|
||||||
|
qreal value() const;
|
||||||
|
|
||||||
|
Q_SIGNALS:
|
||||||
|
void valueChanged( qreal );
|
||||||
|
|
||||||
|
public Q_SLOTS:
|
||||||
|
void setValue( qreal );
|
||||||
|
|
||||||
|
private:
|
||||||
|
void updateLabel( qreal );
|
||||||
|
|
||||||
|
QskTextLabel* m_label = nullptr;
|
||||||
|
QskSlider* m_slider = nullptr;
|
||||||
|
QskTextLabel* m_valueLabel = nullptr;
|
||||||
|
};
|
||||||
|
|
@ -3,129 +3,31 @@
|
||||||
* SPDX-License-Identifier: BSD-3-Clause
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
#include "ShadowedBox.h"
|
#include "BoxPage.h"
|
||||||
|
#include "ArcPage.h"
|
||||||
|
|
||||||
#include <QskObjectCounter.h>
|
#include <QskObjectCounter.h>
|
||||||
#include <QskWindow.h>
|
#include <QskWindow.h>
|
||||||
#include <QskGridBox.h>
|
#include <QskTabView.h>
|
||||||
#include <QskSlider.h>
|
#include <QskTabBar.h>
|
||||||
#include <QskTextLabel.h>
|
|
||||||
#include <QskRgbValue.h>
|
|
||||||
|
|
||||||
#include <SkinnyShortcut.h>
|
#include <SkinnyShortcut.h>
|
||||||
#include <QGuiApplication>
|
#include <QGuiApplication>
|
||||||
#include <QFontMetrics>
|
|
||||||
|
|
||||||
class BoxPanel : public QskBox
|
namespace
|
||||||
|
{
|
||||||
|
class TabView : public QskTabView
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
BoxPanel( QQuickItem* parent = nullptr )
|
TabView()
|
||||||
: QskBox( parent )
|
|
||||||
{
|
{
|
||||||
setAutoLayoutChildren( true );
|
//setTabBarEdge( Qt::LeftEdge );
|
||||||
setPadding( 60 );
|
|
||||||
|
|
||||||
setPanel( true );
|
addTab( "Arc Shadow", new ArcPage() );
|
||||||
setGradientHint( QskBox::Panel, QGradient::SnowAgain );
|
addTab( "Box Shadow", new BoxPage() );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class Slider : public QskSlider
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Slider( qreal min, qreal max, qreal step, qreal value, QQuickItem* parent = nullptr )
|
|
||||||
: QskSlider( parent )
|
|
||||||
{
|
|
||||||
setBoundaries( min, max );
|
|
||||||
setStepSize( step );
|
|
||||||
setSnap( true );
|
|
||||||
setValue( value );
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
class ValueLabel : public QskTextLabel
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ValueLabel( QQuickItem* parent = nullptr )
|
|
||||||
: QskTextLabel( parent )
|
|
||||||
{
|
|
||||||
setFixedWidth( QFontMetrics( font() ).horizontalAdvance( "-100" ) );
|
|
||||||
setAlignment( Qt::AlignLeft | Qt::AlignVCenter );
|
|
||||||
}
|
|
||||||
|
|
||||||
void setValue( qreal value )
|
|
||||||
{
|
|
||||||
setText( QString::number( value ) );
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class GridBox : public QskGridBox
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
GridBox( QQuickItem* parent = nullptr )
|
|
||||||
: QskGridBox( parent )
|
|
||||||
{
|
|
||||||
setPanel( true );
|
|
||||||
setPadding( 5 );
|
|
||||||
setColumnStretchFactor( 1, 1 );
|
|
||||||
|
|
||||||
auto sliderX = new Slider( -50, 50, 1, 10 );
|
|
||||||
auto sliderY = new Slider( -50, 50, 1, 10 );
|
|
||||||
auto sliderSpread = new Slider( 0, 50, 1, 0 );
|
|
||||||
auto sliderBlur = new Slider( 0, 50, 1, 10 );
|
|
||||||
auto sliderOpacity = new Slider( 0, 1, 0.01, 1 );
|
|
||||||
|
|
||||||
auto panel = new BoxPanel();
|
|
||||||
|
|
||||||
int row = 0;
|
|
||||||
|
|
||||||
addSlider( row++, "Offset X", sliderX );
|
|
||||||
addSlider( row++, "Offset Y", sliderY );
|
|
||||||
addSlider( row++, "Spread Radius", sliderSpread );
|
|
||||||
addSlider( row++, "Blur Radius", sliderBlur );
|
|
||||||
addSlider( row++, "Opacity", sliderOpacity );
|
|
||||||
|
|
||||||
addItem( panel, row, 0, -1, -1 );
|
|
||||||
|
|
||||||
auto box = new ShadowedBox( panel );
|
|
||||||
|
|
||||||
box->setOffsetX( sliderX->value() );
|
|
||||||
box->setOffsetY( sliderY->value() );
|
|
||||||
box->setSpreadRadius( sliderSpread->value() );
|
|
||||||
box->setBlurRadius( sliderBlur->value() );
|
|
||||||
box->setOpacity( sliderOpacity->value() );
|
|
||||||
|
|
||||||
connect( sliderX, &QskSlider::valueChanged,
|
|
||||||
box, &ShadowedBox::setOffsetX );
|
|
||||||
|
|
||||||
connect( sliderY, &QskSlider::valueChanged,
|
|
||||||
box, &ShadowedBox::setOffsetY );
|
|
||||||
|
|
||||||
connect( sliderSpread, &QskSlider::valueChanged,
|
|
||||||
box, &ShadowedBox::setSpreadRadius );
|
|
||||||
|
|
||||||
connect( sliderBlur, &QskSlider::valueChanged,
|
|
||||||
box, &ShadowedBox::setBlurRadius );
|
|
||||||
|
|
||||||
connect( sliderOpacity, &QskSlider::valueChanged,
|
|
||||||
box, &ShadowedBox::setOpacity );
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
void addSlider( int row, const QString& text, QskSlider* slider )
|
|
||||||
{
|
|
||||||
addItem( new QskTextLabel( text ), row, 0 );
|
|
||||||
addItem( slider, row, 1 );
|
|
||||||
|
|
||||||
auto label = new ValueLabel();
|
|
||||||
label->setValue( slider->value() );
|
|
||||||
|
|
||||||
addItem( label, row, 2 );
|
|
||||||
|
|
||||||
connect( slider, &QskSlider::valueChanged,
|
|
||||||
label, [label]( qreal value ) { label->setText( QString::number( value ) ); } );
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
int main( int argc, char* argv[] )
|
int main( int argc, char* argv[] )
|
||||||
{
|
{
|
||||||
|
|
@ -138,7 +40,7 @@ int main( int argc, char* argv[] )
|
||||||
SkinnyShortcut::enable( SkinnyShortcut::AllShortcuts );
|
SkinnyShortcut::enable( SkinnyShortcut::AllShortcuts );
|
||||||
|
|
||||||
QskWindow window;
|
QskWindow window;
|
||||||
window.addItem( new GridBox() );
|
window.addItem( new TabView() );
|
||||||
window.resize( 600, 600 );
|
window.resize( 600, 600 );
|
||||||
window.show();
|
window.show();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -99,6 +99,7 @@ list(APPEND SOURCES
|
||||||
|
|
||||||
list(APPEND HEADERS
|
list(APPEND HEADERS
|
||||||
nodes/QskArcNode.h
|
nodes/QskArcNode.h
|
||||||
|
nodes/QskArcShadowNode.h
|
||||||
nodes/QskBasicLinesNode.h
|
nodes/QskBasicLinesNode.h
|
||||||
nodes/QskBoxNode.h
|
nodes/QskBoxNode.h
|
||||||
nodes/QskBoxClipNode.h
|
nodes/QskBoxClipNode.h
|
||||||
|
|
@ -138,6 +139,7 @@ list(APPEND PRIVATE_HEADERS
|
||||||
|
|
||||||
list(APPEND SOURCES
|
list(APPEND SOURCES
|
||||||
nodes/QskArcNode.cpp
|
nodes/QskArcNode.cpp
|
||||||
|
nodes/QskArcShadowNode.cpp
|
||||||
nodes/QskBasicLinesNode.cpp
|
nodes/QskBasicLinesNode.cpp
|
||||||
nodes/QskBoxNode.cpp
|
nodes/QskBoxNode.cpp
|
||||||
nodes/QskBoxClipNode.cpp
|
nodes/QskBoxClipNode.cpp
|
||||||
|
|
|
||||||
|
|
@ -231,7 +231,7 @@ static inline QSGNode* qskUpdateArcNode(
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
auto arcNode = QskSGNode::ensureNode< QskArcNode >( node );
|
auto arcNode = QskSGNode::ensureNode< QskArcNode >( node );
|
||||||
arcNode->setArcData( rect, metrics, borderWidth, borderColor, gradient );
|
arcNode->setArcData( rect, metrics, borderWidth, borderColor, gradient, {}, {} );
|
||||||
|
|
||||||
return arcNode;
|
return arcNode;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,15 +5,27 @@
|
||||||
|
|
||||||
#include "QskArcNode.h"
|
#include "QskArcNode.h"
|
||||||
#include "QskArcMetrics.h"
|
#include "QskArcMetrics.h"
|
||||||
|
#include "QskArcShadowNode.h"
|
||||||
#include "QskMargins.h"
|
#include "QskMargins.h"
|
||||||
#include "QskGradient.h"
|
#include "QskGradient.h"
|
||||||
#include "QskShapeNode.h"
|
#include "QskShapeNode.h"
|
||||||
#include "QskStrokeNode.h"
|
#include "QskStrokeNode.h"
|
||||||
#include "QskSGNode.h"
|
#include "QskSGNode.h"
|
||||||
|
#include "QskShadowMetrics.h"
|
||||||
|
|
||||||
#include <qpen.h>
|
#include <qpen.h>
|
||||||
#include <qpainterpath.h>
|
#include <qpainterpath.h>
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
enum NodeRole
|
||||||
|
{
|
||||||
|
ShadowRole,
|
||||||
|
FillRole,
|
||||||
|
BorderRole
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
static inline QskGradient qskEffectiveGradient(
|
static inline QskGradient qskEffectiveGradient(
|
||||||
const QskGradient& gradient, const QskArcMetrics& metrics )
|
const QskGradient& gradient, const QskArcMetrics& metrics )
|
||||||
{
|
{
|
||||||
|
|
@ -54,6 +66,14 @@ static inline QRectF qskEffectiveRect(
|
||||||
return qskValidOrEmptyInnerRect( rect, QskMargins( 0.5 * borderWidth ) );
|
return qskValidOrEmptyInnerRect( rect, QskMargins( 0.5 * borderWidth ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void qskUpdateChildren( QSGNode* parentNode, quint8 role, QSGNode* node )
|
||||||
|
{
|
||||||
|
static const QVector< quint8 > roles = { ShadowRole, FillRole, BorderRole };
|
||||||
|
|
||||||
|
auto oldNode = QskSGNode::findChildNode( parentNode, role );
|
||||||
|
QskSGNode::replaceChildNode( roles, role, parentNode, oldNode, node );
|
||||||
|
}
|
||||||
|
|
||||||
QskArcNode::QskArcNode()
|
QskArcNode::QskArcNode()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
@ -65,20 +85,24 @@ QskArcNode::~QskArcNode()
|
||||||
void QskArcNode::setArcData( const QRectF& rect,
|
void QskArcNode::setArcData( const QRectF& rect,
|
||||||
const QskArcMetrics& arcMetrics, const QskGradient& fillGradient )
|
const QskArcMetrics& arcMetrics, const QskGradient& fillGradient )
|
||||||
{
|
{
|
||||||
setArcData( rect, arcMetrics, 0.0, QColor(), fillGradient );
|
setArcData( rect, arcMetrics, 0.0, QColor(), fillGradient, {}, {} );
|
||||||
}
|
}
|
||||||
|
|
||||||
void QskArcNode::setArcData( const QRectF& rect, const QskArcMetrics& arcMetrics,
|
void QskArcNode::setArcData( const QRectF& rect, const QskArcMetrics& arcMetrics,
|
||||||
qreal borderWidth, const QColor& borderColor, const QskGradient& fillGradient )
|
const qreal borderWidth, const QColor& borderColor, const QskGradient& fillGradient )
|
||||||
{
|
{
|
||||||
enum NodeRole
|
setArcData( rect, arcMetrics, borderWidth, borderColor, fillGradient, {}, {} );
|
||||||
{
|
}
|
||||||
FillRole,
|
|
||||||
BorderRole
|
|
||||||
};
|
|
||||||
|
|
||||||
const auto metrics = qskEffectiveMetrics( arcMetrics, rect );
|
void QskArcNode::setArcData( const QRectF& rect, const QskArcMetrics& arcMetrics,
|
||||||
const auto gradient = qskEffectiveGradient( fillGradient, metrics );
|
const qreal borderWidth, const QColor& borderColor, const QskGradient& fillGradient,
|
||||||
|
const QColor& shadowColor, const QskShadowMetrics& shadowMetrics )
|
||||||
|
{
|
||||||
|
const auto metricsArc = qskEffectiveMetrics( arcMetrics, rect );
|
||||||
|
const auto gradient = qskEffectiveGradient( fillGradient, metricsArc );
|
||||||
|
|
||||||
|
auto shadowNode = static_cast< QskArcShadowNode* >(
|
||||||
|
QskSGNode::findChildNode( this, ShadowRole ) );
|
||||||
|
|
||||||
auto fillNode = static_cast< QskShapeNode* >(
|
auto fillNode = static_cast< QskShapeNode* >(
|
||||||
QskSGNode::findChildNode( this, FillRole ) );
|
QskSGNode::findChildNode( this, FillRole ) );
|
||||||
|
|
@ -89,22 +113,52 @@ void QskArcNode::setArcData( const QRectF& rect, const QskArcMetrics& arcMetrics
|
||||||
const auto arcRect = qskEffectiveRect( rect, borderWidth );
|
const auto arcRect = qskEffectiveRect( rect, borderWidth );
|
||||||
if ( arcRect.isEmpty() )
|
if ( arcRect.isEmpty() )
|
||||||
{
|
{
|
||||||
|
delete shadowNode;
|
||||||
delete fillNode;
|
delete fillNode;
|
||||||
delete borderNode;
|
delete borderNode;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto path = metrics.painterPath( arcRect );
|
const auto isFillNodeVisible = gradient.isVisible() && !metricsArc.isNull();
|
||||||
|
const auto isStrokeNodeVisible = borderWidth > 0.0 && borderColor.alpha() > 0;
|
||||||
|
const auto isShadowNodeVisible = shadowColor.alpha() > 0.0 && isFillNodeVisible;
|
||||||
|
|
||||||
if ( gradient.isVisible() && !metrics.isNull() )
|
const auto path = metricsArc.painterPath( arcRect );
|
||||||
|
|
||||||
|
if ( isShadowNodeVisible )
|
||||||
|
{
|
||||||
|
if ( shadowNode == nullptr )
|
||||||
|
{
|
||||||
|
shadowNode = new QskArcShadowNode;
|
||||||
|
QskSGNode::setNodeRole( shadowNode, ShadowRole );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
The shader of the shadow node is for circular arcs and we have some
|
||||||
|
unwanted scaling issues for the spread/blur values when having ellipsoid
|
||||||
|
arcs. We might also want to add the spread value to the ends of the arc
|
||||||
|
and not only to its radius. TODO ...
|
||||||
|
*/
|
||||||
|
|
||||||
|
const auto sm = shadowMetrics.toAbsolute( arcRect.size() );
|
||||||
|
const auto shadowRect = sm.shadowRect( arcRect );
|
||||||
|
const auto spreadRadius = sm.spreadRadius() + 0.5 * metricsArc.thickness();
|
||||||
|
|
||||||
|
shadowNode->setShadowData( shadowRect, spreadRadius, sm.blurRadius(),
|
||||||
|
metricsArc.startAngle(), metricsArc.spanAngle(), shadowColor );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
delete shadowNode;
|
||||||
|
shadowNode = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( isFillNodeVisible )
|
||||||
{
|
{
|
||||||
if ( fillNode == nullptr )
|
if ( fillNode == nullptr )
|
||||||
{
|
{
|
||||||
fillNode = new QskShapeNode;
|
fillNode = new QskShapeNode;
|
||||||
QskSGNode::setNodeRole( fillNode, FillRole );
|
QskSGNode::setNodeRole( fillNode, FillRole );
|
||||||
|
|
||||||
prependChildNode( fillNode );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fillNode->updateNode( path, QTransform(), arcRect, gradient );
|
fillNode->updateNode( path, QTransform(), arcRect, gradient );
|
||||||
|
|
@ -112,16 +166,15 @@ void QskArcNode::setArcData( const QRectF& rect, const QskArcMetrics& arcMetrics
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
delete fillNode;
|
delete fillNode;
|
||||||
|
fillNode = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( borderWidth > 0.0 && borderColor.alpha() > 0 )
|
if ( isStrokeNodeVisible )
|
||||||
{
|
{
|
||||||
if ( borderNode == nullptr )
|
if ( borderNode == nullptr )
|
||||||
{
|
{
|
||||||
borderNode = new QskStrokeNode;
|
borderNode = new QskStrokeNode;
|
||||||
QskSGNode::setNodeRole( borderNode, BorderRole );
|
QskSGNode::setNodeRole( borderNode, BorderRole );
|
||||||
|
|
||||||
appendChildNode( borderNode );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QPen pen( borderColor, borderWidth );
|
QPen pen( borderColor, borderWidth );
|
||||||
|
|
@ -132,5 +185,10 @@ void QskArcNode::setArcData( const QRectF& rect, const QskArcMetrics& arcMetrics
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
delete borderNode;
|
delete borderNode;
|
||||||
|
borderNode = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
qskUpdateChildren(this, ShadowRole, shadowNode);
|
||||||
|
qskUpdateChildren(this, FillRole, fillNode);
|
||||||
|
qskUpdateChildren(this, BorderRole, borderNode);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
|
|
||||||
class QskArcMetrics;
|
class QskArcMetrics;
|
||||||
class QskGradient;
|
class QskGradient;
|
||||||
|
class QskShadowMetrics;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
For the moment a QPainterPath/QskShapeNode.
|
For the moment a QPainterPath/QskShapeNode.
|
||||||
|
|
@ -23,8 +24,13 @@ class QSK_EXPORT QskArcNode : public QskShapeNode
|
||||||
~QskArcNode() override;
|
~QskArcNode() override;
|
||||||
|
|
||||||
void setArcData( const QRectF&, const QskArcMetrics&, const QskGradient& );
|
void setArcData( const QRectF&, const QskArcMetrics&, const QskGradient& );
|
||||||
|
|
||||||
void setArcData( const QRectF&, const QskArcMetrics&,
|
void setArcData( const QRectF&, const QskArcMetrics&,
|
||||||
qreal borderWidth, const QColor& borderColor, const QskGradient& );
|
qreal borderWidth, const QColor& borderColor, const QskGradient& );
|
||||||
|
|
||||||
|
void setArcData( const QRectF&, const QskArcMetrics&,
|
||||||
|
qreal borderWidth, const QColor& borderColor, const QskGradient&,
|
||||||
|
const QColor& shadowColor, const QskShadowMetrics&);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,368 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* QSkinny - Copyright (C) 2016 Uwe Rathmann
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#include "QskArcShadowNode.h"
|
||||||
|
|
||||||
|
#include <qcolor.h>
|
||||||
|
#include <qsgmaterial.h>
|
||||||
|
#include <qsgmaterialshader.h>
|
||||||
|
#include <qmath.h>
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
QSK_QT_PRIVATE_BEGIN
|
||||||
|
#include <private/qsgnode_p.h>
|
||||||
|
QSK_QT_PRIVATE_END
|
||||||
|
|
||||||
|
// QSGMaterialRhiShader became QSGMaterialShader in Qt6
|
||||||
|
|
||||||
|
#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 )
|
||||||
|
#include <QSGMaterialRhiShader>
|
||||||
|
using RhiShader = QSGMaterialRhiShader;
|
||||||
|
#else
|
||||||
|
using RhiShader = QSGMaterialShader;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
class Material final : public QSGMaterial
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Material();
|
||||||
|
|
||||||
|
#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 )
|
||||||
|
QSGMaterialShader* createShader() const override;
|
||||||
|
#else
|
||||||
|
QSGMaterialShader* createShader( QSGRendererInterface::RenderMode ) const override;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
QSGMaterialType* type() const override;
|
||||||
|
int compare( const QSGMaterial* other ) const override;
|
||||||
|
|
||||||
|
QVector4D m_color { 0, 0, 0, 1 };
|
||||||
|
QVector4D m_arc = {};
|
||||||
|
|
||||||
|
float m_spreadRadius = 0.0f;
|
||||||
|
float m_blurRadius = 0.0f;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
class ShaderRhi final : public RhiShader
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ShaderRhi()
|
||||||
|
{
|
||||||
|
const QString root( ":/qskinny/shaders/" );
|
||||||
|
setShaderFileName( VertexStage, root + "arcshadow.vert.qsb" );
|
||||||
|
setShaderFileName( FragmentStage, root + "arcshadow.frag.qsb" );
|
||||||
|
}
|
||||||
|
|
||||||
|
bool updateUniformData( RenderState& state,
|
||||||
|
QSGMaterial* const newMaterial, QSGMaterial* const oldMaterial ) override
|
||||||
|
{
|
||||||
|
const auto matOld = static_cast< Material* >( oldMaterial );
|
||||||
|
const auto matNew = static_cast< Material* >( newMaterial );
|
||||||
|
|
||||||
|
Q_ASSERT( state.uniformData()->size() == 108 );
|
||||||
|
|
||||||
|
auto data = state.uniformData()->data();
|
||||||
|
bool changed = false;
|
||||||
|
|
||||||
|
if ( state.isMatrixDirty() )
|
||||||
|
{
|
||||||
|
const auto matrix = state.combinedMatrix();
|
||||||
|
memcpy( data + 0, matrix.constData(), 64 );
|
||||||
|
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( matOld == nullptr || matNew->m_color != matOld->m_color )
|
||||||
|
{
|
||||||
|
memcpy( data + 64, &matNew->m_color, 16 );
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( matOld == nullptr || matNew->m_arc != matOld->m_arc )
|
||||||
|
{
|
||||||
|
memcpy( data + 80, &matNew->m_arc, 16 );
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( matOld == nullptr || matNew->m_spreadRadius != matOld->m_spreadRadius )
|
||||||
|
{
|
||||||
|
memcpy( data + 96, &matNew->m_spreadRadius, 4 );
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( matOld == nullptr || matNew->m_blurRadius != matOld->m_blurRadius )
|
||||||
|
{
|
||||||
|
memcpy( data + 100, &matNew->m_blurRadius, 4 );
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( state.isOpacityDirty() )
|
||||||
|
{
|
||||||
|
const float opacity = state.opacity();
|
||||||
|
memcpy( data + 104, &opacity, 4 );
|
||||||
|
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return changed;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 )
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
// the old type of shader - specific for OpenGL
|
||||||
|
|
||||||
|
class ShaderGL final : public QSGMaterialShader
|
||||||
|
{
|
||||||
|
struct Uniforms
|
||||||
|
{
|
||||||
|
int matrix = -1;
|
||||||
|
int color = -1;
|
||||||
|
int arc = -1;
|
||||||
|
int spreadRadius = -1;
|
||||||
|
int blurRadius = -1;
|
||||||
|
int opacity = -1;
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
ShaderGL()
|
||||||
|
{
|
||||||
|
const QString root( ":/qskinny/shaders/" );
|
||||||
|
setShaderSourceFile( QOpenGLShader::Vertex, root + "arcshadow.vert" );
|
||||||
|
setShaderSourceFile( QOpenGLShader::Fragment, root + "arcshadow.frag" );
|
||||||
|
}
|
||||||
|
|
||||||
|
char const* const* attributeNames() const override
|
||||||
|
{
|
||||||
|
static char const* const names[] = { "in_vertex", "in_coord", nullptr };
|
||||||
|
return names;
|
||||||
|
}
|
||||||
|
|
||||||
|
void initialize() override
|
||||||
|
{
|
||||||
|
QSGMaterialShader::initialize();
|
||||||
|
|
||||||
|
const auto* const p = program();
|
||||||
|
|
||||||
|
id.matrix = p->uniformLocation( "matrix" );
|
||||||
|
id.color = p->uniformLocation( "color" );
|
||||||
|
id.arc = p->uniformLocation( "arc" );
|
||||||
|
id.spreadRadius = p->uniformLocation( "spreadRadius" );
|
||||||
|
id.blurRadius = p->uniformLocation( "blurRadius" );
|
||||||
|
id.opacity = p->uniformLocation( "opacity" );
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateState( const QSGMaterialShader::RenderState& state,
|
||||||
|
QSGMaterial* const newMaterial, QSGMaterial* const oldMaterial ) override
|
||||||
|
{
|
||||||
|
auto* const p = program();
|
||||||
|
|
||||||
|
if ( state.isMatrixDirty() )
|
||||||
|
{
|
||||||
|
p->setUniformValue( id.matrix, state.combinedMatrix() );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( state.isOpacityDirty() )
|
||||||
|
{
|
||||||
|
p->setUniformValue( id.opacity, state.opacity() );
|
||||||
|
}
|
||||||
|
|
||||||
|
auto updateMaterial = ( oldMaterial == nullptr ) ||
|
||||||
|
( newMaterial->compare( oldMaterial ) != 0 );
|
||||||
|
|
||||||
|
updateMaterial |= state.isCachedMaterialDataDirty();
|
||||||
|
|
||||||
|
if ( updateMaterial )
|
||||||
|
{
|
||||||
|
const auto* const material = static_cast< const Material* >( newMaterial );
|
||||||
|
|
||||||
|
p->setUniformValue( id.color, material->m_color );
|
||||||
|
p->setUniformValue( id.arc, material->m_arc );
|
||||||
|
p->setUniformValue( id.spreadRadius, material->m_spreadRadius );
|
||||||
|
p->setUniformValue( id.blurRadius, material->m_blurRadius );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Uniforms id;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
Material::Material()
|
||||||
|
{
|
||||||
|
setFlag( QSGMaterial::Blending, true );
|
||||||
|
#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 )
|
||||||
|
setFlag( QSGMaterial::SupportsRhiShader, true );
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 )
|
||||||
|
|
||||||
|
QSGMaterialShader* Material::createShader() const
|
||||||
|
{
|
||||||
|
if ( !( flags() & QSGMaterial::RhiShaderWanted ) )
|
||||||
|
return new ShaderGL();
|
||||||
|
|
||||||
|
return new ShaderRhi();
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
QSGMaterialShader* Material::createShader( QSGRendererInterface::RenderMode ) const
|
||||||
|
{
|
||||||
|
return new ShaderRhi();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
QSGMaterialType* Material::type() const
|
||||||
|
{
|
||||||
|
static QSGMaterialType staticType;
|
||||||
|
return &staticType;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Material::compare( const QSGMaterial* const other ) const
|
||||||
|
{
|
||||||
|
auto material = static_cast< const Material* >( other );
|
||||||
|
|
||||||
|
if ( ( material->m_color == m_color )
|
||||||
|
&& ( material->m_arc == m_arc )
|
||||||
|
&& qFuzzyCompare( material->m_spreadRadius, m_spreadRadius )
|
||||||
|
&& qFuzzyCompare( material->m_blurRadius, m_blurRadius ) )
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return QSGMaterial::compare( other );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class QskArcShadowNodePrivate final : public QSGGeometryNodePrivate
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
QskArcShadowNodePrivate()
|
||||||
|
: geometry( QSGGeometry::defaultAttributes_TexturedPoint2D(), 4 )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
QSGGeometry geometry;
|
||||||
|
Material material;
|
||||||
|
QRectF rect;
|
||||||
|
};
|
||||||
|
|
||||||
|
QskArcShadowNode::QskArcShadowNode()
|
||||||
|
: QSGGeometryNode( *new QskArcShadowNodePrivate )
|
||||||
|
{
|
||||||
|
Q_D( QskArcShadowNode );
|
||||||
|
|
||||||
|
setGeometry( &d->geometry );
|
||||||
|
setMaterial( &d->material );
|
||||||
|
|
||||||
|
d->geometry.setDrawingMode( QSGGeometry::DrawTriangleStrip );
|
||||||
|
d->material.setFlag( QSGMaterial::Blending );
|
||||||
|
}
|
||||||
|
|
||||||
|
QskArcShadowNode::~QskArcShadowNode() = default;
|
||||||
|
|
||||||
|
void QskArcShadowNode::setShadowData(
|
||||||
|
const QRectF& rect, qreal spreadRadius, qreal blurRadius,
|
||||||
|
qreal startAngle, qreal spanAngle, const QColor& color )
|
||||||
|
{
|
||||||
|
if ( qFuzzyIsNull( spanAngle ) || color.alpha() == 0 )
|
||||||
|
{
|
||||||
|
setBoundingRectangle( {} );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Q_D( QskArcShadowNode );
|
||||||
|
|
||||||
|
if ( d->rect != rect )
|
||||||
|
{
|
||||||
|
setBoundingRectangle( rect ); // bounding rectangle includig spread/blur
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto size = qMin( rect.width(), rect.height() );
|
||||||
|
|
||||||
|
{
|
||||||
|
#if 1
|
||||||
|
const auto a = color.alphaF();
|
||||||
|
const QVector4D c( color.redF() * a, color.greenF() * a, color.blueF() * a, a );
|
||||||
|
#else
|
||||||
|
const QVector4D c( color.redF(), color.greenF(), color.blueF(), color.alphaF() );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if ( d->material.m_color != c )
|
||||||
|
{
|
||||||
|
d->material.m_color = c;
|
||||||
|
markDirty( QSGNode::DirtyMaterial );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const float r = spreadRadius / size;
|
||||||
|
|
||||||
|
if ( d->material.m_spreadRadius != r )
|
||||||
|
{
|
||||||
|
d->material.m_spreadRadius = r;
|
||||||
|
markDirty( QSGNode::DirtyMaterial );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const float r = blurRadius / size;
|
||||||
|
|
||||||
|
if ( d->material.m_blurRadius != r )
|
||||||
|
{
|
||||||
|
d->material.m_blurRadius = r;
|
||||||
|
markDirty( QSGNode::DirtyMaterial );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
QVector4D arc( 0.0, 0.0, 1.0, 0.0 );
|
||||||
|
|
||||||
|
{
|
||||||
|
const auto a1 = qDegreesToRadians( startAngle + 0.5 * spanAngle );
|
||||||
|
const auto a2 = qDegreesToRadians( 0.5 * qAbs( spanAngle ) );
|
||||||
|
|
||||||
|
arc = QVector4D( ::cos( a1 ), ::sin( a1 ), ::cos( a2 ), ::sin( a2 ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( d->material.m_arc != arc )
|
||||||
|
{
|
||||||
|
d->material.m_arc = arc;
|
||||||
|
markDirty( QSGNode::DirtyMaterial );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QskArcShadowNode::setBoundingRectangle( const QRectF& rect )
|
||||||
|
{
|
||||||
|
Q_D( QskArcShadowNode );
|
||||||
|
|
||||||
|
if ( d->rect == rect )
|
||||||
|
return;
|
||||||
|
|
||||||
|
d->rect = rect;
|
||||||
|
|
||||||
|
QSGGeometry::updateTexturedRectGeometry(
|
||||||
|
&d->geometry, d->rect, { -0.5, -0.5, 1.0, 1.0 } );
|
||||||
|
d->geometry.markVertexDataDirty();
|
||||||
|
|
||||||
|
markDirty( QSGNode::DirtyGeometry );
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* QSkinny - Copyright (C) 2016 Uwe Rathmann
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef QSK_ARC_SHADOW_NODE_H
|
||||||
|
#define QSK_ARC_SHADOW_NODE_H
|
||||||
|
|
||||||
|
#include "QskGlobal.h"
|
||||||
|
#include <qsgnode.h>
|
||||||
|
|
||||||
|
class QskArcMetrics;
|
||||||
|
class QskShadowMetrics;
|
||||||
|
|
||||||
|
class QskArcShadowNodePrivate;
|
||||||
|
|
||||||
|
class QskArcShadowNode : public QSGGeometryNode
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
QskArcShadowNode();
|
||||||
|
~QskArcShadowNode() override;
|
||||||
|
|
||||||
|
void setShadowData( const QRectF&, qreal spreadRadius, qreal blurRadius,
|
||||||
|
qreal startAngle, qreal spanAngle, const QColor& );
|
||||||
|
|
||||||
|
private:
|
||||||
|
void setBoundingRectangle( const QRectF& );
|
||||||
|
|
||||||
|
Q_DECLARE_PRIVATE( QskArcShadowNode )
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -40,7 +40,7 @@ namespace
|
||||||
|
|
||||||
int compare( const QSGMaterial* other ) const override;
|
int compare( const QSGMaterial* other ) const override;
|
||||||
|
|
||||||
QVector2D m_aspect = QVector2D{ 1, 1 };
|
QVector2D m_aspectRatio = QVector2D{ 1, 1 };
|
||||||
QVector4D m_radius = QVector4D{ 0, 0, 0, 0 };
|
QVector4D m_radius = QVector4D{ 0, 0, 0, 0 };
|
||||||
QVector4D m_color = QVector4D{ 0, 0, 0, 1 };
|
QVector4D m_color = QVector4D{ 0, 0, 0, 1 };
|
||||||
float m_blurExtent = 0.0;
|
float m_blurExtent = 0.0;
|
||||||
|
|
@ -91,9 +91,9 @@ namespace
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( matOld == nullptr || matNew->m_aspect != matOld->m_aspect )
|
if ( matOld == nullptr || matNew->m_aspectRatio != matOld->m_aspectRatio )
|
||||||
{
|
{
|
||||||
memcpy( data + 96, &matNew->m_aspect, 8 );
|
memcpy( data + 96, &matNew->m_aspectRatio, 8 );
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -146,7 +146,7 @@ namespace
|
||||||
auto p = program();
|
auto p = program();
|
||||||
|
|
||||||
m_matrixId = p->uniformLocation( "matrix" );
|
m_matrixId = p->uniformLocation( "matrix" );
|
||||||
m_aspectId = p->uniformLocation( "aspect" );
|
m_aspectRatioId = p->uniformLocation( "aspectRatio" );
|
||||||
m_opacityId = p->uniformLocation( "opacity" );
|
m_opacityId = p->uniformLocation( "opacity" );
|
||||||
m_blurExtentId = p->uniformLocation( "blurExtent" );
|
m_blurExtentId = p->uniformLocation( "blurExtent" );
|
||||||
m_radiusId = p->uniformLocation( "radius" );
|
m_radiusId = p->uniformLocation( "radius" );
|
||||||
|
|
@ -173,7 +173,7 @@ namespace
|
||||||
{
|
{
|
||||||
auto material = static_cast< const Material* >( newMaterial );
|
auto material = static_cast< const Material* >( newMaterial );
|
||||||
|
|
||||||
p->setUniformValue( m_aspectId, material->m_aspect );
|
p->setUniformValue( m_aspectRatioId, material->m_aspectRatio );
|
||||||
p->setUniformValue( m_blurExtentId, material->m_blurExtent);
|
p->setUniformValue( m_blurExtentId, material->m_blurExtent);
|
||||||
p->setUniformValue( m_radiusId, material->m_radius );
|
p->setUniformValue( m_radiusId, material->m_radius );
|
||||||
p->setUniformValue( m_colorId, material->m_color );
|
p->setUniformValue( m_colorId, material->m_color );
|
||||||
|
|
@ -183,7 +183,7 @@ namespace
|
||||||
private:
|
private:
|
||||||
int m_matrixId = -1;
|
int m_matrixId = -1;
|
||||||
int m_opacityId = -1;
|
int m_opacityId = -1;
|
||||||
int m_aspectId = -1;
|
int m_aspectRatioId = -1;
|
||||||
int m_blurExtentId = -1;
|
int m_blurExtentId = -1;
|
||||||
int m_radiusId = -1;
|
int m_radiusId = -1;
|
||||||
int m_colorId = -1;
|
int m_colorId = -1;
|
||||||
|
|
@ -231,7 +231,7 @@ int Material::compare( const QSGMaterial* other ) const
|
||||||
auto material = static_cast< const Material* >( other );
|
auto material = static_cast< const Material* >( other );
|
||||||
|
|
||||||
if ( ( material->m_color == m_color )
|
if ( ( material->m_color == m_color )
|
||||||
&& ( material->m_aspect == m_aspect )
|
&& ( material->m_aspectRatio == m_aspectRatio )
|
||||||
&& qFuzzyCompare(material->m_blurExtent, m_blurExtent)
|
&& qFuzzyCompare(material->m_blurExtent, m_blurExtent)
|
||||||
&& qFuzzyCompare(material->m_radius, m_radius) )
|
&& qFuzzyCompare(material->m_radius, m_radius) )
|
||||||
{
|
{
|
||||||
|
|
@ -284,16 +284,16 @@ void QskBoxShadowNode::setShadowData(
|
||||||
d->geometry.markVertexDataDirty();
|
d->geometry.markVertexDataDirty();
|
||||||
markDirty( QSGNode::DirtyGeometry );
|
markDirty( QSGNode::DirtyGeometry );
|
||||||
|
|
||||||
QVector2D aspect( 1.0, 1.0 );
|
QVector2D aspectRatio( 1.0, 1.0 );
|
||||||
|
|
||||||
if ( rect.width() >= rect.height() )
|
if ( rect.width() >= rect.height() )
|
||||||
aspect.setX( rect.width() / rect.height() );
|
aspectRatio.setX( rect.width() / rect.height() );
|
||||||
else
|
else
|
||||||
aspect.setY( rect.height() / rect.width() );
|
aspectRatio.setY( rect.height() / rect.width() );
|
||||||
|
|
||||||
if ( d->material.m_aspect != aspect )
|
if ( d->material.m_aspectRatio != aspectRatio )
|
||||||
{
|
{
|
||||||
d->material.m_aspect = aspect;
|
d->material.m_aspectRatio = aspectRatio;
|
||||||
markDirty( QSGNode::DirtyMaterial );
|
markDirty( QSGNode::DirtyMaterial );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,11 @@
|
||||||
<RCC version="1.0">
|
<RCC version="1.0">
|
||||||
<qresource prefix="/qskinny/">
|
<qresource prefix="/qskinny/">
|
||||||
|
|
||||||
|
<file>shaders/arcshadow.frag</file>
|
||||||
|
<file>shaders/arcshadow.vert</file>
|
||||||
|
<file>shaders/arcshadow.frag.qsb</file>
|
||||||
|
<file>shaders/arcshadow.vert.qsb</file>
|
||||||
|
|
||||||
<file>shaders/boxshadow.vert.qsb</file>
|
<file>shaders/boxshadow.vert.qsb</file>
|
||||||
<file>shaders/boxshadow.frag.qsb</file>
|
<file>shaders/boxshadow.frag.qsb</file>
|
||||||
<file>shaders/boxshadow.vert</file>
|
<file>shaders/boxshadow.vert</file>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,46 @@
|
||||||
|
#version 440
|
||||||
|
|
||||||
|
layout( location = 0 ) in vec2 coord;
|
||||||
|
layout( location = 0 ) out vec4 fragColor;
|
||||||
|
|
||||||
|
layout( std140, binding = 0 ) uniform buf
|
||||||
|
{
|
||||||
|
mat4 matrix;
|
||||||
|
vec4 color;
|
||||||
|
|
||||||
|
/*
|
||||||
|
arc.xy: cos/sin of the angle of the midpoint
|
||||||
|
arc.zw: cos/sin of the angle between midpoint/endpoint
|
||||||
|
*/
|
||||||
|
vec4 arc;
|
||||||
|
|
||||||
|
float spreadRadius;
|
||||||
|
float blurRadius;
|
||||||
|
|
||||||
|
float opacity;
|
||||||
|
} ubuf;
|
||||||
|
|
||||||
|
mat2 rotation( vec2 v ) { return mat2( v.x, -v.y, v.y, v.x ); }
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
float radius = 0.5 - ubuf.blurRadius - ubuf.spreadRadius;
|
||||||
|
|
||||||
|
float dist = abs( length( coord ) - radius ) - ubuf.spreadRadius;
|
||||||
|
|
||||||
|
if ( ( ubuf.arc.z ) < 1.0 && ( dist < 1.0 ) )
|
||||||
|
{
|
||||||
|
vec2 v = coord * rotation( ubuf.arc.xy ); // x-axial symmetric
|
||||||
|
v.y = abs( v.y );
|
||||||
|
|
||||||
|
v *= rotation ( ubuf.arc.wz ); // end point to 90°
|
||||||
|
if ( v.x < 0.0 )
|
||||||
|
{
|
||||||
|
v.y = max( 0.0, abs( v.y - radius ) - ubuf.spreadRadius );
|
||||||
|
dist = max( dist, length( v ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float a = 1.0 - smoothstep( 0.0, ubuf.blurRadius, dist );
|
||||||
|
fragColor = ubuf.color * a * ubuf.opacity;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
#version 440
|
||||||
|
|
||||||
|
layout( location = 0 ) in vec4 in_vertex;
|
||||||
|
layout( location = 1 ) in vec2 in_coord;
|
||||||
|
layout( location = 0 ) out vec2 coord;
|
||||||
|
|
||||||
|
layout( std140, binding = 0 ) uniform buf
|
||||||
|
{
|
||||||
|
mat4 matrix;
|
||||||
|
vec4 color;
|
||||||
|
vec4 arc;
|
||||||
|
float spreadRadius;
|
||||||
|
float blurRadius;
|
||||||
|
float opacity;
|
||||||
|
} ubuf;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
coord = in_coord;
|
||||||
|
gl_Position = ubuf.matrix * in_vertex;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,37 @@
|
||||||
|
varying lowp vec2 coord;
|
||||||
|
|
||||||
|
uniform lowp vec4 color;
|
||||||
|
uniform lowp float spreadRadius;
|
||||||
|
uniform lowp float blurRadius;
|
||||||
|
uniform lowp float opacity;
|
||||||
|
|
||||||
|
/*
|
||||||
|
arc.xy: cos/sin of the angle of the midpoint
|
||||||
|
arc.zw: cos/sin of the angle between midpoint/endpoint
|
||||||
|
*/
|
||||||
|
uniform lowp vec4 arc;
|
||||||
|
|
||||||
|
mat2 rotation( vec2 v ) { return mat2( v.x, -v.y, v.y, v.x ); }
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
float radius = 0.5 - blurRadius - spreadRadius;
|
||||||
|
|
||||||
|
float dist = abs( length( coord ) - radius ) - spreadRadius;
|
||||||
|
|
||||||
|
if ( ( arc.z < 1.0 ) && ( dist < 1.0 ) )
|
||||||
|
{
|
||||||
|
vec2 v = coord * rotation( arc.xy ); // x-axial symmetric
|
||||||
|
v.y = abs( v.y );
|
||||||
|
|
||||||
|
v *= rotation( arc.wz ); // end point at 90°
|
||||||
|
if ( v.x < 0.0 )
|
||||||
|
{
|
||||||
|
v.y = max( 0.0, abs( v.y - radius ) - spreadRadius );
|
||||||
|
dist = max( dist, length( v ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float a = 1.0 - smoothstep( 0.0, blurRadius, dist );
|
||||||
|
gl_FragColor = color * a * opacity;
|
||||||
|
}
|
||||||
Binary file not shown.
|
|
@ -0,0 +1,12 @@
|
||||||
|
uniform highp mat4 matrix;
|
||||||
|
|
||||||
|
attribute highp vec4 in_vertex;
|
||||||
|
attribute mediump vec2 in_coord;
|
||||||
|
|
||||||
|
varying mediump vec2 coord;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
coord = in_coord;
|
||||||
|
gl_Position = matrix * in_vertex;
|
||||||
|
}
|
||||||
Binary file not shown.
|
|
@ -0,0 +1,10 @@
|
||||||
|
#! /bin/sh
|
||||||
|
|
||||||
|
function qsbcompile {
|
||||||
|
qsbfile=`echo $1 | sed 's/-vulkan//'`
|
||||||
|
qsb --glsl 100es,120,150 --hlsl 50 --msl 12 -b -o ${qsbfile}.qsb $1
|
||||||
|
# qsb --qt6 -b -o ${qsbfile}.qsb $1
|
||||||
|
}
|
||||||
|
|
||||||
|
qsbcompile arcshadow-vulkan.vert
|
||||||
|
qsbcompile arcshadow-vulkan.frag
|
||||||
|
|
@ -8,7 +8,7 @@ layout( std140, binding = 0 ) uniform buf
|
||||||
mat4 matrix;
|
mat4 matrix;
|
||||||
vec4 color;
|
vec4 color;
|
||||||
vec4 radius;
|
vec4 radius;
|
||||||
vec2 aspect;
|
vec2 aspectRatio;
|
||||||
float blurExtent;
|
float blurExtent;
|
||||||
float opacity;
|
float opacity;
|
||||||
} ubuf;
|
} ubuf;
|
||||||
|
|
@ -25,25 +25,21 @@ void main()
|
||||||
{
|
{
|
||||||
vec4 col = vec4(0.0);
|
vec4 col = vec4(0.0);
|
||||||
|
|
||||||
if ( ubuf.opacity > 0.0 )
|
|
||||||
{
|
|
||||||
const float minRadius = 0.05;
|
|
||||||
|
|
||||||
float e2 = 0.5 * ubuf.blurExtent;
|
float e2 = 0.5 * ubuf.blurExtent;
|
||||||
float r = 2.0 * effectiveRadius( ubuf.radius, coord );
|
float r = 2.0 * effectiveRadius( ubuf.radius, coord );
|
||||||
|
|
||||||
|
const float minRadius = 0.05;
|
||||||
float f = minRadius / max( r, minRadius );
|
float f = minRadius / max( r, minRadius );
|
||||||
|
|
||||||
r += e2 * f;
|
r += e2 * f;
|
||||||
|
|
||||||
vec2 d = r + ubuf.blurExtent - ubuf.aspect * ( 1.0 - abs( 2.0 * coord ) );
|
vec2 d = r + ubuf.blurExtent - ubuf.aspectRatio * ( 1.0 - abs( 2.0 * coord ) );
|
||||||
float l = min( max(d.x, d.y), 0.0) + length( max(d, 0.0) );
|
float l = min( max(d.x, d.y), 0.0) + length( max(d, 0.0) );
|
||||||
|
|
||||||
float shadow = l - r;
|
float shadow = l - r;
|
||||||
|
|
||||||
float v = smoothstep( -e2, e2, shadow );
|
float v = smoothstep( -e2, e2, shadow );
|
||||||
col = mix( ubuf.color, vec4(0.0), v ) * ubuf.opacity;
|
col = mix( ubuf.color, vec4(0.0), v ) * ubuf.opacity;
|
||||||
}
|
|
||||||
|
|
||||||
fragColor = col;
|
fragColor = col;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ layout( std140, binding = 0 ) uniform buf
|
||||||
mat4 matrix;
|
mat4 matrix;
|
||||||
vec4 color;
|
vec4 color;
|
||||||
vec4 radius;
|
vec4 radius;
|
||||||
vec2 aspect;
|
vec2 aspectRatio;
|
||||||
float blurExtent;
|
float blurExtent;
|
||||||
float opacity;
|
float opacity;
|
||||||
} ubuf;
|
} ubuf;
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ uniform lowp float opacity;
|
||||||
uniform lowp float blurExtent;
|
uniform lowp float blurExtent;
|
||||||
uniform lowp vec4 radius;
|
uniform lowp vec4 radius;
|
||||||
uniform lowp vec4 color;
|
uniform lowp vec4 color;
|
||||||
uniform lowp vec2 aspect;
|
uniform lowp vec2 aspectRatio;
|
||||||
|
|
||||||
varying lowp vec2 coord;
|
varying lowp vec2 coord;
|
||||||
|
|
||||||
|
|
@ -18,25 +18,19 @@ void main()
|
||||||
{
|
{
|
||||||
lowp vec4 col = vec4(0.0);
|
lowp vec4 col = vec4(0.0);
|
||||||
|
|
||||||
if ( opacity > 0.0 )
|
|
||||||
{
|
|
||||||
const lowp float minRadius = 0.05;
|
|
||||||
|
|
||||||
lowp float e2 = 0.5 * blurExtent;
|
lowp float e2 = 0.5 * blurExtent;
|
||||||
lowp float r = 2.0 * effectiveRadius( radius, coord );
|
lowp float r = 2.0 * effectiveRadius( radius, coord );
|
||||||
|
|
||||||
lowp float f = minRadius / max( r, minRadius );
|
const lowp float minRadius = 0.05;
|
||||||
|
r += e2 * ( minRadius / max( r, minRadius ) );
|
||||||
|
|
||||||
r += e2 * f;
|
lowp vec2 d = r + blurExtent - aspectRatio * ( 1.0 - abs( 2.0 * coord ) );
|
||||||
|
|
||||||
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 l = min( max(d.x, d.y), 0.0) + length( max(d, 0.0) );
|
||||||
|
|
||||||
lowp float shadow = l - r;
|
lowp float shadow = l - r;
|
||||||
|
|
||||||
lowp float v = smoothstep( -e2, e2, shadow );
|
lowp float v = smoothstep( -e2, e2, shadow );
|
||||||
col = mix( color, vec4(0.0), v ) * opacity;
|
col = mix( color, vec4(0.0), v ) * opacity;
|
||||||
}
|
|
||||||
|
|
||||||
gl_FragColor = col;
|
gl_FragColor = col;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Binary file not shown.
Binary file not shown.
|
|
@ -6,6 +6,9 @@ function qsbcompile {
|
||||||
# qsb --qt6 -b -o ${qsbfile}.qsb $1
|
# qsb --qt6 -b -o ${qsbfile}.qsb $1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
qsbcompile arcshadow-vulkan.vert
|
||||||
|
qsbcompile arcshadow-vulkan.frag
|
||||||
|
|
||||||
qsbcompile boxshadow-vulkan.vert
|
qsbcompile boxshadow-vulkan.vert
|
||||||
qsbcompile boxshadow-vulkan.frag
|
qsbcompile boxshadow-vulkan.frag
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue