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

This commit is contained in:
2026-08-17 10:37:00 +02:00
parent 31f73b05e4
commit babfe4b3de
3 changed files with 47 additions and 47 deletions
-1
View File
@@ -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];
+34 -43
View File
@@ -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();
+13 -3
View File
@@ -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;