EPhysics: properly handle world delete

SVN revision: 75140
This commit is contained in:
Bruno Dilly 2012-08-10 21:03:29 +00:00
parent 4d800075e7
commit 0bd1f327a4
1 changed files with 62 additions and 26 deletions

View File

@ -36,20 +36,23 @@ struct _EPhysics_World {
double last_update;
double rate;
double fixed_time_step;
double max_sleeping_time;
Eina_Bool running:1;
Eina_Bool active:1;
Eina_Bool deleted:1;
Eina_Bool outside_autodel:1;
Eina_Bool outside_top:1;
Eina_Bool outside_bottom:1;
Eina_Bool outside_left:1;
Eina_Bool outside_right:1;
double max_sleeping_time;
};
static int _ephysics_world_init_count = 0;
static int _worlds_running = 0;
static Eina_Inlist *_worlds = NULL;
static Eina_List *_worlds_to_delete = NULL;
static Ecore_Animator *_anim_simulate = NULL;
static int _worlds_walking = 0;
struct _ephysics_world_ovelap_filter_cb : public btOverlapFilterCallback
{
@ -124,13 +127,51 @@ _ephysics_world_tick_cb(btDynamicsWorld *dynamics_world, btScalar timeStep)
cb->func(cb->data, world, NULL);
}
static void
_ephysics_world_free(EPhysics_World *world)
{
EPhysics_World_Callback *cb;
EPhysics_Body *body;
_worlds = eina_inlist_remove(_worlds, EINA_INLIST_GET(world));
while (world->callbacks)
{
cb = EINA_INLIST_CONTAINER_GET(world->callbacks,
EPhysics_World_Callback);
world->callbacks = eina_inlist_remove(world->callbacks,
world->callbacks);
free(cb);
}
while (world->bodies)
{
body = EINA_INLIST_CONTAINER_GET(world->bodies, EPhysics_Body);
world->bodies = eina_inlist_remove(world->bodies, world->bodies);
ephysics_orphan_body_del(body);
}
ephysics_camera_del(world->camera);
delete world->dynamics_world;
delete world->solver;
delete world->dispatcher;
delete world->collision;
delete world->broadphase;
free(world);
INF("World %p deleted.", world);
}
static Eina_Bool
_simulate_worlds(void *data)
{
Eina_Inlist *lworlds = (Eina_Inlist *) data;
EPhysics_World *world;
double time_now;
void *wrld;
ephysics_init();
_worlds_walking++;
EINA_INLIST_FOREACH(lworlds, world)
{
double time_now, delta;
@ -146,6 +187,18 @@ _simulate_worlds(void *data)
world->dynamics_world->stepSimulation(delta, world->max_sub_steps,
world->fixed_time_step);
}
_worlds_walking--;
if (_worlds_walking > 0)
{
ephysics_shutdown();
return EINA_TRUE;
}
EINA_LIST_FREE(_worlds_to_delete, wrld)
_ephysics_world_free((EPhysics_World *)wrld);
ephysics_shutdown();
return EINA_TRUE;
}
@ -247,7 +300,6 @@ ephysics_world_shutdown(void)
{
EPhysics_World *world = EINA_INLIST_CONTAINER_GET(
_worlds, EPhysics_World);
_worlds = eina_inlist_remove(_worlds, _worlds);
ephysics_world_del(world);
}
@ -422,7 +474,6 @@ EAPI void
ephysics_world_del(EPhysics_World *world)
{
EPhysics_World_Callback *cb;
EPhysics_Body *body;
if (!world)
{
@ -430,6 +481,9 @@ ephysics_world_del(EPhysics_World *world)
return;
}
if (world->deleted) return;
world->deleted = EINA_TRUE;
EINA_INLIST_FOREACH(world->callbacks, cb)
{
if (cb->type == EPHYSICS_CALLBACK_WORLD_DEL)
@ -437,33 +491,15 @@ ephysics_world_del(EPhysics_World *world)
}
ephysics_world_running_set(world, EINA_FALSE);
_worlds = eina_inlist_remove(_worlds, EINA_INLIST_GET(world));
while (world->callbacks)
if (_worlds_walking > 0)
{
cb = EINA_INLIST_CONTAINER_GET(world->callbacks,
EPhysics_World_Callback);
world->callbacks = eina_inlist_remove(world->callbacks,
world->callbacks);
free(cb);
_worlds_to_delete = eina_list_append(_worlds_to_delete, world);
INF("World %p marked to delete.", world);
return;
}
while (world->bodies)
{
body = EINA_INLIST_CONTAINER_GET(world->bodies, EPhysics_Body);
world->bodies = eina_inlist_remove(world->bodies, world->bodies);
ephysics_orphan_body_del(body);
}
ephysics_camera_del(world->camera);
delete world->dynamics_world;
delete world->solver;
delete world->dispatcher;
delete world->collision;
delete world->broadphase;
free(world);
INF("World %p deleted.", world);
_ephysics_world_free(world);
}
EAPI void