add rotation per subcontrol

This commit is contained in:
Vogel, Rick 2023-07-20 12:01:16 +02:00
parent 87b304e0c5
commit 77c39cdd05
5 changed files with 405 additions and 296 deletions

View File

@ -96,7 +96,7 @@ namespace
}
template<>
void style< QskLevelingSensor >( QskSkinHintTableEditor& ed )
void style< QskLevelingSensor >( QskSkinHintTableEditor& editor )
{
using Q = QskLevelingSensor;
@ -111,34 +111,36 @@ namespace
} };
gradient.setLinearDirection( Qt::Vertical );
ed.setColor( Q::Background, "dimgray" );
editor.setColor( Q::Background, "dimgray" );
ed.setStrutSize( Q::OuterDisk, { r2, r2 } );
ed.setColor( Q::OuterDisk, Qt::white );
editor.setStrutSize( Q::OuterDisk, { r2, r2 } );
editor.setColor( Q::OuterDisk, Qt::white );
ed.setGradient( Q::Horizon, gradient );
ed.setStrutSize( Q::Horizon, { r1, r1 } );
editor.setGradient( Q::Horizon, gradient );
editor.setStrutSize( Q::Horizon, { r1, r1 } );
ed.setColor( Q::TickmarksX, Qt::black );
ed.setStrutSize( Q::TickmarksX, { r1, 0.2 } ); // w %, h %
ed.setHint( Q::TickmarksX, QVector3D{ 0.50, 0.75, 1.0 } ); // %
editor.setColor( Q::TickmarksX, Qt::black );
editor.setStrutSize( Q::TickmarksX, { r1, 0.2 } ); // w %, h %
editor.setHint( Q::TickmarksX, QVector3D{ 0.50, 0.75, 1.0 } ); // %
editor.setAlignment(Q::TickmarksX, Qt::AlignCenter);
ed.setStrutSize( Q::TickmarksXLabels, { r1, 0.15 } ); // w %, h %
ed.setAlignment( Q::TickmarksXLabels, Qt::AlignTop | Qt::AlignHCenter );
editor.setStrutSize( Q::TickmarksXLabels, { r1, 0.15 } ); // w %, h %
editor.setAlignment( Q::TickmarksXLabels, Qt::AlignTop | Qt::AlignHCenter );
ed.setColor( Q::TickmarksY, Qt::black );
ed.setStrutSize( Q::TickmarksY, { 0.1, r1 } ); // w %, h %
ed.setHint( Q::TickmarksY, QVector3D{ 0.50, 0.75, 1.00 } ); // %
editor.setColor( Q::TickmarksY, Qt::black );
editor.setStrutSize( Q::TickmarksY, { 0.1, r1 } ); // w %, h %
editor.setHint( Q::TickmarksY, QVector3D{ 0.50, 0.75, 1.00 } ); // %
editor.setAlignment(Q::TickmarksY, Qt::AlignCenter);
ed.setStrutSize( Q::TickmarksYLabels, { 0.15, r1 } ); // w %, h %
ed.setAlignment( Q::TickmarksYLabels, Qt::AlignCenter );
editor.setStrutSize( Q::TickmarksYLabels, { 0.15, r1 } ); // w %, h %
editor.setAlignment( Q::TickmarksYLabels, Qt::AlignCenter );
ed.setColor( Q::TickmarksZ, "silver" );
ed.setStrutSize( Q::TickmarksZ, { 0.90, 0.95 } );
ed.setHint( Q::TickmarksZ, QVector3D{ 0.50, 0.75, 1.00 } ); // %
editor.setColor( Q::TickmarksZ, "silver" );
editor.setStrutSize( Q::TickmarksZ, { 0.90, 0.95 } );
editor.setHint( Q::TickmarksZ, QVector3D{ 0.50, 0.75, 1.00 } ); // %
ed.setStrutSize( Q::TickmarksZLabels, { 0.9, 0.0 } ); // r1 %, r2 %
ed.setAlignment( Q::TickmarksZLabels, Qt::AlignCenter );
editor.setStrutSize( Q::TickmarksZLabels, { 0.9, 0.0 } ); // r1 %, r2 %
editor.setAlignment( Q::TickmarksZLabels, Qt::AlignCenter );
}
public:

View File

@ -87,17 +87,26 @@ namespace
}
Q_REQUIRED_RESULT QskSlider* makeRotationSlider(
const Qt::Axis axis, QskLevelingSensor* const sensor, QQuickItem* const parent = nullptr )
const Qt::Axis axis, QskLevelingSensor* const sensor, const QskAspect::Subcontrol subControl, QQuickItem* const parent = nullptr )
{
auto* const slider = new QskSlider( Qt::Horizontal, parent );
slider->setMinimum( -360 );
slider->setMaximum( +360 );
QObject::connect( sensor, &QskLevelingSensor::rotationChanged, slider,
[ slider, axis ]( const QVector3D& degree ) { slider->setValue( degree[ axis ] ); } );
QObject::connect( sensor, &QskLevelingSensor::subControlRotationChanged, slider,
[ = ]( const QskAspect::Subcontrol control, const QVector3D& degree ) {
if(control == subControl)
{
slider->setValue( degree[ axis ] );
}
} );
QObject::connect( slider, &QskSlider::valueChanged, sensor,
[ sensor, axis ]( const qreal degree ) { sensor->setRotation( axis, degree ); } );
[ = ]( const qreal degree ) {
auto d = sensor->subControlRotation( subControl );
d[ axis ] = degree;
sensor->setSubControlRotation( subControl, d );
} );
return slider;
}
@ -108,6 +117,8 @@ namespace
Window()
{
auto* const root = new QskLinearBox( Qt::Horizontal, contentItem() );
root->setSpacing(8);
root->setMargins(8);
auto* const left = new QskLinearBox( Qt::Vertical, root );
auto* const right = new QskLinearBox( Qt::Vertical, root );
auto* const sensor = new QskLevelingSensor( left );
@ -125,12 +136,18 @@ namespace
( void ) new QskTextLabel( "Tickmarks Z", right );
auto* const sliderTickmarksZ = makeTickmarksSlider( Qt::ZAxis, sensor, 0, 90, radialIntervalA, radialIntervalB, right );
( void ) new QskTextLabel( "Rotation X", right );
( void ) makeRotationSlider( Qt::XAxis, sensor, right );
( void ) new QskTextLabel( "Rotation Y", right );
( void ) makeRotationSlider( Qt::YAxis, sensor, right );
( void ) new QskTextLabel( "Rotation Z", right );
( void ) makeRotationSlider( Qt::ZAxis, sensor, right );
( void ) new QskTextLabel( "Rotation X Plane", right );
( void ) makeRotationSlider( Qt::XAxis, sensor, QskLevelingSensor::TickmarksX, right );
( void ) makeRotationSlider( Qt::YAxis, sensor, QskLevelingSensor::TickmarksX, right );
( void ) makeRotationSlider( Qt::ZAxis, sensor, QskLevelingSensor::TickmarksX, right );
( void ) new QskTextLabel( "Rotation Y Plane", right );
( void ) makeRotationSlider( Qt::XAxis, sensor, QskLevelingSensor::TickmarksY, right );
( void ) makeRotationSlider( Qt::YAxis, sensor, QskLevelingSensor::TickmarksY, right );
( void ) makeRotationSlider( Qt::ZAxis, sensor, QskLevelingSensor::TickmarksY, right );
( void ) new QskTextLabel( "Rotation Z Plane", right );
( void ) makeRotationSlider( Qt::XAxis, sensor, QskLevelingSensor::TickmarksZ, right );
( void ) makeRotationSlider( Qt::YAxis, sensor, QskLevelingSensor::TickmarksZ, right );
( void ) makeRotationSlider( Qt::ZAxis, sensor, QskLevelingSensor::TickmarksZ, right );
sliderTickmarksX->setValue(15);
sliderTickmarksY->setValue(15);

View File

@ -42,50 +42,23 @@ QSK_SUBCONTROL(QskLevelingSensor, TickmarksZLabels)
#define RETURN_IF_FALSE(expr) if(!(expr)) return;
using Q = QskLevelingSensor;
QskLevelingSensor::QskLevelingSensor(QQuickItem* const parent)
: Inherited(parent)
{
}
void QskLevelingSensor::setRotation(const QVector3D& degree)
{
if (m_rotation != degree)
{
setRotation(Qt::XAxis, degree.x());
setRotation(Qt::YAxis, degree.y());
setRotation(Qt::ZAxis, degree.z());
}
}
void QskLevelingSensor::setRotation(const Qt::Axis axis, const float degree)
{
RETURN_IF_FALSE(isAxis(axis));
if (compareExchange(m_rotation[axis], degree))
{
update();
switch(axis)
{
case Qt::XAxis: Q_EMIT rotationXChanged(m_rotation[axis]); break;
case Qt::YAxis: Q_EMIT rotationYChanged(m_rotation[axis]); break;
case Qt::ZAxis: Q_EMIT rotationZChanged(m_rotation[axis]); break;
}
Q_EMIT rotationChanged(m_rotation);
}
}
void QskLevelingSensor::setTickmarks(const Qt::Axis axis, QskScaleTickmarks tickmarks)
{
RETURN_IF_FALSE(isAxis(axis));
m_tickmarks[axis] = std::move(tickmarks);
update();
}
void QskLevelingSensor::setTickmarksLabels(const Qt::Axis axis, TickmarksLabels labels)
{
RETURN_IF_FALSE(isAxis(axis));
RETURN_IF_FALSE(isAxis(axis));
m_tickmarksLabels[axis] = std::move(labels);
update();
}
@ -135,9 +108,46 @@ const QVector3D& QskLevelingSensor::angle() const noexcept
return m_angle;
}
const QVector3D& QskLevelingSensor::rotation() const noexcept
const QVector3D& QskLevelingSensor::subControlRotation(const QskAspect::Subcontrol subControl) const noexcept
{
return m_rotation;
static const QVector3D notFound;
const auto found = m_subControlRotation.find(subControl);
if(found == m_subControlRotation.end()) {
return notFound;
}
return found->second;
}
void QskLevelingSensor::setSubControlRotation(const QskAspect::Subcontrol subControl, const QVector3D& degree)
{
auto updateSubControlRotation = [this](const QskAspect::Subcontrol subControl, const QVector3D& degree)
{
if ( compareExchange( m_subControlRotation[ subControl ], degree ) )
{
Q_EMIT subControlRotationChanged(subControl, degree);
update();
}
};
if(subControl == Q::TickmarksX || subControl == Q::TickmarksXLabels)
{
updateSubControlRotation(Q::TickmarksX, degree);
updateSubControlRotation(Q::TickmarksXLabels, degree);
}
else if(subControl == Q::TickmarksY || subControl == Q::TickmarksYLabels)
{
updateSubControlRotation(Q::TickmarksY, degree);
updateSubControlRotation(Q::TickmarksYLabels, degree);
}
else if(subControl == Q::TickmarksZ || subControl == TickmarksZLabels)
{
updateSubControlRotation(TickmarksZ, degree);
updateSubControlRotation(TickmarksZLabels, degree);
}
else
{
updateSubControlRotation(subControl, degree);
}
}
#include "moc_QskLevelingSensor.cpp"

View File

@ -5,6 +5,8 @@
#include <QVector3D>
#include <QskAspect.h>
#include <unordered_map>
class QSK_EXPORT QskLevelingSensor : public QskControl
{
Q_OBJECT
@ -23,26 +25,31 @@ public:
using TickmarksLabels = QVector<QPair<qreal, QString>>;
explicit QskLevelingSensor(QQuickItem* parent = nullptr);
public Q_SLOTS:
void setRotation(const QVector3D& degree);
void setRotation(Qt::Axis axis, float degree);
void setTickmarks(Qt::Axis axis, Tickmarks tickmarks);
void setTickmarksLabels(Qt::Axis axis, TickmarksLabels labels);
void setAngle(const QVector3D& degree);
void setAngle(Qt::Axis axis, float degree);
void setSubControlRotation(QskAspect::Subcontrol subControl, const QVector3D& degree);
Q_SIGNALS:
void rotationXChanged(qreal degree);
void rotationYChanged(qreal degree);
void rotationZChanged(qreal degree);
void rotationChanged(const QVector3D& degree);
void anglesChanged(const QVector3D& degree);
void subControlRotationChanged(QskAspect::Subcontrol subControl, const QVector3D& degree);
public:
Q_REQUIRED_RESULT const QVector3D& rotation() const noexcept;
Q_REQUIRED_RESULT const Tickmarks& tickmarks(Qt::Axis axis) const;
Q_REQUIRED_RESULT const TickmarksLabels& tickmarkLabels(Qt::Axis axis) const;
Q_REQUIRED_RESULT const QVector3D& angle() const noexcept;
Q_REQUIRED_RESULT const QVector3D& subControlRotation(QskAspect::Subcontrol subControl) const noexcept;
private:
// TODO use pimpl
QVector3D m_rotation;
QVector3D m_angle = { 45,45,45 };
Tickmarks m_tickmarks[3];
TickmarksLabels m_tickmarksLabels[3];
std::unordered_map<QskAspect::Subcontrol, QVector3D> m_subControlRotation;
};

View File

@ -1,7 +1,7 @@
#include "QskLevelingSensorSkinlet.h"
#include "QskLevelingSensor.h"
#include "QskLevelingSensorUtility.h"
#include "QskLevelingSensorNodes.h"
#include "QskLevelingSensorUtility.h"
#include "QskSGNodeUtility.h"
#include <QskArcMetrics.h>
@ -24,34 +24,86 @@
#include <QSGGeometryNode>
#include <qmath.h>
namespace
{
template< typename T >
struct State;
template<>
struct State< QskLevelingSensor >
{
qreal r1 = 0.0;
qreal r2 = 0.0;
qreal cX = 0.0;
qreal cY = 0.0;
qreal sX = 0.0;
qreal sY = 0.0;
qreal sZ = 0.0;
explicit State( const QskLevelingSensor* const sensor )
: r1( QskLevelingSensorSkinlet::innerRadius( sensor ) )
, r2( QskLevelingSensorSkinlet::outerRadius( sensor ) )
, cX( QskLevelingSensorSkinlet::center( sensor ).x() )
, cY( QskLevelingSensorSkinlet::center( sensor ).y() )
, sX( r1 / sensor->angle().x() )
, sY( r1 / sensor->angle().y() )
, sZ( r1 / sensor->angle().z() )
{
}
};
template<>
struct State< QskAspect::Subcontrol > : State< QskLevelingSensor >
{
qreal rX = 0.0;
qreal rY = 0.0;
qreal rZ = 0.0;
qreal tX = 0.0;
qreal tY = 0.0;
qreal tZ = 0.0;
State( const QskLevelingSensor* const sensor, QskAspect::Subcontrol subcontrol )
: State< QskLevelingSensor >( sensor )
, rX( sensor->subControlRotation( subcontrol ).x() )
, rY( sensor->subControlRotation( subcontrol ).y() )
, rZ( sensor->subControlRotation( subcontrol ).z() )
, tX( rY * sX )
, tY( rX * sY )
, tZ( 0.0 )
{
}
};
}
using Q = QskLevelingSensor;
using R = QskLevelingSensorSkinlet::NodeRole;
using namespace QskSGNode;
float QskLevelingSensorSkinlet::outerRadius(const QskSkinnable* const skinnable)
float QskLevelingSensorSkinlet::outerRadius( const QskSkinnable* const skinnable )
{
const auto* const sensor = static_cast<const Q*>(skinnable);
const auto* const sensor = static_cast< const Q* >( skinnable );
const auto contentsRect = sensor->contentsRect();
return 0.5f * qMin(contentsRect.width(), contentsRect.height());
return 0.5f * qMin( contentsRect.width(), contentsRect.height() );
}
float QskLevelingSensorSkinlet::innerRadius(const QskSkinnable* const skinnable)
float QskLevelingSensorSkinlet::innerRadius( const QskSkinnable* const skinnable )
{
const auto scale = skinnable->strutSizeHint(Q::Horizon);
return outerRadius(skinnable) * scale.width();
const auto scale = skinnable->strutSizeHint( Q::Horizon );
return outerRadius( skinnable ) * scale.width();
}
QPointF QskLevelingSensorSkinlet::center(const QskSkinnable* const skinnable)
QPointF QskLevelingSensorSkinlet::center( const QskSkinnable* const skinnable )
{
const auto* const sensor = static_cast<const Q*>(skinnable);
const auto* const sensor = static_cast< const Q* >( skinnable );
return sensor->contentsRect().center();
}
QskLevelingSensorSkinlet::QskLevelingSensorSkinlet(QskSkin* skin)
: Inherited(skin)
QskLevelingSensorSkinlet::QskLevelingSensorSkinlet( QskSkin* skin )
: Inherited( skin )
{
setNodeRoles({
setNodeRoles( {
OuterDisk,
Horizon,
HorizonClip,
@ -60,19 +112,20 @@ QskLevelingSensorSkinlet::QskLevelingSensorSkinlet(QskSkin* skin)
TickmarksY,
TickmarksYLabels,
TickmarksZ,
TickmarksZLabels, });
TickmarksZLabels,
} );
}
template<QskLevelingSensorSkinlet::NodeRole>
Q_REQUIRED_RESULT QRectF QskLevelingSensorSkinlet::subControlRect(const QskLevelingSensor* const sensor,
const QRectF& contentsRect) const = delete;
template< QskLevelingSensorSkinlet::NodeRole >
Q_REQUIRED_RESULT QRectF QskLevelingSensorSkinlet::subControlRect(
const QskLevelingSensor* const sensor, const QRectF& contentsRect ) const = delete;
template<>
Q_REQUIRED_RESULT QRectF QskLevelingSensorSkinlet::subControlRect<R::OuterDisk>(const QskLevelingSensor* const sensor,
const QRectF& contentsRect) const
Q_REQUIRED_RESULT QRectF QskLevelingSensorSkinlet::subControlRect< R::OuterDisk >(
const QskLevelingSensor* const sensor, const QRectF& contentsRect ) const
{
const auto radius = outerRadius(sensor);
const auto scale = sensor->strutSizeHint(Q::OuterDisk);
const auto radius = outerRadius( sensor );
const auto scale = sensor->strutSizeHint( Q::OuterDisk );
const auto width = 2 * radius * scale.width();
const auto height = width;
const auto x = contentsRect.center().x() - width / 2;
@ -81,333 +134,353 @@ Q_REQUIRED_RESULT QRectF QskLevelingSensorSkinlet::subControlRect<R::OuterDisk>(
}
template<>
Q_REQUIRED_RESULT QRectF QskLevelingSensorSkinlet::subControlRect<R::Horizon>(const QskLevelingSensor* const sensor,
const QRectF& contentsRect) const
Q_REQUIRED_RESULT QRectF QskLevelingSensorSkinlet::subControlRect< R::Horizon >(
const QskLevelingSensor* const sensor, const QRectF& contentsRect ) const
{
const auto scale = sensor->strutSizeHint(Q::Horizon);
const auto width = 2 * innerRadius(sensor) * scale.width();
const auto scale = sensor->strutSizeHint( Q::Horizon );
const auto width = 2 * innerRadius( sensor ) * scale.width();
const auto height = width;
return {
center(sensor).x() - width / 2,
center(sensor).y() - height / 2,
width,
height
};
return { center( sensor ).x() - width / 2, center( sensor ).y() - height / 2, width, height };
}
QRectF QskLevelingSensorSkinlet::subControlRect(const QskSkinnable* skinnable,
const QRectF& contentsRect, QskAspect::Subcontrol subControl) const
QRectF QskLevelingSensorSkinlet::subControlRect( const QskSkinnable* skinnable,
const QRectF& contentsRect, QskAspect::Subcontrol subControl ) const
{
const auto* const sensor = static_cast<const Q*>(skinnable);
const auto* const sensor = static_cast< const Q* >( skinnable );
if (subControl == Q::OuterDisk)
if ( subControl == Q::OuterDisk )
{
return subControlRect<OuterDisk>(sensor, contentsRect);
return subControlRect< OuterDisk >( sensor, contentsRect );
}
if (subControl == Q::Horizon)
if ( subControl == Q::Horizon )
{
return subControlRect<Horizon>(sensor, contentsRect);
return subControlRect< Horizon >( sensor, contentsRect );
}
return Inherited::subControlRect(skinnable, contentsRect, subControl);
return Inherited::subControlRect( skinnable, contentsRect, subControl );
}
template<QskLevelingSensorSkinlet::NodeRole>
QSGNode* QskLevelingSensorSkinlet::updateSubNode(const QskLevelingSensor* const sensor,
const quint8 nodeRole, QSGNode* const node) const = delete;
template< QskLevelingSensorSkinlet::NodeRole >
QSGNode* QskLevelingSensorSkinlet::updateSubNode( const QskLevelingSensor* const sensor,
const quint8 nodeRole, QSGNode* const node ) const = delete;
template<>
QSGNode* QskLevelingSensorSkinlet::updateSubNode<R::OuterDisk>(const QskLevelingSensor* const sensor,
const quint8 nodeRole, QSGNode* const node) const
QSGNode* QskLevelingSensorSkinlet::updateSubNode< R::OuterDisk >(
const QskLevelingSensor* const sensor, const quint8 nodeRole, QSGNode* const node ) const
{
const auto subControl = Q::OuterDisk;
const auto contentsRect = sensor->contentsRect();
const auto boxRect = subControlRect<OuterDisk>(sensor, contentsRect);
const auto boxRect = subControlRect< OuterDisk >( sensor, contentsRect );
const auto boxShapeMetrics = QskBoxShapeMetrics{ boxRect.width() / 2 };
const auto boxBorderMetrics = sensor->boxBorderMetricsHint(subControl);
const auto boxBorderColors = sensor->boxBorderColorsHint(subControl);
const auto boxGradient = sensor->gradientHint(subControl);
const auto boxBorderMetrics = sensor->boxBorderMetricsHint( subControl );
const auto boxBorderColors = sensor->boxBorderColorsHint( subControl );
const auto boxGradient = sensor->gradientHint( subControl );
auto* const root = ensure<QSGTransformNode, par<1, QskBoxNode>>::node(node);
auto* const bNode = static_cast<QskBoxNode*>(root->firstChild());
auto* const root = ensure< QSGTransformNode, par< 1, QskBoxNode > >::node( node );
auto* const bNode = static_cast< QskBoxNode* >( root->firstChild() );
const auto size = outerRadius(sensor) * sensor->strutSizeHint(Q::OuterDisk).width();
updateBoxNode(sensor, bNode, { 0, 0, 2 * size, 2 * size }, boxShapeMetrics, boxBorderMetrics, boxBorderColors, boxGradient);
const auto size = outerRadius( sensor ) * sensor->strutSizeHint( Q::OuterDisk ).width();
updateBoxNode( sensor, bNode, { 0, 0, 2 * size, 2 * size }, boxShapeMetrics, boxBorderMetrics,
boxBorderColors, boxGradient );
const auto cX = center(sensor).x();
const auto cY = center(sensor).y();
const auto cX = center( sensor ).x();
const auto cY = center( sensor ).y();
const auto rZ = 0.0;
const auto matrix =
matrix_deg(0.0, 0.0, 0.0, cX, cY, 0) *
matrix_deg(0.0, 0.0, rZ, 0, 0, 0) *
matrix_deg(0.0, 0.0, 0.0, -size, -size, 0);
const auto matrix = matrix_deg( 0.0, 0.0, 0.0, cX, cY, 0 ) *
matrix_deg( 0.0, 0.0, rZ, 0, 0, 0 ) *
matrix_deg( 0.0, 0.0, 0.0, -size, -size, 0 );
root->setMatrix(matrix);
root->setMatrix( matrix );
return root;
}
template<>
QSGNode* QskLevelingSensorSkinlet::updateSubNode<R::Horizon>(const QskLevelingSensor* const sensor,
const quint8 nodeRole, QSGNode* const node) const
QSGNode* QskLevelingSensorSkinlet::updateSubNode< R::Horizon >(
const QskLevelingSensor* const sensor, const quint8 nodeRole, QSGNode* const node ) const
{
const auto subControl = Q::Horizon;
const auto r1 = innerRadius(sensor);
const auto cX = center(sensor).x();
const auto cY = center(sensor).y();
const auto rX = sensor->rotation().x();
const auto r1 = innerRadius( sensor );
const auto cX = center( sensor ).x();
const auto cY = center( sensor ).y();
const auto rX = sensor->subControlRotation( subControl ).x();
const auto rZ = 0.0;
const auto dY = 2 * sensor->angle().y();
const auto p = qBound(0.0, 0.5 + (-rX / dY), 1.0);
const auto p = qBound( 0.0, 0.5 + ( -rX / dY ), 1.0 );
const auto shape = QskBoxShapeMetrics{ r1 };
const auto bmetrics = sensor->boxBorderMetricsHint(subControl);
const auto bcolors = sensor->boxBorderColorsHint(subControl);
const auto bmetrics = sensor->boxBorderMetricsHint( subControl );
const auto bcolors = sensor->boxBorderColorsHint( subControl );
auto gradient = sensor->gradientHint(Q::Horizon);
gradient.setDirection(QskGradient::Linear);
gradient.setLinearDirection(Qt::Vertical);
gradient.setStops({
{0.0, gradient.startColor()},
{p, gradient.startColor()},
{p, gradient.endColor()},
{1.0, gradient.endColor()}
});
auto gradient = sensor->gradientHint( Q::Horizon );
gradient.setDirection( QskGradient::Linear );
gradient.setLinearDirection( Qt::Vertical );
gradient.setStops( { { 0.0, gradient.startColor() }, { p, gradient.startColor() },
{ p, gradient.endColor() }, { 1.0, gradient.endColor() } } );
auto* const tNode = ensure<QSGTransformNode, par<1, QskBoxNode>>::node(node);
auto* const boxNode = static_cast<QskBoxNode*>(tNode->firstChild());
updateBoxNode(sensor, boxNode, { 0, 0, 2 * r1, 2 * r1 }, shape, bmetrics, bcolors, gradient);
auto* const tNode = ensure< QSGTransformNode, par< 1, QskBoxNode > >::node( node );
auto* const boxNode = static_cast< QskBoxNode* >( tNode->firstChild() );
updateBoxNode( sensor, boxNode, { 0, 0, 2 * r1, 2 * r1 }, shape, bmetrics, bcolors, gradient );
const auto matrix =
matrix_deg(0, 0, 0, cX, cY, 0) *
matrix_deg(0, 0, rZ, 0, 0, 0) *
matrix_deg(0, 0, 0, -r1, -r1, 0);
const auto matrix = matrix_deg( 0, 0, 0, cX, cY, 0 ) * matrix_deg( 0, 0, rZ, 0, 0, 0 ) *
matrix_deg( 0, 0, 0, -r1, -r1, 0 );
tNode->setMatrix(matrix);
tNode->setMatrix( matrix );
return tNode;
}
template<>
QSGNode* QskLevelingSensorSkinlet::updateSubNode<R::TickmarksX>(const QskLevelingSensor* const sensor,
const quint8 nodeRole, QSGNode* const node) const
QSGNode* QskLevelingSensorSkinlet::updateSubNode< R::TickmarksX >(
const QskLevelingSensor* const sensor, const quint8 nodeRole, QSGNode* const node ) const
{
const auto subControl = Q::TickmarksX;
const auto color = sensor->color(subControl);
const auto scale = sensor->strutSizeHint(subControl);
const auto cX = center(sensor).x();
const auto cY = center(sensor).y();
const auto color = sensor->color( subControl );
const auto scale = sensor->strutSizeHint( subControl );
const auto rX = sensor->rotation().x();
const auto rY = sensor->rotation().y();
const auto rZ = sensor->arcMetricsHint(subControl).startAngle();
const auto cX = center( sensor ).x();
const auto cY = center( sensor ).y();
const auto r1 = innerRadius(sensor);
const auto rotation = sensor->subControlRotation( subControl );
const auto r1 = innerRadius( sensor );
const auto r2 = outerRadius( sensor );
const auto r3 = r1 * scale.height();
const auto sX = r1 / sensor->angle().x();
const auto sY = r1 / sensor->angle().y();
const auto tX = static_cast<float>(rY * sX);
const auto tY = 0.0; // static_cast<float>(rX * sY);
const auto tX = static_cast< float >( rotation.y() * sX );
const auto tY = static_cast< float >( rotation.x() * sY );
auto* const clipping = ensure<PolygonClipNode, par<1, QSGTransformNode, par<1, LinearTickmarksNode>>>::node(node);
auto* const transform = static_cast<QSGTransformNode*>(clipping->firstChild());
auto* const tickmarks = static_cast<LinearTickmarksNode*>(transform->firstChild());
auto* const clipping =
ensure< PolygonClipNode, par< 1, QSGTransformNode, par< 1, LinearTickmarksNode > > >::node(
node );
auto* const transform = static_cast< QSGTransformNode* >( clipping->firstChild() );
auto* const tickmarks = static_cast< LinearTickmarksNode* >( transform->firstChild() );
auto size = qvariant_cast<QVector3D>(sensor->effectiveSkinHint(subControl)) * r3;
auto size = qvariant_cast< QVector3D >( sensor->effectiveSkinHint( subControl ) ) * r3;
clipping->setGeometryProperties(r1, cX, cY);
clipping->setGeometryProperties( r1, cX, cY );
tickmarks->setMaterialProperties(color);
tickmarks->setGeometryProperties(sensor->tickmarks(Qt::XAxis), size, {sX, 0.0f}, {tX, tY});
tickmarks->setMaterialProperties( color );
tickmarks->setGeometryProperties(
sensor->tickmarks( Qt::XAxis ), size, { sX, 0.0f }, { tX, tY } );
const auto matrix = matrix_deg(0, 0, rZ, cX, cY, 0);
transform->setMatrix(matrix);
const auto matrix = matrix_deg( 0, 0, rotation.z(), cX, cY, 0 );
transform->setMatrix( matrix );
return clipping;
}
template<>
QSGNode* QskLevelingSensorSkinlet::updateSubNode<R::TickmarksY>(const QskLevelingSensor* const sensor,
const quint8 nodeRole, QSGNode* const node) const
QSGNode* QskLevelingSensorSkinlet::updateSubNode< R::TickmarksY >(
const QskLevelingSensor* const sensor, const quint8 nodeRole, QSGNode* const node ) const
{
const auto subControl = Q::TickmarksY;
const auto color = sensor->color(subControl);
const auto scale = sensor->strutSizeHint(subControl);
const State< QskAspect::Subcontrol > state( sensor, subControl );
const auto r1 = innerRadius(sensor);
const auto r3 = r1 * scale.width();
const auto rX = 0.00;
const auto rY = 0.00;
const auto rZ = sensor->rotation().z();
const auto color = sensor->color( subControl );
const auto scale = sensor->strutSizeHint( subControl );
const auto tX = center(sensor).x();
const auto tY = center(sensor).y();
const auto tZ = 0.0;
const auto r3 = state.r1 * scale.width();
auto* const cNode = ensure<PolygonClipNode, par<1, QSGTransformNode, par<1, LinearTickmarksNode>>>::node(node);
auto* const tNode = static_cast<QSGTransformNode*>(cNode->firstChild());
auto* const lNode = static_cast<LinearTickmarksNode*>(tNode->firstChild());
const auto rotation = sensor->subControlRotation( subControl );
auto size = qvariant_cast<QVector3D>(sensor->effectiveSkinHint(subControl)) * r3;
auto* const cNode =
ensure< PolygonClipNode, par< 1, QSGTransformNode, par< 1, LinearTickmarksNode > > >::node(
node );
auto* const tNode = static_cast< QSGTransformNode* >( cNode->firstChild() );
auto* const lNode = static_cast< LinearTickmarksNode* >( tNode->firstChild() );
cNode->setGeometryProperties(r1, tX, tY);
auto size = qvariant_cast< QVector3D >( sensor->effectiveSkinHint( subControl ) ) * r3;
const auto sY = static_cast<float>(r1 / sensor->angle().y());
lNode->setMaterialProperties(color);
#ifdef USE_FILTERING
using TickType = QskScaleTickmarks::TickType;
const auto filter = [=](TickType, qreal v){ return rY - r1 / sY <= v && v <= rY + r1 / sY; };
lNode->setGeometryProperties(filtered(sensor->tickmarks(Qt::YAxis), filter), size, {0.0f, sY}, {}, 1.0f, true);
#else
lNode->setGeometryProperties(sensor->tickmarks(Qt::YAxis), size, {0.0f, sY});
#endif
cNode->setGeometryProperties( state.r1, state.cX, state.cY );
const auto matrix = matrix_deg(rX, rY, rZ, tX, tY, tZ);
tNode->setMatrix(matrix);
const auto sY = static_cast< float >( state.r1 / sensor->angle().y() );
lNode->setMaterialProperties( color );
lNode->setGeometryProperties( sensor->tickmarks( Qt::YAxis ), size, { 0.0f, sY },
{ ( float ) state.tX, ( float ) state.tY } );
const auto matrix = matrix_deg( 0, 0, state.rZ, state.cX, state.cY );
tNode->setMatrix( matrix );
return cNode;
}
template<>
QSGNode* QskLevelingSensorSkinlet::updateSubNode<R::TickmarksZ>(const QskLevelingSensor* const sensor,
const quint8 nodeRole, QSGNode* const node) const
QSGNode* QskLevelingSensorSkinlet::updateSubNode< R::TickmarksZ >(
const QskLevelingSensor* const sensor, const quint8 nodeRole, QSGNode* const node ) const
{
const auto subControl = Q::TickmarksZ;
const auto color = sensor->color(subControl);
const auto scale = sensor->strutSizeHint(subControl);
const auto r1 = innerRadius(sensor);
const auto r2 = outerRadius(sensor);
const auto r3 = qvariant_cast<QVector3D>(sensor->effectiveSkinHint(subControl)) * (r2 - r1) + QVector3D{r1, r1, r1};
const auto color = sensor->color( subControl );
const auto scale = sensor->strutSizeHint( subControl );
auto* const transform = ensure<QSGTransformNode, par<1,RadialTickmarksNode>>::node(node);
auto* const tickmarksNode = static_cast<RadialTickmarksNode*>(transform->firstChild());
tickmarksNode->setMaterialProperties(color);
tickmarksNode->setGeometryProperties(sensor->tickmarks(Qt::ZAxis), r1, r3);
const auto r1 = innerRadius( sensor );
const auto r2 = outerRadius( sensor );
const auto r3 =
qvariant_cast< QVector3D >( sensor->effectiveSkinHint( subControl ) ) * ( r2 - r1 ) +
QVector3D{ r1, r1, r1 };
const auto rZ = sensor->arcMetricsHint(subControl).startAngle();
const auto tX = center(sensor).x();
const auto tY = center(sensor).y();
auto* const transform = ensure< QSGTransformNode, par< 1, RadialTickmarksNode > >::node( node );
auto* const tickmarksNode = static_cast< RadialTickmarksNode* >( transform->firstChild() );
tickmarksNode->setMaterialProperties( color );
tickmarksNode->setGeometryProperties( sensor->tickmarks( Qt::ZAxis ), r1, r3 );
const auto matrix = matrix_deg(0.0, 0.0, rZ, tX, tY);
transform->setMatrix(matrix);
const auto rZ = sensor->subControlRotation( subControl ).z();
const auto tX = center( sensor ).x();
const auto tY = center( sensor ).y();
const auto matrix = matrix_deg( 0.0, 0.0, rZ, tX, tY );
transform->setMatrix( matrix );
return transform;
}
template<>
QSGNode* QskLevelingSensorSkinlet::updateSubNode<R::TickmarksXLabels>(const QskLevelingSensor* const sensor,
const quint8 nodeRole, QSGNode* const node) const
QSGNode* QskLevelingSensorSkinlet::updateSubNode< R::TickmarksXLabels >(
const QskLevelingSensor* const sensor, const quint8 nodeRole, QSGNode* const node ) const
{
const auto subControl = Q::TickmarksXLabels;
const auto r1 = innerRadius(sensor);
const auto r3 = static_cast<float>(r1 * sensor->strutSizeHint(Q::TickmarksX).height());
const auto r1 = innerRadius( sensor );
const auto r3 = static_cast< float >( r1 * sensor->strutSizeHint( Q::TickmarksX ).height() );
const auto sX = r1 / sensor->angle().x();
const auto sY = r1 / sensor->angle().y();
const auto rZ = sensor->arcMetricsHint(subControl).startAngle();
const auto cX = center(sensor).x();
const auto cY = center(sensor).y();
const auto tX = sensor->rotation().y() * sX;
const auto tY = r3;
auto* const cNode = ensure<PolygonClipNode, par<1, QSGTransformNode, par<1, LinearTickmarksLabelsNode>>>::node(node);
auto* const tNode = static_cast<QSGTransformNode*>(cNode->firstChild());
auto* const lNode = static_cast<LinearTickmarksLabelsNode*>(tNode->firstChild());
tNode->setMatrix(matrix_deg(0.0, 0.0, rZ, cX, cY));
cNode->setGeometryProperties(r1, center(sensor).x(), center(sensor).y());
lNode->update(sensor, subControl, sensor->tickmarkLabels(Qt::XAxis), { sX , 0.0}, {tX, tY});
const auto rotation = sensor->subControlRotation( subControl );
const auto rZ = rotation.z();
const auto cX = center( sensor ).x();
const auto cY = center( sensor ).y();
const auto tX = rotation.y() * sX;
const auto tY = r3 + rotation.x() * sY;
auto* const cNode = ensure< PolygonClipNode,
par< 1, QSGTransformNode, par< 1, LinearTickmarksLabelsNode > > >::node( node );
auto* const tNode = static_cast< QSGTransformNode* >( cNode->firstChild() );
auto* const lNode = static_cast< LinearTickmarksLabelsNode* >( tNode->firstChild() );
tNode->setMatrix( matrix_deg( 0.0, 0.0, rZ, cX, cY ) );
cNode->setGeometryProperties( r1, center( sensor ).x(), center( sensor ).y() );
lNode->update(
sensor, subControl, sensor->tickmarkLabels( Qt::XAxis ), { sX, 0.0 }, { tX, tY } );
return cNode;
}
template<>
QSGNode* QskLevelingSensorSkinlet::updateSubNode<R::TickmarksYLabels>(const QskLevelingSensor* const sensor,
const quint8 nodeRole, QSGNode* const node) const
QSGNode* QskLevelingSensorSkinlet::updateSubNode< R::TickmarksYLabels >(
const QskLevelingSensor* const sensor, const quint8 nodeRole, QSGNode* const node ) const
{
const auto subControl = Q::TickmarksYLabels;
const auto r1 = innerRadius(sensor);
const auto r3 = static_cast<float>(r1 * sensor->strutSizeHint(Q::TickmarksY).width());
const auto cX = static_cast<float>(center(sensor).x());
const auto cY = static_cast<float>(center(sensor).y());
const auto rZ = sensor->rotation().z();
auto* const cNode = ensure<PolygonClipNode, par<1, QSGTransformNode, par<1, LinearTickmarksLabelsNode>>>::node(node);
auto* const tNode = static_cast<QSGTransformNode*>(cNode->firstChild());
auto* const lNode = static_cast<LinearTickmarksLabelsNode*>(tNode->firstChild());
cNode->setGeometryProperties(r1, cX, cY);
tNode->setMatrix(matrix_deg(0.0, 0.0, 0, cX, cY));
lNode->update(sensor, subControl, sensor->tickmarkLabels(Qt::YAxis), { 0.0, r1 / sensor->angle().y() }, {r3, 0.0});
const auto r1 = innerRadius( sensor );
const auto r3 = static_cast< float >( r1 * sensor->strutSizeHint( Q::TickmarksY ).width() );
const auto cX = static_cast< float >( center( sensor ).x() );
const auto cY = static_cast< float >( center( sensor ).y() );
const auto scale = sensor->strutSizeHint( subControl );
const auto angles = sensor->angle();
const auto rotation = sensor->subControlRotation( subControl );
const auto sX = r1 / angles.x();
const auto sY = r1 / angles.y();
const auto tX = static_cast< float >( rotation.y() * sX );
const auto tY = static_cast< float >( rotation.x() * sY );
auto* const cNode = ensure< PolygonClipNode,
par< 1, QSGTransformNode, par< 1, LinearTickmarksLabelsNode > > >::node( node );
auto* const tNode = static_cast< QSGTransformNode* >( cNode->firstChild() );
auto* const lNode = static_cast< LinearTickmarksLabelsNode* >( tNode->firstChild() );
cNode->setGeometryProperties( r1, cX, cY );
tNode->setMatrix( matrix_deg( 0.0, 0.0, rotation.z(), cX, cY ) );
lNode->update( sensor, subControl, sensor->tickmarkLabels( Qt::YAxis ),
{ 0.0, r1 / sensor->angle().y() }, { r3 + tX, tY } );
return cNode;
}
template<>
QSGNode* QskLevelingSensorSkinlet::updateSubNode<R::TickmarksZLabels>(const QskLevelingSensor* const sensor,
const quint8 nodeRole, QSGNode* const node) const
QSGNode* QskLevelingSensorSkinlet::updateSubNode< R::TickmarksZLabels >(
const QskLevelingSensor* const sensor, const quint8 nodeRole, QSGNode* const node ) const
{
const auto subControl = Q::TickmarksZLabels;
auto* const tNode = ensure<QSGTransformNode, par<1,RadialTickmarksLabelsNode>>::node(node);
auto* const lNode = static_cast<RadialTickmarksLabelsNode*>(tNode->firstChild());
const auto r1 = innerRadius(sensor);
const auto r3 = static_cast<float>(r1 * sensor->strutSizeHint(subControl).width());
const auto cX = static_cast<float>(center(sensor).x());
const auto cY = static_cast<float>(center(sensor).y());
const auto rZ = sensor->arcMetricsHint(subControl).startAngle();
lNode->update(sensor, subControl, sensor->tickmarkLabels(Qt::ZAxis), { r3, r3 });
tNode->setMatrix(matrix_deg(0.0, 0.0, rZ, cX, cY));
auto* const tNode =
ensure< QSGTransformNode, par< 1, RadialTickmarksLabelsNode > >::node( node );
auto* const lNode = static_cast< RadialTickmarksLabelsNode* >( tNode->firstChild() );
const auto r1 = innerRadius( sensor );
const auto r3 = static_cast< float >( r1 * sensor->strutSizeHint( subControl ).width() );
const auto cX = static_cast< float >( center( sensor ).x() );
const auto cY = static_cast< float >( center( sensor ).y() );
const auto rZ = sensor->subControlRotation( subControl ).z();
lNode->update( sensor, subControl, sensor->tickmarkLabels( Qt::ZAxis ), { r3, r3 } );
tNode->setMatrix( matrix_deg( 0.0, 0.0, rZ, cX, cY ) );
return tNode;
}
template<>
QSGNode* QskLevelingSensorSkinlet::updateSubNode<R::HorizonClip>(const QskLevelingSensor* const sensor,
const quint8 nodeRole, QSGNode* const node) const
QSGNode* QskLevelingSensorSkinlet::updateSubNode< R::HorizonClip >(
const QskLevelingSensor* const sensor, const quint8 nodeRole, QSGNode* const node ) const
{
const auto cX = center(sensor).x();
const auto cY = center(sensor).y();
const auto r1 = innerRadius(sensor);
const auto cX = center( sensor ).x();
const auto cY = center( sensor ).y();
const auto r1 = innerRadius( sensor );
auto* const clipNode = ensure<PolygonClipNode>::node(node);
clipNode->setGeometryProperties(r1, cX, cY);
auto* const clipNode = ensure< PolygonClipNode >::node( node );
clipNode->setGeometryProperties( r1, cX, cY );
return clipNode;
}
QSGNode* QskLevelingSensorSkinlet::updateSubNode(
const QskSkinnable* const skinnable, const quint8 nodeRole, QSGNode* const node) const
const QskSkinnable* const skinnable, const quint8 nodeRole, QSGNode* const node ) const
{
const auto* const sensor = static_cast<const Q*>(skinnable);
const auto* const sensor = static_cast< const Q* >( skinnable );
const auto subControl = [nodeRole, sensor](){
switch(static_cast<R>(nodeRole))
const auto subControl = [ nodeRole, sensor ]() {
switch ( static_cast< R >( nodeRole ) )
{
case OuterDisk: return Q::OuterDisk;
case Horizon: return Q::Horizon;
case HorizonClip: return Q::Horizon;
case TickmarksX: return Q::TickmarksX;
case TickmarksXLabels: return Q::TickmarksXLabels;
case TickmarksY: return Q::TickmarksY;
case TickmarksYLabels: return Q::TickmarksYLabels;
case TickmarksZ: return Q::TickmarksZ;
case TickmarksZLabels: return Q::TickmarksZLabels;
default: return QskAspect::NoSubcontrol;
case OuterDisk:
return Q::OuterDisk;
case Horizon:
return Q::Horizon;
case HorizonClip:
return Q::Horizon;
case TickmarksX:
return Q::TickmarksX;
case TickmarksXLabels:
return Q::TickmarksXLabels;
case TickmarksY:
return Q::TickmarksY;
case TickmarksYLabels:
return Q::TickmarksYLabels;
case TickmarksZ:
return Q::TickmarksZ;
case TickmarksZLabels:
return Q::TickmarksZLabels;
default:
return QskAspect::NoSubcontrol;
}
}();
if (qvariant_cast<bool>(sensor->effectiveSkinHint(subControl | QskAspect::Option)))
if ( qvariant_cast< bool >( sensor->effectiveSkinHint( subControl | QskAspect::Option ) ) )
{
return nullptr;
}
switch(static_cast<R>(nodeRole))
switch ( static_cast< R >( nodeRole ) )
{
case OuterDisk: return updateSubNode<OuterDisk>(sensor, nodeRole, node);
case Horizon: return updateSubNode<Horizon>(sensor, nodeRole, node);
case HorizonClip: return updateSubNode<HorizonClip>(sensor, nodeRole, node);
case TickmarksX: return updateSubNode<TickmarksX>(sensor, nodeRole, node);
case TickmarksXLabels: return updateSubNode<TickmarksXLabels>(sensor, nodeRole, node);
case TickmarksY: return updateSubNode<TickmarksY>(sensor, nodeRole, node);
case TickmarksYLabels: return updateSubNode<TickmarksYLabels>(sensor, nodeRole, node);
case TickmarksZ: return updateSubNode<TickmarksZ>(sensor, nodeRole, node);
case TickmarksZLabels: return updateSubNode<TickmarksZLabels>(sensor, nodeRole, node);
default: return Inherited::updateSubNode(sensor, nodeRole, node);
case OuterDisk:
return updateSubNode< OuterDisk >( sensor, nodeRole, node );
case Horizon:
return updateSubNode< Horizon >( sensor, nodeRole, node );
case HorizonClip:
return updateSubNode< HorizonClip >( sensor, nodeRole, node );
case TickmarksX:
return updateSubNode< TickmarksX >( sensor, nodeRole, node );
case TickmarksXLabels:
return updateSubNode< TickmarksXLabels >( sensor, nodeRole, node );
case TickmarksY:
return updateSubNode< TickmarksY >( sensor, nodeRole, node );
case TickmarksYLabels:
return updateSubNode< TickmarksYLabels >( sensor, nodeRole, node );
case TickmarksZ:
return updateSubNode< TickmarksZ >( sensor, nodeRole, node );
case TickmarksZLabels:
return updateSubNode< TickmarksZLabels >( sensor, nodeRole, node );
default:
return Inherited::updateSubNode( sensor, nodeRole, node );
}
}