From: Enlightenment S. <no-...@en...> - 2012-07-03 23:20:57
|
Log: 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. Author: bdilly Date: 2012-07-03 16:20:49 -0700 (Tue, 03 Jul 2012) New Revision: 73245 Trac: http://trac.enlightenment.org/e/changeset/73245 Modified: trunk/ephysics/src/lib/EPhysics.h trunk/ephysics/src/lib/ephysics_body.cpp trunk/ephysics/src/lib/ephysics_private.h trunk/ephysics/src/lib/ephysics_world.cpp Modified: trunk/ephysics/src/lib/EPhysics.h =================================================================== --- trunk/ephysics/src/lib/EPhysics.h 2012-07-03 16:28:06 UTC (rev 73244) +++ trunk/ephysics/src/lib/EPhysics.h 2012-07-03 23:20:49 UTC (rev 73245) @@ -622,6 +622,150 @@ 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); + +/** * @} */ Modified: trunk/ephysics/src/lib/ephysics_body.cpp =================================================================== --- trunk/ephysics/src/lib/ephysics_body.cpp 2012-07-03 16:28:06 UTC (rev 73244) +++ trunk/ephysics/src/lib/ephysics_body.cpp 2012-07-03 23:20:49 UTC (rev 73245) @@ -186,6 +186,30 @@ 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 @@ 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 Modified: trunk/ephysics/src/lib/ephysics_private.h =================================================================== --- trunk/ephysics/src/lib/ephysics_private.h 2012-07-03 16:28:06 UTC (rev 73244) +++ trunk/ephysics/src/lib/ephysics_private.h 2012-07-03 23:20:49 UTC (rev 73245) @@ -62,6 +62,7 @@ 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); Modified: trunk/ephysics/src/lib/ephysics_world.cpp =================================================================== --- trunk/ephysics/src/lib/ephysics_world.cpp 2012-07-03 16:28:06 UTC (rev 73244) +++ trunk/ephysics/src/lib/ephysics_world.cpp 2012-07-03 23:20:49 UTC (rev 73245) @@ -35,6 +35,11 @@ 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 @@ 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 |