--- 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 <qvector3d>
#include <qtimer>
#include <qpropertyanimation>
@@ -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>();
+ }
+ 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>());
- QVector3D scale = mScaleAnimation.currentValue().value<QVector3D>();
- mQuad->setScale(QVector2D(scale.x(), scale.y()));
+ mQuad->setPosition(mPosition.currentValue().value<QVector3D>());
+ mQuad->setRotation(mRotation.currentValue().value<QQuaternion>());
}
+ 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<int, HgQuad*>::iterator i = mNextState.mQuads.begin();
+ while(i != mNextState.mQuads.end())
+ {
+ HgQuad* qB = i.value();
+ HgQuad* qA = NULL;
+ QMap<int, HgQuad*>::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;
+}