190 lines
5.9 KiB
C
190 lines
5.9 KiB
C
#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);
|
|
efd->anim = NULL;
|
|
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;
|
|
int r, g, b, a;
|
|
|
|
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, &r, &g, &b, &a);
|
|
efd->start.r = r;
|
|
efd->start.g = g;
|
|
efd->start.b = b;
|
|
efd->alpha[0] = a;
|
|
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 (!eina_dbl_exact(total_time, 0))
|
|
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);
|
|
}
|