19 #include <QTimer> |
19 #include <QTimer> |
20 #include "trace.h" |
20 #include "trace.h" |
21 |
21 |
22 const int KTimeDelta(10); |
22 const int KTimeDelta(10); |
23 const qreal KTimeDeltaF(0.01f); |
23 const qreal KTimeDeltaF(0.01f); |
24 //const qreal KVelocitySnap(0.05f); |
24 const qreal KVelocitySnap(0.06f); |
25 const qreal KPositionSnap(0.01f); |
25 const qreal KPositionSnap(0.01f); |
26 const int KTimerInterval(10); |
26 const int KTimerInterval(10); |
27 |
27 |
28 HgSpring::HgSpring() : |
28 HgSpring::HgSpring() : |
29 mStartPos(QPointF(0,0)), |
29 mStartPos(QPointF(0,0)), |
30 mPos(QPointF(0,0)), |
30 mPos(QPointF(0,0)), |
31 mEndPos(QPointF(0,0)), |
31 mEndPos(QPointF(0,0)), |
|
32 mEndPosOverListBoundary(QPointF(0,0)), |
32 mVelocity(QPointF(0,0)), |
33 mVelocity(QPointF(0,0)), |
33 mK(30.1), |
34 mK(30.1), |
34 mDamping(10.1), |
35 mDamping(10.1), |
35 mAccumulator(0.0), |
36 mAccumulator(0.0), |
36 mDoNotUpdate(false) |
37 mDoNotUpdate(false), |
|
38 mEndPosOverListEdge(false) |
37 { |
39 { |
38 mTimer = new QTimer(this); |
40 mTimer = new QTimer(this); |
39 |
41 |
40 QObject::connect( mTimer, SIGNAL( timeout() ), this, SLOT( update() ) ); |
42 QObject::connect( mTimer, SIGNAL( timeout() ), this, SLOT( update() ) ); |
41 |
43 |
54 void HgSpring::setDamping(qreal damping) |
56 void HgSpring::setDamping(qreal damping) |
55 { |
57 { |
56 mDamping = damping; |
58 mDamping = damping; |
57 } |
59 } |
58 |
60 |
|
61 qreal HgSpring::k() const |
|
62 { |
|
63 return mK; |
|
64 } |
|
65 |
|
66 qreal HgSpring::damping() const |
|
67 { |
|
68 return mDamping; |
|
69 } |
|
70 |
|
71 // TODO: Remove this function and use only the animateToPosAfterPanning version? |
59 void HgSpring::animateToPos(const QPointF& pos) |
72 void HgSpring::animateToPos(const QPointF& pos) |
60 { |
73 { |
61 mStartPos = mPos; |
74 mStartPos = mPos; |
62 mEndPos = pos; |
75 mEndPos = pos; |
|
76 |
|
77 emit started(); |
|
78 |
|
79 if (!mTimer->isActive()) |
|
80 { |
|
81 mTimer->start(KTimerInterval); |
|
82 mPrevTime.start(); |
|
83 } |
|
84 } |
|
85 |
|
86 void HgSpring::animateToPosAfterPanning(const QPointF& pos, qreal worldWidth) |
|
87 { |
|
88 mWorldWidth = worldWidth; |
|
89 mStartPos = mPos; |
|
90 |
|
91 qreal xPos = pos.x(); |
|
92 if( xPos < 0.0 ) |
|
93 { |
|
94 mEndPosOverListEdge = true; |
|
95 mEndPosOverListBoundary = pos; |
|
96 mEndPos = QPointF(0, 0); |
|
97 } |
|
98 else if( xPos > worldWidth ) |
|
99 { |
|
100 mEndPosOverListEdge = true; |
|
101 mEndPosOverListBoundary = pos; |
|
102 mEndPos = QPointF(worldWidth, 0); |
|
103 } |
|
104 else |
|
105 { |
|
106 mEndPosOverListEdge = false; |
|
107 mEndPos = pos; |
|
108 } |
63 |
109 |
64 emit started(); |
110 emit started(); |
65 |
111 |
66 if (!mTimer->isActive()) |
112 if (!mTimer->isActive()) |
67 { |
113 { |
120 mAccumulator += deltaTime; |
166 mAccumulator += deltaTime; |
121 |
167 |
122 bool stopped = false; |
168 bool stopped = false; |
123 while (mAccumulator >= KTimeDelta) |
169 while (mAccumulator >= KTimeDelta) |
124 { |
170 { |
125 QPointF delta = mEndPos - mPos; |
171 QPointF delta; |
|
172 if(mEndPosOverListEdge) |
|
173 { |
|
174 delta = mEndPosOverListBoundary - mPos; |
|
175 |
|
176 if( mPos.x() < KPositionSnap || mPos.x() > mWorldWidth ) |
|
177 { |
|
178 // When list's position goes past the world boundary |
|
179 // we reset our mEndPosOverListEdge boolean flag |
|
180 // -> the passed boundary will be used as end point, |
|
181 // and the K value of this spring will be modified. |
|
182 mEndPosOverListEdge = false; //reset |
|
183 mEndPosOverListBoundary = QPointF(0,0); //reset |
|
184 mWorldWidth = 0.0; //reset |
|
185 mK = 60.0; |
|
186 } |
|
187 |
|
188 } |
|
189 else |
|
190 { |
|
191 delta = mEndPos - mPos; |
|
192 } |
|
193 |
126 QPointF force = delta * mK - mVelocity * mDamping; |
194 QPointF force = delta * mK - mVelocity * mDamping; |
127 mVelocity += force * KTimeDeltaF; |
195 mVelocity += force * KTimeDeltaF; |
128 mPos += mVelocity * KTimeDeltaF; |
196 mPos += mVelocity * KTimeDeltaF; |
|
197 |
129 if ( (qAbs(mPos.x() - mEndPos.x()) < KPositionSnap && |
198 if ( (qAbs(mPos.x() - mEndPos.x()) < KPositionSnap && |
130 qAbs(mPos.y() - mEndPos.y()) < KPositionSnap) ) |
199 qAbs(mPos.y() - mEndPos.y()) < KPositionSnap) |
|
200 && qAbs(mVelocity.x()) < KVelocitySnap ) |
131 { |
201 { |
132 mPos = mEndPos; |
202 mPos = mEndPos; |
133 mAccumulator = 0; |
203 mAccumulator = 0; |
134 mVelocity = QPointF(0,0); |
204 mVelocity = QPointF(0,0); |
135 mTimer->stop(); |
205 mTimer->stop(); |