add rotation and state per subcontrol
This commit is contained in:
parent
77c39cdd05
commit
10fa1e4a69
|
@ -1,10 +1,13 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "QskLevelingSensorUtility.h"
|
||||||
|
|
||||||
#include <QSGGeometry>
|
#include <QSGGeometry>
|
||||||
#include <QSGGeometryNode>
|
#include <QSGGeometryNode>
|
||||||
#include <QSGFlatColorMaterial>
|
#include <QSGFlatColorMaterial>
|
||||||
|
|
||||||
#include <QFontMetricsF>
|
#include <QFontMetricsF>
|
||||||
|
#include <qmath.h>
|
||||||
|
|
||||||
class RadialTickmarksNode final : public QSGGeometryNode
|
class RadialTickmarksNode final : public QSGGeometryNode
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#include "QskLevelingSensorSkinlet.h"
|
#include "QskLevelingSensorSkinlet.h"
|
||||||
#include "QskLevelingSensor.h"
|
#include "QskLevelingSensor.h"
|
||||||
#include "QskLevelingSensorNodes.h"
|
|
||||||
#include "QskLevelingSensorUtility.h"
|
#include "QskLevelingSensorUtility.h"
|
||||||
|
#include "QskLevelingSensorNodes.h"
|
||||||
#include "QskSGNodeUtility.h"
|
#include "QskSGNodeUtility.h"
|
||||||
|
|
||||||
#include <QskArcMetrics.h>
|
#include <QskArcMetrics.h>
|
||||||
|
@ -50,6 +50,11 @@ namespace
|
||||||
, sZ( r1 / sensor->angle().z() )
|
, sZ( r1 / sensor->angle().z() )
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Q_REQUIRED_RESULT QVector3D scale() const noexcept
|
||||||
|
{
|
||||||
|
return {(float)sX, (float)sY, (float)sZ};
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
|
@ -72,6 +77,16 @@ namespace
|
||||||
, tZ( 0.0 )
|
, tZ( 0.0 )
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Q_REQUIRED_RESULT QVector3D translation() const noexcept
|
||||||
|
{
|
||||||
|
return {(float)tX, (float)tY, (float)tZ};
|
||||||
|
}
|
||||||
|
|
||||||
|
Q_REQUIRED_RESULT QMatrix4x4 matrix() const noexcept
|
||||||
|
{
|
||||||
|
return matrix_deg( 0, 0, rZ, cX, cY );
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -176,7 +191,7 @@ QSGNode* QskLevelingSensorSkinlet::updateSubNode< R::OuterDisk >(
|
||||||
const auto boxBorderColors = sensor->boxBorderColorsHint( subControl );
|
const auto boxBorderColors = sensor->boxBorderColorsHint( subControl );
|
||||||
const auto boxGradient = sensor->gradientHint( subControl );
|
const auto boxGradient = sensor->gradientHint( subControl );
|
||||||
|
|
||||||
auto* const root = ensure< QSGTransformNode, par< 1, QskBoxNode > >::node( node );
|
auto* const root = ensureNode< QSGTransformNode, QskBoxNode >( node );
|
||||||
auto* const bNode = static_cast< QskBoxNode* >( root->firstChild() );
|
auto* const bNode = static_cast< QskBoxNode* >( root->firstChild() );
|
||||||
|
|
||||||
const auto size = outerRadius( sensor ) * sensor->strutSizeHint( Q::OuterDisk ).width();
|
const auto size = outerRadius( sensor ) * sensor->strutSizeHint( Q::OuterDisk ).width();
|
||||||
|
@ -200,30 +215,27 @@ QSGNode* QskLevelingSensorSkinlet::updateSubNode< R::Horizon >(
|
||||||
const QskLevelingSensor* const sensor, const quint8 nodeRole, QSGNode* const node ) const
|
const QskLevelingSensor* const sensor, const quint8 nodeRole, QSGNode* const node ) const
|
||||||
{
|
{
|
||||||
const auto subControl = Q::Horizon;
|
const auto subControl = Q::Horizon;
|
||||||
const auto r1 = innerRadius( sensor );
|
const State<QskAspect::Subcontrol> state(sensor, subControl);
|
||||||
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 shape = QskBoxShapeMetrics{ r1 };
|
const auto dY = 2 * sensor->angle().y();
|
||||||
const auto bmetrics = sensor->boxBorderMetricsHint( subControl );
|
const auto pY = qBound( 0.0, 0.5 + ( -state.rX / dY ), 1.0 );
|
||||||
const auto bcolors = sensor->boxBorderColorsHint( subControl );
|
|
||||||
|
const auto shape = QskBoxShapeMetrics{ state.r1 };
|
||||||
|
const auto metrics = sensor->boxBorderMetricsHint( subControl );
|
||||||
|
const auto colors = sensor->boxBorderColorsHint( subControl );
|
||||||
|
|
||||||
auto gradient = sensor->gradientHint( Q::Horizon );
|
auto gradient = sensor->gradientHint( Q::Horizon );
|
||||||
gradient.setDirection( QskGradient::Linear );
|
gradient.setDirection( QskGradient::Linear );
|
||||||
gradient.setLinearDirection( Qt::Vertical );
|
gradient.setLinearDirection( Qt::Vertical );
|
||||||
gradient.setStops( { { 0.0, gradient.startColor() }, { p, gradient.startColor() },
|
gradient.setStops( { { 0.0, gradient.startColor() }, { pY, gradient.startColor() },
|
||||||
{ p, gradient.endColor() }, { 1.0, gradient.endColor() } } );
|
{ pY, gradient.endColor() }, { 1.0, gradient.endColor() } } );
|
||||||
|
|
||||||
auto* const tNode = ensure< QSGTransformNode, par< 1, QskBoxNode > >::node( node );
|
auto* const tNode = ensureNode< QSGTransformNode, QskBoxNode >( node );
|
||||||
auto* const boxNode = static_cast< QskBoxNode* >( tNode->firstChild() );
|
auto* const boxNode = static_cast< QskBoxNode* >( tNode->firstChild() );
|
||||||
updateBoxNode( sensor, boxNode, { 0, 0, 2 * r1, 2 * r1 }, shape, bmetrics, bcolors, gradient );
|
updateBoxNode( sensor, boxNode, { 0, 0, 2 * state.r1, 2 * state.r1 }, shape, metrics, colors, gradient );
|
||||||
|
|
||||||
const auto matrix = matrix_deg( 0, 0, 0, cX, cY, 0 ) * matrix_deg( 0, 0, rZ, 0, 0, 0 ) *
|
const auto matrix = matrix_deg( 0, 0, 0, state.cX, state.cY, 0 ) *
|
||||||
matrix_deg( 0, 0, 0, -r1, -r1, 0 );
|
matrix_deg( 0, 0, 0, -state.r1, -state.r1, 0 );
|
||||||
|
|
||||||
tNode->setMatrix( matrix );
|
tNode->setMatrix( matrix );
|
||||||
return tNode;
|
return tNode;
|
||||||
|
@ -234,39 +246,26 @@ QSGNode* QskLevelingSensorSkinlet::updateSubNode< R::TickmarksX >(
|
||||||
const QskLevelingSensor* const sensor, const quint8 nodeRole, QSGNode* const node ) const
|
const QskLevelingSensor* const sensor, const quint8 nodeRole, QSGNode* const node ) const
|
||||||
{
|
{
|
||||||
const auto subControl = Q::TickmarksX;
|
const auto subControl = Q::TickmarksX;
|
||||||
|
State<QskAspect::Subcontrol> state(sensor, subControl);
|
||||||
const auto color = sensor->color( subControl );
|
const auto color = sensor->color( subControl );
|
||||||
const auto scale = sensor->strutSizeHint( subControl );
|
const auto scale = sensor->strutSizeHint( subControl );
|
||||||
|
const auto r3 = state.r1 * scale.height();
|
||||||
const auto cX = center( sensor ).x();
|
|
||||||
const auto cY = center( sensor ).y();
|
|
||||||
|
|
||||||
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 >( rotation.y() * sX );
|
|
||||||
const auto tY = static_cast< float >( rotation.x() * sY );
|
|
||||||
|
|
||||||
auto* const clipping =
|
auto* const clipping =
|
||||||
ensure< PolygonClipNode, par< 1, QSGTransformNode, par< 1, LinearTickmarksNode > > >::node(
|
ensureNode< PolygonClipNode, QSGTransformNode, LinearTickmarksNode >(
|
||||||
node );
|
node );
|
||||||
auto* const transform = static_cast< QSGTransformNode* >( clipping->firstChild() );
|
auto* const transform = static_cast< QSGTransformNode* >( clipping->firstChild() );
|
||||||
auto* const tickmarks = static_cast< LinearTickmarksNode* >( transform->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( state.r1, state.cX, state.cY );
|
||||||
|
|
||||||
tickmarks->setMaterialProperties( color );
|
tickmarks->setMaterialProperties( color );
|
||||||
tickmarks->setGeometryProperties(
|
tickmarks->setGeometryProperties( sensor->tickmarks( Qt::XAxis ), size,
|
||||||
sensor->tickmarks( Qt::XAxis ), size, { sX, 0.0f }, { tX, tY } );
|
{ state.scale().x(), 0.0f }, state.translation().toVector2D() );
|
||||||
|
|
||||||
const auto matrix = matrix_deg( 0, 0, rotation.z(), cX, cY, 0 );
|
const auto matrix = matrix_deg( 0, 0, state.rZ, state.cX, state.cY );
|
||||||
transform->setMatrix( matrix );
|
transform->setMatrix( matrix );
|
||||||
return clipping;
|
return clipping;
|
||||||
}
|
}
|
||||||
|
@ -286,7 +285,7 @@ QSGNode* QskLevelingSensorSkinlet::updateSubNode< R::TickmarksY >(
|
||||||
const auto rotation = sensor->subControlRotation( subControl );
|
const auto rotation = sensor->subControlRotation( subControl );
|
||||||
|
|
||||||
auto* const cNode =
|
auto* const cNode =
|
||||||
ensure< PolygonClipNode, par< 1, QSGTransformNode, par< 1, LinearTickmarksNode > > >::node(
|
ensureNode< PolygonClipNode,QSGTransformNode, LinearTickmarksNode>(
|
||||||
node );
|
node );
|
||||||
auto* const tNode = static_cast< QSGTransformNode* >( cNode->firstChild() );
|
auto* const tNode = static_cast< QSGTransformNode* >( cNode->firstChild() );
|
||||||
auto* const lNode = static_cast< LinearTickmarksNode* >( tNode->firstChild() );
|
auto* const lNode = static_cast< LinearTickmarksNode* >( tNode->firstChild() );
|
||||||
|
@ -297,11 +296,10 @@ QSGNode* QskLevelingSensorSkinlet::updateSubNode< R::TickmarksY >(
|
||||||
|
|
||||||
const auto sY = static_cast< float >( state.r1 / sensor->angle().y() );
|
const auto sY = static_cast< float >( state.r1 / sensor->angle().y() );
|
||||||
lNode->setMaterialProperties( color );
|
lNode->setMaterialProperties( color );
|
||||||
lNode->setGeometryProperties( sensor->tickmarks( Qt::YAxis ), size, { 0.0f, sY },
|
lNode->setGeometryProperties( sensor->tickmarks( Qt::YAxis ), size, { 0.0f, state.scale().y() },
|
||||||
{ ( float ) state.tX, ( float ) state.tY } );
|
{ ( float ) state.tX, ( float ) state.tY } );
|
||||||
|
|
||||||
const auto matrix = matrix_deg( 0, 0, state.rZ, state.cX, state.cY );
|
tNode->setMatrix( state.matrix() );
|
||||||
tNode->setMatrix( matrix );
|
|
||||||
return cNode;
|
return cNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -310,25 +308,20 @@ QSGNode* QskLevelingSensorSkinlet::updateSubNode< R::TickmarksZ >(
|
||||||
const QskLevelingSensor* const sensor, const quint8 nodeRole, QSGNode* const node ) const
|
const QskLevelingSensor* const sensor, const quint8 nodeRole, QSGNode* const node ) const
|
||||||
{
|
{
|
||||||
const auto subControl = Q::TickmarksZ;
|
const auto subControl = Q::TickmarksZ;
|
||||||
|
const State< QskAspect::Subcontrol > state( sensor, subControl );
|
||||||
const auto color = sensor->color( subControl );
|
const auto color = sensor->color( subControl );
|
||||||
const auto scale = sensor->strutSizeHint( subControl );
|
const auto scale = sensor->strutSizeHint( subControl );
|
||||||
|
|
||||||
const auto r1 = innerRadius( sensor );
|
|
||||||
const auto r2 = outerRadius( sensor );
|
|
||||||
const auto r3 =
|
const auto r3 =
|
||||||
qvariant_cast< QVector3D >( sensor->effectiveSkinHint( subControl ) ) * ( r2 - r1 ) +
|
qvariant_cast< QVector3D >( sensor->effectiveSkinHint( subControl ) ) * ( state.r2 - state.r1 ) +
|
||||||
QVector3D{ r1, r1, r1 };
|
QVector3D{ (float)state.r1, (float)state.r1, (float)state.r1 };
|
||||||
|
|
||||||
auto* const transform = ensure< QSGTransformNode, par< 1, RadialTickmarksNode > >::node( node );
|
auto* const transform = ensureNode< QSGTransformNode, RadialTickmarksNode >( node );
|
||||||
auto* const tickmarksNode = static_cast< RadialTickmarksNode* >( transform->firstChild() );
|
auto* const tickmarksNode = static_cast< RadialTickmarksNode* >( transform->firstChild() );
|
||||||
tickmarksNode->setMaterialProperties( color );
|
tickmarksNode->setMaterialProperties( color );
|
||||||
tickmarksNode->setGeometryProperties( sensor->tickmarks( Qt::ZAxis ), r1, r3 );
|
tickmarksNode->setGeometryProperties( sensor->tickmarks( Qt::ZAxis ), state.r1, r3 );
|
||||||
|
|
||||||
const auto rZ = sensor->subControlRotation( subControl ).z();
|
const auto matrix = matrix_deg( 0.0, 0.0, state.rZ, state.cX, state.cY );
|
||||||
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 );
|
transform->setMatrix( matrix );
|
||||||
return transform;
|
return transform;
|
||||||
}
|
}
|
||||||
|
@ -338,28 +331,18 @@ QSGNode* QskLevelingSensorSkinlet::updateSubNode< R::TickmarksXLabels >(
|
||||||
const QskLevelingSensor* const sensor, const quint8 nodeRole, QSGNode* const node ) const
|
const QskLevelingSensor* const sensor, const quint8 nodeRole, QSGNode* const node ) const
|
||||||
{
|
{
|
||||||
const auto subControl = Q::TickmarksXLabels;
|
const auto subControl = Q::TickmarksXLabels;
|
||||||
|
const State< QskAspect::Subcontrol > state( sensor, subControl );
|
||||||
|
const auto r3 = static_cast< float >( state.r1 * sensor->strutSizeHint( Q::TickmarksX ).height() );
|
||||||
|
const auto translation = state.translation().toVector2D() + QVector2D{0, r3};
|
||||||
|
|
||||||
const auto r1 = innerRadius( sensor );
|
auto* const cNode =
|
||||||
const auto r3 = static_cast< float >( r1 * sensor->strutSizeHint( Q::TickmarksX ).height() );
|
ensureNode< PolygonClipNode, QSGTransformNode, LinearTickmarksLabelsNode >( node );
|
||||||
const auto sX = r1 / sensor->angle().x();
|
|
||||||
const auto sY = r1 / sensor->angle().y();
|
|
||||||
|
|
||||||
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 tNode = static_cast< QSGTransformNode* >( cNode->firstChild() );
|
||||||
auto* const lNode = static_cast< LinearTickmarksLabelsNode* >( tNode->firstChild() );
|
auto* const lNode = static_cast< LinearTickmarksLabelsNode* >( tNode->firstChild() );
|
||||||
tNode->setMatrix( matrix_deg( 0.0, 0.0, rZ, cX, cY ) );
|
cNode->setGeometryProperties( state.r1, state.cX, state.cY );
|
||||||
cNode->setGeometryProperties( r1, center( sensor ).x(), center( sensor ).y() );
|
tNode->setMatrix( state.matrix() );
|
||||||
lNode->update(
|
lNode->update(
|
||||||
sensor, subControl, sensor->tickmarkLabels( Qt::XAxis ), { sX, 0.0 }, { tX, tY } );
|
sensor, subControl, sensor->tickmarkLabels( Qt::XAxis ), { state.scale().x(), 0.0 }, translation );
|
||||||
return cNode;
|
return cNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -368,27 +351,21 @@ QSGNode* QskLevelingSensorSkinlet::updateSubNode< R::TickmarksYLabels >(
|
||||||
const QskLevelingSensor* const sensor, const quint8 nodeRole, QSGNode* const node ) const
|
const QskLevelingSensor* const sensor, const quint8 nodeRole, QSGNode* const node ) const
|
||||||
{
|
{
|
||||||
const auto subControl = Q::TickmarksYLabels;
|
const auto subControl = Q::TickmarksYLabels;
|
||||||
const auto r1 = innerRadius( sensor );
|
const State< QskAspect::Subcontrol > state( sensor, subControl );
|
||||||
const auto r3 = static_cast< float >( r1 * sensor->strutSizeHint( Q::TickmarksY ).width() );
|
const auto r3 = static_cast< float >( state.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 scale = sensor->strutSizeHint( subControl );
|
||||||
const auto angles = sensor->angle();
|
const auto angles = sensor->angle();
|
||||||
const auto rotation = sensor->subControlRotation( subControl );
|
const auto rotation = sensor->subControlRotation( subControl );
|
||||||
const auto sX = r1 / angles.x();
|
const auto translation = state.translation().toVector2D() + QVector2D( r3, 0 );
|
||||||
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,
|
auto* const cNode = ensureNode< PolygonClipNode, QSGTransformNode, LinearTickmarksLabelsNode >( node );
|
||||||
par< 1, QSGTransformNode, par< 1, LinearTickmarksLabelsNode > > >::node( node );
|
|
||||||
auto* const tNode = static_cast< QSGTransformNode* >( cNode->firstChild() );
|
auto* const tNode = static_cast< QSGTransformNode* >( cNode->firstChild() );
|
||||||
auto* const lNode = static_cast< LinearTickmarksLabelsNode* >( tNode->firstChild() );
|
auto* const lNode = static_cast< LinearTickmarksLabelsNode* >( tNode->firstChild() );
|
||||||
cNode->setGeometryProperties( r1, cX, cY );
|
cNode->setGeometryProperties( state.r1, state.cX, state.cY );
|
||||||
tNode->setMatrix( matrix_deg( 0.0, 0.0, rotation.z(), cX, cY ) );
|
tNode->setMatrix( state.matrix() );
|
||||||
lNode->update( sensor, subControl, sensor->tickmarkLabels( Qt::YAxis ),
|
lNode->update( sensor, subControl, sensor->tickmarkLabels( Qt::YAxis ),
|
||||||
{ 0.0, r1 / sensor->angle().y() }, { r3 + tX, tY } );
|
{ 0.0, state.scale().y() }, translation );
|
||||||
return cNode;
|
return cNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -397,16 +374,12 @@ QSGNode* QskLevelingSensorSkinlet::updateSubNode< R::TickmarksZLabels >(
|
||||||
const QskLevelingSensor* const sensor, const quint8 nodeRole, QSGNode* const node ) const
|
const QskLevelingSensor* const sensor, const quint8 nodeRole, QSGNode* const node ) const
|
||||||
{
|
{
|
||||||
const auto subControl = Q::TickmarksZLabels;
|
const auto subControl = Q::TickmarksZLabels;
|
||||||
auto* const tNode =
|
const State< QskAspect::Subcontrol > state( sensor, subControl );
|
||||||
ensure< QSGTransformNode, par< 1, RadialTickmarksLabelsNode > >::node( node );
|
auto* const tNode = ensureNode< QSGTransformNode, RadialTickmarksLabelsNode>( node );
|
||||||
auto* const lNode = static_cast< RadialTickmarksLabelsNode* >( tNode->firstChild() );
|
auto* const lNode = static_cast< RadialTickmarksLabelsNode* >( tNode->firstChild() );
|
||||||
const auto r1 = innerRadius( sensor );
|
const auto r3 = static_cast< float >( state.r1 * sensor->strutSizeHint( subControl ).width() );
|
||||||
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 } );
|
lNode->update( sensor, subControl, sensor->tickmarkLabels( Qt::ZAxis ), { r3, r3 } );
|
||||||
tNode->setMatrix( matrix_deg( 0.0, 0.0, rZ, cX, cY ) );
|
tNode->setMatrix( state.matrix() );
|
||||||
return tNode;
|
return tNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -418,7 +391,7 @@ QSGNode* QskLevelingSensorSkinlet::updateSubNode< R::HorizonClip >(
|
||||||
const auto cY = center( sensor ).y();
|
const auto cY = center( sensor ).y();
|
||||||
const auto r1 = innerRadius( sensor );
|
const auto r1 = innerRadius( sensor );
|
||||||
|
|
||||||
auto* const clipNode = ensure< PolygonClipNode >::node( node );
|
auto* const clipNode = ensureNode< PolygonClipNode >( node );
|
||||||
clipNode->setGeometryProperties( r1, cX, cY );
|
clipNode->setGeometryProperties( r1, cX, cY );
|
||||||
return clipNode;
|
return clipNode;
|
||||||
}
|
}
|
||||||
|
@ -454,6 +427,7 @@ QSGNode* QskLevelingSensorSkinlet::updateSubNode(
|
||||||
}
|
}
|
||||||
}();
|
}();
|
||||||
|
|
||||||
|
// use the subcontrol's option hint to hide it (default is visible)
|
||||||
if ( qvariant_cast< bool >( sensor->effectiveSkinHint( subControl | QskAspect::Option ) ) )
|
if ( qvariant_cast< bool >( sensor->effectiveSkinHint( subControl | QskAspect::Option ) ) )
|
||||||
{
|
{
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
|
@ -39,7 +39,7 @@ inline Q_REQUIRED_RESULT QMatrix4x4 matrix_deg(
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline bool compareExchange(T& dst, const T& src)
|
inline Q_REQUIRED_RESULT bool compareExchange(T& dst, const T& src)
|
||||||
{
|
{
|
||||||
if (dst != src)
|
if (dst != src)
|
||||||
{
|
{
|
||||||
|
@ -50,7 +50,7 @@ inline bool compareExchange(T& dst, const T& src)
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
inline bool compareExchange<float>(float& dst, const float& src)
|
inline Q_REQUIRED_RESULT bool compareExchange<float>(float& dst, const float& src)
|
||||||
{
|
{
|
||||||
if (!qskFuzzyCompare (dst, src))
|
if (!qskFuzzyCompare (dst, src))
|
||||||
{
|
{
|
||||||
|
@ -61,7 +61,7 @@ inline bool compareExchange<float>(float& dst, const float& src)
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
inline bool compareExchange<qreal>(qreal& dst, const qreal& src)
|
inline Q_REQUIRED_RESULT bool compareExchange<qreal>(qreal& dst, const qreal& src)
|
||||||
{
|
{
|
||||||
if (!qskFuzzyCompare (dst, src))
|
if (!qskFuzzyCompare (dst, src))
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,190 +0,0 @@
|
||||||
#include <cstdlib>
|
|
||||||
#include <type_traits>
|
|
||||||
#include <iostream>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#include <QSGNode>
|
|
||||||
|
|
||||||
#include "QskLevelingSensorUtility.h"
|
|
||||||
|
|
||||||
#define ASSERT_TRUE(expr) if(!(expr)) { std::cerr << "ASSERT_TRUE(!" << #expr << "):" << __LINE__ << '\n'; return false; }
|
|
||||||
|
|
||||||
class QSGNodeBase : public QSGNode
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
virtual std::string name() const = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
class QSGNodeA final : public QSGNodeBase{ public: QSGNodeA() { std::cout << name() << '\n'; } std::string name() const override { return "A"; }};
|
|
||||||
class QSGNodeB final : public QSGNodeBase{ public: QSGNodeB() { std::cout << name() << '\n'; } std::string name() const override { return "B"; }};
|
|
||||||
class QSGNodeC final : public QSGNodeBase{ public: QSGNodeC() { std::cout << name() << '\n'; } std::string name() const override { return "C"; }};
|
|
||||||
class QSGNodeD final : public QSGNodeBase{ public: QSGNodeD() { std::cout << name() << '\n'; } std::string name() const override { return "D"; }};
|
|
||||||
class QSGNodeE final : public QSGNodeBase{ public: QSGNodeE() { std::cout << name() << '\n'; } std::string name() const override { return "E"; }};
|
|
||||||
class QSGNodeF final : public QSGNodeBase{ public: QSGNodeF() { std::cout << name() << '\n'; } std::string name() const override { return "F"; }};
|
|
||||||
class QSGNodeG final : public QSGNodeBase{ public: QSGNodeG() { std::cout << name() << '\n'; } std::string name() const override { return "G"; }};
|
|
||||||
class QSGNodeH final : public QSGNodeBase{ public: QSGNodeH() { std::cout << name() << '\n'; } std::string name() const override { return "H"; }};
|
|
||||||
|
|
||||||
using NodeType = QSGNode;
|
|
||||||
|
|
||||||
bool testcase_ensure_node()
|
|
||||||
{
|
|
||||||
NodeType* root = nullptr;
|
|
||||||
ASSERT_TRUE(root = ensure_node<NodeType>());
|
|
||||||
ASSERT_TRUE(root->childCount() == 0);
|
|
||||||
delete root;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// seq<par<seq<seq<N<QSGNodeD, 4>>
|
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
bool testcase_seq()
|
|
||||||
{
|
|
||||||
using namespace qsg;
|
|
||||||
{
|
|
||||||
auto* const root = ensure_node<NodeType>();
|
|
||||||
seq<N<QSGNodeA>, N<QSGNodeB>, N<QSGNodeC>>::append(root);
|
|
||||||
delete root;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
auto* const root = ensure_node<NodeType>();
|
|
||||||
ASSERT_TRUE(root);
|
|
||||||
ASSERT_TRUE(root->childCount() == 0);
|
|
||||||
qsg::seq<>::append(root);
|
|
||||||
ASSERT_TRUE(root->childCount() == 0);
|
|
||||||
delete root;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
auto* const root = ensure_node<NodeType>();
|
|
||||||
ASSERT_TRUE(root);
|
|
||||||
ASSERT_TRUE(root->childCount() == 0);
|
|
||||||
qsg::seq<N<QSGNodeA>>::append(root);
|
|
||||||
ASSERT_TRUE(root->childCount() == 1);
|
|
||||||
delete root;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
auto* const root = ensure_node<NodeType>();
|
|
||||||
ASSERT_TRUE(root);
|
|
||||||
ASSERT_TRUE(root->childCount() == 0);
|
|
||||||
qsg::seq<N<QSGNodeA>, N<QSGNodeB>>::append(root);
|
|
||||||
ASSERT_TRUE(root->childCount() == 2);
|
|
||||||
delete root;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
// - QSGNode
|
|
||||||
// - QSGNodeA
|
|
||||||
// - QSGNodeB
|
|
||||||
// - QSGNodeC
|
|
||||||
auto* const root = ensure_node<NodeType>();
|
|
||||||
ASSERT_TRUE(root);
|
|
||||||
ASSERT_TRUE(root->childCount() == 0);
|
|
||||||
qsg::seq<N<QSGNodeA>, N<QSGNodeB>, N<QSGNodeC>>::append(root);
|
|
||||||
ASSERT_TRUE(root->childCount() == 3);
|
|
||||||
delete root;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
bool testcase_par()
|
|
||||||
{
|
|
||||||
using namespace qsg;
|
|
||||||
{
|
|
||||||
std::cout << __func__ << 0 << '\n';
|
|
||||||
//auto* const root = ensure_node<QSGNode>();
|
|
||||||
//ASSERT_TRUE(root->childCount() == 0);
|
|
||||||
//par<4, QSGNodeA, par<4, QSGNodeB>>::append(root);
|
|
||||||
//ASSERT_TRUE(root->childCount() == 4);
|
|
||||||
//for(int i = 0; i < 4; ++i)
|
|
||||||
//{
|
|
||||||
// ASSERT_TRUE(root->childAtIndex(i)->childCount() == 4);
|
|
||||||
//}
|
|
||||||
//delete root;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
std::cout << __func__ << 1 << '\n';
|
|
||||||
// - QSGNode
|
|
||||||
// - QSGNodeA
|
|
||||||
// - QSGNodeB
|
|
||||||
// - QSGNodeC
|
|
||||||
// - QSGNodeD
|
|
||||||
// - QSGNodeA
|
|
||||||
// - QSGNodeB
|
|
||||||
// - QSGNodeC
|
|
||||||
// - QSGNodeD
|
|
||||||
// - QSGNodeA
|
|
||||||
// - QSGNodeB
|
|
||||||
// - QSGNodeC
|
|
||||||
// - QSGNodeD
|
|
||||||
// - QSGNodeA
|
|
||||||
// - QSGNodeB
|
|
||||||
// - QSGNodeC
|
|
||||||
// - QSGNodeD
|
|
||||||
auto* const root = ensure_node<QSGNode>();
|
|
||||||
ASSERT_TRUE(root->childCount() == 0);
|
|
||||||
par<4, QSGNodeA,
|
|
||||||
seq<par<1, QSGNodeB>,
|
|
||||||
par<1, QSGNodeC>,
|
|
||||||
par<1, QSGNodeD>>>::append(root);
|
|
||||||
ASSERT_TRUE(root->childCount() == 4);
|
|
||||||
ASSERT_TRUE(root->childAtIndex(0)->childCount() == 3);
|
|
||||||
ASSERT_TRUE(root->childAtIndex(1)->childCount() == 3);
|
|
||||||
ASSERT_TRUE(root->childAtIndex(2)->childCount() == 3);
|
|
||||||
ASSERT_TRUE(root->childAtIndex(3)->childCount() == 3);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
std::cout << __func__ << 3 << '\n';
|
|
||||||
auto* const root = ensure_node<QSGNode>();
|
|
||||||
seq<
|
|
||||||
par<1, QSGNodeE,
|
|
||||||
seq<
|
|
||||||
par<1, QSGNodeA>,
|
|
||||||
par<1, QSGNodeB>,
|
|
||||||
par<1, QSGNodeC>>>,
|
|
||||||
par<1, QSGNodeF,
|
|
||||||
seq<
|
|
||||||
par<1, QSGNodeB>,
|
|
||||||
par<1, QSGNodeC>,
|
|
||||||
par<1, QSGNodeA>>>,
|
|
||||||
par<1, QSGNodeG,
|
|
||||||
seq<
|
|
||||||
par<1, QSGNodeC>,
|
|
||||||
par<1, QSGNodeA>,
|
|
||||||
par<1, QSGNodeB>>>
|
|
||||||
>::append(root);
|
|
||||||
ASSERT_TRUE(root->childCount() == 3);
|
|
||||||
for(int i = 0; i < root->childCount(); ++i)
|
|
||||||
{
|
|
||||||
ASSERT_TRUE(root->childAtIndex(i)->childCount() == 3);
|
|
||||||
for(int j = 0; j < root->childAtIndex(i)->childAtIndex(i)->childCount(); ++j)
|
|
||||||
{
|
|
||||||
ASSERT_TRUE(root->childAtIndex(i)->childCount() == 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ASSERT_TRUE(dynamic_cast<QSGNodeE*>(root->childAtIndex(0)));
|
|
||||||
ASSERT_TRUE(dynamic_cast<QSGNodeA*>(root->childAtIndex(0)->childAtIndex(0)));
|
|
||||||
ASSERT_TRUE(dynamic_cast<QSGNodeB*>(root->childAtIndex(0)->childAtIndex(1)));
|
|
||||||
ASSERT_TRUE(dynamic_cast<QSGNodeC*>(root->childAtIndex(0)->childAtIndex(2)));
|
|
||||||
ASSERT_TRUE(dynamic_cast<QSGNodeF*>(root->childAtIndex(1)));
|
|
||||||
ASSERT_TRUE(dynamic_cast<QSGNodeB*>(root->childAtIndex(1)->childAtIndex(0)));
|
|
||||||
ASSERT_TRUE(dynamic_cast<QSGNodeC*>(root->childAtIndex(1)->childAtIndex(1)));
|
|
||||||
ASSERT_TRUE(dynamic_cast<QSGNodeA*>(root->childAtIndex(1)->childAtIndex(2)));
|
|
||||||
ASSERT_TRUE(dynamic_cast<QSGNodeG*>(root->childAtIndex(2)));
|
|
||||||
ASSERT_TRUE(dynamic_cast<QSGNodeC*>(root->childAtIndex(2)->childAtIndex(0)));
|
|
||||||
ASSERT_TRUE(dynamic_cast<QSGNodeA*>(root->childAtIndex(2)->childAtIndex(1)));
|
|
||||||
ASSERT_TRUE(dynamic_cast<QSGNodeB*>(root->childAtIndex(2)->childAtIndex(2)));
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
bool result = true;
|
|
||||||
// result &= testcase_ensure_node();
|
|
||||||
// result &= testcase_seq();
|
|
||||||
result &= testcase_par();
|
|
||||||
std::cout << (result ? "ok" : "failed") << std::endl;
|
|
||||||
return result ? EXIT_SUCCESS : EXIT_FAILURE;
|
|
||||||
}
|
|
|
@ -1,100 +1,42 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <QSGNode>
|
#include <QSGNode>
|
||||||
#include <type_traits>
|
|
||||||
|
|
||||||
namespace QskSGNode
|
namespace QskSGNode
|
||||||
{
|
{
|
||||||
using NodeType = QSGNode;
|
namespace detail
|
||||||
|
|
||||||
template<typename ... Ts>
|
|
||||||
struct seq;
|
|
||||||
|
|
||||||
template<>
|
|
||||||
struct seq<>
|
|
||||||
{
|
{
|
||||||
static void append(NodeType* root)
|
template< typename... Ts >
|
||||||
{
|
struct append;
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T>
|
template<>
|
||||||
struct seq<T>
|
struct append<>
|
||||||
{
|
|
||||||
static void append(NodeType* root)
|
|
||||||
{
|
{
|
||||||
T::append(root);
|
static void nodes( QSGNode* root )
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T, typename ... Ts>
|
|
||||||
struct seq<T, Ts...>
|
|
||||||
{
|
|
||||||
static void append(NodeType* root)
|
|
||||||
{
|
|
||||||
T::append(root);
|
|
||||||
seq<Ts...>::append(root);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<int N, typename ... Ts>
|
|
||||||
struct par;
|
|
||||||
|
|
||||||
template<int N, typename T>
|
|
||||||
struct par<N,T>
|
|
||||||
{
|
|
||||||
static void append(NodeType* root)
|
|
||||||
{
|
|
||||||
const auto n = N;
|
|
||||||
for (int i = 0; i < N; ++i)
|
|
||||||
{
|
{
|
||||||
root->appendChildNode(new T);
|
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
};
|
|
||||||
|
|
||||||
template<int N, typename T, typename U>
|
template< typename Child, typename... Children >
|
||||||
struct par<N,T,U>
|
struct append< Child, Children... >
|
||||||
{
|
|
||||||
static void append(NodeType* root)
|
|
||||||
{
|
{
|
||||||
const auto n = N;
|
static void nodes( QSGNode* root )
|
||||||
for (int i = 0; i < N; ++i)
|
|
||||||
{
|
{
|
||||||
auto* const t = new T;
|
auto* const child = new Child;
|
||||||
U::append(t);
|
root->appendChildNode( child );
|
||||||
root->appendChildNode(t);
|
append< Children... >::nodes( child );
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
};
|
}
|
||||||
|
|
||||||
template<typename ... Ts>
|
template< typename Root, typename... Children >
|
||||||
struct ensure;
|
inline Q_REQUIRED_RESULT Root* ensureNode( QSGNode* root = nullptr )
|
||||||
|
|
||||||
template<typename Root>
|
|
||||||
struct ensure<Root>
|
|
||||||
{
|
{
|
||||||
static Q_REQUIRED_RESULT Root* node(NodeType* root = nullptr)
|
if ( root == nullptr )
|
||||||
{
|
{
|
||||||
if(root == nullptr)
|
root = new Root;
|
||||||
{
|
detail::append< Children... >::nodes( root );
|
||||||
root = new Root;
|
|
||||||
}
|
|
||||||
return static_cast<Root*>(root);
|
|
||||||
}
|
}
|
||||||
};
|
return static_cast< Root* >( root );
|
||||||
|
}
|
||||||
template<typename Root, typename Append>
|
|
||||||
struct ensure<Root, Append>
|
|
||||||
{
|
|
||||||
static Q_REQUIRED_RESULT Root* node(NodeType* root = nullptr)
|
|
||||||
{
|
|
||||||
if(root == nullptr)
|
|
||||||
{
|
|
||||||
root = new Root;
|
|
||||||
Append::append(root);
|
|
||||||
}
|
|
||||||
return static_cast<Root*>(root);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
Loading…
Reference in New Issue