126 ret.setCoords(_q_interpolate(f.left(), t.left(), progress),
127 _q_interpolate(f.top(), t.top(), progress),
128 _q_interpolate(f.right(), t.right(), progress),
129 _q_interpolate(f.bottom(), t.bottom(), progress));
135 qreal x1, y1, w1, h1;
136 f.getRect(&x1, &y1, &w1, &h1);
137 qreal x2, y2, w2, h2;
138 t.getRect(&x2, &y2, &w2, &h2);
139 return QRectF(_q_interpolate(x1, x2, progress), _q_interpolate(y1, y2, progress),
140 _q_interpolate(w1, w2, progress), _q_interpolate(h1, h2, progress));
159void QVariantAnimationPrivate::convertValues(
int t)
161 auto type = QMetaType(t);
163 for (
int i = 0; i < keyValues.size(); ++i) {
164 QVariantAnimation::KeyValue &pair = keyValues[i];
165 pair.second.convert(type);
168 currentInterval.start.second.convert(type);
169 currentInterval.end.second.convert(type);
172 updateInterpolator();
175void QVariantAnimationPrivate::updateInterpolator()
177 int type = currentInterval.start.second.userType();
178 if (type == currentInterval.end.second.userType())
179 interpolator = getInterpolator(type);
181 interpolator =
nullptr;
185 interpolator = &defaultInterpolator;
194void QVariantAnimationPrivate::recalculateCurrentInterval(
bool force)
197 if ((keyValues.size() + (defaultStartEndValue.isValid() ? 1 : 0)) < 2)
200 const qreal endProgress = (direction == QAbstractAnimation::Forward) ? qreal(1) : qreal(0);
201 const qreal progress = easing.value().valueForProgress(
202 duration == 0 ? endProgress : qreal(currentTime) / qreal(duration));
205 if (force || (currentInterval.start.first > 0 && progress < currentInterval.start.first)
206 || (currentInterval.end.first < 1 && progress > currentInterval.end.first)) {
208 QVariantAnimation::KeyValues::const_iterator it = std::lower_bound(keyValues.constBegin(),
209 keyValues.constEnd(),
210 std::pair{progress, QVariant{}},
211 animationValueLessThan);
212 if (it == keyValues.constBegin()) {
214 if (it->first == 0 && keyValues.size() > 1) {
215 currentInterval.start = *it;
216 currentInterval.end = *(it+1);
218 currentInterval.start = {qreal(0), defaultStartEndValue};
219 currentInterval.end = *it;
221 }
else if (it == keyValues.constEnd()) {
223 if (it->first == 1 && keyValues.size() > 1) {
225 currentInterval.start = *(it-1);
226 currentInterval.end = *it;
229 currentInterval.start = *it;
230 currentInterval.end = {qreal(1), defaultStartEndValue};
233 currentInterval.start = *(it-1);
234 currentInterval.end = *it;
238 updateInterpolator();
240 setCurrentValueForProgress(progress);
243void QVariantAnimationPrivate::setCurrentValueForProgress(
const qreal progress)
245 Q_Q(QVariantAnimation);
247 const qreal startProgress = currentInterval.start.first;
248 const qreal endProgress = currentInterval.end.first;
249 const qreal localProgress =
250 qIsNull(progress - startProgress) ? 0.0
251 : (progress - startProgress) / (endProgress - startProgress);
253 QVariant ret = q->interpolated(currentInterval.start.second,
254 currentInterval.end.second,
256 qSwap(currentValue, ret);
257 q->updateCurrentValue(currentValue);
258 Q_CONSTINIT
static QBasicAtomicInt changedSignalIndex = Q_BASIC_ATOMIC_INITIALIZER(0);
259 if (!changedSignalIndex.loadRelaxed()) {
261 changedSignalIndex.testAndSetRelaxed(0, signalIndex(
"valueChanged(QVariant)"));
263 if (isSignalConnected(changedSignalIndex.loadRelaxed()) && currentValue != ret) {
265 emit q->valueChanged(currentValue);
269QVariant QVariantAnimationPrivate::valueAt(qreal step)
const
271 const auto sought =
std::pair{step, QVariant()};
272 const auto result = std::lower_bound(keyValues.cbegin(), keyValues.cend(), sought,
273 animationValueLessThan);
274 if (result != keyValues.cend() && !animationValueLessThan(sought, *result))
275 return result->second;
280void QVariantAnimationPrivate::setValueAt(qreal step,
const QVariant &value)
282 if (step < qreal(0.0) || step > qreal(1.0)) {
283 qWarning(
"QVariantAnimation::setValueAt: invalid step = %f", step);
287 QVariantAnimation::KeyValue pair(step, value);
289 QVariantAnimation::KeyValues::iterator result = std::lower_bound(keyValues.begin(), keyValues.end(), pair, animationValueLessThan);
290 if (result == keyValues.end() || result->first != step) {
291 keyValues.insert(result, pair);
294 result->second = value;
296 keyValues.erase(result);
299 recalculateCurrentInterval(
true);
358void QVariantAnimation::setEasingCurve(
const QEasingCurve &easing)
360 Q_D(QVariantAnimation);
361 d->easing.removeBindingUnlessInWrapper();
362 const bool valueChanged = easing != d->easing.valueBypassingBindings();
363 d->easing.setValueBypassingBindings(easing);
364 d->recalculateCurrentInterval();
426QVariantAnimation::Interpolator QVariantAnimationPrivate::getInterpolator(
int interpolationType)
430 const auto locker = qt_scoped_lock(registeredInterpolatorsMutex);
431 QVariantAnimation::Interpolator ret =
nullptr;
432 if (interpolationType < interpolators->size()) {
433 ret = interpolators->at(interpolationType);
438 switch(interpolationType)
441 return castToInterpolator(_q_interpolateVariant<
int>);
442 case QMetaType::UInt:
443 return castToInterpolator(_q_interpolateVariant<uint>);
444 case QMetaType::Double:
445 return castToInterpolator(_q_interpolateVariant<
double>);
446 case QMetaType::Float:
447 return castToInterpolator(_q_interpolateVariant<
float>);
448 case QMetaType::QLine:
449 return castToInterpolator(_q_interpolateVariant<
QLine>);
450 case QMetaType::QLineF:
451 return castToInterpolator(_q_interpolateVariant<
QLineF>);
452 case QMetaType::QPoint:
453 return castToInterpolator(_q_interpolateVariant<QPoint>);
454 case QMetaType::QPointF:
455 return castToInterpolator(_q_interpolateVariant<QPointF>);
456 case QMetaType::QSize:
457 return castToInterpolator(_q_interpolateVariant<QSize>);
458 case QMetaType::QSizeF:
459 return castToInterpolator(_q_interpolateVariant<QSizeF>);
460 case QMetaType::QRect:
461 return castToInterpolator(_q_interpolateVariant<
QRect>);
462 case QMetaType::QRectF:
463 return castToInterpolator(_q_interpolateVariant<
QRectF>);
484void QVariantAnimation::setDuration(
int msecs)
486 Q_D(QVariantAnimation);
488 qWarning(
"QVariantAnimation::setDuration: cannot set a negative duration");
491 d->duration.removeBindingUnlessInWrapper();
492 if (d->duration.valueBypassingBindings() != msecs) {
493 d->duration.setValueBypassingBindings(msecs);
494 d->recalculateCurrentInterval();
495 d->duration.notify();
595void QVariantAnimation::setKeyValues(
const KeyValues &keyValues)
597 Q_D(QVariantAnimation);
598 d->keyValues = keyValues;
599 std::sort(d->keyValues.begin(), d->keyValues.end(), animationValueLessThan);
600 d->recalculateCurrentInterval(
true);
667QVariant QVariantAnimation::interpolated(
const QVariant &from,
const QVariant &to, qreal progress)
const
669 return d_func()->interpolator(from.constData(), to.constData(), progress);