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