add a namespaced version of efx

this will eventually be merged into the efl tree but the current release
cycle is not a good time for it
This commit is contained in:
Mike Blumenkrantz 2016-03-02 15:13:16 -05:00
parent d4996e2db3
commit d3fe687ada
19 changed files with 3527 additions and 1 deletions

View File

@ -1,10 +1,26 @@
DISTCLEANFILES += src/bin/e_fm_shared_types.h
efx_files = \
src/bin/efx/efx_bumpmapping.c \
src/bin/efx/efx.c \
src/bin/efx/efx_fade.c \
src/bin/efx/efx_helpers.c \
src/bin/efx/efx_move.c \
src/bin/efx/efx_pan.c \
src/bin/efx/e_efx_private.h \
src/bin/efx/efx_queue.c \
src/bin/efx/efx_resize.c \
src/bin/efx/efx_rotate.c \
src/bin/efx/efx_spin.c \
src/bin/efx/efx_util.c \
src/bin/efx/efx_zoom.c
E_CPPFLAGS = \
-I$(top_builddir) \
-I$(top_builddir)/src/bin \
-I$(top_srcdir) \
-I$(top_srcdir)/src/bin \
-I$(top_srcdir)/src/bin/efx \
-I$(top_srcdir)/src/bin/generated \
@e_cflags@ \
@cf_cflags@ \
@ -43,6 +59,7 @@ internal_bin_PROGRAMS += src/bin/enlightenment_ckpasswd
endif
ENLIGHTENMENTHEADERS = \
src/bin/efx/e_Efx.h \
src/bin/e_about.h \
src/bin/e_acpi.h \
src/bin/e_actions.h \
@ -359,7 +376,8 @@ src/bin/e_xkb.c \
src/bin/e_xinerama.c \
src/bin/e_zoomap.c \
src/bin/e_zone.c \
$(ENLIGHTENMENTHEADERS)
$(ENLIGHTENMENTHEADERS) \
$(efx_files)
if ! HAVE_WAYLAND_ONLY
enlightenment_src += \

View File

@ -129,6 +129,7 @@ void *alloca (size_t);
# include <Eio.h>
# include <Emotion.h>
# include <Elementary.h>
# include "e_Efx.h"
# ifdef HAVE_WAYLAND
# include <Ecore_Wl2.h>

View File

@ -3,6 +3,7 @@ EFM_CPPFLAGS = \
-I$(top_builddir)/src/bin \
-I$(top_srcdir) \
-I$(top_srcdir)/src/bin \
-I$(top_srcdir)/src/bin/efx \
@e_cflags@ \
@cf_cflags@ \
@VALGRIND_CFLAGS@ \

View File

@ -372,6 +372,15 @@ main(int argc, char **argv)
else
e_first_frame = NULL;
TS("EFX Init");
if (!e_efx_init())
{
e_error_message_show(_("Enlightenment cannot initialize EFX!\n"));
_e_main_shutdown(-1);
}
TS("EFX Init Done");
_e_main_shutdown_push((void*)e_efx_shutdown);
TS("EIO Init");
if (!eio_init())
{

1076
src/bin/efx/e_Efx.h Normal file

File diff suppressed because it is too large Load Diff

128
src/bin/efx/e_efx_private.h Normal file
View File

@ -0,0 +1,128 @@
#ifndef E_EFX_PRIVATE_H
#define E_EFX_PRIVATE_H
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <math.h>
#include <Evas.h>
#include <Ecore.h>
#include "e_Efx.h"
#define DBG(...) EINA_LOG_DOM_DBG(_e_efx_log_dom, __VA_ARGS__)
#define INF(...) EINA_LOG_DOM_INFO(_e_efx_log_dom, __VA_ARGS__)
#define WRN(...) EINA_LOG_DOM_WARN(_e_efx_log_dom, __VA_ARGS__)
#define ERR(...) EINA_LOG_DOM_ERR(_e_efx_log_dom, __VA_ARGS__)
#define CRI(...) EINA_LOG_DOM_CRIT(_e_efx_log_dom, __VA_ARGS__)
#ifdef EAPI
# undef EAPI
#endif /* ifdef EAPI */
#ifdef _WIN32
# ifdef EFL_E_EFX_BUILD
# ifdef DLL_EXPORT
# define EAPI __declspec(dllexport)
# else /* ifdef DLL_EXPORT */
# define EAPI
# endif /* ! DLL_EXPORT */
# else /* ifdef EFL_BUILD */
# define EAPI __declspec(dllimport)
# endif /* ! EFL_BUILD */
#else /* ifdef _WIN32 */
# ifdef __GNUC__
# if __GNUC__ >= 4
# define EAPI __attribute__ ((visibility("default")))
# else /* if __GNUC__ >= 4 */
# define EAPI
# endif /* if __GNUC__ >= 4 */
# else /* ifdef __GNUC__ */
# define EAPI
# endif /* ifdef __GNUC__ */
#endif /* ! _WIN32 */
#ifndef MIN
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
#endif
static const char *e_efx_speed_str[] =
{
"LINEAR", "ACCELERATE", "DECELERATE", "SINUSOIDAL"
};
extern int _e_efx_log_dom;
typedef struct E_EFX E_EFX;
struct E_EFX
{
Evas_Object *obj;
E_EFX *owner;
void *spin_data;
void *rotate_data;
void *zoom_data;
void *move_data;
void *bumpmap_data;
void *pan_data;
void *fade_data;
void *resize_data;
E_Efx_Map_Data map_data;
Eina_List *followers;
Eina_List *queue;
};
void _e_efx_zoom_calc(void *, void *, Evas_Object *obj, Evas_Map *map);
void _e_efx_rotate_calc(void *, void *, Evas_Object *obj, Evas_Map *map);
void _e_efx_spin_calc(void *, void *, Evas_Object *obj, Evas_Map *map);
void _e_efx_resize_adjust(E_EFX *e, int *x, int *y);
#define E_EFX_MAPS_APPLY_ALL EINA_TRUE, EINA_TRUE, EINA_TRUE
#define E_EFX_MAPS_APPLY_ROTATE EINA_TRUE, EINA_FALSE, EINA_FALSE
#define E_EFX_MAPS_APPLY_SPIN EINA_FALSE, EINA_TRUE, EINA_FALSE
#define E_EFX_MAPS_APPLY_ZOOM EINA_FALSE, EINA_FALSE, EINA_TRUE
#define E_EFX_MAPS_APPLY_ROTATE_SPIN EINA_TRUE, EINA_TRUE, EINA_FALSE
void e_efx_maps_apply(E_EFX *e, Evas_Object *obj, Evas_Map *map, Eina_Bool rotate, Eina_Bool spin, Eina_Bool zoom);
E_EFX *e_efx_new(Evas_Object *obj);
void e_efx_free(E_EFX *e);
Evas_Map *e_efx_map_new(Evas_Object *obj);
void e_efx_map_set(Evas_Object *obj, Evas_Map *map);
Eina_Bool e_efx_rotate_center_init(E_EFX *e, const Evas_Point *center);
Eina_Bool e_efx_zoom_center_init(E_EFX *e, const Evas_Point *center);
Eina_Bool e_efx_move_center_init(E_EFX *e, const Evas_Point *center);
void e_efx_rotate_helper(E_EFX *e, Evas_Object *obj, Evas_Map *map, double degrees);
void e_efx_clip_setup(Evas_Object *obj, Evas_Object *clip);
void e_efx_fade_reclip(void *efd);
#define E_EFX_QUEUE_CHECK(X) do \
{ \
Eina_Bool run; \
E_EFX *ee = (X)->e; \
run = e_efx_queue_complete((X)->e, (X)); \
if ((X)->cb) (X)->cb((X)->data, &(X)->e->map_data, (X)->e->obj); \
if (run) e_efx_queue_process(ee); \
} while (0)
Eina_Bool e_efx_queue_complete(E_EFX *e, void *effect_data);
void e_efx_queue_process(E_EFX *e);
static inline void
_size_debug(Evas_Object *obj)
{
Evas_Coord x, y, w, h;
evas_object_geometry_get(obj, &x, &y, &w, &h);
DBG("%s %p: x=%d,y=%d,w=%d,h=%d", evas_object_visible_get(obj) ? "vis" : "hid", obj, x, y, w, h);
}
static inline void
_color_debug(Evas_Object *obj)
{
Evas_Coord r, g, b, a;
evas_object_color_get(obj, &r, &g, &b, &a);
DBG("%d/%d/%d/%d", MIN(r, a), MIN(g, a), MIN(b, a), a);
}
#define HIT DBG("HIT")
#endif

65
src/bin/efx/efx.c Normal file
View File

@ -0,0 +1,65 @@
#include "e_efx_private.h"
int _e_efx_log_dom = -1;
static int _e_efx_init_count = 0;
static uint64_t _e_efx_obj_count = 0;
E_EFX *
e_efx_new(Evas_Object *obj)
{
E_EFX *e;
e = calloc(1, sizeof(E_EFX));
EINA_SAFETY_ON_NULL_RETURN_VAL(e, NULL);
e->obj = obj;
evas_object_data_set(obj, "e_efx-data", e);
_e_efx_obj_count++;
return e;
}
void
e_efx_free(E_EFX *e)
{
E_EFX *ef;
if (e->zoom_data || e->resize_data || e->rotate_data || e->spin_data || e->move_data || e->bumpmap_data || e->pan_data || e->fade_data || e->queue) return;
DBG("freeing e_efx for %p", e->obj);
EINA_LIST_FREE(e->followers, ef)
e_efx_free(ef);
evas_object_data_del(e->obj, "e_efx-data");
e_efx_map_set(e->obj, NULL);
free(e->map_data.rotate_center);
free(e->map_data.zoom_center);
if (!(--_e_efx_obj_count))
{
if (!_e_efx_init_count)
e_efx_shutdown();
}
free(e);
}
EAPI int
e_efx_init(void)
{
if (++_e_efx_init_count > 1) return _e_efx_init_count;
if (eina_init() < 1) goto err;
_e_efx_log_dom = eina_log_domain_register("e_efx", EINA_COLOR_GREEN);
if (_e_efx_log_dom < 0) goto lgerr;
return _e_efx_init_count;
lgerr:
eina_shutdown();
err:
return --_e_efx_init_count;
(void)e_efx_speed_str;
}
EAPI void
e_efx_shutdown(void)
{
if (_e_efx_init_count && (--_e_efx_init_count != 0)) return;
if (_e_efx_obj_count) return;
eina_log_domain_unregister(_e_efx_log_dom);
_e_efx_log_dom = -1;
eina_shutdown();
}

View File

@ -0,0 +1,186 @@
#include "e_efx_private.h"
#include <math.h>
#define DATA8 unsigned char
#define A_VAL(p) (((DATA8 *)(p))[3])
#define R_VAL(p) (((DATA8 *)(p))[2])
#define G_VAL(p) (((DATA8 *)(p))[1])
#define B_VAL(p) (((DATA8 *)(p))[0])
typedef struct E_Efx_Bumpmap_Data
{
E_EFX *e;
int x;
int y;
int z;
int depth;
int red;
int green;
int blue;
int ambient;
unsigned int *img_data;
} E_Efx_Bumpmap_Data;
static void
_bumpmap(E_Efx_Bumpmap_Data *ebd)
{
Evas_Object *o;
int w;
int h;
int i, j;
int x;
int y;
int z;
int depth;
int red;
int green;
int blue;
int ambient;
int z_2, lightx, lighty;
int mx;
int my;
unsigned int *d1;
unsigned int *src;
unsigned int *mp;
unsigned int *mpy;
unsigned int *mpp;
x = ebd->x;
y = ebd->y;
z = ebd->z;
red = ebd->red / 0x100;
green = ebd->green / 0x100;
blue = ebd->blue / 0x100;
ambient = ebd->ambient / 0x100;
depth = ebd->depth / 0x100;
depth /= (255 * (255 + 255 + 255));
z_2 = z * z;
o = ebd->e->obj;
evas_object_image_size_get(o, &w, &h);
if ((!w) || (!h)) return;
d1 = malloc(w * h * sizeof(int));
memcpy(d1, ebd->img_data, w * h * sizeof(int));
src = d1;
mpp = ebd->img_data;
my = h;
lighty = -y;
for (j = h; --j >= 0;)
{
mp = mpp;
mpp += w;
if (--my <= 0)
{
mpp -= w * h;
my = h;
}
mpy = mpp;
mx = w;
lightx = -x;
i = w - 1;
do
{
double v;
int r, g, b, gr, x1, y_1;
gr = A_VAL(mp) * (R_VAL(mp) + G_VAL(mp) + B_VAL(mp));
y_1 = depth * (A_VAL(mpy) * (R_VAL(mpy) +
G_VAL(mpy) +
B_VAL(mpy)) - gr);
mp++;
mpy++;
if (--mx <= 0)
{
mp -= w;
mpy -= w;
mx = w;
}
x1 = depth * (A_VAL(mp) * (R_VAL(mp) +
G_VAL(mp) + B_VAL(mp)) - gr);
v = x1 * lightx + y_1 * lighty + z;
v /= sqrt(((x1 * x1) + (y_1 * y_1) + 1) * ((lightx * lightx) + (lighty * lighty) + z_2));
v += ambient;
r = v * R_VAL(src) * red;
g = v * G_VAL(src) * green;
b = v * B_VAL(src) * blue;
if (r < 0)
r = 0;
else if (r > 255)
r = 255;
if (g < 0)
g = 0;
else if (g > 255)
g = 255;
if (b < 0)
b = 0;
else if (b > 255)
b = 255;
R_VAL(src) = r;
G_VAL(src) = g;
B_VAL(src) = b;
lightx++;
src++;
} while (--i >= 0);
lighty++;
}
evas_object_image_data_set(o, d1);
evas_object_image_data_update_add(o, 0, 0, w, h);
}
EAPI Eina_Bool
e_efx_bumpmap(Evas_Object *obj, Evas_Coord x, Evas_Coord y)
{
E_EFX *e;
E_Efx_Bumpmap_Data *ebd;
EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EINA_FALSE);
e = evas_object_data_get(obj, "e_efx-data");
if (!e)
e = e_efx_new(obj);
EINA_SAFETY_ON_NULL_RETURN_VAL(e, EINA_FALSE);
if (!e->bumpmap_data)
e->bumpmap_data = calloc(1, sizeof(E_Efx_Bumpmap_Data));
EINA_SAFETY_ON_NULL_RETURN_VAL(e->bumpmap_data, EINA_FALSE);
ebd = e->bumpmap_data;
ebd->e = e;
ebd->x = x;
ebd->y = y;
ebd->z = 30;
ebd->depth = 0x200;
ebd->red = 0x200;
ebd->green = 0x200;
ebd->blue = 0x200;
ebd->ambient = 0;
if (!ebd->img_data)
{
unsigned int *m;
int w;
int h;
evas_object_image_size_get(obj, &w, &h);
m = (unsigned int *)evas_object_image_data_get(obj, 1);
ebd->img_data = (unsigned int *)malloc(w * h * sizeof(unsigned int));
if (!ebd->img_data)
{
free(ebd);
return EINA_FALSE;
}
printf("memcpy\n");
memcpy(ebd->img_data, m, (w * h * sizeof(unsigned int)));
}
_bumpmap(ebd);
return EINA_TRUE;
(void)e_efx_speed_str;
}

184
src/bin/efx/efx_fade.c Normal file
View File

@ -0,0 +1,184 @@
#include "e_efx_private.h"
typedef struct E_Efx_Fade_Data
{
E_EFX *e;
E_Efx_Effect_Speed speed;
Ecore_Animator *anim;
Evas_Object *clip;
E_Efx_Color start;
E_Efx_Color color;
unsigned char alpha[2];
E_Efx_End_Cb cb;
void *data;
} E_Efx_Fade_Data;
static void
_clip_setup(void *data EINA_UNUSED, Evas *evas EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
{
E_EFX *e;
E_Efx_Fade_Data *efd;
e = evas_object_data_get(obj, "e_efx-data");
if (!e) return;
efd = e->fade_data;
e_efx_clip_setup(obj, efd->clip);
}
static void
_obj_del(E_Efx_Fade_Data *efd, Evas *evas EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
{
if (efd->anim) ecore_animator_del(efd->anim);
evas_object_event_callback_del_full(efd->e->obj, EVAS_CALLBACK_RESIZE, (Evas_Object_Event_Cb)_clip_setup, efd);
evas_object_event_callback_del_full(efd->e->obj, EVAS_CALLBACK_MOVE, (Evas_Object_Event_Cb)_clip_setup, efd);
if (efd->clip)
{
Evas_Object *clip;
clip = evas_object_clip_get(efd->clip);
evas_object_clip_unset(efd->e->obj);
evas_object_del(efd->clip);
efd->clip = NULL;
if (clip && (!obj)) //obj is only passed during actual del
evas_object_clip_set(efd->e->obj, clip);
}
efd->e->fade_data = NULL;
if ((!efd->e->owner) && (!efd->e->followers)) e_efx_free(efd->e);
free(efd);
}
static Eina_Bool
_fade_cb(E_Efx_Fade_Data *efd, double pos)
{
double factor;
unsigned char r, g, b, a;
if (pos < 1.0)
{
r = efd->start.r;
g = efd->start.g;
b = efd->start.b;
a = efd->alpha[0];
factor = ecore_animator_pos_map(pos, efd->speed, 0, 0);
if (efd->color.r != efd->start.r)
r -= lround(factor * ((int)efd->start.r - (int)efd->color.r));
if (efd->color.g != efd->start.g)
g -= lround(factor * ((int)efd->start.g - (int)efd->color.g));
if (efd->color.b != efd->start.b)
b -= lround(factor * ((int)efd->start.b - (int)efd->color.b));
if (efd->alpha[0] != efd->alpha[1])
a -= lround(factor * ((int)efd->alpha[0] - (int)efd->alpha[1]));
evas_object_color_set(efd->clip, MIN(r, a), MIN(g, a), MIN(b, a), a);
// _color_debug(efd->clip);
return EINA_TRUE;
}
else
/* lround will usually be off by 1 at the end, so we manually set this here */
evas_object_color_set(efd->clip, MIN(efd->color.r, efd->alpha[1]), MIN(efd->color.g, efd->alpha[1]), MIN(efd->color.b, efd->alpha[1]), efd->alpha[1]);
efd->anim = NULL;
E_EFX_QUEUE_CHECK(efd);
return EINA_TRUE;
}
static void
_fade_stop(Evas_Object *obj, Eina_Bool reset)
{
E_EFX *e;
E_Efx_Fade_Data *efd;
e = evas_object_data_get(obj, "e_efx-data");
if ((!e) || (!e->fade_data)) return;
efd = e->fade_data;
if (reset)
{
evas_object_event_callback_del_full(obj, EVAS_CALLBACK_FREE, (Evas_Object_Event_Cb)_obj_del, efd);
evas_object_event_callback_del_full(obj, EVAS_CALLBACK_RESIZE, (Evas_Object_Event_Cb)_clip_setup, efd);
evas_object_event_callback_del_full(obj, EVAS_CALLBACK_MOVE, (Evas_Object_Event_Cb)_clip_setup, efd);
if (e_efx_queue_complete(efd->e, efd))
e_efx_queue_process(efd->e);
_obj_del(efd, NULL, NULL, NULL);
INF("reset faded object %p", obj);
}
else
{
INF("stopped faded object %p", obj);
if (efd->anim) ecore_animator_del(efd->anim);
if (e_efx_queue_complete(efd->e, efd))
e_efx_queue_process(efd->e);
}
}
void
e_efx_fade_reclip(void *fade_data)
{
E_Efx_Fade_Data *efd = fade_data;
Evas_Object *clip;
clip = evas_object_clip_get(efd->e->obj);
if (clip == efd->clip) return;
evas_object_clip_set(efd->e->obj, efd->clip);
if (clip)
evas_object_clip_set(efd->clip, clip);
e_efx_clip_setup(efd->e->obj, efd->clip);
}
EAPI Eina_Bool
e_efx_fade(Evas_Object *obj, E_Efx_Effect_Speed speed, E_Efx_Color *ec, unsigned char alpha, double total_time, E_Efx_End_Cb cb, const void *data)
{
E_EFX *e;
E_Efx_Fade_Data *efd;
EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EINA_FALSE);
e = evas_object_data_get(obj, "e_efx-data");
if (!e) e = e_efx_new(obj);
EINA_SAFETY_ON_NULL_RETURN_VAL(e, EINA_FALSE);
efd = e->fade_data;
if (!efd)
{
e->fade_data = efd = calloc(1, sizeof(E_Efx_Fade_Data));
EINA_SAFETY_ON_NULL_RETURN_VAL(efd, EINA_FALSE);
evas_object_event_callback_add(obj, EVAS_CALLBACK_FREE, (Evas_Object_Event_Cb)_obj_del, e->fade_data);
evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE, (Evas_Object_Event_Cb)_clip_setup, e->fade_data);
evas_object_event_callback_add(obj, EVAS_CALLBACK_MOVE, (Evas_Object_Event_Cb)_clip_setup, e->fade_data);
efd->clip = evas_object_rectangle_add(evas_object_evas_get(obj));
}
efd->e = e;
e_efx_fade_reclip(efd);
evas_object_show(efd->clip);
efd->alpha[1] = alpha;
efd->cb = cb;
efd->data = (void*)data;
evas_object_color_get(efd->clip, (int*)&efd->start.r, (int*)&efd->start.g, (int*)&efd->start.b, (int*)&alpha);
efd->alpha[0] = (unsigned char)alpha;
if (ec)
{
efd->color.r = ec->r;
efd->color.g = ec->g;
efd->color.b = ec->b;
}
else efd->color = (E_Efx_Color){255, 255, 255};
INF("fade: %p || %d/%d/%d/%d => %d/%d/%d/%d %s over %gs", obj, efd->start.r, efd->start.g, efd->start.b, efd->alpha[0], efd->color.r, efd->color.g, efd->color.b, efd->alpha[1], e_efx_speed_str[speed], total_time);
if (efd->anim) ecore_animator_del(efd->anim);
efd->anim = NULL;
if (total_time)
efd->anim = ecore_animator_timeline_add(total_time, (Ecore_Timeline_Cb)_fade_cb, efd);
else
_fade_cb(efd, 1.0);
return EINA_TRUE;
}
EAPI void
e_efx_fade_reset(Evas_Object *obj)
{
_fade_stop(obj, EINA_TRUE);
}
EAPI void
e_efx_fade_stop(Evas_Object *obj)
{
_fade_stop(obj, EINA_FALSE);
}

115
src/bin/efx/efx_helpers.c Normal file
View File

@ -0,0 +1,115 @@
#include "e_efx_private.h"
Eina_Bool
e_efx_rotate_center_init(E_EFX *e, const Evas_Point *center)
{
if (center)
{
if (!e->map_data.rotate_center) e->map_data.rotate_center = malloc(sizeof(Evas_Point));
EINA_SAFETY_ON_NULL_RETURN_VAL(e->map_data.rotate_center, EINA_FALSE);
e->map_data.rotate_center->x = center->x, e->map_data.rotate_center->y = center->y;
}
else
{
free(e->map_data.rotate_center);
e->map_data.rotate_center = NULL;
}
return EINA_TRUE;
}
Eina_Bool
e_efx_zoom_center_init(E_EFX *e, const Evas_Point *center)
{
if (center)
{
if (!e->map_data.zoom_center) e->map_data.zoom_center = malloc(sizeof(Evas_Point));
EINA_SAFETY_ON_NULL_RETURN_VAL(e->map_data.zoom_center, EINA_FALSE);
e->map_data.zoom_center->x = center->x, e->map_data.zoom_center->y = center->y;
}
else
{
free(e->map_data.zoom_center);
e->map_data.zoom_center = NULL;
}
return EINA_TRUE;
}
Eina_Bool
e_efx_move_center_init(E_EFX *e, const Evas_Point *center)
{
if (center)
{
if (!e->map_data.move_center) e->map_data.move_center = malloc(sizeof(Evas_Point));
EINA_SAFETY_ON_NULL_RETURN_VAL(e->map_data.move_center, EINA_FALSE);
e->map_data.move_center->x = center->x, e->map_data.move_center->y = center->y;
}
else
{
free(e->map_data.move_center);
e->map_data.move_center = NULL;
}
return EINA_TRUE;
}
Evas_Map *
e_efx_map_new(Evas_Object *obj)
{
Evas_Map *map;
map = evas_map_new(4);
evas_map_smooth_set(map, EINA_FALSE);
evas_map_util_points_populate_from_object(map, obj);
return map;
(void)e_efx_speed_str;
}
void
e_efx_map_set(Evas_Object *obj, Evas_Map *map)
{
evas_object_map_set(obj, map);
evas_object_map_enable_set(obj, !!map);
if (map) evas_map_free(map);
}
void
e_efx_rotate_helper(E_EFX *e, Evas_Object *obj, Evas_Map *map, double degrees)
{
if (e->map_data.rotate_center)
evas_map_util_rotate(map, degrees, e->map_data.rotate_center->x, e->map_data.rotate_center->y);
else
{
Evas_Coord x, y, w, h;
evas_object_geometry_get(obj, &x, &y, &w, &h);
evas_map_util_rotate(map, degrees, x + (w / 2), y + (h / 2));
}
//DBG("rotation: %g", degrees);
// _size_debug(e->obj);
}
void
e_efx_maps_apply(E_EFX *e, Evas_Object *obj, Evas_Map *map, Eina_Bool rotate, Eina_Bool spin, Eina_Bool zoom)
{
Eina_Bool new = EINA_FALSE;
if ((!e->owner) && (!e->rotate_data) && (!e->spin_data) && (!e->zoom_data)) return;
if (!map)
{
map = e_efx_map_new(obj);
new = EINA_TRUE;
}
if (rotate && (e->rotate_data || (e->owner && e->owner->rotate_data))) _e_efx_rotate_calc(e->rotate_data, e->owner ? e->owner->rotate_data : NULL, obj, map);
if (spin && (e->spin_data || (e->owner && e->owner->spin_data))) _e_efx_spin_calc(e->spin_data, e->owner ? e->owner->spin_data : NULL, obj, map);
if (zoom && (e->zoom_data || (e->owner && e->owner->zoom_data))) _e_efx_zoom_calc(e->zoom_data, e->owner ? e->owner->zoom_data : NULL, obj, map);
if (new) e_efx_map_set(obj, map);
// DBG("%p: %s %s %s", obj, rotate ? "rotate" : "", spin ? "spin" : "", zoom ? "zoom" : "");
}
void
e_efx_clip_setup(Evas_Object *obj, Evas_Object *clip)
{
Evas_Coord x, y, w, h;
if ((!obj) || (!clip)) return;
evas_object_geometry_get(obj, &x, &y, &w, &h);
evas_object_move(clip, x - w, y - h);
evas_object_resize(clip, 3 * w, 3 * h);
}

225
src/bin/efx/efx_move.c Normal file
View File

@ -0,0 +1,225 @@
#include "e_efx_private.h"
typedef struct E_Efx_Move_Data
{
E_EFX *e;
Ecore_Animator *anim;
E_Efx_Effect_Speed speed;
Evas_Point start;
Evas_Point change;
Evas_Point current;
int degrees;
E_Efx_End_Cb cb;
void *data;
} E_Efx_Move_Data;
static void
_obj_del(E_Efx_Move_Data *emd, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
{
if (emd->anim) ecore_animator_del(emd->anim);
emd->e->move_data = NULL;
if ((!emd->e->owner) && (!emd->e->followers)) e_efx_free(emd->e);
free(emd);
}
static void
_move(Evas_Object *obj, int x, int y)
{
Evas_Coord ox, oy;
evas_object_geometry_get(obj, &ox, &oy, NULL, NULL);
evas_object_move(obj, ox + x, oy + y);
//DBG("%p to (%d,%d)", obj, ox + x, oy + y);
}
static Eina_Bool
_move_circle_cb(E_Efx_Move_Data *emd, double pos)
{
double pct, degrees;
Eina_List *l;
E_EFX *e;
double x, y, r, rad;
Evas_Coord xx, yy, ox, oy, w, h;
pct = ecore_animator_pos_map(pos, emd->speed, 0, 0);
degrees = pct * emd->degrees;
evas_object_geometry_get(emd->e->obj, &ox, &oy, &w, &h);
r = (degrees * M_PI) / 180.0;
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) +
(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));
x = emd->e->map_data.move_center->x + rad * cos(r);
y = emd->e->map_data.move_center->y + rad * sin(r);
x -= (double)w / 2.;
y -= (double)h / 2.;
xx = lround(x);
yy = lround(y);
//DBG("move: %g || %g,%g", degrees, x, y);
evas_object_move(emd->e->obj, xx, yy);
e_efx_maps_apply(emd->e, emd->e->obj, NULL, E_EFX_MAPS_APPLY_ALL);
EINA_LIST_FOREACH(emd->e->followers, l, e)
{
_move(e->obj, xx - ox, yy - oy);
e_efx_maps_apply(e, e->obj, NULL, E_EFX_MAPS_APPLY_ALL);
}
if (pos < 1.0) return EINA_TRUE;
E_EFX_QUEUE_CHECK(emd);
return EINA_TRUE;
}
static Eina_Bool
_move_cb(E_Efx_Move_Data *emd, double pos)
{
int x, y;
double pct;
Eina_List *l;
E_EFX *e;
pct = ecore_animator_pos_map(pos, emd->speed, 0, 0);
x = lround(pct * (double)emd->change.x) - emd->current.x;
y = lround(pct * (double)emd->change.y) - emd->current.y;
_e_efx_resize_adjust(emd->e, &x, &y);
_move(emd->e->obj, x, y);
e_efx_maps_apply(emd->e, emd->e->obj, NULL, E_EFX_MAPS_APPLY_ALL);
EINA_LIST_FOREACH(emd->e->followers, l, e)
{
_move(e->obj, x, y);
e_efx_maps_apply(e, e->obj, NULL, E_EFX_MAPS_APPLY_ALL);
}
emd->current.x += x;
emd->current.y += y;
if (pos < 1.0) return EINA_TRUE;
emd->anim = NULL;
E_EFX_QUEUE_CHECK(emd);
return EINA_TRUE;
}
static void
_move_stop(Evas_Object *obj, Eina_Bool reset)
{
E_EFX *e;
E_Efx_Move_Data *emd;
e = evas_object_data_get(obj, "e_efx-data");
if ((!e) || (!e->move_data)) return;
emd = e->move_data;
if (reset)
{
evas_object_move(obj, emd->start.x, emd->start.y);
evas_object_event_callback_del_full(obj, EVAS_CALLBACK_FREE, (Evas_Object_Event_Cb)_obj_del, emd);
if (e_efx_queue_complete(emd->e, emd))
e_efx_queue_process(emd->e);
_obj_del(emd, NULL, NULL, NULL);
INF("reset moved object %p", obj);
}
else
{
INF("stopped moved object %p", obj);
if (emd->anim) ecore_animator_del(emd->anim);
if (e_efx_queue_complete(emd->e, emd))
e_efx_queue_process(emd->e);
}
}
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)
{
E_EFX *e;
E_Efx_Move_Data *emd;
Evas_Coord x, y;
EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EINA_FALSE);
if (!end_point) return EINA_FALSE;
if (total_time < 0.0) return EINA_FALSE;
if (speed > E_EFX_EFFECT_SPEED_SINUSOIDAL) return EINA_FALSE;
e = evas_object_data_get(obj, "e_efx-data");
if (!e) e = e_efx_new(obj);
EINA_SAFETY_ON_NULL_RETURN_VAL(e, EINA_FALSE);
evas_object_geometry_get(obj, &x, &y, NULL, NULL);
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]);
if (!total_time)
{
evas_object_move(obj, end_point->x, end_point->y);
return EINA_TRUE;
}
if (!e->move_data)
{
e->move_data = calloc(1, sizeof(E_Efx_Move_Data));
EINA_SAFETY_ON_NULL_RETURN_VAL(e->move_data, EINA_FALSE);
evas_object_event_callback_add(obj, EVAS_CALLBACK_FREE, (Evas_Object_Event_Cb)_obj_del, e->move_data);
}
emd = e->move_data;
emd->e = e;
emd->speed = speed;
emd->change.x = end_point->x - x;
emd->change.y = end_point->y - y;
emd->current.x = emd->current.y = 0;
emd->cb = cb;
emd->data = (void*)data;
if (emd->anim) ecore_animator_del(emd->anim);
emd->anim = ecore_animator_timeline_add(total_time, (Ecore_Timeline_Cb)_move_cb, emd);
return EINA_TRUE;
}
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)
{
E_EFX *e;
E_Efx_Move_Data *emd;
Evas_Coord x, y;
EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EINA_FALSE);
if (!degrees) return EINA_FALSE;
if (!center) return EINA_FALSE;
if (total_time < 0.0) return EINA_FALSE;
if (speed > E_EFX_EFFECT_SPEED_SINUSOIDAL) return EINA_FALSE;
e = evas_object_data_get(obj, "e_efx-data");
if (!e) e = e_efx_new(obj);
EINA_SAFETY_ON_NULL_RETURN_VAL(e, EINA_FALSE);
if (!e_efx_move_center_init(e, center)) return EINA_FALSE;
evas_object_geometry_get(obj, &x, &y, NULL, NULL);
INF("move: %p - (%d,%d) %d over %gs: %s", obj, x, y, degrees, total_time, e_efx_speed_str[speed]);
if (!total_time)
{
// evas_object_move(obj, end_point->x, end_point->y);
return EINA_TRUE;
}
if (!e->move_data)
{
e->move_data = calloc(1, sizeof(E_Efx_Move_Data));
EINA_SAFETY_ON_NULL_RETURN_VAL(e->move_data, EINA_FALSE);
evas_object_event_callback_add(obj, EVAS_CALLBACK_FREE, (Evas_Object_Event_Cb)_obj_del, e->move_data);
}
emd = e->move_data;
emd->e = e;
emd->speed = speed;
emd->start.x = emd->current.x = x;
emd->start.y = emd->current.y = y;
emd->degrees = degrees;
emd->cb = cb;
emd->data = (void*)data;
if (emd->anim) ecore_animator_del(emd->anim);
emd->anim = ecore_animator_timeline_add(total_time, (Ecore_Timeline_Cb)_move_circle_cb, emd);
return EINA_TRUE;
}
EAPI void
e_efx_move_reset(Evas_Object *obj)
{
_move_stop(obj, EINA_TRUE);
}
EAPI void
e_efx_move_stop(Evas_Object *obj)
{
_move_stop(obj, EINA_FALSE);
}

390
src/bin/efx/efx_pan.c Normal file
View File

@ -0,0 +1,390 @@
#include "e_efx_private.h"
#define PAN_FUNC_CHECK Smart_Data *sd; sd = evas_object_smart_data_get(obj); if ((!obj) || (!sd) || (evas_object_type_get(obj) && strcmp(evas_object_type_get(obj), "e_efx_pan")))
#define PAN_CB_SETUP Smart_Data *sd; sd = evas_object_smart_data_get(obj); if (!sd) return
typedef struct Smart_Data
{
E_EFX *e;
Evas_Object *smart_obj;
Evas_Object *child_obj;
Evas_Coord x, y, w, h;
Evas_Coord child_w, child_h, px, py, dx, dy;
} Smart_Data;
typedef struct E_Efx_Pan_Data
{
E_EFX *e;
Evas_Object *pan;
Ecore_Animator *anim;
E_Efx_Effect_Speed speed;
Evas_Point change;
Evas_Point current;
int degrees;
E_Efx_End_Cb cb;
void *data;
} E_Efx_Pan_Data;
static void _smart_pan_child_set(Evas_Object *obj, Evas_Object *child);
/* local subsystem functions */
static void _smart_child_del_hook(void *data, Evas *e, Evas_Object *obj, void *event_info);
static void _smart_child_resize_hook(void *data, Evas *e, Evas_Object *obj, void *event_info);
static void _smart_reconfigure(Smart_Data *sd);
static void _smart_add(Evas_Object *obj);
static void _smart_del(Evas_Object *obj);
static void _smart_move(Evas_Object *obj, Evas_Coord x, Evas_Coord y);
static void _smart_resize(Evas_Object *obj, Evas_Coord w, Evas_Coord h);
static void _smart_show(Evas_Object *obj);
static void _smart_hide(Evas_Object *obj);
static void _smart_color_set(Evas_Object *obj, int r, int g, int b, int a);
static void _smart_clip_set(Evas_Object *obj, Evas_Object * clip);
static void _smart_clip_unset(Evas_Object *obj);
static void _smart_init(void);
/* local subsystem globals */
static Evas_Smart *_smart = NULL;
/* local subsystem functions */
static void
_smart_child_del_hook(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
{
Smart_Data *sd;
sd = data;
sd->child_obj = NULL;
}
static void
_smart_child_resize_hook(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
{
Smart_Data *sd;
Evas_Coord w, h;
sd = data;
evas_object_geometry_get(sd->child_obj, NULL, NULL, &w, &h);
if ((w != sd->child_w) || (h != sd->child_h))
{
sd->child_w = w;
sd->child_h = h;
_smart_reconfigure(sd);
}
}
static void
_smart_reconfigure(Smart_Data *sd)
{
Eina_List *l;
E_EFX *e;
Evas_Coord x, y;
evas_object_move(sd->child_obj, sd->x - sd->px, sd->y - sd->py);
e_efx_maps_apply(sd->e, sd->child_obj, NULL, E_EFX_MAPS_APPLY_ALL);
//DBG("DELTA: (%d,%d)", sd->dx, sd->dy);
EINA_LIST_FOREACH(sd->e->followers, l, e)
{
evas_object_geometry_get(e->obj, &x, &y, NULL, NULL);
evas_object_move(e->obj, x - sd->dx, y - sd->dy);
e_efx_maps_apply(e, e->obj, NULL, E_EFX_MAPS_APPLY_ALL);
// _size_debug(e->obj);
}
}
static void
_smart_add(Evas_Object *obj)
{
Smart_Data *sd;
sd = calloc(1, sizeof(Smart_Data));
if (!sd) return;
sd->smart_obj = obj;
sd->x = 0;
sd->y = 0;
sd->w = 0;
sd->h = 0;
evas_object_smart_data_set(obj, sd);
}
static void
_smart_del(Evas_Object *obj)
{
PAN_CB_SETUP;
_smart_pan_child_set(obj, NULL);
free(sd);
}
static void
_smart_move(Evas_Object *obj, Evas_Coord x, Evas_Coord y)
{
PAN_CB_SETUP;
sd->x = x;
sd->y = y;
_smart_reconfigure(sd);
}
static void
_smart_resize(Evas_Object *obj, Evas_Coord w, Evas_Coord h)
{
PAN_CB_SETUP;
sd->w = w;
sd->h = h;
_smart_reconfigure(sd);
}
static void
_smart_show(Evas_Object *obj)
{
PAN_CB_SETUP;
if (sd->child_obj)
evas_object_show(sd->child_obj);
}
static void
_smart_hide(Evas_Object *obj)
{
PAN_CB_SETUP;
if (sd->child_obj)
evas_object_hide(sd->child_obj);
}
static void
_smart_color_set(Evas_Object *obj, int r, int g, int b, int a)
{
PAN_CB_SETUP;
if (sd->child_obj)
evas_object_color_set(sd->child_obj, r, g, b, a);
}
static void
_smart_clip_set(Evas_Object *obj, Evas_Object *clip)
{
PAN_CB_SETUP;
if (sd->child_obj)
evas_object_clip_set(sd->child_obj, clip);
}
static void
_smart_clip_unset(Evas_Object *obj)
{
PAN_CB_SETUP;
if (sd->child_obj)
evas_object_clip_unset(sd->child_obj);
}
/* never need to touch this */
static void
_smart_init(void)
{
if (_smart) return;
{
static const Evas_Smart_Class sc =
{
"e_efx_pan",
EVAS_SMART_CLASS_VERSION,
_smart_add,
_smart_del,
_smart_move,
_smart_resize,
_smart_show,
_smart_hide,
_smart_color_set,
_smart_clip_set,
_smart_clip_unset,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL
};
_smart = evas_smart_class_new(&sc);
}
}
static Evas_Object *
_smart_pan_add(Evas *evas)
{
_smart_init();
return evas_object_smart_add(evas, _smart);
}
static void
_smart_pan_child_set(Evas_Object *obj, Evas_Object *child)
{
PAN_FUNC_CHECK return;
if (child == sd->child_obj) return;
if (sd->child_obj)
{
evas_object_clip_unset(sd->child_obj);
evas_object_smart_member_del(sd->child_obj);
evas_object_event_callback_del_full(sd->child_obj, EVAS_CALLBACK_FREE, _smart_child_del_hook, sd);
evas_object_event_callback_del_full(sd->child_obj, EVAS_CALLBACK_RESIZE, _smart_child_resize_hook, sd);
sd->child_obj = NULL;
}
if (child)
{
Evas_Coord w, h;
int r, g, b, a;
sd->child_obj = child;
evas_object_smart_member_add(sd->child_obj, sd->smart_obj);
evas_object_geometry_get(sd->child_obj, NULL, NULL, &w, &h);
sd->child_w = w;
sd->child_h = h;
evas_object_event_callback_add(child, EVAS_CALLBACK_FREE, _smart_child_del_hook, sd);
evas_object_event_callback_add(child, EVAS_CALLBACK_RESIZE, _smart_child_resize_hook, sd);
evas_object_color_get(sd->smart_obj, &r, &g, &b, &a);
evas_object_color_set(sd->child_obj, r, g, b, a);
evas_object_clip_set(sd->child_obj, evas_object_clip_get(sd->smart_obj));
if (evas_object_visible_get(sd->smart_obj)) evas_object_show(sd->child_obj);
else evas_object_hide(sd->child_obj);
_smart_reconfigure(sd);
}
}
static void
_smart_pan_set(Evas_Object *obj, Evas_Coord x, Evas_Coord y)
{
PAN_FUNC_CHECK return;
if ((x == sd->px) && (y == sd->py)) return;
sd->dx = x - sd->px;
sd->dy = y - sd->py;
sd->px = x;
sd->py = y;
_smart_reconfigure(sd);
}
static void
_smart_pan_get(Evas_Object *obj, Evas_Coord *x, Evas_Coord *y)
{
PAN_FUNC_CHECK return;
if (x) *x = sd->px;
if (y) *y = sd->py;
}
/*
static void
_smart_pan_max_get(Evas_Object *obj, Evas_Coord *x, Evas_Coord *y)
{
PAN_FUNC_CHECK return;
if (x)
{
if (sd->w < sd->child_w) *x = sd->child_w - sd->w;
else *x = 0;
}
if (y)
{
if (sd->h < sd->child_h) *y = sd->child_h - sd->h;
else *y = 0;
}
}
*/
static void
_obj_del(E_Efx_Pan_Data *epd, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
{
if (epd->anim) ecore_animator_del(epd->anim);
if (epd->pan)
{
evas_object_del(epd->pan);
epd->pan = NULL;
}
epd->e->pan_data = NULL;
if ((!epd->e->owner) && (!epd->e->followers)) e_efx_free(epd->e);
free(epd);
}
static Eina_Bool
_pan_cb(E_Efx_Pan_Data *epd, double pos)
{
int x, y, px = 0, py = 0;
double pct;
pct = ecore_animator_pos_map(pos, epd->speed, 0, 0);
x = lround(pct * (double)epd->change.x) - epd->current.x;
y = lround(pct * (double)epd->change.y) - epd->current.y;
_smart_pan_get(epd->pan, &px, &py);
//DBG("PAN: (%d,%d) += (%d,%d)", px, py, x, y);
_smart_pan_set(epd->pan, px + x, py + y);
epd->e->map_data.pan.x = px + x;
epd->e->map_data.pan.y = py + y;
epd->current.x += x;
epd->current.y += y;
if (pos < 1.0) return EINA_TRUE;
epd->anim = NULL;
E_EFX_QUEUE_CHECK(epd);
return EINA_TRUE;
}
static E_EFX *
_e_efx_pan_init(Evas_Object *obj)
{
E_EFX *e;
E_Efx_Pan_Data *epd;
Smart_Data *sd;
EINA_SAFETY_ON_NULL_RETURN_VAL(obj, NULL);
e = evas_object_data_get(obj, "e_efx-data");
if (!e) e = e_efx_new(obj);
EINA_SAFETY_ON_NULL_RETURN_VAL(e, NULL);
if (!e->pan_data)
{
e->pan_data = calloc(1, sizeof(E_Efx_Pan_Data));
EINA_SAFETY_ON_NULL_RETURN_VAL(e->pan_data, EINA_FALSE);
evas_object_event_callback_add(obj, EVAS_CALLBACK_FREE, (Evas_Object_Event_Cb)_obj_del, e->pan_data);
epd = e->pan_data;
epd->pan = _smart_pan_add(evas_object_evas_get(obj));
sd = evas_object_smart_data_get(epd->pan);
sd->e = e;
_smart_pan_child_set(epd->pan, obj);
evas_object_show(epd->pan);
}
return e;
}
EAPI Eina_Bool
e_efx_pan_init(Evas_Object *obj)
{
return !!_e_efx_pan_init(obj);
}
EAPI Eina_Bool
e_efx_pan(Evas_Object *obj, E_Efx_Effect_Speed speed, const Evas_Point *distance, double total_time, E_Efx_End_Cb cb, const void *data)
{
E_EFX *e;
E_Efx_Pan_Data *epd;
Evas_Coord x = 0, y = 0;
if (!distance) return EINA_FALSE;
if (total_time < 0.0) return EINA_FALSE;
if (speed > E_EFX_EFFECT_SPEED_SINUSOIDAL) return EINA_FALSE;
e = _e_efx_pan_init(obj);
if (!e) return EINA_FALSE;
epd = e->pan_data;
epd->e = e;
_smart_pan_get(epd->pan, &x, &y);
INF("pan: %p - (%d,%d) += (%d,%d) over %gs: %s", obj, x, y, distance->x, distance->y, total_time, e_efx_speed_str[speed]);
if (!total_time)
{
_smart_pan_set(epd->pan, x + distance->x, y + distance->y);
return EINA_TRUE;
}
epd->speed = speed;
epd->change.x = distance->x;
epd->change.y = distance->y;
epd->current.x = epd->current.y = 0;
epd->cb = cb;
epd->data = (void*)data;
if (epd->anim) ecore_animator_del(epd->anim);
epd->anim = ecore_animator_timeline_add(total_time, (Ecore_Timeline_Cb)_pan_cb, epd);
return EINA_TRUE;
}

301
src/bin/efx/efx_queue.c Normal file
View File

@ -0,0 +1,301 @@
#include "e_efx_private.h"
struct E_Efx_Queue_Data
{
E_EFX *e;
E_Efx_Queued_Effect effect;
E_Efx_Effect_Speed speed;
double time;
E_Efx_End_Cb cb;
void *data;
Eina_List *subeffects;
void *effect_data;
Eina_Bool active : 1;
};
static void
_queue_advance(E_Efx_Queue_Data *eqd)
{
E_Efx_Queue_Data *run;
Eina_List *l;
INF("queue_advance: %p", eqd->e->obj);
switch (eqd->effect.type)
{
case E_EFX_EFFECT_TYPE_ROTATE:
e_efx_rotate(eqd->e->obj, eqd->speed, eqd->effect.effect.rotation.degrees, eqd->effect.effect.rotation.center, eqd->time, eqd->cb, eqd->data);
eqd->effect_data = eqd->e->rotate_data;
break;
case E_EFX_EFFECT_TYPE_ZOOM:
e_efx_zoom(eqd->e->obj, eqd->speed, eqd->effect.effect.zoom.start, eqd->effect.effect.zoom.end, eqd->effect.effect.zoom.center, eqd->time, eqd->cb, eqd->data);
eqd->effect_data = eqd->e->zoom_data;
break;
case E_EFX_EFFECT_TYPE_MOVE:
e_efx_move(eqd->e->obj, eqd->speed, &eqd->effect.effect.movement.point, eqd->time, eqd->cb, eqd->data);
eqd->effect_data = eqd->e->move_data;
break;
case E_EFX_EFFECT_TYPE_PAN:
e_efx_pan(eqd->e->obj, eqd->speed, &eqd->effect.effect.movement.point, eqd->time, eqd->cb, eqd->data);
eqd->effect_data = eqd->e->pan_data;
break;
case E_EFX_EFFECT_TYPE_FADE:
e_efx_fade(eqd->e->obj, eqd->speed, &eqd->effect.effect.fade.color, eqd->effect.effect.fade.alpha, eqd->time, eqd->cb, eqd->data);
eqd->effect_data = eqd->e->fade_data;
break;
case E_EFX_EFFECT_TYPE_RESIZE:
default:
e_efx_resize(eqd->e->obj, eqd->speed, eqd->effect.effect.resize.point, eqd->effect.effect.resize.w, eqd->effect.effect.resize.h, eqd->time, eqd->cb, eqd->data);
eqd->effect_data = eqd->e->resize_data;
}
eqd->active = EINA_TRUE;
EINA_LIST_FOREACH(eqd->subeffects, l, run)
_queue_advance(run);
}
void
e_efx_queue_process(E_EFX *e)
{
E_Efx_Queue_Data *eqd;
eqd = eina_list_data_get(e->queue);
if (!eqd) return;
if (eqd->active) return;
_queue_advance(eqd);
}
void
eqd_free(E_Efx_Queue_Data *eqd)
{
E_Efx_Queue_Data *sub;
if (!eqd) return;
if (eqd->effect.type == E_EFX_EFFECT_TYPE_ROTATE)
free(eqd->effect.effect.rotation.center);
else if (eqd->effect.type == E_EFX_EFFECT_TYPE_ZOOM)
free(eqd->effect.effect.zoom.center);
else if (eqd->effect.type == E_EFX_EFFECT_TYPE_RESIZE)
free(eqd->effect.effect.resize.point);
EINA_LIST_FREE(eqd->subeffects, sub)
eqd_free(sub);
free(eqd);
}
Eina_Bool
e_efx_queue_complete(E_EFX *e, void *effect_data)
{
E_Efx_Queue_Data *eqd;
eqd = eina_list_data_get(e->queue);
if (!eqd)
{
e_efx_free(e);
return EINA_FALSE;
}
DBG("%p: %p", e->obj, effect_data);
if (eqd->effect_data != effect_data) return EINA_FALSE;
e->queue = eina_list_remove_list(e->queue, e->queue);
eqd_free(eqd);
return !!e->queue;
}
E_Efx_Queue_Data *
eqd_new(E_EFX *e, E_Efx_Effect_Speed speed, const E_Efx_Queued_Effect *effect, double total_time, E_Efx_End_Cb cb, const void *data)
{
E_Efx_Queue_Data *eqd;
eqd = calloc(1, sizeof(E_Efx_Queue_Data));
memcpy(&eqd->effect, effect, sizeof(E_Efx_Queued_Effect));
eqd->e = e;
if (effect->type == E_EFX_EFFECT_TYPE_ROTATE)
{
if (effect->effect.rotation.center)
{
eqd->effect.effect.rotation.center = malloc(sizeof(Evas_Point));
if (!eqd->effect.effect.rotation.center) goto error;
memcpy(eqd->effect.effect.rotation.center, effect->effect.rotation.center, sizeof(Evas_Point));
}
}
else if (effect->type == E_EFX_EFFECT_TYPE_ZOOM)
{
if (effect->effect.zoom.center)
{
eqd->effect.effect.zoom.center = malloc(sizeof(Evas_Point));
if (!eqd->effect.effect.zoom.center) goto error;
memcpy(eqd->effect.effect.zoom.center, effect->effect.zoom.center, sizeof(Evas_Point));
}
}
else if (effect->type == E_EFX_EFFECT_TYPE_RESIZE)
{
if (effect->effect.resize.point)
{
eqd->effect.effect.resize.point = malloc(sizeof(Evas_Point));
if (!eqd->effect.effect.resize.point) goto error;
memcpy(eqd->effect.effect.resize.point, effect->effect.resize.point, sizeof(Evas_Point));
}
}
eqd->speed = speed;
eqd->time = total_time;
eqd->cb = cb;
eqd->data = (void*)data;
return eqd;
error:
free(eqd);
e_efx_free(e);
return NULL;
}
EAPI void
e_efx_queue_run(Evas_Object *obj)
{
E_EFX *e;
e = evas_object_data_get(obj, "e_efx-data");
if (!e) return;
e_efx_queue_process(e);
}
EAPI E_Efx_Queue_Data *
e_efx_queue_append(Evas_Object *obj, E_Efx_Effect_Speed speed, const E_Efx_Queued_Effect *effect, double total_time, E_Efx_End_Cb cb, const void *data)
{
E_EFX *e;
E_Efx_Queue_Data *eqd;
EINA_SAFETY_ON_NULL_RETURN_VAL(obj, NULL);
EINA_SAFETY_ON_NULL_RETURN_VAL(effect, NULL);
EINA_SAFETY_ON_FALSE_RETURN_VAL(total_time >= 0.0, NULL);
if (effect->type > E_EFX_EFFECT_TYPE_RESIZE) return NULL;
e = evas_object_data_get(obj, "e_efx-data");
if (!e) e = e_efx_new(obj);
EINA_SAFETY_ON_NULL_RETURN_VAL(e, NULL);
eqd = eqd_new(e, speed, effect, total_time, cb, data);
EINA_SAFETY_ON_NULL_RETURN_VAL(eqd, NULL);
e->queue = eina_list_append(e->queue, eqd);
return eqd;
(void)e_efx_speed_str;
}
EAPI E_Efx_Queue_Data *
e_efx_queue_prepend(Evas_Object *obj, E_Efx_Effect_Speed speed, const E_Efx_Queued_Effect *effect, double total_time, E_Efx_End_Cb cb, const void *data)
{
E_EFX *e;
E_Efx_Queue_Data *eqd, *eqd2;
EINA_SAFETY_ON_NULL_RETURN_VAL(obj, NULL);
EINA_SAFETY_ON_NULL_RETURN_VAL(effect, NULL);
EINA_SAFETY_ON_FALSE_RETURN_VAL(total_time >= 0.0, NULL);
if (effect->type > E_EFX_EFFECT_TYPE_RESIZE) return NULL;
e = evas_object_data_get(obj, "e_efx-data");
if (!e) e = e_efx_new(obj);
EINA_SAFETY_ON_NULL_RETURN_VAL(e, NULL);
eqd = eqd_new(e, speed, effect, total_time, cb, data);
EINA_SAFETY_ON_NULL_RETURN_VAL(eqd, NULL);
if (e->queue)
{
eqd2 = eina_list_data_get(e->queue);
if (eqd2->active)
e->queue = eina_list_append_relative_list(e->queue, eqd, e->queue);
else
e->queue = eina_list_prepend(e->queue, eqd);
}
else
e->queue = eina_list_append(e->queue, eqd);
return eqd;
(void)e_efx_speed_str;
}
EAPI void
e_efx_queue_promote(Evas_Object *obj, E_Efx_Queue_Data *eqd)
{
E_EFX *e;
EINA_SAFETY_ON_NULL_RETURN(obj);
EINA_SAFETY_ON_NULL_RETURN(eqd);
e = evas_object_data_get(obj, "e_efx-data");
EINA_SAFETY_ON_NULL_RETURN(e);
EINA_SAFETY_ON_NULL_RETURN(e->queue);
EINA_SAFETY_ON_TRUE_RETURN(eqd->active);
if (e->queue->data == eqd) return;
e->queue = eina_list_remove(e->queue, eqd);
e->queue = eina_list_append_relative_list(e->queue, eqd, e->queue);
}
EAPI void
e_efx_queue_demote(Evas_Object *obj, E_Efx_Queue_Data *eqd)
{
E_EFX *e;
EINA_SAFETY_ON_NULL_RETURN(obj);
EINA_SAFETY_ON_NULL_RETURN(eqd);
e = evas_object_data_get(obj, "e_efx-data");
EINA_SAFETY_ON_NULL_RETURN(e);
EINA_SAFETY_ON_NULL_RETURN(e->queue);
EINA_SAFETY_ON_TRUE_RETURN(eqd->active);
if (eina_list_last(e->queue)->data == eqd) return;
e->queue = eina_list_demote_list(e->queue, eina_list_data_find_list(e->queue, eqd));
}
EAPI void
e_efx_queue_delete(Evas_Object *obj, E_Efx_Queue_Data *eqd)
{
E_EFX *e;
EINA_SAFETY_ON_NULL_RETURN(obj);
EINA_SAFETY_ON_NULL_RETURN(eqd);
e = evas_object_data_get(obj, "e_efx-data");
EINA_SAFETY_ON_NULL_RETURN(e);
EINA_SAFETY_ON_NULL_RETURN(e->queue);
EINA_SAFETY_ON_TRUE_RETURN(eqd->active);
e->queue = eina_list_remove(e->queue, eqd);
eqd_free(eqd);
}
EAPI void
e_efx_queue_clear(Evas_Object *obj)
{
E_EFX *e;
E_Efx_Queue_Data *eqd;
Eina_List *l, *ll;
EINA_SAFETY_ON_NULL_RETURN(obj);
e = evas_object_data_get(obj, "e_efx-data");
EINA_SAFETY_ON_NULL_RETURN(e);
if (!e->queue) return;
EINA_LIST_FOREACH_SAFE(e->queue, l, ll, eqd)
{
if (eqd->active) continue;
e->queue = eina_list_remove_list(e->queue, l);
eqd_free(eqd);
}
}
EAPI Eina_Bool
e_efx_queue_effect_attach(E_Efx_Queue_Data *eqd, E_Efx_Effect_Speed speed, const E_Efx_Queued_Effect *effect, double total_time, E_Efx_End_Cb cb, const void *data)
{
E_EFX *e;
E_Efx_Queue_Data *sub;
EINA_SAFETY_ON_NULL_RETURN_VAL(eqd, EINA_FALSE);
EINA_SAFETY_ON_NULL_RETURN_VAL(effect, EINA_FALSE);
EINA_SAFETY_ON_FALSE_RETURN_VAL(total_time >= 0.0, EINA_FALSE);
if (effect->type > E_EFX_EFFECT_TYPE_RESIZE) return EINA_FALSE;
e = eqd->e;
sub = eqd_new(e, speed, effect, total_time, cb, data);
EINA_SAFETY_ON_NULL_RETURN_VAL(sub, EINA_FALSE);
eqd->subeffects = eina_list_append(eqd->subeffects, sub);
return EINA_TRUE;
(void)e_efx_speed_str;
}

225
src/bin/efx/efx_resize.c Normal file
View File

@ -0,0 +1,225 @@
#include "e_efx_private.h"
typedef enum
{
NONE,
TOP_RIGHT,
BOTTOM_LEFT,
BOTTOM_RIGHT
} Anchor;
typedef struct E_Efx_Resize_Data
{
E_EFX *e;
E_Efx_Effect_Speed speed;
Ecore_Animator *anim;
int w, h;
int start_w, start_h;
E_Efx_End_Cb cb;
void *data;
Anchor anchor_type;
Evas_Point anchor;
Eina_Bool moving : 1;
} E_Efx_Resize_Data;
static void
_obj_del(void *data, Evas *evas EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
{
E_Efx_Resize_Data *erd = data;
if (erd->anim) ecore_animator_del(erd->anim);
erd->e->resize_data = NULL;
if ((!erd->e->owner) && (!erd->e->followers)) e_efx_free(erd->e);
free(erd);
}
static void
_resize_anchor(E_Efx_Resize_Data *erd)
{
int x = 0, y = 0;
int cx, cy;
if (!erd->anchor_type) return;
_e_efx_resize_adjust(erd->e, &x, &y);
if ((!x) && (!y)) return;
evas_object_geometry_get(erd->e->obj, &cx, &cy, NULL, NULL);
x += cx, y += cy;
evas_object_move(erd->e->obj, x, y);
}
static Eina_Bool
_resize_cb(E_Efx_Resize_Data *erd, double pos)
{
double factor;
if (pos < 1.0)
{
int w, h;
factor = ecore_animator_pos_map(pos, erd->speed, 0, 0);
w = lround(factor * (erd->w - erd->start_w)) + erd->start_w;
h = lround(factor * (erd->h - erd->start_h)) + erd->start_h;
evas_object_resize(erd->e->obj, w, h);
_resize_anchor(erd);
return EINA_TRUE;
}
/* lround will usually be off by 1 at the end, so we manually set this here */
evas_object_resize(erd->e->obj, erd->w, erd->h);
_resize_anchor(erd);
erd->anim = NULL;
E_EFX_QUEUE_CHECK(erd);
return EINA_TRUE;
}
static void
_resize_stop(Evas_Object *obj, Eina_Bool reset)
{
E_EFX *e;
E_Efx_Resize_Data *erd;
e = evas_object_data_get(obj, "e_efx-data");
if ((!e) || (!e->resize_data)) return;
erd = e->resize_data;
if (reset)
{
evas_object_resize(obj, erd->start_w, erd->start_h);
evas_object_event_callback_del_full(obj, EVAS_CALLBACK_FREE, (Evas_Object_Event_Cb)_obj_del, erd);
if (erd->moving)
{
erd->moving = 0;
e_efx_move_reset(obj);
}
else if (e_efx_queue_complete(erd->e, erd))
e_efx_queue_process(erd->e);
_obj_del(erd, NULL, NULL, NULL);
INF("reset resized object %p", obj);
}
else
{
INF("stopped resized object %p", obj);
if (erd->anim) ecore_animator_del(erd->anim);
if (erd->moving)
{
erd->moving = 0;
e_efx_move_stop(obj);
}
if (e_efx_queue_complete(erd->e, erd))
e_efx_queue_process(erd->e);
}
}
void
_e_efx_resize_adjust(E_EFX *e, int *ax, int *ay)
{
E_Efx_Resize_Data *erd = e->resize_data;
int x, y, w, h;
if (!erd) return;
evas_object_geometry_get(e->obj, &x, &y, &w, &h);
switch (erd->anchor_type)
{
case TOP_RIGHT:
*ax = erd->anchor.x - (x + w);
*ay = erd->anchor.y - y;
break;
case BOTTOM_LEFT:
*ax = erd->anchor.x - x;
*ay = erd->anchor.y - (y + h);
break;
case BOTTOM_RIGHT:
*ax = erd->anchor.x - (x + w);
*ay = erd->anchor.y - (y + h);
break;
default: break;
}
}
EAPI Eina_Bool
e_efx_resize(Evas_Object *obj, E_Efx_Effect_Speed speed, const Evas_Point *position, int w, int h, double total_time, E_Efx_End_Cb cb, const void *data)
{
E_EFX *e;
E_Efx_Resize_Data *erd;
int x, y;
EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EINA_FALSE);
EINA_SAFETY_ON_TRUE_RETURN_VAL(w < 0, EINA_FALSE);
EINA_SAFETY_ON_TRUE_RETURN_VAL(h < 0, EINA_FALSE);
e = evas_object_data_get(obj, "e_efx-data");
if (!e) e = e_efx_new(obj);
EINA_SAFETY_ON_NULL_RETURN_VAL(e, EINA_FALSE);
erd = e->resize_data;
if (!erd)
{
e->resize_data = erd = calloc(1, sizeof(E_Efx_Resize_Data));
EINA_SAFETY_ON_NULL_RETURN_VAL(erd, EINA_FALSE);
evas_object_event_callback_add(obj, EVAS_CALLBACK_FREE, (Evas_Object_Event_Cb)_obj_del, e->resize_data);
}
erd->e = e;
erd->anchor_type = NONE;
erd->w = w;
erd->h = h;
erd->cb = cb;
erd->data = (void*)data;
evas_object_geometry_get(obj, &x, &y, &erd->start_w, &erd->start_h);
INF("resize: %p || %dx%d => %dx%d %s over %gs", obj, erd->start_w, erd->start_h, w, h, e_efx_speed_str[speed], total_time);
if (position && ((position->x != x) || (position->y != y)))
{
Evas_Point tr, bl, br;
Evas_Point atr, abl, abr;
tr = (Evas_Point){x + erd->start_w, y};
bl = (Evas_Point){x, y + erd->start_h};
br = (Evas_Point){x + erd->start_w, y + erd->start_h};
atr = (Evas_Point){position->x + w, position->y};
abl = (Evas_Point){position->x, position->y + h};
abr = (Evas_Point){position->x + w, position->y + h};
if (!memcmp(&tr, &atr, sizeof(Evas_Point)))
{
erd->anchor_type = TOP_RIGHT;
erd->anchor = tr;
}
else if (!memcmp(&bl, &abl, sizeof(Evas_Point)))
{
erd->anchor_type = BOTTOM_LEFT;
erd->anchor = bl;
}
else if (!memcmp(&br, &abr, sizeof(Evas_Point)))
{
erd->anchor_type = BOTTOM_RIGHT;
erd->anchor = br;
}
if (!e_efx_move(obj, speed, position, total_time, NULL, NULL))
{
evas_object_event_callback_del_full(obj, EVAS_CALLBACK_FREE, (Evas_Object_Event_Cb)_obj_del, e->resize_data);
free(erd);
e->resize_data = NULL;
e_efx_free(e);
return EINA_FALSE;
}
else
erd->moving = 1;
}
if (total_time)
erd->anim = ecore_animator_timeline_add(total_time, (Ecore_Timeline_Cb)_resize_cb, erd);
else
_resize_cb(erd, 1.0);
return EINA_TRUE;
}
EAPI void
e_efx_resize_reset(Evas_Object *obj)
{
_resize_stop(obj, EINA_TRUE);
}
EAPI void
e_efx_resize_stop(Evas_Object *obj)
{
_resize_stop(obj, EINA_FALSE);
}

145
src/bin/efx/efx_rotate.c Normal file
View File

@ -0,0 +1,145 @@
#include "e_efx_private.h"
typedef struct E_Efx_Rotate_Data
{
E_EFX *e;
Ecore_Animator *anim;
E_Efx_Effect_Speed speed;
double start_degrees;
double degrees;
E_Efx_End_Cb cb;
void *data;
} E_Efx_Rotate_Data;
static void
_obj_del(E_Efx_Rotate_Data *erd, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
{
if (erd->anim) ecore_animator_del(erd->anim);
erd->e->rotate_data = NULL;
if ((!erd->e->owner) && (!erd->e->followers)) e_efx_free(erd->e);
free(erd);
}
static Eina_Bool
_rotate_cb(E_Efx_Rotate_Data *erd, double pos)
{
double degrees;
Eina_List *l;
E_EFX *e;
degrees = ecore_animator_pos_map(pos, erd->speed, 0, 0);
erd->e->map_data.rotation = degrees * erd->degrees + erd->start_degrees;
//DBG("erd->e->map_data.rotation=%g,erd->degrees=%g,erd->start_degrees=%g", erd->e->map_data.rotation, erd->degrees, erd->start_degrees);
e_efx_maps_apply(erd->e, erd->e->obj, NULL, E_EFX_MAPS_APPLY_ALL);
EINA_LIST_FOREACH(erd->e->followers, l, e)
e_efx_maps_apply(e, e->obj, NULL, E_EFX_MAPS_APPLY_ALL);
if (pos < 1.0) return EINA_TRUE;
erd->anim = NULL;
E_EFX_QUEUE_CHECK(erd);
return EINA_TRUE;
}
static void
_rotate_stop(Evas_Object *obj, Eina_Bool reset)
{
E_EFX *e;
E_Efx_Rotate_Data *erd;
e = evas_object_data_get(obj, "e_efx-data");
if ((!e) || (!e->rotate_data)) return;
erd = e->rotate_data;
if (reset)
{
erd->start_degrees = 0;
_rotate_cb(erd, 0);
evas_object_event_callback_del_full(obj, EVAS_CALLBACK_FREE, (Evas_Object_Event_Cb)_obj_del, erd);
erd->e->map_data.rotation = 0;
if (e_efx_queue_complete(erd->e, erd))
e_efx_queue_process(erd->e);
_obj_del(erd, NULL, NULL, NULL);
INF("reset rotating object %p", obj);
}
else
{
if (erd->anim) ecore_animator_del(erd->anim);
erd->anim = NULL;
INF("stopped rotating object %p", obj);
if (e_efx_queue_complete(erd->e, erd))
e_efx_queue_process(erd->e);
}
}
void
_e_efx_rotate_calc(void *data, void *owner, Evas_Object *obj, Evas_Map *map)
{
E_Efx_Rotate_Data *erd = data;
E_Efx_Rotate_Data *erd2 = owner;
e_efx_rotate_helper(erd2 ? erd2->e : (erd ? erd->e : NULL), obj, map, (erd ? erd->e->map_data.rotation : 0) + (erd2 ? erd2->e->map_data.rotation : 0));
}
EAPI Eina_Bool
e_efx_rotate(Evas_Object *obj, E_Efx_Effect_Speed speed, double degrees, const Evas_Point *center, double total_time, E_Efx_End_Cb cb, const void *data)
{
E_EFX *e;
E_Efx_Rotate_Data *erd;
EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EINA_FALSE);
if (!degrees) return EINA_FALSE;
if (total_time < 0.0) return EINA_FALSE;
if (speed > E_EFX_EFFECT_SPEED_SINUSOIDAL) return EINA_FALSE;
/* can't rotate a spinning object, so we stop it first */
e = evas_object_data_get(obj, "e_efx-data");
if (e)
{
if (e->spin_data) e_efx_spin_stop(obj);
if (e->rotate_data)
{
erd = e->rotate_data;
if (erd->anim) e_efx_rotate_stop(obj);
}
}
else
{
e = e_efx_new(obj);
EINA_SAFETY_ON_NULL_RETURN_VAL(e, EINA_FALSE);
}
if (!e_efx_rotate_center_init(e, center)) return EINA_FALSE;
INF("rotate: %p - %g degrees over %gs: %s", obj, degrees, total_time, e_efx_speed_str[speed]);
if (!e->rotate_data)
{
e->rotate_data = calloc(1, sizeof(E_Efx_Rotate_Data));
EINA_SAFETY_ON_NULL_RETURN_VAL(e->rotate_data, EINA_FALSE);
evas_object_event_callback_add(obj, EVAS_CALLBACK_FREE, (Evas_Object_Event_Cb)_obj_del, e->rotate_data);
}
erd = e->rotate_data;
erd->e = e;
erd->speed = speed;
erd->degrees = degrees;
erd->start_degrees = e->map_data.rotation;
erd->cb = cb;
erd->data = (void*)data;
if (!total_time)
{
e->map_data.rotation += degrees;
_rotate_cb(erd, 1.0);
return EINA_TRUE;
}
if (erd->anim) ecore_animator_del(erd->anim);
erd->anim = ecore_animator_timeline_add(total_time, (Ecore_Timeline_Cb)_rotate_cb, erd);
return EINA_TRUE;
}
EAPI void
e_efx_rotate_reset(Evas_Object *obj)
{
_rotate_stop(obj, EINA_TRUE);
}
EAPI void
e_efx_rotate_stop(Evas_Object *obj)
{
_rotate_stop(obj, EINA_FALSE);
}

148
src/bin/efx/efx_spin.c Normal file
View File

@ -0,0 +1,148 @@
#include "e_efx_private.h"
typedef struct E_Efx_Spin_Data
{
E_EFX *e;
Ecore_Animator *anim;
long dps;
double start;
unsigned int frame;
} E_Efx_Spin_Data;
static void
_obj_del(void *data EINA_UNUSED, Evas *evas EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
{
E_EFX *e;
E_Efx_Spin_Data *esd;
e = evas_object_data_get(obj, "e_efx-data");
if (!e) return; /* bug? */
esd = e->spin_data;
if (esd)
{
if (esd->anim) ecore_animator_del(esd->anim);
e->spin_data = NULL;
free(esd);
}
if ((!e->owner) && (!e->followers)) e_efx_free(e);
}
static Eina_Bool
_spin_cb(E_Efx_Spin_Data *esd)
{
double fps;
Eina_List *l;
E_EFX *e;
fps = 1.0 / ecore_animator_frametime_get();
esd->e->map_data.rotation = (double)esd->frame * ((double)esd->dps / fps) + esd->start;
e_efx_maps_apply(esd->e, esd->e->obj, NULL, E_EFX_MAPS_APPLY_ALL);
EINA_LIST_FOREACH(esd->e->followers, l, e)
{
e_efx_maps_apply(e, e->obj, NULL, E_EFX_MAPS_APPLY_ALL);
}
/*
if (esd->frame % (int)fps == 0)
DBG("frame: %u || rotate: %g", esd->frame, esd->e->map_data.rotation);
*/
if (!fmod(esd->e->map_data.rotation, 360.0)) esd->frame = 0;
esd->frame++; /* FIXME: this may overflow */
return EINA_TRUE;
}
static void
_spin_stop(Evas_Object *obj, Eina_Bool reset)
{
E_EFX *e;
E_Efx_Spin_Data *esd;
e = evas_object_data_get(obj, "e_efx-data");
if ((!e) || (!e->spin_data)) return;
esd = e->spin_data;
esd->frame = 0;
if (reset)
{
esd->e->map_data.rotation = esd->start = 0;
e_efx_rotate_center_init(esd->e, NULL);
_spin_cb(esd);
evas_object_event_callback_del_full(obj, EVAS_CALLBACK_FREE, (Evas_Object_Event_Cb)_obj_del, esd);
_obj_del(NULL, NULL, e->obj, NULL);
INF("reset spinning object %p", obj);
}
else
{
INF("stopped spinning object %p", obj);
if (esd->anim) ecore_animator_del(esd->anim);
free(esd);
e->spin_data = NULL;
}
}
void
_e_efx_spin_calc(void *data, void *owner, Evas_Object *obj, Evas_Map *map)
{
E_Efx_Spin_Data *esd = data;
E_Efx_Spin_Data *esd2 = owner;
e_efx_rotate_helper(esd2 ? esd2->e : (esd ? esd->e : NULL), obj, map, (esd ? esd->e->map_data.rotation : 0) + (esd2 ? esd2->e->map_data.rotation : 0));
}
EAPI Eina_Bool
e_efx_spin_start(Evas_Object *obj, long dps, const Evas_Point *center)
{
E_EFX *e;
E_Efx_Spin_Data *esd;
EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EINA_FALSE);
EINA_SAFETY_ON_FALSE_RETURN_VAL(dps, EINA_FALSE);
/* must stop rotating if object is in motion */
e_efx_rotate_stop(obj);
e = evas_object_data_get(obj, "e_efx-data");
if (!e) e = e_efx_new(obj);
EINA_SAFETY_ON_NULL_RETURN_VAL(e, EINA_FALSE);
if (!e_efx_rotate_center_init(e, center)) return EINA_FALSE;
esd = e->spin_data;
if (esd)
{
esd->dps = dps;
esd->start = esd->e->map_data.rotation;
if (!esd->anim) esd->anim = ecore_animator_add((Ecore_Task_Cb)_spin_cb, esd);
if (e->map_data.rotate_center)
INF("spin modified: %p - %s around (%d,%d) || %lddps", obj, (dps > 0) ? "clockwise" : "counter-clockwise",
e->map_data.rotate_center->x, e->map_data.rotate_center->y, dps);
else
INF("spin modified: %p - %s || %lddps", obj, (dps > 0) ? "clockwise" : "counter-clockwise", dps);
return EINA_TRUE;
}
else
{
e->spin_data = esd = calloc(1, sizeof(E_Efx_Spin_Data));
EINA_SAFETY_ON_NULL_RETURN_VAL(esd, EINA_FALSE);
evas_object_event_callback_add(obj, EVAS_CALLBACK_FREE, (Evas_Object_Event_Cb)_obj_del, e->spin_data);
}
esd->e = e;
esd->dps = dps;
esd->start = e->map_data.rotation;
if (e->map_data.rotate_center)
INF("spin: %p - %s around (%d,%d) || %lddps", obj, (dps > 0) ? "clockwise" : "counter-clockwise",
e->map_data.rotate_center->x, e->map_data.rotate_center->y, dps);
else
INF("spin: %p - %s || %lddps", obj, (dps > 0) ? "clockwise" : "counter-clockwise", dps);
esd->anim = ecore_animator_add((Ecore_Task_Cb)_spin_cb, esd);
return EINA_TRUE;
(void)e_efx_speed_str;
}
EAPI void
e_efx_spin_reset(Evas_Object *obj)
{
_spin_stop(obj, EINA_TRUE);
}
EAPI void
e_efx_spin_stop(Evas_Object *obj)
{
_spin_stop(obj, EINA_FALSE);
}

137
src/bin/efx/efx_util.c Normal file
View File

@ -0,0 +1,137 @@
#include "e_efx_private.h"
static void
_obj_del(void *data EINA_UNUSED, Evas *evas EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
{
E_EFX *e;
e = evas_object_data_get(obj, "e_efx-data");
if (!e) return;
if (e->owner)
e->owner->followers = eina_list_remove(e->owner->followers, e);
e->owner = NULL;
e_efx_free(e);
}
EAPI void
e_efx_realize(Evas_Object *obj)
{
E_EFX *e;
Evas_Coord x, y, ox, oy, w, h;
Evas_Point p1, p2;
double zw, zh;
Evas_Map *map;
e = evas_object_data_get(obj, "e_efx-data");
if (!e) return;
if (!e->map_data.rotate_center) return;
evas_object_geometry_get(obj, &ox, &oy, &w, &h);
map = (Evas_Map*)evas_object_map_get(obj);
if (!map) return;
evas_map_point_coord_get(map, 0, &p1.x, &p1.y, NULL);
evas_map_point_coord_get(map, 2, &p2.x, &p2.y, NULL);
x = lround((double)(p1.x + p2.x) / 2.);
y = lround((double)(p1.y + p2.y) / 2.);
if (e->map_data.zoom)
zw = e->map_data.zoom * w, zh = e->map_data.zoom * h;
else
zw = w, zh = h;
x = lround(x - (zw / 2.));
y = lround(y - (zh / 2.));
evas_object_move(obj, x, y);
evas_object_resize(obj, lround(zw), lround(zh));
e->map_data.zoom = 0;
free(e->map_data.rotate_center);
e->map_data.rotate_center = NULL;
map = e_efx_map_new(obj);
e_efx_maps_apply(e, obj, map, E_EFX_MAPS_APPLY_ALL);
e_efx_map_set(obj, map);
INF("realize: %p - (%d,%d)@%dx%d -> (%d,%d)@%dx%d", obj, ox, oy, w, h, x, y, (int)zw, (int)zh);
}
EAPI Eina_Bool
e_efx_follow(Evas_Object *obj, Evas_Object *follower)
{
E_EFX *e, *ef;
EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EINA_FALSE);
EINA_SAFETY_ON_NULL_RETURN_VAL(follower, EINA_FALSE);
e = evas_object_data_get(obj, "e_efx-data");
if (!e) e = e_efx_new(obj);
EINA_SAFETY_ON_NULL_RETURN_VAL(e, EINA_FALSE);
while (e->owner) e = e->owner;
ef = evas_object_data_get(follower, "e_efx-data");
if (ef)
{
if (ef->owner)
{
if (ef->owner == e) return EINA_TRUE;
ef->owner->followers = eina_list_remove(ef->owner->followers, ef);
}
}
else
ef = e_efx_new(follower);
EINA_SAFETY_ON_NULL_RETURN_VAL(ef, EINA_FALSE);
if ((!ef->zoom_data) && (!ef->rotate_data) && (!ef->spin_data) && (!ef->move_data) && (!ef->bumpmap_data) && (!ef->pan_data) && (!ef->fade_data))
evas_object_event_callback_priority_add(ef->obj, EVAS_CALLBACK_FREE, EVAS_CALLBACK_PRIORITY_BEFORE, (Evas_Object_Event_Cb)_obj_del, ef);
ef->owner = e;
e->followers = eina_list_append(e->followers, ef);
INF("follow: (owner %p: %u) || (follower %p)", obj, eina_list_count(e->followers), follower);
return EINA_TRUE;
(void)e_efx_speed_str;
}
EAPI void
e_efx_unfollow(Evas_Object *obj)
{
E_EFX *e;
EINA_SAFETY_ON_NULL_RETURN(obj);
e = evas_object_data_get(obj, "e_efx-data");
if (!e) return;
if (!e->owner) return;
INF("unfollow: (owner %p) || (follower %p)", e->owner->obj, obj);
e->owner->followers = eina_list_remove(e->owner->followers, e);
evas_object_event_callback_del_full(obj, EVAS_CALLBACK_FREE, (Evas_Object_Event_Cb)_obj_del, e);
e_efx_free(e->owner);
e->owner = NULL;
e_efx_free(e);
}
EAPI Eina_List *
e_efx_followers_get(Evas_Object *obj)
{
E_EFX *e, *f;
Eina_List *l, *ret = NULL;
EINA_SAFETY_ON_NULL_RETURN_VAL(obj, NULL);
e = evas_object_data_get(obj, "e_efx-data");
if (!e) return NULL;
EINA_LIST_FOREACH(e->followers, l, f)
ret = eina_list_append(ret, f->obj);
return ret;
}
EAPI Evas_Object *
e_efx_leader_get(Evas_Object *obj)
{
E_EFX *e;
EINA_SAFETY_ON_NULL_RETURN_VAL(obj, NULL);
e = evas_object_data_get(obj, "e_efx-data");
if (!e) return NULL;
return e->owner ? e->owner->obj : NULL;
}
EAPI void
e_efx_reclip(Evas_Object *obj)
{
E_EFX *e;
EINA_SAFETY_ON_NULL_RETURN(obj);
e = evas_object_data_get(obj, "e_efx-data");
if (!e) return;
if (e->fade_data) e_efx_fade_reclip(e->fade_data);
}

171
src/bin/efx/efx_zoom.c Normal file
View File

@ -0,0 +1,171 @@
#include "e_efx_private.h"
typedef struct E_Efx_Zoom_Data
{
E_EFX *e;
Ecore_Animator *anim;
E_Efx_Effect_Speed speed;
double ending_zoom;
double starting_zoom;
E_Efx_End_Cb cb;
void *data;
} E_Efx_Zoom_Data;
static void
_obj_del(E_Efx_Zoom_Data *ezd, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
{
if (ezd->anim) ecore_animator_del(ezd->anim);
ezd->e->zoom_data = NULL;
if ((!ezd->e->owner) && (!ezd->e->followers)) e_efx_free(ezd->e);
free(ezd);
}
static void
_zoom_center_calc(E_EFX *e, Evas_Object *obj, Evas_Coord *x, Evas_Coord *y)
{
Evas_Coord w, h;
if (e->map_data.zoom_center)
{
*x = e->map_data.zoom_center->x;
*y = e->map_data.zoom_center->y;
}
else
{
evas_object_geometry_get(obj, x, y, &w, &h);
*x += (w / 2);
*y += (h / 2);
}
}
static void
_zoom(E_EFX *e, Evas_Object *obj, double zoom)
{
Evas_Map *map;
Evas_Coord x, y;
map = e_efx_map_new(obj);
_zoom_center_calc(e, e->obj, &x, &y);
//DBG("ZOOM %p: %g: %d,%d", obj, zoom, x, y);
evas_map_util_zoom(map, zoom, zoom, x, y);
e_efx_maps_apply(e, obj, map, E_EFX_MAPS_APPLY_ROTATE_SPIN);
e_efx_map_set(obj, map);
}
static Eina_Bool
_zoom_cb(E_Efx_Zoom_Data *ezd, double pos)
{
double zoom;
Eina_List *l;
E_EFX *e;
zoom = ecore_animator_pos_map(pos, ezd->speed, 0, 0);
ezd->e->map_data.zoom = (zoom * (ezd->ending_zoom - ezd->starting_zoom)) + ezd->starting_zoom;
//DBG("total: %g || zoom (pos %g): %g || endzoom: %g || startzoom: %g", ezd->e->map_data.zoom, zoom, pos, ezd->ending_zoom, ezd->starting_zoom);
e_efx_maps_apply(ezd->e, ezd->e->obj, NULL, E_EFX_MAPS_APPLY_ALL);
EINA_LIST_FOREACH(ezd->e->followers, l, e)
e_efx_maps_apply(e, e->obj, NULL, E_EFX_MAPS_APPLY_ALL);
if (pos < 1.0) return EINA_TRUE;
ezd->anim = NULL;
E_EFX_QUEUE_CHECK(ezd);
return EINA_TRUE;
}
static void
_zoom_stop(Evas_Object *obj, Eina_Bool reset)
{
E_EFX *e;
E_Efx_Zoom_Data *ezd;
e = evas_object_data_get(obj, "e_efx-data");
if ((!e) || (!e->zoom_data)) return;
ezd = e->zoom_data;
if (reset)
{
ezd->starting_zoom = 0.0;
_zoom(e, obj, 1.0);
evas_object_event_callback_del_full(obj, EVAS_CALLBACK_FREE, (Evas_Object_Event_Cb)_obj_del, ezd);
if (e_efx_queue_complete(ezd->e, ezd))
e_efx_queue_process(ezd->e);
_obj_del(ezd, NULL, NULL, NULL);
INF("reset zooming object %p", obj);
}
else
{
ecore_animator_del(ezd->anim);
ezd->anim = NULL;
INF("stopped zooming object %p", obj);
if (e_efx_queue_complete(ezd->e, ezd))
e_efx_queue_process(ezd->e);
}
}
void
_e_efx_zoom_calc(void *data, void *owner, Evas_Object *obj, Evas_Map *map)
{
E_Efx_Zoom_Data *ezd = data;
E_Efx_Zoom_Data *ezd2 = owner;
Evas_Coord x, y;
double zoom;
if ((ezd2 && (ezd2->e->map_data.zoom <= 0)) || (ezd && (ezd->e->map_data.zoom <= 0))) return;
_zoom_center_calc(ezd2 ? ezd2->e : ezd->e, ezd2 ? ezd2->e->obj : obj, &x, &y);
zoom = ezd ? ezd->e->map_data.zoom : 0;
if (ezd2) zoom += ezd2->e->map_data.zoom;
//DBG("zoom: %g @ (%d,%d)", zoom, x, y);
evas_map_util_zoom(map, zoom, zoom, x, y);
}
EAPI Eina_Bool
e_efx_zoom(Evas_Object *obj, E_Efx_Effect_Speed speed, double starting_zoom, double ending_zoom, const Evas_Point *zoom_point, double total_time, E_Efx_End_Cb cb, const void *data)
{
E_EFX *e;
E_Efx_Zoom_Data *ezd;
EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EINA_FALSE);
if (ending_zoom <= 0.0) return EINA_FALSE;
if (starting_zoom < 0.0) return EINA_FALSE;
if (total_time < 0.0) return EINA_FALSE;
if (speed > E_EFX_EFFECT_SPEED_SINUSOIDAL) return EINA_FALSE;
e = evas_object_data_get(obj, "e_efx-data");
if (!e) e = e_efx_new(obj);
EINA_SAFETY_ON_NULL_RETURN_VAL(e, EINA_FALSE);
if (!e_efx_zoom_center_init(e, zoom_point)) return EINA_FALSE;
INF("zoom: %p - %g%%->%g%% over %gs: %s", obj, (starting_zoom ?: e->map_data.zoom) * 100.0, ending_zoom * 100.0, total_time, e_efx_speed_str[speed]);
if (!e->zoom_data)
{
e->zoom_data = calloc(1, sizeof(E_Efx_Zoom_Data));
EINA_SAFETY_ON_NULL_RETURN_VAL(e->zoom_data, EINA_FALSE);
evas_object_event_callback_add(obj, EVAS_CALLBACK_FREE, (Evas_Object_Event_Cb)_obj_del, e->zoom_data);
}
ezd = e->zoom_data;
ezd->e = e;
ezd->speed = speed;
ezd->ending_zoom = ending_zoom;
ezd->starting_zoom = starting_zoom ?: ezd->e->map_data.zoom;
ezd->cb = cb;
ezd->data = (void*)data;
if (!total_time)
{
_zoom_cb(ezd, 1.0);
return EINA_TRUE;
}
if (!ezd->starting_zoom) ezd->starting_zoom = 1.0;
_zoom_cb(ezd, 0);
if (ezd->anim) ecore_animator_del(ezd->anim);
ezd->anim = ecore_animator_timeline_add(total_time, (Ecore_Timeline_Cb)_zoom_cb, ezd);
return EINA_TRUE;
}
EAPI void
e_efx_zoom_reset(Evas_Object *obj)
{
_zoom_stop(obj, EINA_TRUE);
}
EAPI void
e_efx_zoom_stop(Evas_Object *obj)
{
_zoom_stop(obj, EINA_FALSE);
}

View File

@ -3,6 +3,7 @@ MOD_LDFLAGS = -module -avoid-version
MOD_CPPFLAGS = -I. \
-I$(top_srcdir) \
-I$(top_srcdir)/src/bin \
-I$(top_srcdir)/src/bin/efx \
-I$(top_builddir)/src/bin \
-I$(top_srcdir)/src/modules \
@e_cflags@ \