/**
* @brief
+ * Add a @p body to a given collision group.
+ *
+ * After calling this function the body is said to be added to collision @p
+ * group.
+ *
+ * If not added to any group the body will collide against any other body.
+ * Otherwise this body will collide only against those in the same groups.
+ *
+ * @param body The body to be added to @p group.
+ * @param group The group the @p body will belong to.
+ * @return EINA_TRUE on success, EINA_FALSE otherwise.
+ *
+ * @see ephysics_body_collision_group_del()
+ * @see ephysics_body_collision_group_list_get()
+ * @ingroup EPhysics_Body
+ */
+EAPI Eina_Bool ephysics_body_collision_group_add(EPhysics_Body *body, const char *group);
+
+/**
+ * @brief
+ * Removes @p body from collision @p group.
+ *
+ * This @p body will not belong to @p group any more and the collisions filter
+ * must take that on account.
+ *
+ * @param body The body to be removed from @p group.
+ * @param group The group @p body must be removed from.
+ * @return EINA_TRUE on success, EINA_FALSE otherwise.
+ *
+ * @see ephysics_body_collision_group_add()
+ * @ingroup EPhysics_Body
+ */
+EAPI Eina_Bool ephysics_body_collision_group_del(EPhysics_Body *body, const char *group);
+
+/**
+ * @brief
+ * Get the collision group list of @p body.
+ *
+ * @param body The body of interest.
+ * @return The collision group list of @p body, NULL on failure or case no
+ * group has been added to @p body.
+ *
+ * @warning The collision group list is an EPhysics internal data structure and
+ * should @b never be modified by its callers.
+ *
+ * @see ephysics_body_collision_group_add()
+ * @ingroup EPhysics_Body
+ */
+EAPI const Eina_List *ephysics_body_collision_group_list_get(const EPhysics_Body *body);
+
+/**
+ * @brief
* Update the evas object associated to the body.
*
* This function should be called to update position and rotation of
Eina_Inlist *callbacks;
double mass;
Eina_Bool active:1;
+ Eina_List *collision_groups;
};
struct _EPhysics_Body_Collision {
EINA_INLIST_FOREACH(body->callbacks, cb)
if (cb->type == EPHYSICS_CALLBACK_BODY_STOPPED)
cb->func(cb->data, body, (void *) body->evas_obj);
+};
+
+Eina_Bool
+ephysics_body_filter_collision(EPhysics_Body *body0, EPhysics_Body *body1)
+{
+ void *grp;
+ Eina_Iterator *it;
+ Eina_List *l;
+
+ if ((!body0->collision_groups) || (!body1->collision_groups))
+ return EINA_TRUE;
+
+ EINA_LIST_FOREACH(body0->collision_groups, l, grp)
+ {
+ if (eina_list_data_find(body1->collision_groups, grp))
+ return EINA_TRUE;
+ }
+
+ return EINA_FALSE;
+}
+
+EAPI Eina_Bool
+ephysics_body_collision_group_add(EPhysics_Body *body, const char *group)
+{
+ Eina_List *l;
+ void *grp;
+ Eina_Stringshare *group_str;
+
+ if (!body)
+ {
+ ERR("Can't add body collision group, body is null.");
+ return EINA_FALSE;
+ }
+
+ group_str = eina_stringshare_add(group);
+ EINA_LIST_FOREACH(body->collision_groups, l, grp)
+ {
+ if (grp == group_str)
+ {
+ eina_stringshare_del(group_str);
+ return EINA_TRUE;
+ }
+ }
+
+ body->collision_groups = eina_list_append(body->collision_groups, group_str);
+ return EINA_TRUE;
+}
+
+EAPI Eina_Bool
+ephysics_body_collision_group_del(EPhysics_Body *body, const char *group)
+{
+ Eina_Stringshare *group_str;
+
+ if (!body)
+ {
+ ERR("Can't remove body collision group, body is null.");
+ return EINA_FALSE;
+ }
+
+ group_str = eina_stringshare_add(group);
+ body->collision_groups = eina_list_remove(body->collision_groups, group_str);
+ eina_stringshare_del(group_str);
+ eina_stringshare_del(group_str);
+ return EINA_TRUE;
+}
+
+EAPI const Eina_List *
+ephysics_body_collision_group_list_get(const EPhysics_Body *body)
+{
+ if (!body)
+ {
+ ERR("Can't get the body's collision group, body is null.");
+ return NULL;
+ }
+
+ return body->collision_groups;
}
static EPhysics_Body *
return NULL;
}
+ body->collision_groups = NULL;
body->collision_shape = collision_shape;
body->rigid_body = rigid_body;
body->mass = mass;
_ephysics_body_del(EPhysics_Body *body)
{
EPhysics_Body_Callback *cb;
+ void *group;
if (body->evas_obj)
evas_object_event_callback_del(body->evas_obj, EVAS_CALLBACK_DEL,
free(cb);
}
+ EINA_LIST_FREE(body->collision_groups, group)
+ eina_stringshare_del((Eina_Stringshare *)group);
+
delete body->rigid_body->getMotionState();
delete body->collision_shape;
delete body->rigid_body;
EPhysics_Body *ephysics_world_boundary_get(const EPhysics_World *world, EPhysics_World_Boundary boundary);
Eina_Bool ephysics_world_bodies_outside_autodel_get(const EPhysics_World *world);
+Eina_Bool ephysics_body_filter_collision(EPhysics_Body *body0, EPhysics_Body *body1);
+
void ephysics_body_evas_object_update_select(EPhysics_Body *body);
void ephysics_orphan_body_del(EPhysics_Body *body);
void ephysics_body_contact_processed(EPhysics_Body *body, EPhysics_Body *contact_body, btVector3 position);
static Eina_List *_worlds = NULL;
static Ecore_Animator *_anim_simulate = NULL;
+struct _ephysics_world_ovelap_filter_cb : public btOverlapFilterCallback
+{
+ virtual bool needBroadphaseCollision(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) const
+ {
+ btCollisionObject *coll0 = (btCollisionObject *)proxy0->m_clientObject;
+ btCollisionObject *coll1 = (btCollisionObject *)proxy1->m_clientObject;
+
+ EPhysics_Body *body0 = (EPhysics_Body *)coll0->getUserPointer();
+ EPhysics_Body *body1 = (EPhysics_Body *)coll1->getUserPointer();
+
+ if ((!body0 || !body1) || (ephysics_body_filter_collision(body0, body1)))
+ return EINA_TRUE;
+
+ return EINA_FALSE;
+ }
+};
+
static void
_ephysics_world_tick_cb(btDynamicsWorld *dynamics_world, btScalar timeStep)
{
ephysics_world_new(void)
{
EPhysics_World *world;
+ btOverlapFilterCallback *filter_cb;
world = (EPhysics_World *) calloc(1, sizeof(EPhysics_World));
if (!world)
world->dynamics_world->getSolverInfo().m_solverMode ^=
EPHYSICS_WORLD_SOLVER_SIMD;
world->dynamics_world->setGravity(btVector3(0, -9.8, 0));
+
+ filter_cb = new _ephysics_world_ovelap_filter_cb();
+ if (!filter_cb)
+ INF("Couldn't initialize the collision filter.");
+ else
+ world->dynamics_world->getPairCache()->setOverlapFilterCallback(filter_cb);
+
world->rate = 30;
world->dynamics_world->setInternalTickCallback(_ephysics_world_tick_cb,
(void *) world);