126void QQuickAbstractAnimationPrivate::commence()
128 Q_Q(QQuickAbstractAnimation);
130 QQuickStateActions actions;
131 QQmlProperties properties;
133 auto *newInstance = q->transition(actions, properties, QQuickAbstractAnimation::Forward);
135 Q_ASSERT(newInstance != animationInstance || !newInstance);
136 delete animationInstance;
137 animationInstance = newInstance;
139 if (animationInstance) {
140 if (q->threadingModel() == QQuickAbstractAnimation::RenderThread)
141 animationInstance =
new QQuickAnimatorProxyJob(animationInstance, q);
142 animationInstance->addAnimationChangeListener(
this,
143 QAbstractAnimationJob::Completion | QAbstractAnimationJob::CurrentLoop);
145 animationInstance->start();
235void QQuickAbstractAnimation::setRunning(
bool r)
237 Q_D(QQuickAbstractAnimation);
238 if (!d->componentComplete) {
241 d->avoidPropertyValueSourceStart =
true;
242 else if (!d->needsDeferredSetRunning)
243 d->needsDeferredSetRunning =
true;
250 if (d->group || d->disableUserControl) {
251 qmlWarning(
this) <<
"setRunning() cannot be used on non-root animation nodes.";
257 bool supressStart =
false;
258 if (d->alwaysRunToEnd && d->loopCount != 1
259 && d->animationInstance && d->animationInstance->isRunning()) {
261 if (d->loopCount == -1)
262 d->animationInstance->setLoopCount(d->loopCount);
264 d->animationInstance->setLoopCount(d->animationInstance->currentLoop() + d->loopCount);
272 emit pausedChanged(d->paused);
275 if (d->animationInstance) {
276 if (d->alwaysRunToEnd) {
277 if (d->loopCount != 1)
278 d->animationInstance->setLoopCount(d->animationInstance->currentLoop()+1);
280 d->animationInstance->stop();
287 if (r == d->running) {
294 emit runningChanged(d->running);
295 }
else if (d->animationInstance) {
297 d->running = d->animationInstance->isRunning();
1019QAbstractAnimationJob* QQuickScriptAction::transition(QQuickStateActions &actions,
1020 QQmlProperties &modified,
1021 TransitionDirection direction,
1022 QObject *defaultTarget)
1024 Q_D(QQuickScriptAction);
1026 Q_UNUSED(defaultTarget);
1028 d->hasRunScriptScript =
false;
1029 d->reversing = (direction == Backward);
1030 if (!d->name.isEmpty()) {
1031 for (
int ii = 0; ii < actions.size(); ++ii) {
1032 QQuickStateAction &action = actions[ii];
1034 if (action.event && action.event->type() == QQuickStateActionEvent::Script
1035 &&
static_cast<QQuickStateChangeScript*>(action.event)->name() == d->name) {
1036 d->runScriptScript =
static_cast<QQuickStateChangeScript*>(action.event)->script();
1037 d->hasRunScriptScript =
true;
1038 action.actionDone =
true;
1043 return initInstance(
new QActionAnimation(d->createAction()));
1204QAbstractAnimationJob* QQuickPropertyAction::transition(QQuickStateActions &actions,
1205 QQmlProperties &modified,
1206 TransitionDirection direction,
1207 QObject *defaultTarget)
1209 Q_D(QQuickPropertyAction);
1210 Q_UNUSED(direction);
1212 struct QQuickSetPropertyAnimationAction :
public QAbstractAnimationAction
1214 QQuickStateActions actions;
1215 void doAction() override
1217 for (
int ii = 0; ii < actions.size(); ++ii) {
1218 const QQuickStateAction &action = actions.at(ii);
1219 QQmlPropertyPrivate::write(action.property, action.toValue, QQmlPropertyData::BypassInterceptor | QQmlPropertyData::DontRemoveBinding);
1222 void debugAction(QDebug d,
int indentLevel)
const override {
1223 QByteArray ind(indentLevel,
' ');
1224 for (
int ii = 0; ii < actions.size(); ++ii) {
1225 const QQuickStateAction &action = actions.at(ii);
1226 d <<
"\n" << ind.constData() <<
"target:" << action.property.object() <<
"property:" << action.property.name()
1227 <<
"value:" << action.toValue;
1232 QStringList props = d->properties.isEmpty() ? QStringList() : d->properties.split(QLatin1Char(
','));
1233 for (
int ii = 0; ii < props.size(); ++ii)
1234 props[ii] = props.at(ii).trimmed();
1235 if (!d->propertyName.isEmpty())
1236 props << d->propertyName;
1238 QList<QObject*> targets = d->targets;
1240 targets.append(d->target);
1242 bool hasSelectors = !props.isEmpty() || !targets.isEmpty() || !d->exclude.isEmpty();
1244 if (d->defaultProperty.isValid() && !hasSelectors) {
1245 props << d->defaultProperty.name();
1246 targets << d->defaultProperty.object();
1249 if (defaultTarget && targets.isEmpty())
1250 targets << defaultTarget;
1252 QQuickSetPropertyAnimationAction *data =
new QQuickSetPropertyAnimationAction;
1254 bool hasExplicit =
false;
1256 if (d->value.isValid()) {
1257 for (
int i = 0; i < props.size(); ++i) {
1258 for (
int j = 0; j < targets.size(); ++j) {
1259 QQuickStateAction myAction;
1260 myAction.property = d->createProperty(targets.at(j), props.at(i),
this);
1261 if (myAction.property.isValid()) {
1262 myAction.toValue = d->value;
1263 QQuickPropertyAnimationPrivate::convertVariant(myAction.toValue, myAction.property.propertyMetaType());
1264 data->actions << myAction;
1266 for (
int ii = 0; ii < actions.size(); ++ii) {
1267 QQuickStateAction &action = actions[ii];
1268 if (action.property.object() == myAction.property.object() &&
1269 myAction.property.name() == action.property.name()) {
1270 modified << action.property;
1280 for (
int ii = 0; ii < actions.size(); ++ii) {
1281 QQuickStateAction &action = actions[ii];
1283 QObject *obj = action.property.object();
1284 QString propertyName = action.property.name();
1285 QObject *sObj = action.specifiedObject;
1286 QString sPropertyName = action.specifiedProperty;
1287 bool same = (obj == sObj);
1289 if ((targets.isEmpty() || targets.contains(obj) || (!same && targets.contains(sObj))) &&
1290 (!d->exclude.contains(obj)) && (same || (!d->exclude.contains(sObj))) &&
1291 (props.contains(propertyName) || (!same && props.contains(sPropertyName)))) {
1292 QQuickStateAction myAction = action;
1294 if (d->value.isValid())
1295 myAction.toValue = d->value;
1296 QQuickPropertyAnimationPrivate::convertVariant(myAction.toValue, myAction.property.propertyMetaType());
1298 modified << action.property;
1299 data->actions << myAction;
1300 action.fromValue = myAction.toValue;
1304 QActionAnimation *action =
new QActionAnimation;
1305 if (data->actions.size()) {
1306 action->setAnimAction(data);
1310 return initInstance(action);
1676void QQuickRotationAnimation::setDirection(QQuickRotationAnimation::RotationDirection direction)
1678 Q_D(QQuickRotationAnimation);
1679 if (d->direction == direction)
1682 d->direction = direction;
1683 switch(d->direction) {
1685 d->interpolator =
reinterpret_cast<QVariantAnimation::Interpolator>(
reinterpret_cast<
void *>(&_q_interpolateClockwiseRotation));
1687 case Counterclockwise:
1688 d->interpolator =
reinterpret_cast<QVariantAnimation::Interpolator>(
reinterpret_cast<
void *>(&_q_interpolateCounterclockwiseRotation));
1691 d->interpolator =
reinterpret_cast<QVariantAnimation::Interpolator>(
reinterpret_cast<
void *>(&_q_interpolateShortestRotation));
1694 d->interpolator = QVariantAnimationPrivate::getInterpolator(d->interpolatorType);
1697 emit directionChanged();
1870QAbstractAnimationJob* QQuickSequentialAnimation::transition(QQuickStateActions &actions,
1871 QQmlProperties &modified,
1872 TransitionDirection direction,
1873 QObject *defaultTarget)
1875 Q_D(QQuickAnimationGroup);
1877 QSequentialAnimationGroupJob *ag =
new QSequentialAnimationGroupJob;
1881 if (direction == Backward) {
1883 from = d->animations.size() - 1;
1886 ThreadingModel execution = threadingModel();
1888 bool valid = d->defaultProperty.isValid();
1889 QAbstractAnimationJob* anim;
1890 for (
int ii = from; ii < d->animations.size() && ii >= 0; ii += inc) {
1892 d->animations.at(ii)->setDefaultTarget(d->defaultProperty);
1893 anim = d->animations.at(ii)->transition(actions, modified, direction, defaultTarget);
1895 if (d->animations.at(ii)->threadingModel() == RenderThread && execution != RenderThread)
1896 anim =
new QQuickAnimatorProxyJob(anim,
this);
1897 inc == -1 ? ag->prependAnimation(anim) : ag->appendAnimation(anim);
1901 return initInstance(ag);
1961QAbstractAnimationJob* QQuickParallelAnimation::transition(QQuickStateActions &actions,
1962 QQmlProperties &modified,
1963 TransitionDirection direction,
1964 QObject *defaultTarget)
1966 Q_D(QQuickAnimationGroup);
1967 QParallelAnimationGroupJob *ag =
new QParallelAnimationGroupJob;
1969 ThreadingModel style = threadingModel();
1971 bool valid = d->defaultProperty.isValid();
1972 QAbstractAnimationJob* anim;
1973 for (
int ii = 0; ii < d->animations.size(); ++ii) {
1975 d->animations.at(ii)->setDefaultTarget(d->defaultProperty);
1976 anim = d->animations.at(ii)->transition(actions, modified, direction, defaultTarget);
1978 if (d->animations.at(ii)->threadingModel() == RenderThread && style != RenderThread)
1979 anim =
new QQuickAnimatorProxyJob(anim,
this);
1980 ag->appendAnimation(anim);
1983 return initInstance(ag);
2690 return QQmlListProperty<QObject>(
this, &(d->targets), appendFn, countFn, atFn, clearFN, replaceFn, removeLastFn);
2704void QQuickAnimationPropertyUpdater::setValue(qreal v)
2706 bool deleted =
false;
2707 wasDeleted = &deleted;
2710 for (
int ii = 0; ii < actions.size(); ++ii) {
2711 QQuickStateAction &action = actions[ii];
2713 if (v == qreal(1.0) && extendedInterpolator ==
nullptr) {
2714 QQmlPropertyPrivate::write(action.property, action.toValue, QQmlPropertyData::BypassInterceptor | QQmlPropertyData::DontRemoveBinding);
2716 if (!fromIsSourced && !fromIsDefined) {
2717 action.fromValue = action.property.read();
2718 if (interpolatorType) {
2719 QQuickPropertyAnimationPrivate::convertVariant(action.fromValue, QMetaType(interpolatorType));
2722 if (!interpolatorType) {
2723 int propType = action.property.propertyType();
2724 if (!prevInterpolatorType || prevInterpolatorType != propType) {
2725 prevInterpolatorType = propType;
2726 interpolator = QVariantAnimationPrivate::getInterpolator(prevInterpolatorType);
2730 QVariant interpolated;
2731 if (extendedInterpolator) {
2732 QVariant current = action.property.read();
2733 interpolated = extendedInterpolator(action.fromValue.constData(),
2734 action.toValue.constData(),
2738 }
else if (interpolator) {
2739 interpolated = interpolator(action.fromValue.constData(), action.toValue.constData(), v);
2741 QQmlPropertyPrivate::write(action.property,
2743 QQmlPropertyData::BypassInterceptor | QQmlPropertyData::DontRemoveBinding);
2748 wasDeleted =
nullptr;
2749 fromIsSourced =
true;
2762QQuickStateActions QQuickPropertyAnimation::createTransitionActions(QQuickStateActions &actions,
2763 QQmlProperties &modified,
2764 QObject *defaultTarget)
2766 Q_D(QQuickPropertyAnimation);
2767 QQuickStateActions newActions;
2769 QStringList props = d->properties.isEmpty() ? QStringList() : d->properties.split(QLatin1Char(
','));
2770 for (
int ii = 0; ii < props.size(); ++ii)
2771 props[ii] = props.at(ii).trimmed();
2772 if (!d->propertyName.isEmpty())
2773 props << d->propertyName;
2775 QList<QPointer<QObject>> targets = d->targets;
2777 targets.append(d->target);
2779 bool hasSelectors = !props.isEmpty() || !targets.isEmpty() || !d->exclude.isEmpty();
2780 bool useType = (props.isEmpty() && d->defaultToInterpolatorType) ?
true :
false;
2782 if (d->defaultProperty.isValid() && !hasSelectors) {
2783 props << d->defaultProperty.name();
2784 targets << d->defaultProperty.object();
2787 if (defaultTarget && targets.isEmpty())
2788 targets << defaultTarget;
2790 bool usingDefaultProperties =
false;
2791 if (props.isEmpty() && !d->defaultProperties.isEmpty()) {
2792 props << d->defaultProperties.split(QLatin1Char(
','));
2793 usingDefaultProperties =
true;
2796 bool hasExplicit =
false;
2798 if (d->toIsDefined) {
2799 QVector<QString> errorMessages;
2800 bool successfullyCreatedDefaultProperty =
false;
2802 for (
int i = 0; i < props.size(); ++i) {
2803 for (
int j = 0; j < targets.size(); ++j) {
2804 const auto& guarded = targets.at(j);
2805 if (guarded.isNull())
2807 QObject *target = guarded.get();
2808 QQuickStateAction myAction;
2809 QString errorMessage;
2810 const QString &propertyName = props.at(i);
2811 myAction.property = d->createProperty(target, propertyName,
this, &errorMessage);
2812 if (myAction.property.isValid()) {
2813 if (usingDefaultProperties)
2814 successfullyCreatedDefaultProperty =
true;
2816 if (d->fromIsDefined) {
2817 myAction.fromValue = d->from;
2818 d->convertVariant(myAction.fromValue, d->interpolatorType ? QMetaType(d->interpolatorType) : myAction.property.propertyMetaType());
2820 myAction.toValue = d->to;
2821 d->convertVariant(myAction.toValue, d->interpolatorType ? QMetaType(d->interpolatorType) : myAction.property.propertyMetaType());
2822 newActions << myAction;
2824 for (
int ii = 0; ii < actions.size(); ++ii) {
2825 QQuickStateAction &action = actions[ii];
2826 if (action.property.object() == myAction.property.object() &&
2827 myAction.property.name() == action.property.name()) {
2828 modified << action.property;
2833 errorMessages.append(errorMessage);
2838 if (!successfullyCreatedDefaultProperty) {
2839 for (
const QString &errorMessage : std::as_const(errorMessages))
2840 qmlWarning(
this) << errorMessage;
2845 for (
int ii = 0; ii < actions.size(); ++ii) {
2846 QQuickStateAction &action = actions[ii];
2848 QObject *obj = action.property.object();
2849 QString propertyName = action.property.name();
2850 QObject *sObj = action.specifiedObject;
2851 QString sPropertyName = action.specifiedProperty;
2852 bool same = (obj == sObj);
2854 if ((targets.isEmpty() || targets.contains(obj) || (!same && targets.contains(sObj))) &&
2855 (!d->exclude.contains(obj)) && (same || (!d->exclude.contains(sObj))) &&
2856 (props.contains(propertyName) || (!same && props.contains(sPropertyName))
2857 || (useType && action.property.propertyType() == d->interpolatorType))) {
2858 QQuickStateAction myAction = action;
2860 if (d->fromIsDefined)
2861 myAction.fromValue = d->from;
2863 myAction.fromValue = QVariant();
2865 myAction.toValue = d->to;
2867 d->convertVariant(myAction.fromValue, d->interpolatorType ? QMetaType(d->interpolatorType) : myAction.property.propertyMetaType());
2868 d->convertVariant(myAction.toValue, d->interpolatorType ? QMetaType(d->interpolatorType) : myAction.property.propertyMetaType());
2870 modified << action.property;
2872 newActions << myAction;
2873 action.fromValue = myAction.toValue;
2880QAbstractAnimationJob* QQuickPropertyAnimation::transition(QQuickStateActions &actions,
2881 QQmlProperties &modified,
2882 TransitionDirection direction,
2883 QObject *defaultTarget)
2885 Q_D(QQuickPropertyAnimation);
2887 QQuickStateActions dataActions = createTransitionActions(actions, modified, defaultTarget);
2889 QQuickBulkValueAnimator *animator =
new QQuickBulkValueAnimator;
2890 animator->setDuration(d->duration);
2891 animator->setEasingCurve(d->easing);
2893 if (!dataActions.isEmpty()) {
2894 QQuickAnimationPropertyUpdater *data =
new QQuickAnimationPropertyUpdater;
2895 data->interpolatorType = d->interpolatorType;
2896 data->interpolator = d->interpolator;
2897 data->extendedInterpolator = d->extendedInterpolator;
2898 data->reverse = direction == Backward ?
true :
false;
2899 data->fromIsSourced =
false;
2900 data->fromIsDefined = d->fromIsDefined;
2901 data->actions = dataActions;
2902 animator->setAnimValue(data);
2903 animator->setFromIsSourcedValue(&data->fromIsSourced);
2904 d->actions = &data->actions;
2907 return initInstance(animator);