55 } |
57 } |
56 private: |
58 private: |
57 QVector3D mValue; |
59 QVector3D mValue; |
58 }; |
60 }; |
59 |
61 |
|
62 class MyQuaternionAnimation : public QVariantAnimation |
|
63 { |
|
64 public: |
|
65 virtual void updateCurrentValue(const QVariant& value) |
|
66 { |
|
67 mValue = value.value<QQuaternion>(); |
|
68 } |
|
69 QQuaternion getValue() const |
|
70 { |
|
71 return mValue; |
|
72 } |
|
73 private: |
|
74 QQuaternion mValue; |
|
75 }; |
|
76 |
|
77 |
60 class HgAnimatedQuad |
78 class HgAnimatedQuad |
61 { |
79 { |
62 public: |
80 public: |
63 |
81 |
64 HgAnimatedQuad(HgQuad* start, HgQuad* end, |
82 static HgAnimatedQuad* createScrollDirectionChangeAnimation( |
65 int duration) : mQuad(start) |
83 HgQuad* a, HgQuad* b, const QMatrix4x4& tm, const QMatrix4x4& rm, |
66 { |
84 const QQuaternion& rot, Qt::Orientation orientation, |
67 mPositionAnimation.setDuration(duration); |
85 int duration) |
68 mPositionAnimation.setKeyValueAt(0, start->position()); |
86 { |
69 mPositionAnimation.setKeyValueAt(1.0, end->position()); |
87 HgAnimatedQuad* q = new HgAnimatedQuad(); |
70 mPositionAnimation.setEasingCurve(QEasingCurve::Linear); |
88 q->mQuad = a; |
71 |
89 |
72 mScaleAnimation.setDuration(duration); |
90 q->mPosition.setEasingCurve(QEasingCurve::InOutCubic); |
73 mScaleAnimation.setKeyValueAt(0, QVector3D(start->scale().x(), start->scale().y(), 0)); |
91 q->mPosition.setDuration(duration); |
74 mScaleAnimation.setKeyValueAt(1, QVector3D(end->scale().x(), end->scale().y(), 0)); |
92 QVector3D pos = tm * (a->position() * rm); |
75 mScaleAnimation.setEasingCurve(QEasingCurve::Linear); |
93 q->mPosition.setKeyValueAt(0, pos); |
76 |
94 |
77 } |
95 QVector3D pos2; |
78 |
96 |
79 ~HgAnimatedQuad() |
97 if (orientation == Qt::Horizontal) |
80 { |
98 { |
81 } |
99 pos2 = QVector3D(pos.x(), 0, pos.z() + (pos.y() > b->position().y() ? -0.5f : -0.5f)); |
82 |
100 } |
|
101 else |
|
102 { |
|
103 pos2 = QVector3D(0, pos.y(), pos.z() + (pos.x() > b->position().x() ? -0.5f : -0.5f)); |
|
104 } |
|
105 |
|
106 q->mPosition.setKeyValueAt(0.5f, pos2); |
|
107 q->mPosition.setKeyValueAt(1, b->position()); |
|
108 |
|
109 q->mRotation.setEasingCurve(QEasingCurve::InOutCubic); |
|
110 q->mRotation.setDuration(duration); |
|
111 q->mRotation.setKeyValueAt(0, rot); |
|
112 q->mRotation.setKeyValueAt(0.5f, QQuaternion::fromAxisAndAngle(QVector3D(1,1,0), 180)); |
|
113 q->mRotation.setKeyValueAt(1, b->rotation()); |
|
114 |
|
115 return q; |
|
116 } |
|
117 |
|
118 static HgAnimatedQuad* createBasicAnimation(HgQuad* a, HgQuad* b, int duration) |
|
119 { |
|
120 HgAnimatedQuad* q = new HgAnimatedQuad(); |
|
121 q->mQuad = a; |
|
122 |
|
123 q->mPosition.setDuration(duration); |
|
124 q->mPosition.setKeyValueAt(0, a->position()); |
|
125 q->mPosition.setKeyValueAt(1, b->position()); |
|
126 |
|
127 q->mRotation.setDuration(duration); |
|
128 q->mRotation.setKeyValueAt(0, a->rotation()); |
|
129 q->mRotation.setKeyValueAt(1, b->rotation()); |
|
130 |
|
131 return q; |
|
132 } |
|
133 |
83 void start() |
134 void start() |
84 { |
135 { |
85 mPositionAnimation.start(); |
136 mPosition.start(); |
86 mScaleAnimation.start(); |
137 mRotation.start(); |
87 } |
138 } |
88 |
139 |
89 void update() |
140 void update() |
90 { |
141 { |
91 mQuad->setPosition(mPositionAnimation.currentValue().value<QVector3D>()); |
142 mQuad->setPosition(mPosition.currentValue().value<QVector3D>()); |
92 QVector3D scale = mScaleAnimation.currentValue().value<QVector3D>(); |
143 mQuad->setRotation(mRotation.currentValue().value<QQuaternion>()); |
93 mQuad->setScale(QVector2D(scale.x(), scale.y())); |
144 } |
94 } |
145 |
95 |
146 const HgQuad* quad() const |
|
147 { |
|
148 return mQuad; |
|
149 } |
|
150 |
|
151 private: |
96 HgQuad* mQuad; |
152 HgQuad* mQuad; |
97 MyVectorAnimation mPositionAnimation; |
153 MyVectorAnimation mPosition; |
98 MyVectorAnimation mScaleAnimation; |
154 //MyVectorAnimation mScale; |
|
155 MyQuaternionAnimation mRotation; |
|
156 |
99 }; |
157 }; |
100 |
158 |
|
159 class HgAnimatedQuadFactory |
|
160 { |
|
161 public: |
|
162 virtual HgAnimatedQuad* createQuad(HgQuad* qA, HgQuad* qB) const=0; |
|
163 }; |
|
164 |
|
165 class HgScrollDirChangeQuadFactory : public HgAnimatedQuadFactory |
|
166 { |
|
167 public: |
|
168 void setup(Qt::Orientation nextScrollDirection, |
|
169 const QRectF& rect, const QSizeF& spacing, const QSizeF& size, |
|
170 int duration) |
|
171 { |
|
172 mNextScrollDirection = nextScrollDirection; |
|
173 mDuration = duration; |
|
174 |
|
175 if (mNextScrollDirection == Qt::Horizontal) |
|
176 { |
|
177 qreal stepY = spacing.height() + size.height(); |
|
178 qreal posY = 0.5f - (rect.height() / rect.width() / 2.0 - stepY / 2.0); |
|
179 tm.translate(-posY,0); |
|
180 rm.rotate(-90, QVector3D(0,0,1)); |
|
181 rot = QQuaternion::fromAxisAndAngle(QVector3D(0,0,1), -90); |
|
182 } |
|
183 else if (mNextScrollDirection == Qt::Vertical) |
|
184 { |
|
185 tm.translate(0,0.5f); |
|
186 rm.rotate(90, QVector3D(0,0,1)); |
|
187 rot = QQuaternion::fromAxisAndAngle(QVector3D(0,0,1), -90); |
|
188 } |
|
189 |
|
190 |
|
191 } |
|
192 |
|
193 HgAnimatedQuad* createQuad(HgQuad* qA, HgQuad* qB) const |
|
194 { |
|
195 return HgAnimatedQuad::createScrollDirectionChangeAnimation(qA, qB, |
|
196 tm, rm, rot, mNextScrollDirection, mDuration); |
|
197 } |
|
198 private: |
|
199 QMatrix4x4 tm; |
|
200 QMatrix4x4 rm; |
|
201 QQuaternion rot; |
|
202 Qt::Orientation mNextScrollDirection; |
|
203 int mDuration; |
|
204 }; |
|
205 |
|
206 class HgRowCountChangeQuadFactory : public HgAnimatedQuadFactory |
|
207 { |
|
208 public: |
|
209 HgRowCountChangeQuadFactory(int duration) : mDuration(duration) |
|
210 { |
|
211 |
|
212 } |
|
213 |
|
214 HgAnimatedQuad* createQuad(HgQuad* qA, HgQuad* qB) const |
|
215 { |
|
216 return HgAnimatedQuad::createBasicAnimation(qA, qB, mDuration); |
|
217 } |
|
218 private: |
|
219 int mDuration; |
|
220 }; |
|
221 |
|
222 |
101 HgMediaWallRenderer::HgMediaWallRenderer(HgMediaWallDataProvider* provider, |
223 HgMediaWallRenderer::HgMediaWallRenderer(HgMediaWallDataProvider* provider, |
102 Qt::Orientation scrollDirection, bool coverflowMode) : |
224 Qt::Orientation orientation, Qt::Orientation scrollDirection, bool coverflowMode) : |
103 mDataProvider(provider), |
225 mDataProvider(provider), |
104 mRenderer(NULL), |
226 mRenderer(NULL), |
105 mIndicatorRenderer(NULL), |
227 mIndicatorRenderer(NULL), |
106 mRendererInitialized(false), |
228 mRendererInitialized(false), |
107 mOrientation(scrollDirection), |
229 mScrollDirection(scrollDirection), |
108 mNextOrientation(scrollDirection), |
230 mNextScrollDirection(scrollDirection), |
|
231 mOrientation(orientation), |
109 mStateAnimationAlpha(0), |
232 mStateAnimationAlpha(0), |
110 mStateAnimationOnGoing(false), |
233 mStateAnimationOnGoing(false), |
111 mAnimationAlpha(0), |
234 mAnimationAlpha(0), |
112 mOpeningAnimationDuration(500), |
|
113 mOpenedItem(-1), |
|
114 mFlipAngle(qreal(360)), |
|
115 mZoomAmount(qreal(0.5)), |
|
116 mCoverflowMode(coverflowMode), |
235 mCoverflowMode(coverflowMode), |
117 mRowCount(1), |
236 mRowCount(1), |
118 mNextRowCount(1), |
237 mNextRowCount(1), |
119 mStateAnimationDuration(300), |
238 mStateAnimationDuration(500), |
120 mStep(1.1), |
239 mStep(1.1), |
121 mZfar(-2), |
240 mZfar(-2), |
122 mSpacing2D(10,10), |
241 mSpacing2D(10,10), |
123 mImageSize2D(100, 60), |
242 mImageSize2D(100, 60), |
124 mCameraDistance(0), |
243 mCameraDistance(0), |
125 mCameraRotationY(0), |
244 mCameraRotationY(0), |
126 mCameraRotationZ(0), |
245 mCameraRotationZ(0), |
127 mFrontCoverElevation(0.4), |
246 mFrontCoverElevation(0.4), |
128 mReflectionsEnabled(true), |
247 mFrontItemPosition(0,0) |
129 mItemCountChanged(false), |
|
130 mOpenedItemState(ItemClosed), |
|
131 mFrontItemPosition(0,0), |
|
132 mFrontItemPositionSet(false) |
|
133 { |
248 { |
134 createStateMachine(); |
249 createStateMachine(); |
135 mImageFader = new HgImageFader(); |
250 mRenderer = new HgQtQuadRenderer(64); |
136 mRenderer = new HgVgQuadRenderer(256); |
251 mRenderer->enableReflections(true); |
137 mRendererInitialized = true; |
252 mRendererInitialized = true; |
138 if (mCoverflowMode) { |
253 if (mCoverflowMode) { |
139 mOrientation = Qt::Horizontal; |
254 mScrollDirection = Qt::Horizontal; |
140 mNextOrientation = mOrientation; |
255 mNextScrollDirection = mScrollDirection; |
141 } |
256 } |
142 } |
257 } |
143 |
258 |
144 HgMediaWallRenderer::~HgMediaWallRenderer() |
259 HgMediaWallRenderer::~HgMediaWallRenderer() |
145 { |
260 { |
146 delete mRenderer; |
261 delete mRenderer; |
147 delete mImageFader; |
|
148 delete mStateMachine; |
262 delete mStateMachine; |
149 } |
263 } |
150 |
264 |
151 |
265 |
152 void HgMediaWallRenderer::setCameraDistance(qreal distance) |
266 void HgMediaWallRenderer::setCameraDistance(qreal distance) |
182 void HgMediaWallRenderer::draw( |
296 void HgMediaWallRenderer::draw( |
183 const QPointF& startPosition, |
297 const QPointF& startPosition, |
184 const QPointF& position, |
298 const QPointF& position, |
185 const QPointF& targetPosition, |
299 const QPointF& targetPosition, |
186 qreal springVelocity, |
300 qreal springVelocity, |
187 QPainter* painter) |
301 QPainter* painter, |
188 { |
302 const QTransform& sceneTransform, |
|
303 const QRectF& rect) |
|
304 { |
|
305 // save new rect |
|
306 mRect = rect; |
|
307 |
189 // if still not initialized we cant draw anything |
308 // if still not initialized we cant draw anything |
190 if (!mRendererInitialized) |
309 if (!mRendererInitialized) |
191 return; |
310 return; |
192 |
311 |
193 if (mOrientation != mNextOrientation || |
312 if (mScrollDirection != mNextScrollDirection) |
194 mRowCount != mNextRowCount) |
313 { |
195 { |
314 startScrollDirectionChangeAnimation(startPosition, position, |
196 |
315 targetPosition, springVelocity, painter, sceneTransform, |
197 // save old state of the quads |
316 rect); |
198 recordState(mOldState); |
317 } |
199 |
318 else if (mRowCount != mNextRowCount) |
200 // goto wanted orientation / rowcount |
319 { |
201 mOrientation = mNextOrientation; |
320 startRowCountChangeAnimation(startPosition, position, |
202 mRowCount = mNextRowCount; |
321 targetPosition, springVelocity, painter, sceneTransform, |
203 setImageSize(mNextImageSize); |
322 rect); |
204 |
|
205 // setup quads to new state |
|
206 setupRows(startPosition, position, targetPosition, springVelocity, painter); |
|
207 |
|
208 // record state for animation |
|
209 recordState(mNextState); |
|
210 |
|
211 startStateAnimation(painter); |
|
212 } |
323 } |
213 else |
324 else |
214 { |
325 { |
215 if (!mStateAnimationOnGoing) |
326 if (!mStateAnimationOnGoing) |
216 { |
327 { |
308 { |
398 { |
309 mStateMachine = new QStateMachine(this); |
399 mStateMachine = new QStateMachine(this); |
310 mStateMachine->setAnimated(true); |
400 mStateMachine->setAnimated(true); |
311 |
401 |
312 QState* root = new QState(QState::ParallelStates); |
402 QState* root = new QState(QState::ParallelStates); |
313 QState* p1 = new QState(root); |
|
314 QState* p2 = new QState(root); |
403 QState* p2 = new QState(root); |
315 |
404 |
316 // create idle/opened states |
|
317 { |
|
318 QState* idle = new QState(p1); |
|
319 QState* opened = new QState(p1); |
|
320 |
|
321 idle->assignProperty(this, "animationAlpha", qreal(0)); |
|
322 opened->assignProperty(this, "animationAlpha", qreal(1)); |
|
323 |
|
324 // add opening animation |
|
325 QPropertyAnimation* anim1 = new QPropertyAnimation(this, "animationAlpha"); |
|
326 anim1->setDuration(mOpeningAnimationDuration); |
|
327 idle->addTransition(this, SIGNAL(toggleItem()), opened)->addAnimation(anim1); |
|
328 |
|
329 // add closing animation |
|
330 QPropertyAnimation* anim2 = new QPropertyAnimation(this, "animationAlpha"); |
|
331 anim2->setDuration(mOpeningAnimationDuration); |
|
332 opened->addTransition(this, SIGNAL(toggleItem()), idle)->addAnimation(anim2); |
|
333 |
|
334 QObject::connect(idle, SIGNAL(entered()), this, SLOT(onIdleState())); |
|
335 QObject::connect(opened, SIGNAL(entered()), this, SLOT(onOpenedState())); |
|
336 |
|
337 p1->setInitialState(idle); |
|
338 } |
|
339 |
|
340 // create two states to animate between |
405 // create two states to animate between |
341 { |
406 { |
342 QState* s1 = new QState(p2); |
407 QState* s1 = new QState(p2); |
343 QState* s2 = new QState(p2); |
408 QState* s2 = new QState(p2); |
344 |
409 |
354 s2->addTransition(this, SIGNAL(toggleState()), s1)->addAnimation(anim); |
419 s2->addTransition(this, SIGNAL(toggleState()), s1)->addAnimation(anim); |
355 |
420 |
356 p2->setInitialState(s1); |
421 p2->setInitialState(s1); |
357 } |
422 } |
358 |
423 |
359 root->setInitialState(p1); |
424 root->setInitialState(p2); |
360 mStateMachine->addState(root); |
425 mStateMachine->addState(root); |
361 mStateMachine->setInitialState(root); |
426 mStateMachine->setInitialState(root); |
362 mStateMachine->start(); |
427 mStateMachine->start(); |
363 |
428 |
364 } |
429 } |
365 |
430 |
366 void HgMediaWallRenderer::onIdleState() |
431 void HgMediaWallRenderer::setScrollDirection(Qt::Orientation scrollDirection, bool animate) |
367 { |
|
368 emit itemClosed(mOpenedItem); |
|
369 } |
|
370 |
|
371 void HgMediaWallRenderer::onOpenedState() |
|
372 { |
|
373 emit itemOpened(mOpenedItem); |
|
374 } |
|
375 |
|
376 void HgMediaWallRenderer::setOrientation(Qt::Orientation orientation, bool animate) |
|
377 { |
432 { |
378 // coverflow is always horizontal |
433 // coverflow is always horizontal |
379 if (mCoverflowMode) |
434 if (mCoverflowMode) |
380 { |
435 { |
381 mOrientation = Qt::Horizontal; |
436 mScrollDirection = Qt::Horizontal; |
382 mNextOrientation = mOrientation; |
437 mNextScrollDirection = mScrollDirection; |
383 return; |
438 return; |
384 } |
439 } |
385 |
440 |
386 if (mOrientation != orientation) |
441 if (mScrollDirection != scrollDirection) |
387 { |
442 { |
388 mStateMachine->setAnimated(animate); |
443 mStateMachine->setAnimated(animate); |
389 mNextOrientation = orientation; |
444 mNextScrollDirection = scrollDirection; |
390 |
445 |
391 if (!animate) |
446 if (!animate) |
392 mOrientation = orientation; |
447 mScrollDirection = scrollDirection; |
393 else |
448 else |
394 { |
449 { |
395 emit renderingNeeded(); |
450 //emit renderingNeeded(); |
396 } |
451 } |
397 } |
452 } |
398 } |
453 } |
399 |
454 |
400 Qt::Orientation HgMediaWallRenderer::getOrientation() const |
455 Qt::Orientation HgMediaWallRenderer::getScrollDirection() const |
401 { |
456 { |
402 return mOrientation; |
457 return mScrollDirection; |
403 } |
458 } |
404 |
459 |
405 void HgMediaWallRenderer::drawQuads(QPainter* painter) |
460 void HgMediaWallRenderer::drawQuads(QPainter* painter, |
406 { |
461 const QTransform& sceneTransform) |
407 |
462 { |
408 mRenderer->transformQuads(mViewMatrix, mProjMatrix, mRect); |
463 mRenderer->drawQuads(painter, mRect, mViewMatrix, mProjMatrix, mOrientation, |
409 |
464 sceneTransform); |
410 mRenderer->drawQuads(mRect, painter); |
|
411 } |
465 } |
412 |
466 |
413 |
467 |
414 void HgMediaWallRenderer::enableCoverflowMode(bool enabled) |
468 void HgMediaWallRenderer::enableCoverflowMode(bool enabled) |
415 { |
469 { |
521 |
563 |
522 view.lookAt(QVector3D(0.0, 0.0, 1.0f + mCameraDistance), |
564 view.lookAt(QVector3D(0.0, 0.0, 1.0f + mCameraDistance), |
523 QVector3D(0.0f, 0.0f, 0.0f), QVector3D(0.0f, 1.0f, 0.0f)); |
565 QVector3D(0.0f, 0.0f, 0.0f), QVector3D(0.0f, 1.0f, 0.0f)); |
524 |
566 |
525 QMatrix4x4 rot; |
567 QMatrix4x4 rot; |
526 rot.rotate(mCameraRotationZ, QVector3D(0,0,1)); |
568 //rot.rotate(mCameraRotationZ, QVector3D(0,0,1)); |
527 rot.rotate(mCameraRotationY, QVector3D(0,1,0)); |
569 rot.rotate(mCameraRotationY, QVector3D(0,1,0)); |
528 view *= rot; |
570 view *= rot; |
529 |
571 |
530 qreal aspect = mRect.width() / mRect.height(); |
|
531 |
|
532 QMatrix4x4 proj; |
572 QMatrix4x4 proj; |
533 proj.setToIdentity(); |
573 proj.setToIdentity(); |
534 |
574 |
535 if (mRect.width() <= mRect.height()) |
575 // setup projection matrix so that width of the item wichi has the |
536 { |
576 // width of the screen has width of 1 in 3D space |
537 qreal aspect = mRect.height() / mRect.width(); |
577 qreal aspect = mRect.height() / mRect.width(); |
538 proj.frustum(-0.5f, 0.5f, -0.5f*aspect, 0.5f*aspect, 1.0f, 1000.0f); |
578 proj.frustum(-0.5f, 0.5f, -0.5f * aspect, 0.5f * aspect, 1.0f, 1000.0f); |
539 } |
579 |
540 else |
|
541 { |
|
542 qreal aspect = mRect.width() / mRect.height(); |
|
543 proj.frustum(-0.5f*aspect, 0.5f*aspect, -0.5f, 0.5f, 1.0f, 1000.0f); |
|
544 } |
|
545 |
|
546 mViewMatrix = view; |
580 mViewMatrix = view; |
547 mProjMatrix = proj; |
581 mProjMatrix = proj; |
548 |
582 |
549 qreal mirrorPlaneY; |
583 qreal mirrorPlaneY; |
550 if (mCoverflowMode) |
584 if (mCoverflowMode) |
635 { |
643 { |
636 qreal step = -(mSpacing3D.width() + mImageSize3D.width()); |
644 qreal step = -(mSpacing3D.width() + mImageSize3D.width()); |
637 return mColumnCount == 1 ? qreal(0) : (((qreal)mColumnCount/qreal(2)-qreal(0.5)) - (qreal)col) * step; |
645 return mColumnCount == 1 ? qreal(0) : (((qreal)mColumnCount/qreal(2)-qreal(0.5)) - (qreal)col) * step; |
638 } |
646 } |
639 |
647 |
640 |
|
641 void HgMediaWallRenderer::enableReflections(bool enabled) |
648 void HgMediaWallRenderer::enableReflections(bool enabled) |
642 { |
649 { |
643 mReflectionsEnabled = enabled; |
650 mRenderer->enableReflections(enabled); |
644 } |
651 } |
645 |
652 |
646 bool HgMediaWallRenderer::reflectionsEnabled() const |
653 bool HgMediaWallRenderer::reflectionsEnabled() const |
647 { |
654 { |
648 return mReflectionsEnabled; |
655 return mRenderer->reflectionsEnabled(); |
649 } |
656 } |
650 |
657 |
651 QPointF HgMediaWallRenderer::mapFromWindow(const QPointF& point) const |
|
652 { |
|
653 return QPointF(point.x(), mRect.height() - point.y()); |
|
654 } |
|
655 |
|
656 void HgMediaWallRenderer::emitUpdate() |
|
657 { |
|
658 emit renderingNeeded(); |
|
659 } |
|
660 |
|
661 void HgMediaWallRenderer::applyOpeningAnimation(HgQuad* quad) |
|
662 { |
|
663 QQuaternion rot(0,0,0,1); |
|
664 qreal rotAngle = mAnimationAlpha * mFlipAngle; |
|
665 rot = QQuaternion::fromAxisAndAngle(QVector3D(0,1,0), rotAngle); |
|
666 quad->setRotation(rot); |
|
667 quad->setPosition(quad->position() + QVector3D(0,0,mAnimationAlpha * mZoomAmount)); |
|
668 } |
|
669 |
|
670 |
|
671 qreal HgMediaWallRenderer::getWorldWidth() const |
658 qreal HgMediaWallRenderer::getWorldWidth() const |
672 { |
659 { |
673 qreal width = ceil((qreal)mDataProvider->imageCount() / (qreal)mRowCount - 1.0f); |
660 qreal width = ceil((qreal)mDataProvider->imageCount() / (qreal)mRowCount - 1.0f); |
674 |
661 |
675 // if we are in vertical orientation we want last and first item |
662 // if we are in vertical orientation we want last and first item |
676 // to place at the top and bottom of the screen instead of center |
663 // to place at the top and bottom of the screen instead of center |
677 if (mOrientation == Qt::Vertical) |
664 if (mScrollDirection == Qt::Vertical) |
678 { |
665 { |
679 qreal step = mSpacing2D.height() + mImageSize2D.height(); |
666 qreal step = mSpacing2D.height() + mImageSize2D.height(); |
680 width -= (mRect.height() / step - 1.0f); |
667 width -= (mRect.height() / step - 1.0f); |
681 } |
668 } |
|
669 else if (mScrollDirection == Qt::Horizontal && !mCoverflowMode) |
|
670 { |
|
671 qreal step = mSpacing2D.width() + mImageSize2D.width(); |
|
672 width -= (mRect.width() / step - 1.0f); |
|
673 } |
682 |
674 |
683 return width; |
675 return width; |
684 } |
676 } |
685 |
677 |
686 void HgMediaWallRenderer::beginRemoveRows(int start, int end) |
678 |
687 { |
679 void HgMediaWallRenderer::createAnimatedQuads(const HgAnimatedQuadFactory& factory) |
688 mRemoveStart = start; |
680 { |
689 mRemoveEnd = end; |
|
690 mItemCountChanged = true; |
|
691 |
|
692 recordState(mOldState); |
|
693 |
|
694 } |
|
695 |
|
696 void HgMediaWallRenderer::endRemoveRows() |
|
697 { |
|
698 |
|
699 mStateMachine->setAnimated(true); |
|
700 |
|
701 emit renderingNeeded(); |
|
702 |
|
703 } |
|
704 |
|
705 void HgMediaWallRenderer::startStateAnimation(QPainter* painter) |
|
706 { |
|
707 |
|
708 // clear previous animation quads |
681 // clear previous animation quads |
709 for (int i = 0; i < mAnimatedQuads.size(); i++) |
682 qDeleteAll(mAnimatedQuads.begin(), mAnimatedQuads.end()); |
710 { |
|
711 delete mAnimatedQuads[i]; |
|
712 } |
|
713 mAnimatedQuads.clear(); |
683 mAnimatedQuads.clear(); |
714 |
684 |
715 // setup animated quads |
685 // default quad is used if no counterpart for the current quad exits. |
716 HgQuad* defaultQuad = new HgQuad(); |
686 HgQuad* defaultQuad = new HgQuad(); |
717 defaultQuad->setPosition(QVector3D(100,100,-100)); |
687 defaultQuad->setPosition(QVector3D(100,100,-100)); |
718 int n = mOldState.mQuads.count() < mNextState.mQuads.count() ? mNextState.mQuads.count() : mOldState.mQuads.count(); |
688 |
719 for (int i = 0; i < n; i++) |
689 // setup new animated quads |
720 { |
690 QMap<int, HgQuad*>::iterator i = mNextState.mQuads.begin(); |
721 HgQuad* qA = (i >= mOldState.mQuads.count()) ? defaultQuad : mOldState.mQuads[i]; |
691 while(i != mNextState.mQuads.end()) |
722 HgQuad* qB = (i >= mNextState.mQuads.count()) ? defaultQuad : mNextState.mQuads[i]; |
692 { |
723 |
693 HgQuad* qB = i.value(); |
724 HgAnimatedQuad* q = new HgAnimatedQuad(qA, qB, mStateAnimationDuration); |
694 HgQuad* qA = NULL; |
|
695 QMap<int, HgQuad*>::iterator j = mOldState.mQuads.find(i.key()); |
|
696 if (j != mOldState.mQuads.end()) |
|
697 { |
|
698 qA = j.value(); |
|
699 } |
|
700 else |
|
701 { |
|
702 qA = defaultQuad->copy(); |
|
703 } |
|
704 |
|
705 HgAnimatedQuad* q = factory.createQuad(qA, qB); |
725 mAnimatedQuads.append(q); |
706 mAnimatedQuads.append(q); |
|
707 |
726 q->start(); |
708 q->start(); |
727 } |
709 i++; |
728 |
710 } |
|
711 } |
|
712 |
|
713 void HgMediaWallRenderer::startScrollDirectionChangeAnimation( |
|
714 const QPointF& startPosition, |
|
715 const QPointF& position, |
|
716 const QPointF& targetPosition, |
|
717 qreal springVelocity, |
|
718 QPainter* painter, |
|
719 const QTransform& sceneTransform, |
|
720 const QRectF& rect) |
|
721 { |
|
722 |
|
723 // save state for current orientation |
|
724 setupRows(startPosition, position, targetPosition, springVelocity, painter); |
|
725 recordState(mOldState); |
|
726 |
|
727 // goto wanted orientation |
|
728 mScrollDirection = mNextScrollDirection; |
|
729 |
|
730 // setup quads to new state |
|
731 setupRows(startPosition, position, targetPosition, springVelocity, painter); |
|
732 |
|
733 // record state for animation |
|
734 recordState(mNextState); |
|
735 |
|
736 HgScrollDirChangeQuadFactory factory; |
|
737 factory.setup(mNextScrollDirection, mRect, mSpacing3D, mImageSize3D, mStateAnimationDuration); |
|
738 |
|
739 createAnimatedQuads(factory); |
|
740 |
729 mStateAnimationOnGoing = true; |
741 mStateAnimationOnGoing = true; |
730 |
742 |
731 // setup first frame of the animation |
743 // setup first frame of the animation |
732 setupStateAnimation(painter); |
744 setupStateAnimation(painter); |
733 |
745 |
734 // toggle state animation on |
746 // toggle state animation on |
735 toggleState(); |
747 toggleState(); |
736 |
748 |
|
749 } |
|
750 |
|
751 void HgMediaWallRenderer::startRowCountChangeAnimation( |
|
752 const QPointF& startPosition, |
|
753 const QPointF& position, |
|
754 const QPointF& targetPosition, |
|
755 qreal springVelocity, |
|
756 QPainter* painter, |
|
757 const QTransform& sceneTransform, |
|
758 const QRectF& rect) |
|
759 { |
|
760 setupRows(startPosition, position, targetPosition, springVelocity, painter); |
|
761 recordState(mOldState); |
|
762 |
|
763 mRowCount = mNextRowCount; |
|
764 setImageSize(mNextImageSize); |
|
765 |
|
766 setupRows(startPosition, position, targetPosition, springVelocity, painter); |
|
767 recordState(mNextState); |
|
768 |
|
769 HgRowCountChangeQuadFactory factory(mStateAnimationDuration); |
|
770 |
|
771 createAnimatedQuads(factory); |
|
772 |
|
773 mStateAnimationOnGoing = true; |
|
774 |
|
775 // setup first frame of the animation |
|
776 setupStateAnimation(painter); |
|
777 |
|
778 // toggle state animation on |
|
779 toggleState(); |
737 } |
780 } |
738 |
781 |
739 void HgMediaWallRenderer::setupCoverflow(const QPointF& startPosition, |
782 void HgMediaWallRenderer::setupCoverflow(const QPointF& startPosition, |
740 const QPointF& position, |
783 const QPointF& position, |
741 const QPointF& targetPosition, |
784 const QPointF& targetPosition, |
896 |
936 |
897 setupGridColumn(posX, itemIndex, quadIndex); |
937 setupGridColumn(posX, itemIndex, quadIndex); |
898 |
938 |
899 posX += stepX; |
939 posX += stepX; |
900 col++; |
940 col++; |
901 itemIndex+=mRowCount; |
941 } |
902 } |
942 } |
903 } |
943 |
904 |
944 void HgMediaWallRenderer::setupGridColumn(qreal posX, int& itemIndex, int& quadIndex) |
905 void HgMediaWallRenderer::setupGridColumn(qreal posX, int itemIndex, int& quadIndex) |
|
906 { |
945 { |
907 for (int i = 0; i < mRowCount; i++) |
946 for (int i = 0; i < mRowCount; i++) |
908 { |
947 { |
|
948 if (quadIndex >= mRenderer->quadCount() || itemIndex >= mDataProvider->imageCount()) |
|
949 return; |
|
950 |
909 qreal posY = getRowPosY(i); |
951 qreal posY = getRowPosY(i); |
910 |
952 |
911 // enable reflections for the last row needed |
953 // enable reflections for the last row needed |
912 bool reflections = (i == (mRowCount-1) && mReflectionsEnabled); |
954 bool reflections = (i == (mRowCount-1) && reflectionsEnabled()); |
913 |
955 |
914 setupDefaultQuad(QVector3D(posX, posY, 0), itemIndex++, reflections, quadIndex); |
956 setupDefaultQuad(QVector3D(posX, posY, 0), itemIndex++, reflections, quadIndex); |
915 |
957 |
916 if (itemIndex >= mDataProvider->imageCount()) |
|
917 return; |
|
918 } |
958 } |
919 } |
959 } |
920 |
960 |
921 void HgMediaWallRenderer::setupGridRow(qreal posY, int itemIndex, int& quadIndex) |
961 void HgMediaWallRenderer::setupGridRow(qreal posY, int& itemIndex, int& quadIndex) |
922 { |
962 { |
923 for (int i = 0; i < mColumnCount; i++) |
963 for (int i = 0; i < mColumnCount; i++) |
924 { |
964 { |
|
965 if (quadIndex >= mRenderer->quadCount() || itemIndex >= mDataProvider->imageCount()) |
|
966 return; |
|
967 |
925 qreal posX = getColumnPosX(i); |
968 qreal posX = getColumnPosX(i); |
|
969 |
926 setupDefaultQuad(QVector3D(posX, posY, 0), itemIndex++, false, quadIndex); |
970 setupDefaultQuad(QVector3D(posX, posY, 0), itemIndex++, false, quadIndex); |
927 if (itemIndex >= mDataProvider->imageCount()) |
|
928 return; |
|
929 } |
971 } |
930 } |
972 } |
931 |
973 |
932 void HgMediaWallRenderer::setupDefaultQuad(const QVector3D& pos, int itemIndex, bool reflectionsEnabled, int& quadIndex) |
974 void HgMediaWallRenderer::setupDefaultQuad(const QVector3D& pos, int itemIndex, bool reflectionsEnabled, int& quadIndex) |
933 { |
975 { |