EPhysics: support autodel of bodies outside render area

Now it's possible to request a world to delete bodies outside
render area, so we can save some resources and avoid issues
with world stopped event.



SVN revision: 73245
This commit is contained in:
Bruno Dilly 2012-07-03 23:20:49 +00:00
parent 23523c9b70
commit 9d0b63143b
4 changed files with 293 additions and 0 deletions

View File

@ -621,6 +621,150 @@ EAPI void ephysics_world_linear_slop_set(EPhysics_World *world, double linear_sl
*/
EAPI double ephysics_world_linear_slop_get(EPhysics_World *world);
/**
* @brief
* Set world autodeleting bodies mode when they're outside of render area
* by the top.
*
* It's useful when you don't care about bodies leaving the render
* area set with @ref ephysics_world_render_area_set(), and don't think
* they could / should return. So you can safely delete them and save resources.
*
* Also, it's useful if you have only a bottom border set with
* @ref ephysics_body_top_boundary_add() and gravity set,
* and want to listen for @ref EPHYSICS_CALLBACK_WORLD_STOPPED event.
* If a body goes out of the render area, they will be acting by gravity
* and won't collide to anything, so they could be moving forever and
* world would never stop. For this case, enabling autodel for left and right
* borders seems to be a good idea.
*
* @param world The physics world.
* @param autodel If @c EINA_TRUE delete bodies when they are outside render
* area, otherwise, don't delete.
*
* @see ephysics_world_bodies_outside_top_autodel_get().
* @see ephysics_world_bodies_outside_bottom_autodel_set().
* @see ephysics_world_bodies_outside_left_autodel_set().
* @see ephysics_world_bodies_outside_right_autodel_set().
*
* @ingroup EPhysics_World
*/
EAPI void ephysics_world_bodies_outside_top_autodel_set(EPhysics_World *world, Eina_Bool autodel);
/**
* @brief
* Get world autodeleting bodies mode when they're outside of render area by
* the top.
*
* @param world The physics world.
* @return @c EINA_TRUE if bodies will be deleted or @c EINA_FALSE if they
* won't, or on error.
*
* @see ephysics_world_bodies_outside_top_autodel_set() for details.
*
* @ingroup EPhysics_World
*/
EAPI Eina_Bool ephysics_world_bodies_outside_top_autodel_get(EPhysics_World *world);
/**
* @brief
* Set world autodeleting bodies mode when they're outside of render area
* by the bottom.
*
* @param world The physics world.
* @param autodel If @c EINA_TRUE delete bodies when they are outside render
* area, otherwise, don't delete.
*
* @see ephysics_world_bodies_outside_top_autodel_set() for more details.
* @see ephysics_world_bodies_outside_bottom_autodel_get().
* @see ephysics_world_bodies_outside_left_autodel_set().
* @see ephysics_world_bodies_outside_right_autodel_set().
*
* @ingroup EPhysics_World
*/
EAPI void ephysics_world_bodies_outside_bottom_autodel_set(EPhysics_World *world, Eina_Bool autodel);
/**
* @brief
* Get world autodeleting bodies mode when they're outside of render area by
* the bottom.
*
* @param world The physics world.
* @return @c EINA_TRUE if bodies will be deleted or @c EINA_FALSE if they
* won't, or on error.
*
* @see ephysics_world_bodies_outside_bottom_autodel_set() for details.
*
* @ingroup EPhysics_World
*/
EAPI Eina_Bool ephysics_world_bodies_outside_bottom_autodel_get(EPhysics_World *world);
/**
* @brief
* Set world autodeleting bodies mode when they're outside of render area
* by the right.
*
* @param world The physics world.
* @param autodel If @c EINA_TRUE delete bodies when they are outside render
* area, otherwise, don't delete.
*
* @see ephysics_world_bodies_outside_top_autodel_set() for more details.
* @see ephysics_world_bodies_outside_right_autodel_get().
* @see ephysics_world_bodies_outside_bottom_autodel_set().
* @see ephysics_world_bodies_outside_left_autodel_set().
*
* @ingroup EPhysics_World
*/
EAPI void ephysics_world_bodies_outside_right_autodel_set(EPhysics_World *world, Eina_Bool autodel);
/**
* @brief
* Get world autodeleting bodies mode when they're outside of render area by
* the right.
*
* @param world The physics world.
* @return @c EINA_TRUE if bodies will be deleted or @c EINA_FALSE if they
* won't, or on error.
*
* @see ephysics_world_bodies_outside_right_autodel_set() for details.
*
* @ingroup EPhysics_World
*/
EAPI Eina_Bool ephysics_world_bodies_outside_right_autodel_get(EPhysics_World *world);
/**
* @brief
* Set world autodeleting bodies mode when they're outside of render area
* by the left.
*
* @param world The physics world.
* @param autodel If @c EINA_TRUE delete bodies when they are outside render
* area, otherwise, don't delete.
*
* @see ephysics_world_bodies_outside_top_autodel_set() for more details.
* @see ephysics_world_bodies_outside_left_autodel_get().
* @see ephysics_world_bodies_outside_bottom_autodel_set().
* @see ephysics_world_bodies_outside_right_autodel_set().
*
* @ingroup EPhysics_World
*/
EAPI void ephysics_world_bodies_outside_left_autodel_set(EPhysics_World *world, Eina_Bool autodel);
/**
* @brief
* Get world autodeleting bodies mode when they're outside of render area by
* the left.
*
* @param world The physics world.
* @return @c EINA_TRUE if bodies will be deleted or @c EINA_FALSE if they
* won't, or on error.
*
* @see ephysics_world_bodies_outside_left_autodel_set() for details.
*
* @ingroup EPhysics_World
*/
EAPI Eina_Bool ephysics_world_bodies_outside_left_autodel_get(EPhysics_World *world);
/**
* @}
*/

View File

@ -186,6 +186,30 @@ _ephysics_body_evas_object_default_update(EPhysics_Body *body)
evas_map_free(map);
}
static void
_ephysics_body_outside_render_area_check(EPhysics_Body *body)
{
int wx, wy, ww, wh, bx, by, bw, bh;
ephysics_world_render_geometry_get(body->world, &wx, &wy, &ww, &wh);
ephysics_body_geometry_get(body, &bx, &by, &bw, &bh);
// FIXME: check what should be done regarding rotated bodies
if (((ephysics_world_bodies_outside_top_autodel_get(body->world)) &&
(by + bh < wy)) ||
((ephysics_world_bodies_outside_bottom_autodel_get(body->world)) &&
(by > wy + wh)) ||
((ephysics_world_bodies_outside_left_autodel_get(body->world)) &&
(bx + bh < wx)) ||
((ephysics_world_bodies_outside_right_autodel_get(body->world)) &&
(bx > wx + ww)))
{
ephysics_world_body_del(body->world, body, body->rigid_body);
ephysics_orphan_body_del(body);
DBG("Body %p deleted. Out of render area", body);
}
}
void
ephysics_body_evas_object_update_select(EPhysics_Body *body)
{
@ -205,6 +229,9 @@ ephysics_body_evas_object_update_select(EPhysics_Body *body)
if (!callback_called)
_ephysics_body_evas_object_default_update(body);
if (ephysics_world_bodies_outside_autodel_get(body->world))
_ephysics_body_outside_render_area_check(body);
}
void

View File

@ -62,6 +62,7 @@ void ephysics_world_constraint_del(EPhysics_World *world, btTypedConstraint *bt_
void ephysics_body_world_boundaries_resize(EPhysics_World *world);
void ephysics_world_boundary_set(EPhysics_World *world, EPhysics_World_Boundary boundary, EPhysics_Body *body);
EPhysics_Body *ephysics_world_boundary_get(const EPhysics_World *world, EPhysics_World_Boundary boundary);
Eina_Bool ephysics_world_bodies_outside_autodel_get(EPhysics_World *world);
void ephysics_body_evas_object_update_select(EPhysics_Body *body);
void ephysics_orphan_body_del(EPhysics_Body *body);

View File

@ -35,6 +35,11 @@ struct _EPhysics_World {
double rate;
Eina_Bool running:1;
Eina_Bool active: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;
};
static int _ephysics_world_init_count = 0;
@ -692,6 +697,122 @@ ephysics_world_linear_slop_get(EPhysics_World *world)
return world->dynamics_world->getSolverInfo().m_linearSlop;
}
EAPI void
ephysics_world_bodies_outside_top_autodel_set(EPhysics_World *world, Eina_Bool autodel)
{
if (!world)
{
ERR("Can't set autodelete mode, world is null.");
return;
}
world->outside_top = !!autodel;
world->outside_autodel = world->outside_top || world->outside_bottom ||
world->outside_left || world->outside_right;
}
EAPI Eina_Bool
ephysics_world_bodies_outside_top_autodel_get(EPhysics_World *world)
{
if (!world)
{
ERR("Can't get autodelete mode, world is null.");
return EINA_FALSE;
}
return world->outside_top;
}
EAPI void
ephysics_world_bodies_outside_bottom_autodel_set(EPhysics_World *world, Eina_Bool autodel)
{
if (!world)
{
ERR("Can't set autodelete mode, world is null.");
return;
}
world->outside_bottom = !!autodel;
world->outside_autodel = world->outside_top || world->outside_bottom ||
world->outside_left || world->outside_right;
}
EAPI Eina_Bool
ephysics_world_bodies_outside_bottom_autodel_get(EPhysics_World *world)
{
if (!world)
{
ERR("Can't get autodelete mode, world is null.");
return EINA_FALSE;
}
return world->outside_bottom;
}
EAPI void
ephysics_world_bodies_outside_left_autodel_set(EPhysics_World *world, Eina_Bool autodel)
{
if (!world)
{
ERR("Can't set autodelete mode, world is null.");
return;
}
world->outside_left = !!autodel;
world->outside_autodel = world->outside_top || world->outside_bottom ||
world->outside_left || world->outside_right;
}
EAPI Eina_Bool
ephysics_world_bodies_outside_left_autodel_get(EPhysics_World *world)
{
if (!world)
{
ERR("Can't get autodelete mode, world is null.");
return EINA_FALSE;
}
return world->outside_left;
}
EAPI void
ephysics_world_bodies_outside_right_autodel_set(EPhysics_World *world, Eina_Bool autodel)
{
if (!world)
{
ERR("Can't set autodelete mode, world is null.");
return;
}
world->outside_right = !!autodel;
world->outside_autodel = world->outside_top || world->outside_bottom ||
world->outside_left || world->outside_right;
}
EAPI Eina_Bool
ephysics_world_bodies_outside_right_autodel_get(EPhysics_World *world)
{
if (!world)
{
ERR("Can't get autodelete mode, world is null.");
return EINA_FALSE;
}
return world->outside_right;
}
Eina_Bool
ephysics_world_bodies_outside_autodel_get(EPhysics_World *world)
{
if (!world)
{
ERR("Can't get autodelete mode, world is null.");
return EINA_FALSE;
}
return world->outside_autodel;
}
#ifdef __cplusplus
}
#endif