Revision control

Copy as Markdown

// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
// Qt-Security score:significant reason:default
#include "qtimelineanimationnode_p.h"
QT_BEGIN_NAMESPACE
/*!
\qmltype TimelineAnimationNode
\inherits BlendTreeNode
\nativetype QTimelineAnimationNode
\inqmlmodule QtQuick.Timeline.BlendTrees
\ingroup qtqmltypes
\brief A blend tree source node that plays a timeline animation.
TimelineAnimationNode is a blend tree source node that plays a timeline
animation and outputs the animation's frame data. This node wraps a
TimelineAnimation and its associated Timeline and provides a way to
intercept the animation's frame data and output it to the blend tree.
*/
/*!
\qmlproperty TimelineAnimation TimelineAnimationNode::animation
This property holds the timeline animation to play.
*/
/*!
\qmlproperty Timeline TimelineAnimationNode::timeline
This property holds the timeline that the animation is played on.
*/
/*!
\qmlproperty real TimelineAnimationNode::currentFrame
This property holds the current frame of the animation.
*/
QTimelineAnimationNode::QTimelineAnimationNode(QObject *parent)
: QBlendTreeNode(parent)
{
}
QQuickTimelineAnimation *QTimelineAnimationNode::animation() const
{
return m_animation;
}
void QTimelineAnimationNode::setAnimation(QQuickTimelineAnimation *newAnimation)
{
if (m_animation == newAnimation)
return;
if (m_animation)
disconnect(m_animationDestroyedConnection);
m_animation = newAnimation;
if (m_animation)
m_animationDestroyedConnection = connect(m_animation,
&QObject::destroyed,
this,
[this] {setAnimation(nullptr);});
updateAnimationTarget();
updateFrameData();
Q_EMIT animationChanged();
}
QQuickTimeline *QTimelineAnimationNode::timeline() const
{
return m_timeline;
}
void QTimelineAnimationNode::setTimeline(QQuickTimeline *newTimeline)
{
if (m_timeline == newTimeline)
return;
if (m_timeline)
disconnect(m_timelineDestroyedConnection);
m_timeline = newTimeline;
if (m_timeline)
m_timelineDestroyedConnection = connect(m_timeline,
&QObject::destroyed,
this,
[this] {setTimeline(nullptr);});
updateFrameData();
Q_EMIT timelineChanged();
}
qreal QTimelineAnimationNode::currentFrame() const
{
return m_currentFrame;
}
void QTimelineAnimationNode::setCurrentFrame(qreal newCurrentFrame)
{
if (qFuzzyCompare(m_currentFrame, newCurrentFrame))
return;
m_currentFrame = newCurrentFrame;
updateFrameData();
Q_EMIT currentFrameChanged();
}
static QHash<QQmlProperty, QVariant> getFrameData(QQuickTimeline *timeline, qreal frame)
{
QHash<QQmlProperty, QVariant> frameData;
if (timeline) {
QQmlListReference keyframeGroups(timeline, "keyframeGroups");
if (keyframeGroups.isValid() && keyframeGroups.isReadable()) {
for (int i = 0; i < keyframeGroups.count(); ++i) {
QQuickKeyframeGroup *keyframeGroup = qobject_cast<QQuickKeyframeGroup *>(keyframeGroups.at(i));
if (keyframeGroup && keyframeGroup->target()) {
QQmlProperty qmlProperty(keyframeGroup->target(), keyframeGroup->property());
QVariant value = keyframeGroup->evaluate(frame);
frameData.insert(qmlProperty, value);
}
}
}
}
return frameData;
}
void QTimelineAnimationNode::updateFrameData()
{
if (!m_animation || !m_timeline)
return;
m_frameData = getFrameData(m_timeline, m_currentFrame);
Q_EMIT frameDataChanged();
}
void QTimelineAnimationNode::updateAnimationTarget()
{
if (!m_animation)
return;
// Property should already be set to "currentFrame"
m_animation->setTargetObject(this);
}
QT_END_NAMESPACE