From: Jaeun Choi Date: Wed, 29 Aug 2018 14:24:45 +0000 (+0900) Subject: lottie/example: enhanced lottieviewer example X-Git-Tag: submit/tizen/20180917.042405~51 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=5b53b71f4eb7b39c6474c6385e301cca57920771;p=platform%2Fcore%2Fuifw%2Flottie-player.git lottie/example: enhanced lottieviewer example Change-Id: I0eb2a8c528376397190c75b084e9510c3698c034 --- diff --git a/example/lottieview.cpp b/example/lottieview.cpp index 79ce8fb..82eba73 100644 --- a/example/lottieview.cpp +++ b/example/lottieview.cpp @@ -6,8 +6,12 @@ static Eina_Bool animator(void *data , double pos) { LottieView *view = static_cast(data); - view->seek(pos); - if (pos == 1.0) { + float nextPos = pos + view->mStartPos; + if (nextPos > 1.0) nextPos = 1.0; + + view->seek(nextPos); + if (nextPos == 1.0) { + view->mAnimator = NULL; view->finished(); return EINA_FALSE; } @@ -81,6 +85,38 @@ void LottieView::update(const std::vector &renderList) evas_object_vg_root_node_set(mVg, root); } +static void mImageDelCb(void *data, Evas *evas, Evas_Object *obj, void *) +{ + LottieView *lottie = (LottieView *)data; + + if (lottie->mImage != obj) return; + + lottie->mImage = NULL; + lottie->stop(); +} + +static void mVgDelCb(void *data, Evas *evas, Evas_Object *obj, void *) +{ + LottieView *lottie = (LottieView *)data; + if (lottie->mVg != obj) return; + + lottie->mVg = NULL; + lottie->stop(); +} + +void LottieView::initializeBufferObject(Evas *evas) +{ + if (mRenderMode) { + mImage = evas_object_image_filled_add(evas); + evas_object_image_colorspace_set(mImage, EVAS_COLORSPACE_ARGB8888); + evas_object_image_alpha_set(mImage, EINA_TRUE); + evas_object_event_callback_add(mImage, EVAS_CALLBACK_DEL, mImageDelCb, this); + } else { + mVg = evas_object_vg_add(evas); + evas_object_event_callback_add(mVg, EVAS_CALLBACK_DEL, mVgDelCb, this); + } +} + LottieView::LottieView(Evas *evas, bool renderMode, bool asyncRender):mVg(nullptr), mImage(nullptr) { mPalying = false; @@ -95,13 +131,7 @@ LottieView::LottieView(Evas *evas, bool renderMode, bool asyncRender):mVg(nullpt mRenderMode = renderMode; mAsyncRender = asyncRender; - if (mRenderMode) { - mImage = evas_object_image_filled_add(evas); - evas_object_image_colorspace_set(mImage, EVAS_COLORSPACE_ARGB8888); - evas_object_image_alpha_set(mImage, EINA_TRUE); - } else { - mVg = evas_object_vg_add(evas); - } + initializeBufferObject(evas); } LottieView::~LottieView() @@ -115,6 +145,14 @@ LottieView::~LottieView() delete mPlayer; } +Evas_Object *LottieView::getImage() { + if (mRenderMode) { + return mImage; + } else { + return mVg; + } +} + void LottieView::show() { if (mRenderMode) { @@ -139,16 +177,17 @@ void LottieView::seek(float pos) if (mPalying && mReverse) pos = 1.0 - pos; + mPos = pos; + if (mRenderMode) { LOTBuffer buf; evas_object_image_size_get(mImage, &buf.width, &buf.height); if (mAsyncRender) { if (mRenderTask.valid()) return; mDirty = true; - mPendingPos = pos; buf.buffer = (uint32_t *)evas_object_image_data_get(mImage, EINA_TRUE); buf.bytesPerLine = evas_object_image_stride_get(mImage); - mRenderTask = mPlayer->render(mPendingPos, buf); + mRenderTask = mPlayer->render(mPos, buf); mBuffer = buf; // to force a redraw evas_object_image_data_update_add(mImage, 0 , 0, buf.width, buf.height); @@ -168,6 +207,11 @@ void LottieView::seek(float pos) } } +float LottieView::getPos() +{ + return mPos; +} + void LottieView::render() { if (!mDirty) return; @@ -186,7 +230,7 @@ void LottieView::render() } mBuffer.buffer = nullptr; } else { - const std::vector &renderList = mPlayer->renderList(mPendingPos); + const std::vector &renderList = mPlayer->renderList(mPos); update(renderList); } } @@ -239,6 +283,8 @@ void LottieView::setRepeatMode(LottieView::RepeatMode mode) void LottieView::play() { + mStartPos = mPos; + if (mAnimator) ecore_animator_del(mAnimator); mAnimator = ecore_animator_timeline_add(mPlayer->playTime()/mSpeed, animator, this); mReverse = false; mCurCount = mRepeatCount; @@ -253,6 +299,10 @@ void LottieView::pause() void LottieView::stop() { mPalying = false; + if (mAnimator) { + ecore_animator_del(mAnimator); + mAnimator = NULL; + } } void LottieView::restart() @@ -263,6 +313,9 @@ void LottieView::restart() mReverse = !mReverse; else mReverse = false; + + mStartPos = 0; + if (mAnimator) ecore_animator_del(mAnimator); mAnimator = ecore_animator_timeline_add(mPlayer->playTime()/mSpeed, animator, this); } } diff --git a/example/lottieview.h b/example/lottieview.h index e3e02d5..c94247c 100644 --- a/example/lottieview.h +++ b/example/lottieview.h @@ -25,7 +25,7 @@ public: }; LottieView(Evas *evas, bool renderMode = true, bool asyncRender = true); ~LottieView(); - Evas_Object * getImage() { return mRenderMode ? mImage : mVg; } + Evas_Object *getImage(); void setSize(int w, int h); void setPos(int x, int y); void setFilePath(const char *filePath); @@ -39,11 +39,13 @@ public: long getTotalFrame() const { return mTotalFrame; } public: void seek(float pos); + float getPos(); void finished(); void play(); void pause(); void stop(); void render(); + void initializeBufferObject(Evas *evas); private: void createVgNode(LOTNode *node, Efl_VG *parent); void update(const std::vector &); @@ -67,7 +69,8 @@ public: bool mRenderMode; bool mAsyncRender; bool mDirty; - float mPendingPos; + float mStartPos; + float mPos; float mFrameRate; long mTotalFrame; std::future mRenderTask; diff --git a/example/lottieviewer.cpp b/example/lottieviewer.cpp index 9e80c55..1d0b2e3 100644 --- a/example/lottieviewer.cpp +++ b/example/lottieviewer.cpp @@ -2,6 +2,10 @@ #include "lottieview.h" #include #include +#include +#include +#include +#include using namespace std; @@ -9,13 +13,74 @@ typedef struct _AppInfo AppInfo; struct _AppInfo { LottieView *view; Evas_Object *layout; + Evas_Object *slider; + Evas_Object *button; + Ecore_Evas *ee; + Eina_Bool autoPlaying; }; +typedef struct _ItemData ItemData; +struct _ItemData { + int index; +}; + +Eina_List *jsonFiles; +bool renderMode = true; + +static void +_layout_del_cb(void *data, Evas *, Evas_Object *, void *) +{ + AppInfo *info = (AppInfo *)data; + if (info->view) delete info->view; + info->view = NULL; + + ecore_evas_data_set(info->ee, "AppInfo", NULL); + + free(info); +} + +static void +_update_frame_info(AppInfo *info, double pos) +{ + int frameNo = pos * info->view->getTotalFrame(); + char buf[64]; + + sprintf(buf, "%d / %ld", frameNo, info->view->getTotalFrame()); + elm_object_part_text_set(info->layout, "text", buf); +} + +static void +_toggle_start_button(AppInfo *info) +{ + if (!info->autoPlaying) + { + info->autoPlaying = EINA_TRUE; + info->view->play(); + elm_object_text_set(info->button, "Stop"); + } + else + { + info->autoPlaying = EINA_FALSE; + info->view->stop(); + elm_object_text_set(info->button, "Start"); + } +} + static void -_win_del_cb(void *data, Evas_Object *obj, void *event_info EINA_UNUSED) +_ee_pre_render_cb(Ecore_Evas *ee) { - LottieView *view = (LottieView *)data; - delete view; + AppInfo *info = (AppInfo *)ecore_evas_data_get(ee, "AppInfo"); + + if (info && info->autoPlaying && info->view) + { + float pos = info->view->getPos(); + _update_frame_info(info, pos); + elm_slider_value_set(info->slider, (double)pos); + info->view->render(); + + if (pos >= 1.0) + _toggle_start_button(info); + } } static void @@ -24,37 +89,34 @@ _slider_cb(void *data, Evas_Object *obj, void *event_info EINA_UNUSED) double val = elm_slider_value_get(obj); AppInfo *info = (AppInfo *)data; - int frameNo = val * info->view->getTotalFrame(); - char buf[64]; + _update_frame_info(info, val); - sprintf(buf, "%d / %ld", frameNo, info->view->getTotalFrame()); + if (!info->autoPlaying) + { + info->view->seek(val); + info->view->render(); + } +} - elm_object_part_text_set(info->layout, "text", buf); +static void +_button_clicked_cb(void *data, Evas_Object *obj, void *event_info) +{ + AppInfo *info = (AppInfo *)data; - info->view->seek(val); - info->view->render(); + _toggle_start_button(info); } -EAPI_MAIN int -elm_main(int argc EINA_UNUSED, char **argv EINA_UNUSED) +Evas_Object * +create_layout(Evas_Object *parent, char *file) { - Evas_Object *win, *layout, *slider, *image; - bool renderMode = true; + Evas_Object *layout, *slider, *image, *button; + Evas *e; + Ecore_Evas *ee; char buf[64]; - AppInfo appInfo; - - if (argc > 1) { - if (!strcmp(argv[1], "--disable-render")) - renderMode = false; - } - - elm_policy_set(ELM_POLICY_QUIT, ELM_POLICY_QUIT_LAST_WINDOW_CLOSED); - win = elm_win_util_standard_add("lottie", "LottieViewer"); - elm_win_autodel_set(win, EINA_TRUE); - evas_object_resize(win, 500, 700); - evas_object_show(win); + AppInfo *info = (AppInfo *)calloc(sizeof(AppInfo), 1); - layout = elm_layout_add(win); + //LAYOUT + layout = elm_layout_add(parent); evas_object_show(layout); evas_object_size_hint_weight_set(layout, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); @@ -62,29 +124,42 @@ elm_main(int argc EINA_UNUSED, char **argv EINA_UNUSED) edjPath +="layout.edj"; elm_layout_file_set(layout, edjPath.c_str(), "layout"); - elm_win_resize_object_add(win, layout); + //LOTTIEVIEW + LottieView *view = new LottieView(evas_object_evas_get(layout), renderMode); std::string filePath = DEMO_DIR; - filePath +="insta_camera.json"; + filePath +=file; - LottieView *view = new LottieView(evas_object_evas_get(win), renderMode); view->setFilePath(filePath.c_str()); view->setSize(500, 500); - evas_object_smart_callback_add(win, "delete,request", _win_del_cb, (void *)view); - + //IMAGE from LOTTIEVIEW image = view->getImage(); evas_object_show(image); evas_object_size_hint_min_set(image, 500, 500); elm_object_part_content_set(layout, "lottie", image); - appInfo.view = view; - appInfo.layout = layout; - + //SLIDER slider = elm_slider_add(layout); - evas_object_show(slider); elm_object_part_content_set(layout, "slider", slider); - evas_object_smart_callback_add(slider, "changed", _slider_cb, (void *)&appInfo); + evas_object_smart_callback_add(slider, "changed", _slider_cb, (void *)info); + + button = elm_button_add(layout); + elm_object_text_set(button, "Start"); + elm_object_part_content_set(layout, "button", button); + evas_object_smart_callback_add(button, "clicked", _button_clicked_cb, (void *)info); + + e = evas_object_evas_get(layout); + ee = ecore_evas_ecore_evas_get(e); + ecore_evas_data_set(ee, "AppInfo", info); + ecore_evas_callback_pre_render_set(ee, _ee_pre_render_cb); + + info->view = view; + info->layout = layout; + info->slider = slider; + info->button = button; + info->ee = ee; + evas_object_event_callback_add(layout, EVAS_CALLBACK_DEL, _layout_del_cb, (void *)info); sprintf(buf, "%d / %ld", 0, view->getTotalFrame()); elm_object_part_text_set(layout, "text", buf); @@ -92,6 +167,89 @@ elm_main(int argc EINA_UNUSED, char **argv EINA_UNUSED) view->seek(0.0); view->render(); + return layout; +} + +static void +_gl_selected_cb(void *data, Evas_Object *obj, void *event_info) +{ + Evas_Object *nf = (Evas_Object *)data; + Elm_Object_Item *it = (Elm_Object_Item *)event_info; + elm_genlist_item_selected_set(it, EINA_FALSE); + + Evas_Object *layout = create_layout(nf, (char *)eina_list_nth(jsonFiles, (elm_genlist_item_index_get(it) - 1))); + elm_naviframe_item_push(nf, NULL, NULL, NULL, layout, NULL); +} + +static char * +_gl_text_get(void *data, Evas_Object *obj, const char *part) +{ + ItemData *id = (ItemData *) data; + char *str = (char *)eina_list_nth(jsonFiles, id->index); + return strdup(str); +} + +static void +_gl_del(void *data, Evas_Object *obj) +{ +} + +EAPI_MAIN int +elm_main(int argc EINA_UNUSED, char **argv EINA_UNUSED) +{ + Evas_Object *win, *nf, *genlist; + Elm_Genlist_Item_Class *itc = elm_genlist_item_class_new(); + ItemData *itemData; + DIR *dir; + struct dirent *ent; + int i, fileCount = 0; + + if (argc > 1) { + if (!strcmp(argv[1], "--disable-render")) + renderMode = false; + } + + //WIN + elm_policy_set(ELM_POLICY_QUIT, ELM_POLICY_QUIT_LAST_WINDOW_CLOSED); + win = elm_win_util_standard_add("lottie", "LottieViewer"); + elm_win_autodel_set(win, EINA_TRUE); + evas_object_resize(win, 500, 700); + evas_object_show(win); + + //NAVIFRAME + nf = elm_naviframe_add(win); + evas_object_size_hint_weight_set(nf, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + elm_win_resize_object_add(win, nf); + evas_object_show(nf); + + //GENLIST + genlist = elm_genlist_add(nf); + elm_genlist_mode_set(genlist, ELM_LIST_COMPRESS); + evas_object_smart_callback_add(genlist, "selected", _gl_selected_cb, nf); + + itc->item_style = "default"; + itc->func.text_get = _gl_text_get; + itc->func.del = _gl_del; + + std::string rscPath = DEMO_DIR; + + dir = opendir(rscPath.c_str()); + while ((ent = readdir(dir)) != NULL) { + if (!strncmp(ent->d_name + (strlen(ent->d_name) - 4), "json", 4)) { + jsonFiles = eina_list_append(jsonFiles, strdup(ent->d_name)); + fileCount++; + } + } + closedir(dir); + + for (i = 0; i < fileCount; i++) { + itemData = (ItemData *)calloc(sizeof(ItemData), 1); + itemData->index = i; + elm_genlist_item_append(genlist, itc, (void *)itemData, NULL, ELM_GENLIST_ITEM_NONE, NULL, NULL); + } + + elm_naviframe_item_push(nf, "Lottie Viewer", NULL, NULL, genlist, NULL); + elm_run(); return 0; diff --git a/example/resource/layout.edc b/example/resource/layout.edc index f13e870..9754416 100644 --- a/example/resource/layout.edc +++ b/example/resource/layout.edc @@ -45,22 +45,51 @@ collections { align: 0.5 1.0; rel1.to_x: "left_pad"; rel1.relative: 1.0 1.0; - rel2.to_x: "right_pad"; + rel2.to_x: "button_left_pad"; rel2.relative: 0.0 1.0; + fixed: 0 1; } } spacer { "left_pad"; desc { state: "default" 0.0; + fixed: 1 0; min: 20 0; + align: 0.0 0.5; rel2.relative: 0.0 0.0; } } spacer { "right_pad"; desc { state: "default" 0.0; + fixed: 1 0; min: 20 0; + align: 1.0 0.5; rel1.relative: 1.0 0.0; } } + swallow { "button"; + desc { state: "default" 0.0; + fixed: 1 1; + min: 80 55; + align: 1.0 0.5; + rel1.to_x: "right_pad"; + rel1.to_y: "slider"; + rel1.relative: 0.0 0.5; + rel2.to_x: "right_pad"; + rel2.to_y: "slider"; + rel2.relative: 0.0 0.5; + } + } + spacer { "button_left_pad"; + desc { state: "default" 0.0; + fixed: 1 0; + min: 20 0; + align: 1.0 0.5; + rel1.to_x: "button"; + rel1.relative: 0.0 0.0; + rel2.to_x: "button"; + rel2.relative: 0.0 1.0; + } + } } } } diff --git a/example/resource/layout.edj b/example/resource/layout.edj index 38add6b..8a74b1a 100644 Binary files a/example/resource/layout.edj and b/example/resource/layout.edj differ