enlightenment/src/bin/efx/efx_queue.c

302 lines
8.8 KiB
C

#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;
}