QskSkinTransition fixed to work with graphic roles
This commit is contained in:
parent
c4325d5f45
commit
736a28d02f
|
@ -96,6 +96,12 @@ static QVector< AnimatorCandidate > qskAnimatorCandidates(
|
||||||
|
|
||||||
const int role2 = entry.second.toInt();
|
const int role2 = entry.second.toInt();
|
||||||
|
|
||||||
|
/*
|
||||||
|
When the role is the same we already have the animators
|
||||||
|
for the graphic filter table running
|
||||||
|
*/
|
||||||
|
if ( role1 != role2 )
|
||||||
|
{
|
||||||
const auto it1 = oldFilters.find( role1 );
|
const auto it1 = oldFilters.find( role1 );
|
||||||
const auto it2 = newFilters.find( role2 );
|
const auto it2 = newFilters.find( role2 );
|
||||||
|
|
||||||
|
@ -111,6 +117,7 @@ static QVector< AnimatorCandidate > qskAnimatorCandidates(
|
||||||
QVariant::fromValue( f2 ) );
|
QVariant::fromValue( f2 ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case QskAspect::FontRole:
|
case QskAspect::FontRole:
|
||||||
|
@ -167,27 +174,31 @@ namespace
|
||||||
m_notifyConnection = QskAnimator::addAdvanceHandler( this,
|
m_notifyConnection = QskAnimator::addAdvanceHandler( this,
|
||||||
SLOT( notify( QQuickWindow* ) ) );
|
SLOT( notify( QQuickWindow* ) ) );
|
||||||
|
|
||||||
for ( auto& it : m_map )
|
for ( auto& it : m_hintAnimatorMap )
|
||||||
|
it.second.start();
|
||||||
|
|
||||||
|
for ( auto& it : m_graphicFilterAnimatorMap )
|
||||||
it.second.start();
|
it.second.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isRunning() const
|
bool isRunning() const
|
||||||
{
|
{
|
||||||
return !m_map.empty();
|
return !m_hintAnimatorMap.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
void reset()
|
void reset()
|
||||||
{
|
{
|
||||||
disconnect( m_notifyConnection );
|
disconnect( m_notifyConnection );
|
||||||
|
|
||||||
m_map.clear();
|
m_hintAnimatorMap.clear();
|
||||||
|
m_graphicFilterAnimatorMap.clear();
|
||||||
m_updateInfos.clear();
|
m_updateInfos.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline QVariant animatedHint( QskAspect::Aspect aspect ) const
|
inline QVariant animatedHint( QskAspect::Aspect aspect ) const
|
||||||
{
|
{
|
||||||
auto it = m_map.find( aspect );
|
auto it = m_hintAnimatorMap.find( aspect );
|
||||||
if ( it != m_map.cend() )
|
if ( it != m_hintAnimatorMap.cend() )
|
||||||
{
|
{
|
||||||
const auto& animator = it->second;
|
const auto& animator = it->second;
|
||||||
if ( animator.isRunning() )
|
if ( animator.isRunning() )
|
||||||
|
@ -197,6 +208,49 @@ namespace
|
||||||
return QVariant();
|
return QVariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline QVariant animatedGraphicFilter( int graphicRole ) const
|
||||||
|
{
|
||||||
|
auto it = m_graphicFilterAnimatorMap.find( graphicRole );
|
||||||
|
if ( it != m_graphicFilterAnimatorMap.cend() )
|
||||||
|
{
|
||||||
|
const auto& animator = it->second;
|
||||||
|
if ( animator.isRunning() )
|
||||||
|
return animator.currentValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
void addGraphicFilterAnimators(
|
||||||
|
QQuickWindow* window, const QskAnimationHint& animatorHint,
|
||||||
|
const std::unordered_map< int, QskColorFilter >& oldFilters,
|
||||||
|
const std::unordered_map< int, QskColorFilter >& newFilters )
|
||||||
|
{
|
||||||
|
const QskColorFilter noFilter;
|
||||||
|
|
||||||
|
for ( auto it2 = newFilters.begin(); it2 != newFilters.end(); ++it2 )
|
||||||
|
{
|
||||||
|
auto it1 = oldFilters.find( it2->first );
|
||||||
|
if ( it1 == oldFilters.cend() )
|
||||||
|
it1 = oldFilters.find( 0 );
|
||||||
|
|
||||||
|
const auto& f1 = ( it1 != oldFilters.cend() ) ? it1->second : noFilter;
|
||||||
|
const auto& f2 = it2->second;
|
||||||
|
|
||||||
|
if ( f1 != f2 )
|
||||||
|
{
|
||||||
|
QskVariantAnimator animator;
|
||||||
|
animator.setWindow( window );
|
||||||
|
animator.setDuration( animatorHint.duration );
|
||||||
|
animator.setEasingCurve( animatorHint.type );
|
||||||
|
animator.setStartValue( QVariant::fromValue( f1 ) );
|
||||||
|
animator.setEndValue( QVariant::fromValue( f2 ) );
|
||||||
|
|
||||||
|
m_graphicFilterAnimatorMap.emplace( it2->first, animator );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void addAnimators( QQuickItem* item,
|
void addAnimators( QQuickItem* item,
|
||||||
const QskAnimationHint& animatorHint,
|
const QskAnimationHint& animatorHint,
|
||||||
const QVector< AnimatorCandidate >& candidates, QskSkin* skin )
|
const QVector< AnimatorCandidate >& candidates, QskSkin* skin )
|
||||||
|
@ -207,7 +261,17 @@ namespace
|
||||||
if ( auto control = qobject_cast< QskControl* >( item ) )
|
if ( auto control = qobject_cast< QskControl* >( item ) )
|
||||||
{
|
{
|
||||||
if ( control->isInitiallyPainted() && ( skin == control->effectiveSkin() ) )
|
if ( control->isInitiallyPainted() && ( skin == control->effectiveSkin() ) )
|
||||||
|
{
|
||||||
addControlAnimators( control, animatorHint, candidates );
|
addControlAnimators( control, animatorHint, candidates );
|
||||||
|
#if 1
|
||||||
|
/*
|
||||||
|
As it is hard to identify which controls depend on the animated
|
||||||
|
graphic filters we schedule an initial update and let the
|
||||||
|
controls do the rest: see QskSkinnable::effectiveGraphicFilter
|
||||||
|
*/
|
||||||
|
control->update();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto children = item->childItems();
|
const auto children = item->childItems();
|
||||||
|
@ -237,9 +301,9 @@ namespace
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !m_map.empty() )
|
if ( !m_hintAnimatorMap.empty() )
|
||||||
{
|
{
|
||||||
if ( !m_map.begin()->second.isRunning() )
|
if ( !m_hintAnimatorMap.begin()->second.isRunning() )
|
||||||
reset();
|
reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -307,19 +371,19 @@ namespace
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
addAnimator( control, candidate, animatorHint );
|
addAnimator( control->window(), candidate, animatorHint );
|
||||||
storeUpdateInfo( control, candidate.aspect );
|
storeUpdateInfo( control, candidate.aspect );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void addAnimator( QskControl* control,
|
void addAnimator( QQuickWindow* window,
|
||||||
const AnimatorCandidate& candidate, QskAnimationHint animationHint )
|
const AnimatorCandidate& candidate, QskAnimationHint animationHint )
|
||||||
{
|
{
|
||||||
auto it = m_map.find( candidate.aspect );
|
auto it = m_hintAnimatorMap.find( candidate.aspect );
|
||||||
if ( it != m_map.end() )
|
if ( it != m_hintAnimatorMap.end() )
|
||||||
return; // already there
|
return; // already there
|
||||||
|
|
||||||
it = m_map.emplace( candidate.aspect, QskHintAnimator() ).first;
|
it = m_hintAnimatorMap.emplace( candidate.aspect, QskHintAnimator() ).first;
|
||||||
auto& animator = it->second;
|
auto& animator = it->second;
|
||||||
|
|
||||||
animator.setAspect( candidate.aspect );
|
animator.setAspect( candidate.aspect );
|
||||||
|
@ -330,7 +394,7 @@ namespace
|
||||||
animator.setEasingCurve( animationHint.type );
|
animator.setEasingCurve( animationHint.type );
|
||||||
|
|
||||||
animator.setControl( nullptr );
|
animator.setControl( nullptr );
|
||||||
animator.setWindow( control->window() );
|
animator.setWindow( window );
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void storeUpdateInfo( QskControl* control, QskAspect::Aspect aspect )
|
inline void storeUpdateInfo( QskControl* control, QskAspect::Aspect aspect )
|
||||||
|
@ -351,7 +415,8 @@ namespace
|
||||||
m_updateInfos.insert( it, info );
|
m_updateInfos.insert( it, info );
|
||||||
}
|
}
|
||||||
|
|
||||||
std::map< QskAspect::Aspect, QskHintAnimator > m_map;
|
std::unordered_map< QskAspect::Aspect, QskHintAnimator > m_hintAnimatorMap;
|
||||||
|
std::unordered_map< int, QskVariantAnimator > m_graphicFilterAnimatorMap;
|
||||||
std::vector< UpdateInfo > m_updateInfos; // vector: for fast iteration
|
std::vector< UpdateInfo > m_updateInfos; // vector: for fast iteration
|
||||||
|
|
||||||
QMetaObject::Connection m_notifyConnection;
|
QMetaObject::Connection m_notifyConnection;
|
||||||
|
@ -400,14 +465,14 @@ QskSkin* QskSkinTransition::targetSkin() const
|
||||||
return m_skins[1];
|
return m_skins[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
void QskSkinTransition::setAnimation( QskAnimationHint animation )
|
void QskSkinTransition::setAnimation( QskAnimationHint animationHint )
|
||||||
{
|
{
|
||||||
m_animation = animation;
|
m_animationHint = animationHint;
|
||||||
}
|
}
|
||||||
|
|
||||||
QskAnimationHint QskSkinTransition::animation() const
|
QskAnimationHint QskSkinTransition::animation() const
|
||||||
{
|
{
|
||||||
return m_animation;
|
return m_animationHint;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QskSkinTransition::updateSkin( QskSkin*, QskSkin* )
|
void QskSkinTransition::updateSkin( QskSkin*, QskSkin* )
|
||||||
|
@ -425,7 +490,7 @@ void QskSkinTransition::process()
|
||||||
|
|
||||||
qskSkinAnimator->reset();
|
qskSkinAnimator->reset();
|
||||||
|
|
||||||
if ( ( m_animation.duration <= 0 ) || ( m_mask == 0 ) )
|
if ( ( m_animationHint.duration <= 0 ) || ( m_mask == 0 ) )
|
||||||
{
|
{
|
||||||
// no animations, we can apply the changes
|
// no animations, we can apply the changes
|
||||||
updateSkin( m_skins[0], m_skins[1] );
|
updateSkin( m_skins[0], m_skins[1] );
|
||||||
|
@ -433,13 +498,13 @@ void QskSkinTransition::process()
|
||||||
}
|
}
|
||||||
|
|
||||||
QVector< AnimatorCandidate > candidates;
|
QVector< AnimatorCandidate > candidates;
|
||||||
|
const auto oldFilters = m_skins[0]->graphicFilters();
|
||||||
|
|
||||||
{
|
{
|
||||||
// copy out all hints before updating the skin
|
// copy out all hints before updating the skin
|
||||||
// - would be good to have Copy on Write here
|
// - would be good to have Copy on Write here
|
||||||
|
|
||||||
const auto oldTable = m_skins[0]->hintTable();
|
const auto oldTable = m_skins[0]->hintTable();
|
||||||
const auto oldFilters = m_skins[0]->graphicFilters();
|
|
||||||
|
|
||||||
// apply the changes
|
// apply the changes
|
||||||
updateSkin( m_skins[0], m_skins[1] );
|
updateSkin( m_skins[0], m_skins[1] );
|
||||||
|
@ -450,20 +515,29 @@ void QskSkinTransition::process()
|
||||||
|
|
||||||
if ( !candidates.isEmpty() )
|
if ( !candidates.isEmpty() )
|
||||||
{
|
{
|
||||||
/*
|
bool firstWindow = true;
|
||||||
finally we schedule the animators the hard way by running
|
|
||||||
over the the item trees. for the moment o.k. but we should
|
|
||||||
find a way not to create lots of identical animator objects for
|
|
||||||
each object.
|
|
||||||
*/
|
|
||||||
|
|
||||||
const auto windows = qGuiApp->topLevelWindows();
|
const auto windows = qGuiApp->topLevelWindows();
|
||||||
for ( const auto window : windows )
|
for ( const auto window : windows )
|
||||||
{
|
{
|
||||||
if ( auto quickWindow = qobject_cast< const QQuickWindow* >( window ) )
|
if ( auto quickWindow = qobject_cast< QQuickWindow* >( window ) )
|
||||||
{
|
{
|
||||||
|
if ( firstWindow )
|
||||||
|
{
|
||||||
|
qskSkinAnimator->addGraphicFilterAnimators(
|
||||||
|
quickWindow, m_animationHint,
|
||||||
|
oldFilters, m_skins[1]->graphicFilters() );
|
||||||
|
|
||||||
|
firstWindow = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
finally we schedule the animators the hard way by running
|
||||||
|
over the the item trees.
|
||||||
|
*/
|
||||||
|
|
||||||
qskSkinAnimator->addAnimators( quickWindow->contentItem(),
|
qskSkinAnimator->addAnimators( quickWindow->contentItem(),
|
||||||
m_animation, candidates, m_skins[1] );
|
m_animationHint, candidates, m_skins[1] );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -484,4 +558,12 @@ QVariant QskSkinTransition::animatedHint( QskAspect::Aspect aspect )
|
||||||
return qskSkinAnimator->animatedHint( aspect );
|
return qskSkinAnimator->animatedHint( aspect );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QVariant QskSkinTransition::animatedGraphicFilter( int graphicRole )
|
||||||
|
{
|
||||||
|
if ( !qskSkinAnimator.exists() )
|
||||||
|
return QVariant();
|
||||||
|
|
||||||
|
return qskSkinAnimator->animatedGraphicFilter( graphicRole );
|
||||||
|
}
|
||||||
|
|
||||||
#include "QskSkinTransition.moc"
|
#include "QskSkinTransition.moc"
|
||||||
|
|
|
@ -39,13 +39,14 @@ public:
|
||||||
|
|
||||||
static bool isRunning();
|
static bool isRunning();
|
||||||
static QVariant animatedHint( QskAspect::Aspect );
|
static QVariant animatedHint( QskAspect::Aspect );
|
||||||
|
static QVariant animatedGraphicFilter( int graphicRole );
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void updateSkin( QskSkin*, QskSkin* );
|
virtual void updateSkin( QskSkin*, QskSkin* );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QskSkin* m_skins[2];
|
QskSkin* m_skins[2];
|
||||||
QskAnimationHint m_animation;
|
QskAnimationHint m_animationHint;
|
||||||
Type m_mask : 2;
|
Type m_mask : 2;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -84,10 +84,10 @@ static inline bool qskCompareResolvedStates(
|
||||||
|
|
||||||
// clear the placement bit and restart with the initial state
|
// clear the placement bit and restart with the initial state
|
||||||
aspect1 = a1;
|
aspect1 = a1;
|
||||||
aspect1.setPlacement( static_cast< QskAspect::Placement>( 0 ) );
|
aspect1.setPlacement( static_cast< QskAspect::Placement >( 0 ) );
|
||||||
|
|
||||||
aspect2 = a2;
|
aspect2 = a2;
|
||||||
aspect2.setPlacement( static_cast< QskAspect::Placement>( 0 ) );
|
aspect2.setPlacement( static_cast< QskAspect::Placement >( 0 ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -176,12 +176,12 @@ const QskSkinlet* QskSkinnable::effectiveSkinlet() const
|
||||||
return m_data->skinlet;
|
return m_data->skinlet;
|
||||||
}
|
}
|
||||||
|
|
||||||
QskSkinHintTable &QskSkinnable::hintTable()
|
QskSkinHintTable& QskSkinnable::hintTable()
|
||||||
{
|
{
|
||||||
return m_data->hintTable;
|
return m_data->hintTable;
|
||||||
}
|
}
|
||||||
|
|
||||||
const QskSkinHintTable &QskSkinnable::hintTable() const
|
const QskSkinHintTable& QskSkinnable::hintTable() const
|
||||||
{
|
{
|
||||||
return m_data->hintTable;
|
return m_data->hintTable;
|
||||||
}
|
}
|
||||||
|
@ -325,7 +325,6 @@ QskColorFilter QskSkinnable::effectiveGraphicFilter(
|
||||||
aspect.setPlacement( effectivePlacement() );
|
aspect.setPlacement( effectivePlacement() );
|
||||||
aspect = aspect | QskAspect::GraphicRole;
|
aspect = aspect | QskAspect::GraphicRole;
|
||||||
|
|
||||||
#if 1
|
|
||||||
QskSkinHintStatus status;
|
QskSkinHintStatus status;
|
||||||
|
|
||||||
const QVariant hint = storedHint( aspect | skinState(), &status );
|
const QVariant hint = storedHint( aspect | skinState(), &status );
|
||||||
|
@ -336,13 +335,32 @@ QskColorFilter QskSkinnable::effectiveGraphicFilter(
|
||||||
|
|
||||||
aspect.setSubControl( status.aspect.subControl() );
|
aspect.setSubControl( status.aspect.subControl() );
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
if ( !aspect.isAnimator() )
|
if ( !aspect.isAnimator() )
|
||||||
{
|
{
|
||||||
const QVariant v = animatedValue( aspect, nullptr );
|
QVariant v = animatedValue( aspect, nullptr );
|
||||||
if ( v.canConvert< QskColorFilter >() )
|
if ( v.canConvert< QskColorFilter >() )
|
||||||
return v.value< QskColorFilter >();
|
return v.value< QskColorFilter >();
|
||||||
|
|
||||||
|
if ( QskSkinTransition::isRunning() )
|
||||||
|
{
|
||||||
|
v = QskSkinTransition::animatedGraphicFilter( hint.toInt() );
|
||||||
|
|
||||||
|
if ( v.canConvert< QskColorFilter >() )
|
||||||
|
{
|
||||||
|
if ( owningControl() )
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
As it is hard to find out which controls depend
|
||||||
|
on the animated graphic filters we reschedule
|
||||||
|
our updates here.
|
||||||
|
*/
|
||||||
|
owningControl()->update();
|
||||||
|
}
|
||||||
|
|
||||||
|
return v.value< QskColorFilter >();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return effectiveSkin()->graphicFilter( hint.toInt() );
|
return effectiveSkin()->graphicFilter( hint.toInt() );
|
||||||
|
|
Loading…
Reference in New Issue