on xenial help sign in
improved the whole animation a lot
commit44f7ef579bc48238ae7bb3497f7d7df3423e9a35 authorMichael Zanetti <michael.zanetti@canonical.com> dateWed 15 Jan 2014, 10:43 (13 years ago) parent240add3
5 files changed+267−102
plugins/Utils/CMakeLists.txt+2−1 plugins/Utils/easingcurve.cpp+49 plugins/Utils/easingcurve.h+42 plugins/Utils/plugin.cpp+2 qml/Stages/PhoneStage.qml+172−101
plugins/Utils/CMakeLists.txt+2−1
@@ -18,6 +18,7 @@ set(QMLPLUGIN_SRC
1818 qsortfilterproxymodelqml.cpp
1919 timeformatter.cpp
2020 unitymenumodelpaths.cpp
21+ easingcurve.cpp
2122 plugin.cpp
2223 )
2324
@@ -33,7 +34,7 @@ target_link_libraries(Utils-qml ${GIO_LDFLAGS})
3334# files directly in targets.
3435set_target_properties(Utils-qml PROPERTIES COMPILE_FLAGS -fvisibility=default)
3536
36−qt5_use_modules(Utils-qml Qml Quick DBus Network XmlPatterns)
37+qt5_use_modules(Utils-qml Qml Quick DBus Network XmlPatterns Gui)
3738
3839# export the qmldir qmltypes and plugin files
3940export_qmlfiles(Utils Utils)
plugins/Utils/easingcurve.cppnew file+49
@@ -0,0 +1,49 @@
1+#include "easingcurve.h"
2+
3+
4+EasingCurve::EasingCurve(QObject *parent):
5+ QObject(parent)
6+{
7+
8+}
9+
10+QEasingCurve::Type EasingCurve::type() const
11+{
12+ return m_easingCurve.type();
13+}
14+
15+void EasingCurve::setType(const QEasingCurve::Type &type)
16+{
17+ m_easingCurve.setType(type);
18+ Q_EMIT typeChanged();
19+}
20+
21+qreal EasingCurve::period() const
22+{
23+ return m_easingCurve.period();
24+}
25+
26+void EasingCurve::setPeriod(qreal period)
27+{
28+ m_easingCurve.setPeriod(period);
29+ Q_EMIT periodChanged();
30+}
31+
32+qreal EasingCurve::progress() const
33+{
34+ return m_progress;
35+}
36+
37+void EasingCurve::setProgress(qreal progress)
38+{
39+ if (m_progress != progress) {
40+ m_progress = progress;
41+ m_value = m_easingCurve.valueForProgress(m_progress);
42+ Q_EMIT progressChanged();
43+ }
44+}
45+
46+qreal EasingCurve::value() const
47+{
48+ return m_value;
49+}
plugins/Utils/easingcurve.hnew file+42
@@ -0,0 +1,42 @@
1+#ifndef EASINGCURVE_H
2+#define EASINGCURVE_H
3+
4+#include <QObject>
5+#include <QEasingCurve>
6+
7+class EasingCurve: public QObject
8+{
9+ Q_OBJECT
10+ Q_ENUMS(QEasingCurve::Type)
11+ Q_PROPERTY(QEasingCurve::Type type READ type WRITE setType NOTIFY typeChanged)
12+ Q_PROPERTY(qreal period READ period WRITE setPeriod NOTIFY periodChanged)
13+ Q_PROPERTY(qreal progress READ progress WRITE setProgress NOTIFY progressChanged)
14+ Q_PROPERTY(qreal value READ value NOTIFY progressChanged)
15+
16+public:
17+ EasingCurve(QObject *parent = 0);
18+
19+ QEasingCurve::Type type() const;
20+ void setType(const QEasingCurve::Type &type);
21+
22+ qreal period() const;
23+ void setPeriod(qreal period);
24+
25+ qreal progress() const;
26+ void setProgress(qreal progress);
27+
28+ qreal value() const;
29+
30+Q_SIGNALS:
31+ void typeChanged();
32+ void periodChanged();
33+ void progressChanged();
34+
35+private:
36+ QEasingCurve m_easingCurve;
37+ qreal m_progress;
38+ qreal m_value;
39+};
40+
41+#endif
42+
plugins/Utils/plugin.cpp+2
@@ -32,6 +32,7 @@
3232#include "qsortfilterproxymodelqml.h"
3333#include "timeformatter.h"
3434#include "unitymenumodelpaths.h"
35+#include "easingcurve.h"
3536
3637static const char* BOTTOM_BAR_VISIBILITY_COMMUNICATOR_DBUS_PATH = "/BottomBarVisibilityCommunicator";
3738static const char* DBUS_SERVICE = "com.canonical.Shell.BottomBarVisibilityCommunicator";
@@ -46,6 +47,7 @@ void UtilsPlugin::registerTypes(const char *uri)
4647 qmlRegisterType<TimeFormatter>(uri, 0, 1, "TimeFormatter");
4748 qmlRegisterType<GDateTimeFormatter>(uri, 0, 1, "GDateTimeFormatter");
4849 qmlRegisterUncreatableType<BottomBarVisibilityCommunicatorShell>(uri, 0, 1, "BottomBarVisibilityCommunicatorShell", "Can't create BottomBarVisibilityCommunicatorShell");
50+ qmlRegisterType<EasingCurve>(uri, 0, 1, "EasingCurve");
4951}
5052
5153void UtilsPlugin::initializeEngine(QQmlEngine *engine, const char *uri)
qml/Stages/PhoneStage.qml+172−101
@@ -2,6 +2,7 @@ import QtQuick 2.0
22import Ubuntu.Components 0.1
33import Ubuntu.Gestures 0.1
44import Unity.Application 0.1
5+import Utils 0.1
56import "../Components"
67
78/*
@@ -18,6 +19,7 @@ Item {
1819
1920 // State information propagated to the outside
2021 readonly property bool painting: mainScreenshotImage.visible || fadeInScreenshotImage.visible || appSplash.visible
22+ onPaintingChanged: print("**********************+ painting changed", painting)
2123
2224 onMovingChanged: {
2325 if (moving) {
@@ -230,8 +232,8 @@ Item {
230232 onContentXChanged: {
231233// print("contentX changed", contentX)
232234 var progress = contentX / width
233− if (progress > .5) {
234− progress += progress - .5
235+ if (progress > coverFlip.progressMarker1) {
236+ progress += progress - coverFlip.progressMarker1
235237 }
236238
237239 coverFlip.progress = progress;
@@ -256,6 +258,8 @@ Item {
256258 // marks the line where first application is finished moving in from the right
257259 property real progressMarker1: 0.5
258260
261+ property real tileDistance: 0.1
262+
259263 property bool animatingBack: false
260264
261265 property real tileWidth: root.width
@@ -311,10 +315,6 @@ Item {
311315 height: parent.height
312316 width: coverFlip.tileWidth
313317
314− function select() {
315− switchToAppAnimation.start();
316− }
317−
318318 Image {
319319 id: appImage
320320 anchors { left: parent.left; bottom: parent.bottom }
@@ -322,7 +322,30 @@ Item {
322322 source: ApplicationManager.get(index).screenshot
323323 scale: 1
324324
325+ // This is the main progress, of the gesture, the same for every tile
325326 property real progress: coverFlip.progress
327+ // The progress, translated for the second stage of the animation, after the first app switch has happened
328+ // Additionally it speeds it up a bit, depending on the distance of the tile
329+ property real translatedProgress: appImage.progress - coverFlip.progressMarker1 - (coverFlip.tileDistance * (index-1))
330+
331+ // Is this tile selected by a click?
332+ property bool isSelected: false
333+ // We need to remember some values when app is selected to be able to animate it to the foreground
334+ property real selectedXTranslation: 0
335+ property real selectedTranslatedProgress: 0
336+ property real selectedAngle: 0
337+ property real selectedXScale: 0
338+
339+ function select() {
340+ print("selecting item, current translation:", appImage.xTranslation)
341+ appImage.selectedXTranslation = appImage.xTranslation;
342+ appImage.selectedAngle = appImage.angle;
343+ appImage.selectedXScale = appImage.xScale;
344+ appImage.selectedTranslatedProgress = appImage.translatedProgress;
345+ print("set selected x translation", appImage.selectedXTranslation)
346+ appImage.isSelected = true;
347+ switchToAppAnimation.start();
348+ }
326349
327350 property int xTranslation: {
328351 var xTranslate = 0;
@@ -349,113 +372,165 @@ Item {
349372 // Intentionally no break here...
350373 default:
351374 if (appImage.progress > coverFlip.progressMarker1) {
352− // Used to move all tiles directly to the right of the screen as starting position
353− var mainTranslate = -root.width * (index - 1)
354− // Used to add the offset to each tile so they are not on one stack
355− var indexTranslate = (index - 1) * root.width / 4
375+ xTranslate = xTranslateEasing.value * xTranslateEasing.period;
356376
357− var progress = appImage.progress - coverFlip.progressMarker1
358− var progressDiff = 1 - coverFlip.progressMarker1
359− var translateDiff = -root.width * coverFlip.progressMarker1// -(coverFlip.progressMarker1 + index * root.width * 0.25 + root.width * 0.25)
377+ // make sure we stop at the left screen edge
378+// xTranslate = Math.max(xTranslate, minXTranslate)
379+ break;
380+ }
381+ }
382+ if (appImage.isSelected) {
383+ var newTranslate = selectedXTranslateEasing.value * selectedXTranslateEasing.period
384+ xTranslate = appImage.selectedXTranslation + newTranslate;
385+ }
360386
361− // progress : progressDiff = translate : translateDiff
362− xTranslate = progress * translateDiff / progressDiff;
387+ return xTranslate;
388+ }
363389
364− // Add starting point and index translate
365− xTranslate += mainTranslate + indexTranslate;
390+ property real angle: {
391+ var newAngle = 0;
392+ switch (index) {
393+ case 0:
394+ if (appImage.progress <= coverFlip.progressMarker1) {
395+ var progress = appImage.progress;
396+ var angleDiff = coverFlip.endAngle;
397+ var progressDiff = coverFlip.progressMarker1;
398+ // progress : progressDiff = angle : angleDiff
399+ newAngle = progress * angleDiff / progressDiff;
400+ } else {
401+ var progress = appImage.progress - coverFlip.progressMarker1;
402+ var angleDiff = coverFlip.endAngle;
403+ var progressDiff = 1 - coverFlip.progressMarker1;
404+ // progress : progressDiff = angle : angleDiff
405+ newAngle = progress * angleDiff / progressDiff;
406+ newAngle = Math.min(coverFlip.endAngle, newAngle);
407+ }
408+ break;
409+ case 1:
410+ if (appImage.progress < coverFlip.progressMarker1) {
411+ var progress = coverFlip.progress;
412+ var angleDiff = coverFlip.startAngle;
413+ var progressDiff = coverFlip.progressMarker1;
414+ // progress : progressDiff = angle : angleDiff
415+ var angle = progress * angleDiff / progressDiff;
416+ newAngle = coverFlip.startAngle - angle;
417+ break;
418+ }
419+ // Intentionally no break here...
420+ default:
421+// var progress = appImage.progress;
422+// var angleDiff = coverFlip.startAngle - coverFlip.endAngle;
423+//// var progressDiff = coverFlip.progressMarker1 + index * 0.25 + 0.25
424+// var progressDiff = index
425+// // progress : progressDiff = angle : angleDiff
426+// newAngle = progress * angleDiff / progressDiff;
427+// newAngle = Math.max(coverFlip.endAngle, coverFlip.startAngle - newAngle)
366428
367− // make sure we stop at the left screen edge
368− xTranslate = Math.max(xTranslate, minXTranslate)
429+ newAngle = coverFlip.startAngle - (angleEasing.value * angleEasing.period);
430+
431+ // make sure we stop at the left screen edge
432+ newAngle = Math.max(newAngle, coverFlip.endAngle);
433+
434+ }
435+ if (appImage.isSelected) {
436+ var selectedAngleTranslate = selectedAngleEasing.value * selectedAngleEasing.period
437+ print("selectedAngle", appImage.selectedAngle, "translate", selectedAngleTranslate)
438+ newAngle = appImage.selectedAngle - selectedAngleTranslate;
439+ }
440+
441+ return newAngle;
442+ }
443+
444+ property real xScale: {
445+ var scale = 1;
446+
447+ switch (index) {
448+ case 0:
449+ if (appImage.progress > coverFlip.progressMarker1) {
450+ var scaleDiff = coverFlip.maxScale - 1;
451+ var progressDiff = 1.5 - coverFlip.progressMarker1;
452+ // progress : progressDiff = scale : scaleDiff
453+ scale = 1 - (appImage.progress - coverFlip.progressMarker1) * scaleDiff / progressDiff;
454+ }
455+ break;
456+ case 1:
457+ if (appImage.progress < coverFlip.progressMarker1) {
458+ var scaleDiff = coverFlip.maxScale - 1
459+ var progressDiff = coverFlip.progressMarker1
460+ // progress : progressDiff = scale : scaleDiff
461+ scale = coverFlip.maxScale - (appImage.progress * scaleDiff / progressDiff);
369462 break;
370463 }
464+ // Intentionally no break
465+ default:
466+// var scaleDiff = coverFlip.maxScale - coverFlip.minScale
467+//// var progressDiff = coverFlip.progressMarker1 + index * 0.25 + 0.25
468+// var progressDiff = index
469+// // progress : progressDiff = scale : scaleDiff
470+// scale = coverFlip.maxScale - (appImage.progress - coverFlip.progressMarker1) * scaleDiff / progressDiff
471+// break;
472+
473+ scale = coverFlip.maxScale - scaleEasing.value * scaleEasing.period;
371474 }
372− return xTranslate;
475+
476+ if (appImage.isSelected) {
477+ var selectedScaleTranslate = selectedScaleEasing.value * selectedScaleEasing.period
478+ scale = appImage.selectedXScale + selectedScaleTranslate;
479+ }
480+
481+ return Math.min(coverFlip.maxScale, Math.max(coverFlip.minScale, scale));
482+ }
483+
484+
485+ EasingCurve {
486+ id: xTranslateEasing
487+ type: EasingCurve.OutQuad
488+ period: index * -width
489+ progress: appImage.translatedProgress
490+ }
491+ EasingCurve {
492+ id: selectedXTranslateEasing
493+ type: EasingCurve.Linear
494+ period: xTranslateEasing.period - appImage.selectedXTranslation
495+ progress: appImage.selectedTranslatedProgress - xTranslateEasing.progress
496+ }
497+ EasingCurve {
498+ id: angleEasing
499+ type: EasingCurve.InQuad
500+ period: coverFlip.startAngle - coverFlip.endAngle
501+ progress: appImage.translatedProgress
502+ }
503+ EasingCurve {
504+ id: selectedAngleEasing
505+ type: EasingCurve.Linear
506+ period: appImage.selectedAngle
507+ progress: appImage.selectedTranslatedProgress - angleEasing.progress
508+ }
509+ EasingCurve {
510+ id: scaleEasing
511+ type: EasingCurve.Linear
512+ period: coverFlip.maxScale - coverFlip.minScale
513+ progress: appImage.translatedProgress
514+ }
515+ EasingCurve {
516+ id: selectedScaleEasing
517+ type: EasingCurve.Linear
518+ period: 1 - appImage.selectedXScale
519+ progress: appImage.selectedTranslatedProgress - scaleEasing.progress
373520 }
374521
375522 transform: [
376523 Rotation {
377524 origin { x: 0; y: coverFlip.height / 2 }
378525 axis { x: 0; y: 1; z: 0 }
379− angle: {
380− var newAngle = 0;
381− if (coverFlip.animatingBack) {
382− newAngle = Math.min(appImage.progress, .75) * coverFlip.endAngle;
383− } else {
384− switch (index) {
385− case 0:
386− if (appImage.progress <= coverFlip.progressMarker1) {
387− var progress = appImage.progress;
388− var angleDiff = coverFlip.endAngle;
389− var progressDiff = coverFlip.progressMarker1;
390− // progress : progressDiff = angle : angleDiff
391− newAngle = progress * angleDiff / progressDiff;
392− } else {
393− var progress = appImage.progress - coverFlip.progressMarker1;
394− var angleDiff = coverFlip.endAngle;
395− var progressDiff = 1 - coverFlip.progressMarker1;
396− // progress : progressDiff = angle : angleDiff
397− newAngle = progress * angleDiff / progressDiff;
398− newAngle = Math.min(coverFlip.endAngle, newAngle);
399− }
400− break;
401− case 1:
402− if (appImage.progress < coverFlip.progressMarker1) {
403− var progress = coverFlip.progress;
404− var angleDiff = coverFlip.startAngle;
405− var progressDiff = coverFlip.progressMarker1;
406− // progress : progressDiff = angle : angleDiff
407− var angle = progress * angleDiff / progressDiff;
408− newAngle = coverFlip.startAngle - angle;
409− break;
410− }
411− // Intentionally no break here...
412− default:
413− var progress = appImage.progress;
414− var angleDiff = coverFlip.startAngle - coverFlip.endAngle;
415− var progressDiff = coverFlip.progressMarker1 + index * 0.25 + 0.25
416− // progress : progressDiff = angle : angleDiff
417− newAngle = progress * angleDiff / progressDiff;
418− newAngle = Math.max(coverFlip.endAngle, coverFlip.startAngle - newAngle)
419− }
420− }
421− return newAngle;
422− }
526+ angle: appImage.angle
423527 },
424528 Translate {
425529 x: appImage.xTranslation
426530 },
427531 Scale {
428532 origin { x: appImage.xTranslation; y: root.height / 2 - (root.height - appImage.height)}
429− xScale: {
430− var scale = 1;
431−
432− switch (index) {
433− case 0:
434− if (appImage.progress > coverFlip.progressMarker1) {
435− var scaleDiff = coverFlip.maxScale - 1;
436− var progressDiff = 1.5 - coverFlip.progressMarker1;
437− // progress : progressDiff = scale : scaleDiff
438− scale = 1 - (appImage.progress - coverFlip.progressMarker1) * scaleDiff / progressDiff;
439− }
440− break;
441− case 1:
442− if (appImage.progress < coverFlip.progressMarker1) {
443− var scaleDiff = coverFlip.maxScale - 1
444− var progressDiff = coverFlip.progressMarker1
445− // progress : progressDiff = scale : scaleDiff
446− scale = coverFlip.maxScale - (appImage.progress * scaleDiff / progressDiff);
447− break;
448− }
449− // Intentionally no break
450− default:
451− var scaleDiff = coverFlip.maxScale - coverFlip.minScale
452− var progressDiff = coverFlip.progressMarker1 + index * 0.25 + 0.25
453− // progress : progressDiff = scale : scaleDiff
454− scale = coverFlip.maxScale - (appImage.progress - coverFlip.progressMarker1) * scaleDiff / progressDiff
455− break;
456− }
457− return Math.min(coverFlip.maxScale, Math.max(coverFlip.minScale, scale));
458− }
533+ xScale: appImage.xScale
459534 yScale: xScale
460535 }
461536 ]
@@ -464,25 +539,21 @@ Item {
464539 anchors.fill: parent
465540 onClicked: {
466541 print("clicked on index", index)
467− select()
542+ appImage.select()
468543 }
469544 }
470545 }
471546
472547 SequentialAnimation {
473548 id: switchToAppAnimation
474− PropertyAction { target: coverFlip; property: "animatingBack"; value: true }
475549 ParallelAnimation {
476− UbuntuNumberAnimation { target: coverFlickable; property: "contentX"; to: 0; duration: 5000 }
477− UbuntuNumberAnimation { target: coverFlip; property: "x"; to: -root.width * index; duration: 5000 }
550+ UbuntuNumberAnimation { target: coverFlickable; property: "contentX"; to: 0}
478551 }
479552 ScriptAction {
480553 script: {
481554 ApplicationManager.focusApplication(ApplicationManager.get(index).appId);
555+ appImage.isSelected = false;
482556 coverFlip.progress = 0;
483− coverFlip.x = 0;
484− coverFlip.animatingBack = false;
485− appImage.x = 0;
486557 }
487558 }
488559 }