1 #include "e_efx_private.h"
2 
3 typedef struct E_Efx_Move_Data
4 {
5    E_EFX *e;
6    Ecore_Animator *anim;
7    E_Efx_Effect_Speed speed;
8    Evas_Point start;
9    Evas_Point change;
10    Evas_Point current;
11    int degrees;
12    E_Efx_End_Cb cb;
13    void *data;
14 } E_Efx_Move_Data;
15 
16 static void
_obj_del(E_Efx_Move_Data * emd,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)17 _obj_del(E_Efx_Move_Data *emd, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
18 {
19    if (emd->anim) ecore_animator_del(emd->anim);
20    emd->e->move_data = NULL;
21    if ((!emd->e->owner) && (!emd->e->followers)) e_efx_free(emd->e);
22    free(emd);
23 }
24 
25 static void
_move(E_EFX * e,int x,int y)26 _move(E_EFX *e, int x, int y)
27 {
28    e->x += x, e->y += y;
29    evas_object_move(e->obj, e->x, e->y);
30    //DBG("%p to (%d,%d)", e->obj, e->x, e->y);
31 }
32 
33 static Eina_Bool
_move_circle_cb(E_Efx_Move_Data * emd,double pos)34 _move_circle_cb(E_Efx_Move_Data *emd, double pos)
35 {
36    double pct, degrees;
37    Eina_List *l;
38    E_EFX *e;
39    double x, y, r, rad;
40    Evas_Coord xx, yy, ox, oy, w, h;
41 
42 
43    pct = ecore_animator_pos_map(pos, (Ecore_Pos_Map)emd->speed, 0, 0);
44    degrees = pct * emd->degrees;
45    ox = emd->e->x, oy = emd->e->y;
46    if (emd->e->resize_data)
47      w = emd->e->w, h = emd->e->h;
48    else
49      evas_object_geometry_get(emd->e->obj, NULL, NULL, &w, &h);
50    r = (degrees * M_PI) / 180.0;
51    rad = sqrt((emd->current.x + w/2.0 - emd->e->map_data.move_center->x) * (emd->current.x + w/2.0 - emd->e->map_data.move_center->x) +
52               (emd->current.y + h/2.0 - emd->e->map_data.move_center->y) * (emd->current.y + h/2.0 - emd->e->map_data.move_center->y));
53    x = emd->e->map_data.move_center->x + rad * cos(r);
54    y = emd->e->map_data.move_center->y + rad * sin(r);
55    x -= (double)w / 2.;
56    y -= (double)h / 2.;
57    xx = lround(x);
58    yy = lround(y);
59    //DBG("move: %g || %g,%g", degrees, x, y);
60    emd->e->x = xx, emd->e->y = yy;
61    evas_object_move(emd->e->obj, xx, yy);
62    e_efx_maps_apply(emd->e, emd->e->obj, NULL, E_EFX_MAPS_APPLY_ALL);
63    EINA_LIST_FOREACH(emd->e->followers, l, e)
64      {
65         _move(e, xx - ox, yy - oy);
66         e_efx_maps_apply(e, e->obj, NULL, E_EFX_MAPS_APPLY_ALL);
67      }
68 
69    if (pos < 1.0) return EINA_TRUE;
70 
71    E_EFX_QUEUE_CHECK(emd);
72    return EINA_TRUE;
73 }
74 
75 static Eina_Bool
_move_cb(E_Efx_Move_Data * emd,double pos)76 _move_cb(E_Efx_Move_Data *emd, double pos)
77 {
78    int x, y;
79    double pct;
80    Eina_List *l;
81    E_EFX *e;
82 
83    pct = ecore_animator_pos_map(pos, (Ecore_Pos_Map)emd->speed, 0, 0);
84    x = lround(pct * (double)emd->change.x) - emd->current.x;
85    y = lround(pct * (double)emd->change.y) - emd->current.y;
86    _e_efx_resize_adjust(emd->e, &x, &y);
87    _move(emd->e, x, y);
88    e_efx_maps_apply(emd->e, emd->e->obj, NULL, E_EFX_MAPS_APPLY_ALL);
89    EINA_LIST_FOREACH(emd->e->followers, l, e)
90      {
91         _move(e, x, y);
92         e_efx_maps_apply(e, e->obj, NULL, E_EFX_MAPS_APPLY_ALL);
93      }
94 
95    emd->current.x += x;
96    emd->current.y += y;
97    if (pos < 1.0) return EINA_TRUE;
98 
99    emd->anim = NULL;
100    E_EFX_QUEUE_CHECK(emd);
101    return EINA_TRUE;
102 }
103 
104 static void
_move_stop(Evas_Object * obj,Eina_Bool reset)105 _move_stop(Evas_Object *obj, Eina_Bool reset)
106 {
107    E_EFX *e;
108    E_Efx_Move_Data *emd;
109 
110    e = evas_object_data_get(obj, "e_efx-data");
111    if ((!e) || (!e->move_data)) return;
112    emd = e->move_data;
113    if (reset)
114      {
115         evas_object_move(obj, emd->start.x, emd->start.y);
116         evas_object_event_callback_del_full(obj, EVAS_CALLBACK_FREE, (Evas_Object_Event_Cb)_obj_del, emd);
117         if (e_efx_queue_complete(emd->e, emd))
118           e_efx_queue_process(emd->e);
119         _obj_del(emd, NULL, NULL, NULL);
120         INF("reset moved object %p", obj);
121      }
122    else
123      {
124         INF("stopped moved object %p", obj);
125         if (emd->anim) ecore_animator_del(emd->anim);
126         emd->anim = NULL;
127         if (e_efx_queue_complete(emd->e, emd))
128           e_efx_queue_process(emd->e);
129      }
130 }
131 
132 EAPI Eina_Bool
e_efx_move(Evas_Object * obj,E_Efx_Effect_Speed speed,const Evas_Point * end_point,double total_time,E_Efx_End_Cb cb,const void * data)133 e_efx_move(Evas_Object *obj, E_Efx_Effect_Speed speed, const Evas_Point *end_point, double total_time, E_Efx_End_Cb cb, const void *data)
134 {
135    E_EFX *e;
136    E_Efx_Move_Data *emd;
137    Evas_Coord x, y;
138 
139    EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EINA_FALSE);
140    if (!end_point) return EINA_FALSE;
141    if (total_time < 0.0) return EINA_FALSE;
142    if (speed > E_EFX_EFFECT_SPEED_SINUSOIDAL) return EINA_FALSE;
143 
144    e = evas_object_data_get(obj, "e_efx-data");
145    if (!e) e = e_efx_new(obj);
146    EINA_SAFETY_ON_NULL_RETURN_VAL(e, EINA_FALSE);
147 
148    evas_object_geometry_get(obj, &x, &y, NULL, NULL);
149    INF("move: %p - (%d,%d) -> (%d,%d) over %gs: %s", obj, x, y, end_point->x, end_point->y, total_time, e_efx_speed_str[speed]);
150    if (eina_dbl_exact(total_time, 0))
151      {
152         evas_object_move(obj, end_point->x, end_point->y);
153         return EINA_TRUE;
154      }
155    if (!e->move_data)
156      {
157         e->move_data = calloc(1, sizeof(E_Efx_Move_Data));
158         EINA_SAFETY_ON_NULL_RETURN_VAL(e->move_data, EINA_FALSE);
159         evas_object_event_callback_add(obj, EVAS_CALLBACK_FREE, (Evas_Object_Event_Cb)_obj_del, e->move_data);
160      }
161    emd = e->move_data;
162    emd->e = e;
163    emd->speed = speed;
164    e->x = x, e->y = y;
165    emd->change.x = end_point->x - x;
166    emd->change.y = end_point->y - y;
167    emd->current.x = emd->current.y = 0;
168    emd->cb = cb;
169    emd->data = (void*)data;
170    if (emd->anim) ecore_animator_del(emd->anim);
171    emd->anim = ecore_animator_timeline_add(total_time, (Ecore_Timeline_Cb)_move_cb, emd);
172    return EINA_TRUE;
173 }
174 
175 
176 EAPI Eina_Bool
e_efx_move_circle(Evas_Object * obj,E_Efx_Effect_Speed speed,const Evas_Point * center,int degrees,double total_time,E_Efx_End_Cb cb,const void * data)177 e_efx_move_circle(Evas_Object *obj, E_Efx_Effect_Speed speed, const Evas_Point *center, int degrees, double total_time, E_Efx_End_Cb cb, const void *data)
178 {
179    E_EFX *e;
180    E_Efx_Move_Data *emd;
181    Evas_Coord x, y;
182 
183    EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EINA_FALSE);
184    if (!degrees) return EINA_FALSE;
185    if (!center) return EINA_FALSE;
186    if (total_time < 0.0) return EINA_FALSE;
187    if (speed > E_EFX_EFFECT_SPEED_SINUSOIDAL) return EINA_FALSE;
188 
189    e = evas_object_data_get(obj, "e_efx-data");
190    if (!e) e = e_efx_new(obj);
191    EINA_SAFETY_ON_NULL_RETURN_VAL(e, EINA_FALSE);
192    if (!e_efx_move_center_init(e, center)) return EINA_FALSE;
193 
194    evas_object_geometry_get(obj, &x, &y, NULL, NULL);
195    INF("move: %p - (%d,%d) %d over %gs: %s", obj, x, y, degrees, total_time, e_efx_speed_str[speed]);
196    if (eina_dbl_exact(total_time, 0))
197      {
198      //   evas_object_move(obj, end_point->x, end_point->y);
199         return EINA_TRUE;
200      }
201    if (!e->move_data)
202      {
203         e->move_data = calloc(1, sizeof(E_Efx_Move_Data));
204         EINA_SAFETY_ON_NULL_RETURN_VAL(e->move_data, EINA_FALSE);
205         evas_object_event_callback_add(obj, EVAS_CALLBACK_FREE, (Evas_Object_Event_Cb)_obj_del, e->move_data);
206      }
207    emd = e->move_data;
208    emd->e = e;
209    emd->speed = speed;
210    e->x = emd->start.x = emd->current.x = x;
211    e->y = emd->start.y = emd->current.y = y;
212    emd->degrees = degrees;
213    emd->cb = cb;
214    emd->data = (void*)data;
215    if (emd->anim) ecore_animator_del(emd->anim);
216    emd->anim = ecore_animator_timeline_add(total_time, (Ecore_Timeline_Cb)_move_circle_cb, emd);
217    return EINA_TRUE;
218 }
219 
220 EAPI void
e_efx_move_reset(Evas_Object * obj)221 e_efx_move_reset(Evas_Object *obj)
222 {
223    _move_stop(obj, EINA_TRUE);
224 }
225 
226 EAPI void
e_efx_move_stop(Evas_Object * obj)227 e_efx_move_stop(Evas_Object *obj)
228 {
229    _move_stop(obj, EINA_FALSE);
230 }
231