allow to retarget animations
parent
07cc30d136
commit
1faa8aa039
|
@ -92,114 +92,133 @@ bool AnimationEffect::isActive() const
|
|||
#define RELATIVE_XY(_FIELD_) const bool relative[2] = { static_cast<bool>(metaData(Relative##_FIELD_##X, meta)), \
|
||||
static_cast<bool>(metaData(Relative##_FIELD_##Y, meta)) }
|
||||
|
||||
quint64 AnimationEffect::p_animate( EffectWindow *w, Attribute a, uint meta, int ms, FPx2 to, QEasingCurve curve, int delay, FPx2 from, bool keepAtTarget )
|
||||
void AnimationEffect::validate(Attribute a, uint &meta, FPx2 *from, FPx2 *to, const EffectWindow *w) const
|
||||
{
|
||||
const bool waitAtSource = from.isValid();
|
||||
if (a < NonFloatBase) {
|
||||
if (a == Scale) {
|
||||
QRect area = effects->clientArea(ScreenArea , w);
|
||||
if (from.isValid()) {
|
||||
if (from && from->isValid()) {
|
||||
RELATIVE_XY(Source);
|
||||
from.set( relative[0] ? from[0] * area.width() / w->width() : from[0],
|
||||
relative[1] ? from[1] * area.height() / w->height() : from[1] );
|
||||
from->set(relative[0] ? (*from)[0] * area.width() / w->width() : (*from)[0],
|
||||
relative[1] ? (*from)[1] * area.height() / w->height() : (*from)[1]);
|
||||
}
|
||||
if (to.isValid()) {
|
||||
if (to && to->isValid()) {
|
||||
RELATIVE_XY(Target);
|
||||
to.set( relative[0] ? to[0] * area.width() / w->width() : to[0],
|
||||
relative[1] ? to[1] * area.height() / w->height() : to[1] );
|
||||
to->set(relative[0] ? (*to)[0] * area.width() / w->width() : (*to)[0],
|
||||
relative[1] ? (*to)[1] * area.height() / w->height() : (*to)[1] );
|
||||
}
|
||||
} else if (a == Rotation) {
|
||||
if (!from.isValid()) {
|
||||
setMetaData( SourceAnchor, metaData(TargetAnchor, meta), meta );
|
||||
from.set(0.0,0.0);
|
||||
if (from && !from->isValid()) {
|
||||
setMetaData(SourceAnchor, metaData(TargetAnchor, meta), meta);
|
||||
from->set(0.0,0.0);
|
||||
}
|
||||
if (!to.isValid()) {
|
||||
setMetaData( TargetAnchor, metaData(SourceAnchor, meta), meta );
|
||||
to.set(0.0,0.0);
|
||||
if (to && !to->isValid()) {
|
||||
setMetaData(TargetAnchor, metaData(SourceAnchor, meta), meta);
|
||||
to->set(0.0,0.0);
|
||||
}
|
||||
}
|
||||
if (!from.isValid())
|
||||
from.set(1.0,1.0);
|
||||
if (!to.isValid())
|
||||
to.set(1.0,1.0);
|
||||
if (from && !from->isValid())
|
||||
from->set(1.0,1.0);
|
||||
if (to && !to->isValid())
|
||||
to->set(1.0,1.0);
|
||||
|
||||
|
||||
} else if (a == Position) {
|
||||
QRect area = effects->clientArea(ScreenArea , w);
|
||||
QPoint pt = w->geometry().bottomRight(); // cannot be < 0 ;-)
|
||||
if (from.isValid()) {
|
||||
RELATIVE_XY(Source);
|
||||
from.set( relative[0] ? area.x() + from[0] * area.width() : from[0],
|
||||
relative[1] ? area.y() + from[1] * area.height() : from[1] );
|
||||
} else {
|
||||
from.set(pt.x(), pt.y());
|
||||
setMetaData( SourceAnchor, AnimationEffect::Bottom|AnimationEffect::Right, meta );
|
||||
if (from) {
|
||||
if (from->isValid()) {
|
||||
RELATIVE_XY(Source);
|
||||
from->set(relative[0] ? area.x() + (*from)[0] * area.width() : (*from)[0],
|
||||
relative[1] ? area.y() + (*from)[1] * area.height() : (*from)[1]);
|
||||
} else {
|
||||
from->set(pt.x(), pt.y());
|
||||
setMetaData(SourceAnchor, AnimationEffect::Bottom|AnimationEffect::Right, meta);
|
||||
}
|
||||
}
|
||||
|
||||
if (to.isValid()) {
|
||||
RELATIVE_XY(Target);
|
||||
to.set( relative[0] ? area.x() + to[0] * area.width() : to[0],
|
||||
relative[1] ? area.y() + to[1] * area.height() : to[1] );
|
||||
} else {
|
||||
to.set(pt.x(), pt.y());
|
||||
setMetaData( TargetAnchor, AnimationEffect::Bottom|AnimationEffect::Right, meta );
|
||||
if (to) {
|
||||
if (to->isValid()) {
|
||||
RELATIVE_XY(Target);
|
||||
to->set(relative[0] ? area.x() + (*to)[0] * area.width() : (*to)[0],
|
||||
relative[1] ? area.y() + (*to)[1] * area.height() : (*to)[1]);
|
||||
} else {
|
||||
to->set(pt.x(), pt.y());
|
||||
setMetaData( TargetAnchor, AnimationEffect::Bottom|AnimationEffect::Right, meta );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} else if (a == Size) {
|
||||
QRect area = effects->clientArea(ScreenArea , w);
|
||||
if (from.isValid()) {
|
||||
RELATIVE_XY(Source);
|
||||
from.set( relative[0] ? from[0] * area.width() : from[0],
|
||||
relative[1] ? from[1] * area.height() : from[1] );
|
||||
} else {
|
||||
from.set(w->width(), w->height());
|
||||
if (from) {
|
||||
if (from->isValid()) {
|
||||
RELATIVE_XY(Source);
|
||||
from->set(relative[0] ? (*from)[0] * area.width() : (*from)[0],
|
||||
relative[1] ? (*from)[1] * area.height() : (*from)[1]);
|
||||
} else {
|
||||
from->set(w->width(), w->height());
|
||||
}
|
||||
}
|
||||
|
||||
if (to.isValid()) {
|
||||
RELATIVE_XY(Target);
|
||||
to.set( relative[0] ? to[0] * area.width() : to[0],
|
||||
relative[1] ? to[1] * area.height() : to[1] );
|
||||
} else {
|
||||
to.set(w->width(), w->height());
|
||||
if (to) {
|
||||
if (from->isValid()) {
|
||||
RELATIVE_XY(Target);
|
||||
to->set(relative[0] ? (*to)[0] * area.width() : (*to)[0],
|
||||
relative[1] ? (*to)[1] * area.height() : (*to)[1]);
|
||||
} else {
|
||||
to->set(w->width(), w->height());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} else if (a == Translation) {
|
||||
QRect area = w->rect();
|
||||
if (from.isValid()) {
|
||||
RELATIVE_XY(Source);
|
||||
from.set( relative[0] ? from[0] * area.width() : from[0],
|
||||
relative[1] ? from[1] * area.height() : from[1] );
|
||||
} else {
|
||||
from.set(0.0, 0.0);
|
||||
if (from) {
|
||||
if (from->isValid()) {
|
||||
RELATIVE_XY(Source);
|
||||
from->set(relative[0] ? (*from)[0] * area.width() : (*from)[0],
|
||||
relative[1] ? (*from)[1] * area.height() : (*from)[1]);
|
||||
} else {
|
||||
from->set(0.0, 0.0);
|
||||
}
|
||||
}
|
||||
|
||||
if (to.isValid()) {
|
||||
RELATIVE_XY(Target);
|
||||
to.set( relative[0] ? to[0] * area.width() : to[0],
|
||||
relative[1] ? to[1] * area.height() : to[1] );
|
||||
} else {
|
||||
to.set(0.0, 0.0);
|
||||
if (to) {
|
||||
if (from->isValid()) {
|
||||
RELATIVE_XY(Target);
|
||||
to->set(relative[0] ? (*to)[0] * area.width() : (*to)[0],
|
||||
relative[1] ? (*to)[1] * area.height() : (*to)[1]);
|
||||
} else {
|
||||
to->set(0.0, 0.0);
|
||||
}
|
||||
}
|
||||
|
||||
} else if (a == Clip) {
|
||||
if (!from.isValid()) {
|
||||
from.set(1.0,1.0);
|
||||
setMetaData( SourceAnchor, metaData(TargetAnchor, meta), meta );
|
||||
if (from && !from->isValid()) {
|
||||
from->set(1.0,1.0);
|
||||
setMetaData(SourceAnchor, metaData(TargetAnchor, meta), meta);
|
||||
}
|
||||
if (!to.isValid()) {
|
||||
to.set(1.0,1.0);
|
||||
setMetaData( TargetAnchor, metaData(SourceAnchor, meta), meta );
|
||||
if (to && !to->isValid()) {
|
||||
to->set(1.0,1.0);
|
||||
setMetaData(TargetAnchor, metaData(SourceAnchor, meta), meta);
|
||||
}
|
||||
|
||||
} else if (a == CrossFadePrevious) {
|
||||
if (!from.isValid()) {
|
||||
from.set(0.0);
|
||||
if (from && !from->isValid()) {
|
||||
from->set(0.0);
|
||||
}
|
||||
if (!to.isValid()) {
|
||||
to.set(1.0);
|
||||
if (to && !to->isValid()) {
|
||||
to->set(1.0);
|
||||
}
|
||||
w->referencePreviousWindowPixmap();
|
||||
}
|
||||
}
|
||||
|
||||
quint64 AnimationEffect::p_animate( EffectWindow *w, Attribute a, uint meta, int ms, FPx2 to, QEasingCurve curve, int delay, FPx2 from, bool keepAtTarget )
|
||||
{
|
||||
const bool waitAtSource = from.isValid();
|
||||
validate(a, meta, &from, &to, w);
|
||||
if (a == CrossFadePrevious)
|
||||
w->referencePreviousWindowPixmap();
|
||||
|
||||
Q_D(AnimationEffect);
|
||||
if (!d->m_isInitialized)
|
||||
|
@ -233,6 +252,27 @@ quint64 AnimationEffect::p_animate( EffectWindow *w, Attribute a, uint meta, int
|
|||
return ret_id;
|
||||
}
|
||||
|
||||
bool AnimationEffect::retarget(quint64 animationId, FPx2 newTarget, int newRemainingTime)
|
||||
{
|
||||
Q_D(AnimationEffect);
|
||||
if (animationId == d->m_justEndedAnimation)
|
||||
return false; // this is just ending, do not try to retarget it
|
||||
for (AniMap::iterator entry = d->m_animations.begin(),
|
||||
mapEnd = d->m_animations.end(); entry != mapEnd; ++entry) {
|
||||
for (QList<AniData>::iterator anim = entry->first.begin(),
|
||||
animEnd = entry->first.end(); anim != animEnd; ++anim) {
|
||||
if (quint64(&(*anim)) == animationId) {
|
||||
anim->from.set(interpolated(*anim, 0), interpolated(*anim, 1));
|
||||
validate(anim->attribute, anim->meta, nullptr, &newTarget, entry.key());
|
||||
anim->to.set(newTarget[0], newTarget[1]);
|
||||
anim->duration = anim->time + newRemainingTime;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false; // no animation found
|
||||
}
|
||||
|
||||
bool AnimationEffect::cancel(quint64 animationId)
|
||||
{
|
||||
Q_D(AnimationEffect);
|
||||
|
|
|
@ -172,6 +172,19 @@ protected:
|
|||
quint64 set( EffectWindow *w, Attribute a, uint meta, int ms, FPx2 to, QEasingCurve curve = QEasingCurve(), int delay = 0, FPx2 from = FPx2() )
|
||||
{ return p_animate(w, a, meta, ms, to, curve, delay, from, true); }
|
||||
|
||||
/**
|
||||
* this allows to alter the target (but not type or curve) of a running animation
|
||||
* with the ID @param animationId
|
||||
* @param newTarget alters the "to" parameter of the animation
|
||||
* If @param newRemainingTime allows to lengthen (or shorten) the remaining time
|
||||
* of the animation. By default (-1) the remaining time remains unchanged
|
||||
*
|
||||
* Please use @function cancel to cancel an animation rather than altering it.
|
||||
* NOTICE that you can NOT retarget an animation that just has just @function animationEnded !
|
||||
* @return whether there was such animation and it could be altered
|
||||
*/
|
||||
bool retarget(quint64 animationId, FPx2 newTarget, int newRemainingTime = -1);
|
||||
|
||||
/**
|
||||
* Called whenever an animation end, passes the transformed @class EffectWindow @enum Attribute and originally supplied @param meta
|
||||
* You can reimplement it to keep a constant transformation for the window (ie. keep it a this opacity or position) or to start another animation
|
||||
|
@ -200,6 +213,7 @@ private:
|
|||
float progress( const AniData& ) const;
|
||||
void disconnectGeometryChanges();
|
||||
void updateLayerRepaints();
|
||||
void validate(Attribute a, uint &meta, FPx2 *from, FPx2 *to, const EffectWindow *w) const;
|
||||
private Q_SLOTS:
|
||||
void init();
|
||||
void triggerRepaint();
|
||||
|
|
Loading…
Reference in New Issue