add AnimationEffect::set() and ::cancel()

This will allow to sue the AnimationEffect class for
(temorarily) persistent changes like required by the
translucency effect

REVIEW: 109211
This commit is contained in:
Thomas Lübking 2013-02-28 19:51:00 +01:00
parent 9aef5b85a0
commit 39499de9cc
5 changed files with 62 additions and 11 deletions

View file

@ -30,11 +30,11 @@ AniData::AniData()
attribute = AnimationEffect::Opacity;
windowType = (NET::WindowTypeMask)0;
duration = time = meta = startTime = 0;
waitAtSource = false;
waitAtSource = keepAtTarget = false;
}
AniData::AniData(AnimationEffect::Attribute a, int meta, int ms, const FPx2 &to,
QEasingCurve curve, int delay, const FPx2 &from, bool waitAtSource )
QEasingCurve curve, int delay, const FPx2 &from, bool waitAtSource, bool keepAtTarget )
{
attribute = a;
this->from = from;
@ -44,6 +44,7 @@ AniData::AniData(AnimationEffect::Attribute a, int meta, int ms, const FPx2 &to,
time = 0;
this->meta = meta;
this->waitAtSource = waitAtSource;
this->keepAtTarget = keepAtTarget;
startTime = AnimationEffect::clock() + delay;
}
@ -58,6 +59,8 @@ AniData::AniData(const AniData &other)
customCurve = other.customCurve;
windowType = other.windowType;
meta = other.meta;
waitAtSource = other.waitAtSource;
keepAtTarget = other.keepAtTarget;
startTime = other.startTime;
}

View file

@ -31,7 +31,7 @@ class AniData {
public:
AniData();
AniData(AnimationEffect::Attribute a, int meta, int ms, const FPx2 &to,
QEasingCurve curve, int delay, const FPx2 &from, bool waitAtSource );
QEasingCurve curve, int delay, const FPx2 &from, bool waitAtSource, bool keepAtTarget = false);
AniData(const AniData &other);
explicit AniData(const QString &str);
inline void addTime(int t) { time += t; }
@ -48,7 +48,7 @@ public:
uint meta;
qint64 startTime;
NET::WindowTypeMask windowType;
bool waitAtSource;
bool waitAtSource, keepAtTarget;
};
} // namespace

View file

@ -74,7 +74,7 @@ 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)) }
void AnimationEffect::animate( EffectWindow *w, Attribute a, uint meta, int ms, FPx2 to, QEasingCurve curve, int delay, FPx2 from )
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();
if (a < NonFloatBase) {
@ -179,7 +179,8 @@ void AnimationEffect::animate( EffectWindow *w, Attribute a, uint meta, int ms,
AniMap::iterator it = d->m_animations.find(w);
if (it == d->m_animations.end())
it = d->m_animations.insert(w, QPair<QList<AniData>, QRect>(QList<AniData>(), QRect()));
it->first.append(AniData(a, meta, ms, to, curve, delay, from, waitAtSource));
it->first.append(AniData(a, meta, ms, to, curve, delay, from, waitAtSource, keepAtTarget));
quint64 ret_id = quint64(&it->first.last());
it->second = QRect();
d->m_animationsTouched = true;
@ -192,6 +193,29 @@ void AnimationEffect::animate( EffectWindow *w, Attribute a, uint meta, int ms,
else {
triggerRepaint();
}
return ret_id;
}
bool AnimationEffect::cancel(quint64 animationId)
{
Q_D(AnimationEffect);
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) {
entry->first.erase(anim); // remove the animation
if (entry->first.isEmpty()) { // no other animations on the window, release it.
const int i = d->m_zombies.indexOf(entry.key());
if ( i > -1 ) {
d->m_zombies.removeAt( i );
entry.key()->unrefWindow();
}
d->m_animations.erase(entry);
}
return true;
}
}
}
return false;
}
void AnimationEffect::prePaintScreen( ScreenPrePaintData& data, int time )
@ -221,7 +245,7 @@ void AnimationEffect::prePaintScreen( ScreenPrePaintData& data, int time )
anim->addTime(time);
}
if (anim->time < anim->duration) {
if (anim->time < anim->duration || anim->keepAtTarget) {
// if (anim->attribute != Brightness && anim->attribute != Saturation && anim->attribute != Opacity)
// transformed = true;
d->m_animated = true;
@ -540,14 +564,18 @@ float AnimationEffect::interpolated( const AniData &a, int i ) const
{
if (a.startTime > clock())
return a.from[i];
return a.from[i] + a.curve.valueForProgress( ((float)a.time)/a.duration )*(a.to[i] - a.from[i]);
if (a.time < a.duration)
return a.from[i] + a.curve.valueForProgress( ((float)a.time)/a.duration )*(a.to[i] - a.from[i]);
return a.to[i]; // we're done and "waiting" at the target value
}
float AnimationEffect::progress( const AniData &a ) const
{
if (a.startTime > clock())
return 0.0;
return a.curve.valueForProgress( ((float)a.time)/a.duration );
if (a.time < a.duration)
return a.curve.valueForProgress( ((float)a.time)/a.duration );
return 1.0; // we're done and "waiting" at the target value
}

View file

@ -155,13 +155,32 @@ protected:
* @param shape - How the animation progresses, eg. Linear progresses constantly while Exponential start slow and becomes very fast in the end
* @param delay - When the animation will start compared to "now" (the window will remain at the "from" position until then)
* @param from - the starting value, the default is invalid, ie. the attribute for the window is not transformed in the beginning
* @return an ID that you can use to cancel a running animation
*/
void animate( EffectWindow *w, Attribute a, uint meta, int ms, FPx2 to, QEasingCurve curve = QEasingCurve(), int delay = 0, FPx2 from = FPx2() );
quint64 animate( 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, false); }
/**
* Equal to ::animate() with one important difference:
* The target value for the attribute is kept until you ::cancel() this animation
* @return an ID that you need to use to cancel this manipulation
*/
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); }
/**
* 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
*/
virtual void animationEnded( EffectWindow *, Attribute, uint meta ) {Q_UNUSED(meta);}
/**
* Cancel a running animation. @return true if an animation for @p animationId was found (and canceled)
* NOTICE that there is NO animated reset of the original value. You'll have to provide that with a second animation
* NOTICE as well that this will eventually release a Deleted window.
* If you intend to run another animation on the (Deleted) window, you have to do that before cancelling the old animation (to keep the window around)
*/
bool cancel(quint64 animationId);
/**
* Called if the transformed @enum Attribute is Generic. You should reimplement it if you transform this "Attribute".
* You could use the meta information to eg. support more than one additional animations
@ -170,6 +189,7 @@ protected:
{Q_UNUSED(w); Q_UNUSED(data); Q_UNUSED(progress); Q_UNUSED(meta);}
private:
quint64 p_animate( EffectWindow *w, Attribute a, uint meta, int ms, FPx2 to, QEasingCurve curve, int delay, FPx2 from, bool keepAtTarget );
QRect clipRect(const QRect &windowRect, const AniData&) const;
void clipWindow(const EffectWindow *, const AniData &, WindowQuadList &) const;
float interpolated( const AniData&, int i = 0 ) const;

View file

@ -170,7 +170,7 @@ X-KDE-Library=kwin4_effect_cooleffect
#define KWIN_EFFECT_API_MAKE_VERSION( major, minor ) (( major ) << 8 | ( minor ))
#define KWIN_EFFECT_API_VERSION_MAJOR 0
#define KWIN_EFFECT_API_VERSION_MINOR 220
#define KWIN_EFFECT_API_VERSION_MINOR 221
#define KWIN_EFFECT_API_VERSION KWIN_EFFECT_API_MAKE_VERSION( \
KWIN_EFFECT_API_VERSION_MAJOR, KWIN_EFFECT_API_VERSION_MINOR )