examples/lottie: Add example for the Marker

Co-authored-by: Jinny You <jinny@lottiefiles.com>
This commit is contained in:
Lucas Niu 2024-04-12 15:44:23 +09:00 committed by Hermet Park
parent 3af9faf116
commit b7ced09fef
2 changed files with 90 additions and 54 deletions

View file

@ -19,46 +19,60 @@
#include "Common.h" #include "Common.h"
#include <thorvg_lottie.h> #include <thorvg_lottie.h>
#include <vector>
/************************************************************************/ /************************************************************************/
/* Drawing Commands */ /* Drawing Commands */
/************************************************************************/ /************************************************************************/
static unique_ptr<tvg::LottieAnimation> animation; #define NUM_PER_ROW 2
static Elm_Transit *transit; #define NUM_PER_COL 1
static bool updated = false; #define SIZE (WIDTH/NUM_PER_ROW)
void tvgUpdateCmds(tvg::Canvas* canvas, tvg::LottieAnimation* animation, float progress) static int counter = 0;
static std::vector<unique_ptr<tvg::LottieAnimation>> animations;
static std::vector<Elm_Transit*> transitions;
static tvg::Canvas* canvas;
void lottieSlotCmds(tvg::LottieAnimation* animation)
{ {
if (updated || !canvas) return; const char* slotJson = R"({"gradient_fill":{"p":{"a":0,"k":[0,0.1,0.1,0.2,1,1,0.1,0.2,0.1,1]}}})";
if (animation->override(slotJson) == tvg::Result::Success) {
//Update animation frame only when it's changed
if (animation->frame(animation->totalFrame() * progress) == tvg::Result::Success) {
canvas->update(); canvas->update();
updated = true; } else {
cout << "Failed to override the slot" << endl;
} }
} }
void tvgDrawCmds(tvg::Canvas* canvas) void lottieMarkerCmds(tvg::LottieAnimation* animation)
{ {
if (animation->segment("sectionC") != tvg::Result::Success) {
cout << "Failed to segment by the marker" << endl;
}
}
void lottieDirCallback(const char* name, const char* path, void* data)
{
if (counter >= NUM_PER_ROW * NUM_PER_COL) return;
char buf[PATH_MAX];
snprintf(buf, sizeof(buf), "/%s/%s", path, name);
//Animation Controller //Animation Controller
animation = tvg::LottieAnimation::gen(); auto animation = tvg::LottieAnimation::gen();
auto picture = animation->picture(); auto picture = animation->picture();
//Background if (picture->load(buf) != tvg::Result::Success) {
auto shape = tvg::Shape::gen();
shape->appendRect(0, 0, WIDTH, HEIGHT);
shape->fill(50, 50, 50);
if (canvas->push(std::move(shape)) != tvg::Result::Success) return;
const char* slotJson = R"({"gradient_fill":{"p":{"a":0,"k":[0,0.1,0.1,0.2,1,1,0.1,0.2,0.1,1]}}})";
if (picture->load(EXAMPLE_DIR"/lottie/extensions/slotsample.json") != tvg::Result::Success) {
cout << "Lottie is not supported. Did you enable Lottie Loader?" << endl; cout << "Lottie is not supported. Did you enable Lottie Loader?" << endl;
return; return;
} }
canvas->push(tvg::cast(picture));
if (!strcmp(name, "slotsample.json")) lottieSlotCmds(animation.get());
else if (!strcmp(name, "marker_sample.json")) lottieMarkerCmds(animation.get());
else return;
//image scaling preserving its aspect ratio //image scaling preserving its aspect ratio
float scale; float scale;
float shiftX = 0.0f, shiftY = 0.0f; float shiftX = 0.0f, shiftY = 0.0f;
@ -66,30 +80,49 @@ void tvgDrawCmds(tvg::Canvas* canvas)
picture->size(&w, &h); picture->size(&w, &h);
if (w > h) { if (w > h) {
scale = WIDTH / w; scale = SIZE / w;
shiftY = (HEIGHT - h * scale) * 0.5f; shiftY = (SIZE - h * scale) * 0.5f;
} else { } else {
scale = HEIGHT / h; scale = SIZE / h;
shiftX = (WIDTH - w * scale) * 0.5f; shiftX = (SIZE - w * scale) * 0.5f;
} }
picture->scale(scale); picture->scale(scale);
picture->translate(shiftX, shiftY); picture->translate((counter % NUM_PER_ROW) * SIZE + shiftX, (counter / NUM_PER_ROW) * (HEIGHT / NUM_PER_COL) + shiftY);
canvas->push(tvg::cast(picture)); animations.push_back(std::move(animation));
//Override slot data cout << "Lottie: " << buf << endl;
if (animation->override(slotJson) == tvg::Result::Success) {
canvas->update(); counter++;
} else {
cout << "Failed to override the slot" << endl;
} }
void tvgUpdateCmds(Elm_Transit_Effect *effect, Elm_Transit* transit, double progress)
{
auto animation = static_cast<tvg::Animation*>(effect);
animation->frame(animation->totalFrame() * progress);
}
void tvgDrawCmds(tvg::Canvas* canvas)
{
//Background
auto shape = tvg::Shape::gen();
shape->appendRect(0, 0, WIDTH, HEIGHT);
shape->fill(75, 75, 75);
if (canvas->push(std::move(shape)) != tvg::Result::Success) return;
eina_file_dir_list(EXAMPLE_DIR"/lottie/extensions", EINA_FALSE, lottieDirCallback, canvas);
//Run animation loop //Run animation loop
for (auto& animation : animations) {
Elm_Transit* transit = elm_transit_add();
elm_transit_effect_add(transit, tvgUpdateCmds, animation.get(), nullptr);
elm_transit_duration_set(transit, animation->duration()); elm_transit_duration_set(transit, animation->duration());
elm_transit_repeat_times_set(transit, -1); elm_transit_repeat_times_set(transit, -1);
elm_transit_go(transit); elm_transit_go(transit);
} }
}
/************************************************************************/ /************************************************************************/
@ -104,7 +137,9 @@ void tvgSwTest(uint32_t* buffer)
swCanvas = tvg::SwCanvas::gen(); swCanvas = tvg::SwCanvas::gen();
swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT, tvg::SwCanvas::ARGB8888); swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT, tvg::SwCanvas::ARGB8888);
canvas = swCanvas.get();
tvgDrawCmds(swCanvas.get()); tvgDrawCmds(swCanvas.get());
} }
void drawSwView(void* data, Eo* obj) void drawSwView(void* data, Eo* obj)
@ -112,20 +147,21 @@ void drawSwView(void* data, Eo* obj)
//It's not necessary to clear buffer since it has a solid background //It's not necessary to clear buffer since it has a solid background
//swCanvas->clear(false); //swCanvas->clear(false);
//canvas update
swCanvas->update();
if (swCanvas->draw() == tvg::Result::Success) { if (swCanvas->draw() == tvg::Result::Success) {
swCanvas->sync(); swCanvas->sync();
updated = false;
} }
} }
void transitSwCb(Elm_Transit_Effect *effect, Elm_Transit* transit, double progress) Eina_Bool animatorSwCb(void *data)
{ {
tvgUpdateCmds(swCanvas.get(), animation.get(), progress); Eo* img = (Eo*) data;
//Update Efl Canvas
Eo* img = (Eo*) effect;
evas_object_image_data_update_add(img, 0, 0, WIDTH, HEIGHT); evas_object_image_data_update_add(img, 0, 0, WIDTH, HEIGHT);
evas_object_image_pixels_dirty_set(img, EINA_TRUE); evas_object_image_pixels_dirty_set(img, EINA_TRUE);
return ECORE_CALLBACK_RENEW;
} }
@ -147,7 +183,9 @@ void initGLview(Evas_Object *obj)
glCanvas->target(targetId, WIDTH, HEIGHT); glCanvas->target(targetId, WIDTH, HEIGHT);
canvas = glCanvas.get();
tvgDrawCmds(glCanvas.get()); tvgDrawCmds(glCanvas.get());
} }
void drawGLview(Evas_Object *obj) void drawGLview(Evas_Object *obj)
@ -161,10 +199,11 @@ void drawGLview(Evas_Object *obj)
} }
} }
void transitGlCb(Elm_Transit_Effect *effect, Elm_Transit* transit, double progress) Eina_Bool animatorGlCb(void *data)
{ {
tvgUpdateCmds(glCanvas.get(), animation.get(), progress); elm_glview_changed_set((Evas_Object*)data);
elm_glview_changed_set((Evas_Object*)effect);
return ECORE_CALLBACK_RENEW;
} }
@ -189,24 +228,20 @@ int main(int argc, char **argv)
elm_init(argc, argv); elm_init(argc, argv);
transit = elm_transit_add();
if (tvgEngine == tvg::CanvasEngine::Sw) { if (tvgEngine == tvg::CanvasEngine::Sw) {
auto view = createSwView(1024, 1024); auto view = createSwView(1280, 1280);
elm_transit_effect_add(transit, transitSwCb, view, nullptr); ecore_animator_add(animatorSwCb, view);
} else { } else {
auto view = createGlView(1024, 1024); auto view = createGlView(1280, 1280);
elm_transit_effect_add(transit, transitGlCb, view, nullptr); ecore_animator_add(animatorGlCb, view);
} }
elm_run(); elm_run();
elm_transit_del(transit);
elm_shutdown(); elm_shutdown();
//Terminate ThorVG Engine //Terminate ThorVG Engine
tvg::Initializer::term(); tvg::Initializer::term();
} else { } else {
cout << "engine is not supported" << endl; cout << "engine is not supported" << endl;
} }

File diff suppressed because one or more lines are too long