diff options
Diffstat (limited to 'src/imports/timeline/qquickkeyframe.cpp')
-rw-r--r-- | src/imports/timeline/qquickkeyframe.cpp | 320 |
1 files changed, 320 insertions, 0 deletions
diff --git a/src/imports/timeline/qquickkeyframe.cpp b/src/imports/timeline/qquickkeyframe.cpp new file mode 100644 index 0000000..3e3dbb3 --- /dev/null +++ b/src/imports/timeline/qquickkeyframe.cpp @@ -0,0 +1,320 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd +** All rights reserved. +** For any questions to The Qt Company, please use contact form at http://www.qt.io/contact-us +** +** This file is part of the Qt Enterprise Qt Quick Timeline Add-on. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. +** +** If you have questions regarding the use of this file, please use +** contact form at http://www.qt.io/contact-us +** +****************************************************************************/ + +#include "qquickkeyframe_p.h" + +#include "qquickkeyframemutator_p.h" + +#include <QtCore/QVariantAnimation> +#include <QtCore/qmath.h> +#include <QtGui/qpainter.h> +#include <QtQuick/private/qquickitem_p.h> +#include <QtQml/QQmlProperty> + +#include <private/qvariantanimation_p.h> + +#include <algorithm> + +QT_BEGIN_NAMESPACE + +class QQuickKeyframesPrivate : public QObjectPrivate +{ + Q_DECLARE_PUBLIC(QQuickKeyframes) +public: + QQuickKeyframesPrivate() + : target(nullptr), + componentComplete(false) + { + } + + QObject *target; + QString propertyName; + bool componentComplete; + +protected: + void setupKeyframes(); + + static void append_keyframe(QQmlListProperty<QQuickKeyframe> *list, QQuickKeyframe *a); + static int keyframe_count(QQmlListProperty<QQuickKeyframe> *list); + static QQuickKeyframe* keyframe_at(QQmlListProperty<QQuickKeyframe> *list, int pos); + static void clear_keyframes(QQmlListProperty<QQuickKeyframe> *list); + + QList<QQuickKeyframe *> keyframes; + QList<QQuickKeyframe *> sortedKeyframes; + + QVariant originalValue; +}; + +void QQuickKeyframesPrivate::setupKeyframes() +{ + sortedKeyframes = keyframes; + std::sort(sortedKeyframes.begin(), sortedKeyframes.end(), [](const QQuickKeyframe *first, const QQuickKeyframe *second) { + return first->frame() < second->frame(); + }); +} + +void QQuickKeyframesPrivate::append_keyframe(QQmlListProperty<QQuickKeyframe> *list, QQuickKeyframe *a) +{ + QQuickKeyframes *q = static_cast<QQuickKeyframes *>(list->object); + q->d_func()->keyframes.append(a); + q->d_func()->setupKeyframes(); + q->reset(); +} + +int QQuickKeyframesPrivate::keyframe_count(QQmlListProperty<QQuickKeyframe> *list) +{ + QQuickKeyframes *q = static_cast<QQuickKeyframes *>(list->object); + return q->d_func()->keyframes.count(); +} + +QQuickKeyframe* QQuickKeyframesPrivate::keyframe_at(QQmlListProperty<QQuickKeyframe> *list, int pos) +{ + QQuickKeyframes *q = static_cast<QQuickKeyframes *>(list->object); + return q->d_func()->keyframes.at(pos); +} + +void QQuickKeyframesPrivate::clear_keyframes(QQmlListProperty<QQuickKeyframe> *list) +{ + QQuickKeyframes *q = static_cast<QQuickKeyframes *>(list->object); + while (q->d_func()->keyframes.count()) { + QQuickKeyframe *firstKeyframe = q->d_func()->keyframes.at(0); + q->d_func()->keyframes.removeAll(firstKeyframe); + } +} + +class QQuickKeyframePrivate : public QObjectPrivate +{ + Q_DECLARE_PUBLIC(QQuickKeyframe) +public: + QQuickKeyframePrivate() + : frame(0) + { + } + + qreal frame; + QEasingCurve easingCurve; + QVariant value; +}; + +QQuickKeyframe::QQuickKeyframe(QObject *parent) + : QObject(*(new QQuickKeyframePrivate), parent) +{ + +} + +qreal QQuickKeyframe::frame() const +{ + Q_D(const QQuickKeyframe); + return d->frame; +} + +void QQuickKeyframe::setFrame(qreal f) +{ + Q_D(QQuickKeyframe); + if (d->frame == f) + return; + d->frame = f; + emit frameChanged(); +} + +void QQuickKeyframe::reset() +{ + QQuickKeyframes *keyframes = qobject_cast<QQuickKeyframes*>(parent()); + if (keyframes) + keyframes->reset(); +} + +QQuickKeyframe::QQuickKeyframe(QQuickKeyframePrivate &dd, QObject *parent) + : QObject(dd, parent) +{ + +} + +QQuickKeyframes::QQuickKeyframes(QObject *parent) + : QObject(*(new QQuickKeyframesPrivate), parent) +{ + +} + +QQmlListProperty<QQuickKeyframe> QQuickKeyframes::keyframes() +{ + Q_D(QQuickKeyframes); + + return QQmlListProperty<QQuickKeyframe>(this, &d->keyframes, QQuickKeyframesPrivate::append_keyframe, + QQuickKeyframesPrivate::keyframe_count, + QQuickKeyframesPrivate::keyframe_at, + QQuickKeyframesPrivate::clear_keyframes); +} + +QObject *QQuickKeyframes::target() const +{ + Q_D(const QQuickKeyframes); + return d->target; +} + +void QQuickKeyframes::setTargetObject(QObject *o) +{ + Q_D(QQuickKeyframes); + if (d->target == o) + return; + d->target = o; + emit targetChanged(); +} + +QString QQuickKeyframes::property() const +{ + Q_D(const QQuickKeyframes); + return d->propertyName; +} + +void QQuickKeyframes::setProperty(const QString &n) +{ + Q_D(QQuickKeyframes); + if (d->propertyName == n) + return; + d->propertyName = n; + emit propertyChanged(); +} + +QVariant QQuickKeyframes::evaluate(qreal frame) const +{ + Q_D(const QQuickKeyframes); + + if (d->sortedKeyframes.isEmpty()) + return QVariant(); + + QQuickKeyframe *lastFrame = nullptr; + + for (auto keyFrame : qAsConst(d->sortedKeyframes)) { + if (frame <= keyFrame->frame()) + return keyFrame->evaluate(lastFrame, frame, QQmlProperty(target(), property()).property().userType()); + lastFrame = keyFrame; + } + + return QVariant(); +} + +void QQuickKeyframes::setProperty(qreal frame) +{ + QQmlProperty property(target(), property()); + + property.write(evaluate(frame)); +} + +void QQuickKeyframes::init() +{ + Q_D(QQuickKeyframes); + d->originalValue = QQmlProperty::read(target(), property()); +} + +void QQuickKeyframes::resetDefaultValue() +{ + Q_D(QQuickKeyframes); + QQmlProperty::write(target(), property(), d->originalValue); +} + +void QQuickKeyframes::reset() +{ + Q_D(QQuickKeyframes); + if (!d->componentComplete) + return; + + QQuickKeyframeMutator *mutator = qobject_cast<QQuickKeyframeMutator*>(parent()); + if (mutator) + setProperty(mutator->currentFrame()); +} + +void QQuickKeyframes::setupKeyframes() +{ + Q_D(QQuickKeyframes); + + if (d->componentComplete) + d->setupKeyframes(); +} + +void QQuickKeyframes::classBegin() +{ + Q_D(QQuickKeyframes); + d->componentComplete = false; +} + +void QQuickKeyframes::componentComplete() +{ + Q_D(QQuickKeyframes); + d->componentComplete = true; + setupKeyframes(); +} + +QEasingCurve QQuickKeyframe::easing() const +{ + Q_D(const QQuickKeyframe); + return d->easingCurve; +} + +void QQuickKeyframe::setEasing(const QEasingCurve &e) +{ + Q_D(QQuickKeyframe); + if (d->easingCurve == e) + return; + + d->easingCurve = e; + emit easingCurveChanged(); +} + +QVariant QQuickKeyframe::value() const +{ + Q_D(const QQuickKeyframe); + return d->value; +} + +void QQuickKeyframe::setValue(QVariant v) +{ + Q_D(QQuickKeyframe); + if (d->value == v) + return; + d->value = v; + + reset(); + + emit valueChanged(); +} + +QVariant QQuickKeyframe::evaluate(QQuickKeyframe *pre, qreal frametime, int userType) const +{ + QVariantAnimation::Interpolator interpolator = QVariantAnimationPrivate::getInterpolator(userType); + if (!pre) + return value(); + + QVariant preValue = pre->value(); + qreal preFrame = pre->frame(); + + qreal duration = frame() - preFrame; + qreal offset = frametime - preFrame; + + qreal progress = easing().valueForProgress(offset / duration); + + preValue.convert(userType); + QVariant convertedValue = value(); + convertedValue.convert(userType); + + return interpolator(preValue.constData(), convertedValue.constData(), progress); +} + +QT_END_NAMESPACE + + |