Merge branch 'master' into features/effectnode
This commit is contained in:
commit
d397e4f26a
|
@ -0,0 +1 @@
|
|||
github: [uwerat]
|
|
@ -35,9 +35,11 @@ It might support all versions Qt >= 5.15, but you can rely on:
|
|||
- current long term supported ( LTS ) version of Qt ( at the moment Qt 6.5.x )
|
||||
- current version of Qt
|
||||
|
||||
On debian bullseye these packages need to be installed for Qt5: `build-essential
|
||||
qtbase5-dev qtbase5-private-dev qtdeclarative5-dev qtdeclarative5-private-dev libqt5svg5-dev`.
|
||||
For Qt6 you need the corresponding ones.
|
||||
On Debian these packages need to be installed for Qt6: `build-essential cmake
|
||||
qtbase6-dev qtbase6-private-dev qtdeclarative6-dev qtdeclarative6-private-dev libqt6svg-dev qt6-shadertools`
|
||||
For Qt5 you need: `build-essential cmake
|
||||
qtbase5-dev qtbase5-private-dev qtdeclarative5-dev qtdeclarative5-private-dev libqt5svg-dev`.
|
||||
|
||||
|
||||
> Optional: When enabling the `hunspell` feature the following package needs to be installed: `libhunspell-dev`
|
||||
|
||||
|
|
|
@ -5,12 +5,20 @@
|
|||
|
||||
macro(qsk_setup_Qt)
|
||||
|
||||
# Often users have several Qt installations on their system and
|
||||
# need to be able to explicitly the one to be used. Let's see if
|
||||
# standard cmake features are good enough or if we need to introduce
|
||||
# something sort of additional option. TODO ...
|
||||
# Use QSK_QT_VERSION specified with baseline 5.15
|
||||
# otherwise fallback to latest known supported Qt version gte 5.15
|
||||
# set vars for correct alpha descending sort order and direction (ex. Qt6, Qt5)
|
||||
if ( NOT QSK_QT_VERSION ) # QSK_QT_VERSION=Qt5
|
||||
set(QSK_QT_VERSION Qt6 Qt5)
|
||||
set(CMAKE_FIND_PACKAGE_SORT_ORDER NAME)
|
||||
set(CMAKE_FIND_PACKAGE_SORT_DIRECTION DEC)
|
||||
endif()
|
||||
find_package(QT "5.15" NAMES ${QSK_QT_VERSION} REQUIRED COMPONENTS Quick)
|
||||
|
||||
find_package(QT "5.15" NAMES Qt6 Qt5 REQUIRED COMPONENTS Quick)
|
||||
if(QT_VERSION_MAJOR VERSION_GREATER_EQUAL 6)
|
||||
# we need the qsb tool for Qt6
|
||||
find_package(Qt6 REQUIRED COMPONENTS ShaderTools)
|
||||
endif()
|
||||
|
||||
if ( QT_FOUND )
|
||||
|
||||
|
|
|
@ -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
|
||||
############################################################################
|
||||
|
||||
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 )
|
||||
: QskBox( true, parentItem )
|
||||
{
|
||||
QColor c( Qt::darkRed );
|
||||
#if 0
|
||||
c.setAlpha( 100 );
|
||||
#endif
|
||||
|
||||
setGradientHint( Panel, c );
|
||||
setGradientHint( Panel, Qt::darkRed );
|
||||
setBoxShapeHint( Panel, QskBoxShapeMetrics( 40, 0, 15, 0 ) );
|
||||
|
||||
setBoxBorderMetricsHint( Panel, 0 );
|
||||
|
||||
#if 0
|
||||
setBoxBorderMetricsHint( Panel, 10 );
|
||||
setBoxBorderColorsHint( Panel, Qt::blue );
|
||||
#endif
|
||||
|
||||
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
|
||||
*****************************************************************************/
|
||||
|
||||
#include "ShadowedBox.h"
|
||||
#include "BoxPage.h"
|
||||
#include "ArcPage.h"
|
||||
|
||||
#include <QskObjectCounter.h>
|
||||
#include <QskWindow.h>
|
||||
#include <QskGridBox.h>
|
||||
#include <QskSlider.h>
|
||||
#include <QskTextLabel.h>
|
||||
#include <QskRgbValue.h>
|
||||
#include <QskTabView.h>
|
||||
#include <QskTabBar.h>
|
||||
|
||||
#include <SkinnyShortcut.h>
|
||||
#include <QGuiApplication>
|
||||
#include <QFontMetrics>
|
||||
|
||||
class BoxPanel : public QskBox
|
||||
namespace
|
||||
{
|
||||
public:
|
||||
BoxPanel( QQuickItem* parent = nullptr )
|
||||
: QskBox( parent )
|
||||
class TabView : public QskTabView
|
||||
{
|
||||
setAutoLayoutChildren( true );
|
||||
setPadding( 60 );
|
||||
public:
|
||||
TabView()
|
||||
{
|
||||
//setTabBarEdge( Qt::LeftEdge );
|
||||
|
||||
setPanel( true );
|
||||
setGradientHint( QskBox::Panel, QGradient::SnowAgain );
|
||||
}
|
||||
};
|
||||
|
||||
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 ) ); } );
|
||||
}
|
||||
};
|
||||
addTab( "Arc Shadow", new ArcPage() );
|
||||
addTab( "Box Shadow", new BoxPage() );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
int main( int argc, char* argv[] )
|
||||
{
|
||||
|
@ -138,7 +40,7 @@ int main( int argc, char* argv[] )
|
|||
SkinnyShortcut::enable( SkinnyShortcut::AllShortcuts );
|
||||
|
||||
QskWindow window;
|
||||
window.addItem( new GridBox() );
|
||||
window.addItem( new TabView() );
|
||||
window.resize( 600, 600 );
|
||||
window.show();
|
||||
|
||||
|
|
|
@ -99,6 +99,7 @@ list(APPEND SOURCES
|
|||
|
||||
list(APPEND HEADERS
|
||||
nodes/QskArcNode.h
|
||||
nodes/QskArcShadowNode.h
|
||||
nodes/QskBasicLinesNode.h
|
||||
nodes/QskBoxNode.h
|
||||
nodes/QskBoxClipNode.h
|
||||
|
@ -138,6 +139,7 @@ list(APPEND PRIVATE_HEADERS
|
|||
|
||||
list(APPEND SOURCES
|
||||
nodes/QskArcNode.cpp
|
||||
nodes/QskArcShadowNode.cpp
|
||||
nodes/QskBasicLinesNode.cpp
|
||||
nodes/QskBoxNode.cpp
|
||||
nodes/QskBoxClipNode.cpp
|
||||
|
@ -171,7 +173,9 @@ list(APPEND SOURCES
|
|||
nodes/QskVertex.cpp
|
||||
)
|
||||
|
||||
qt_add_resources(SOURCES nodes/shaders.qrc)
|
||||
if (QT_VERSION_MAJOR VERSION_LESS 6)
|
||||
qt_add_resources(SOURCES nodes/shaders.qrc)
|
||||
endif()
|
||||
|
||||
list(APPEND HEADERS
|
||||
controls/QskAbstractButton.h
|
||||
|
@ -471,6 +475,49 @@ if(BUILD_QSKDLL)
|
|||
set_target_properties(${target} PROPERTIES DEFINE_SYMBOL QSK_MAKEDLL)
|
||||
endif()
|
||||
|
||||
if (QT_VERSION_MAJOR VERSION_GREATER_EQUAL 6)
|
||||
|
||||
qt6_add_shaders(${target} "qskshaders"
|
||||
|
||||
BATCHABLE
|
||||
PRECOMPILE
|
||||
|
||||
#OPTIMIZED
|
||||
QUIET
|
||||
|
||||
PREFIX
|
||||
"/qskinny/shaders"
|
||||
|
||||
FILES
|
||||
nodes/shaders/arcshadow-vulkan.vert
|
||||
nodes/shaders/arcshadow-vulkan.frag
|
||||
nodes/shaders/boxshadow-vulkan.vert
|
||||
nodes/shaders/boxshadow-vulkan.frag
|
||||
nodes/shaders/crisplines-vulkan.vert
|
||||
nodes/shaders/crisplines-vulkan.frag
|
||||
nodes/shaders/gradientconic-vulkan.vert
|
||||
nodes/shaders/gradientconic-vulkan.frag
|
||||
nodes/shaders/gradientlinear-vulkan.vert
|
||||
nodes/shaders/gradientlinear-vulkan.frag
|
||||
nodes/shaders/gradientradial-vulkan.vert
|
||||
nodes/shaders/gradientradial-vulkan.frag
|
||||
|
||||
OUTPUTS
|
||||
arcshadow.vert.qsb
|
||||
arcshadow.frag.qsb
|
||||
boxshadow.vert.qsb
|
||||
boxshadow.frag.qsb
|
||||
crisplines.vert.qsb
|
||||
crisplines.frag.qsb
|
||||
gradientconic.vert.qsb
|
||||
gradientconic.frag.qsb
|
||||
gradientlinear.vert.qsb
|
||||
gradientlinear.frag.qsb
|
||||
gradientradial.vert.qsb
|
||||
gradientradial.frag.qsb
|
||||
)
|
||||
endif()
|
||||
|
||||
target_include_directories(${target} PUBLIC
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/common>
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/controls>
|
||||
|
|
|
@ -273,6 +273,25 @@ QskGradientStops qskInterpolatedGradientStops(
|
|||
return qskInterpolatedStops( from, to, ratio );
|
||||
}
|
||||
|
||||
QColor qskInterpolatedColorAt( const QskGradientStops& stops, qreal pos ) noexcept
|
||||
{
|
||||
if ( stops.isEmpty() )
|
||||
return QColor();
|
||||
|
||||
pos = qBound( 0.0, pos, 1.0 );
|
||||
|
||||
if ( pos <= stops.first().position() )
|
||||
return stops.first().color();
|
||||
|
||||
for ( int i = 1; i < stops.count(); i++ )
|
||||
{
|
||||
if ( pos <= stops[i].position() )
|
||||
return qskInterpolatedColor( stops, i - 1, i, pos );
|
||||
}
|
||||
|
||||
return stops.last().color();
|
||||
}
|
||||
|
||||
QskGradientStops qskExtractedGradientStops(
|
||||
const QskGradientStops& stops, qreal from, qreal to )
|
||||
{
|
||||
|
@ -421,4 +440,3 @@ QGradientStops qskToQGradientStops( const QskGradientStops& stops )
|
|||
|
||||
return qStops;
|
||||
}
|
||||
|
||||
|
|
|
@ -120,6 +120,8 @@ QSK_EXPORT QDebug operator<<( QDebug, const QskGradientStop& );
|
|||
|
||||
typedef QVector< QskGradientStop > QskGradientStops;
|
||||
|
||||
QSK_EXPORT QColor qskInterpolatedColorAt( const QskGradientStops&, qreal pos ) noexcept;
|
||||
|
||||
QSK_EXPORT bool qskIsMonochrome( const QskGradientStops& ) noexcept;
|
||||
QSK_EXPORT bool qskIsVisible( const QskGradientStops& ) noexcept;
|
||||
|
||||
|
|
|
@ -231,7 +231,7 @@ static inline QSGNode* qskUpdateArcNode(
|
|||
return nullptr;
|
||||
|
||||
auto arcNode = QskSGNode::ensureNode< QskArcNode >( node );
|
||||
arcNode->setArcData( rect, metrics, borderWidth, borderColor, gradient );
|
||||
arcNode->setArcData( rect, metrics, borderWidth, borderColor, gradient, {}, {} );
|
||||
|
||||
return arcNode;
|
||||
}
|
||||
|
@ -547,11 +547,11 @@ QSGNode* QskSkinlet::updateArcNode( const QskSkinnable* skinnable,
|
|||
}
|
||||
|
||||
QSGNode* QskSkinlet::updateArcNode(
|
||||
const QskSkinnable* skinnable, QSGNode* node, const QRectF& rect,
|
||||
const QskSkinnable* skinnable, QSGNode* node, const QRectF& rect,
|
||||
qreal borderWidth, const QColor& borderColor,
|
||||
const QskGradient& fillGradient, const QskArcMetrics& metrics )
|
||||
{
|
||||
return qskUpdateArcNode( skinnable, node, rect,
|
||||
return qskUpdateArcNode( skinnable, node, rect,
|
||||
borderWidth, borderColor, fillGradient, metrics );
|
||||
}
|
||||
|
||||
|
@ -594,7 +594,7 @@ QSGNode* QskSkinlet::updateArcNode( const QskSkinnable* skinnable,
|
|||
}
|
||||
|
||||
QSGNode* QskSkinlet::updateLineNode( const QskSkinnable* skinnable,
|
||||
QSGNode* node, const QLineF& line, QskAspect::Subcontrol subControl )
|
||||
QSGNode* node, const QLineF& line, QskAspect::Subcontrol subControl )
|
||||
{
|
||||
auto lineStipple = skinnable->stippleMetricsHint( subControl );
|
||||
if ( !lineStipple.isValid() )
|
||||
|
|
|
@ -416,6 +416,20 @@ void QskWindow::keyReleaseEvent( QKeyEvent* event )
|
|||
|
||||
void QskWindow::exposeEvent( QExposeEvent* event )
|
||||
{
|
||||
#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 )
|
||||
if ( qskRenderingHardwareInterface( this ) )
|
||||
{
|
||||
/*
|
||||
Actually our code supports Qt5 RHI ( f9c08c34fb2cc64546bbe6ce9d359f416e934961 ),
|
||||
but Qt5 does not come with the qsb tool out of the box. Then we run into
|
||||
problems with compiling the shader code from the makefiles.
|
||||
But why should anyone use the experimental Qt5 RHI implementations
|
||||
instead of using Qt6 ...
|
||||
*/
|
||||
qFatal( "the experimental Qt5 RHI implementation is not supported:\n"
|
||||
"\tuse Qt6 or run the default OpenGL backend." );
|
||||
}
|
||||
#endif
|
||||
ensureFocus( Qt::OtherFocusReason );
|
||||
layoutItems();
|
||||
|
||||
|
|
|
@ -5,15 +5,27 @@
|
|||
|
||||
#include "QskArcNode.h"
|
||||
#include "QskArcMetrics.h"
|
||||
#include "QskArcShadowNode.h"
|
||||
#include "QskMargins.h"
|
||||
#include "QskGradient.h"
|
||||
#include "QskShapeNode.h"
|
||||
#include "QskStrokeNode.h"
|
||||
#include "QskSGNode.h"
|
||||
#include "QskShadowMetrics.h"
|
||||
|
||||
#include <qpen.h>
|
||||
#include <qpainterpath.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
enum NodeRole
|
||||
{
|
||||
ShadowRole,
|
||||
FillRole,
|
||||
BorderRole
|
||||
};
|
||||
}
|
||||
|
||||
static inline QskGradient qskEffectiveGradient(
|
||||
const QskGradient& gradient, const QskArcMetrics& metrics )
|
||||
{
|
||||
|
@ -54,6 +66,14 @@ static inline QRectF qskEffectiveRect(
|
|||
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()
|
||||
{
|
||||
}
|
||||
|
@ -65,20 +85,24 @@ QskArcNode::~QskArcNode()
|
|||
void QskArcNode::setArcData( const QRectF& rect,
|
||||
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,
|
||||
qreal borderWidth, const QColor& borderColor, const QskGradient& fillGradient )
|
||||
const qreal borderWidth, const QColor& borderColor, const QskGradient& fillGradient )
|
||||
{
|
||||
enum NodeRole
|
||||
{
|
||||
FillRole,
|
||||
BorderRole
|
||||
};
|
||||
setArcData( rect, arcMetrics, borderWidth, borderColor, fillGradient, {}, {} );
|
||||
}
|
||||
|
||||
const auto metrics = qskEffectiveMetrics( arcMetrics, rect );
|
||||
const auto gradient = qskEffectiveGradient( fillGradient, metrics );
|
||||
void QskArcNode::setArcData( const QRectF& rect, const QskArcMetrics& arcMetrics,
|
||||
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* >(
|
||||
QskSGNode::findChildNode( this, FillRole ) );
|
||||
|
@ -89,22 +113,52 @@ void QskArcNode::setArcData( const QRectF& rect, const QskArcMetrics& arcMetrics
|
|||
const auto arcRect = qskEffectiveRect( rect, borderWidth );
|
||||
if ( arcRect.isEmpty() )
|
||||
{
|
||||
delete shadowNode;
|
||||
delete fillNode;
|
||||
delete borderNode;
|
||||
|
||||
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 )
|
||||
{
|
||||
fillNode = new QskShapeNode;
|
||||
QskSGNode::setNodeRole( fillNode, FillRole );
|
||||
|
||||
prependChildNode( fillNode );
|
||||
}
|
||||
|
||||
fillNode->updateNode( path, QTransform(), arcRect, gradient );
|
||||
|
@ -112,25 +166,29 @@ void QskArcNode::setArcData( const QRectF& rect, const QskArcMetrics& arcMetrics
|
|||
else
|
||||
{
|
||||
delete fillNode;
|
||||
fillNode = nullptr;
|
||||
}
|
||||
|
||||
if ( borderWidth > 0.0 && borderColor.alpha() > 0 )
|
||||
if ( isStrokeNodeVisible )
|
||||
{
|
||||
if ( borderNode == nullptr )
|
||||
{
|
||||
borderNode = new QskStrokeNode;
|
||||
QskSGNode::setNodeRole( borderNode, BorderRole );
|
||||
|
||||
appendChildNode( borderNode );
|
||||
}
|
||||
|
||||
QPen pen( borderColor, borderWidth );
|
||||
pen.setCapStyle( Qt::FlatCap );
|
||||
|
||||
|
||||
borderNode->updateNode( path, QTransform(), pen );
|
||||
}
|
||||
else
|
||||
{
|
||||
delete borderNode;
|
||||
borderNode = nullptr;
|
||||
}
|
||||
|
||||
qskUpdateChildren(this, ShadowRole, shadowNode);
|
||||
qskUpdateChildren(this, FillRole, fillNode);
|
||||
qskUpdateChildren(this, BorderRole, borderNode);
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
class QskArcMetrics;
|
||||
class QskGradient;
|
||||
class QskShadowMetrics;
|
||||
|
||||
/*
|
||||
For the moment a QPainterPath/QskShapeNode.
|
||||
|
@ -23,8 +24,13 @@ class QSK_EXPORT QskArcNode : public QskShapeNode
|
|||
~QskArcNode() override;
|
||||
|
||||
void setArcData( const QRectF&, const QskArcMetrics&, const QskGradient& );
|
||||
|
||||
void setArcData( const QRectF&, const QskArcMetrics&,
|
||||
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
|
||||
|
|
|
@ -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;
|
||||
|
||||
QVector2D m_aspect = QVector2D{ 1, 1 };
|
||||
QVector2D m_aspectRatio = QVector2D{ 1, 1 };
|
||||
QVector4D m_radius = QVector4D{ 0, 0, 0, 0 };
|
||||
QVector4D m_color = QVector4D{ 0, 0, 0, 1 };
|
||||
float m_blurExtent = 0.0;
|
||||
|
@ -91,9 +91,9 @@ namespace
|
|||
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;
|
||||
}
|
||||
|
||||
|
@ -146,7 +146,7 @@ namespace
|
|||
auto p = program();
|
||||
|
||||
m_matrixId = p->uniformLocation( "matrix" );
|
||||
m_aspectId = p->uniformLocation( "aspect" );
|
||||
m_aspectRatioId = p->uniformLocation( "aspectRatio" );
|
||||
m_opacityId = p->uniformLocation( "opacity" );
|
||||
m_blurExtentId = p->uniformLocation( "blurExtent" );
|
||||
m_radiusId = p->uniformLocation( "radius" );
|
||||
|
@ -173,7 +173,7 @@ namespace
|
|||
{
|
||||
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_radiusId, material->m_radius );
|
||||
p->setUniformValue( m_colorId, material->m_color );
|
||||
|
@ -183,7 +183,7 @@ namespace
|
|||
private:
|
||||
int m_matrixId = -1;
|
||||
int m_opacityId = -1;
|
||||
int m_aspectId = -1;
|
||||
int m_aspectRatioId = -1;
|
||||
int m_blurExtentId = -1;
|
||||
int m_radiusId = -1;
|
||||
int m_colorId = -1;
|
||||
|
@ -231,7 +231,7 @@ int Material::compare( const QSGMaterial* other ) const
|
|||
auto material = static_cast< const Material* >( other );
|
||||
|
||||
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_radius, m_radius) )
|
||||
{
|
||||
|
@ -284,16 +284,16 @@ void QskBoxShadowNode::setShadowData(
|
|||
d->geometry.markVertexDataDirty();
|
||||
markDirty( QSGNode::DirtyGeometry );
|
||||
|
||||
QVector2D aspect( 1.0, 1.0 );
|
||||
QVector2D aspectRatio( 1.0, 1.0 );
|
||||
|
||||
if ( rect.width() >= rect.height() )
|
||||
aspect.setX( rect.width() / rect.height() );
|
||||
aspectRatio.setX( rect.width() / rect.height() );
|
||||
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 );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,28 +2,21 @@
|
|||
<RCC version="1.0">
|
||||
<qresource prefix="/qskinny/">
|
||||
|
||||
<file>shaders/boxshadow.vert.qsb</file>
|
||||
<file>shaders/boxshadow.frag.qsb</file>
|
||||
<file>shaders/arcshadow.vert</file>
|
||||
<file>shaders/arcshadow.frag</file>
|
||||
|
||||
<file>shaders/boxshadow.vert</file>
|
||||
<file>shaders/boxshadow.frag</file>
|
||||
|
||||
<file>shaders/gradientconic.vert.qsb</file>
|
||||
<file>shaders/gradientconic.frag.qsb</file>
|
||||
<file>shaders/gradientconic.vert</file>
|
||||
<file>shaders/gradientconic.frag</file>
|
||||
|
||||
<file>shaders/gradientradial.vert.qsb</file>
|
||||
<file>shaders/gradientradial.frag.qsb</file>
|
||||
<file>shaders/gradientradial.vert</file>
|
||||
<file>shaders/gradientradial.frag</file>
|
||||
|
||||
<file>shaders/gradientlinear.vert.qsb</file>
|
||||
<file>shaders/gradientlinear.frag.qsb</file>
|
||||
<file>shaders/gradientlinear.vert</file>
|
||||
<file>shaders/gradientlinear.frag</file>
|
||||
|
||||
<file>shaders/crisplines.vert.qsb</file>
|
||||
<file>shaders/crisplines.frag.qsb</file>
|
||||
<file>shaders/crisplines.vert</file>
|
||||
|
||||
</qresource>
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -8,7 +8,7 @@ layout( std140, binding = 0 ) uniform buf
|
|||
mat4 matrix;
|
||||
vec4 color;
|
||||
vec4 radius;
|
||||
vec2 aspect;
|
||||
vec2 aspectRatio;
|
||||
float blurExtent;
|
||||
float opacity;
|
||||
} ubuf;
|
||||
|
@ -25,25 +25,21 @@ void main()
|
|||
{
|
||||
vec4 col = vec4(0.0);
|
||||
|
||||
if ( ubuf.opacity > 0.0 )
|
||||
{
|
||||
const float minRadius = 0.05;
|
||||
float e2 = 0.5 * ubuf.blurExtent;
|
||||
float r = 2.0 * effectiveRadius( ubuf.radius, coord );
|
||||
|
||||
float e2 = 0.5 * ubuf.blurExtent;
|
||||
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.aspectRatio * ( 1.0 - abs( 2.0 * coord ) );
|
||||
float l = min( max(d.x, d.y), 0.0) + length( max(d, 0.0) );
|
||||
|
||||
vec2 d = r + ubuf.blurExtent - ubuf.aspect * ( 1.0 - abs( 2.0 * coord ) );
|
||||
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 );
|
||||
col = mix( ubuf.color, vec4(0.0), v ) * ubuf.opacity;
|
||||
}
|
||||
float v = smoothstep( -e2, e2, shadow );
|
||||
col = mix( ubuf.color, vec4(0.0), v ) * ubuf.opacity;
|
||||
|
||||
fragColor = col;
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ layout( std140, binding = 0 ) uniform buf
|
|||
mat4 matrix;
|
||||
vec4 color;
|
||||
vec4 radius;
|
||||
vec2 aspect;
|
||||
vec2 aspectRatio;
|
||||
float blurExtent;
|
||||
float opacity;
|
||||
} ubuf;
|
||||
|
|
|
@ -2,7 +2,7 @@ uniform lowp float opacity;
|
|||
uniform lowp float blurExtent;
|
||||
uniform lowp vec4 radius;
|
||||
uniform lowp vec4 color;
|
||||
uniform lowp vec2 aspect;
|
||||
uniform lowp vec2 aspectRatio;
|
||||
|
||||
varying lowp vec2 coord;
|
||||
|
||||
|
@ -18,25 +18,19 @@ 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 e2 = 0.5 * blurExtent;
|
||||
lowp float r = 2.0 * effectiveRadius( radius, coord );
|
||||
const lowp float minRadius = 0.05;
|
||||
r += e2 * ( minRadius / max( r, minRadius ) );
|
||||
|
||||
lowp float f = minRadius / max( r, minRadius );
|
||||
lowp vec2 d = r + blurExtent - aspectRatio * ( 1.0 - abs( 2.0 * coord ) );
|
||||
lowp float l = min( max(d.x, d.y), 0.0) + length( max(d, 0.0) );
|
||||
|
||||
r += e2 * f;
|
||||
lowp float shadow = l - r;
|
||||
|
||||
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;
|
||||
}
|
||||
lowp float v = smoothstep( -e2, e2, shadow );
|
||||
col = mix( color, vec4(0.0), v ) * opacity;
|
||||
|
||||
gl_FragColor = col;
|
||||
}
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -6,6 +6,9 @@ function qsbcompile {
|
|||
# qsb --qt6 -b -o ${qsbfile}.qsb $1
|
||||
}
|
||||
|
||||
qsbcompile arcshadow-vulkan.vert
|
||||
qsbcompile arcshadow-vulkan.frag
|
||||
|
||||
qsbcompile boxshadow-vulkan.vert
|
||||
qsbcompile boxshadow-vulkan.frag
|
||||
|
||||
|
|
Loading…
Reference in New Issue