forked from enlightenment/efl
efl_canvas_animation: fix numerical error on map effect calculation
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.
This commit is contained in:
parent
28adabd214
commit
9eb0b28cc7
|
@ -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));
|
||||
}
|
||||
|
||||
|
|
|
@ -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) && \
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue