summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Blumenkrantz <zmike@osg.samsung.com>2016-02-05 17:18:51 -0500
committerMike Blumenkrantz <zmike@osg.samsung.com>2016-02-05 17:18:51 -0500
commit1792af52a3ea9d0279831c1e1c24d6d245696b29 (patch)
tree9827c90a172992b5d25e3ccabcd7fca96d7697d0
parent389f810457c74621a2646b4fc5f315a73eddd2fd (diff)
anchor resize+move effects to smooth animations where top left corner is moving
if the top left corner of an object is moving during a resize, other corners will likely move due to rounding/timing issues in the animation. to ensure a smooth animation which looks good in these cases, it's necessary to create an anchor point upon starting the effect, performing adjustments on all move/resize operations for each animator tick to nudge the object back onto its anchor point also update resize test
-rw-r--r--src/bin/test_resize.c25
-rw-r--r--src/lib/efx_move.c1
-rw-r--r--src/lib/efx_private.h1
-rw-r--r--src/lib/efx_resize.c96
4 files changed, 115 insertions, 8 deletions
diff --git a/src/bin/test_resize.c b/src/bin/test_resize.c
index 05ec787..ac922ba 100644
--- a/src/bin/test_resize.c
+++ b/src/bin/test_resize.c
@@ -5,19 +5,37 @@
5#include <Efx.h> 5#include <Efx.h>
6#include <Ecore.h> 6#include <Ecore.h>
7#include <Ecore_Evas.h> 7#include <Ecore_Evas.h>
8#include <assert.h>
8 9
9static Evas *e; 10static Evas *e;
10 11
11static Eina_Bool _start(void *d __UNUSED__); 12static Eina_Bool _start(void *d __UNUSED__);
12static void _del(void *data __UNUSED__, Efx_Map_Data *emd __UNUSED__, Evas_Object *r); 13static void _del(void *data __UNUSED__, Efx_Map_Data *emd __UNUSED__, Evas_Object *r);
13 14
15static void
16_size_debug(void *data EINA_UNUSED, Evas *evas, void *event_info EINA_UNUSED)
17{
18 int x, y, w, h;
19 Evas_Object *r;
20
21 r = evas_object_name_find(evas, "rect");
22 if (evas_object_map_enable_get(r)) return;
23 evas_object_geometry_get(r, &x, &y, &w, &h);
24 if (!x) return;
25 assert(x == 25);
26 assert(y + h == 75 + 350);
27}
28
14static Evas_Object * 29static Evas_Object *
15rect_create(void) 30rect_create(void)
16{ 31{
17 Evas_Object *r; 32 Evas_Object *r;
33 int x, y, w, h;
34
18 r = evas_object_rectangle_add(e); 35 r = evas_object_rectangle_add(e);
19 evas_object_resize(r, 72, 72); 36 evas_object_resize(r, 75, 75);
20 evas_object_move(r, 25, 350); 37 evas_object_move(r, 25, 350);
38 evas_object_geometry_get(r, &x, &y, &w, &h);
21 evas_object_show(r); 39 evas_object_show(r);
22 return r; 40 return r;
23} 41}
@@ -34,12 +52,14 @@ _start(void *d __UNUSED__)
34{ 52{
35 Efx_Queue_Data *eqd; 53 Efx_Queue_Data *eqd;
36 Evas_Object *r; 54 Evas_Object *r;
55
37 r = rect_create(); 56 r = rect_create();
57 evas_object_name_set(r, "rect");
38 efx_fade(r, EFX_EFFECT_SPEED_ACCELERATE, &(Efx_Color){255, 0, 0}, 255, 0.0, NULL, NULL); 58 efx_fade(r, EFX_EFFECT_SPEED_ACCELERATE, &(Efx_Color){255, 0, 0}, 255, 0.0, NULL, NULL);
39 efx_queue_append(r, EFX_EFFECT_SPEED_LINEAR, 59 efx_queue_append(r, EFX_EFFECT_SPEED_LINEAR,
40 EFX_QUEUED_EFFECT(EFX_EFFECT_RESIZE(EFX_POINT(25, 25), 150, 400)), 2.0, NULL, NULL); 60 EFX_QUEUED_EFFECT(EFX_EFFECT_RESIZE(EFX_POINT(25, 25), 150, 400)), 2.0, NULL, NULL);
41 eqd = efx_queue_append(r, EFX_EFFECT_SPEED_LINEAR, 61 eqd = efx_queue_append(r, EFX_EFFECT_SPEED_LINEAR,
42 EFX_QUEUED_EFFECT(EFX_EFFECT_RESIZE(NULL, 72, 72)), 2.0, NULL, NULL); 62 EFX_QUEUED_EFFECT(EFX_EFFECT_RESIZE(NULL, 75, 75)), 2.0, NULL, NULL);
43 efx_queue_effect_attach(eqd, EFX_EFFECT_SPEED_LINEAR, 63 efx_queue_effect_attach(eqd, EFX_EFFECT_SPEED_LINEAR,
44 EFX_QUEUED_EFFECT(EFX_EFFECT_FADE(0, 0, 0, 0)), 2.0, _del, NULL); 64 EFX_QUEUED_EFFECT(EFX_EFFECT_FADE(0, 0, 0, 0)), 2.0, _del, NULL);
45 efx_queue_effect_attach(eqd, EFX_EFFECT_SPEED_LINEAR, 65 efx_queue_effect_attach(eqd, EFX_EFFECT_SPEED_LINEAR,
@@ -75,6 +95,7 @@ main(void)
75 95
76 ecore_evas_resize(ee, 450,450); 96 ecore_evas_resize(ee, 450,450);
77 ecore_evas_show(ee); 97 ecore_evas_show(ee);
98 evas_event_callback_add(e, EVAS_CALLBACK_RENDER_POST, _size_debug, r);
78 99
79 ecore_main_loop_begin(); 100 ecore_main_loop_begin();
80 ecore_evas_shutdown(); 101 ecore_evas_shutdown();
diff --git a/src/lib/efx_move.c b/src/lib/efx_move.c
index 9f2992d..650ac2b 100644
--- a/src/lib/efx_move.c
+++ b/src/lib/efx_move.c
@@ -80,6 +80,7 @@ _move_cb(Efx_Move_Data *emd, double pos)
80 pct = ecore_animator_pos_map(pos, emd->speed, 0, 0); 80 pct = ecore_animator_pos_map(pos, emd->speed, 0, 0);
81 x = lround(pct * (double)emd->change.x) - emd->current.x; 81 x = lround(pct * (double)emd->change.x) - emd->current.x;
82 y = lround(pct * (double)emd->change.y) - emd->current.y; 82 y = lround(pct * (double)emd->change.y) - emd->current.y;
83 _efx_resize_adjust(emd->e, &x, &y);
83 _move(emd->e->obj, x, y); 84 _move(emd->e->obj, x, y);
84 efx_maps_apply(emd->e, emd->e->obj, NULL, EFX_MAPS_APPLY_ALL); 85 efx_maps_apply(emd->e, emd->e->obj, NULL, EFX_MAPS_APPLY_ALL);
85 EINA_LIST_FOREACH(emd->e->followers, l, e) 86 EINA_LIST_FOREACH(emd->e->followers, l, e)
diff --git a/src/lib/efx_private.h b/src/lib/efx_private.h
index 3346bce..d26d9da 100644
--- a/src/lib/efx_private.h
+++ b/src/lib/efx_private.h
@@ -52,6 +52,7 @@ struct EFX
52void _efx_zoom_calc(void *, void *, Evas_Object *obj, Evas_Map *map); 52void _efx_zoom_calc(void *, void *, Evas_Object *obj, Evas_Map *map);
53void _efx_rotate_calc(void *, void *, Evas_Object *obj, Evas_Map *map); 53void _efx_rotate_calc(void *, void *, Evas_Object *obj, Evas_Map *map);
54void _efx_spin_calc(void *, void *, Evas_Object *obj, Evas_Map *map); 54void _efx_spin_calc(void *, void *, Evas_Object *obj, Evas_Map *map);
55void _efx_resize_adjust(EFX *e, int *x, int *y);
55 56
56#define EFX_MAPS_APPLY_ALL EINA_TRUE, EINA_TRUE, EINA_TRUE 57#define EFX_MAPS_APPLY_ALL EINA_TRUE, EINA_TRUE, EINA_TRUE
57#define EFX_MAPS_APPLY_ROTATE EINA_TRUE, EINA_FALSE, EINA_FALSE 58#define EFX_MAPS_APPLY_ROTATE EINA_TRUE, EINA_FALSE, EINA_FALSE
diff --git a/src/lib/efx_resize.c b/src/lib/efx_resize.c
index 427055e..1f92489 100644
--- a/src/lib/efx_resize.c
+++ b/src/lib/efx_resize.c
@@ -1,5 +1,13 @@
1#include "efx_private.h" 1#include "efx_private.h"
2 2
3typedef enum
4{
5 NONE,
6 TOP_RIGHT,
7 BOTTOM_LEFT,
8 BOTTOM_RIGHT
9} Anchor;
10
3typedef struct Efx_Resize_Data 11typedef struct Efx_Resize_Data
4{ 12{
5 EFX *e; 13 EFX *e;
@@ -9,6 +17,8 @@ typedef struct Efx_Resize_Data
9 int start_w, start_h; 17 int start_w, start_h;
10 Efx_End_Cb cb; 18 Efx_End_Cb cb;
11 void *data; 19 void *data;
20 Anchor anchor_type;
21 Evas_Point anchor;
12 Eina_Bool moving : 1; 22 Eina_Bool moving : 1;
13} Efx_Resize_Data; 23} Efx_Resize_Data;
14 24
@@ -23,6 +33,22 @@ _obj_del(void *data, Evas *evas __UNUSED__, Evas_Object *obj EINA_UNUSED, void *
23 free(erd); 33 free(erd);
24} 34}
25 35
36static void
37_resize_anchor(Efx_Resize_Data *erd)
38{
39 int x = 0, y = 0;
40 int cx, cy;
41
42 if (!erd->anchor_type) return;
43
44 _efx_resize_adjust(erd->e, &x, &y);
45 if ((!x) && (!y)) return;
46
47 evas_object_geometry_get(erd->e->obj, &cx, &cy, NULL, NULL);
48 x += cx, y += cy;
49 evas_object_move(erd->e->obj, x, y);
50}
51
26static Eina_Bool 52static Eina_Bool
27_resize_cb(Efx_Resize_Data *erd, double pos) 53_resize_cb(Efx_Resize_Data *erd, double pos)
28{ 54{
@@ -30,13 +56,18 @@ _resize_cb(Efx_Resize_Data *erd, double pos)
30 56
31 if (pos < 1.0) 57 if (pos < 1.0)
32 { 58 {
59 int w, h;
60
33 factor = ecore_animator_pos_map(pos, erd->speed, 0, 0); 61 factor = ecore_animator_pos_map(pos, erd->speed, 0, 0);
34 evas_object_resize(erd->e->obj, lround(factor * (erd->w - erd->start_w)) + erd->start_w, lround(factor * (erd->h - erd->start_h)) + erd->start_h); 62 w = lround(factor * (erd->w - erd->start_w)) + erd->start_w;
63 h = lround(factor * (erd->h - erd->start_h)) + erd->start_h;
64 evas_object_resize(erd->e->obj, w, h);
65 _resize_anchor(erd);
35 return EINA_TRUE; 66 return EINA_TRUE;
36 } 67 }
37 else 68 /* lround will usually be off by 1 at the end, so we manually set this here */
38 /* lround will usually be off by 1 at the end, so we manually set this here */ 69 evas_object_resize(erd->e->obj, erd->w, erd->h);
39 evas_object_resize(erd->e->obj, erd->w, erd->h); 70 _resize_anchor(erd);
40 71
41 erd->anim = NULL; 72 erd->anim = NULL;
42 EFX_QUEUE_CHECK(erd); 73 EFX_QUEUE_CHECK(erd);
@@ -80,11 +111,38 @@ _resize_stop(Evas_Object *obj, Eina_Bool reset)
80 } 111 }
81} 112}
82 113
114void
115_efx_resize_adjust(EFX *e, int *ax, int *ay)
116{
117 Efx_Resize_Data *erd = e->resize_data;
118 int x, y, w, h;
119
120 if (!erd) return;
121 evas_object_geometry_get(e->obj, &x, &y, &w, &h);
122 switch (erd->anchor_type)
123 {
124 case TOP_RIGHT:
125 *ax = erd->anchor.x - (x + w);
126 *ay = erd->anchor.y - y;
127 break;
128 case BOTTOM_LEFT:
129 *ax = erd->anchor.x - x;
130 *ay = erd->anchor.y - (y + h);
131 break;
132 case BOTTOM_RIGHT:
133 *ax = erd->anchor.x - (x + w);
134 *ay = erd->anchor.y - (y + h);
135 break;
136 default: break;
137 }
138}
139
83EAPI Eina_Bool 140EAPI Eina_Bool
84efx_resize(Evas_Object *obj, Efx_Effect_Speed speed, const Evas_Point *position, int w, int h, double total_time, Efx_End_Cb cb, const void *data) 141efx_resize(Evas_Object *obj, Efx_Effect_Speed speed, const Evas_Point *position, int w, int h, double total_time, Efx_End_Cb cb, const void *data)
85{ 142{
86 EFX *e; 143 EFX *e;
87 Efx_Resize_Data *erd; 144 Efx_Resize_Data *erd;
145 int x, y;
88 146
89 EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EINA_FALSE); 147 EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EINA_FALSE);
90 EINA_SAFETY_ON_TRUE_RETURN_VAL(w < 0, EINA_FALSE); 148 EINA_SAFETY_ON_TRUE_RETURN_VAL(w < 0, EINA_FALSE);
@@ -101,14 +159,40 @@ efx_resize(Evas_Object *obj, Efx_Effect_Speed speed, const Evas_Point *position,
101 } 159 }
102 160
103 erd->e = e; 161 erd->e = e;
162 erd->anchor_type = NONE;
104 erd->w = w; 163 erd->w = w;
105 erd->h = h; 164 erd->h = h;
106 erd->cb = cb; 165 erd->cb = cb;
107 erd->data = (void*)data; 166 erd->data = (void*)data;
108 evas_object_geometry_get(obj, NULL, NULL, &erd->start_w, &erd->start_h); 167 evas_object_geometry_get(obj, &x, &y, &erd->start_w, &erd->start_h);
109 INF("resize: %p || %dx%d => %dx%d %s over %gs", obj, erd->start_w, erd->start_h, w, h, efx_speed_str[speed], total_time); 168 INF("resize: %p || %dx%d => %dx%d %s over %gs", obj, erd->start_w, erd->start_h, w, h, efx_speed_str[speed], total_time);
110 if (position) 169 if (position && ((position->x != x) || (position->y != y)))
111 { 170 {
171 Evas_Point tr, bl, br;
172 Evas_Point atr, abl, abr;
173
174 tr = (Evas_Point){x + erd->start_w, y};
175 bl = (Evas_Point){x, y + erd->start_h};
176 br = (Evas_Point){x + erd->start_w, y + erd->start_h};
177 atr = (Evas_Point){position->x + w, position->y};
178 abl = (Evas_Point){position->x, position->y + h};
179 abr = (Evas_Point){position->x + w, position->y + h};
180 if (!memcmp(&tr, &atr, sizeof(Evas_Point)))
181 {
182 erd->anchor_type = TOP_RIGHT;
183 erd->anchor = tr;
184 }
185 else if (!memcmp(&bl, &abl, sizeof(Evas_Point)))
186 {
187 erd->anchor_type = BOTTOM_LEFT;
188 erd->anchor = bl;
189 }
190 else if (!memcmp(&br, &abr, sizeof(Evas_Point)))
191 {
192 erd->anchor_type = BOTTOM_RIGHT;
193 erd->anchor = br;
194 }
195
112 if (!efx_move(obj, speed, position, total_time, NULL, NULL)) 196 if (!efx_move(obj, speed, position, total_time, NULL, NULL))
113 { 197 {
114 evas_object_event_callback_del_full(obj, EVAS_CALLBACK_FREE, (Evas_Object_Event_Cb)_obj_del, e->resize_data); 198 evas_object_event_callback_del_full(obj, EVAS_CALLBACK_FREE, (Evas_Object_Event_Cb)_obj_del, e->resize_data);