efl_canvas_animation: fix numerical error on map effect calculation
authorJaehyun Cho <jae_hyun.cho@samsung.com>
Tue, 4 Jun 2019 09:52:14 +0000 (18:52 +0900)
committerHosang Kim <hosang12.kim@samsung.com>
Wed, 12 Jun 2019 05:15:56 +0000 (14:15 +0900)
Previously, for a single canvas animation, map effect was applied in
animator callback without resetting previously applied map effect.
This increased numerical error because each time map effect factors
(e.g. scale, degree) should be calculated based on the current map
coordinates.

To resolve this numerical error, now the previously applied map effect
is reset before applying the current map effect in animator callback.

src/lib/evas/canvas/efl_canvas_animation_player.c
src/lib/evas/canvas/efl_canvas_animation_private.h
src/lib/evas/canvas/efl_canvas_animation_rotate.c
src/lib/evas/canvas/efl_canvas_animation_scale.c
src/lib/evas/canvas/efl_canvas_animation_translate.c

index 42fb2c4..edb4d66 100644 (file)
@@ -107,6 +107,10 @@ _animator_cb(void *data)
         pd->progress = (double)(pd->is_direction_forward);
      }
 
+   /* The previously applied map effect should be reset before applying the
+    * current map effect. Otherwise, the incrementally added map effects
+    * increase numerical error. */
+   efl_gfx_mapping_reset(efl_animation_player_target_get(eo_obj));
    efl_animation_apply(anim, pd->progress, efl_animation_player_target_get(eo_obj));
 
    Efl_Canvas_Animation_Player_Event_Running event_running;
@@ -207,11 +211,14 @@ _efl_canvas_animation_player_efl_player_stop(Eo *eo_obj,
                                       Efl_Canvas_Animation_Player_Data *pd)
 {
    EFL_ANIMATION_PLAYER_ANIMATION_GET(eo_obj, anim);
+
+   //Reset the state of the target to the initial state
+   efl_gfx_mapping_reset(efl_animation_player_target_get(eo_obj));
+
    Eina_Bool play = efl_player_play_get(eo_obj);
    if (play)
      {
         efl_player_play_set(eo_obj, EINA_FALSE);
-        //Reset the state of the target to the initial state
         if ((efl_animation_final_state_keep_get(anim)) &&
             (efl_animation_repeat_mode_get(anim) != EFL_CANVAS_ANIMATION_REPEAT_MODE_REVERSE) &&
             (!(efl_animation_repeat_count_get(anim) & 1)))
@@ -223,14 +230,12 @@ _efl_canvas_animation_player_efl_player_stop(Eo *eo_obj,
         else
           {
              pd->progress = 0.0;
-             efl_gfx_mapping_reset(efl_animation_player_target_get(eo_obj));
           }
         efl_event_callback_call(eo_obj, EFL_ANIMATION_PLAYER_EVENT_ENDED, NULL);
      }
    else
      {
          pd->progress = 0.0;
-         efl_gfx_mapping_reset(efl_animation_player_target_get(eo_obj));
      }
 
    if (pd->auto_del) efl_del(eo_obj);
@@ -303,6 +308,11 @@ _efl_canvas_animation_player_efl_player_pos_set(Eo *eo_obj,
    EFL_ANIMATION_PLAYER_ANIMATION_GET(eo_obj, anim);
    double length = efl_animation_duration_get(anim);
    pd->progress = sec / length;
+
+   /* The previously applied map effect should be reset before applying the
+    * current map effect. Otherwise, the incrementally added map effects
+    * increase numerical error. */
+   efl_gfx_mapping_reset(efl_animation_player_target_get(eo_obj));
    efl_animation_apply(anim, pd->progress, efl_animation_player_target_get(eo_obj));
 }
 
index c1fe16f..c8f0609 100644 (file)
@@ -21,7 +21,7 @@ typedef struct _Efl_Canvas_Animation_Data
    Efl_Canvas_Animation_Data *pd = efl_data_scope_get(o, EFL_CANVAS_ANIMATION_CLASS)
 
 #define GET_STATUS(from, to, progress) \
-   ((from) + (((to) - (from)) * (progress)))
+   ((from * (1.0 - progress)) + (to * progress))
 
 #define FINAL_STATE_IS_REVERSE(anim) \
    ((efl_animation_repeat_mode_get(anim) == EFL_CANVAS_ANIMATION_REPEAT_MODE_REVERSE) && \
index c57f7e1..fe713de 100644 (file)
@@ -2,19 +2,6 @@
 
 #define MY_CLASS EFL_CANVAS_ANIMATION_ROTATE_CLASS
 
-static double
-_rotation_get(Eo *target)
-{
-   double x1, x2, y1, y2;
-   double theta;
-
-   efl_gfx_mapping_coord_absolute_get(target, 0, &x1, &y1, NULL);
-   efl_gfx_mapping_coord_absolute_get(target, 1, &x2, &y2, NULL);
-   theta = atan((y2 - y1) / (x2 - x1));
-
-   return theta * 180 / M_PI;
-}
-
 EOLIAN static void
 _efl_canvas_animation_rotate_rotate_set(Eo *eo_obj EINA_UNUSED,
                                  Efl_Canvas_Animation_Rotate_Data *pd,
@@ -115,26 +102,24 @@ _efl_canvas_animation_rotate_efl_canvas_animation_animation_apply(Eo *eo_obj,
                                                     Efl_Canvas_Object *target)
 {
    double new_degree;
-   double prev_degree;
 
    progress = efl_animation_apply(efl_super(eo_obj, MY_CLASS), progress, target);
    if (!target) return progress;
 
-   prev_degree = _rotation_get(target);
    new_degree = GET_STATUS(pd->from.degree, pd->to.degree, progress);
 
    if (pd->use_rel_pivot)
      {
         efl_gfx_mapping_rotate(target,
-                           new_degree - prev_degree,
-                           (pd->rel_pivot.obj) ? pd->rel_pivot.obj : target,
-                           pd->rel_pivot.cx, pd->rel_pivot.cy);
+                               new_degree,
+                               (pd->rel_pivot.obj) ? pd->rel_pivot.obj : target,
+                               pd->rel_pivot.cx, pd->rel_pivot.cy);
      }
    else
      {
         efl_gfx_mapping_rotate_absolute(target,
-                                    new_degree - prev_degree,
-                                    pd->abs_pivot.cx, pd->abs_pivot.cy);
+                                        new_degree,
+                                        pd->abs_pivot.cx, pd->abs_pivot.cy);
      }
 
    return progress;
index 90304de..1cccbc6 100644 (file)
@@ -2,27 +2,6 @@
 
 #define MY_CLASS EFL_CANVAS_ANIMATION_SCALE_CLASS
 
-static Efl_Canvas_Animation_Scale_Property
-_scale_get(Eo *target)
-{
-   double x1, x2, x3, y1, y2, y3, w, h;
-   Efl_Canvas_Animation_Scale_Property scale;
-   Eina_Rect geometry;
-
-   geometry = efl_gfx_entity_geometry_get(target);
-   efl_gfx_mapping_coord_absolute_get(target, 0, &x1, &y1, NULL);
-   efl_gfx_mapping_coord_absolute_get(target, 1, &x2, &y2, NULL);
-   efl_gfx_mapping_coord_absolute_get(target, 2, &x3, &y3, NULL);
-
-   w = sqrt(((x2 - x1) * (x2 - x1)) + ((y2 - y1) * (y2 - y1)));
-   h = sqrt(((x3 - x2) * (x3 - x2)) + ((y3 - y2) * (y3 - y2)));
-
-   scale.scale_x = w / geometry.w;
-   scale.scale_y = h / geometry.h;
-
-   return scale;
-}
-
 EOLIAN static void
 _efl_canvas_animation_scale_scale_set(Eo *eo_obj EINA_UNUSED,
                                Efl_Canvas_Animation_Scale_Data *pd,
@@ -149,30 +128,26 @@ _efl_canvas_animation_scale_efl_canvas_animation_animation_apply(Eo *eo_obj,
                                                    double progress,
                                                    Efl_Canvas_Object *target)
 {
-   Efl_Canvas_Animation_Scale_Property prev_scale;
    Efl_Canvas_Animation_Scale_Property new_scale;
 
    progress = efl_animation_apply(efl_super(eo_obj, MY_CLASS), progress, target);
    if (!target) return progress;
 
-   prev_scale = _scale_get(target);
    new_scale.scale_x = GET_STATUS(pd->from.scale_x, pd->to.scale_x, progress);
    new_scale.scale_y = GET_STATUS(pd->from.scale_y, pd->to.scale_y, progress);
 
    if (pd->use_rel_pivot)
      {
         efl_gfx_mapping_zoom(target,
-                         new_scale.scale_x / prev_scale.scale_x,
-                         new_scale.scale_y / prev_scale.scale_y,
-                         (pd->rel_pivot.obj) ? pd->rel_pivot.obj : target,
-                         pd->rel_pivot.cx, pd->rel_pivot.cy);
+                             new_scale.scale_x, new_scale.scale_y,
+                             (pd->rel_pivot.obj) ? pd->rel_pivot.obj : target,
+                             pd->rel_pivot.cx, pd->rel_pivot.cy);
      }
    else
      {
         efl_gfx_mapping_zoom_absolute(target,
-                                  new_scale.scale_x / prev_scale.scale_x,
-                                  new_scale.scale_y / prev_scale.scale_y,
-                                  pd->abs_pivot.cx, pd->abs_pivot.cy);
+                                      new_scale.scale_x, new_scale.scale_y,
+                                      pd->abs_pivot.cx, pd->abs_pivot.cy);
      }
 
    return progress;
index 42748ea..39a052c 100644 (file)
@@ -8,23 +8,6 @@ typedef struct __Translate_Property_Double
    double y;
 } _Translate_Property_Double;
 
-static _Translate_Property_Double
-_translation_get(Eo *target)
-{
-   double x1, x2, y1, y2;
-   _Translate_Property_Double translate;
-   Eina_Rect geometry;
-
-   geometry = efl_gfx_entity_geometry_get(target);
-
-   efl_gfx_mapping_coord_absolute_get(target, 0, &x1, &y1, NULL);
-   efl_gfx_mapping_coord_absolute_get(target, 2, &x2, &y2, NULL);
-   translate.x = ((x1 + x2) / 2.0) - (geometry.x + (geometry.w / 2.0));
-   translate.y = ((y1 + y2) / 2.0) - (geometry.y + (geometry.h / 2.0));
-
-   return translate;
-}
-
 EOLIAN static void
 _efl_canvas_animation_translate_translate_set(Eo *eo_obj EINA_UNUSED,
                                        Efl_Canvas_Animation_Translate_Data *pd,
@@ -115,13 +98,12 @@ _efl_canvas_animation_translate_efl_canvas_animation_animation_apply(Eo *eo_obj,
                                                        double progress,
                                                        Efl_Canvas_Object *target)
 {
-   _Translate_Property_Double prev;
    _Translate_Property_Double new;
+   Eina_Rect geometry;
 
    progress = efl_animation_apply(efl_super(eo_obj, MY_CLASS), progress, target);
    if (!target) return progress;
 
-   prev = _translation_get(target);
    if (pd->use_rel_move)
      {
         new.x = GET_STATUS(pd->from.move_x, pd->to.move_x, progress);
@@ -129,11 +111,12 @@ _efl_canvas_animation_translate_efl_canvas_animation_animation_apply(Eo *eo_obj,
      }
    else
      {
-        new.x = GET_STATUS(pd->from.x, pd->to.x, progress);
-        new.y = GET_STATUS(pd->from.y, pd->to.y, progress);
+        geometry = efl_gfx_entity_geometry_get(target);
+        new.x = GET_STATUS(pd->from.x, pd->to.x, progress) - geometry.x;
+        new.y = GET_STATUS(pd->from.y, pd->to.y, progress) - geometry.y;
      }
 
-   efl_gfx_mapping_translate(target, new.x - prev.x, new.y - prev.y, 0.0);
+   efl_gfx_mapping_translate(target, new.x, new.y, 0.0);
 
    return progress;
 }