diff --git a/example/demo.cpp b/example/demo.cpp index 368e29f773..48625c602e 100644 --- a/example/demo.cpp +++ b/example/demo.cpp @@ -45,10 +45,13 @@ main(void) app->setup(); std::string filePath = DEMO_DIR; - filePath +="3d.json"; + filePath +="circuit.json"; LottieView *view = new LottieView(app->evas()); view->setFilePath(filePath.c_str()); + if (view->player()) { + view->player()->setValue("**", rlottie::Color(0, 1, 0)); + } view->setPos(0, 0); view->setSize(800, 800); view->show(); diff --git a/example/lottieview.h b/example/lottieview.h index a0425236a2..0874e9717c 100644 --- a/example/lottieview.h +++ b/example/lottieview.h @@ -43,6 +43,7 @@ public: evas_object_del(renderObject()); } RenderStrategy(Evas_Object *obj):_renderObject(obj){} + virtual rlottie::Animation *player() {return nullptr;} virtual void loadFromFile(const char *filePath) = 0; virtual void loadFromData(const std::string &jsonData, const std::string &key, const std::string &resourcePath) = 0; virtual size_t totalFrame() = 0; @@ -63,7 +64,7 @@ private: class CppApiBase : public RenderStrategy { public: CppApiBase(Evas_Object *renderObject): RenderStrategy(renderObject) {} - + rlottie::Animation *player() {return mPlayer.get();} void loadFromFile(const char *filePath) { mPlayer = rlottie::Animation::loadFromFile(filePath); @@ -283,6 +284,7 @@ public: }; LottieView(Evas *evas, Strategy s = Strategy::renderCppAsync); ~LottieView(); + rlottie::Animation *player(){return mRenderDelegate->player();} Evas_Object *getImage(); void setSize(int w, int h); void setPos(int x, int y); diff --git a/example/resource/dynamic_property.json b/example/resource/dynamic_property.json new file mode 100755 index 0000000000..ef04bd08c4 --- /dev/null +++ b/example/resource/dynamic_property.json @@ -0,0 +1 @@ +{"v":"5.4.3","fr":60,"ip":0,"op":30,"w":800,"h":800,"nm":"Comp 1","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"ABCDEFG Outlines","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[395,397,0],"ix":2},"a":{"a":0,"k":[86,-17,0],"ix":1},"s":{"a":0,"k":[343,343,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,-0.516],[0.334,-0.269],[0.949,-0.047],[0,0],[0,0],[0,0],[0.545,0.475],[0.668,1.594],[0,0],[0,0],[0,0],[0.598,-0.563],[0.996,-0.176],[0,0],[0,0],[0,0],[0.346,0.275],[0,0.363],[-0.399,0.926],[0,0],[0,0]],"o":[[0.469,1.113],[0,0.387],[-0.334,0.27],[0,0],[0,0],[0,0],[-0.973,-0.059],[-0.545,-0.475],[0,0],[0,0],[0,0],[-0.727,1.723],[-0.293,0.281],[0,0],[0,0],[0,0],[-1.149,-0.082],[-0.346,-0.275],[0,-0.457],[0,0],[0,0],[0,0]],"v":[[17.912,-4.553],[18.615,-2.109],[18.114,-1.125],[16.189,-0.65],[16.189,0],[25.594,0],[25.594,-0.65],[23.317,-1.45],[21.498,-4.553],[13.201,-24.381],[12.586,-24.381],[4.201,-4.764],[2.215,-1.336],[0.281,-0.65],[0.281,0],[7.787,0],[7.787,-0.65],[5.546,-1.187],[5.027,-2.145],[5.625,-4.219],[7.242,-7.98],[16.471,-7.98]],"c":true},"ix":2},"nm":"A","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[7.787,-9.281],[11.936,-18.914],[15.979,-9.281]],"c":true},"ix":2},"nm":"A","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"mm","mm":1,"nm":"Merge Paths 1","mn":"ADBE Vector Filter - Merge","hd":false},{"ty":"fl","c":{"a":0,"k":[0.921568986481,0.921568986481,0.921568986481,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"A","np":5,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-0.727,0.943],[0,1.195],[0.926,1.072],[1.758,0.422],[1.922,0],[0,0],[0,0],[0,0],[-0.457,-0.516],[0,-1.477],[0,0],[0.269,-0.41],[0.996,0],[0,0],[0,0],[0,0],[-1.307,0.498],[-0.75,1.084],[0,1.184],[1.137,1.078],[1.652,0.352]],"o":[[0.726,-0.943],[0,-1.394],[-0.926,-1.072],[-1.16,-0.281],[0,0],[0,0],[0,0],[0.902,0],[0.34,0.387],[0,0],[0,1.336],[-0.434,0.633],[0,0],[0,0],[0,0],[2.683,0],[1.307,-0.498],[0.75,-1.084],[0,-1.558],[-0.82,-0.773],[1.418,-0.457]],"v":[[45.844,-14.265],[46.934,-17.473],[45.545,-21.173],[41.52,-23.414],[36.896,-23.836],[26.596,-23.836],[26.596,-23.186],[27.492,-23.186],[29.531,-22.412],[30.041,-19.617],[30.041,-4.219],[29.637,-1.6],[27.492,-0.65],[26.596,-0.65],[26.596,0],[37.846,0],[43.831,-0.747],[46.916,-3.12],[48.041,-6.521],[46.336,-10.477],[42.627,-12.164]],"c":true},"ix":2},"nm":"B","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0,0],[-1.172,0],[-1.137,-0.984],[0,-1.394],[0.457,-0.762],[0.861,-0.369],[1.711,0],[0.556,0.041],[0.433,0.082]],"o":[[0.937,-0.258],[2.18,0],[1.137,0.984],[0,0.903],[-0.457,0.762],[-0.861,0.369],[-0.668,0],[-0.557,-0.041],[0,0]],"v":[[33.416,-22.271],[36.58,-22.658],[41.555,-21.182],[43.26,-17.613],[42.574,-15.117],[40.597,-13.421],[36.738,-12.867],[34.901,-12.929],[33.416,-13.113]],"c":true},"ix":2},"nm":"B","mn":"ADBE Vector Shape - Group","hd":false},{"ind":2,"ty":"sh","ix":3,"ks":{"a":0,"k":{"i":[[0,0],[-0.516,0.024],[-0.727,0],[-1.137,-0.492],[-0.504,-0.855],[0,-0.926],[1.113,-0.955],[2.121,0],[1.359,0.316]],"o":[[0.316,-0.059],[0.516,-0.023],[1.676,0],[1.137,0.492],[0.504,0.856],[0,1.406],[-1.113,0.955],[-1.324,0],[0,0]],"v":[[33.416,-11.496],[34.664,-11.619],[36.527,-11.654],[40.746,-10.916],[43.207,-8.895],[43.963,-6.223],[42.293,-2.681],[37.441,-1.248],[33.416,-1.723]],"c":true},"ix":2},"nm":"B","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"mm","mm":1,"nm":"Merge Paths 1","mn":"ADBE Vector Filter - Merge","hd":false},{"ty":"fl","c":{"a":0,"k":[0.921568986481,0.921568986481,0.921568986481,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"B","np":6,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0.305,-0.316],[0.316,0],[0.492,0.258],[1.723,0],[1.869,-1.096],[1.066,-1.992],[0,-2.379],[-1.617,-2.18],[-3.949,0],[-1.594,0.984],[-1.195,2.121],[0,0],[1.184,-0.662],[1.547,0],[1.389,0.844],[0.691,1.582],[0,2.156],[-0.733,1.758],[-1.277,0.803],[-1.582,0],[-1.348,-1.066],[-0.727,-2.426],[0,0],[0,0]],"o":[[-0.129,0.563],[-0.235,0.223],[-0.211,0],[-1.676,-0.844],[-2.215,0],[-1.869,1.096],[-1.066,1.992],[0,2.953],[2.168,2.93],[2.191,0],[1.594,-0.984],[0,0],[-1.418,1.969],[-1.184,0.662],[-1.781,0],[-1.389,-0.844],[-0.692,-1.582],[0,-2.613],[0.732,-1.758],[1.277,-0.803],[1.887,0],[1.347,1.066],[0,0],[0,0],[0,0]],"v":[[71.068,-24.381],[70.418,-23.063],[69.592,-22.729],[68.537,-23.115],[63.439,-24.381],[57.313,-22.737],[52.91,-18.105],[51.311,-11.549],[53.736,-3.85],[62.912,0.545],[68.59,-0.932],[72.773,-5.59],[72.229,-5.941],[68.326,-1.995],[64.23,-1.002],[59.476,-2.268],[56.355,-5.906],[55.318,-11.514],[56.417,-18.07],[59.432,-21.911],[63.721,-23.115],[68.572,-21.516],[71.684,-16.277],[72.229,-16.277],[71.684,-24.381]],"c":true},"ix":2},"nm":"C","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.921568986481,0.921568986481,0.921568986481,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"C","np":3,"cix":2,"bm":0,"ix":3,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[-2.262,2.485],[0,3.316],[1.131,1.887],[1.857,0.809],[3.562,0],[0,0],[0,0],[0,0],[-0.457,-0.516],[0,-1.488],[0,0],[0.258,-0.387],[1.008,0],[0,0],[0,0]],"o":[[4.629,0],[2.015,-2.226],[0,-2.472],[-1.131,-1.887],[-1.858,-0.809],[0,0],[0,0],[0,0],[0.902,0],[0.328,0.375],[0,0],[0,1.348],[-0.422,0.645],[0,0],[0,0],[0,0]],"v":[[85.289,0],[95.625,-3.727],[98.648,-12.041],[96.952,-18.58],[92.47,-22.623],[84.34,-23.836],[74.637,-23.836],[74.637,-23.186],[75.533,-23.186],[77.572,-22.412],[78.064,-19.617],[78.064,-4.219],[77.678,-1.617],[75.533,-0.65],[74.637,-0.65],[74.637,0]],"c":true},"ix":2},"nm":"D","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0,0],[-1.055,0],[-1.793,-1.898],[0,-3.293],[1.793,-1.91],[2.719,0],[1.488,0.328]],"o":[[1.347,-0.34],[2.813,0],[1.793,1.898],[0,3.27],[-1.793,1.91],[-1.008,0],[0,0]],"v":[[81.439,-21.99],[85.043,-22.5],[91.951,-19.652],[94.641,-11.865],[91.951,-4.096],[85.184,-1.23],[81.439,-1.723]],"c":true},"ix":2},"nm":"D","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"mm","mm":1,"nm":"Merge Paths 1","mn":"ADBE Vector Filter - Merge","hd":false},{"ty":"fl","c":{"a":0,"k":[0.921568986481,0.921568986481,0.921568986481,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"D","np":5,"cix":2,"bm":0,"ix":4,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[-0.469,-0.176],[-0.299,-0.469],[-0.246,-1.254],[0,0],[0,0],[0,0],[0,0],[0,0],[-0.422,-0.469],[0,-1.512],[0,0],[0.135,-0.375],[0.375,-0.187],[0.563,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0.726,-0.726],[0.609,-0.187],[1.347,0],[0,0],[0.234,0.135],[0.094,0.229],[0,1.055],[0,0],[0,0],[-0.481,-0.234],[-0.211,-0.41],[-0.164,-1.16],[0,0],[0,0],[0,0],[0.609,-0.539],[1.359,0],[0,0],[0,0]],"o":[[1.184,0],[0.586,0.246],[0.299,0.469],[0,0],[0,0],[0,0],[0,0],[0,0],[0.984,0],[0.305,0.352],[0,0],[0,1.16],[-0.135,0.375],[-0.504,0.27],[0,0],[0,0],[0,0],[0,0],[0,0],[-0.762,1.465],[-0.563,0.551],[-0.609,0.188],[0,0],[-0.656,0],[-0.235,-0.135],[-0.094,-0.229],[0,0],[0,0],[0.996,0],[0.48,0.235],[0.164,0.328],[0,0],[0,0],[0,0],[-0.07,1.36],[-0.457,0.41],[0,0],[0,0],[0,0]],"v":[[114.082,-22.535],[116.561,-22.271],[117.888,-21.199],[118.705,-18.615],[119.391,-18.615],[119.127,-23.836],[100.758,-23.836],[100.758,-23.186],[101.602,-23.186],[103.711,-22.482],[104.168,-19.688],[104.168,-4.201],[103.966,-1.898],[103.201,-1.055],[101.602,-0.65],[100.758,-0.65],[100.758,0],[119.127,0],[121.184,-5.977],[120.48,-5.977],[118.248,-2.689],[116.49,-1.582],[113.555,-1.301],[109.512,-1.301],[108.176,-1.503],[107.684,-2.048],[107.543,-3.973],[107.543,-11.83],[112.781,-11.83],[114.996,-11.479],[116.033,-10.512],[116.525,-8.279],[117.176,-8.279],[117.176,-16.576],[116.525,-16.576],[115.506,-13.729],[112.781,-13.113],[107.543,-13.113],[107.543,-22.535]],"c":true},"ix":2},"nm":"E","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.921568986481,0.921568986481,0.921568986481,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"E","np":3,"cix":2,"bm":0,"ix":5,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[-0.592,-0.234],[-0.404,-0.521],[-0.305,-1.113],[0,0],[0,0],[0,0],[0,0],[0,0],[-0.504,-0.281],[-0.117,-0.293],[0,-1.207],[0,0],[0.281,-0.375],[0.984,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0.516,0.281],[0.117,0.293],[0,1.207],[0,0],[0,0],[-0.404,-0.217],[-0.229,-0.433],[-0.012,-0.926],[0,0],[0,0],[0,0],[0.463,-0.439],[0.996,0],[0,0],[0,0]],"o":[[1.242,0],[0.592,0.235],[0.404,0.522],[0,0],[0,0],[0,0],[0,0],[0,0],[0.574,0],[0.363,0.211],[0.152,0.387],[0,0],[0,1.43],[-0.445,0.574],[0,0],[0,0],[0,0],[0,0],[0,0],[-0.563,0],[-0.375,-0.211],[-0.152,-0.387],[0,0],[0,0],[0.797,0],[0.404,0.217],[0.229,0.434],[0,0],[0,0],[0,0],[-0.152,1.301],[-0.463,0.439],[0,0],[0,0],[0,0]],"v":[[134.631,-22.535],[137.382,-22.184],[138.876,-21.05],[139.939,-18.598],[140.555,-18.598],[140.326,-23.836],[122.59,-23.836],[122.59,-23.186],[123.434,-23.186],[125.051,-22.764],[125.771,-22.008],[126,-19.617],[126,-4.219],[125.578,-1.512],[123.434,-0.65],[122.59,-0.65],[122.59,0],[132.82,0],[132.82,-0.65],[131.959,-0.65],[130.342,-1.072],[129.604,-1.828],[129.375,-4.219],[129.375,-11.707],[133.717,-11.707],[135.519,-11.382],[136.468,-10.406],[136.828,-8.367],[137.479,-8.367],[137.479,-16.436],[136.828,-16.436],[135.905,-13.825],[133.717,-13.166],[129.375,-13.166],[129.375,-22.535]],"c":true},"ix":2},"nm":"F","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.921568986481,0.921568986481,0.921568986481,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"F","np":3,"cix":2,"bm":0,"ix":6,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0.158,-0.205],[0.222,0],[0.656,0.246],[0.709,0.141],[0.867,0],[1.746,-1.02],[1.195,-2.285],[0,-2.098],[-1.793,-2.215],[-4.605,0],[-1.313,0.34],[-1.348,0.727],[0,0],[-0.235,0.434],[-0.914,0],[0,0],[0,0],[0,0],[0,0],[-0.381,-0.193],[-0.182,-0.369],[0,-1.195],[0,0],[0.82,-0.222],[0.879,0],[1.424,0.873],[0.879,1.875],[0,2.274],[-1.324,2.028],[-3.035,0],[-1.418,-1.371],[-0.621,-1.875],[0,0],[0,0]],"o":[[-0.035,0.598],[-0.158,0.205],[-0.223,0],[-1.301,-0.48],[-0.709,-0.141],[-2.379,0],[-2.086,1.23],[-1.008,1.922],[0,2.895],[2.391,2.953],[1.605,0],[1.312,-0.34],[0,0],[0,-1.277],[0.34,-0.609],[0,0],[0,0],[0,0],[0,0],[0.961,0],[0.381,0.193],[0.182,0.369],[0,0],[-0.762,0.434],[-0.82,0.223],[-1.5,0],[-1.424,-0.873],[-0.879,-1.875],[0,-2.801],[1.582,-2.402],[2.226,0],[0.984,0.949],[0,0],[0,0],[0,0]],"v":[[163.477,-24.381],[163.187,-23.177],[162.615,-22.869],[161.297,-23.238],[158.282,-24.17],[155.918,-24.381],[149.73,-22.852],[144.809,-17.578],[143.297,-11.549],[145.986,-3.885],[156.48,0.545],[160.857,0.035],[164.848,-1.564],[164.848,-8.859],[165.199,-11.426],[167.08,-12.34],[167.52,-12.34],[167.52,-13.008],[158.291,-13.008],[158.291,-12.34],[160.304,-12.05],[161.147,-11.206],[161.42,-8.859],[161.42,-1.969],[159.047,-0.984],[156.498,-0.65],[152.112,-1.96],[148.658,-6.082],[147.34,-12.305],[149.326,-19.547],[156.252,-23.15],[161.719,-21.094],[164.127,-16.857],[164.742,-16.857],[164.127,-24.381]],"c":true},"ix":2},"nm":"G","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.921568986481,0.921568986481,0.921568986481,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"G","np":3,"cix":2,"bm":0,"ix":7,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":30,"st":0,"bm":0}],"markers":[]} \ No newline at end of file diff --git a/inc/rlottie.h b/inc/rlottie.h index 3d6c967a63..11e1e7c2a0 100644 --- a/inc/rlottie.h +++ b/inc/rlottie.h @@ -51,6 +51,38 @@ struct LOTLayerNode; namespace rlottie { +struct Color { + Color(){} + Color(float r, float g , float b):mr(r), mg(g), mb(b){} +public: + float mr{0}, mg{0}, mb{0}; +}; + +struct Size { + Size(float w, float h):mw(w), mh(h){} +private: + float mw{0} , mh{0}; +}; + +struct Point { + Point(float x, float y):mx(x), my(y){} +private: + float mx{0} , my{0}; +}; + +enum class Property { + FillColor, /*!< Color property of Fill object , value type is rlottie::Color */ + FillOpacity, /*!< Opacity property of Fill object , value type is float [ 0 .. 100] */ + StrokeColor, /*!< Color property of Stroke object , value type is rlottie::Color */ + StrokeOpacity, /*!< Opacity property of Stroke object , value type is float [ 0 .. 100] */ + StrokeWidth, /*!< stroke with property of Stroke object , value type is float */ + TrAnchor, /*!< Transform Anchor property of Layer and Group object , value type is rlottie::Point */ + TrPosition, /*!< Transform Position property of Layer and Group object , value type is rlottie::Point */ + TrScale, /*!< Transform Scale property of Layer and Group object , value type is rlottie::Size. range[0 ..100] */ + TrRotation, /*!< Transform Scale property of Layer and Group object , value type is float. range[0 .. 360] in degrees*/ + TrOpacity /*!< Transform Opacity property of Layer and Group object , value type is float [ 0 .. 100] */ +}; + class LOT_EXPORT Surface { public: /** @@ -336,6 +368,29 @@ public: */ const LayerInfoList& layers() const; + /** + * @brief Sets property value for the specified {@link KeyPath}. This {@link KeyPath} can resolve + * to multiple contents. In that case, the callback's value will apply to all of them. + * + * Keypath should conatin object names separated by (.) and can handle globe(**) or wildchar(*). + * + * @usage + * To change fillcolor property of fill1 object in the layer1->group1->fill1 hirarchy to RED color + * + * player->setValue("layer1.group1.fill1", rlottie::Color(1, 0, 0); + * + * if all the color property inside group1 needs to be changed to GREEN color + * + * player->setValue("**.group1.**", rlottie::Color(0, 1, 0); + * + * @internal + */ + template + void setValue(const std::string &keypath, AnyValue value) + { + setValue(std::integral_constant{}, prop, keypath, value); + } + /** * @brief default destructor * @@ -344,6 +399,34 @@ public: ~Animation(); private: + enum class ValueType {Color,Point,Size,Float}; + static constexpr ValueType mapType(Property prop) { + switch (prop) { + case Property::FillColor: + case Property::StrokeColor: + return ValueType::Color; + case Property::FillOpacity: + case Property::StrokeOpacity: + case Property::StrokeWidth: + case Property::TrOpacity: + case Property::TrRotation: + return ValueType::Float; + case Property::TrAnchor: + case Property::TrPosition: + return ValueType::Point; + case Property::TrScale: + return ValueType::Size; + } + } + + void setValue(std::integral_constant, + Property, const std::string &, Color); + void setValue(std::integral_constant, + Property, const std::string &, float); + void setValue(std::integral_constant, + Property, const std::string &, Size); + void setValue(std::integral_constant, + Property, const std::string &, Point); /** * @brief default constructor * @@ -354,6 +437,7 @@ private: std::unique_ptr d; }; + } // namespace lotplayer #endif // _RLOTTIE_H_ diff --git a/src/lottie/CMakeLists.txt b/src/lottie/CMakeLists.txt index a81356b546..89a2b6836d 100644 --- a/src/lottie/CMakeLists.txt +++ b/src/lottie/CMakeLists.txt @@ -7,6 +7,7 @@ target_sources(rlottie "${CMAKE_CURRENT_LIST_DIR}/lottieproxymodel.cpp" "${CMAKE_CURRENT_LIST_DIR}/lottieparser.cpp" "${CMAKE_CURRENT_LIST_DIR}/lottieanimation.cpp" + "${CMAKE_CURRENT_LIST_DIR}/lottiekeypath.cpp" ) target_include_directories(rlottie diff --git a/src/lottie/lottieanimation.cpp b/src/lottie/lottieanimation.cpp index b8e067468f..d5376eaea1 100644 --- a/src/lottie/lottieanimation.cpp +++ b/src/lottie/lottieanimation.cpp @@ -51,6 +51,8 @@ public: renderTree(size_t frameNo, const VSize &size); const LayerInfoList& layerInfoList() const { return mModel->layerInfoList();} + void setValue(const std::string &keypath, LOTVariant &&value); + void removeFilter(const std::string &keypath, Property prop); private: std::string mFilePath; std::shared_ptr mModel; @@ -59,6 +61,12 @@ private: std::atomic mRenderInProgress; }; +void AnimationImpl::setValue(const std::string &keypath, LOTVariant &&value) +{ + if (keypath.empty()) return; + mCompItem->setValue(keypath, value); +} + const LOTLayerNode *AnimationImpl::renderTree(size_t frameNo, const VSize &size) { if (update(frameNo, size)) { @@ -306,6 +314,34 @@ const LayerInfoList& Animation::layers() const return d->layerInfoList(); } +void Animation::setValue(std::integral_constant,Property prop, + const std::string &keypath, + Color value) +{ + d->setValue(keypath, LOTVariant(prop, value)); +} + +void Animation::setValue(std::integral_constant, Property prop, + const std::string &keypath, + float value) +{ + d->setValue(keypath, LOTVariant(prop, value)); +} + +void Animation::setValue(std::integral_constant,Property prop, + const std::string &keypath, + Size value) +{ + d->setValue(keypath, LOTVariant(prop, value)); +} + +void Animation::setValue(std::integral_constant, Property prop, + const std::string &keypath, + Point value) +{ + d->setValue(keypath, LOTVariant(prop, value)); +} + Animation::Animation(): d(std::make_unique()) {} /* diff --git a/src/lottie/lottieitem.cpp b/src/lottie/lottieitem.cpp index 2da69815b6..dd5a113e88 100644 --- a/src/lottie/lottieitem.cpp +++ b/src/lottie/lottieitem.cpp @@ -1,4 +1,4 @@ -/* +/* * Copyright (c) 2018 Samsung Electronics Co., Ltd. All rights reserved. * * This library is free software; you can redistribute it and/or @@ -24,6 +24,7 @@ #include "vdasher.h" #include "vpainter.h" #include "vraster.h" +#include "lottiekeypath.h" /* Lottie Layer Rules * 1. time stretch is pre calculated and applied to all the properties of the @@ -32,6 +33,45 @@ * AE. which means (start frame > endFrame) 3. */ +static +bool transformProp(rlottie::Property prop) +{ + switch (prop) { + case rlottie::Property::TrAnchor: + case rlottie::Property::TrScale: + case rlottie::Property::TrOpacity: + case rlottie::Property::TrPosition: + case rlottie::Property::TrRotation: + return true; + default: + return false; + } +} +static +bool fillProp(rlottie::Property prop) +{ + switch (prop) { + case rlottie::Property::FillColor: + case rlottie::Property::FillOpacity: + return true; + default: + return false; + } +} + +static +bool strokeProp(rlottie::Property prop) +{ + switch (prop) { + case rlottie::Property::StrokeColor: + case rlottie::Property::StrokeOpacity: + case rlottie::Property::StrokeWidth: + return true; + default: + return false; + } +} + LOTCompItem::LOTCompItem(LOTModel *model) : mRootModel(model), mUpdateViewBox(false), mCurFrameNo(-1) { @@ -41,6 +81,12 @@ LOTCompItem::LOTCompItem(LOTModel *model) mViewSize = mCompData->size(); } +void LOTCompItem::setValue(const std::string &keypath, LOTVariant &value) +{ + LOTKeyPath key(keypath); + mRootLayer->resolveKeyPath(key, 0, value); +} + std::unique_ptr LOTCompItem::createLayerItem(LOTLayerData *layerData) { @@ -369,6 +415,50 @@ LOTLayerItem::LOTLayerItem(LOTLayerData *layerData): mLayerData(layerData) mLayerMask = std::make_unique(mLayerData); } +bool LOTLayerItem::resolveKeyPath(LOTKeyPath &keyPath, uint depth, + LOTVariant &value) +{ + if (!keyPath.matches(name(), depth)) { + return false; + } + + if (!keyPath.skip(name())) { + if (keyPath.fullyResolvesTo(name(), depth) && + transformProp(value.property())) { + //@TODO handle propery update. + } + } + return true; +} + +bool LOTShapeLayerItem::resolveKeyPath(LOTKeyPath &keyPath, uint depth, + LOTVariant &value) +{ + if (LOTLayerItem::resolveKeyPath(keyPath, depth, value)){ + if (keyPath.propagate(name(), depth)) { + uint newDepth = keyPath.nextDepth(name(), depth); + mRoot->resolveKeyPath(keyPath, newDepth, value); + } + return true; + } + return false; +} + +bool LOTCompLayerItem::resolveKeyPath(LOTKeyPath &keyPath, uint depth, + LOTVariant &value) +{ + if (LOTLayerItem::resolveKeyPath(keyPath, depth, value)) { + if (keyPath.propagate(name(), depth)) { + uint newDepth = keyPath.nextDepth(name(), depth); + for (const auto &layer : mLayers) { + layer->resolveKeyPath( keyPath, newDepth, value); + } + } + return true; + } + return false; +} + void LOTLayerItem::updateStaticProperty() { if (mParentLayer) mParentLayer->updateStaticProperty(); @@ -862,6 +952,56 @@ void LOTShapeLayerItem::renderList(std::vector &list) mRoot->renderList(list); } +bool LOTContentGroupItem::resolveKeyPath(LOTKeyPath &keyPath, uint depth, LOTVariant &value) +{ + if (!keyPath.matches(name(), depth)) { + return false; + } + + if (!keyPath.skip(name())) { + if (keyPath.fullyResolvesTo(name(), depth) && + transformProp(value.property())) { + //@TODO handle property update + } + } + + if (keyPath.propagate(name(), depth)) { + uint newDepth = keyPath.nextDepth(name(), depth); + for (auto &child : mContents) { + child->resolveKeyPath( keyPath, newDepth, value); + } + } + return true; +} + +bool LOTFillItem::resolveKeyPath(LOTKeyPath &keyPath, uint depth, LOTVariant &value) +{ + if (!keyPath.matches(mModel.name(), depth)) { + return false; + } + + if (keyPath.fullyResolvesTo(mModel.name(), depth) && + fillProp(value.property())) { + mModel.filter().addValue(value); + return true; + } + return false; +} + +bool LOTStrokeItem::resolveKeyPath(LOTKeyPath &keyPath, uint depth, LOTVariant &value) +{ + if (!keyPath.matches(mModel.name(), depth)) { + return false; + } + + if (keyPath.fullyResolvesTo(mModel.name(), depth) && + strokeProp(value.property())) { + mModel.filter().addValue(value); + return true; + } + return false; +} + LOTContentGroupItem::LOTContentGroupItem(LOTGroupData *data) : mData(data) { addChildren(mData); diff --git a/src/lottie/lottieitem.h b/src/lottie/lottieitem.h index 365bbd0752..49276dec7d 100644 --- a/src/lottie/lottieitem.h +++ b/src/lottie/lottieitem.h @@ -31,6 +31,7 @@ #include"rlottie.h" #include"vpainter.h" #include"vdrawable.h" +#include"lottiekeypath.h" V_USE_NAMESPACE @@ -46,7 +47,6 @@ class LOTLayerItem; class LOTMaskItem; class VDrawable; - class LOTCompItem { public: @@ -58,6 +58,7 @@ public: void buildRenderTree(); const LOTLayerNode * renderTree()const; bool render(const rlottie::Surface &surface); + void setValue(const std::string &keypath, LOTVariant &value); private: VMatrix mScaleMatrix; VSize mViewSize; @@ -86,11 +87,12 @@ public: }; typedef vFlag DirtyFlag; + class LOTLayerItem { public: + virtual ~LOTLayerItem() = default; LOTLayerItem(LOTLayerData *layerData); - virtual ~LOTLayerItem()= default; int id() const {return mLayerData->id();} int parentId() const {return mLayerData->parentId();} void setParentLayer(LOTLayerItem *parent){mParentLayer = parent;} @@ -105,6 +107,8 @@ public: bool visible() const; virtual void buildLayerNode(); LOTLayerNode * layerNode() const {return mLayerCNode.get();} + const std::string & name() const {return mLayerData->name();} + virtual bool resolveKeyPath(LOTKeyPath &keyPath, uint depth, LOTVariant &value); protected: virtual void updateContent() = 0; inline VMatrix combinedMatrix() const {return mCombinedMatrix;} @@ -136,6 +140,7 @@ public: void updateStaticProperty() final; void render(VPainter *painter, const VRle &mask, const VRle &matteRle) final; void buildLayerNode() final; + bool resolveKeyPath(LOTKeyPath &keyPath, uint depth, LOTVariant &value) override; protected: void updateContent() final; private: @@ -169,6 +174,7 @@ public: static std::unique_ptr createContentItem(LOTData *contentData); void renderList(std::vector &list)final; void buildLayerNode() final; + bool resolveKeyPath(LOTKeyPath &keyPath, uint depth, LOTVariant &value) override; protected: void updateContent() final; std::vector mCNodeList; @@ -250,11 +256,12 @@ class LOTTrimItem; class LOTContentItem { public: - virtual ~LOTContentItem()= default; + virtual ~LOTContentItem() = default; virtual void update(int frameNo, const VMatrix &parentMatrix, float parentAlpha, const DirtyFlag &flag) = 0; virtual void renderList(std::vector &){} void setParent(LOTContentItem *parent) {mParent = parent;} LOTContentItem *parent() const {return mParent;} + virtual bool resolveKeyPath(LOTKeyPath &keyPath, uint depth, LOTVariant &value) {return false;} private: LOTContentItem *mParent{nullptr}; }; @@ -265,12 +272,18 @@ public: LOTContentGroupItem(){} LOTContentGroupItem(LOTGroupData *data); void addChildren(LOTGroupData *data); - void update(int frameNo, const VMatrix &parentMatrix, float parentAlpha, const DirtyFlag &flag); + void update(int frameNo, const VMatrix &parentMatrix, float parentAlpha, const DirtyFlag &flag) override; void applyTrim(); void processTrimItems(std::vector &list); void processPaintItems(std::vector &list); - void renderList(std::vector &list); + void renderList(std::vector &list) override; const VMatrix & matrix() const { return mMatrix;} + const std::string & name() const + { + static const std::string TAG = "__"; + return mData ? mData->name() : TAG; + } + bool resolveKeyPath(LOTKeyPath &keyPath, uint depth, LOTVariant &value) override; protected: LOTGroupData *mData{nullptr}; std::vector> mContents; @@ -398,6 +411,7 @@ public: protected: void updateContent(int frameNo) final; void updateRenderNode() final; + bool resolveKeyPath(LOTKeyPath &keyPath, uint depth, LOTVariant &value) final; private: LOTProxyModel mModel; VColor mColor; @@ -424,6 +438,7 @@ public: protected: void updateContent(int frameNo) final; void updateRenderNode() final; + bool resolveKeyPath(LOTKeyPath &keyPath, uint depth, LOTVariant &value) final; private: LOTProxyModel mModel; LOTStrokeData *mData; diff --git a/src/lottie/lottiekeypath.cpp b/src/lottie/lottiekeypath.cpp new file mode 100644 index 0000000000..9507660220 --- /dev/null +++ b/src/lottie/lottiekeypath.cpp @@ -0,0 +1,81 @@ +#include "lottiekeypath.h" + +#include + +LOTKeyPath::LOTKeyPath(const std::string &keyPath) +{ + std::stringstream ss (keyPath); + std::string item; + + while (getline (ss, item, '.')) { + mKeys.push_back (item); + } +} + +bool LOTKeyPath::matches(const std::string &key, uint depth) +{ + if (skip(key)) { + // This is an object we programatically create. + return true; + } + if (depth > size()) { + return false; + } + if ((mKeys[depth] == key) || + (mKeys[depth] == "*") || + (mKeys[depth] == "**")) { + return true; + } + return false; +} + +uint LOTKeyPath::nextDepth(const std::string key, uint depth) { + if (skip(key)) { + // If it's a container then we added programatically and it isn't a part of the keypath. + return depth; + } + if ( mKeys[depth] != "**") { + // If it's not a globstar then it is part of the keypath. + return depth + 1; + } + if (depth == size()) { + // The last key is a globstar. + return depth; + } + if (mKeys[depth + 1] == key) { + // We are a globstar and the next key is our current key so consume both. + return depth + 2; + } + return depth; +} + +bool LOTKeyPath::fullyResolvesTo(const std::string key, uint depth) { + if (depth > mKeys.size()) { + return false; + } + + bool isLastDepth = (depth == size()); + + if (!isGlobstar(depth)) { + bool matches = (mKeys[depth] == key) || isGlob(depth); + return (isLastDepth || (depth == size() - 1 && endsWithGlobstar())) && matches; + } + + bool isGlobstarButNextKeyMatches = !isLastDepth && mKeys[depth + 1] == key; + if (isGlobstarButNextKeyMatches) { + return depth == size() - 1 || + (depth == size() - 2 && endsWithGlobstar()); + } + + if (isLastDepth) { + return true; + } + + if (depth + 1 < size()) { + // We are a globstar but there is more than 1 key after the globstar we we can't fully match. + return false; + } + // Return whether the next key (which we now know is the last one) is the same as the current + // key. + return mKeys[depth + 1] == key; + } diff --git a/src/lottie/lottiekeypath.h b/src/lottie/lottiekeypath.h new file mode 100644 index 0000000000..68ddde07d0 --- /dev/null +++ b/src/lottie/lottiekeypath.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef LOTTIEKEYPATH_H +#define LOTTIEKEYPATH_H + +#include +#include + +class LOTKeyPath{ +public: + LOTKeyPath(const std::string &keyPath); + bool matches(const std::string &key, uint depth); + uint nextDepth(const std::string key, uint depth); + bool fullyResolvesTo(const std::string key, uint depth); + + bool propagate(const std::string key, uint depth) { + return skip(key) ? true : (depth < size()) || (mKeys[depth] == "**"); + } + bool skip(const std::string &key) const { return key == "__";} +private: + bool isGlobstar(uint depth) const {return mKeys[depth] == "**";} + bool isGlob(uint depth) const {return mKeys[depth] == "*";} + bool endsWithGlobstar() const { return mKeys.back() == "**"; } + uint size() const {return mKeys.size() - 1;} +private: + std::vector mKeys; +}; + +#endif //LOTTIEKEYPATH_H diff --git a/src/lottie/lottiemodel.h b/src/lottie/lottiemodel.h index 8f4cd93e26..d26aab91f1 100644 --- a/src/lottie/lottiemodel.h +++ b/src/lottie/lottiemodel.h @@ -295,7 +295,7 @@ class LOTDataVisitor; class LOTData { public: - enum class Type { + enum class Type :short { Composition = 1, Layer, ShapeGroup, @@ -316,10 +316,12 @@ public: bool isStatic() const{return mStatic;} void setStatic(bool value) {mStatic = value;} bool hidden() const {return mHidden;} + const std::string& name() const{ return mName;} public: - bool mStatic{true}; - bool mHidden{false}; - LOTData::Type mType; + std::string mName; + bool mStatic{true}; + bool mHidden{false}; + LOTData::Type mType; }; class LOTGroupData: public LOTData diff --git a/src/lottie/lottieparser.cpp b/src/lottie/lottieparser.cpp index 9afdc2d54e..10ecd288a4 100644 --- a/src/lottie/lottieparser.cpp +++ b/src/lottie/lottieparser.cpp @@ -748,6 +748,7 @@ void LottieParserImpl::parseLayers(LOTCompositionData *comp) comp->mRootLayer->mRoot = true; comp->mRootLayer->mLayerType = LayerType::Precomp; comp->mRootLayer->mTransform = std::make_shared(); + comp->mRootLayer->mName = std::string("__"); bool staticFlag = true; RAPIDJSON_ASSERT(PeekType() == kArrayType); EnterArray(); @@ -857,7 +858,7 @@ std::shared_ptr LottieParserImpl::parseLayer(bool record) layer->mLayerType = getLayerType(); } else if (0 == strcmp(key, "nm")) { /*Layer name*/ RAPIDJSON_ASSERT(PeekType() == kStringType); - layerName = GetString(); + layer->mName = GetString(); } else if (0 == strcmp(key, "ind")) { /*Layer index in AE. Used for parenting and expressions.*/ RAPIDJSON_ASSERT(PeekType() == kNumberType); @@ -939,7 +940,7 @@ std::shared_ptr LottieParserImpl::parseLayer(bool record) layer->mCompRef = compRef; if (record) { - mLayerInfoList.push_back(LayerInfo(layerName, layer->mInFrame, layer->mOutFrame)); + mLayerInfoList.push_back(LayerInfo(layer->mName, layer->mInFrame, layer->mOutFrame)); } return sharedLayer; } @@ -1070,7 +1071,9 @@ std::shared_ptr LottieParserImpl::parseGroupObject() LOTShapeGroupData *group = sharedGroup.get(); while (const char *key = NextObjectKey()) { - if (0 == strcmp(key, "it")) { + if (0 == strcmp(key, "nm")) { + group->mName = GetString(); + } else if (0 == strcmp(key, "it")) { RAPIDJSON_ASSERT(PeekType() == kArrayType); EnterArray(); while (NextArrayValue()) { @@ -1105,7 +1108,9 @@ std::shared_ptr LottieParserImpl::parseRectObject() LOTRectData * obj = sharedRect.get(); while (const char *key = NextObjectKey()) { - if (0 == strcmp(key, "p")) { + if (0 == strcmp(key, "nm")) { + obj->mName = GetString(); + } else if (0 == strcmp(key, "p")) { parseProperty(obj->mPos); } else if (0 == strcmp(key, "s")) { parseProperty(obj->mSize); @@ -1134,7 +1139,9 @@ std::shared_ptr LottieParserImpl::parseEllipseObject() LOTEllipseData *obj = sharedEllipse.get(); while (const char *key = NextObjectKey()) { - if (0 == strcmp(key, "p")) { + if (0 == strcmp(key, "nm")) { + obj->mName = GetString(); + } else if (0 == strcmp(key, "p")) { parseProperty(obj->mPos); } else if (0 == strcmp(key, "s")) { parseProperty(obj->mSize); @@ -1160,7 +1167,9 @@ std::shared_ptr LottieParserImpl::parseShapeObject() LOTShapeData *obj = sharedShape.get(); while (const char *key = NextObjectKey()) { - if (0 == strcmp(key, "ks")) { + if (0 == strcmp(key, "nm")) { + obj->mName = GetString(); + } else if (0 == strcmp(key, "ks")) { parseShapeProperty(obj->mShape); } else if (0 == strcmp(key, "d")) { obj->mDirection = GetInt(); @@ -1188,7 +1197,9 @@ std::shared_ptr LottieParserImpl::parsePolystarObject() LOTPolystarData *obj = sharedPolystar.get(); while (const char *key = NextObjectKey()) { - if (0 == strcmp(key, "p")) { + if (0 == strcmp(key, "nm")) { + obj->mName = GetString(); + } else if (0 == strcmp(key, "p")) { parseProperty(obj->mPos); } else if (0 == strcmp(key, "pt")) { parseProperty(obj->mPointCount); @@ -1251,7 +1262,9 @@ std::shared_ptr LottieParserImpl::parseTrimObject() LOTTrimData * obj = sharedTrim.get(); while (const char *key = NextObjectKey()) { - if (0 == strcmp(key, "s")) { + if (0 == strcmp(key, "nm")) { + obj->mName = GetString(); + } else if (0 == strcmp(key, "s")) { parseProperty(obj->mStart); } else if (0 == strcmp(key, "e")) { parseProperty(obj->mEnd); @@ -1280,7 +1293,9 @@ std::shared_ptr LottieParserImpl::parseReapeaterObject() LOTRepeaterData *obj = sharedRepeater.get(); while (const char *key = NextObjectKey()) { - if (0 == strcmp(key, "c")) { + if (0 == strcmp(key, "nm")) { + obj->mName = GetString(); + } else if (0 == strcmp(key, "c")) { parseProperty(obj->mCopies); float maxCopy= 0.0; if (!obj->mCopies.isStatic()) { @@ -1326,7 +1341,9 @@ std::shared_ptr LottieParserImpl::parseTransformObject(bool dd if (ddd) obj->m3D = std::make_unique(); while (const char *key = NextObjectKey()) { - if (0 == strcmp(key, "a")) { + if (0 == strcmp(key, "nm")) { + obj->mName = GetString(); + } else if (0 == strcmp(key, "a")) { parseProperty(obj->mAnchor); } else if (0 == strcmp(key, "p")) { EnterObject(); @@ -1394,7 +1411,9 @@ std::shared_ptr LottieParserImpl::parseFillObject() LOTFillData * obj = sharedFill.get(); while (const char *key = NextObjectKey()) { - if (0 == strcmp(key, "c")) { + if (0 == strcmp(key, "nm")) { + obj->mName = GetString(); + } else if (0 == strcmp(key, "c")) { parseProperty(obj->mColor); } else if (0 == strcmp(key, "o")) { parseProperty(obj->mOpacity); @@ -1480,7 +1499,9 @@ std::shared_ptr LottieParserImpl::parseStrokeObject() LOTStrokeData *obj = sharedStroke.get(); while (const char *key = NextObjectKey()) { - if (0 == strcmp(key, "c")) { + if (0 == strcmp(key, "nm")) { + obj->mName = GetString(); + } else if (0 == strcmp(key, "c")) { parseProperty(obj->mColor); } else if (0 == strcmp(key, "o")) { parseProperty(obj->mOpacity); @@ -1561,7 +1582,9 @@ std::shared_ptr LottieParserImpl::parseGFillObject() LOTGFillData *obj = sharedGFill.get(); while (const char *key = NextObjectKey()) { - if (0 == strcmp(key, "r")) { + if (0 == strcmp(key, "nm")) { + obj->mName = GetString(); + } else if (0 == strcmp(key, "r")) { obj->mFillRule = getFillRule(); } else { parseGradientProperty(obj, key); @@ -1607,7 +1630,9 @@ std::shared_ptr LottieParserImpl::parseGStrokeObject() LOTGStrokeData *obj = sharedGStroke.get(); while (const char *key = NextObjectKey()) { - if (0 == strcmp(key, "w")) { + if (0 == strcmp(key, "nm")) { + obj->mName = GetString(); + } else if (0 == strcmp(key, "w")) { parseProperty(obj->mWidth); } else if (0 == strcmp(key, "lc")) { obj->mCapStyle = getLineCap(); @@ -2077,6 +2102,7 @@ public: vDebug << level << "{ " << layerType(obj->mLayerType) + << ", name: "<< obj->name() << ", id:" << obj->mId << " Pid:" << obj->mParentId << ", a:" << !obj->isStatic() << ", "<mMatteType) @@ -2120,7 +2146,7 @@ public: switch (obj->mType) { case LOTData::Type::Repeater: { auto r = static_cast(obj); - vDebug << level << "{ Repeater: a:" << !obj->isStatic() + vDebug << level << "{ Repeater: name: "<name()<<" , a:" << !obj->isStatic() << ", copies:" << r->maxCopies() << ", offset:" << r->offset(0); visitChildren(static_cast(obj), level); @@ -2128,7 +2154,7 @@ public: break; } case LOTData::Type::ShapeGroup: { - vDebug << level << "{ ShapeGroup: a:" << !obj->isStatic(); + vDebug << level << "{ ShapeGroup: name: "<name()<<" , a:" << !obj->isStatic(); visitChildren(static_cast(obj), level); vDebug << level << "} ShapeGroup"; break; @@ -2138,44 +2164,44 @@ public: break; } case LOTData::Type::Trim:{ - vDebug << level << "{ Trim: a:" << !obj->isStatic() << " }"; + vDebug << level << "{ Trim: name: "<name()<<" , a:" << !obj->isStatic() << " }"; break; } case LOTData::Type::Rect:{ - vDebug << level << "{ Rect: a:" << !obj->isStatic() << " }"; + vDebug << level << "{ Rect: name: "<name()<<" , a:" << !obj->isStatic() << " }"; break; } case LOTData::Type::Ellipse:{ - vDebug << level << "{ Ellipse: a:" << !obj->isStatic() << " }"; + vDebug << level << "{ Ellipse: name: "<name()<<" , a:" << !obj->isStatic() << " }"; break; } case LOTData::Type::Shape:{ - vDebug << level << "{ Shape: a:" << !obj->isStatic() << " }"; + vDebug << level << "{ Shape: name: "<name()<<" , a:" << !obj->isStatic() << " }"; break; } case LOTData::Type::Polystar:{ - vDebug << level << "{ Polystar: a:" << !obj->isStatic() << " }"; + vDebug << level << "{ Polystar: name: "<name()<<" , a:" << !obj->isStatic() << " }"; break; } case LOTData::Type::Transform:{ - vDebug << level << "{ Transform: a: " << !obj->isStatic() << " }"; + vDebug << level << "{ Transform: name: "<name()<<" , a: " << !obj->isStatic() << " }"; break; } case LOTData::Type::Stroke:{ - vDebug << level << "{ Stroke: a:" << !obj->isStatic() << " }"; + vDebug << level << "{ Stroke: name: "<name()<<" , a:" << !obj->isStatic() << " }"; break; } case LOTData::Type::GStroke:{ - vDebug << level << "{ GStroke: a:" << !obj->isStatic() << " }"; + vDebug << level << "{ GStroke: name: "<name()<<" , a:" << !obj->isStatic() << " }"; break; } case LOTData::Type::Fill:{ - vDebug << level << "{ Fill: a:" << !obj->isStatic() << " }"; + vDebug << level << "{ Fill: name: "<name()<<" , a:" << !obj->isStatic() << " }"; break; } case LOTData::Type::GFill:{ auto f = static_cast(obj); - vDebug << level << "{ GFill: a:" << !f->isStatic() + vDebug << level << "{ GFill: name: "<name()<<" , a:" << !f->isStatic() << ", ty:" << f->mGradientType << ", s:" << f->mStartPoint.value(0) << ", e:" << f->mEndPoint.value(0) << " }"; break; diff --git a/src/lottie/lottieproxymodel.h b/src/lottie/lottieproxymodel.h index b62292af28..54a7d52603 100644 --- a/src/lottie/lottieproxymodel.h +++ b/src/lottie/lottieproxymodel.h @@ -19,21 +19,131 @@ #ifndef LOTTIEPROXYMODEL_H #define LOTTIEPROXYMODEL_H +#include #include "lottiemodel.h" +#include "rlottie.h" + +// Naive way to implement std::variant +// refactor it when we move to c++17 +// users should make sure proper combination +// of id and value are passed while creating the object. +class LOTVariant +{ +public: + enum Type {Color, Point, Size, Float}; + LOTVariant(rlottie::Property prop, float v):property_(prop),valueType_(Type::Float),value_(v){} + LOTVariant(rlottie::Property prop, rlottie::Color col):property_(prop),valueType_(Type::Color),color_(col){} + LOTVariant(rlottie::Property prop, rlottie::Point pt):property_(prop),valueType_(Type::Point),pos_(pt){} + LOTVariant(rlottie::Property prop, rlottie::Size sz):property_(prop),valueType_(Type::Size),size_(sz){} + Type type() const {return valueType_;} + rlottie::Property property() const {return property_;} + float value() const {return value_;} + rlottie::Color color() const {return color_;} + rlottie::Point pos() const {return pos_;} + rlottie::Size size() const {return size_;} +public: + rlottie::Property property_; + Type valueType_; + union { + float value_; + rlottie::Color color_; + rlottie::Point pos_; + rlottie::Size size_; + }; +}; + +class LOTFilter +{ +public: + void addValue(LOTVariant &value) + { + uint index = static_cast(value.property()); + if (mBitset.test(index)) { + for (uint i=0; i < mFilters.size(); i++ ) { + if (mFilters[i].property() == value.property()) { + mFilters[i] = value; + break; + } + } + } else { + mBitset.set(index); + mFilters.push_back(value); + } + } + + void removeValue(LOTVariant &value) + { + uint index = static_cast(value.property()); + if (mBitset.test(index)) { + mBitset.reset(index); + for (uint i=0; i < mFilters.size(); i++ ) { + if (mFilters[i].property() == value.property()) { + mFilters.erase(mFilters.begin() + i); + break; + } + } + } + } + bool hasFilter(rlottie::Property prop) const + { + return mBitset.test(static_cast(prop)); + } + LottieColor color(rlottie::Property prop) const + { + rlottie::Color col = data(prop).color(); + return LottieColor(col.mr, col.mg, col.mb); + } + float opacity(rlottie::Property prop) const + { + float val = data(prop).value(); + return val/100; + } + float value(rlottie::Property prop) const + { + return data(prop).value(); + } +private: + LOTVariant data(rlottie::Property prop) const + { + for (uint i=0; i < mFilters.size(); i++ ) { + if (mFilters[i].property() == prop) { + return mFilters[i]; + } + } + return LOTVariant(prop, 0); + } + std::vector mFilters; + std::bitset<32> mBitset{0}; +}; template class LOTProxyModel { public: LOTProxyModel(T *model): _modelData(model) {} - void addValueProvider() {/* Impement*/} - void removeValueProvider() {/* Impement*/} - bool hasValueProvider() {return false;} - LottieColor color(int frame) const { return _modelData->color(frame);} - float opacity(int frame) const { return _modelData->opacity(frame);} - FillRule fillRule() const {return _modelData->fillRule();} - - float strokeWidth(int frame) const {return _modelData->strokeWidth(frame);} + LOTFilter& filter() {return mFilter;} + const std::string & name() const {return _modelData->name();} + LottieColor color(int frame) const + { + if (mFilter.hasFilter(rlottie::Property::StrokeColor)) { + return mFilter.color(rlottie::Property::StrokeColor); + } + return _modelData->color(frame); + } + float opacity(int frame) const + { + if (mFilter.hasFilter(rlottie::Property::StrokeOpacity)) { + return mFilter.opacity(rlottie::Property::StrokeOpacity); + } + return _modelData->opacity(frame); + } + float strokeWidth(int frame) const + { + if (mFilter.hasFilter(rlottie::Property::StrokeWidth)) { + return mFilter.value(rlottie::Property::StrokeWidth); + } + return _modelData->strokeWidth(frame); + } float meterLimit() const {return _modelData->meterLimit();} CapStyle capStyle() const {return _modelData->capStyle();} JoinStyle joinStyle() const {return _modelData->joinStyle();} @@ -41,7 +151,35 @@ public: int getDashInfo(int frameNo, float *array) const {return _modelData->getDashInfo(frameNo, array);} private: - T *_modelData; + T *_modelData; + LOTFilter mFilter; +}; + +template <> +class LOTProxyModel +{ +public: + LOTProxyModel(LOTFillData *model): _modelData(model) {} + LOTFilter& filter() {return mFilter;} + const std::string & name() const {return _modelData->name();} + LottieColor color(int frame) const + { + if (mFilter.hasFilter(rlottie::Property::FillColor)) { + return mFilter.color(rlottie::Property::FillColor); + } + return _modelData->color(frame); + } + float opacity(int frame) const + { + if (mFilter.hasFilter(rlottie::Property::FillOpacity)) { + return mFilter.opacity(rlottie::Property::FillOpacity); + } + return _modelData->opacity(frame); + } + FillRule fillRule() const {return _modelData->fillRule();} +private: + LOTFillData *_modelData; + LOTFilter mFilter; }; #endif // LOTTIEITEM_H diff --git a/src/lottie/meson.build b/src/lottie/meson.build index b49bbb2d56..a6d1856ba7 100644 --- a/src/lottie/meson.build +++ b/src/lottie/meson.build @@ -5,6 +5,7 @@ source_file += files('lottiemodel.cpp') source_file += files('lottieproxymodel.cpp') source_file += files('lottieanimation.cpp') source_file += files('lottieitem.cpp') +source_file += files('lottiekeypath.cpp') lottie_dep = declare_dependency(