flick velocity and deceleration
C++ / fmt (pull_request) Successful in 3s
JS/TS / fmt (pull_request) Successful in 15s
JS/TS / lint (pull_request) Successful in 17s
Python / static (pull_request) Successful in 58s
Rust / fmt (pull_request) Successful in 1m4s
Rust / build (pull_request) Successful in 2m14s
C++ / build (pull_request) Successful in 2m36s
Rust / clippy (pull_request) Successful in 1m30s
Python / verify (pull_request) Successful in 2m53s
C++ / clang-tidy (pull_request) Successful in 4m4s
C++ / fmt (pull_request) Successful in 3s
JS/TS / fmt (pull_request) Successful in 15s
JS/TS / lint (pull_request) Successful in 17s
Python / static (pull_request) Successful in 58s
Rust / fmt (pull_request) Successful in 1m4s
Rust / build (pull_request) Successful in 2m14s
C++ / build (pull_request) Successful in 2m36s
Rust / clippy (pull_request) Successful in 1m30s
Python / verify (pull_request) Successful in 2m53s
C++ / clang-tidy (pull_request) Successful in 4m4s
This commit is contained in:
@@ -26,7 +26,6 @@ Singleton {
|
|||||||
|
|
||||||
function query(search: string): list<var> {
|
function query(search: string): list<var> {
|
||||||
search = transformSearch(search);
|
search = transformSearch(search);
|
||||||
console.log(!search, search, ...list);
|
|
||||||
if (!search)
|
if (!search)
|
||||||
return [...list];
|
return [...list];
|
||||||
|
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ CarouselView::CarouselView(QQuickItem* parent) : QQuickItem(parent) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
m_flickAnim = new QVariantAnimation(this);
|
m_flickAnim = new QVariantAnimation(this);
|
||||||
m_flickAnim->setEasingCurve(QEasingCurve::Linear);
|
m_flickAnim->setEasingCurve(QEasingCurve::OutQuad);
|
||||||
|
|
||||||
connect(
|
connect(
|
||||||
m_flickAnim,
|
m_flickAnim,
|
||||||
@@ -101,9 +101,8 @@ bool CarouselView::childMouseEventFilter(QQuickItem* item, QEvent* event) {
|
|||||||
|
|
||||||
m_dragTimer.start();
|
m_dragTimer.start();
|
||||||
|
|
||||||
m_lastMoveX = pos.x();
|
m_velocitySamples.clear();
|
||||||
m_lastMoveT = 0;
|
addVelocitySample(0, pos.x());
|
||||||
m_velocity = 0;
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -129,17 +128,7 @@ bool CarouselView::childMouseEventFilter(QQuickItem* item, QEvent* event) {
|
|||||||
updateCurrentIndexFromContentX(true);
|
updateCurrentIndexFromContentX(true);
|
||||||
relayout();
|
relayout();
|
||||||
|
|
||||||
const qint64 t = m_dragTimer.elapsed();
|
addVelocitySample(m_dragTimer.elapsed(), pos.x());
|
||||||
const qint64 dt = t - m_lastMoveT;
|
|
||||||
|
|
||||||
if (dt > 0) {
|
|
||||||
const qreal instVel = (m_lastMoveX - pos.x()) / (dt / 1000.0);
|
|
||||||
|
|
||||||
m_velocity = m_velocity * 0.7 + instVel * 0.3;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_lastMoveX = pos.x();
|
|
||||||
m_lastMoveT = t;
|
|
||||||
|
|
||||||
mouseEvent->accept();
|
mouseEvent->accept();
|
||||||
return true;
|
return true;
|
||||||
@@ -1141,10 +1130,8 @@ void CarouselView::mousePressEvent(QMouseEvent* event) {
|
|||||||
|
|
||||||
m_dragTimer.start();
|
m_dragTimer.start();
|
||||||
|
|
||||||
m_lastMoveX = event->position().x();
|
m_velocitySamples.clear();
|
||||||
|
addVelocitySample(0, event->position().x());
|
||||||
m_lastMoveT = 0;
|
|
||||||
m_velocity = 0;
|
|
||||||
|
|
||||||
event->accept();
|
event->accept();
|
||||||
}
|
}
|
||||||
@@ -1170,32 +1157,43 @@ void CarouselView::mouseMoveEvent(QMouseEvent* event) {
|
|||||||
updateCurrentIndexFromContentX(true);
|
updateCurrentIndexFromContentX(true);
|
||||||
relayout();
|
relayout();
|
||||||
|
|
||||||
const qint64 t = m_dragTimer.elapsed();
|
addVelocitySample(m_dragTimer.elapsed(), event->position().x());
|
||||||
|
|
||||||
const qint64 dt = t - m_lastMoveT;
|
|
||||||
|
|
||||||
if (dt > 0) {
|
|
||||||
const qreal instVel =
|
|
||||||
(m_lastMoveX - event->position().x()) / (dt / 1000.0);
|
|
||||||
|
|
||||||
m_velocity = m_velocity * 0.7 + instVel * 0.3;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_lastMoveX = event->position().x();
|
|
||||||
|
|
||||||
m_lastMoveT = t;
|
|
||||||
|
|
||||||
event->accept();
|
event->accept();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CarouselView::addVelocitySample(qint64 t, qreal x) {
|
||||||
|
m_velocitySamples.append({t, x});
|
||||||
|
|
||||||
|
while (m_velocitySamples.size() > 1 &&
|
||||||
|
t - m_velocitySamples.first().t > kVelocitySampleWindowMs) {
|
||||||
|
m_velocitySamples.removeFirst();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
qreal CarouselView::sampledVelocity() const {
|
||||||
|
if (m_velocitySamples.size() < 2) return 0;
|
||||||
|
|
||||||
|
const VelocitySample& oldest = m_velocitySamples.first();
|
||||||
|
const VelocitySample& newest = m_velocitySamples.last();
|
||||||
|
|
||||||
|
const qreal dt = newest.t - oldest.t;
|
||||||
|
|
||||||
|
if (dt < 8) return 0;
|
||||||
|
|
||||||
|
return (oldest.x - newest.x) / (dt / 1000.0);
|
||||||
|
}
|
||||||
|
|
||||||
void CarouselView::mouseReleaseEvent(QMouseEvent* event) {
|
void CarouselView::mouseReleaseEvent(QMouseEvent* event) {
|
||||||
if (!m_dragging) return;
|
if (!m_dragging) return;
|
||||||
|
|
||||||
m_dragging = false;
|
m_dragging = false;
|
||||||
|
|
||||||
|
const bool wasDragActive = m_dragActive;
|
||||||
|
|
||||||
ungrabMouse();
|
ungrabMouse();
|
||||||
|
|
||||||
if (!m_dragActive) {
|
if (!wasDragActive) {
|
||||||
cancelAnimations();
|
cancelAnimations();
|
||||||
snapToNearest();
|
snapToNearest();
|
||||||
|
|
||||||
@@ -1205,7 +1203,7 @@ void CarouselView::mouseReleaseEvent(QMouseEvent* event) {
|
|||||||
|
|
||||||
m_dragActive = false;
|
m_dragActive = false;
|
||||||
|
|
||||||
qreal v = qBound(-kMaxFlickVelocity, m_velocity, kMaxFlickVelocity);
|
qreal v = qBound(-kMaxFlickVelocity, sampledVelocity(), kMaxFlickVelocity);
|
||||||
|
|
||||||
if (std::abs(v) < kMinFlickVelocity) {
|
if (std::abs(v) < kMinFlickVelocity) {
|
||||||
snapToNearest();
|
snapToNearest();
|
||||||
@@ -1215,24 +1213,17 @@ void CarouselView::mouseReleaseEvent(QMouseEvent* event) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const qreal duration = std::abs(v) / (kFlickFriction * 1000.0);
|
const qreal duration = std::abs(v) / (kFlickFriction * 1000.0);
|
||||||
|
|
||||||
const qreal distance = (v * (duration / 1000.0)) / 2.0;
|
const qreal distance = (v * (duration / 1000.0)) / 2.0;
|
||||||
|
|
||||||
const qreal rawDest = m_contentX + distance;
|
const qreal rawDest = m_contentX + distance;
|
||||||
|
|
||||||
const qreal dest = contentXForIndex(indexForContentX(rawDest));
|
const qreal dest = contentXForIndex(indexForContentX(rawDest));
|
||||||
|
|
||||||
cancelAnimations();
|
cancelAnimations();
|
||||||
|
|
||||||
m_flickAnim->setDuration(
|
m_flickAnim->setDuration(
|
||||||
static_cast<int>(qBound<qreal>(120, duration, 900)));
|
static_cast<int>(qBound<qreal>(120, duration, 900)));
|
||||||
|
m_flickAnim->setEasingCurve(QEasingCurve::OutQuad);
|
||||||
m_flickAnim->setEasingCurve(QEasingCurve::OutCubic);
|
|
||||||
|
|
||||||
m_flickAnim->setStartValue(m_contentX);
|
m_flickAnim->setStartValue(m_contentX);
|
||||||
|
|
||||||
m_flickAnim->setEndValue(dest);
|
m_flickAnim->setEndValue(dest);
|
||||||
|
|
||||||
m_flickAnim->start();
|
m_flickAnim->start();
|
||||||
|
|
||||||
event->accept();
|
event->accept();
|
||||||
|
|||||||
@@ -10,6 +10,8 @@
|
|||||||
#include <QVariantAnimation>
|
#include <QVariantAnimation>
|
||||||
#include <QVariantList>
|
#include <QVariantList>
|
||||||
#include <QVector>
|
#include <QVector>
|
||||||
|
#include <qtypes.h>
|
||||||
|
#include <qvectornd.h>
|
||||||
|
|
||||||
namespace ZShell::components {
|
namespace ZShell::components {
|
||||||
|
|
||||||
@@ -150,6 +152,11 @@ class CarouselView : public QQuickItem {
|
|||||||
bool active = false;
|
bool active = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct VelocitySample {
|
||||||
|
qint64 t;
|
||||||
|
qreal x;
|
||||||
|
};
|
||||||
|
|
||||||
void rebuildArrangement();
|
void rebuildArrangement();
|
||||||
void relayout();
|
void relayout();
|
||||||
|
|
||||||
@@ -190,6 +197,9 @@ class CarouselView : public QQuickItem {
|
|||||||
QQuickItem* acquireItem();
|
QQuickItem* acquireItem();
|
||||||
void releaseAllItems();
|
void releaseAllItems();
|
||||||
|
|
||||||
|
void addVelocitySample(qint64 t, qreal x);
|
||||||
|
qreal sampledVelocity() const;
|
||||||
|
|
||||||
QQmlComponent* m_delegate = nullptr;
|
QQmlComponent* m_delegate = nullptr;
|
||||||
QVariantList m_model;
|
QVariantList m_model;
|
||||||
QVariantMap m_delegateProperties;
|
QVariantMap m_delegateProperties;
|
||||||
@@ -226,9 +236,9 @@ class CarouselView : public QQuickItem {
|
|||||||
qreal m_pressContentX = 0;
|
qreal m_pressContentX = 0;
|
||||||
|
|
||||||
QElapsedTimer m_dragTimer;
|
QElapsedTimer m_dragTimer;
|
||||||
qreal m_lastMoveX = 0;
|
|
||||||
qint64 m_lastMoveT = 0;
|
QVector<VelocitySample> m_velocitySamples;
|
||||||
qreal m_velocity = 0;
|
static constexpr qint64 kVelocitySampleWindowMs = 80;
|
||||||
|
|
||||||
QVariantAnimation* m_flickAnim = nullptr;
|
QVariantAnimation* m_flickAnim = nullptr;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user