EPhysics: fix world event callbacks management

SVN revision: 75146
This commit is contained in:
Bruno Dilly 2012-08-10 21:04:22 +00:00
parent fb7528829b
commit 1de4a67ca0
1 changed files with 66 additions and 27 deletions

View File

@ -17,6 +17,7 @@ struct _EPhysics_World_Callback {
void (*func) (void *data, EPhysics_World *world, void *event_info); void (*func) (void *data, EPhysics_World *world, void *event_info);
void *data; void *data;
EPhysics_Callback_World_Type type; EPhysics_Callback_World_Type type;
Eina_Bool deleted:1;
}; };
struct _EPhysics_World { struct _EPhysics_World {
@ -33,8 +34,10 @@ struct _EPhysics_World {
Eina_Inlist *callbacks; Eina_Inlist *callbacks;
Eina_Inlist *bodies; Eina_Inlist *bodies;
Eina_List *to_delete; Eina_List *to_delete;
Eina_List *cb_to_delete;
int max_sub_steps; int max_sub_steps;
int walking; int walking;
int cb_walking;
double last_update; double last_update;
double rate; double rate;
double fixed_time_step; double fixed_time_step;
@ -74,6 +77,49 @@ struct _ephysics_world_ovelap_filter_cb : public btOverlapFilterCallback
} }
}; };
static void
_ephysics_world_event_callback_call(EPhysics_World *world, EPhysics_Callback_World_Type type, void *event_info)
{
EPhysics_World_Callback *cb;
void *clb;
world->cb_walking++;
EINA_INLIST_FOREACH(world->callbacks, cb)
{
if ((cb->type == type) && (!cb->deleted))
cb->func(cb->data, world, event_info);
}
world->cb_walking--;
if (world->cb_walking > 0) return;
EINA_LIST_FREE(world->cb_to_delete, clb)
{
cb = (EPhysics_World_Callback *)clb;
world->callbacks = eina_inlist_remove(world->callbacks,
EINA_INLIST_GET(cb));
free(cb);
}
}
static void
_ephysics_world_event_callback_del(EPhysics_World *world, EPhysics_World_Callback *cb)
{
if (cb->deleted) return;
cb->deleted = EINA_TRUE;
if (world->cb_walking)
{
world->cb_to_delete = eina_list_append(world->cb_to_delete, cb);
return;
}
world->callbacks = eina_inlist_remove(world->callbacks,
EINA_INLIST_GET(cb));
free(cb);
}
static void static void
_ephysics_world_tick_cb(btDynamicsWorld *dynamics_world, btScalar timeStep) _ephysics_world_tick_cb(btDynamicsWorld *dynamics_world, btScalar timeStep)
{ {
@ -125,9 +171,8 @@ _ephysics_world_tick_cb(btDynamicsWorld *dynamics_world, btScalar timeStep)
world->active = world_active; world->active = world_active;
if (world_active) return; if (world_active) return;
EINA_INLIST_FOREACH(world->callbacks, cb) _ephysics_world_event_callback_call(world, EPHYSICS_CALLBACK_WORLD_STOPPED,
if (cb->type == EPHYSICS_CALLBACK_WORLD_STOPPED) NULL);
cb->func(cb->data, world, NULL);
} }
static void static void
@ -511,12 +556,8 @@ ephysics_world_del(EPhysics_World *world)
if (world->deleted) return; if (world->deleted) return;
world->deleted = EINA_TRUE; world->deleted = EINA_TRUE;
EINA_INLIST_FOREACH(world->callbacks, cb) _ephysics_world_event_callback_call(world, EPHYSICS_CALLBACK_WORLD_DEL,
{ NULL);
if (cb->type == EPHYSICS_CALLBACK_WORLD_DEL)
cb->func(cb->data, world, NULL);
}
ephysics_world_running_set(world, EINA_FALSE); ephysics_world_running_set(world, EINA_FALSE);
if (_worlds_walking > 0) if (_worlds_walking > 0)
@ -774,7 +815,7 @@ EAPI void *
ephysics_world_event_callback_del(EPhysics_World *world, EPhysics_Callback_World_Type type, EPhysics_World_Event_Cb func) ephysics_world_event_callback_del(EPhysics_World *world, EPhysics_Callback_World_Type type, EPhysics_World_Event_Cb func)
{ {
EPhysics_World_Callback *cb; EPhysics_World_Callback *cb;
void *cb_data; void *cb_data = NULL;
if (!world) if (!world)
{ {
@ -784,23 +825,22 @@ ephysics_world_event_callback_del(EPhysics_World *world, EPhysics_Callback_World
EINA_INLIST_FOREACH(world->callbacks, cb) EINA_INLIST_FOREACH(world->callbacks, cb)
{ {
if ((cb->type == type) && (cb->func == func)) { if ((cb->type != type) || (cb->func != func))
cb_data = cb->data; continue;
world->callbacks = eina_inlist_remove(world->callbacks,
EINA_INLIST_GET(cb)); cb_data = cb->data;
free(cb); _ephysics_world_event_callback_del(world, cb);
return cb_data; break;
}
} }
return NULL; return cb_data;
} }
EAPI void * EAPI void *
ephysics_world_event_callback_del_full(EPhysics_World *world, EPhysics_Callback_World_Type type, EPhysics_World_Event_Cb func, void *data) ephysics_world_event_callback_del_full(EPhysics_World *world, EPhysics_Callback_World_Type type, EPhysics_World_Event_Cb func, void *data)
{ {
EPhysics_World_Callback *cb; EPhysics_World_Callback *cb;
void *cb_data; void *cb_data = NULL;
if (!world) if (!world)
{ {
@ -810,16 +850,15 @@ ephysics_world_event_callback_del_full(EPhysics_World *world, EPhysics_Callback_
EINA_INLIST_FOREACH(world->callbacks, cb) EINA_INLIST_FOREACH(world->callbacks, cb)
{ {
if ((cb->type == type) && (cb->func == func) && (cb->data == data)) { if ((cb->type != type) || (cb->func != func) || (cb->data != data))
cb_data = cb->data; continue;
world->callbacks = eina_inlist_remove(world->callbacks,
EINA_INLIST_GET(cb)); cb_data = cb->data;
free(cb); _ephysics_world_event_callback_del(world, cb);
return cb_data; break;
}
} }
return NULL; return cb_data;
} }
EAPI Eina_List * EAPI Eina_List *