diff -r e48454f237ca -r 49c70dcc3f17 ganeswidgets/src/hgmediawallrenderer.cpp --- a/ganeswidgets/src/hgmediawallrenderer.cpp Mon May 03 13:32:54 2010 +0300 +++ b/ganeswidgets/src/hgmediawallrenderer.cpp Fri May 14 16:57:01 2010 +0300 @@ -21,6 +21,7 @@ #include "hgimage.h" #include "HgImageFader.h" #include "hgvgquadrenderer.h" +#include "hgqtquadrenderer.h" #include #include #include @@ -37,6 +38,7 @@ const qreal KPi = 3.1415926535897932384626433832795; + static qreal lerp(qreal start, qreal end, qreal t) { return start * (1.0f - t) + end * t; @@ -57,66 +59,183 @@ QVector3D mValue; }; +class MyQuaternionAnimation : public QVariantAnimation +{ +public: + virtual void updateCurrentValue(const QVariant& value) + { + mValue = value.value(); + } + QQuaternion getValue() const + { + return mValue; + } +private: + QQuaternion mValue; +}; + + class HgAnimatedQuad { public: + + static HgAnimatedQuad* createScrollDirectionChangeAnimation( + HgQuad* a, HgQuad* b, const QMatrix4x4& tm, const QMatrix4x4& rm, + const QQuaternion& rot, Qt::Orientation orientation, + int duration) + { + HgAnimatedQuad* q = new HgAnimatedQuad(); + q->mQuad = a; + + q->mPosition.setEasingCurve(QEasingCurve::InOutCubic); + q->mPosition.setDuration(duration); + QVector3D pos = tm * (a->position() * rm); + q->mPosition.setKeyValueAt(0, pos); + + QVector3D pos2; + + if (orientation == Qt::Horizontal) + { + pos2 = QVector3D(pos.x(), 0, pos.z() + (pos.y() > b->position().y() ? -0.5f : -0.5f)); + } + else + { + pos2 = QVector3D(0, pos.y(), pos.z() + (pos.x() > b->position().x() ? -0.5f : -0.5f)); + } + + q->mPosition.setKeyValueAt(0.5f, pos2); + q->mPosition.setKeyValueAt(1, b->position()); + + q->mRotation.setEasingCurve(QEasingCurve::InOutCubic); + q->mRotation.setDuration(duration); + q->mRotation.setKeyValueAt(0, rot); + q->mRotation.setKeyValueAt(0.5f, QQuaternion::fromAxisAndAngle(QVector3D(1,1,0), 180)); + q->mRotation.setKeyValueAt(1, b->rotation()); - HgAnimatedQuad(HgQuad* start, HgQuad* end, - int duration) : mQuad(start) - { - mPositionAnimation.setDuration(duration); - mPositionAnimation.setKeyValueAt(0, start->position()); - mPositionAnimation.setKeyValueAt(1.0, end->position()); - mPositionAnimation.setEasingCurve(QEasingCurve::Linear); - - mScaleAnimation.setDuration(duration); - mScaleAnimation.setKeyValueAt(0, QVector3D(start->scale().x(), start->scale().y(), 0)); - mScaleAnimation.setKeyValueAt(1, QVector3D(end->scale().x(), end->scale().y(), 0)); - mScaleAnimation.setEasingCurve(QEasingCurve::Linear); - + return q; } - ~HgAnimatedQuad() + static HgAnimatedQuad* createBasicAnimation(HgQuad* a, HgQuad* b, int duration) { + HgAnimatedQuad* q = new HgAnimatedQuad(); + q->mQuad = a; + + q->mPosition.setDuration(duration); + q->mPosition.setKeyValueAt(0, a->position()); + q->mPosition.setKeyValueAt(1, b->position()); + + q->mRotation.setDuration(duration); + q->mRotation.setKeyValueAt(0, a->rotation()); + q->mRotation.setKeyValueAt(1, b->rotation()); + + return q; } - + void start() { - mPositionAnimation.start(); - mScaleAnimation.start(); + mPosition.start(); + mRotation.start(); } void update() { - mQuad->setPosition(mPositionAnimation.currentValue().value()); - QVector3D scale = mScaleAnimation.currentValue().value(); - mQuad->setScale(QVector2D(scale.x(), scale.y())); + mQuad->setPosition(mPosition.currentValue().value()); + mQuad->setRotation(mRotation.currentValue().value()); } + const HgQuad* quad() const + { + return mQuad; + } + +private: HgQuad* mQuad; - MyVectorAnimation mPositionAnimation; - MyVectorAnimation mScaleAnimation; + MyVectorAnimation mPosition; + //MyVectorAnimation mScale; + MyQuaternionAnimation mRotation; + +}; + +class HgAnimatedQuadFactory +{ +public: + virtual HgAnimatedQuad* createQuad(HgQuad* qA, HgQuad* qB) const=0; }; +class HgScrollDirChangeQuadFactory : public HgAnimatedQuadFactory +{ +public: + void setup(Qt::Orientation nextScrollDirection, + const QRectF& rect, const QSizeF& spacing, const QSizeF& size, + int duration) + { + mNextScrollDirection = nextScrollDirection; + mDuration = duration; + + if (mNextScrollDirection == Qt::Horizontal) + { + qreal stepY = spacing.height() + size.height(); + qreal posY = 0.5f - (rect.height() / rect.width() / 2.0 - stepY / 2.0); + tm.translate(-posY,0); + rm.rotate(-90, QVector3D(0,0,1)); + rot = QQuaternion::fromAxisAndAngle(QVector3D(0,0,1), -90); + } + else if (mNextScrollDirection == Qt::Vertical) + { + tm.translate(0,0.5f); + rm.rotate(90, QVector3D(0,0,1)); + rot = QQuaternion::fromAxisAndAngle(QVector3D(0,0,1), -90); + } + + + } + + HgAnimatedQuad* createQuad(HgQuad* qA, HgQuad* qB) const + { + return HgAnimatedQuad::createScrollDirectionChangeAnimation(qA, qB, + tm, rm, rot, mNextScrollDirection, mDuration); + } +private: + QMatrix4x4 tm; + QMatrix4x4 rm; + QQuaternion rot; + Qt::Orientation mNextScrollDirection; + int mDuration; +}; + +class HgRowCountChangeQuadFactory : public HgAnimatedQuadFactory +{ +public: + HgRowCountChangeQuadFactory(int duration) : mDuration(duration) + { + + } + + HgAnimatedQuad* createQuad(HgQuad* qA, HgQuad* qB) const + { + return HgAnimatedQuad::createBasicAnimation(qA, qB, mDuration); + } +private: + int mDuration; +}; + + HgMediaWallRenderer::HgMediaWallRenderer(HgMediaWallDataProvider* provider, - Qt::Orientation scrollDirection, bool coverflowMode) : + Qt::Orientation orientation, Qt::Orientation scrollDirection, bool coverflowMode) : mDataProvider(provider), mRenderer(NULL), mIndicatorRenderer(NULL), mRendererInitialized(false), - mOrientation(scrollDirection), - mNextOrientation(scrollDirection), + mScrollDirection(scrollDirection), + mNextScrollDirection(scrollDirection), + mOrientation(orientation), mStateAnimationAlpha(0), mStateAnimationOnGoing(false), mAnimationAlpha(0), - mOpeningAnimationDuration(500), - mOpenedItem(-1), - mFlipAngle(qreal(360)), - mZoomAmount(qreal(0.5)), mCoverflowMode(coverflowMode), mRowCount(1), mNextRowCount(1), - mStateAnimationDuration(300), + mStateAnimationDuration(500), mStep(1.1), mZfar(-2), mSpacing2D(10,10), @@ -125,26 +244,21 @@ mCameraRotationY(0), mCameraRotationZ(0), mFrontCoverElevation(0.4), - mReflectionsEnabled(true), - mItemCountChanged(false), - mOpenedItemState(ItemClosed), - mFrontItemPosition(0,0), - mFrontItemPositionSet(false) + mFrontItemPosition(0,0) { createStateMachine(); - mImageFader = new HgImageFader(); - mRenderer = new HgVgQuadRenderer(256); + mRenderer = new HgQtQuadRenderer(64); + mRenderer->enableReflections(true); mRendererInitialized = true; if (mCoverflowMode) { - mOrientation = Qt::Horizontal; - mNextOrientation = mOrientation; + mScrollDirection = Qt::Horizontal; + mNextScrollDirection = mScrollDirection; } } HgMediaWallRenderer::~HgMediaWallRenderer() { delete mRenderer; - delete mImageFader; delete mStateMachine; } @@ -184,31 +298,28 @@ const QPointF& position, const QPointF& targetPosition, qreal springVelocity, - QPainter* painter) + QPainter* painter, + const QTransform& sceneTransform, + const QRectF& rect) { + // save new rect + mRect = rect; + // if still not initialized we cant draw anything if (!mRendererInitialized) return; - if (mOrientation != mNextOrientation || - mRowCount != mNextRowCount) + if (mScrollDirection != mNextScrollDirection) { - - // save old state of the quads - recordState(mOldState); - - // goto wanted orientation / rowcount - mOrientation = mNextOrientation; - mRowCount = mNextRowCount; - setImageSize(mNextImageSize); - - // setup quads to new state - setupRows(startPosition, position, targetPosition, springVelocity, painter); - - // record state for animation - recordState(mNextState); - - startStateAnimation(painter); + startScrollDirectionChangeAnimation(startPosition, position, + targetPosition, springVelocity, painter, sceneTransform, + rect); + } + else if (mRowCount != mNextRowCount) + { + startRowCountChangeAnimation(startPosition, position, + targetPosition, springVelocity, painter, sceneTransform, + rect); } else { @@ -223,7 +334,7 @@ } updateCameraMatrices(); - drawQuads(painter); + drawQuads(painter, sceneTransform); } void HgMediaWallRenderer::setupRows(const QPointF& startPosition, @@ -243,7 +354,7 @@ } else { - if (mOrientation == Qt::Vertical) + if (mScrollDirection == Qt::Vertical) { setupGridPortrait(startPosition, position, targetPosition, springVelocity, painter); @@ -256,21 +367,6 @@ } } -void HgMediaWallRenderer::setFlipAnimationAngle(qreal angleInDegrees) -{ - mFlipAngle = angleInDegrees; -} - -void HgMediaWallRenderer::setOpeningAnimationType(HgMediaWallRenderer::OpeningAnimationType type) -{ - mOpeningAnimationType = type; -} - -void HgMediaWallRenderer::setOpeningAnimationDuration(int msecs) -{ - mOpeningAnimationDuration = msecs; -} - qreal HgMediaWallRenderer::animationAlpha() const { return mAnimationAlpha; @@ -279,13 +375,7 @@ void HgMediaWallRenderer::setAnimationAlpha(qreal alpha) { mAnimationAlpha = alpha; - - if (mOpenedItemState == ItemClosing && alpha == 0.0f) - mOpenedItemState = ItemClosed; - - if (mOpenedItemState == ItemOpening && alpha == 1.0f) - mOpenedItemState = ItemOpened; - + emit renderingNeeded(); } @@ -310,33 +400,8 @@ mStateMachine->setAnimated(true); QState* root = new QState(QState::ParallelStates); - QState* p1 = new QState(root); QState* p2 = new QState(root); - - // create idle/opened states - { - QState* idle = new QState(p1); - QState* opened = new QState(p1); - - idle->assignProperty(this, "animationAlpha", qreal(0)); - opened->assignProperty(this, "animationAlpha", qreal(1)); - - // add opening animation - QPropertyAnimation* anim1 = new QPropertyAnimation(this, "animationAlpha"); - anim1->setDuration(mOpeningAnimationDuration); - idle->addTransition(this, SIGNAL(toggleItem()), opened)->addAnimation(anim1); - - // add closing animation - QPropertyAnimation* anim2 = new QPropertyAnimation(this, "animationAlpha"); - anim2->setDuration(mOpeningAnimationDuration); - opened->addTransition(this, SIGNAL(toggleItem()), idle)->addAnimation(anim2); - - QObject::connect(idle, SIGNAL(entered()), this, SLOT(onIdleState())); - QObject::connect(opened, SIGNAL(entered()), this, SLOT(onOpenedState())); - - p1->setInitialState(idle); - } - + // create two states to animate between { QState* s1 = new QState(p2); @@ -356,58 +421,47 @@ p2->setInitialState(s1); } - root->setInitialState(p1); + root->setInitialState(p2); mStateMachine->addState(root); mStateMachine->setInitialState(root); mStateMachine->start(); } -void HgMediaWallRenderer::onIdleState() -{ - emit itemClosed(mOpenedItem); -} - -void HgMediaWallRenderer::onOpenedState() -{ - emit itemOpened(mOpenedItem); -} - -void HgMediaWallRenderer::setOrientation(Qt::Orientation orientation, bool animate) +void HgMediaWallRenderer::setScrollDirection(Qt::Orientation scrollDirection, bool animate) { // coverflow is always horizontal if (mCoverflowMode) { - mOrientation = Qt::Horizontal; - mNextOrientation = mOrientation; + mScrollDirection = Qt::Horizontal; + mNextScrollDirection = mScrollDirection; return; } - if (mOrientation != orientation) + if (mScrollDirection != scrollDirection) { mStateMachine->setAnimated(animate); - mNextOrientation = orientation; + mNextScrollDirection = scrollDirection; if (!animate) - mOrientation = orientation; + mScrollDirection = scrollDirection; else { - emit renderingNeeded(); + //emit renderingNeeded(); } } } -Qt::Orientation HgMediaWallRenderer::getOrientation() const +Qt::Orientation HgMediaWallRenderer::getScrollDirection() const { - return mOrientation; + return mScrollDirection; } -void HgMediaWallRenderer::drawQuads(QPainter* painter) +void HgMediaWallRenderer::drawQuads(QPainter* painter, + const QTransform& sceneTransform) { - - mRenderer->transformQuads(mViewMatrix, mProjMatrix, mRect); - - mRenderer->drawQuads(mRect, painter); + mRenderer->drawQuads(painter, mRect, mViewMatrix, mProjMatrix, mOrientation, + sceneTransform); } @@ -453,11 +507,7 @@ void HgMediaWallRenderer::recordState(HgMediaWallRenderer::State& state) { // cleanup old quads - for (int i = 0; i < state.mQuads.size(); i++) - { - delete state.mQuads[i]; - } - + qDeleteAll(state.mQuads.begin(), state.mQuads.end()); state.mQuads.clear(); // record new quads @@ -467,7 +517,8 @@ if (!quad->visible()) continue; - state.mQuads.append(quad->copy()); + int index = quad->userData().toInt(); + state.mQuads[index] = quad->copy(); } } @@ -476,12 +527,18 @@ Q_UNUSED(painter) resetQuads(); + updateSpacingAndImageSize(); + // setup quads from animated state - for (int i = 0; i < mOldState.mQuads.size(); i++) + for (int i = 0; i < mAnimatedQuads.count(); i++) { - mAnimatedQuads[i]->update(); - mRenderer->quad(i)->copyFrom(*mOldState.mQuads[i]); + if (i >= mRenderer->quadCount()) + return; + + mAnimatedQuads[i]->update(); + mRenderer->quad(i)->copyFrom(*mAnimatedQuads[i]->quad()); } + } void HgMediaWallRenderer::resetQuads() @@ -495,22 +552,7 @@ if (!mRendererInitialized) return NULL; - return mRenderer->getQuadAt(position);//mapFromWindow(position)); -} - -bool HgMediaWallRenderer::isItemOpen() const -{ - return (mOpenedItem != -1 && mAnimationAlpha > 0); -} - -void HgMediaWallRenderer::setRect(const QRectF& windowRect) -{ - mRect = windowRect; -} - -const QRectF& HgMediaWallRenderer::getRect() const -{ - return mRect; + return mRenderer->getQuadAt(position); } void HgMediaWallRenderer::updateCameraMatrices() @@ -523,26 +565,18 @@ QVector3D(0.0f, 0.0f, 0.0f), QVector3D(0.0f, 1.0f, 0.0f)); QMatrix4x4 rot; - rot.rotate(mCameraRotationZ, QVector3D(0,0,1)); + //rot.rotate(mCameraRotationZ, QVector3D(0,0,1)); rot.rotate(mCameraRotationY, QVector3D(0,1,0)); view *= rot; - - qreal aspect = mRect.width() / mRect.height(); - + QMatrix4x4 proj; proj.setToIdentity(); - if (mRect.width() <= mRect.height()) - { - qreal aspect = mRect.height() / mRect.width(); - proj.frustum(-0.5f, 0.5f, -0.5f*aspect, 0.5f*aspect, 1.0f, 1000.0f); - } - else - { - qreal aspect = mRect.width() / mRect.height(); - proj.frustum(-0.5f*aspect, 0.5f*aspect, -0.5f, 0.5f, 1.0f, 1000.0f); - } - + // setup projection matrix so that width of the item wichi has the + // width of the screen has width of 1 in 3D space + qreal aspect = mRect.height() / mRect.width(); + proj.frustum(-0.5f, 0.5f, -0.5f * aspect, 0.5f * aspect, 1.0f, 1000.0f); + mViewMatrix = view; mProjMatrix = proj; @@ -562,7 +596,7 @@ void HgMediaWallRenderer::updateSpacingAndImageSize() { - qreal div = mRect.width() <= mRect.height() ? mRect.width() : mRect.height(); + qreal div = mRect.width(); mSpacing3D = mSpacing2D / div; mImageSize3D = mImageSize2D / div; @@ -599,32 +633,6 @@ return mFrontCoverElevation; } -void HgMediaWallRenderer::openItem(int index, bool animate) -{ - if (isItemOpen()) - return; - - mOpenedItem = index; - mOpenedItemState = animate ? ItemOpening : ItemOpened; - - mStateMachine->setAnimated(animate); - emit toggleItem(); - -} - -void HgMediaWallRenderer::closeItem(bool animate) -{ - if (!isItemOpen()) - return; - - mOpenedItemState = animate ? ItemClosing : ItemClosed; - if (!animate) - mOpenedItem = -1; - - mStateMachine->setAnimated(animate); - emit toggleItem(); -} - qreal HgMediaWallRenderer::getRowPosY(int row) { qreal step = mSpacing3D.height() + mImageSize3D.height(); @@ -637,95 +645,99 @@ return mColumnCount == 1 ? qreal(0) : (((qreal)mColumnCount/qreal(2)-qreal(0.5)) - (qreal)col) * step; } - void HgMediaWallRenderer::enableReflections(bool enabled) { - mReflectionsEnabled = enabled; + mRenderer->enableReflections(enabled); } bool HgMediaWallRenderer::reflectionsEnabled() const { - return mReflectionsEnabled; + return mRenderer->reflectionsEnabled(); } -QPointF HgMediaWallRenderer::mapFromWindow(const QPointF& point) const -{ - return QPointF(point.x(), mRect.height() - point.y()); -} - -void HgMediaWallRenderer::emitUpdate() -{ - emit renderingNeeded(); -} - -void HgMediaWallRenderer::applyOpeningAnimation(HgQuad* quad) -{ - QQuaternion rot(0,0,0,1); - qreal rotAngle = mAnimationAlpha * mFlipAngle; - rot = QQuaternion::fromAxisAndAngle(QVector3D(0,1,0), rotAngle); - quad->setRotation(rot); - quad->setPosition(quad->position() + QVector3D(0,0,mAnimationAlpha * mZoomAmount)); -} - - qreal HgMediaWallRenderer::getWorldWidth() const { qreal width = ceil((qreal)mDataProvider->imageCount() / (qreal)mRowCount - 1.0f); // if we are in vertical orientation we want last and first item // to place at the top and bottom of the screen instead of center - if (mOrientation == Qt::Vertical) + if (mScrollDirection == Qt::Vertical) { qreal step = mSpacing2D.height() + mImageSize2D.height(); width -= (mRect.height() / step - 1.0f); } + else if (mScrollDirection == Qt::Horizontal && !mCoverflowMode) + { + qreal step = mSpacing2D.width() + mImageSize2D.width(); + width -= (mRect.width() / step - 1.0f); + } return width; } -void HgMediaWallRenderer::beginRemoveRows(int start, int end) + +void HgMediaWallRenderer::createAnimatedQuads(const HgAnimatedQuadFactory& factory) { - mRemoveStart = start; - mRemoveEnd = end; - mItemCountChanged = true; + // clear previous animation quads + qDeleteAll(mAnimatedQuads.begin(), mAnimatedQuads.end()); + mAnimatedQuads.clear(); + + // default quad is used if no counterpart for the current quad exits. + HgQuad* defaultQuad = new HgQuad(); + defaultQuad->setPosition(QVector3D(100,100,-100)); - recordState(mOldState); - -} - -void HgMediaWallRenderer::endRemoveRows() -{ + // setup new animated quads + QMap::iterator i = mNextState.mQuads.begin(); + while(i != mNextState.mQuads.end()) + { + HgQuad* qB = i.value(); + HgQuad* qA = NULL; + QMap::iterator j = mOldState.mQuads.find(i.key()); + if (j != mOldState.mQuads.end()) + { + qA = j.value(); + } + else + { + qA = defaultQuad->copy(); + } - mStateMachine->setAnimated(true); - - emit renderingNeeded(); - + HgAnimatedQuad* q = factory.createQuad(qA, qB); + mAnimatedQuads.append(q); + + q->start(); + i++; + } } -void HgMediaWallRenderer::startStateAnimation(QPainter* painter) +void HgMediaWallRenderer::startScrollDirectionChangeAnimation( + const QPointF& startPosition, + const QPointF& position, + const QPointF& targetPosition, + qreal springVelocity, + QPainter* painter, + const QTransform& sceneTransform, + const QRectF& rect) { - - // clear previous animation quads - for (int i = 0; i < mAnimatedQuads.size(); i++) - { - delete mAnimatedQuads[i]; - } - mAnimatedQuads.clear(); + + // save state for current orientation + setupRows(startPosition, position, targetPosition, springVelocity, painter); + recordState(mOldState); - // setup animated quads - HgQuad* defaultQuad = new HgQuad(); - defaultQuad->setPosition(QVector3D(100,100,-100)); - int n = mOldState.mQuads.count() < mNextState.mQuads.count() ? mNextState.mQuads.count() : mOldState.mQuads.count(); - for (int i = 0; i < n; i++) - { - HgQuad* qA = (i >= mOldState.mQuads.count()) ? defaultQuad : mOldState.mQuads[i]; - HgQuad* qB = (i >= mNextState.mQuads.count()) ? defaultQuad : mNextState.mQuads[i]; + // goto wanted orientation + mScrollDirection = mNextScrollDirection; + + // setup quads to new state + setupRows(startPosition, position, targetPosition, springVelocity, painter); + + // record state for animation + recordState(mNextState); + + HgScrollDirChangeQuadFactory factory; + factory.setup(mNextScrollDirection, mRect, mSpacing3D, mImageSize3D, mStateAnimationDuration); + + createAnimatedQuads(factory); - HgAnimatedQuad* q = new HgAnimatedQuad(qA, qB, mStateAnimationDuration); - mAnimatedQuads.append(q); - q->start(); - } - mStateAnimationOnGoing = true; // setup first frame of the animation @@ -733,7 +745,38 @@ // toggle state animation on toggleState(); + +} +void HgMediaWallRenderer::startRowCountChangeAnimation( + const QPointF& startPosition, + const QPointF& position, + const QPointF& targetPosition, + qreal springVelocity, + QPainter* painter, + const QTransform& sceneTransform, + const QRectF& rect) +{ + setupRows(startPosition, position, targetPosition, springVelocity, painter); + recordState(mOldState); + + mRowCount = mNextRowCount; + setImageSize(mNextImageSize); + + setupRows(startPosition, position, targetPosition, springVelocity, painter); + recordState(mNextState); + + HgRowCountChangeQuadFactory factory(mStateAnimationDuration); + + createAnimatedQuads(factory); + + mStateAnimationOnGoing = true; + + // setup first frame of the animation + setupStateAnimation(painter); + + // toggle state animation on + toggleState(); } void HgMediaWallRenderer::setupCoverflow(const QPointF& startPosition, @@ -746,10 +789,7 @@ Q_UNUSED(targetPosition) Q_UNUSED(springVelocity) Q_UNUSED(painter) - - // save selected item for coverflow - mSelectedItem = ceil(position.x()); - + int quadsVisible = (mRect.width() / mImageSize2D.width() + 1) * 4; int selectedItemIndex = quadsVisible / 2; @@ -794,7 +834,7 @@ // setup quad for this item HgQuad* quad = mRenderer->quad(quadIndex); - setupDefaultQuad(QVector3D(posX, posY, posZ), itemIndex, mReflectionsEnabled, quadIndex); + setupDefaultQuad(QVector3D(posX, posY, posZ), itemIndex, reflectionsEnabled(), quadIndex); // step to next item posX += step; @@ -816,8 +856,10 @@ Q_UNUSED(springVelocity) Q_UNUSED(painter) - int rowCount = (mRect.height() / mImageSize2D.height() + 1) * 4; - int rowsUp = rowCount/2; + // we need to setup 2 times more rows than visible, because we need + // more quads for the orientation switch + int rowCount = (mRect.height() / mImageSize2D.height() + 1) * 3; + int rowsUp = rowCount / 3; qreal stepY = mSpacing3D.height() + mImageSize3D.height(); qreal ipos = floorf(position.x()); @@ -825,8 +867,7 @@ qreal posY = -(qreal)rowsUp * stepY - frac; // adjust height so that we begin from top - qreal div = mRect.width() <= mRect.height() ? mRect.width() : mRect.height(); - posY -= mRect.height() / div / 2.0 - stepY / 2.0; + posY -= mRect.height() / mRect.width() / 2.0 - stepY / 2.0; int count = mDataProvider->imageCount(); int itemIndex = ((int)(ipos - (qreal)rowsUp)) * mColumnCount; @@ -839,7 +880,6 @@ { itemIndex+=mColumnCount; posY += stepY; - row++; continue; } else if (itemIndex >= count || quadIndex >= mRenderer->quadCount() || row >= rowCount) @@ -851,7 +891,6 @@ posY += stepY; row++; - itemIndex+=mColumnCount; } } @@ -866,15 +905,17 @@ Q_UNUSED(targetPosition) Q_UNUSED(springVelocity) Q_UNUSED(painter) - + int colCount = (mRect.width() / mImageSize2D.width() + 1) * 3; - int colsLeft = colCount/2; + int colsLeft = colCount / 3; qreal stepX = mSpacing3D.width() + mImageSize3D.width(); qreal ipos = floorf(position.x()); qreal frac = (position.x() - ipos) * stepX; qreal posX = -(qreal)colsLeft * stepX - frac; + posX -= 0.5f - stepX / 2.0; + int count = mDataProvider->imageCount(); int itemIndex = ((int)(ipos - (qreal)colsLeft)) * mRowCount; int col = 0; @@ -886,7 +927,6 @@ { itemIndex+=mColumnCount; posX += stepX; - col++; continue; } else if (itemIndex >= count || col >= colCount || quadIndex >= mRenderer->quadCount()) @@ -898,34 +938,36 @@ posX += stepX; col++; - itemIndex+=mRowCount; } } -void HgMediaWallRenderer::setupGridColumn(qreal posX, int itemIndex, int& quadIndex) +void HgMediaWallRenderer::setupGridColumn(qreal posX, int& itemIndex, int& quadIndex) { for (int i = 0; i < mRowCount; i++) { + if (quadIndex >= mRenderer->quadCount() || itemIndex >= mDataProvider->imageCount()) + return; + qreal posY = getRowPosY(i); // enable reflections for the last row needed - bool reflections = (i == (mRowCount-1) && mReflectionsEnabled); + bool reflections = (i == (mRowCount-1) && reflectionsEnabled()); setupDefaultQuad(QVector3D(posX, posY, 0), itemIndex++, reflections, quadIndex); - if (itemIndex >= mDataProvider->imageCount()) - return; } } -void HgMediaWallRenderer::setupGridRow(qreal posY, int itemIndex, int& quadIndex) +void HgMediaWallRenderer::setupGridRow(qreal posY, int& itemIndex, int& quadIndex) { for (int i = 0; i < mColumnCount; i++) { + if (quadIndex >= mRenderer->quadCount() || itemIndex >= mDataProvider->imageCount()) + return; + qreal posX = getColumnPosX(i); + setupDefaultQuad(QVector3D(posX, posY, 0), itemIndex++, false, quadIndex); - if (itemIndex >= mDataProvider->imageCount()) - return; } } @@ -943,14 +985,10 @@ quad->enableMirrorImage(reflectionsEnabled); quad->setAlpha(1.0f); - // apply opening animation if needed - /* if (itemIndex == mOpenedItem) - applyOpeningAnimation(quad); -*/ // setup indicator/decorator for the item if needed int flags = mDataProvider->flags(itemIndex); const HgImage* indicatorImage = mDataProvider->indicator(flags); - if (flags != 0 && indicatorImage) + if (flags != 0 && indicatorImage && quadIndex < mRenderer->quadCount()) { HgQuad* indicator = mRenderer->quad(quadIndex++); setupIndicator(quad, indicator, indicatorImage, @@ -976,9 +1014,6 @@ indicator->enableMirrorImage(false); indicator->setAlpha(parent->alpha()); - // apply opening animation to indicator if needed - if (itemIndex == mOpenedItem) - applyOpeningAnimation(indicator); } HgQuadRenderer* HgMediaWallRenderer::getRenderer() @@ -989,7 +1024,7 @@ bool HgMediaWallRenderer::getItemPoints(int index, QPolygonF& points) const { QPolygonF poly; - if (!mRenderer->getQuadTranformedPoints(poly, index)) + if (!mRenderer->getQuadTranformedPointsByUserData(poly, QVariant(index))) return false; points = poly; @@ -1013,3 +1048,8 @@ { return mFrontItemPosition; } + +void HgMediaWallRenderer::setOrientation(Qt::Orientation orientation) +{ + mOrientation = orientation; +}