Merge branch 'master' of https://github.com/uwerat/qskinny
This commit is contained in:
commit
79f91a57b6
|
|
@ -0,0 +1 @@
|
||||||
|
github: [uwerat]
|
||||||
|
|
@ -104,7 +104,8 @@ jobs:
|
||||||
cc: "gcc",
|
cc: "gcc",
|
||||||
cxx: "g++",
|
cxx: "g++",
|
||||||
archiver: "7z a",
|
archiver: "7z a",
|
||||||
generators: "Ninja Multi-Config",
|
# generators: "Ninja Multi-Config",
|
||||||
|
generators: "Ninja",
|
||||||
env: { DISPLAY: ":1" },
|
env: { DISPLAY: ":1" },
|
||||||
cmake:
|
cmake:
|
||||||
{
|
{
|
||||||
|
|
|
||||||
10
README.md
10
README.md
|
|
@ -32,12 +32,14 @@ But so far only Linux is actively tested.
|
||||||
It might support all versions Qt >= 5.15, but you can rely on:
|
It might support all versions Qt >= 5.15, but you can rely on:
|
||||||
|
|
||||||
- Qt 5.15
|
- Qt 5.15
|
||||||
- current long term supported ( LTS ) version of Qt
|
- current long term supported ( LTS ) version of Qt ( at the moment Qt 6.5.x )
|
||||||
- current version of Qt
|
- current version of Qt
|
||||||
|
|
||||||
On debian bullseye these packages need to be installed: `build-essential
|
On Debian these packages need to be installed for Qt6: `build-essential cmake
|
||||||
qt-qmake qtbase5-dev qtbase5-private-dev qtdeclarative5-dev
|
qtbase6-dev qtbase6-private-dev qtdeclarative6-dev qtdeclarative6-private-dev libqt6svg-dev qt6-shadertools`
|
||||||
qtdeclarative5-private-dev libqt5svg5-dev`.
|
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`
|
> Optional: When enabling the `hunspell` feature the following package needs to be installed: `libhunspell-dev`
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,12 +5,20 @@
|
||||||
|
|
||||||
macro(qsk_setup_Qt)
|
macro(qsk_setup_Qt)
|
||||||
|
|
||||||
# Often users have several Qt installations on their system and
|
# Use QSK_QT_VERSION specified with baseline 5.15
|
||||||
# need to be able to explicitly the one to be used. Let's see if
|
# otherwise fallback to latest known supported Qt version gte 5.15
|
||||||
# standard cmake features are good enough or if we need to introduce
|
# set vars for correct alpha descending sort order and direction (ex. Qt6, Qt5)
|
||||||
# something sort of additional option. TODO ...
|
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 )
|
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
|
# 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
|
||||||
{
|
{
|
||||||
public:
|
class TabView : public QskTabView
|
||||||
BoxPanel( QQuickItem* parent = nullptr )
|
|
||||||
: QskBox( parent )
|
|
||||||
{
|
{
|
||||||
setAutoLayoutChildren( true );
|
public:
|
||||||
setPadding( 60 );
|
TabView()
|
||||||
|
{
|
||||||
|
//setTabBarEdge( Qt::LeftEdge );
|
||||||
|
|
||||||
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
|
||||||
|
|
@ -171,7 +173,9 @@ list(APPEND SOURCES
|
||||||
nodes/QskVertex.cpp
|
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
|
list(APPEND HEADERS
|
||||||
controls/QskAbstractButton.h
|
controls/QskAbstractButton.h
|
||||||
|
|
@ -471,6 +475,49 @@ if(BUILD_QSKDLL)
|
||||||
set_target_properties(${target} PROPERTIES DEFINE_SYMBOL QSK_MAKEDLL)
|
set_target_properties(${target} PROPERTIES DEFINE_SYMBOL QSK_MAKEDLL)
|
||||||
endif()
|
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
|
target_include_directories(${target} PUBLIC
|
||||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/common>
|
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/common>
|
||||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/controls>
|
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/controls>
|
||||||
|
|
|
||||||
|
|
@ -273,6 +273,25 @@ QskGradientStops qskInterpolatedGradientStops(
|
||||||
return qskInterpolatedStops( from, to, ratio );
|
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(
|
QskGradientStops qskExtractedGradientStops(
|
||||||
const QskGradientStops& stops, qreal from, qreal to )
|
const QskGradientStops& stops, qreal from, qreal to )
|
||||||
{
|
{
|
||||||
|
|
@ -421,4 +440,3 @@ QGradientStops qskToQGradientStops( const QskGradientStops& stops )
|
||||||
|
|
||||||
return qStops;
|
return qStops;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -120,6 +120,8 @@ QSK_EXPORT QDebug operator<<( QDebug, const QskGradientStop& );
|
||||||
|
|
||||||
typedef QVector< QskGradientStop > QskGradientStops;
|
typedef QVector< QskGradientStop > QskGradientStops;
|
||||||
|
|
||||||
|
QSK_EXPORT QColor qskInterpolatedColorAt( const QskGradientStops&, qreal pos ) noexcept;
|
||||||
|
|
||||||
QSK_EXPORT bool qskIsMonochrome( const QskGradientStops& ) noexcept;
|
QSK_EXPORT bool qskIsMonochrome( const QskGradientStops& ) noexcept;
|
||||||
QSK_EXPORT bool qskIsVisible( const QskGradientStops& ) noexcept;
|
QSK_EXPORT bool qskIsVisible( const QskGradientStops& ) noexcept;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -47,11 +47,8 @@ class QskMetaFunction::FunctionCall : public QtPrivate::QSlotObjectBase
|
||||||
|
|
||||||
namespace QskMetaFunctionCall
|
namespace QskMetaFunctionCall
|
||||||
{
|
{
|
||||||
using FunctionCall = QskMetaFunction::FunctionCall;
|
|
||||||
using namespace QtPrivate;
|
|
||||||
|
|
||||||
template< typename Function, typename Args, typename R >
|
template< typename Function, typename Args, typename R >
|
||||||
class StaticFunctionCall : public FunctionCall
|
class StaticFunctionCall : public QskMetaFunction::FunctionCall
|
||||||
{
|
{
|
||||||
using MetaCall = StaticFunctionCall< Function, Args, R >;
|
using MetaCall = StaticFunctionCall< Function, Args, R >;
|
||||||
|
|
||||||
|
|
@ -74,7 +71,7 @@ namespace QskMetaFunctionCall
|
||||||
}
|
}
|
||||||
case Call:
|
case Call:
|
||||||
{
|
{
|
||||||
typedef FunctionPointer< Function > FuncType;
|
using FuncType = QtPrivate::FunctionPointer< Function >;
|
||||||
|
|
||||||
FuncType::template call< Args, R >(
|
FuncType::template call< Args, R >(
|
||||||
static_cast< MetaCall* >( functionCall )->m_function, object, args );
|
static_cast< MetaCall* >( functionCall )->m_function, object, args );
|
||||||
|
|
@ -100,7 +97,7 @@ namespace QskMetaFunctionCall
|
||||||
};
|
};
|
||||||
|
|
||||||
template< typename Function, typename Args, typename R >
|
template< typename Function, typename Args, typename R >
|
||||||
class MemberFunctionCall : public FunctionCall
|
class MemberFunctionCall : public QskMetaFunction::FunctionCall
|
||||||
{
|
{
|
||||||
using MetaCall = MemberFunctionCall< Function, Args, R >;
|
using MetaCall = MemberFunctionCall< Function, Args, R >;
|
||||||
|
|
||||||
|
|
@ -123,7 +120,7 @@ namespace QskMetaFunctionCall
|
||||||
}
|
}
|
||||||
case Call:
|
case Call:
|
||||||
{
|
{
|
||||||
typedef FunctionPointer< Function > FuncType;
|
using FuncType = QtPrivate::FunctionPointer< Function >;
|
||||||
|
|
||||||
FuncType::template call< Args, R >(
|
FuncType::template call< Args, R >(
|
||||||
static_cast< MetaCall* >( functionCall )->m_function,
|
static_cast< MetaCall* >( functionCall )->m_function,
|
||||||
|
|
@ -144,7 +141,7 @@ namespace QskMetaFunctionCall
|
||||||
};
|
};
|
||||||
|
|
||||||
template< typename Function, int N, typename Args, typename R >
|
template< typename Function, int N, typename Args, typename R >
|
||||||
class FunctorFunctionCall : public FunctionCall
|
class FunctorFunctionCall : public QskMetaFunction::FunctionCall
|
||||||
{
|
{
|
||||||
using MetaCall = FunctorFunctionCall< Function, N, Args, R >;
|
using MetaCall = FunctorFunctionCall< Function, N, Args, R >;
|
||||||
|
|
||||||
|
|
@ -167,7 +164,11 @@ namespace QskMetaFunctionCall
|
||||||
}
|
}
|
||||||
case Call:
|
case Call:
|
||||||
{
|
{
|
||||||
typedef Functor< Function, N > FuncType;
|
#if QT_VERSION < QT_VERSION_CHECK( 6, 7, 0 )
|
||||||
|
using FuncType = QtPrivate::Functor< Function, N >;
|
||||||
|
#else
|
||||||
|
using FuncType = QtPrivate::Callable< Function, Args >;
|
||||||
|
#endif
|
||||||
|
|
||||||
FuncType::template call< Args, R >(
|
FuncType::template call< Args, R >(
|
||||||
static_cast< MetaCall* >( functionCall )->m_function, object, args );
|
static_cast< MetaCall* >( functionCall )->m_function, object, args );
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
@ -547,11 +547,11 @@ QSGNode* QskSkinlet::updateArcNode( const QskSkinnable* skinnable,
|
||||||
}
|
}
|
||||||
|
|
||||||
QSGNode* QskSkinlet::updateArcNode(
|
QSGNode* QskSkinlet::updateArcNode(
|
||||||
const QskSkinnable* skinnable, QSGNode* node, const QRectF& rect,
|
const QskSkinnable* skinnable, QSGNode* node, const QRectF& rect,
|
||||||
qreal borderWidth, const QColor& borderColor,
|
qreal borderWidth, const QColor& borderColor,
|
||||||
const QskGradient& fillGradient, const QskArcMetrics& metrics )
|
const QskGradient& fillGradient, const QskArcMetrics& metrics )
|
||||||
{
|
{
|
||||||
return qskUpdateArcNode( skinnable, node, rect,
|
return qskUpdateArcNode( skinnable, node, rect,
|
||||||
borderWidth, borderColor, fillGradient, metrics );
|
borderWidth, borderColor, fillGradient, metrics );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -594,7 +594,7 @@ QSGNode* QskSkinlet::updateArcNode( const QskSkinnable* skinnable,
|
||||||
}
|
}
|
||||||
|
|
||||||
QSGNode* QskSkinlet::updateLineNode( 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 );
|
auto lineStipple = skinnable->stippleMetricsHint( subControl );
|
||||||
if ( !lineStipple.isValid() )
|
if ( !lineStipple.isValid() )
|
||||||
|
|
|
||||||
|
|
@ -416,6 +416,20 @@ void QskWindow::keyReleaseEvent( QKeyEvent* event )
|
||||||
|
|
||||||
void QskWindow::exposeEvent( QExposeEvent* 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 );
|
ensureFocus( Qt::OtherFocusReason );
|
||||||
layoutItems();
|
layoutItems();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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,25 +166,29 @@ 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 );
|
||||||
pen.setCapStyle( Qt::FlatCap );
|
pen.setCapStyle( Qt::FlatCap );
|
||||||
|
|
||||||
borderNode->updateNode( path, QTransform(), pen );
|
borderNode->updateNode( path, QTransform(), pen );
|
||||||
}
|
}
|
||||||
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 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -127,16 +127,26 @@ static void qskRenderText(
|
||||||
if ( glyphNode == nullptr )
|
if ( glyphNode == nullptr )
|
||||||
{
|
{
|
||||||
const bool preferNativeGlyphNode = false; // QskTextOptions?
|
const bool preferNativeGlyphNode = false; // QskTextOptions?
|
||||||
|
|
||||||
#if QT_VERSION >= QT_VERSION_CHECK( 6, 0, 0 )
|
|
||||||
constexpr int renderQuality = -1; // QQuickText::DefaultRenderTypeQuality
|
constexpr int renderQuality = -1; // QQuickText::DefaultRenderTypeQuality
|
||||||
|
|
||||||
|
#if QT_VERSION >= QT_VERSION_CHECK( 6, 7, 0 )
|
||||||
|
const auto renderType = preferNativeGlyphNode
|
||||||
|
? QSGTextNode::QtRendering : QSGTextNode::NativeRendering;
|
||||||
|
glyphNode = sgContext->createGlyphNode(
|
||||||
|
renderContext, renderType, renderQuality );
|
||||||
|
#elif QT_VERSION >= QT_VERSION_CHECK( 6, 0, 0 )
|
||||||
glyphNode = sgContext->createGlyphNode(
|
glyphNode = sgContext->createGlyphNode(
|
||||||
renderContext, preferNativeGlyphNode, renderQuality );
|
renderContext, preferNativeGlyphNode, renderQuality );
|
||||||
#else
|
#else
|
||||||
|
Q_UNUSED( renderQuality );
|
||||||
glyphNode = sgContext->createGlyphNode(
|
glyphNode = sgContext->createGlyphNode(
|
||||||
renderContext, preferNativeGlyphNode );
|
renderContext, preferNativeGlyphNode );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if QT_VERSION < QT_VERSION_CHECK( 6, 7, 0 )
|
||||||
glyphNode->setOwnerElement( item );
|
glyphNode->setOwnerElement( item );
|
||||||
|
#endif
|
||||||
|
|
||||||
glyphNode->setFlags( QSGNode::OwnedByParent | GlyphFlag );
|
glyphNode->setFlags( QSGNode::OwnedByParent | GlyphFlag );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,26 @@ QSK_QT_PRIVATE_END
|
||||||
#include <qopenglframebufferobject.h>
|
#include <qopenglframebufferobject.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static int qskRenderOrderCompare( const QSGNode* rootNode,
|
||||||
|
const QSGNode* node1, const QSGNode* node2 )
|
||||||
|
{
|
||||||
|
if ( rootNode == node1 )
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if ( rootNode == node2 )
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
for ( auto node = rootNode->firstChild();
|
||||||
|
node != nullptr; node = node->nextSibling() )
|
||||||
|
{
|
||||||
|
const auto ret = qskRenderOrderCompare( node, node1, node2 );
|
||||||
|
if ( ret )
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
#if QT_VERSION >= QT_VERSION_CHECK( 6, 0, 0 )
|
#if QT_VERSION >= QT_VERSION_CHECK( 6, 0, 0 )
|
||||||
|
|
@ -51,7 +71,20 @@ namespace
|
||||||
|
|
||||||
#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 )
|
#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 )
|
||||||
inline int textureId() const { return m_fbo ? m_fbo->texture() : 0; }
|
inline int textureId() const { return m_fbo ? m_fbo->texture() : 0; }
|
||||||
inline void renderScene() { Inherited::renderScene( textureId() ); }
|
|
||||||
|
inline void renderScene()
|
||||||
|
{
|
||||||
|
class Bindable : public QSGBindable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Bindable( QOpenGLFramebufferObject* fbo ) : m_fbo( fbo ) {}
|
||||||
|
void bind() const override { m_fbo->bind(); }
|
||||||
|
private:
|
||||||
|
QOpenGLFramebufferObject* m_fbo;
|
||||||
|
};
|
||||||
|
|
||||||
|
Inherited::renderScene( Bindable( m_fbo ) );
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
inline QRhiTexture* rhiTexture() const { return m_rhiTexture; }
|
inline QRhiTexture* rhiTexture() const { return m_rhiTexture; }
|
||||||
|
|
@ -62,6 +95,7 @@ namespace
|
||||||
|
|
||||||
void setProjection( const QRectF& );
|
void setProjection( const QRectF& );
|
||||||
void setTextureSize( const QSize& );
|
void setTextureSize( const QSize& );
|
||||||
|
QSize textureSize() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void nodeChanged( QSGNode*, QSGNode::DirtyState ) override;
|
void nodeChanged( QSGNode*, QSGNode::DirtyState ) override;
|
||||||
|
|
@ -70,12 +104,13 @@ namespace
|
||||||
private:
|
private:
|
||||||
void createTarget( const QSize& );
|
void createTarget( const QSize& );
|
||||||
void clearTarget();
|
void clearTarget();
|
||||||
|
void markDirty();
|
||||||
|
|
||||||
QSGTransformNode* m_finalNode = nullptr;
|
QSGTransformNode* m_finalNode = nullptr;
|
||||||
QskSceneTexture* m_texture = nullptr;
|
QskSceneTexture* m_texture = nullptr;
|
||||||
|
|
||||||
#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 )
|
#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 )
|
||||||
QOpenGLFramebufferObject* m_fbo;
|
QOpenGLFramebufferObject* m_fbo = nullptr;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if QT_VERSION < QT_VERSION_CHECK( 6, 4, 0 )
|
#if QT_VERSION < QT_VERSION_CHECK( 6, 4, 0 )
|
||||||
|
|
@ -100,6 +135,9 @@ namespace
|
||||||
, m_texture( texture )
|
, m_texture( texture )
|
||||||
{
|
{
|
||||||
setClearColor( Qt::transparent );
|
setClearColor( Qt::transparent );
|
||||||
|
|
||||||
|
connect( this, &QSGRenderer::sceneGraphChanged,
|
||||||
|
this, &Renderer::markDirty );
|
||||||
}
|
}
|
||||||
|
|
||||||
Renderer::~Renderer()
|
Renderer::~Renderer()
|
||||||
|
|
@ -112,6 +150,7 @@ namespace
|
||||||
if ( node != m_finalNode )
|
if ( node != m_finalNode )
|
||||||
{
|
{
|
||||||
m_finalNode = node;
|
m_finalNode = node;
|
||||||
|
markDirty();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -169,6 +208,16 @@ namespace
|
||||||
setViewportRect( r );
|
setViewportRect( r );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QSize Renderer::textureSize() const
|
||||||
|
{
|
||||||
|
#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 )
|
||||||
|
if ( m_fbo ) return m_fbo->size();
|
||||||
|
#else
|
||||||
|
if( m_rt.rt ) return m_rt.rt->pixelSize();
|
||||||
|
#endif
|
||||||
|
return QSize();
|
||||||
|
}
|
||||||
|
|
||||||
void Renderer::render()
|
void Renderer::render()
|
||||||
{
|
{
|
||||||
m_dirty = false;
|
m_dirty = false;
|
||||||
|
|
@ -186,16 +235,25 @@ namespace
|
||||||
|
|
||||||
void Renderer::nodeChanged( QSGNode* node, QSGNode::DirtyState state )
|
void Renderer::nodeChanged( QSGNode* node, QSGNode::DirtyState state )
|
||||||
{
|
{
|
||||||
Inherited::nodeChanged( node, state );
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
We want to limit updates to nodes, that are actually rendered. TODO ...
|
No need to update the texture for changes of nodes behind
|
||||||
|
the final node.
|
||||||
|
|
||||||
In any case we need to block update requests, when the textureNode reports
|
Unfortunately QQuickWindow does not update the scene graph in
|
||||||
that it has been updated by us to the renderer of the window.
|
rendering order and we might be called for relevant nodes after
|
||||||
|
the texture has already been updated. In these situations we
|
||||||
|
update the texture twice. Not so good ...
|
||||||
*/
|
*/
|
||||||
if ( ( state != QSGNode::DirtyMaterial )
|
if ( qskRenderOrderCompare( rootNode(), node, m_finalNode ) > 0 )
|
||||||
|| ( node != m_texture->textureNode() ) )
|
{
|
||||||
|
// triggering QSGRenderer::sceneGraphChanged signals
|
||||||
|
Inherited::nodeChanged( node, state );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Renderer::markDirty()
|
||||||
|
{
|
||||||
|
if ( !m_dirty )
|
||||||
{
|
{
|
||||||
m_dirty = true;
|
m_dirty = true;
|
||||||
Q_EMIT m_texture->updateRequested();
|
Q_EMIT m_texture->updateRequested();
|
||||||
|
|
@ -295,19 +353,44 @@ class QskSceneTexturePrivate final : public QSGTexturePrivate
|
||||||
|
|
||||||
#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 )
|
#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 )
|
||||||
int comparisonKey() const override
|
int comparisonKey() const override
|
||||||
{ return int( qintptr( rhiTexture() ) ); }
|
{
|
||||||
|
if ( renderer )
|
||||||
|
{
|
||||||
|
if ( renderer->textureId() )
|
||||||
|
return renderer->textureId();
|
||||||
|
|
||||||
|
if ( renderer->rhiTexture() )
|
||||||
|
return int( qintptr( renderer->rhiTexture() ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
return int( qintptr( this ) );
|
||||||
|
}
|
||||||
|
|
||||||
QRhiTexture *rhiTexture() const override
|
QRhiTexture *rhiTexture() const override
|
||||||
{ return renderer ? renderer->rhiTexture() : nullptr; }
|
{ return renderer ? renderer->rhiTexture() : nullptr; }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
QSize pixelSize() const
|
||||||
|
{
|
||||||
|
QSize size( qCeil( rect.width() ), qCeil( rect.height() ) );
|
||||||
|
size *= devicePixelRatio;
|
||||||
|
|
||||||
|
const QSize minSize = context->sceneGraphContext()->minimumFBOSize();
|
||||||
|
|
||||||
|
while ( size.width() < minSize.width() )
|
||||||
|
size.rwidth() *= 2;
|
||||||
|
|
||||||
|
while ( size.height() < minSize.height() )
|
||||||
|
size.rheight() *= 2;
|
||||||
|
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
QRectF rect;
|
QRectF rect;
|
||||||
const qreal devicePixelRatio;
|
const qreal devicePixelRatio;
|
||||||
|
|
||||||
Renderer* renderer = nullptr;
|
Renderer* renderer = nullptr;
|
||||||
QSGDefaultRenderContext* context = nullptr;
|
QSGDefaultRenderContext* context = nullptr;
|
||||||
|
|
||||||
const QSGGeometryNode* textureNode = nullptr;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
QskSceneTexture::QskSceneTexture( const QQuickWindow* window )
|
QskSceneTexture::QskSceneTexture( const QQuickWindow* window )
|
||||||
|
|
@ -321,32 +404,10 @@ QskSceneTexture::~QskSceneTexture()
|
||||||
delete d_func()->renderer;
|
delete d_func()->renderer;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QskSceneTexture::setTextureNode( const QSGGeometryNode* node )
|
|
||||||
{
|
|
||||||
d_func()->textureNode = node;
|
|
||||||
}
|
|
||||||
|
|
||||||
const QSGGeometryNode* QskSceneTexture::textureNode() const
|
|
||||||
{
|
|
||||||
return d_func()->textureNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
QSize QskSceneTexture::textureSize() const
|
QSize QskSceneTexture::textureSize() const
|
||||||
{
|
{
|
||||||
Q_D( const QskSceneTexture );
|
Q_D( const QskSceneTexture );
|
||||||
|
return d->renderer ? d->renderer->textureSize() : QSize();
|
||||||
QSize size( qCeil( d->rect.width() ), qCeil( d->rect.height() ) );
|
|
||||||
size *= d->devicePixelRatio;
|
|
||||||
|
|
||||||
const QSize minSize = d->context->sceneGraphContext()->minimumFBOSize();
|
|
||||||
|
|
||||||
while ( size.width() < minSize.width() )
|
|
||||||
size.rwidth() *= 2;
|
|
||||||
|
|
||||||
while ( size.height() < minSize.height() )
|
|
||||||
size.rheight() *= 2;
|
|
||||||
|
|
||||||
return size;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void QskSceneTexture::render( const QSGRootNode* rootNode,
|
void QskSceneTexture::render( const QSGRootNode* rootNode,
|
||||||
|
|
@ -366,7 +427,7 @@ void QskSceneTexture::render( const QSGRootNode* rootNode,
|
||||||
d->renderer->setFinalNode( const_cast< QSGTransformNode* >( finalNode ) );
|
d->renderer->setFinalNode( const_cast< QSGTransformNode* >( finalNode ) );
|
||||||
|
|
||||||
d->renderer->setProjection( d->rect );
|
d->renderer->setProjection( d->rect );
|
||||||
d->renderer->setTextureSize( textureSize() );
|
d->renderer->setTextureSize( d->pixelSize() );
|
||||||
d->renderer->renderScene();
|
d->renderer->renderScene();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,6 @@ class QskSceneTexturePrivate;
|
||||||
|
|
||||||
class QSGRootNode;
|
class QSGRootNode;
|
||||||
class QSGTransformNode;
|
class QSGTransformNode;
|
||||||
class QSGGeometryNode;
|
|
||||||
class QQuickWindow;
|
class QQuickWindow;
|
||||||
|
|
||||||
class QSK_EXPORT QskSceneTexture : public QSGTexture
|
class QSK_EXPORT QskSceneTexture : public QSGTexture
|
||||||
|
|
@ -26,12 +25,6 @@ class QSK_EXPORT QskSceneTexture : public QSGTexture
|
||||||
QskSceneTexture( const QQuickWindow* );
|
QskSceneTexture( const QQuickWindow* );
|
||||||
~QskSceneTexture();
|
~QskSceneTexture();
|
||||||
|
|
||||||
#if 1
|
|
||||||
// to avoid recursive update - need to find a better solution TODO
|
|
||||||
void setTextureNode( const QSGGeometryNode* );
|
|
||||||
const QSGGeometryNode* textureNode() const;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void render( const QSGRootNode*, const QSGTransformNode*, const QRectF& );
|
void render( const QSGRootNode*, const QSGTransformNode*, const QRectF& );
|
||||||
|
|
||||||
QSize textureSize() const override;
|
QSize textureSize() const override;
|
||||||
|
|
|
||||||
|
|
@ -2,28 +2,21 @@
|
||||||
<RCC version="1.0">
|
<RCC version="1.0">
|
||||||
<qresource prefix="/qskinny/">
|
<qresource prefix="/qskinny/">
|
||||||
|
|
||||||
<file>shaders/boxshadow.vert.qsb</file>
|
<file>shaders/arcshadow.vert</file>
|
||||||
<file>shaders/boxshadow.frag.qsb</file>
|
<file>shaders/arcshadow.frag</file>
|
||||||
|
|
||||||
<file>shaders/boxshadow.vert</file>
|
<file>shaders/boxshadow.vert</file>
|
||||||
<file>shaders/boxshadow.frag</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.vert</file>
|
||||||
<file>shaders/gradientconic.frag</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.vert</file>
|
||||||
<file>shaders/gradientradial.frag</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.vert</file>
|
||||||
<file>shaders/gradientlinear.frag</file>
|
<file>shaders/gradientlinear.frag</file>
|
||||||
|
|
||||||
<file>shaders/crisplines.vert.qsb</file>
|
|
||||||
<file>shaders/crisplines.frag.qsb</file>
|
|
||||||
<file>shaders/crisplines.vert</file>
|
<file>shaders/crisplines.vert</file>
|
||||||
|
|
||||||
</qresource>
|
</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;
|
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 )
|
float e2 = 0.5 * ubuf.blurExtent;
|
||||||
{
|
float r = 2.0 * effectiveRadius( ubuf.radius, coord );
|
||||||
const float minRadius = 0.05;
|
|
||||||
|
|
||||||
float e2 = 0.5 * ubuf.blurExtent;
|
const float minRadius = 0.05;
|
||||||
float r = 2.0 * effectiveRadius( ubuf.radius, coord );
|
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 shadow = l - r;
|
||||||
float l = min( max(d.x, d.y), 0.0) + length( max(d, 0.0) );
|
|
||||||
|
|
||||||
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;
|
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 )
|
lowp float e2 = 0.5 * blurExtent;
|
||||||
{
|
lowp float r = 2.0 * effectiveRadius( radius, coord );
|
||||||
const lowp float minRadius = 0.05;
|
|
||||||
|
|
||||||
lowp float e2 = 0.5 * blurExtent;
|
const lowp float minRadius = 0.05;
|
||||||
lowp float r = 2.0 * effectiveRadius( radius, coord );
|
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 v = smoothstep( -e2, e2, shadow );
|
||||||
lowp float l = min( max(d.x, d.y), 0.0) + length( max(d, 0.0) );
|
col = mix( color, vec4(0.0), v ) * opacity;
|
||||||
|
|
||||||
lowp float shadow = l - r;
|
|
||||||
|
|
||||||
lowp float v = smoothstep( -e2, e2, shadow );
|
|
||||||
col = mix( color, vec4(0.0), v ) * opacity;
|
|
||||||
}
|
|
||||||
|
|
||||||
gl_FragColor = col;
|
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
|
# 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