From 118c812e6420122c01523c30dfd4eb9c968e3d15 Mon Sep 17 00:00:00 2001 From: Taehyub Kim Date: Thu, 6 May 2021 17:25:07 +0900 Subject: [PATCH] example: add user interaction sample(follow cursor). --- example/meson.build | 11 ++ example/user_interaction_follow_cursor.cpp | 201 +++++++++++++++++++++++++++++ 2 files changed, 212 insertions(+) create mode 100644 example/user_interaction_follow_cursor.cpp diff --git a/example/meson.build b/example/meson.build index 73474a6..7844ec8 100644 --- a/example/meson.build +++ b/example/meson.build @@ -43,3 +43,14 @@ executable('user_interaction_roll_in_out', dependencies : [elementary_dep, rive_cpp_dep, rive_tizen_dep, rive_tizen_renderer_dep], link_with: rive_tizen_lib, install : true) + +demo5_source_file = [ + 'user_interaction_follow_cursor.cpp' +] + +executable('user_interaction_follow_cursor', + demo5_source_file, + include_directories: headers, + dependencies : [elementary_dep, rive_cpp_dep, rive_tizen_dep, rive_tizen_renderer_dep], + link_with: rive_tizen_lib, + install : true) diff --git a/example/user_interaction_follow_cursor.cpp b/example/user_interaction_follow_cursor.cpp new file mode 100644 index 0000000..51a8c99 --- /dev/null +++ b/example/user_interaction_follow_cursor.cpp @@ -0,0 +1,201 @@ +#include +#include +#include +#include +#include + +#include "node.hpp" +#include "animation/linear_animation_instance.hpp" +#include "artboard.hpp" +#include "file.hpp" +#include "tvg_renderer.hpp" + +using namespace std; + +#define WIDTH 1000 +#define HEIGHT 700 +#define LIST_HEIGHT 200 + +static unique_ptr canvas = nullptr; +static rive::File* currentFile = nullptr; +static rive::Artboard* artboard = nullptr; +static rive::LinearAnimationInstance* animationInstance; +static Ecore_Animator *animator = nullptr; +static Eo* view = nullptr; +static vector rivefiles; +static double lastTime; +static Eo* statePopup = nullptr; + +static void deleteWindow(void *data, Evas_Object *obj, void *ev) +{ + elm_exit(); +} + +static void drawToCanvas(void* data, Eo* obj) +{ + if (canvas->draw() == tvg::Result::Success) canvas->sync(); +} + +static void loadRiveFile(const char* filename) +{ + lastTime = ecore_time_get(); + + // Load Rive File + FILE* fp = fopen(filename, "r"); + + fseek(fp, 0, SEEK_END); + size_t length = ftell(fp); + fseek(fp, 0, SEEK_SET); + + uint8_t* bytes = new uint8_t[length]; + if (fread(bytes, 1, length, fp) != length) + { + delete[] bytes; + fprintf(stderr, "failed to read all of %s\n", filename); + return; + } + + auto reader = rive::BinaryReader(bytes, length); + rive::File* file = nullptr; + auto result = rive::File::import(reader, &file); + if (result != rive::ImportResult::success) + { + delete[] bytes; + fprintf(stderr, "failed to import %s\n", filename); + return; + } + + artboard = file->artboard(); + artboard->advance(0.0f); + + delete animationInstance; + animationInstance = nullptr; + + auto animation = artboard->firstAnimation(); + if (animation) animationInstance = new rive::LinearAnimationInstance(animation); + + delete currentFile; + currentFile = file; + + delete[] bytes; +} + +Eina_Bool animationLoop(void *data) +{ + canvas->clear(); + + double currentTime = ecore_time_get(); + float elapsed = currentTime - lastTime; + lastTime = currentTime; + + if (!artboard) return ECORE_CALLBACK_RENEW; + + animationInstance->advance(elapsed); + animationInstance->apply(artboard); + + artboard->advance(elapsed); + + rive::TvgRenderer renderer(canvas.get()); + renderer.save(); + renderer.align(rive::Fit::contain, + rive::Alignment::center, + rive::AABB(0, 0, WIDTH, HEIGHT), + artboard->bounds()); + artboard->draw(&renderer); + renderer.restore(); + + evas_object_image_pixels_dirty_set(view, EINA_TRUE); + evas_object_image_data_update_add(view, 0, 0, WIDTH, HEIGHT); + + return ECORE_CALLBACK_RENEW; +} + +static void runExample(uint32_t* buffer) +{ + std::string path = RIVE_FILE_DIR; + path.append("runtime_color_change.riv"); + loadRiveFile(path.c_str()); + + //Create a Canvas + canvas = tvg::SwCanvas::gen(); + canvas->target(buffer, WIDTH, WIDTH, HEIGHT, tvg::SwCanvas::ARGB8888); + animator = ecore_animator_add(animationLoop, nullptr); +} + +static void cleanExample() +{ + delete animationInstance; +} + +static void mouseMoveCb(void *data, Evas *evas EINA_UNUSED, Evas_Object *obj, void *event_info) +{ + Evas_Event_Mouse_Move *ev = (Evas_Event_Mouse_Move*)event_info; + static bool preIn = false; + static bool isIn = false; + + int viewx, viewy; + evas_object_geometry_get(obj, &viewx, &viewy, nullptr, nullptr); + + // Viewx and viewy are the view start position + int posx = ev->cur.canvas.x - viewx; + // 250 is the constant for align y center + int posy = ev->cur.canvas.y - viewy + 250; + + // Get the root instance + auto instance = artboard->find("root"); + auto node = instance->as(); + + // The resource scale is 0.5, so It should be divided by 2 + node->x(posx / 2); + node->y(posy / 2); +} + +static void setupScreen(uint32_t* buffer) +{ + Eo* win = elm_win_util_standard_add(nullptr, "Rive Viewer"); + evas_object_smart_callback_add(win, "delete,request", deleteWindow, 0); + + Eo* box = elm_box_add(win); + evas_object_size_hint_weight_set(box, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + elm_win_resize_object_add(win, box); + evas_object_show(box); + + view = evas_object_image_filled_add(evas_object_evas_get(box)); + evas_object_image_size_set(view, WIDTH, HEIGHT); + evas_object_image_data_set(view, buffer); + evas_object_image_pixels_get_callback_set(view, drawToCanvas, nullptr); + evas_object_image_pixels_dirty_set(view, EINA_TRUE); + evas_object_image_data_update_add(view, 0, 0, WIDTH, HEIGHT); + evas_object_size_hint_weight_set(view, EVAS_HINT_EXPAND, 0.0); + evas_object_size_hint_min_set(view, WIDTH, HEIGHT); + evas_object_show(view); + elm_box_pack_end(box, view); + + evas_object_event_callback_add(view, EVAS_CALLBACK_MOUSE_MOVE, mouseMoveCb, nullptr); + + evas_object_resize(win, WIDTH, HEIGHT + LIST_HEIGHT); + evas_object_show(win); +} + +int main(int argc, char **argv) +{ + static uint32_t buffer[WIDTH * HEIGHT]; + + tvg::Initializer::init(tvg::CanvasEngine::Sw, thread::hardware_concurrency()); + + elm_init(argc, argv); + + setupScreen(buffer); + + runExample(buffer); + + elm_run(); + + cleanExample(); + + elm_shutdown(); + + tvg::Initializer::term(tvg::CanvasEngine::Sw); + + return 0; +} -- 2.7.4