QtLottie: Make property parsing non-virtual.

This commit is contained in:
John Preston 2019-05-15 17:32:42 +03:00
parent 38e2837cb6
commit 12a4a849ca
3 changed files with 28 additions and 113 deletions

@ -1 +1 @@
Subproject commit 2fa825bfd9384b864e79861e8fa41273da8ab973
Subproject commit f95d9f5260af2dcf1e724d1d0814bd9176149b76

View File

@ -69,7 +69,6 @@ struct EasingSegment {
T startValue;
T endValue;
BezierEasing easing;
QPainterPath bezier;
double bezierLength = 0.;
struct BezierPoint {
@ -85,7 +84,7 @@ class BODYMOVIN_EXPORT BMProperty
public:
virtual ~BMProperty() = default;
virtual void construct(const QJsonObject &definition)
void construct(const QJsonObject &definition)
{
if (definition.value(QStringLiteral("s")).toVariant().toInt())
qCWarning(lcLottieQtBodymovinParser)
@ -210,7 +209,7 @@ protected:
return m_currentEasing;
}
virtual EasingSegment<T> parseKeyframe(const QJsonObject keyframe)
EasingSegment<T> parseKeyframe(const QJsonObject keyframe)
{
EasingSegment<T> easing;
@ -251,23 +250,36 @@ protected:
QJsonObject easingIn = keyframe.value(QStringLiteral("i")).toObject();
QJsonObject easingOut = keyframe.value(QStringLiteral("o")).toObject();
qreal eix = easingIn.value(QStringLiteral("x")).toArray().at(0).toDouble();
qreal eiy = easingIn.value(QStringLiteral("y")).toArray().at(0).toDouble();
if (easingIn.value(QStringLiteral("x")).isArray()) {
qreal eix = easingIn.value(QStringLiteral("x")).toArray().at(0).toDouble();
qreal eiy = easingIn.value(QStringLiteral("y")).toArray().at(0).toDouble();
qreal eox = easingOut.value(QStringLiteral("x")).toArray().at(0).toDouble();
qreal eoy = easingOut.value(QStringLiteral("y")).toArray().at(0).toDouble();
qreal eox = easingOut.value(QStringLiteral("x")).toArray().at(0).toDouble();
qreal eoy = easingOut.value(QStringLiteral("y")).toArray().at(0).toDouble();
QPointF c1 = QPointF(eox, eoy);
QPointF c2 = QPointF(eix, eiy);
QPointF c1 = QPointF(eox, eoy);
QPointF c2 = QPointF(eix, eiy);
easing.easing.addCubicBezierSegment(c1, c2, QPointF(1.0, 1.0));
easing.easing.addCubicBezierSegment(c1, c2, QPointF(1.0, 1.0));
} else {
qreal eix = easingIn.value(QStringLiteral("x")).toDouble();
qreal eiy = easingIn.value(QStringLiteral("y")).toDouble();
qreal eox = easingOut.value(QStringLiteral("x")).toDouble();
qreal eoy = easingOut.value(QStringLiteral("y")).toDouble();
QPointF c1 = QPointF(eox, eoy);
QPointF c2 = QPointF(eix, eiy);
easing.easing.addCubicBezierSegment(c1, c2, QPointF(1.0, 1.0));
}
return easing;
}
virtual void postprocessEasingCurve(
EasingSegment<T> &easing,
const QJsonObject keyframe) {
const QJsonObject &keyframe) {
}
virtual T getValue(const QJsonValue &value)
@ -302,10 +314,9 @@ protected:
const EasingSegment<T> *m_currentEasing = nullptr;
int m_startFrame = INT_MAX;
int m_endFrame = 0;
T m_value;
T m_value = T();
};
template <typename T>
class BODYMOVIN_EXPORT BMProperty2D : public BMProperty<T>
{
@ -318,95 +329,6 @@ protected:
else
return T();
}
EasingSegment<T> parseKeyframe(const QJsonObject keyframe) override
{
QJsonArray startValues = keyframe.value(QStringLiteral("s")).toArray();
QJsonArray endValues = keyframe.value(QStringLiteral("e")).toArray();
int startTime = keyframe.value(QStringLiteral("t")).toVariant().toInt();
EasingSegment<T> easingCurve;
easingCurve.startFrame = startTime;
// AE exported Bodymovin file includes the last
// key frame but no other properties.
// No need to process in that case
if (startValues.isEmpty() && endValues.isEmpty()) {
// In this case start time is the last frame for the property
this->m_endFrame = startTime;
easingCurve.startFrame = startTime;
easingCurve.endFrame = startTime;
easingCurve.state = EasingSegmentState::Final;
if (this->m_easingCurves.length()) {
const EasingSegment<T> &last = this->m_easingCurves.last();
if (last.state == EasingSegmentState::Complete) {
easingCurve.startValue = last.endValue;
easingCurve.endValue = last.endValue;
} else {
qCWarning(lcLottieQtBodymovinParser())
<< "Last keyframe found after an incomplete one";
}
}
return easingCurve;
}
if (this->m_startFrame > startTime)
this->m_startFrame = startTime;
qreal xs, ys;
xs = startValues.at(0).toDouble();
ys = startValues.at(1).toDouble();
T s(xs, ys);
QJsonObject easingIn = keyframe.value(QStringLiteral("i")).toObject();
QJsonObject easingOut = keyframe.value(QStringLiteral("o")).toObject();
easingCurve.startFrame = startTime;
easingCurve.startValue = s;
if (!endValues.isEmpty()) {
qreal xe, ye;
xe = endValues.at(0).toDouble();
ye = endValues.at(1).toDouble();
T e(xe, ye);
easingCurve.endValue = e;
easingCurve.state = EasingSegmentState::Complete;
}
if (easingIn.value(QStringLiteral("x")).isArray()) {
QJsonArray eixArr = easingIn.value(QStringLiteral("x")).toArray();
QJsonArray eiyArr = easingIn.value(QStringLiteral("y")).toArray();
QJsonArray eoxArr = easingOut.value(QStringLiteral("x")).toArray();
QJsonArray eoyArr = easingOut.value(QStringLiteral("y")).toArray();
if (!eixArr.isEmpty() && !eiyArr.isEmpty()) {
qreal eix = eixArr.takeAt(0).toDouble();
qreal eiy = eiyArr.takeAt(0).toDouble();
qreal eox = eoxArr.takeAt(0).toDouble();
qreal eoy = eoyArr.takeAt(0).toDouble();
QPointF c1 = QPointF(eox, eoy);
QPointF c2 = QPointF(eix, eiy);
easingCurve.easing.addCubicBezierSegment(c1, c2, QPointF(1.0, 1.0));
}
}
else {
qreal eix = easingIn.value(QStringLiteral("x")).toDouble();
qreal eiy = easingIn.value(QStringLiteral("y")).toDouble();
qreal eox = easingOut.value(QStringLiteral("x")).toDouble();
qreal eoy = easingOut.value(QStringLiteral("y")).toDouble();
QPointF c1 = QPointF(eox, eoy);
QPointF c2 = QPointF(eix, eiy);
easingCurve.easing.addCubicBezierSegment(c1, c2, QPointF(1.0, 1.0));
}
return easingCurve;
}
};
template <typename T>

View File

@ -51,15 +51,9 @@ QT_BEGIN_NAMESPACE
class BMSpatialProperty : public BMProperty2D<QPointF>
{
public:
virtual void construct(const QJsonObject &definition) override
{
qCDebug(lcLottieQtBodymovinParser) << "BMSpatialProperty::construct()";
BMProperty2D<QPointF>::construct(definition);
}
virtual void postprocessEasingCurve(
EasingSegment<QPointF> &easing,
const QJsonObject keyframe) override {
const QJsonObject &keyframe) override {
// No need to parse further incomplete keyframes (i.e. last keyframes)
if (easing.state != EasingSegmentState::Complete) {
return;
@ -83,15 +77,14 @@ public:
c1 += s;
c2 += e;
easing.bezier.moveTo(s);
easing.bezier.cubicTo(c1, c2, e);
QBezier bezier = QBezier::fromPoints(s, c1, c2, e);
const auto kCount = 150;
easing.bezierPoints.reserve(kCount);
for (auto k = 0; k < kCount; ++k) {
const auto percent = double(k) / (kCount - 1.);
auto point = EasingSegment<QPointF>::BezierPoint();
point.point = easing.bezier.pointAtPercent(percent);
point.point = bezier.pointAt(percent);
if (k > 0) {
const auto delta = (point.point - easing.bezierPoints[k - 1].point);
point.length = std::sqrt(QPointF::dotProduct(delta, delta));