Use QEasing instead of Bezier to paint the curve segments

This way "failure state" is reflected in the appearance of the curve item

Change-Id: I997f86f1a6072eaf65c77f2df0afd53a80dc0d0e
Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
Knud Dollereder
2020-03-17 16:41:34 +01:00
committed by Thomas Hartmann
parent 7675296fcf
commit d72e18da2d
3 changed files with 28 additions and 14 deletions

View File

@@ -224,6 +224,23 @@ QPainterPath CurveSegment::path() const
return path;
}
void CurveSegment::extendWithEasingCurve(QPainterPath &path, const QEasingCurve &curve) const
{
auto mapEasing = [](const QPointF &start, const QPointF &end, const QPointF &pos) {
QPointF slope(end.x() - start.x(), end.y() - start.y());
return QPointF(start.x() + slope.x() * pos.x(), start.y() + slope.y() * pos.y());
};
QVector<QPointF> points = curve.toCubicSpline();
int numSegments = points.count() / 3;
for (int i = 0; i < numSegments; i++) {
QPointF p1 = mapEasing(m_left.position(), m_right.position(), points.at(i * 3));
QPointF p2 = mapEasing(m_left.position(), m_right.position(), points.at(i * 3 + 1));
QPointF p3 = mapEasing(m_left.position(), m_right.position(), points.at(i * 3 + 2));
path.cubicTo(p1, p2, p3);
}
}
void CurveSegment::extend(QPainterPath &path) const
{
if (interpolation() == Keyframe::Interpolation::Linear) {
@@ -232,23 +249,11 @@ void CurveSegment::extend(QPainterPath &path) const
path.lineTo(QPointF(m_right.position().x(), m_left.position().y()));
path.lineTo(m_right.position());
} else if (interpolation() == Keyframe::Interpolation::Bezier) {
path.cubicTo(m_left.rightHandle(), m_right.leftHandle(), m_right.position());
extendWithEasingCurve(path, easingCurve());
} else if (interpolation() == Keyframe::Interpolation::Easing) {
auto mapEasing = [](const QPointF &start, const QPointF &end, const QPointF &pos) {
QPointF slope(end.x() - start.x(), end.y() - start.y());
return QPointF(start.x() + slope.x() * pos.x(), start.y() + slope.y() * pos.y());
};
QVariant data = m_right.data();
if (data.isValid() && data.type() == static_cast<int>(QMetaType::QEasingCurve)) {
QVector<QPointF> points = data.value<QEasingCurve>().toCubicSpline();
int numSegments = points.count() / 3;
for (int i = 0; i < numSegments; i++) {
QPointF p1 = mapEasing(m_left.position(), m_right.position(), points.at(i * 3));
QPointF p2 = mapEasing(m_left.position(), m_right.position(), points.at(i * 3 + 1));
QPointF p3 = mapEasing(m_left.position(), m_right.position(), points.at(i * 3 + 2));
path.cubicTo(p1, p2, p3);
}
extendWithEasingCurve(path, data.value<QEasingCurve>());
}
}
}

View File

@@ -61,6 +61,8 @@ public:
void extend(QPainterPath &path) const;
void extendWithEasingCurve(QPainterPath &path, const QEasingCurve &curve) const;
QEasingCurve easingCurve() const;
std::vector<QPointF> extrema() const;

View File

@@ -206,6 +206,13 @@ std::vector<DesignTools::Keyframe> resolveSmallCurves(
QEasingCurve curve = frame.data().toEasingCurve();
if (curve.toCubicSpline().count() == 3) {
DesignTools::Keyframe &previous = out.back();
#if 0
// Do not resolve when two adjacent keyframes have the same value.
if (qFuzzyCompare(previous.position().y(), frame.position().y())) {
out.push_back(frame);
continue;
}
#endif
DesignTools::AnimationCurve acurve(curve, previous.position(), frame.position());
previous.setRightHandle(acurve.keyframeAt(0).rightHandle());
out.push_back(acurve.keyframeAt(1));