diff options
Diffstat (limited to 'src/declarative/fx/qfxtransform.cpp')
-rw-r--r-- | src/declarative/fx/qfxtransform.cpp | 522 |
1 files changed, 295 insertions, 227 deletions
diff --git a/src/declarative/fx/qfxtransform.cpp b/src/declarative/fx/qfxtransform.cpp index a001214..9f18413 100644 --- a/src/declarative/fx/qfxtransform.cpp +++ b/src/declarative/fx/qfxtransform.cpp @@ -51,7 +51,7 @@ QT_BEGIN_NAMESPACE #define M_PI 3.14159265358979323846 #endif -QML_DEFINE_TYPE(QFxTransform,Transform); +QML_DEFINE_NOCREATE_TYPE(QFxTransform); /*! \qmlclass Transform @@ -62,6 +62,10 @@ QFxTransform::QFxTransform(QObject *parent) : { } +QFxTransform::~QFxTransform() +{ +} + bool QFxTransform::isIdentity() const { return true; @@ -75,143 +79,192 @@ QSimpleCanvas::Matrix QFxTransform::transform() const void QFxTransform::update() { QFxItem *item = qobject_cast<QFxItem *>(parent()); - if(item) + if (item) item->updateTransform(); } -QML_DEFINE_TYPE(QFxAxis,Axis); +/*! + \qmlclass Axis + \brief An axis that can be used for rotation or translation. +*/ + +QML_DEFINE_TYPE(QFxAxis, Axis); QFxAxis::QFxAxis(QObject *parent) -: QFxTransform(parent), _xStart(0), _yStart(0), _xEnd(0), _yEnd(0), _zEnd(0), _rotation(0), - _translation(0), _distanceToPlane(1024.), _dirty(true) +: QObject(parent), _startX(0), _startY(0), _endX(0), _endY(0), _endZ(0) { } -qreal QFxAxis::xStart() const +QFxAxis::~QFxAxis() { - return _xStart; } -void QFxAxis::setXStart(qreal x) +qreal QFxAxis::startX() const { - _xStart = x; - update(); + return _startX; } -qreal QFxAxis::yStart() const +void QFxAxis::setStartX(qreal x) { - return _yStart; + _startX = x; + emit updated(); } -void QFxAxis::setYStart(qreal y) +qreal QFxAxis::startY() const { - _yStart = y; - update(); + return _startY; } -qreal QFxAxis::xEnd() const +void QFxAxis::setStartY(qreal y) { - return _xEnd; + _startY = y; + emit updated(); } -void QFxAxis::setXEnd(qreal x) +qreal QFxAxis::endX() const { - _xEnd = x; - update(); + return _endX; } -qreal QFxAxis::yEnd() const +void QFxAxis::setEndX(qreal x) { - return _yEnd; + _endX = x; + emit updated(); } -void QFxAxis::setYEnd(qreal y) +qreal QFxAxis::endY() const { - _yEnd = y; - update(); + return _endY; } -qreal QFxAxis::zEnd() const +void QFxAxis::setEndY(qreal y) { - return _zEnd; + _endY = y; + emit updated(); } -void QFxAxis::setZEnd(qreal z) +qreal QFxAxis::endZ() const { -#if !defined(QFX_RENDER_OPENGL) - if(z != 0. && translation() != 0.) { - qmlInfo(this) << "QTransform cannot translate along Z-axis"; - return; - } -#endif + return _endZ; +} - _zEnd = z; - update(); +void QFxAxis::setEndZ(qreal z) +{ + _endZ = z; + emit updated(); } -qreal QFxAxis::rotation() const +/*! + \qmlclass AxisRotation + \brief The AxisRotation element provides a way to rotate an Item around an axis. + + Here is an example of various rotations applied to an \l Image. + \code + <HorizontalLayout margin="10" spacing="10"> + <Image src="qt.png"/> + <Image src="qt.png"> + <transform> + <AxisRotation axis.startX="30" axis.endX="30" axis.endY="60" angle="18"/> + </transform> + </Image> + <Image src="qt.png"> + <transform> + <AxisRotation axis.startX="30" axis.endX="30" axis.endY="60" angle="36"/> + </transform> + </Image> + <Image src="qt.png"> + <transform> + <AxisRotation axis.startX="30" axis.endX="30" axis.endY="60" angle="54"/> + </transform> + </Image> + <Image src="qt.png"> + <transform> + <AxisRotation axis.startX="30" axis.endX="30" axis.endY="60" angle="72"/> + </transform> + </Image> + </HorizontalLayout> + \endcode + + \image axisrotation.png +*/ + +QML_DEFINE_TYPE(QFxRotation,AxisRotation); + +QFxRotation::QFxRotation(QObject *parent) +: QFxTransform(parent), _angle(0), _distanceToPlane(1024.), _dirty(true) { - return _rotation; + connect(&_axis, SIGNAL(updated()), this, SLOT(update())); } -void QFxAxis::setRotation(qreal r) +QFxRotation::~QFxRotation() { - _rotation = r; - update(); } -qreal QFxAxis::translation() const +/*! + \qmlproperty real AxisRotation::axis.startX + \qmlproperty real AxisRotation::axis.startY + \qmlproperty real AxisRotation::axis.endX + \qmlproperty real AxisRotation::axis.endY + \qmlproperty real AxisRotation::axis.endZ + + A rotation axis is specified by 2 points in 3D space: a start point and + an end point. The z-position of the start point is assumed to be 0, and cannot + be changed. +*/ +QFxAxis *QFxRotation::axis() { - return _translation; + return &_axis; } -void QFxAxis::setTranslation(qreal t) +/*! + \qmlproperty real AxisRotation::angle + + The angle, in degrees, to rotate around the specified axis. +*/ +qreal QFxRotation::angle() const { -#if !defined(QFX_RENDER_OPENGL) - if(zEnd() != 0. && t != 0.) { - qmlInfo(this) << "QTransform cannot translate along Z-axis"; - return; - } -#endif + return _angle; +} - _translation = t; +void QFxRotation::setAngle(qreal angle) +{ + _angle = angle; update(); } -bool QFxAxis::isIdentity() const +bool QFxRotation::isIdentity() const { - return (_rotation == 0. && _translation == 0.) || - (zEnd() == 0. && yEnd() == yStart() && xEnd() == xStart()); + return (_angle == 0.) || (_axis.endZ() == 0. && _axis.endY() == _axis.startY() && _axis.endX() == _axis.startX()); } #if defined(QFX_RENDER_QPAINTER) const qreal inv_dist_to_plane = 1. / 1024.; -QTransform QFxAxis::transform() const +QTransform QFxRotation::transform() const { - if(_dirty) { + if (_dirty) { _transform = QTransform(); - if(!isIdentity()) { - if(rotation() != 0.) { + if (!isIdentity()) { + if (angle() != 0.) { QTransform rotTrans; - rotTrans.translate(-xStart(), -yStart()); + rotTrans.translate(-_axis.startX(), -_axis.startY()); QTransform rotTrans2; - rotTrans2.translate(xStart(), yStart()); + rotTrans2.translate(_axis.startX(), _axis.startY()); - qreal rad = rotation() * 2. * M_PI / 360.; + qreal rad = angle() * 2. * M_PI / 360.; qreal c = ::cos(rad); qreal s = ::sin(rad); - qreal x = xEnd() - xStart(); - qreal y = yEnd() - yStart(); - qreal z = zEnd(); + qreal x = _axis.endX() - _axis.startX(); + qreal y = _axis.endY() - _axis.startY(); + qreal z = _axis.endZ(); qreal idtp = inv_dist_to_plane; - if(distanceToPlane() != 1024.) + if (distanceToPlane() != 1024.) idtp = 1. / distanceToPlane(); qreal len = x * x + y * y + z * z; - if(len != 1.) { + if (len != 1.) { len = ::sqrt(len); x /= len; y /= len; @@ -226,13 +279,6 @@ QTransform QFxAxis::transform() const _transform *= rot; _transform *= rotTrans2; } - - if(translation() != 0.) { - QTransform trans; - trans.translate((xEnd() - xStart()) * translation(), - (yEnd() - yStart()) * translation()); - _transform *= trans; - } } _dirty = false; @@ -241,27 +287,22 @@ QTransform QFxAxis::transform() const return _transform; } #elif defined(QFX_RENDER_OPENGL) -QMatrix4x4 QFxAxis::transform() const +QMatrix4x4 QFxRotation::transform() const { - if(_dirty) { + if (_dirty) { _dirty = false; _transform = QMatrix4x4(); - if(!isIdentity()) { - if(rotation() != 0.) { - qreal x = xEnd() - xStart(); - qreal y = yEnd() - yStart(); - qreal z = zEnd(); + if (!isIdentity()) { + if (angle() != 0.) { + qreal x = _axis.endX() - _axis.startX(); + qreal y = _axis.endY() - _axis.startY(); + qreal z = _axis.endZ(); - _transform.translate(xStart(), yStart(), 0); - _transform.rotate(rotation(), x, y, z); - _transform.translate(-xStart(), -yStart(), 0); + _transform.translate(_axis.startX(), _axis.startY(), 0); + _transform.rotate(angle(), x, y, z); + _transform.translate(-_axis.startX(), -_axis.startY(), 0); } - - if(translation() != 0.) - _transform.translate((xEnd() - xStart()) * translation(), - (yEnd() - yStart()) * translation(), - (zEnd()) * translation()); } } @@ -269,198 +310,161 @@ QMatrix4x4 QFxAxis::transform() const } #endif -qreal QFxAxis::distanceToPlane() const +/*! + \qmlproperty real AxisRotation::distanceToPlane +*/ +qreal QFxRotation::distanceToPlane() const { return _distanceToPlane; } -void QFxAxis::setDistanceToPlane(qreal d) +void QFxRotation::setDistanceToPlane(qreal d) { _distanceToPlane = d; update(); } -void QFxAxis::update() +void QFxRotation::update() { _dirty = true; QFxItem *item = qobject_cast<QFxItem *>(parent()); - if(item) + if (item) item->updateTransform(); } -QML_DEFINE_TYPE(QFxFlipable,Flipable); - -class QFxFlipablePrivate : public QFxItemPrivate -{ -public: - QFxFlipablePrivate() : current(QFxFlipable::Front), front(0), back(0) {} - - QFxFlipable::Side current; - QFxItem *front; - QFxItem *back; -}; - /*! - \qmlclass Flipable QFxFlipable - \brief The Flipable element provides a surface that can be flipped. - \inherits Item - - Flipable allows you to specify a front and a back and then flip between those sides. + \qmlclass AxisTranslation + \brief The AxisTranslation element provides a way to move an Item along an axis. + The following example translates the image to 10, 3. \code - <Flipable id="flipable" width="40" height="40"> + <Image src="logo.png"> <transform> - <Axis id="axis" xStart="20" xEnd="20" yStart="20" yEnd="0" /> + <AxisTranslation axis.startX="0" axis.startY="0" axis.endX="1" axis.endY=".3" distance="10"/> </transform> - <front> - <Image file="front.png"/> - </front> - <back> - <Image file="back.png"/> - </back> - <states> - <State name="back"> - <SetProperty target="{axis}" property="rotation" value="180" /> - </State> - </states> - <transitions> - <Transition> - <NumericAnimation easing="easeInOutQuad" properties="rotation"/> - </Transition> - </transitions> - </Flipable> + </Image> \endcode - - \image flipable.gif */ -/*! - \internal - \class QFxFlipable - \brief The QFxFlipable class provides a flipable surface. - - \ingroup group_widgets +QML_DEFINE_TYPE(QFxTranslation,AxisTranslation); - QFxFlipable allows you to specify a front and a back, as well as an - axis for the flip. -*/ +QFxTranslation::QFxTranslation(QObject *parent) +: QFxTransform(parent), _distance(0), _dirty(true) +{ + connect(&_axis, SIGNAL(updated()), this, SLOT(update())); +} -QFxFlipable::QFxFlipable(QFxItem *parent) -: QFxItem(*(new QFxFlipablePrivate), parent) +QFxTranslation::~QFxTranslation() { } -QFxFlipable::~QFxFlipable() +/*! + \qmlproperty real AxisTranslation::axis.startX + \qmlproperty real AxisTranslation::axis.startY + \qmlproperty real AxisTranslation::axis.endX + \qmlproperty real AxisTranslation::axis.endY + \qmlproperty real AxisTranslation::axis.endZ + + A translation axis is specified by 2 points in 3D space: a start point and + an end point. The z-position of the start point is assumed to be 0, and cannot + be changed. Changing the z-position of the end point is only valid when running + under OpenGL. +*/ +QFxAxis *QFxTranslation::axis() { + return &_axis; } /*! - \qmlproperty Item Flipable::front - \qmlproperty Item Flipable::back + \qmlproperty real AxisTranslation::distance - The front and back sides of the flipable. -*/ + The distance to translate along the specified axis. distance is a multiplier; + in the example below, a distance of 1 would translate to 100, 50, while a distance + of 0.5 would translate to 50, 25. -QFxItem *QFxFlipable::front() + \code + <AxisTranslation axis.startX="0" axis.startY="0" axis.endX="100" axis.endY="50"/> + \endcode +*/ +qreal QFxTranslation::distance() const { - Q_D(const QFxFlipable); - return d->front; + return _distance; } -void QFxFlipable::setFront(QFxItem *front) +void QFxTranslation::setDistance(qreal distance) { - Q_D(QFxFlipable); - if(d->front) { - qmlInfo(this) << "front is a write-once property"; - return; - } - d->front = front; - children()->append(d->front); - if(Back == d->current) - d->front->setOpacity(0.); + _distance = distance; + update(); } -QFxItem *QFxFlipable::back() +bool QFxTranslation::isIdentity() const { - Q_D(const QFxFlipable); - return d->back; + return (_distance == 0.) || (_axis.endZ() == 0. && _axis.endY() == _axis.startY() && _axis.endX() == _axis.startX()); } -void QFxFlipable::setBack(QFxItem *back) +#if defined(QFX_RENDER_QPAINTER) +QTransform QFxTranslation::transform() const { - Q_D(QFxFlipable); - if(d->back) { - qmlInfo(this) << "back is a write-once property"; - return; - } - d->back = back; - children()->append(d->back); - if(Front == d->current) - d->back->setOpacity(0.); -} + if (_dirty) { + _transform = QTransform(); -/*! - \qmlproperty enumeration Flipable::side + if (!isIdentity()) { + if (distance() != 0.) { + QTransform trans; + trans.translate((_axis.endX() - _axis.startX()) * distance(), + (_axis.endY() - _axis.startY()) * distance()); + _transform *= trans; + } + } - The side of the Flippable currently visible. Possible values are \c - Front and \c Back. -*/ -QFxFlipable::Side QFxFlipable::side() const -{ - Q_D(const QFxFlipable); - return d->current; -} + _dirty = false; + } -void QFxFlipable::transformChanged(const QSimpleCanvas::Matrix &trans) + return _transform; +} +#elif defined(QFX_RENDER_OPENGL) +QMatrix4x4 QFxRotation::transform() const { - Q_D(QFxFlipable); - QPointF p1(0, 0); - QPointF p2(1, 0); - QPointF p3(1, 1); - - p1 = trans.map(p1); - p2 = trans.map(p2); - p3 = trans.map(p3); + if (_dirty) { + _dirty = false; + _transform = QMatrix4x4(); - qreal cross = (p1.x() - p2.x()) * (p3.y() - p2.y()) - - (p1.y() - p2.y()) * (p3.x() - p2.x()); + if (!isIdentity()) { + if (distance() != 0.) + _transform.translate((_axis.endX() - _axis.startX()) * distance(), + (_axis.endY() - _axis.startY()) * distance(), + (_axis.endZ()) * distance()); - Side newSide; - if(cross > 0) { - newSide = Back; - } else { - newSide = Front; + } } - if(newSide != d->current) { - d->current = newSide; - if (d->current==Back) { - QSimpleCanvas::Matrix mat; -#ifdef QFX_RENDER_OPENGL - mat.translate(d->back->width()/2,d->back->height()/2, 0); - if(d->back->width() && p1.x() >= p2.x()) - mat.rotate(180, 0, 1, 0); - if(d->back->height() && p2.y() >= p3.y()) - mat.rotate(180, 1, 0, 0); - mat.translate(-d->back->width()/2,-d->back->height()/2, 0); -#else - mat.translate(d->back->width()/2,d->back->height()/2); - if(d->back->width() && p1.x() >= p2.x()) - mat.rotate(180, Qt::YAxis); - if(d->back->height() && p2.y() >= p3.y()) - mat.rotate(180, Qt::XAxis); - mat.translate(-d->back->width()/2,-d->back->height()/2); + return _transform; +} #endif - d->back->setTransform(mat); - } - if(d->front) - d->front->setOpacity((d->current==Front)?1.:0.); - if(d->back) - d->back->setOpacity((d->current==Back)?1.:0.); - emit sideChanged(); + +void QFxTranslation::update() +{ + _dirty = true; + +#if !defined(QFX_RENDER_OPENGL) + if (_axis.endZ() != 0. && distance() != 0.) { + qmlInfo(this) << "QTransform cannot translate along Z-axis."; } +#endif + + QFxItem *item = qobject_cast<QFxItem *>(parent()); + if (item) + item->updateTransform(); } +/*! + \qmlclass Perspective + \brief The Perspective element specifies a perspective transformation. + + A Perspective transform only affects an item when running under OpenGL; when running under software + rasterization it has no effect. +*/ + QML_DEFINE_TYPE(QFxPerspective,Perspective); QFxPerspective::QFxPerspective(QObject *parent) @@ -468,6 +472,10 @@ QFxPerspective::QFxPerspective(QObject *parent) { } +QFxPerspective::~QFxPerspective() +{ +} + #if defined(QFX_RENDER_OPENGL) bool QFxPerspective::isIdentity() const { @@ -486,6 +494,33 @@ QMatrix4x4 QFxPerspective::transform() const } #endif +/*! + \qmlproperty real Perspective::angle +*/ + +/*! + \qmlproperty real Perspective::aspect +*/ + +/*! + \qmlproperty real Perspective::x +*/ + +/*! + \qmlproperty real Perspective::y +*/ + +/*! + \qmlproperty real Perspective::scale +*/ + +/*! + \qmlclass Squish + \brief The Squish element allows you to distort an items appearance by 'squishing' it. + + A Squish transform only affects an item when running under OpenGL; when running under software + rasterization it has no effect. +*/ QML_DEFINE_TYPE(QFxSquish,Squish); QFxSquish::QFxSquish(QObject *parent) @@ -493,6 +528,13 @@ QFxSquish::QFxSquish(QObject *parent) { } +QFxSquish::~QFxSquish() +{ +} + +/*! + \qmlproperty real Squish::x +*/ qreal QFxSquish::x() const { return p.x(); @@ -504,6 +546,9 @@ void QFxSquish::setX(qreal v) update(); } +/*! + \qmlproperty real Squish::y +*/ qreal QFxSquish::y() const { return p.y(); @@ -515,6 +560,9 @@ void QFxSquish::setY(qreal v) update(); } +/*! + \qmlproperty real Squish::width +*/ qreal QFxSquish::width() const { return s.width(); @@ -526,6 +574,9 @@ void QFxSquish::setWidth(qreal v) update(); } +/*! + \qmlproperty real Squish::height +*/ qreal QFxSquish::height() const { return s.height(); @@ -537,6 +588,10 @@ void QFxSquish::setHeight(qreal v) update(); } +/*! + \qmlproperty real Squish::topLeftX + \qmlproperty real Squish::topLeftY +*/ qreal QFxSquish::topLeft_x() const { return p1.x(); @@ -559,6 +614,10 @@ void QFxSquish::settopLeft_y(qreal v) update(); } +/*! + \qmlproperty real Squish::topRightX + \qmlproperty real Squish::topRightY +*/ qreal QFxSquish::topRight_x() const { return p2.x(); @@ -581,6 +640,10 @@ void QFxSquish::settopRight_y(qreal v) update(); } +/*! + \qmlproperty real Squish::bottomLeftX + \qmlproperty real Squish::bottomLeftY +*/ qreal QFxSquish::bottomLeft_x() const { return p3.x(); @@ -603,6 +666,10 @@ void QFxSquish::setbottomLeft_y(qreal v) update(); } +/*! + \qmlproperty real Squish::bottomRightX + \qmlproperty real Squish::bottomRightY +*/ qreal QFxSquish::bottomRight_x() const { return p4.x(); @@ -628,7 +695,7 @@ void QFxSquish::setbottomRight_y(qreal v) void QFxSquish::update() { QFxItem *item = qobject_cast<QFxItem *>(parent()); - if(item) + if (item) item->updateTransform(); } @@ -647,10 +714,11 @@ QMatrix4x4 QFxSquish::transform() const QTransform t; QMatrix4x4 rv; - if(QTransform::quadToQuad(poly, poly2, t)) + if (QTransform::quadToQuad(poly, poly2, t)) rv = QMatrix4x4(t); return rv; } -QT_END_NAMESPACE #endif + +QT_END_NAMESPACE |