From: subhransu mohanty Date: Wed, 12 Sep 2018 08:16:05 +0000 (+0900) Subject: lottie/feature: Added support for handing lottie repeater objects. X-Git-Tag: submit/tizen/20181211.054046~2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=99aa016f8405cd573580c60f17fe19f2f0a986f8;p=platform%2Fcore%2Fuifw%2Flottie-player.git lottie/feature: Added support for handing lottie repeater objects. Change-Id: If65b81aab08baeecd3c16ff70a38587429bd8c61 --- diff --git a/src/lottie/lottieitem.cpp b/src/lottie/lottieitem.cpp index 766a174..8170c16 100644 --- a/src/lottie/lottieitem.cpp +++ b/src/lottie/lottieitem.cpp @@ -563,7 +563,7 @@ LOTShapeLayerItem::createContentItem(LOTData *contentData) switch (contentData->type()) { case LOTData::Type::ShapeGroup: { return std::make_unique( - static_cast(contentData)); + static_cast(contentData)); break; } case LOTData::Type::Rect: { @@ -644,7 +644,7 @@ void LOTShapeLayerItem::renderList(std::vector &list) mRoot->renderList(list); } -LOTContentGroupItem::LOTContentGroupItem(LOTShapeGroupData *data) : mData(data) +LOTContentGroupItem::LOTContentGroupItem(LOTGroupData *data) : mData(data) { addChildren(mData); } @@ -672,7 +672,7 @@ void LOTContentGroupItem::update(int frameNo, const VMatrix &parentMatrix, float alpha = parentAlpha; DirtyFlag newFlag = flag; - if (mData) { + if (mData && mData->mTransform) { // update the matrix and the flag if ((flag & DirtyFlagBit::Matrix) || !mData->mTransform->staticMatrix()) { @@ -1139,14 +1139,44 @@ void LOTTrimItem::addPathItems(std::vector &list, int startOf } -LOTRepeaterItem::LOTRepeaterItem(LOTRepeaterData *data) : mData(data) {} - -void LOTRepeaterItem::update(int /*frameNo*/, const VMatrix &/*parentMatrix*/, - float /*parentAlpha*/, const DirtyFlag &/*flag*/) +LOTRepeaterItem::LOTRepeaterItem(LOTRepeaterData *data) : mData(data) { + assert(mData->mChildren.size() == 1); + LOTGroupData *root = reinterpret_cast(mData->mChildren[0].get()); + assert(root); + + for (int i= 0; i < mData->copies(0); i++) { + auto content = std::make_unique(static_cast(root)); + content->setParent(this); + mContents.push_back(std::move(content)); + } } -void LOTRepeaterItem::renderList(std::vector &/*list*/) {} +void LOTRepeaterItem::update(int frameNo, const VMatrix &parentMatrix, float parentAlpha, const DirtyFlag &flag) +{ + + DirtyFlag newFlag = flag; + + if (mData->hasMtrixChange(frameNo)) { + newFlag |= DirtyFlagBit::Matrix; + } + + float multiplier = mData->offset(frameNo); + float startOpacity = mData->mTransform->startOpacity(frameNo); + float endOpacity = mData->mTransform->endOpacity(frameNo); + float index = 0; + float copies = mData->copies(frameNo); + if (!vCompare(copies, 1)) copies -=1; + + newFlag |= DirtyFlagBit::Alpha; + for (const auto &content : mContents) { + float newAlpha = parentAlpha * lerp(startOpacity, endOpacity, index / copies); + VMatrix result = mData->mTransform->matrixForRepeater(frameNo, multiplier) * parentMatrix; + content->update(frameNo, result, newAlpha, newFlag); + multiplier += 1; + index +=1; + } +} static void updateGStops(LOTNode *n, const VGradient *grad) { diff --git a/src/lottie/lottieitem.h b/src/lottie/lottieitem.h index d87f37a..0251460 100644 --- a/src/lottie/lottieitem.h +++ b/src/lottie/lottieitem.h @@ -197,16 +197,17 @@ private: class LOTContentGroupItem: public LOTContentItem { public: - LOTContentGroupItem(LOTShapeGroupData *data); + LOTContentGroupItem(){} + LOTContentGroupItem(LOTGroupData *data); void addChildren(LOTGroupData *data); - void update(int frameNo, const VMatrix &parentMatrix, float parentAlpha, const DirtyFlag &flag) final; + void update(int frameNo, const VMatrix &parentMatrix, float parentAlpha, const DirtyFlag &flag); void applyTrim(); void processTrimItems(std::vector &list); void processPaintItems(std::vector &list); void renderList(std::vector &list) final; const VMatrix & matrix() const { return mMatrix;} -private: - LOTShapeGroupData *mData; +protected: + LOTGroupData *mData{nullptr}; std::vector> mContents; VMatrix mMatrix; }; @@ -416,12 +417,11 @@ private: bool mDirty{true}; }; -class LOTRepeaterItem : public LOTContentItem +class LOTRepeaterItem : public LOTContentGroupItem { public: LOTRepeaterItem(LOTRepeaterData *data); void update(int frameNo, const VMatrix &parentMatrix, float parentAlpha, const DirtyFlag &flag) final; - void renderList(std::vector &list) final; private: LOTRepeaterData *mData; }; diff --git a/src/lottie/lottiemodel.cpp b/src/lottie/lottiemodel.cpp index c9b6b62..63b924e 100644 --- a/src/lottie/lottiemodel.cpp +++ b/src/lottie/lottiemodel.cpp @@ -3,26 +3,46 @@ #include #include +/* + * We process the iterator objects in the children list + * by iterating from back to front. when we find a repeater object + * we remove the objects from satrt till repeater object and then place + * under a new shape group object which we add it as children to the repeater + * object. + * Then we visit the childrens of the newly created shape group object to + * process the remaining repeater object(when children list contains more than one + * repeater). + * + */ class LottieRepeaterProcesser { public: - void visitChildren(LOTGroupData *obj) - { - for (const auto& child : obj->mChildren) { - if (child->mType == LOTData::Type::Repeater) { - LOTRepeaterData *repeater = - static_cast(child.get()); - std::shared_ptr sharedShapeGroup = - std::make_shared(); + void visitChildren(LOTGroupData *obj) { + for (auto i = obj->mChildren.rbegin(); i != obj->mChildren.rend(); ++i ) { + auto child = (*i).get(); + if (child->type() == LOTData::Type::Repeater) { + LOTRepeaterData *repeater = static_cast(child); + auto sharedShapeGroup = std::make_shared(); LOTShapeGroupData *shapeGroup = sharedShapeGroup.get(); + // 1. increment the reverse iterator to point to the + // object before the repeater + ++i; + // 2. move all the children till repater to the group + std::move(obj->mChildren.begin(), + i.base(), back_inserter(shapeGroup->mChildren)); + // 3. erase the objects from the original children list + obj->mChildren.erase(obj->mChildren.begin(), + i.base()); + // 4. Add the newly created group to the repeater object. repeater->mChildren.push_back(sharedShapeGroup); - // copy all the child of the object till repeater and - // move that in to a group and then add that group to - // the repeater object. - for (const auto& cpChild : obj->mChildren) { - if (cpChild == child) break; - shapeGroup->mChildren.push_back(cpChild); - } + + // 5. visit newly created group to process remaining repeater object. + visitChildren(shapeGroup); + // 6. exit the loop as the current iterators are invalid + break; + } else { + visit(child); } + } } @@ -47,6 +67,20 @@ void LOTCompositionData::processRepeaterObjects() visitor.visit(mRootLayer.get()); } +VMatrix LOTTransformData::matrixForRepeater(int frameNo, float multiplier) const +{ + VPointF scale = mScale.value(frameNo) / 100.f; + scale.setX(std::pow(scale.x(), multiplier)); + scale.setY(std::pow(scale.y(), multiplier)); + VMatrix m; + m.translate(mPosition.value(frameNo) * multiplier) + .rotate(mRotation.value(frameNo) * multiplier) + .scale(scale) + .translate(mAnchor.value(frameNo)); + return m; +} + + VMatrix LOTTransformData::matrix(int frameNo, bool autoOrient) const { if (mStaticMatrix) diff --git a/src/lottie/lottiemodel.h b/src/lottie/lottiemodel.h index 8ceb1c5..a939979 100644 --- a/src/lottie/lottiemodel.h +++ b/src/lottie/lottiemodel.h @@ -444,6 +444,7 @@ class LOTTransformData : public LOTData public: LOTTransformData():LOTData(LOTData::Type::Transform),mScale({100, 100}){} VMatrix matrix(int frameNo, bool autoOrient = false) const; + VMatrix matrixForRepeater(int frameNo, float multiplier) const; float opacity(int frameNo) const { return mOpacity.value(frameNo)/100;} float startOpacity(int frameNo) const { return mStartOpacity.value(frameNo)/100;} float endOpacity(int frameNo) const { return mEndOpacity.value(frameNo)/100;} @@ -745,6 +746,11 @@ class LOTRepeaterData : public LOTGroupData { public: LOTRepeaterData():LOTGroupData(LOTData::Type::Repeater){} + bool hasMtrixChange(int /*frameNo*/) const { + return !(mTransform->isStatic() && mOffset.isStatic()); + } + float copies(int frameNo) const {return mCopies.value(frameNo);} + float offset(int frameNo) const {return mOffset.value(frameNo);} public: LOTAnimatable mCopies{0}; LOTAnimatable mOffset{0}; diff --git a/src/lottie/lottieparser.cpp b/src/lottie/lottieparser.cpp index b63d1e9..91e9f39 100644 --- a/src/lottie/lottieparser.cpp +++ b/src/lottie/lottieparser.cpp @@ -1966,7 +1966,10 @@ public: void visit(LOTData *obj, std::string level) { switch (obj->mType) { case LOTData::Type::Repeater: { - vDebug << level << "{ Repeater:"; + auto r = static_cast(obj); + vDebug << level << "{ Repeater: a:" << !obj->isStatic() + << ", copies:" << r->copies(0) + << ", offset:" << r->offset(0); visitChildren(static_cast(obj), level); vDebug << level << "} Repeater"; break;