10#include <private/qquickitem_p.h>
11#if QT_CONFIG(quick_shadereffect)
12#include <private/qquickshadereffect_p.h>
14#include <private/qanimationgroupjob_p.h>
16#include <qcoreapplication.h>
42 if (--helper
->ref == 0) {
43 store.remove(helper->item);
51QQuickAnimatorProxyJob::QQuickAnimatorProxyJob(QAbstractAnimationJob *job,
52 QQuickAbstractAnimation *animation)
53 : m_controller(
nullptr)
54 , m_internalState(State_Stopped)
58 m_isRenderThreadProxy =
true;
60 setLoopCount(job->loopCount());
71 QObject *ctx = findAnimationContext(animation);
73 qWarning(
"QtQuick: unable to find animation context for RT animation...");
77 QQuickWindow *window = qobject_cast<QQuickWindow *>(ctx);
81 QQuickItem *item = qobject_cast<QQuickItem *>(ctx);
83 setWindow(item->window());
84 connect(item, &QQuickItem::windowChanged,
this, &QQuickAnimatorProxyJob::windowChanged);
88void QQuickAnimatorProxyJob::updateLoopCount(
int loopCount)
90 m_job->setLoopCount(loopCount);
93QQuickAnimatorProxyJob::~QQuickAnimatorProxyJob()
95 if (m_job && m_controller)
96 m_controller->cancel(m_job);
100QObject *QQuickAnimatorProxyJob::findAnimationContext(QQuickAbstractAnimation *a)
102 QObject *p = a->parent();
103 while (p !=
nullptr && qobject_cast<QQuickWindow *>(p) ==
nullptr && qobject_cast<QQuickItem *>(p) ==
nullptr)
108void QQuickAnimatorProxyJob::updateCurrentTime(
int)
110 if (m_internalState != State_Running)
115 m_currentLoop = m_job->currentLoop();
120 Q_ASSERT(m_controller);
132 if (!m_controller->isPendingStart(m_job)
133 && !m_job->isRunning()) {
138void QQuickAnimatorProxyJob::updateState(QAbstractAnimationJob::State newState, QAbstractAnimationJob::State)
140 if (m_state == Running) {
141 m_internalState = State_Starting;
143 m_internalState = State_Running;
144 m_controller->start(m_job);
147 }
else if (newState == Stopped) {
148 m_internalState = State_Stopped;
150 syncBackCurrentValues();
151 m_controller->cancel(m_job);
156void QQuickAnimatorProxyJob::debugAnimation(QDebug d)
const
158 d <<
"QuickAnimatorProxyJob("<< Qt::hex << (
const void *)
this << Qt::dec
159 <<
"state:" << state() <<
"duration:" << duration()
160 <<
"proxying: (" << job() <<
')';
163void QQuickAnimatorProxyJob::windowChanged(QQuickWindow *window)
168void QQuickAnimatorProxyJob::setWindow(QQuickWindow *window)
171 if (m_job && m_controller) {
172 disconnect(m_controller->window(), &QQuickWindow::sceneGraphInitialized,
173 this, &QQuickAnimatorProxyJob::sceneGraphInitialized);
174 m_controller->cancel(m_job);
177 m_controller =
nullptr;
180 }
else if (!m_controller && m_job) {
181 m_controller = QQuickWindowPrivate::get(window)->animationController.get();
182 if (window->isSceneGraphInitialized())
185 connect(window, &QQuickWindow::sceneGraphInitialized,
this, &QQuickAnimatorProxyJob::sceneGraphInitialized);
189void QQuickAnimatorProxyJob::sceneGraphInitialized()
192 disconnect(m_controller->window(), &QQuickWindow::sceneGraphInitialized,
this, &QQuickAnimatorProxyJob::sceneGraphInitialized);
197void QQuickAnimatorProxyJob::readyToAnimate()
199 Q_ASSERT(m_controller);
200 if (m_internalState == State_Starting) {
201 m_internalState = State_Running;
202 m_controller->start(m_job);
208 if (job->isRenderThreadJob()) {
209 static_cast<QQuickAnimatorJob *>(job)->writeBack();
211 }
else if (job->isGroup()) {
212 QAnimationGroupJob *g =
static_cast<QAnimationGroupJob *>(job);
213 for (QAbstractAnimationJob *a : *g->children())
214 qquick_syncback_helper(a);
219void QQuickAnimatorProxyJob::syncBackCurrentValues()
222 qquick_syncback_helper(m_job.data());
225QQuickAnimatorJob::QQuickAnimatorJob()
227 , m_controller(
nullptr)
232 , m_isTransform(
false)
235 m_isRenderThreadJob =
true;
238void QQuickAnimatorJob::debugAnimation(QDebug d)
const
240 d <<
"QuickAnimatorJob(" << Qt::hex << (
const void *)
this << Qt::dec
241 <<
") state:" << state() <<
"duration:" << duration()
242 <<
"target:" << m_target <<
"value:" << m_value;
245qreal QQuickAnimatorJob::progress(
int time)
const
247 return m_easing.valueForProgress((m_duration == 0) ? qreal(1) : qreal(time) / qreal(m_duration));
250void QQuickAnimatorJob::boundValue()
252 qreal rangeMin = m_from;
253 qreal rangeMax = m_to;
258 m_value = qBound(rangeMin, m_value, rangeMax);
261qreal QQuickAnimatorJob::value()
const
265 m_controller->lock();
267 m_controller->unlock();
272void QQuickAnimatorJob::setTarget(QQuickItem *target)
277void QQuickAnimatorJob::initialize(QQuickAnimatorController *controller)
279 m_controller = controller;
285 m_isTransform =
true;
291 qquick_transform_animatorjob_helper_store()->release(
m_helper);
299 if (m_helper && m_target)
301 QQuickAnimatorJob::setTarget(item);
307 if (m_helper && (m_helper->item != m_target || !m_target)) {
308 qquick_transform_animatorjob_helper_store()->release(
m_helper);
318 m_helper = qquick_transform_animatorjob_helper_store()->acquire(m_target);
343 const quint32 mask = QQuickItemPrivate::Position
344 | QQuickItemPrivate::BasicTransform
345 | QQuickItemPrivate::TransformOrigin
346 | QQuickItemPrivate::Size;
348 QQuickItemPrivate *d = QQuickItemPrivate::get(item);
349#if QT_CONFIG(quick_shadereffect)
350 if (d->extra.isAllocated()
352 && d->extra->layer->enabled()) {
353 d = QQuickItemPrivate::get(d->extra->layer->m_effectSource);
357 quint32 dirty = mask & d->dirtyAttributes;
365 node = d->itemNode();
370 if (dirty & QQuickItemPrivate::Position) {
375 if (dirty & QQuickItemPrivate::BasicTransform) {
380 if (dirty & (QQuickItemPrivate::TransformOrigin | QQuickItemPrivate::Size)) {
381 QPointF o =
item->transformOriginPoint();
389 if (!wasChanged || !node)
397 m.translate(-
ox, -
oy);
409void QQuickXAnimatorJob::writeBack()
412 m_target->setX(value());
415void QQuickXAnimatorJob::updateCurrentTime(
int time)
420 m_value = m_from + (m_to - m_from) * progress(time);
421 m_helper->dx = m_value;
422 m_helper->wasChanged =
true;
425void QQuickYAnimatorJob::writeBack()
428 m_target->setY(value());
431void QQuickYAnimatorJob::updateCurrentTime(
int time)
436 m_value = m_from + (m_to - m_from) * progress(time);
437 m_helper->dy = m_value;
438 m_helper->wasChanged =
true;
441void QQuickScaleAnimatorJob::writeBack()
444 m_target->setScale(value());
447void QQuickScaleAnimatorJob::updateCurrentTime(
int time)
452 m_value = m_from + (m_to - m_from) * progress(time);
453 m_helper->scale = m_value;
454 m_helper->wasChanged =
true;
458QQuickRotationAnimatorJob::QQuickRotationAnimatorJob()
459 : m_direction(QQuickRotationAnimator::Numerical)
467void QQuickRotationAnimatorJob::updateCurrentTime(
int time)
472 float t = progress(time);
474 switch (m_direction) {
475 case QQuickRotationAnimator::Clockwise:
476 m_value = _q_interpolateClockwiseRotation(m_from, m_to, t).toFloat();
483 case QQuickRotationAnimator::Counterclockwise:
484 m_value = _q_interpolateCounterclockwiseRotation(m_from, m_to, t).toFloat();
486 case QQuickRotationAnimator::Shortest:
487 m_value = _q_interpolateShortestRotation(m_from, m_to, t).toFloat();
489 case QQuickRotationAnimator::Numerical:
490 m_value = m_from + (m_to - m_from) * t;
493 m_helper->rotation = m_value;
494 m_helper->wasChanged =
true;
497void QQuickRotationAnimatorJob::writeBack()
500 m_target->setRotation(value());
504QQuickOpacityAnimatorJob::QQuickOpacityAnimatorJob()
505 : m_opacityNode(
nullptr)
509void QQuickOpacityAnimatorJob::postSync()
516 QQuickItemPrivate *d = QQuickItemPrivate::get(m_target);
517#if QT_CONFIG(quick_shadereffect)
518 if (d->extra.isAllocated()
520 && d->extra->layer->enabled()) {
521 d = QQuickItemPrivate::get(d->extra->layer->m_effectSource);
525 m_opacityNode = d->opacityNode();
527 if (!m_opacityNode) {
528 m_opacityNode =
new QSGOpacityNode();
531
532
533
534
535
536
537
538
539
540
541
542
543 QSGNode *iNode = d->itemNode();
544 QSGNode *child = d->childContainerNode();
545 if (child != iNode) {
547 child->parent()->removeChildNode(child);
548 m_opacityNode->appendChildNode(child);
549 iNode->appendChildNode(m_opacityNode);
551 iNode->reparentChildNodesTo(m_opacityNode);
552 iNode->appendChildNode(m_opacityNode);
555 d->extra.value().opacityNode = m_opacityNode;
556 updateCurrentTime(0);
558 Q_ASSERT(m_opacityNode);
561void QQuickOpacityAnimatorJob::invalidate()
563 m_opacityNode =
nullptr;
566void QQuickOpacityAnimatorJob::writeBack()
569 m_target->setOpacity(value());
572void QQuickOpacityAnimatorJob::updateCurrentTime(
int time)
577 m_value = m_from + (m_to - m_from) * progress(time);
578 m_opacityNode->setOpacity(m_value);
581#if QT_CONFIG(quick_shadereffect)
582QQuickUniformAnimatorJob::QQuickUniformAnimatorJob()
587void QQuickUniformAnimatorJob::setTarget(QQuickItem *target)
590 if (qobject_cast<QQuickShaderEffect *>(target) !=
nullptr)
594void QQuickUniformAnimatorJob::updateCurrentTime(
int time)
596 if (!m_effect || m_target != m_effect)
599 m_value = m_from + (m_to - m_from) * progress(time);
600 m_effect->updateUniformValue(m_uniform, m_value);
603void QQuickUniformAnimatorJob::writeBack()
606 m_target->setProperty(m_uniform, value());
609void QQuickUniformAnimatorJob::postSync()
616 m_effect = qobject_cast<QQuickShaderEffect *>(m_target);
619void QQuickUniformAnimatorJob::invalidate()
627#include "moc_qquickanimatorjob_p.cpp"
QVariant _q_interpolateClockwiseRotation(qreal &f, qreal &t, qreal progress)
QVariant _q_interpolateShortestRotation(qreal &f, qreal &t, qreal progress)
\qmltype RotationAnimation \nativetype QQuickRotationAnimation \inqmlmodule QtQuick\inherits Property...
QVariant _q_interpolateCounterclockwiseRotation(qreal &f, qreal &t, qreal progress)
Q_GLOBAL_STATIC(QQuickTransformAnimatorHelperStore, qquick_transform_animatorjob_helper_store)
static void qquick_syncback_helper(QAbstractAnimationJob *job)