From 47df732f4a1f4c529d07058d45d43fd5f1060846 Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Fri, 9 Sep 2022 10:25:46 +0200 Subject: [PATCH] better seperation between state animators and those for skin changes --- src/controls/QskSkinnable.cpp | 172 ++++++++++++++++------------------ src/controls/QskSkinnable.h | 3 +- 2 files changed, 85 insertions(+), 90 deletions(-) diff --git a/src/controls/QskSkinnable.cpp b/src/controls/QskSkinnable.cpp index cc97672b..b00a72de 100644 --- a/src/controls/QskSkinnable.cpp +++ b/src/controls/QskSkinnable.cpp @@ -737,7 +737,8 @@ QskColorFilter QskSkinnable::effectiveGraphicFilter( aspect.setSection( QskAspect::Body ); aspect.setPlacement( QskAspect::NoPlacement ); - const auto v = animatedValue( aspect, nullptr ); + const auto v = animatedHint( aspect, nullptr ); + if ( v.canConvert< QskColorFilter >() ) return v.value< QskColorFilter >(); @@ -866,22 +867,33 @@ QVariant QskSkinnable::effectiveSkinHint( { aspect.setSubControl( effectiveSubcontrol( aspect.subControl() ) ); + if ( !( aspect.isAnimator() || aspect.hasStates() ) ) + { + const auto v = animatedHint( aspect, status ); + if ( v.isValid() ) + return v; + } + if ( aspect.section() == QskAspect::Body ) aspect.setSection( section() ); if ( aspect.placement() == QskAspect::NoPlacement ) aspect.setPlacement( effectivePlacement() ); - if ( aspect.isAnimator() ) - return storedHint( aspect, status ); - - const auto v = animatedValue( aspect, status ); - if ( v.isValid() ) - return v; - if ( !aspect.hasStates() ) aspect.setStates( skinStates() ); + if ( !aspect.isAnimator() && QskSkinTransition::isRunning() ) + { + /* + The skin has changed and the hints are interpolated + between the old and the new one over time + */ + const auto v = interpolatedHint( aspect, status ); + if ( v.isValid() ) + return v; + } + return storedHint( aspect, status ); } @@ -919,12 +931,12 @@ bool QskSkinnable::moveSkinHint( QskAspect aspect, const QVariant& value ) return moveSkinHint( aspect, effectiveSkinHint( aspect ), value ); } -QVariant QskSkinnable::animatedValue( +QVariant QskSkinnable::animatedHint( QskAspect aspect, QskSkinHintStatus* status ) const { QVariant v; - if ( !m_data->animators.isEmpty() && !aspect.hasStates() ) + if ( !m_data->animators.isEmpty() ) { /* The local animators were invented to be stateless @@ -932,92 +944,65 @@ QVariant QskSkinnable::animatedValue( But that might change ... */ - auto a = aspect; + v = m_data->animators.currentValue( aspect ); + } - Q_FOREVER + if ( status && v.isValid() ) + { + status->source = QskSkinHintStatus::Animator; + status->aspect = aspect; + } + + return v; +} + +QVariant QskSkinnable::interpolatedHint( + QskAspect aspect, QskSkinHintStatus* status ) const +{ + if ( !QskSkinTransition::isRunning() || m_data->hintTable.hasHint( aspect ) ) + return QVariant(); + + const auto control = owningControl(); + if ( control == nullptr ) + return QVariant(); + + QVariant v; + + auto a = aspect; + + Q_FOREVER + { + v = QskSkinTransition::animatedHint( control->window(), aspect ); + + if ( !v.isValid() ) { - v = m_data->animators.currentValue( aspect ); - - if ( !v.isValid() ) + if ( const auto topState = aspect.topState() ) { - if ( aspect.placement() ) - { - // clear the placement bits and restart - aspect = a; - aspect.setPlacement( QskAspect::NoPlacement ); - - continue; - } - } - - if ( aspect.section() != QskAspect::Body ) - { - // try to resolve from QskAspect::Body - - a.setSection( QskAspect::Body ); - aspect = a; - + aspect.clearState( aspect.topState() ); continue; } - break; - } - } - - if ( !v.isValid() ) - { - if ( QskSkinTransition::isRunning() && - !m_data->hintTable.hasHint( aspect ) ) - { - /* - Next we check for values from the skin. Those - animators are usually from global skin/color changes - and are state aware - */ - - if ( const auto control = owningControl() ) + if ( aspect.placement() ) { - if ( !aspect.hasStates() ) - aspect.setStates( skinStates() ); + // clear the placement bits and restart + aspect = a; + aspect.setPlacement( QskAspect::NoPlacement ); - auto a = aspect; - - Q_FOREVER - { - v = QskSkinTransition::animatedHint( control->window(), aspect ); - - if ( !v.isValid() ) - { - if ( const auto topState = aspect.topState() ) - { - aspect.clearState( aspect.topState() ); - continue; - } - - if ( aspect.placement() ) - { - // clear the placement bits and restart - aspect = a; - aspect.setPlacement( QskAspect::NoPlacement ); - - continue; - } - } - - if ( aspect.section() != QskAspect::Body ) - { - // try to resolve from QskAspect::Body - - a.setSection( QskAspect::Body ); - aspect = a; - - continue; - } - - break; - } + continue; } } + + if ( a.section() != QskAspect::Body ) + { + // try to resolve with the default section + + a.setSection( QskAspect::Body ); + aspect = a; + + continue; + } + + break; } if ( status && v.isValid() ) @@ -1264,9 +1249,15 @@ void QskSkinnable::startHintTransition( QskAspect aspect, v2.setValue( skin->graphicFilter( v2.toInt() ) ); } + /* + We do not need the extra bits that would slow down resolving + the effective aspect in animatedHint. + */ + aspect.clearStates(); + aspect.setSection( QskAspect::Body ); + aspect.setPlacement( QskAspect::NoPlacement ); aspect.setAnimator( false ); - aspect.setPlacement( effectivePlacement() ); #if DEBUG_ANIMATOR qDebug() << aspect << animationHint.duration; @@ -1333,13 +1324,16 @@ void QskSkinnable::setSkinStates( QskAspect::States newStates ) if ( control->window() && isTransitionAccepted( QskAspect() ) ) { - const auto placement = effectivePlacement(); + QskAspect aspect; + aspect.setPlacement( effectivePlacement() ); + aspect.setSection( section() ); + const auto primitiveCount = QskAspect::primitiveCount(); const auto subControls = control->subControls(); for ( const auto subControl : subControls ) { - auto aspect = subControl | placement; + aspect.setSubControl( subControl ); const auto& skinTable = skin->hintTable(); diff --git a/src/controls/QskSkinnable.h b/src/controls/QskSkinnable.h index 896d7d5a..92b5dac3 100644 --- a/src/controls/QskSkinnable.h +++ b/src/controls/QskSkinnable.h @@ -261,7 +261,8 @@ class QSK_EXPORT QskSkinnable void startHintTransition( QskAspect, QskAnimationHint, const QVariant& from, const QVariant& to ); - QVariant animatedValue( QskAspect, QskSkinHintStatus* ) const; + QVariant animatedHint( QskAspect, QskSkinHintStatus* ) const; + QVariant interpolatedHint( QskAspect, QskSkinHintStatus* ) const; const QVariant& storedHint( QskAspect, QskSkinHintStatus* = nullptr ) const; class PrivateData;