forked from enlightenment/enlightenment
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:
parent
d4996e2db3
commit
d3fe687ada
|
@ -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 += \
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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@ \
|
||||
|
|
|
@ -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())
|
||||
{
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -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
|
|
@ -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();
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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@ \
|
||||
|
|
Loading…
Reference in New Issue