Commit ee725696 authored by Vlad Zahorodnii's avatar Vlad Zahorodnii

[libkwineffects] Port AnimationEffect to TimeLine

Summary:
TimeLine has nice API for controlling its direction that can be re-used
later by AnimationEffect.

Test Plan: The existing tests for scripting effects still pass.

Reviewers: #kwin, davidedmundson, graesslin

Reviewed By: #kwin, davidedmundson, graesslin

Subscribers: davidedmundson, abetts, kwin

Tags: #kwin

Differential Revision: https://phabricator.kde.org/D16448
parent e0257326
......@@ -49,6 +49,8 @@ along with this program. If not, see <http:// www.gnu.org/licenses/>.
#include <KWayland/Client/xdgshell.h>
using namespace KWin;
using namespace std::chrono_literals;
static const QString s_socketName = QStringLiteral("wayland_test_effects_scripts-0");
class ScriptedEffectsTest : public QObject
......@@ -289,25 +291,20 @@ void ScriptedEffectsTest::testAnimations()
QVERIFY(c);
QCOMPARE(workspace()->activeClient(), c);
// we are running the event loop during renderAndWaitForShown
// some time will pass with the event loop running between the window being added and getting to here
// anim.duration is an aboslute value, but retarget will update the duration based on time passed
int timePassed = 0;
{
const AnimationEffect::AniMap state = effect->state();
QCOMPARE(state.count(), 1);
QCOMPARE(state.firstKey(), c->effectWindow());
const auto &animationsForWindow = state.first().first;
QCOMPARE(animationsForWindow.count(), animationCount);
QCOMPARE(animationsForWindow[0].duration, 100);
QCOMPARE(animationsForWindow[0].timeLine.duration(), 100ms);
QCOMPARE(animationsForWindow[0].to, FPx2(1.4));
QCOMPARE(animationsForWindow[0].attribute, AnimationEffect::Scale);
QCOMPARE(animationsForWindow[0].curve.type(), QEasingCurve::OutQuad);
QCOMPARE(animationsForWindow[0].timeLine.easingCurve().type(), QEasingCurve::OutQuad);
QCOMPARE(animationsForWindow[0].keepAtTarget, false);
timePassed = animationsForWindow[0].time;
if (animationCount == 2) {
QCOMPARE(animationsForWindow[1].duration, 100);
QCOMPARE(animationsForWindow[1].timeLine.duration(), 100ms);
QCOMPARE(animationsForWindow[1].to, FPx2(0.0));
QCOMPARE(animationsForWindow[1].attribute, AnimationEffect::Opacity);
QCOMPARE(animationsForWindow[1].keepAtTarget, false);
......@@ -323,12 +320,12 @@ void ScriptedEffectsTest::testAnimations()
QCOMPARE(state.count(), 1);
const auto &animationsForWindow = state.first().first;
QCOMPARE(animationsForWindow.count(), animationCount);
QCOMPARE(animationsForWindow[0].duration, 200 + timePassed);
QCOMPARE(animationsForWindow[0].timeLine.duration(), 200ms);
QCOMPARE(animationsForWindow[0].to, FPx2(1.5));
QCOMPARE(animationsForWindow[0].attribute, AnimationEffect::Scale);
QCOMPARE(animationsForWindow[0].keepAtTarget, false);
if (animationCount == 2) {
QCOMPARE(animationsForWindow[1].duration, 200 + timePassed);
QCOMPARE(animationsForWindow[1].timeLine.duration(), 200ms);
QCOMPARE(animationsForWindow[1].to, FPx2(1.5));
QCOMPARE(animationsForWindow[1].attribute, AnimationEffect::Opacity);
QCOMPARE(animationsForWindow[1].keepAtTarget, false);
......
......@@ -70,8 +70,6 @@ PreviousWindowPixmapLock::~PreviousWindowPixmapLock()
AniData::AniData()
: attribute(AnimationEffect::Opacity)
, customCurve(0) // Linear
, time(0)
, duration(0)
, meta(0)
, startTime(0)
, waitAtSource(false)
......@@ -80,16 +78,13 @@ AniData::AniData()
{
}
AniData::AniData(AnimationEffect::Attribute a, int meta_, int ms, const FPx2 &to_,
QEasingCurve curve_, int delay, const FPx2 &from_, bool waitAtSource_, bool keepAtTarget_,
AniData::AniData(AnimationEffect::Attribute a, int meta_, const FPx2 &to_,
int delay, const FPx2 &from_, bool waitAtSource_, bool keepAtTarget_,
FullScreenEffectLockPtr fullScreenEffectLock_, bool keepAlive,
PreviousWindowPixmapLockPtr previousWindowPixmapLock_)
: attribute(a)
, curve(curve_)
, from(from_)
, to(to_)
, time(0)
, duration(ms)
, meta(meta_)
, startTime(AnimationEffect::clock() + delay)
, fullScreenEffectLock(fullScreenEffectLock_)
......@@ -122,6 +117,6 @@ QString AniData::debugInfo() const
QLatin1String("\n From: ") + from.toString() +
QLatin1String("\n To: ") + to.toString() +
QLatin1String("\n Started: ") + QString::number(AnimationEffect::clock() - startTime) + QLatin1String("ms ago\n") +
QLatin1String( " Duration: ") + QString::number(duration) + QLatin1String("ms\n") +
QLatin1String( " Passed: ") + QString::number(time) + QLatin1String("ms\n");
QLatin1String( " Duration: ") + QString::number(timeLine.duration().count()) + QLatin1String("ms\n") +
QLatin1String( " Passed: ") + QString::number(timeLine.elapsed().count()) + QLatin1String("ms\n");
}
......@@ -74,11 +74,11 @@ typedef QSharedPointer<PreviousWindowPixmapLock> PreviousWindowPixmapLockPtr;
class KWINEFFECTS_EXPORT AniData {
public:
AniData();
AniData(AnimationEffect::Attribute a, int meta, int ms, const FPx2 &to,
QEasingCurve curve, int delay, const FPx2 &from, bool waitAtSource,
AniData(AnimationEffect::Attribute a, int meta, const FPx2 &to,
int delay, const FPx2 &from, bool waitAtSource,
bool keepAtTarget = false, FullScreenEffectLockPtr=FullScreenEffectLockPtr(),
bool keepAlive = true, PreviousWindowPixmapLockPtr previousWindowPixmapLock = {});
inline void addTime(int t) { time += t; }
inline bool isOneDimensional() const {
return from[0] == from[1] && to[0] == to[1];
}
......@@ -86,10 +86,9 @@ public:
quint64 id{0};
QString debugInfo() const;
AnimationEffect::Attribute attribute;
QEasingCurve curve;
int customCurve;
FPx2 from, to;
int time, duration;
TimeLine timeLine;
uint meta;
qint64 startTime;
QSharedPointer<FullScreenEffectLock> fullScreenEffectLock;
......
......@@ -254,9 +254,7 @@ quint64 AnimationEffect::p_animate( EffectWindow *w, Attribute a, uint meta, int
it->first.append(AniData(
a, // Attribute
meta, // Metadata
ms, // Duration
to, // Target
curve, // Easing curve
delay, // Delay
from, // Source
waitAtSource, // Whether the animation should be kept at source
......@@ -266,8 +264,16 @@ quint64 AnimationEffect::p_animate( EffectWindow *w, Attribute a, uint meta, int
previousPixmap // Previous window pixmap lock
));
quint64 ret_id = ++d->m_animCounter;
it->first.last().id = ret_id;
const quint64 ret_id = ++d->m_animCounter;
AniData &animation = it->first.last();
animation.id = ret_id;
animation.timeLine.setDirection(TimeLine::Forward);
animation.timeLine.setDuration(std::chrono::milliseconds(ms));
animation.timeLine.setEasingCurve(curve);
animation.timeLine.setSourceRedirectMode(TimeLine::RedirectMode::Strict);
animation.timeLine.setTargetRedirectMode(TimeLine::RedirectMode::Relaxed);
it->second = QRect();
d->m_animationsTouched = true;
......@@ -297,7 +303,11 @@ bool AnimationEffect::retarget(quint64 animationId, FPx2 newTarget, int newRemai
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;
anim->timeLine.setDirection(TimeLine::Forward);
anim->timeLine.setDuration(std::chrono::milliseconds(newRemainingTime));
anim->timeLine.reset();
return true;
}
}
......@@ -351,10 +361,10 @@ void AnimationEffect::prePaintScreen( ScreenPrePaintData& data, int time )
continue;
}
} else {
anim->addTime(time);
anim->timeLine.update(std::chrono::milliseconds(time));
}
if (anim->time < anim->duration || anim->keepAtTarget) {
if (!anim->timeLine.done() || anim->keepAtTarget) {
// if (anim->attribute != Brightness && anim->attribute != Saturation && anim->attribute != Opacity)
// transformed = true;
d->m_animated = true;
......@@ -671,7 +681,7 @@ void AnimationEffect::postPaintScreen()
for (; anim != it->first.constEnd(); ++anim) {
if (anim->startTime > clock())
continue;
if (anim->time < anim->duration) {
if (!anim->timeLine.done()) {
addRepaint = true;
break;
}
......@@ -689,18 +699,14 @@ float AnimationEffect::interpolated( const AniData &a, int i ) const
{
if (a.startTime > clock())
return 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]);
if (!a.timeLine.done())
return a.from[i] + a.timeLine.value() * (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;
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
return a.startTime < clock() ? a.timeLine.value() : 0.0;
}
......@@ -782,7 +788,7 @@ void AnimationEffect::triggerRepaint()
static float fixOvershoot(float f, const AniData &d, short int dir, float s = 1.1)
{
switch(d.curve.type()) {
switch(d.timeLine.easingCurve().type()) {
case QEasingCurve::InOutElastic:
case QEasingCurve::InOutBack:
return f * s;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment