diff options
author | Thomas Hartmann <thomas.hartmann@qt.io> | 2017-11-27 10:17:41 +0100 |
---|---|---|
committer | Thomas Hartmann <thomas.hartmann@qt.io> | 2017-11-29 13:48:22 +0000 |
commit | fe7e09d8ccf6daaf50a8152329960a6bd0157bc8 (patch) | |
tree | 05a6a8671c9d1c97f4c9e81b9405a9d6a58615dc | |
parent | 575402ef399d949ce14ae0235ce126edebfbe29f (diff) |
Initial commit
This implements the timeline module for keyframe based
animations in Qt Quick.
Change-Id: Icf4a4191da7580f670a02ef52e4b0bee4befed18
Reviewed-by: Alessandro Portale <alessandro.portale@qt.io>
Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
-rw-r--r-- | .qmake.conf | 5 | ||||
-rw-r--r-- | src/imports/imports.pro | 3 | ||||
-rw-r--r-- | src/imports/timeline/designer/designer.pri | 2 | ||||
-rw-r--r-- | src/imports/timeline/qmldir | 4 | ||||
-rw-r--r-- | src/imports/timeline/qquickkeyframe.cpp | 320 | ||||
-rw-r--r-- | src/imports/timeline/qquickkeyframe_p.h | 124 | ||||
-rw-r--r-- | src/imports/timeline/qquickkeyframemutator.cpp | 219 | ||||
-rw-r--r-- | src/imports/timeline/qquickkeyframemutator_p.h | 89 | ||||
-rw-r--r-- | src/imports/timeline/qtquicktimelineplugin.cpp | 64 | ||||
-rw-r--r-- | src/imports/timeline/qtquicktimelineplugin.qrc | 4 | ||||
-rw-r--r-- | src/imports/timeline/timeline.pri | 7 | ||||
-rw-r--r-- | src/imports/timeline/timeline.pro | 25 | ||||
-rw-r--r-- | src/src.pro | 3 | ||||
-rw-r--r-- | tests/manual/timelineTestApp/main.cpp | 32 | ||||
-rw-r--r-- | tests/manual/timelineTestApp/main.qml | 65 | ||||
-rw-r--r-- | tests/manual/timelineTestApp/qml.qrc | 8 | ||||
-rw-r--r-- | tests/manual/timelineTestApp/test01.qml | 137 | ||||
-rw-r--r-- | tests/manual/timelineTestApp/test02.qml | 237 | ||||
-rw-r--r-- | tests/manual/timelineTestApp/test03.qml | 103 | ||||
-rw-r--r-- | tests/manual/timelineTestApp/timelineTestApp.pro | 6 | ||||
-rw-r--r-- | timeline.pro | 2 |
21 files changed, 1459 insertions, 0 deletions
diff --git a/.qmake.conf b/.qmake.conf new file mode 100644 index 0000000..168dab9 --- /dev/null +++ b/.qmake.conf @@ -0,0 +1,5 @@ +load(qt_build_config) +CONFIG += warning_clean +DEFINES += QT_NO_FOREACH + +MODULE_VERSION = 5.10.0 diff --git a/src/imports/imports.pro b/src/imports/imports.pro new file mode 100644 index 0000000..9dca5d7 --- /dev/null +++ b/src/imports/imports.pro @@ -0,0 +1,3 @@ +TEMPLATE = subdirs +SUBDIRS += \ + timeline diff --git a/src/imports/timeline/designer/designer.pri b/src/imports/timeline/designer/designer.pri new file mode 100644 index 0000000..0c5d5b6 --- /dev/null +++ b/src/imports/timeline/designer/designer.pri @@ -0,0 +1,2 @@ +QML_FILES += \ + $$PWD/images/*.png diff --git a/src/imports/timeline/qmldir b/src/imports/timeline/qmldir new file mode 100644 index 0000000..b7daa69 --- /dev/null +++ b/src/imports/timeline/qmldir @@ -0,0 +1,4 @@ +module QtQuick.Timeline +plugin qtquicktimelineplugin +classname QtQuickTimelinePlugin +designersupported 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 + + diff --git a/src/imports/timeline/qquickkeyframe_p.h b/src/imports/timeline/qquickkeyframe_p.h new file mode 100644 index 0000000..fec1493 --- /dev/null +++ b/src/imports/timeline/qquickkeyframe_p.h @@ -0,0 +1,124 @@ +/**************************************************************************** +** +** 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 +** +****************************************************************************/ + +#ifndef QQUICKKEYFRAME_P_H +#define QQUICKKEYFRAME_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtCore/QObject> +#include <QtCore/qeasingcurve.h> + +#include <QtQml/qqml.h> + +QT_BEGIN_NAMESPACE + +class QQuickKeyframesPrivate; +class QQuickKeyframePrivate; +class QQuickNumberKeyframePrivate; + +class QQuickKeyframe : public QObject +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QQuickKeyframe) + + Q_PROPERTY(qreal frame READ frame WRITE setFrame NOTIFY frameChanged) + Q_PROPERTY(QEasingCurve easing READ easing WRITE setEasing NOTIFY easingCurveChanged) + Q_PROPERTY(QVariant value READ value WRITE setValue NOTIFY valueChanged) + +public: + explicit QQuickKeyframe(QObject *parent = nullptr); + + qreal frame() const; + void setFrame(qreal); + void reset(); + + QEasingCurve easing() const; + void setEasing(const QEasingCurve &); + + QVariant value() const; + void setValue(QVariant); + + virtual QVariant evaluate(QQuickKeyframe *pre, qreal frame, int userType) const; + +protected: + QQuickKeyframe(QQuickKeyframePrivate &dd, QObject *parent); + +Q_SIGNALS: + void frameChanged(); + void easingCurveChanged(); + void valueChanged(); +}; + +class QQuickKeyframes : public QObject, public QQmlParserStatus +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QQuickKeyframes) + + Q_INTERFACES(QQmlParserStatus) + + Q_PROPERTY(QObject *target READ target WRITE setTargetObject NOTIFY targetChanged) + Q_PROPERTY(QString property READ property WRITE setProperty NOTIFY propertyChanged) + Q_PROPERTY(QQmlListProperty<QQuickKeyframe> keyframes READ keyframes) + + Q_CLASSINFO("DefaultProperty", "keyframes") + +public: + explicit QQuickKeyframes(QObject *parent = nullptr); + + QQmlListProperty<QQuickKeyframe> keyframes(); + + QObject *target() const; + void setTargetObject(QObject *); + + QString property() const; + void setProperty(const QString &); + + QVariant evaluate(qreal frame) const; + + void setProperty(qreal frame); + + void init(); + + void resetDefaultValue(); + + void reset(); + +protected: + void setupKeyframes(); + + void classBegin() override; + void componentComplete() override; + +Q_SIGNALS: + void targetChanged(); + void propertyChanged(); +}; + +QT_END_NAMESPACE + +#endif // QQUICKKEYFRAME_P_H diff --git a/src/imports/timeline/qquickkeyframemutator.cpp b/src/imports/timeline/qquickkeyframemutator.cpp new file mode 100644 index 0000000..ab4b593 --- /dev/null +++ b/src/imports/timeline/qquickkeyframemutator.cpp @@ -0,0 +1,219 @@ +/**************************************************************************** +** +** 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 "qquickkeyframemutator_p.h" + +#include <QtCore/qmath.h> +#include <QtGui/qpainter.h> +#include <QtQuick/private/qquickitem_p.h> + +QT_BEGIN_NAMESPACE + +class QQuickKeyframeMutatorPrivate : public QObjectPrivate +{ + Q_DECLARE_PUBLIC(QQuickKeyframeMutator) +public: + QQuickKeyframeMutatorPrivate() + : startFrame(0), + endFrame(0), + currentFrame(0), + enabled(false), + componentComplete(true) + { + } + + qreal startFrame; + qreal endFrame; + qreal currentFrame; + + bool enabled:1; + bool componentComplete:1; + +protected: + void init(); + void disable(); + + static void append_keyframe(QQmlListProperty<QQuickKeyframes> *list, QQuickKeyframes *a); + static int keyframe_count(QQmlListProperty<QQuickKeyframes> *list); + static QQuickKeyframes* keyframe_at(QQmlListProperty<QQuickKeyframes> *list, int pos); + static void clear_keyframes(QQmlListProperty<QQuickKeyframes> *list); + + QList<QQuickKeyframes *> keyframes; +}; + +void QQuickKeyframeMutatorPrivate::init() +{ + for (auto keyFrames : keyframes) { + keyFrames->init(); + keyFrames->setProperty(currentFrame); + } +} + +void QQuickKeyframeMutatorPrivate::disable() +{ + for (auto keyFrames : keyframes) + keyFrames->resetDefaultValue(); +} + +void QQuickKeyframeMutatorPrivate::append_keyframe(QQmlListProperty<QQuickKeyframes> *list, QQuickKeyframes *a) +{ + QQuickKeyframeMutator *q = static_cast<QQuickKeyframeMutator *>(list->object); + q->d_func()->keyframes.append(a); +} + +int QQuickKeyframeMutatorPrivate::keyframe_count(QQmlListProperty<QQuickKeyframes> *list) +{ + QQuickKeyframeMutator *q = static_cast<QQuickKeyframeMutator *>(list->object); + return q->d_func()->keyframes.count(); +} + +QQuickKeyframes* QQuickKeyframeMutatorPrivate::keyframe_at(QQmlListProperty<QQuickKeyframes> *list, int pos) +{ + QQuickKeyframeMutator *q = static_cast<QQuickKeyframeMutator *>(list->object); + return q->d_func()->keyframes.at(pos); +} + +void QQuickKeyframeMutatorPrivate::clear_keyframes(QQmlListProperty<QQuickKeyframes> *list) +{ + QQuickKeyframeMutator *q = static_cast<QQuickKeyframeMutator *>(list->object); + while (q->d_func()->keyframes.count()) { + QQuickKeyframes *firstKeyframe = q->d_func()->keyframes.at(0); + q->d_func()->keyframes.removeAll(firstKeyframe); + } +} + +QQuickKeyframeMutator::QQuickKeyframeMutator(QObject *parent) : QObject(*(new QQuickKeyframeMutatorPrivate), parent) +{ + +} + +QQmlListProperty<QQuickKeyframes> QQuickKeyframeMutator::keyframes() +{ + Q_D(QQuickKeyframeMutator); + + return QQmlListProperty<QQuickKeyframes>(this, &d->keyframes, QQuickKeyframeMutatorPrivate::append_keyframe, + QQuickKeyframeMutatorPrivate::keyframe_count, + QQuickKeyframeMutatorPrivate::keyframe_at, + QQuickKeyframeMutatorPrivate::clear_keyframes); +} + +bool QQuickKeyframeMutator::enabled() const +{ + Q_D(const QQuickKeyframeMutator); + return d->enabled; +} + +void QQuickKeyframeMutator::setEnabled(bool b) +{ + Q_D(QQuickKeyframeMutator); + if (d->enabled == b) + return; + d->enabled = b; + + if (d->componentComplete) { + if (b) + init(); + else + reset(); + } + + emit enabledChanged(); +} + +qreal QQuickKeyframeMutator::startFrame() const +{ + Q_D(const QQuickKeyframeMutator); + return d->startFrame; +} + +void QQuickKeyframeMutator::setStartFrame(qreal frame) +{ + Q_D(QQuickKeyframeMutator); + if (d->startFrame == frame) + return; + d->startFrame = frame; + emit startFrameChanged(); +} + +qreal QQuickKeyframeMutator::endFrame() const +{ + Q_D(const QQuickKeyframeMutator); + return d->endFrame; +} + +void QQuickKeyframeMutator::setEndFrame(qreal frame) +{ + Q_D(QQuickKeyframeMutator); + if (d->endFrame == frame) + return; + d->endFrame = frame; + emit endFrameChanged(); +} + +qreal QQuickKeyframeMutator::currentFrame() const +{ + Q_D(const QQuickKeyframeMutator); + return d->currentFrame; +} + +void QQuickKeyframeMutator::setCurrentFrame(qreal frame) +{ + Q_D(QQuickKeyframeMutator); + if (d->currentFrame == frame) + return; + d->currentFrame = frame; + + if (d->componentComplete && d->enabled) + for (auto keyFrames : d->keyframes) + keyFrames->setProperty(d->currentFrame); + + emit currentFrameChanged(); +} + +void QQuickKeyframeMutator::init() +{ + Q_D(QQuickKeyframeMutator); + + if (d->componentComplete) + d->init(); +} + +void QQuickKeyframeMutator::reset() +{ + Q_D(QQuickKeyframeMutator); + + if (d->componentComplete) + d->disable(); +} + +void QQuickKeyframeMutator::classBegin() +{ + Q_D(QQuickKeyframeMutator); + d->componentComplete = false; +} + +void QQuickKeyframeMutator::componentComplete() +{ + Q_D(QQuickKeyframeMutator); + d->componentComplete = true; + + if (d->enabled) + init(); +} + +QT_END_NAMESPACE diff --git a/src/imports/timeline/qquickkeyframemutator_p.h b/src/imports/timeline/qquickkeyframemutator_p.h new file mode 100644 index 0000000..8cba93a --- /dev/null +++ b/src/imports/timeline/qquickkeyframemutator_p.h @@ -0,0 +1,89 @@ +/**************************************************************************** +** +** 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 +** +****************************************************************************/ + +#ifndef QQUICKKEYFRAMEMUTATOR_P_H +#define QQUICKKEYFRAMEMUTATOR_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qquickkeyframe_p.h" + +#include <QtQml/qqml.h> + +QT_BEGIN_NAMESPACE + +class QQuickKeyframeMutatorPrivate; + +class QQuickKeyframeMutator : public QObject, public QQmlParserStatus +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QQuickKeyframeMutator) + + Q_INTERFACES(QQmlParserStatus) + + Q_PROPERTY(qreal startFrame READ startFrame WRITE setStartFrame NOTIFY startFrameChanged) + Q_PROPERTY(qreal endFrame READ endFrame WRITE setEndFrame NOTIFY endFrameChanged) + Q_PROPERTY(qreal currentFrame READ currentFrame WRITE setCurrentFrame NOTIFY currentFrameChanged) + Q_PROPERTY(QQmlListProperty<QQuickKeyframes> keyframes READ keyframes) + Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged) + + Q_CLASSINFO("DefaultProperty", "keyframes") + +public: + explicit QQuickKeyframeMutator(QObject *parent = nullptr); + + QQmlListProperty<QQuickKeyframes> keyframes(); + + bool enabled() const; + void setEnabled(bool enabled); + + qreal startFrame() const; + void setStartFrame(qreal); + + qreal endFrame() const; + void setEndFrame(qreal); + + qreal currentFrame() const; + void setCurrentFrame(qreal); + + void init(); + void reset(); + +protected: + void classBegin() override; + void componentComplete() override; + +Q_SIGNALS: + void enabledChanged(); + void startFrameChanged(); + void endFrameChanged(); + void currentFrameChanged(); +}; + +QT_END_NAMESPACE + +#endif // QQUICKKEYFRAMEMUTATOR_P_H diff --git a/src/imports/timeline/qtquicktimelineplugin.cpp b/src/imports/timeline/qtquicktimelineplugin.cpp new file mode 100644 index 0000000..2a69ddf --- /dev/null +++ b/src/imports/timeline/qtquicktimelineplugin.cpp @@ -0,0 +1,64 @@ +/**************************************************************************** +** +** 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 <QtQml/qqmlextensionplugin.h> + +#include "qquickkeyframemutator_p.h" +#include "qquickkeyframe_p.h" + +static inline void initResources() +{ + Q_INIT_RESOURCE(qtquicktimelineplugin); +#ifdef QT_STATIC + Q_INIT_RESOURCE(qmake_QtQuick_Controls_2); +#endif +} + +QT_BEGIN_NAMESPACE + +class QtQuickTimelinePlugin: public QQmlExtensionPlugin +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid) + +public: + QtQuickTimelinePlugin(QObject *parent = nullptr); + void registerTypes(const char *uri) override; + void initializeEngine(QQmlEngine *engine, const char *uri) override; +}; + +QtQuickTimelinePlugin::QtQuickTimelinePlugin(QObject *parent) : QQmlExtensionPlugin(parent) +{ + initResources(); +} + +void QtQuickTimelinePlugin::registerTypes(const char *uri) +{ + qmlRegisterType<QQuickKeyframeMutator>(uri, 1, 0, "KeyframeMutator"); + qmlRegisterType<QQuickKeyframe>(uri, 1, 0, "Keyframe"); + qmlRegisterType<QQuickKeyframes>(uri, 1, 0, "Keyframes"); +} + +void QtQuickTimelinePlugin::initializeEngine(QQmlEngine *engine, const char *uri) +{ + QQmlExtensionPlugin::initializeEngine(engine, uri); +} + +QT_END_NAMESPACE + +#include "qtquicktimelineplugin.moc" diff --git a/src/imports/timeline/qtquicktimelineplugin.qrc b/src/imports/timeline/qtquicktimelineplugin.qrc new file mode 100644 index 0000000..f34aa6c --- /dev/null +++ b/src/imports/timeline/qtquicktimelineplugin.qrc @@ -0,0 +1,4 @@ +<RCC> + <qresource prefix="/qt-project.org/imports/QtQuick/Timeline"> + </qresource> +</RCC> diff --git a/src/imports/timeline/timeline.pri b/src/imports/timeline/timeline.pri new file mode 100644 index 0000000..df73d4e --- /dev/null +++ b/src/imports/timeline/timeline.pri @@ -0,0 +1,7 @@ +HEADERS += \ + $$PWD/qquickkeyframemutator_p.h \ + $$PWD/qquickkeyframe_p.h + +SOURCES += \ + $$PWD/qquickkeyframemutator.cpp \ + $$PWD/qquickkeyframe.cpp diff --git a/src/imports/timeline/timeline.pro b/src/imports/timeline/timeline.pro new file mode 100644 index 0000000..26e5e2f --- /dev/null +++ b/src/imports/timeline/timeline.pro @@ -0,0 +1,25 @@ +TARGET = qtquicktimelineplugin +TARGETPATH = QtQuick/Timeline +IMPORT_VERSION = 1.0 + +QT += qml quick core-private + +QT_PRIVATE += core-private gui-private qml-private quick-private + +DEFINES += QT_NO_CAST_TO_ASCII QT_NO_CAST_FROM_ASCII + +include(timeline.pri) + +DISTFILES += \ + qmldir + +SOURCES += \ + $$PWD/qtquicktimelineplugin.cpp + +RESOURCES += \ + $$PWD/qtquicktimelineplugin.qrc + +!static: qtConfig(quick-designer): include(designer/designer.pri) + +CONFIG += no_cxx_module +load(qml_plugin) diff --git a/src/src.pro b/src/src.pro new file mode 100644 index 0000000..5377565 --- /dev/null +++ b/src/src.pro @@ -0,0 +1,3 @@ +TEMPLATE = subdirs +SUBDIRS += \ + imports diff --git a/tests/manual/timelineTestApp/main.cpp b/tests/manual/timelineTestApp/main.cpp new file mode 100644 index 0000000..405b8a9 --- /dev/null +++ b/tests/manual/timelineTestApp/main.cpp @@ -0,0 +1,32 @@ +/**************************************************************************** +** +** 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 <QGuiApplication> +#include <QQmlApplicationEngine> + +int main(int argc, char *argv[]) +{ + QGuiApplication app(argc, argv); + + QQmlApplicationEngine engine; + engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); + if (engine.rootObjects().isEmpty()) + return -1; + + return app.exec(); +} diff --git a/tests/manual/timelineTestApp/main.qml b/tests/manual/timelineTestApp/main.qml new file mode 100644 index 0000000..8b43d52 --- /dev/null +++ b/tests/manual/timelineTestApp/main.qml @@ -0,0 +1,65 @@ +/**************************************************************************** +** +** 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 +** +****************************************************************************/ + +import QtQuick 2.6 +import QtQuick.Window 2.2 +import QtQuick.Timeline 1.0 + +Window { + visible: true + width: 640 + height: 480 + title: qsTr("Hello World") + + Loader { + id: loader + anchors.fill: parent + } + + Row { + x: 8 + y: 457 + + Text { + text: "Test 01" + font.pixelSize: 12 + MouseArea { + anchors.fill: parent + onClicked: loader.source = "test01.qml" + } + } + + Text { + text: "Test 02" + font.pixelSize: 12 + MouseArea { + anchors.fill: parent + onClicked: loader.source = "test02.qml" + } + } + + Text { + text: "Test 03" + font.pixelSize: 12 + MouseArea { + anchors.fill: parent + onClicked: loader.source = "test03.qml" + } + } + } +} diff --git a/tests/manual/timelineTestApp/qml.qrc b/tests/manual/timelineTestApp/qml.qrc new file mode 100644 index 0000000..4da9ddc --- /dev/null +++ b/tests/manual/timelineTestApp/qml.qrc @@ -0,0 +1,8 @@ +<RCC> + <qresource prefix="/"> + <file>main.qml</file> + <file>test01.qml</file> + <file>test02.qml</file> + <file>test03.qml</file> + </qresource> +</RCC> diff --git a/tests/manual/timelineTestApp/test01.qml b/tests/manual/timelineTestApp/test01.qml new file mode 100644 index 0000000..95af21d --- /dev/null +++ b/tests/manual/timelineTestApp/test01.qml @@ -0,0 +1,137 @@ +/**************************************************************************** +** +** 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 +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.Timeline 1.0 + +Item { + Rectangle { + width: 40 + height: 40 + color: "blue" + MouseArea { + anchors.fill: parent + onClicked: mutator.enabled = !mutator.enabled + } + } + + Rectangle { + x: 80 + width: 40 + height: 40 + color: "blue" + MouseArea { + anchors.fill: parent + onClicked: animation.start() + } + } + + NumberAnimation { + id: animation + target: mutator + property: "currentFrame" + easing.type: Easing.InOutQuad + duration: 2000 + from: 0 + to: 100 + running: true + } + + Item { + width: 480 + height: 480 + + KeyframeMutator { + id: mutator + + startFrame: 0 + endFrame: 100 + currentFrame: 50 + + enabled: true + + Keyframes { + target: rectangle + property: "x" + + Keyframe { + frame: 0 + value: 0 + } + + Keyframe { + frame: 50 + value: 100 + } + + Keyframe { + frame: 100 + value: 200 + } + } + + Keyframes { + target: rectangle + property: "y" + + Keyframe { + frame: 0 + value: 0 + } + + Keyframe { + frame: 50 + value: 100 + easing.type: Easing.InBounce + } + + Keyframe { + frame: 100 + value: 200 + } + } + + Keyframes { + target: rectangle + property: "color" + + Keyframe { + frame: 0 + value: "red" + } + + Keyframe { + frame: 50 + value: "blue" + } + + Keyframe { + frame: 100 + value: "yellow" + } + } + } + + Rectangle { + id: rectangle + width: 20 + height: 20 + color: "red" + } + } +} diff --git a/tests/manual/timelineTestApp/test02.qml b/tests/manual/timelineTestApp/test02.qml new file mode 100644 index 0000000..449b69e --- /dev/null +++ b/tests/manual/timelineTestApp/test02.qml @@ -0,0 +1,237 @@ +/**************************************************************************** +** +** 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 +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.Timeline 1.0 + +Item { + PropertyAnimation { + running: true + duration: 1000 + target: mutator + property: "currentFrame" + from: 0 + to: 1000 + } + + Rectangle { + id: leftGauge + x: 20 + y: 140 + width: 200 + height: 200 + color: "#969696" + radius: width / 2 + + Rectangle { + x: 5 + y: 5 + width: 190 + height: 190 + color: "#0d0d0d" + radius: width /2 + } + } + + Rectangle { + id: rightGauge + x: 420 + y: 140 + width: 200 + height: 200 + color: "#969696" + radius: width / 2 + Rectangle { + x: 5 + y: 5 + width: 190 + height: 190 + color: "#0d0d0d" + radius: width /2 + } + } + + Rectangle { + id: bottomPane + x: 81 + y: 424 + width: 478 + height: 48 + color: "#242424" + } + + KeyframeMutator { + id: mutator + enabled: true + + startFrame: 0 + endFrame: 1000 + + Keyframes { + target: leftGauge + property: "x" + Keyframe { + frame: 0 + value: -200 + } + Keyframe { + frame: 500 + value: 0 + easing.type: Easing.InQuad + } + + Keyframe { + frame: 1000 + value: 20 + easing.type: Easing.OutQuad + } + } + Keyframes { + target: leftGauge + property: "y" + Keyframe { + frame: 0 + value: 280 + } + + Keyframe { + frame: 500 + value: 226 + easing.type: Easing.InQuad + } + Keyframe { + frame: 1000 + value: 140 + easing.type: Easing.OutQuad + } + } + Keyframes { + target: leftGauge + property: "opacity" + Keyframe { + frame: 0 + value: 0 + } + Keyframe { + frame: 500 + value: 0.2 + easing.type: Easing.InQuad + } + Keyframe { + frame: 1000 + value: 1 + easing.type: Easing.OutQuad + } + } + + Keyframes { + target: rightGauge + property: "x" + Keyframe { + frame: 0 + value: 639 + } + Keyframe { + frame: 500 + value: 440 + easing.type: Easing.InQuad + } + Keyframe { + frame: 1000 + value: 420 + easing.type: Easing.OutQuad + } + } + Keyframes { + target: rightGauge + property: "y" + Keyframe { + frame: 0 + value: 280 + } + Keyframe { + frame: 500 + value: 226 + easing.type: Easing.InQuad + } + Keyframe { + frame: 1000 + value: 140 + easing.type: Easing.OutQuad + } + } + Keyframes { + target: rightGauge + property: "opacity" + Keyframe { + frame: 0 + value: 0.0 + } + Keyframe { + frame: 500 + value: 0.2 + easing.type: Easing.InQuad + } + Keyframe { + frame: 1000 + value: 1.0 + easing.type: Easing.OutQuad + } + } + + Keyframes { + target: bottomPane + property: "y" + + Keyframe { + frame: 0 + value: 502 + } + Keyframe { + frame: 500 + value: 432 + easing.type: Easing.InQuad + } + + Keyframe { + frame: 1000 + value: 424 + easing.type: Easing.OutQuad + } + } + Keyframes { + target: bottomPane + property: "opacity" + Keyframe { + frame: 0 + value: 0 + } + Keyframe { + frame: 500 + value: 0.7 + easing.type: Easing.InQuad + } + Keyframe { + frame: 1000 + value: 1 + easing.type: Easing.OutQuad + } + } + } + +} diff --git a/tests/manual/timelineTestApp/test03.qml b/tests/manual/timelineTestApp/test03.qml new file mode 100644 index 0000000..19368f8 --- /dev/null +++ b/tests/manual/timelineTestApp/test03.qml @@ -0,0 +1,103 @@ +/**************************************************************************** +** +** 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 +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.Timeline 1.0 + +Item { + id: item1 + + KeyframeMutator { + id: mutator + enabled: true + + startFrame: 0 + endFrame: 200 + currentFrame: input.text + Keyframes { + target: needle + property: "rotation" + Keyframe { + frame: 0 + value: 0 + } + + Keyframe { + frame: 100 + value: 90 + } + Keyframe { + frame: 200 + value: 180 + } + } + + Keyframes { + target: needle + property: "color" + Keyframe { + frame: 0 + value: "blue" + } + + Keyframe { + frame: 100 + value: "green" + } + Keyframe { + frame: 200 + value: "red" + } + } + + } + + Rectangle { + id: rectangle + x: 220 + y: 140 + width: 300 + height: 300 + color: "#000000" + radius: 150 + anchors.horizontalCenter: parent.horizontalCenter + anchors.verticalCenter: parent.verticalCenter + + Rectangle { + id: needle + x: 0 + y: 148 + width: 150 + height: 4 + color: "#c41616" + transformOrigin: Item.Right + } + } + + TextInput { + id: input + x: 207 + y: 392 + width: 227 + height: 65 + text: "10" + anchors.horizontalCenter: parent.horizontalCenter + horizontalAlignment: Text.AlignHCenter + font.pointSize: 14 + } +} diff --git a/tests/manual/timelineTestApp/timelineTestApp.pro b/tests/manual/timelineTestApp/timelineTestApp.pro new file mode 100644 index 0000000..25a916c --- /dev/null +++ b/tests/manual/timelineTestApp/timelineTestApp.pro @@ -0,0 +1,6 @@ +QT += quick +CONFIG += c++11 + +SOURCES += main.cpp + +RESOURCES += qml.qrc diff --git a/timeline.pro b/timeline.pro new file mode 100644 index 0000000..ce6617e --- /dev/null +++ b/timeline.pro @@ -0,0 +1,2 @@ +requires(qtHaveModule(quick)) +load(qt_parts) |