2012-06-26 15:36:12 -07:00
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
# include <config.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <Evas.h>
|
|
|
|
|
|
|
|
#include "ephysics_private.h"
|
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
extern "C" {
|
|
|
|
#endif
|
|
|
|
|
|
|
|
typedef struct _EPhysics_Body_Callback EPhysics_Body_Callback;
|
|
|
|
|
|
|
|
struct _EPhysics_Body_Callback {
|
|
|
|
EINA_INLIST;
|
|
|
|
void (*func) (void *data, EPhysics_Body *body, void *event_info);
|
|
|
|
void *data;
|
2012-07-02 19:09:34 -07:00
|
|
|
EPhysics_Callback_Body_Type type;
|
2012-08-10 14:04:08 -07:00
|
|
|
Eina_Bool deleted:1;
|
2012-06-26 15:36:12 -07:00
|
|
|
};
|
|
|
|
|
2012-07-27 07:49:37 -07:00
|
|
|
struct _EPhysics_Body_Collision {
|
|
|
|
EPhysics_Body *contact_body;
|
|
|
|
Evas_Coord x;
|
|
|
|
Evas_Coord y;
|
|
|
|
};
|
|
|
|
|
2012-08-20 15:15:52 -07:00
|
|
|
static void
|
|
|
|
_ephysics_body_forces_update(EPhysics_Body *body)
|
|
|
|
{
|
|
|
|
body->force.x = body->rigid_body->getTotalForce().getX();
|
|
|
|
body->force.y = body->rigid_body->getTotalForce().getY();
|
|
|
|
body->force.torque = body->rigid_body->getTotalTorque().getZ();
|
|
|
|
body->rigid_body->clearForces();
|
|
|
|
}
|
|
|
|
|
2012-08-16 14:35:04 -07:00
|
|
|
static inline void
|
|
|
|
_ephysics_body_sleeping_threshold_set(EPhysics_Body *body, double linear_threshold, double angular_threshold, double rate)
|
|
|
|
{
|
|
|
|
body->rigid_body->setSleepingThresholds(linear_threshold / rate,
|
|
|
|
angular_threshold / RAD_TO_DEG);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
_ephysics_body_linear_velocity_set(EPhysics_Body *body, double x, double y, double rate)
|
|
|
|
{
|
2012-08-16 14:35:31 -07:00
|
|
|
body->rigid_body->setLinearVelocity(btVector3(x / rate, -y / rate, 0));
|
2012-08-16 14:35:04 -07:00
|
|
|
}
|
|
|
|
|
2012-08-10 14:04:08 -07:00
|
|
|
static void
|
|
|
|
_ephysics_body_event_callback_del(EPhysics_Body *body, EPhysics_Body_Callback *cb)
|
|
|
|
{
|
|
|
|
if (cb->deleted) return;
|
|
|
|
|
|
|
|
cb->deleted = EINA_TRUE;
|
|
|
|
|
|
|
|
if (body->walking)
|
|
|
|
{
|
|
|
|
body->to_delete = eina_list_append(body->to_delete, cb);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
body->callbacks = eina_inlist_remove(body->callbacks, EINA_INLIST_GET(cb));
|
|
|
|
free(cb);
|
|
|
|
}
|
|
|
|
|
|
|
|
static Eina_Bool
|
|
|
|
_ephysics_body_event_callback_call(EPhysics_Body *body, EPhysics_Callback_Body_Type type, void *event_info)
|
|
|
|
{
|
|
|
|
Eina_Bool called = EINA_FALSE;
|
|
|
|
EPhysics_Body_Callback *cb;
|
|
|
|
void *clb;
|
|
|
|
|
|
|
|
body->walking++;
|
|
|
|
EINA_INLIST_FOREACH(body->callbacks, cb)
|
|
|
|
{
|
|
|
|
if ((cb->type == type) && (!cb->deleted))
|
|
|
|
{
|
|
|
|
cb->func(cb->data, body, event_info);
|
|
|
|
called = EINA_TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
body->walking--;
|
|
|
|
|
|
|
|
if (body->walking > 0) return called;
|
|
|
|
|
|
|
|
EINA_LIST_FREE(body->to_delete, clb)
|
|
|
|
{
|
|
|
|
cb = (EPhysics_Body_Callback *) clb;
|
|
|
|
body->callbacks = eina_inlist_remove(body->callbacks,
|
|
|
|
EINA_INLIST_GET(cb));
|
|
|
|
free(cb);
|
|
|
|
}
|
|
|
|
|
|
|
|
return called;
|
|
|
|
}
|
|
|
|
|
2012-06-26 15:36:12 -07:00
|
|
|
void
|
|
|
|
ephysics_body_active_set(EPhysics_Body *body, Eina_Bool active)
|
|
|
|
{
|
|
|
|
EPhysics_Body_Callback *cb;
|
|
|
|
|
|
|
|
if (body->active == !!active) return;
|
|
|
|
body->active = !!active;
|
|
|
|
if (active) return;
|
|
|
|
|
2012-08-10 14:04:08 -07:00
|
|
|
_ephysics_body_event_callback_call(body, EPHYSICS_CALLBACK_BODY_STOPPED,
|
|
|
|
(void *) body->evas_obj);
|
2012-07-27 07:49:53 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
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_Stringshare *group_str;
|
|
|
|
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't add body collision group, body is null.");
|
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
group_str = eina_stringshare_add(group);
|
2012-07-27 07:50:25 -07:00
|
|
|
if (eina_list_data_find(body->collision_groups, group_str))
|
2012-07-27 07:49:53 -07:00
|
|
|
{
|
2012-07-27 07:50:25 -07:00
|
|
|
INF("Body already added to group: %s", group);
|
|
|
|
eina_stringshare_del(group_str);
|
|
|
|
return EINA_TRUE;
|
2012-07-27 07:49:53 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
2012-07-27 07:50:25 -07:00
|
|
|
if (!eina_list_data_find(body->collision_groups, group_str))
|
|
|
|
{
|
|
|
|
INF("Body isn't part of group: %s", group);
|
|
|
|
eina_stringshare_del(group_str);
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
2012-07-27 07:49:53 -07:00
|
|
|
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;
|
2012-06-26 15:36:12 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static EPhysics_Body *
|
2012-08-10 14:05:05 -07:00
|
|
|
_ephysics_body_add(EPhysics_World *world, btCollisionShape *collision_shape, const char *type)
|
2012-06-26 15:36:12 -07:00
|
|
|
{
|
2012-08-10 14:05:05 -07:00
|
|
|
btRigidBody::btRigidBodyConstructionInfo *rigid_body_ci;
|
|
|
|
btDefaultMotionState *motion_state;
|
|
|
|
btRigidBody *rigid_body;
|
2012-06-26 15:36:12 -07:00
|
|
|
EPhysics_Body *body;
|
|
|
|
btScalar mass = 1;
|
2012-08-10 14:05:05 -07:00
|
|
|
btVector3 inertia;
|
|
|
|
|
|
|
|
if (!collision_shape)
|
|
|
|
{
|
|
|
|
ERR("Couldn't create a %s shape.", type);
|
|
|
|
return NULL;
|
|
|
|
}
|
2012-06-26 15:36:12 -07:00
|
|
|
|
|
|
|
body = (EPhysics_Body *) calloc(1, sizeof(EPhysics_Body));
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Couldn't create a new body instance.");
|
2012-08-10 14:05:05 -07:00
|
|
|
goto err_body;
|
2012-06-26 15:36:12 -07:00
|
|
|
}
|
|
|
|
|
2012-08-10 14:05:05 -07:00
|
|
|
motion_state = new btDefaultMotionState();
|
2012-06-26 15:36:12 -07:00
|
|
|
if (!motion_state)
|
|
|
|
{
|
|
|
|
ERR("Couldn't create a motion state.");
|
2012-08-10 14:05:05 -07:00
|
|
|
goto err_motion_state;
|
2012-06-26 15:36:12 -07:00
|
|
|
}
|
|
|
|
|
2012-08-10 14:05:05 -07:00
|
|
|
inertia = btVector3(0, 0, 0);
|
2012-06-26 15:36:12 -07:00
|
|
|
collision_shape->calculateLocalInertia(mass, inertia);
|
|
|
|
|
2012-08-10 14:05:05 -07:00
|
|
|
rigid_body_ci = new btRigidBody::btRigidBodyConstructionInfo(
|
2012-06-26 15:36:12 -07:00
|
|
|
mass, motion_state, collision_shape, inertia);
|
2012-08-10 14:05:05 -07:00
|
|
|
if (!rigid_body_ci)
|
|
|
|
{
|
|
|
|
ERR("Couldn't create a rigid body construction info.");
|
|
|
|
goto err_rigid_body_ci;
|
|
|
|
}
|
|
|
|
|
|
|
|
rigid_body = new btRigidBody(*rigid_body_ci);
|
2012-06-26 15:36:12 -07:00
|
|
|
if (!rigid_body)
|
|
|
|
{
|
|
|
|
ERR("Couldn't create a rigid body.");
|
2012-08-10 14:05:05 -07:00
|
|
|
goto err_rigid_body;
|
2012-06-26 15:36:12 -07:00
|
|
|
}
|
|
|
|
|
2012-07-27 07:49:53 -07:00
|
|
|
body->collision_groups = NULL;
|
2012-06-26 15:36:12 -07:00
|
|
|
body->collision_shape = collision_shape;
|
|
|
|
body->rigid_body = rigid_body;
|
2012-07-27 07:47:23 -07:00
|
|
|
body->mass = mass;
|
2012-06-26 15:36:12 -07:00
|
|
|
body->world = world;
|
|
|
|
body->rigid_body->setUserPointer(body);
|
|
|
|
body->rigid_body->setLinearFactor(btVector3(1, 1, 0));
|
|
|
|
body->rigid_body->setAngularFactor(btVector3(0, 0, 1));
|
|
|
|
|
2012-08-10 14:05:05 -07:00
|
|
|
if (!ephysics_world_body_add(body->world, body))
|
|
|
|
{
|
|
|
|
ERR("Couldn't add body to world's bodies list");
|
|
|
|
goto err_world_add;
|
|
|
|
}
|
|
|
|
|
|
|
|
delete rigid_body_ci;
|
|
|
|
|
|
|
|
INF("Body %p of type %s added.", body, type);
|
2012-06-26 15:36:12 -07:00
|
|
|
return body;
|
2012-08-10 14:05:05 -07:00
|
|
|
|
|
|
|
err_world_add:
|
|
|
|
delete rigid_body;
|
|
|
|
err_rigid_body:
|
|
|
|
delete rigid_body_ci;
|
|
|
|
err_rigid_body_ci:
|
|
|
|
delete motion_state;
|
|
|
|
err_motion_state:
|
|
|
|
free(body);
|
|
|
|
err_body:
|
|
|
|
delete collision_shape;
|
|
|
|
return NULL;
|
2012-06-26 15:36:12 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_ephysics_body_evas_obj_del_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
|
|
|
|
{
|
|
|
|
EPhysics_Body *body = (EPhysics_Body *) data;
|
|
|
|
body->evas_obj = NULL;
|
|
|
|
DBG("Evas object deleted. Updating body: %p", body);
|
|
|
|
}
|
|
|
|
|
2012-08-20 15:10:52 -07:00
|
|
|
static void
|
|
|
|
_ephysics_body_resize(EPhysics_Body *body, Evas_Coord w, Evas_Coord h)
|
|
|
|
{
|
|
|
|
double rate, sx, sy;
|
|
|
|
|
|
|
|
rate = ephysics_world_rate_get(body->world);
|
|
|
|
sx = w / rate;
|
|
|
|
sy = h / rate;
|
|
|
|
|
|
|
|
body->collision_shape->setLocalScaling(btVector3(sx, sy, 1));
|
|
|
|
|
|
|
|
if(!body->rigid_body->isStaticObject())
|
|
|
|
ephysics_body_mass_set(body, ephysics_body_mass_get(body));
|
|
|
|
|
|
|
|
body->w = w;
|
|
|
|
body->h = h;
|
|
|
|
|
|
|
|
body->rigid_body->activate(1);
|
|
|
|
|
|
|
|
DBG("Body %p scale changed to %lf, %lf.", body, sx, sy);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_ephysics_body_move(EPhysics_Body *body, Evas_Coord x, Evas_Coord y)
|
|
|
|
{
|
|
|
|
double rate, mx, my;
|
|
|
|
btTransform trans;
|
|
|
|
int wy, height;
|
|
|
|
|
|
|
|
rate = ephysics_world_rate_get(body->world);
|
|
|
|
ephysics_world_render_geometry_get(body->world, NULL, &wy, NULL, &height);
|
|
|
|
height += wy;
|
|
|
|
|
|
|
|
mx = (x + body->w / 2) / rate;
|
|
|
|
my = (height - (y + body->h / 2)) / rate;
|
|
|
|
|
|
|
|
body->rigid_body->getMotionState()->getWorldTransform(trans);
|
|
|
|
trans.setOrigin(btVector3(mx, my, 0));
|
|
|
|
body->rigid_body->proceedToTransform(trans);
|
|
|
|
body->rigid_body->getMotionState()->setWorldTransform(trans);
|
|
|
|
|
|
|
|
body->rigid_body->activate(1);
|
|
|
|
|
|
|
|
DBG("Body %p position changed to %lf, %lf.", body, mx, my);
|
|
|
|
}
|
|
|
|
|
2012-06-26 15:36:12 -07:00
|
|
|
static void
|
2012-08-16 14:35:04 -07:00
|
|
|
_ephysics_body_geometry_set(EPhysics_Body *body, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h, double rate)
|
2012-06-26 15:36:12 -07:00
|
|
|
{
|
2012-08-16 14:35:04 -07:00
|
|
|
double mx, my, sx, sy;
|
2012-06-26 15:36:12 -07:00
|
|
|
btTransform trans;
|
|
|
|
int wy, height;
|
|
|
|
|
|
|
|
ephysics_world_render_geometry_get(body->world, NULL, &wy, NULL, &height);
|
|
|
|
height += wy;
|
|
|
|
|
|
|
|
mx = (x + w / 2) / rate;
|
|
|
|
my = (height - (y + h / 2)) / rate;
|
|
|
|
sx = w / rate;
|
|
|
|
sy = h / rate;
|
|
|
|
|
|
|
|
body->rigid_body->getMotionState()->getWorldTransform(trans);
|
|
|
|
trans.setOrigin(btVector3(mx, my, 0));
|
|
|
|
body->rigid_body->proceedToTransform(trans);
|
|
|
|
|
|
|
|
body->collision_shape->setLocalScaling(btVector3(sx, sy, 1));
|
|
|
|
|
|
|
|
if(!body->rigid_body->isStaticObject())
|
|
|
|
ephysics_body_mass_set(body, ephysics_body_mass_get(body));
|
|
|
|
|
|
|
|
body->rigid_body->getMotionState()->setWorldTransform(trans);
|
|
|
|
|
2012-08-13 15:24:47 -07:00
|
|
|
body->w = w;
|
|
|
|
body->h = h;
|
|
|
|
|
2012-08-16 14:35:04 -07:00
|
|
|
body->rigid_body->activate(1);
|
|
|
|
|
2012-07-03 16:21:11 -07:00
|
|
|
DBG("Body %p position changed to %lf, %lf.", body, mx, my);
|
|
|
|
DBG("Body %p scale changed to %lf, %lf.", body, sx, sy);
|
2012-06-26 15:36:12 -07:00
|
|
|
}
|
|
|
|
|
2012-08-13 15:24:47 -07:00
|
|
|
static void
|
|
|
|
_ephysics_body_evas_obj_resize_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
|
|
|
|
{
|
|
|
|
EPhysics_Body *body = (EPhysics_Body *) data;
|
2012-08-20 15:10:52 -07:00
|
|
|
int w, h;
|
2012-08-13 15:24:47 -07:00
|
|
|
|
|
|
|
evas_object_geometry_get(obj, NULL, NULL, &w, &h);
|
|
|
|
if ((w == body->w) && (h == body->h))
|
|
|
|
return;
|
|
|
|
|
|
|
|
DBG("Resizing body %p to w=%i, h=%i", body, w, h);
|
2012-08-20 15:10:52 -07:00
|
|
|
_ephysics_body_resize(body, w, h);
|
2012-08-13 15:24:47 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_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,
|
|
|
|
_ephysics_body_evas_obj_del_cb);
|
|
|
|
evas_object_event_callback_del(body->evas_obj, EVAS_CALLBACK_RESIZE,
|
|
|
|
_ephysics_body_evas_obj_resize_cb);
|
|
|
|
}
|
|
|
|
|
|
|
|
while (body->callbacks)
|
|
|
|
{
|
|
|
|
cb = EINA_INLIST_CONTAINER_GET(body->callbacks,
|
|
|
|
EPhysics_Body_Callback);
|
|
|
|
body->callbacks = eina_inlist_remove(body->callbacks, body->callbacks);
|
|
|
|
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;
|
|
|
|
|
|
|
|
free(body);
|
|
|
|
}
|
|
|
|
|
2012-06-26 15:36:12 -07:00
|
|
|
static void
|
|
|
|
_ephysics_body_evas_object_default_update(EPhysics_Body *body)
|
|
|
|
{
|
2012-07-27 07:50:03 -07:00
|
|
|
int x, y, w, h, wx, wy, wh, cx, cy;
|
|
|
|
EPhysics_Camera *camera;
|
2012-06-26 15:36:12 -07:00
|
|
|
btTransform trans;
|
|
|
|
double rate, rot;
|
|
|
|
Evas_Map *map;
|
|
|
|
|
|
|
|
if (!body->evas_obj)
|
|
|
|
return;
|
|
|
|
|
|
|
|
body->rigid_body->getMotionState()->getWorldTransform(trans);
|
2012-07-27 07:50:03 -07:00
|
|
|
ephysics_world_render_geometry_get(body->world, &wx, &wy, NULL, &wh);
|
|
|
|
|
|
|
|
camera = ephysics_world_camera_get(body->world);
|
|
|
|
ephysics_camera_position_get(camera, &cx, &cy);
|
|
|
|
cx -= wx;
|
|
|
|
cy -= wy;
|
2012-06-26 15:36:12 -07:00
|
|
|
|
|
|
|
evas_object_geometry_get(body->evas_obj, NULL, NULL, &w, &h);
|
|
|
|
rate = ephysics_world_rate_get(body->world);
|
2012-07-27 07:50:03 -07:00
|
|
|
x = (int) (trans.getOrigin().getX() * rate) - w / 2 - cx;
|
|
|
|
y = wh + wy - (int) (trans.getOrigin().getY() * rate) - h / 2 - cy;
|
2012-06-26 15:36:12 -07:00
|
|
|
|
|
|
|
evas_object_move(body->evas_obj, x, y);
|
|
|
|
|
2012-08-13 15:24:36 -07:00
|
|
|
if ((!w) || (!h))
|
|
|
|
{
|
|
|
|
DBG("Evas object with no geometry: %p, w=%i h=%i", body->evas_obj,
|
|
|
|
w, h);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-06-26 15:36:12 -07:00
|
|
|
rot = - trans.getRotation().getAngle() * RAD_TO_DEG *
|
|
|
|
trans.getRotation().getAxis().getZ();
|
|
|
|
|
|
|
|
map = evas_map_new(4);
|
|
|
|
evas_map_util_points_populate_from_object(map, body->evas_obj);
|
|
|
|
evas_map_util_rotate(map, rot, x + (w / 2), y + (h / 2));
|
|
|
|
evas_object_map_set(body->evas_obj, map);
|
|
|
|
evas_object_map_enable_set(body->evas_obj, EINA_TRUE);
|
|
|
|
evas_map_free(map);
|
|
|
|
}
|
|
|
|
|
2012-07-03 16:20:49 -07:00
|
|
|
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)))
|
|
|
|
{
|
2012-08-10 14:03:39 -07:00
|
|
|
DBG("Body %p out of render area", body);
|
|
|
|
ephysics_body_del(body);
|
2012-07-03 16:20:49 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-08-20 15:15:52 -07:00
|
|
|
void
|
|
|
|
ephysics_body_forces_apply(EPhysics_Body *body)
|
|
|
|
{
|
|
|
|
double rate = ephysics_world_rate_get(body->world);
|
|
|
|
body->rigid_body->activate(1);
|
|
|
|
body->rigid_body->applyCentralForce(btVector3(body->force.x / rate,
|
|
|
|
body->force.y / rate, 0));
|
|
|
|
body->rigid_body->applyTorque(btVector3(0, 0, body->force.torque));
|
|
|
|
}
|
|
|
|
|
2012-08-16 14:35:04 -07:00
|
|
|
void
|
|
|
|
ephysics_body_recalc(EPhysics_Body *body, double rate)
|
|
|
|
{
|
|
|
|
Evas_Coord x, y, w, h;
|
|
|
|
double vx, vy, lt, at;
|
|
|
|
|
|
|
|
ephysics_body_geometry_get(body, &x, &y, &w, &h);
|
|
|
|
ephysics_body_linear_velocity_get(body, &vx, &vy);
|
|
|
|
ephysics_body_sleeping_threshold_get(body, <, &at);
|
|
|
|
|
|
|
|
_ephysics_body_geometry_set(body, x, y, w, h, rate);
|
|
|
|
_ephysics_body_linear_velocity_set(body, vx, vy, rate);
|
|
|
|
_ephysics_body_sleeping_threshold_set(body, lt, at, rate);
|
|
|
|
}
|
|
|
|
|
2012-06-26 15:36:12 -07:00
|
|
|
void
|
|
|
|
ephysics_body_evas_object_update_select(EPhysics_Body *body)
|
|
|
|
{
|
|
|
|
Eina_Bool callback_called = EINA_FALSE;
|
|
|
|
|
|
|
|
if (!body)
|
|
|
|
return;
|
|
|
|
|
2012-08-10 14:04:08 -07:00
|
|
|
callback_called = _ephysics_body_event_callback_call(
|
|
|
|
body, EPHYSICS_CALLBACK_BODY_UPDATE, (void *) body->evas_obj);
|
2012-06-26 15:36:12 -07:00
|
|
|
|
|
|
|
if (!callback_called)
|
|
|
|
_ephysics_body_evas_object_default_update(body);
|
2012-07-03 16:20:49 -07:00
|
|
|
|
|
|
|
if (ephysics_world_bodies_outside_autodel_get(body->world))
|
|
|
|
_ephysics_body_outside_render_area_check(body);
|
2012-06-26 15:36:12 -07:00
|
|
|
}
|
|
|
|
|
2012-07-27 07:49:37 -07:00
|
|
|
EAPI void
|
|
|
|
ephysics_body_collision_position_get(const EPhysics_Body_Collision *collision, Evas_Coord *x, Evas_Coord *y)
|
|
|
|
{
|
|
|
|
if (!collision)
|
|
|
|
{
|
|
|
|
ERR("Can't get body's collision data, collision is null.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (x) *x = collision->x;
|
|
|
|
if (y) *y = collision->y;
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI EPhysics_Body *
|
|
|
|
ephysics_body_collision_contact_body_get(const EPhysics_Body_Collision *collision)
|
|
|
|
{
|
|
|
|
if (!collision)
|
|
|
|
{
|
|
|
|
ERR("Can't get body's collision contact body, collision is null.");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return collision->contact_body;
|
|
|
|
}
|
|
|
|
|
2012-06-26 15:36:12 -07:00
|
|
|
void
|
2012-07-27 07:49:37 -07:00
|
|
|
ephysics_body_contact_processed(EPhysics_Body *body, EPhysics_Body *contact_body, btVector3 position)
|
2012-06-26 15:36:12 -07:00
|
|
|
{
|
2012-08-10 14:04:08 -07:00
|
|
|
EPhysics_Body_Collision *collision;
|
2012-06-26 15:36:12 -07:00
|
|
|
EPhysics_Body_Callback *cb;
|
2012-08-10 14:04:08 -07:00
|
|
|
EPhysics_World *world;;
|
|
|
|
double rate;
|
|
|
|
int wy, wh;
|
2012-06-26 15:36:12 -07:00
|
|
|
|
|
|
|
if ((!body) || (!contact_body))
|
|
|
|
return;
|
|
|
|
|
2012-08-10 14:04:42 -07:00
|
|
|
collision = (EPhysics_Body_Collision *)calloc(
|
|
|
|
1, sizeof(EPhysics_Body_Collision));
|
2012-08-10 14:04:08 -07:00
|
|
|
|
|
|
|
if (!collision)
|
2012-06-26 15:36:12 -07:00
|
|
|
{
|
2012-08-10 14:04:08 -07:00
|
|
|
ERR("Can't allocate collision data structure.");
|
|
|
|
return;
|
|
|
|
}
|
2012-07-27 07:50:25 -07:00
|
|
|
|
2012-08-10 14:04:08 -07:00
|
|
|
world = contact_body->world;
|
|
|
|
ephysics_world_render_geometry_get(world, NULL, &wy, NULL, &wh);
|
|
|
|
rate = ephysics_world_rate_get(world);
|
2012-07-27 07:50:25 -07:00
|
|
|
|
2012-08-10 14:04:08 -07:00
|
|
|
collision->contact_body = contact_body;
|
|
|
|
collision->x = position.getX() * rate;
|
|
|
|
collision->y = wh + wy - (position.getY() * rate);
|
2012-07-27 07:50:25 -07:00
|
|
|
|
2012-08-10 14:04:08 -07:00
|
|
|
_ephysics_body_event_callback_call(body, EPHYSICS_CALLBACK_BODY_COLLISION,
|
|
|
|
(void *) collision);
|
|
|
|
|
|
|
|
free(collision);
|
2012-06-26 15:36:12 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
btRigidBody *
|
2012-07-06 07:36:40 -07:00
|
|
|
ephysics_body_rigid_body_get(const EPhysics_Body *body)
|
2012-06-26 15:36:12 -07:00
|
|
|
{
|
|
|
|
return body->rigid_body;
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI EPhysics_Body *
|
|
|
|
ephysics_body_circle_add(EPhysics_World *world)
|
|
|
|
{
|
2012-08-10 14:05:05 -07:00
|
|
|
btCollisionShape *collision_shape;
|
2012-06-26 15:36:12 -07:00
|
|
|
|
2012-08-10 14:05:05 -07:00
|
|
|
if (!world)
|
2012-06-26 15:36:12 -07:00
|
|
|
{
|
2012-08-10 14:05:05 -07:00
|
|
|
ERR("Can't add circle, world is null.");
|
2012-06-26 15:36:12 -07:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2012-08-10 14:05:05 -07:00
|
|
|
collision_shape = new btCylinderShapeZ(btVector3(0.5, 0.5, 0.5));
|
2012-06-26 15:36:12 -07:00
|
|
|
|
2012-08-10 14:05:05 -07:00
|
|
|
return _ephysics_body_add(world, collision_shape, "circle");
|
2012-06-26 15:36:12 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
EAPI EPhysics_Body *
|
|
|
|
ephysics_body_box_add(EPhysics_World *world)
|
|
|
|
{
|
2012-08-10 14:05:05 -07:00
|
|
|
btCollisionShape *collision_shape;
|
2012-06-26 15:36:12 -07:00
|
|
|
|
2012-08-10 14:05:05 -07:00
|
|
|
if (!world)
|
2012-06-26 15:36:12 -07:00
|
|
|
{
|
2012-08-10 14:05:05 -07:00
|
|
|
ERR("Can't add box, world is null.");
|
2012-06-26 15:36:12 -07:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2012-08-10 14:05:05 -07:00
|
|
|
collision_shape = new btBoxShape(btVector3(0.5, 0.5, 0.5));
|
2012-06-26 15:36:12 -07:00
|
|
|
|
2012-08-10 14:05:05 -07:00
|
|
|
return _ephysics_body_add(world, collision_shape, "box");
|
2012-06-26 15:36:12 -07:00
|
|
|
}
|
|
|
|
|
2012-08-10 14:05:19 -07:00
|
|
|
EAPI EPhysics_Body *
|
|
|
|
ephysics_body_shape_add(EPhysics_World *world, EPhysics_Shape *shape)
|
|
|
|
{
|
|
|
|
btConvexHullShape* collision_shape;
|
|
|
|
const Eina_Inlist *points;
|
|
|
|
EPhysics_Point *point;
|
|
|
|
btVector3 point3d;
|
|
|
|
|
|
|
|
if (!world)
|
|
|
|
{
|
|
|
|
ERR("Can't add shape, world is null.");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!shape)
|
|
|
|
{
|
|
|
|
ERR("Can't add shape, shape is null.");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
collision_shape = new btConvexHullShape();
|
|
|
|
if (!collision_shape)
|
|
|
|
{
|
|
|
|
ERR("Couldn't create a generic convex shape.");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
points = ephysics_shape_points_get(shape);
|
|
|
|
|
|
|
|
EINA_INLIST_FOREACH(points, point)
|
|
|
|
{
|
|
|
|
point3d = btVector3(point->x, point->y, 0);
|
|
|
|
collision_shape->addPoint(point3d);
|
|
|
|
point3d = btVector3(point->x, point->y, 0.5);
|
|
|
|
collision_shape->addPoint(point3d);
|
|
|
|
}
|
|
|
|
|
|
|
|
return _ephysics_body_add(world, (btCollisionShape *)collision_shape,
|
|
|
|
"generic");
|
|
|
|
}
|
|
|
|
|
2012-06-26 15:36:12 -07:00
|
|
|
void
|
|
|
|
ephysics_body_world_boundaries_resize(EPhysics_World *world)
|
|
|
|
{
|
|
|
|
Evas_Coord x, y, width, height;
|
|
|
|
EPhysics_Body *bottom, *top, *left, *right;
|
|
|
|
|
|
|
|
ephysics_world_render_geometry_get(world, &x, &y, &width, &height);
|
|
|
|
|
|
|
|
bottom = ephysics_world_boundary_get(world, EPHYSICS_WORLD_BOUNDARY_BOTTOM);
|
|
|
|
if (bottom)
|
|
|
|
ephysics_body_geometry_set(bottom, x, y + height, width, 10);
|
|
|
|
|
|
|
|
right = ephysics_world_boundary_get(world, EPHYSICS_WORLD_BOUNDARY_RIGHT);
|
|
|
|
if (right)
|
|
|
|
ephysics_body_geometry_set(right, x + width, 0, 10, y + height);
|
|
|
|
|
|
|
|
left = ephysics_world_boundary_get(world, EPHYSICS_WORLD_BOUNDARY_LEFT);
|
|
|
|
if (left)
|
|
|
|
ephysics_body_geometry_set(left, x - 10, 0, 10, y + height);
|
|
|
|
|
|
|
|
top = ephysics_world_boundary_get(world, EPHYSICS_WORLD_BOUNDARY_TOP);
|
|
|
|
if (top)
|
|
|
|
ephysics_body_geometry_set(top, 0, y - 10, x + width, 10);
|
|
|
|
}
|
|
|
|
|
|
|
|
static EPhysics_Body *
|
|
|
|
_ephysics_body_boundary_add(EPhysics_World *world, EPhysics_World_Boundary boundary, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h)
|
|
|
|
{
|
|
|
|
EPhysics_Body *body;
|
|
|
|
|
|
|
|
if (!world)
|
|
|
|
{
|
|
|
|
ERR("Can't add boundary, world is null.");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
body = ephysics_world_boundary_get(world, boundary);
|
|
|
|
if (body)
|
|
|
|
return body;
|
|
|
|
|
|
|
|
body = ephysics_body_box_add(world);
|
|
|
|
if (!body)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
ephysics_body_mass_set(body, 0);
|
|
|
|
ephysics_world_boundary_set(world, boundary, body);
|
|
|
|
ephysics_body_geometry_set(body, x, y, w, h);
|
|
|
|
|
|
|
|
return body;
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI EPhysics_Body *
|
|
|
|
ephysics_body_top_boundary_add(EPhysics_World *world)
|
|
|
|
{
|
|
|
|
Evas_Coord x, y, w;
|
|
|
|
ephysics_world_render_geometry_get(world, &x, &y, &w, NULL);
|
|
|
|
return _ephysics_body_boundary_add(world, EPHYSICS_WORLD_BOUNDARY_TOP,
|
|
|
|
0, y - 10, x + w, 10);
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI EPhysics_Body *
|
|
|
|
ephysics_body_bottom_boundary_add(EPhysics_World *world)
|
|
|
|
{
|
|
|
|
Evas_Coord x, y, w, h;
|
|
|
|
ephysics_world_render_geometry_get(world, &x, &y, &w, &h);
|
|
|
|
return _ephysics_body_boundary_add(world, EPHYSICS_WORLD_BOUNDARY_BOTTOM,
|
|
|
|
x, y + h, w, 10);
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI EPhysics_Body *
|
|
|
|
ephysics_body_left_boundary_add(EPhysics_World *world)
|
|
|
|
{
|
|
|
|
Evas_Coord x, y, h;
|
|
|
|
ephysics_world_render_geometry_get(world, &x, &y, NULL, &h);
|
|
|
|
return _ephysics_body_boundary_add(world, EPHYSICS_WORLD_BOUNDARY_LEFT,
|
|
|
|
x - 10, 0, 10, y + h);
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI EPhysics_Body *
|
|
|
|
ephysics_body_right_boundary_add(EPhysics_World *world)
|
|
|
|
{
|
|
|
|
Evas_Coord x, y, w, h;
|
|
|
|
ephysics_world_render_geometry_get(world, &x, &y, &w, &h);
|
|
|
|
return _ephysics_body_boundary_add(world, EPHYSICS_WORLD_BOUNDARY_RIGHT,
|
|
|
|
x + w, 0, 10, y + h);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
ephysics_orphan_body_del(EPhysics_Body *body)
|
|
|
|
{
|
|
|
|
EPhysics_Body_Callback *cb;
|
|
|
|
|
2012-08-10 14:04:08 -07:00
|
|
|
_ephysics_body_event_callback_call(body, EPHYSICS_CALLBACK_BODY_DEL, NULL);
|
2012-06-26 15:36:12 -07:00
|
|
|
_ephysics_body_del(body);
|
2012-08-10 14:03:39 -07:00
|
|
|
INF("Body %p deleted.", body);
|
2012-06-26 15:36:12 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
EAPI void
|
|
|
|
ephysics_body_del(EPhysics_Body *body)
|
|
|
|
{
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't delete body, it wasn't provided.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-08-10 14:03:39 -07:00
|
|
|
if (body->deleted) return;
|
|
|
|
body->deleted = EINA_TRUE;
|
|
|
|
ephysics_world_body_del(body->world, body);
|
2012-06-26 15:36:12 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
EAPI void
|
|
|
|
ephysics_body_evas_object_set(EPhysics_Body *body, Evas_Object *evas_obj, Eina_Bool use_obj_pos)
|
|
|
|
{
|
|
|
|
int obj_x, obj_y, obj_w, obj_h;
|
|
|
|
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't set evas object to body, the last wasn't provided.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!evas_obj)
|
|
|
|
{
|
|
|
|
ERR("Can't set evas object to body, the first wasn't provided.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (body->evas_obj)
|
2012-08-13 15:24:47 -07:00
|
|
|
{
|
|
|
|
evas_object_event_callback_del(body->evas_obj, EVAS_CALLBACK_DEL,
|
|
|
|
_ephysics_body_evas_obj_del_cb);
|
|
|
|
evas_object_event_callback_del(body->evas_obj, EVAS_CALLBACK_RESIZE,
|
|
|
|
_ephysics_body_evas_obj_resize_cb);
|
|
|
|
}
|
2012-06-26 15:36:12 -07:00
|
|
|
|
|
|
|
body->evas_obj = evas_obj;
|
|
|
|
evas_object_event_callback_add(evas_obj, EVAS_CALLBACK_DEL,
|
|
|
|
_ephysics_body_evas_obj_del_cb, body);
|
|
|
|
|
|
|
|
if (!use_obj_pos)
|
|
|
|
return;
|
|
|
|
|
2012-08-13 15:24:47 -07:00
|
|
|
evas_object_event_callback_add(evas_obj, EVAS_CALLBACK_RESIZE,
|
|
|
|
_ephysics_body_evas_obj_resize_cb, body);
|
2012-06-26 15:36:12 -07:00
|
|
|
evas_object_geometry_get(body->evas_obj, &obj_x, &obj_y, &obj_w, &obj_h);
|
2012-08-16 14:35:04 -07:00
|
|
|
_ephysics_body_geometry_set(body, obj_x, obj_y, obj_w, obj_h,
|
|
|
|
ephysics_world_rate_get(body->world));
|
2012-06-26 15:36:12 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
EAPI Evas_Object *
|
|
|
|
ephysics_body_evas_object_unset(EPhysics_Body *body)
|
|
|
|
{
|
|
|
|
Evas_Object *obj;
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't unset evas object from body, it wasn't provided.");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
obj = body->evas_obj;
|
|
|
|
body->evas_obj = NULL;
|
|
|
|
|
|
|
|
if (obj)
|
2012-08-13 15:24:47 -07:00
|
|
|
{
|
|
|
|
evas_object_event_callback_del(obj, EVAS_CALLBACK_DEL,
|
|
|
|
_ephysics_body_evas_obj_del_cb);
|
|
|
|
evas_object_event_callback_del(obj, EVAS_CALLBACK_RESIZE,
|
|
|
|
_ephysics_body_evas_obj_resize_cb);
|
|
|
|
}
|
2012-06-26 15:36:12 -07:00
|
|
|
|
|
|
|
return obj;
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI Evas_Object *
|
|
|
|
ephysics_body_evas_object_get(const EPhysics_Body *body)
|
|
|
|
{
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't get evas object from body, it wasn't provided.");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return body->evas_obj;
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI void
|
|
|
|
ephysics_body_geometry_set(EPhysics_Body *body, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h)
|
|
|
|
{
|
|
|
|
if (!body)
|
|
|
|
{
|
2012-08-20 15:10:52 -07:00
|
|
|
ERR("Can't set body geometry, body is null.");
|
2012-06-26 15:36:12 -07:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((w <= 0) || (h <= 0))
|
|
|
|
{
|
|
|
|
ERR("Width and height must to be a non-null, positive value.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-08-16 14:35:04 -07:00
|
|
|
_ephysics_body_geometry_set(body, x, y, w, h,
|
|
|
|
ephysics_world_rate_get(body->world));
|
2012-06-26 15:36:12 -07:00
|
|
|
}
|
|
|
|
|
2012-08-20 15:10:52 -07:00
|
|
|
EAPI void
|
|
|
|
ephysics_body_resize(EPhysics_Body *body, Evas_Coord w, Evas_Coord h)
|
|
|
|
{
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't set body size, body is null.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((w <= 0) || (h <= 0))
|
|
|
|
{
|
|
|
|
ERR("Width and height must to be a non-null, positive value.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
_ephysics_body_resize(body, w, h);
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI void
|
|
|
|
ephysics_body_move(EPhysics_Body *body, Evas_Coord x, Evas_Coord y)
|
|
|
|
{
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't set body position, body is null.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
_ephysics_body_move(body, x, y);
|
|
|
|
}
|
|
|
|
|
2012-06-26 15:36:12 -07:00
|
|
|
EAPI void
|
|
|
|
ephysics_body_geometry_get(const EPhysics_Body *body, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h)
|
|
|
|
{
|
|
|
|
btTransform trans;
|
|
|
|
btVector3 vector;
|
|
|
|
double rate;
|
|
|
|
int wy, height;
|
|
|
|
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't get body position, body is null.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
body->rigid_body->getMotionState()->getWorldTransform(trans);
|
|
|
|
vector = body->collision_shape->getLocalScaling();
|
|
|
|
|
|
|
|
rate = ephysics_world_rate_get(body->world);
|
|
|
|
ephysics_world_render_geometry_get(body->world, NULL, &wy, NULL, &height);
|
|
|
|
height += wy;
|
|
|
|
|
|
|
|
if (x) *x = round((trans.getOrigin().getX() - vector.x() / 2) * rate);
|
|
|
|
if (y) *y = height - round((trans.getOrigin().getY() + vector.y() / 2)
|
|
|
|
* rate);
|
2012-08-13 15:24:47 -07:00
|
|
|
if (w) *w = body->w;
|
|
|
|
if (h) *h = body->h;
|
2012-06-26 15:36:12 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
EAPI void
|
|
|
|
ephysics_body_mass_set(EPhysics_Body *body, double mass)
|
|
|
|
{
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't set body mass, body is null.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
btVector3 inertia(0, 0, 0);
|
|
|
|
body->collision_shape->calculateLocalInertia(mass, inertia);
|
|
|
|
body->rigid_body->setMassProps(mass, inertia);
|
|
|
|
body->rigid_body->updateInertiaTensor();
|
2012-07-27 07:47:23 -07:00
|
|
|
body->mass = mass;
|
2012-06-26 15:36:12 -07:00
|
|
|
|
2012-07-03 16:21:11 -07:00
|
|
|
DBG("Body %p mass changed to %lf.", body, mass);
|
2012-06-26 15:36:12 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
EAPI double
|
|
|
|
ephysics_body_mass_get(const EPhysics_Body *body)
|
|
|
|
{
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't get body mass, body is null.");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-07-27 07:47:23 -07:00
|
|
|
return body->mass;
|
2012-06-26 15:36:12 -07:00
|
|
|
}
|
|
|
|
|
2012-07-04 15:04:37 -07:00
|
|
|
EAPI void
|
|
|
|
ephysics_body_linear_velocity_set(EPhysics_Body *body, double x, double y)
|
|
|
|
{
|
|
|
|
double rate;
|
|
|
|
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't set body linear velocity, body is null.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-08-16 14:35:04 -07:00
|
|
|
_ephysics_body_linear_velocity_set(body, x, y,
|
|
|
|
ephysics_world_rate_get(body->world));
|
2012-07-04 15:04:37 -07:00
|
|
|
DBG("Linear velocity of body %p set to %lf, %lf", body, x, y);
|
|
|
|
}
|
|
|
|
|
2012-07-02 19:15:28 -07:00
|
|
|
EAPI void
|
|
|
|
ephysics_body_linear_velocity_get(const EPhysics_Body *body, double *x, double *y)
|
|
|
|
{
|
2012-07-02 19:18:14 -07:00
|
|
|
double rate;
|
2012-07-04 15:04:37 -07:00
|
|
|
|
2012-07-02 19:18:14 -07:00
|
|
|
if (!body)
|
2012-07-02 19:15:28 -07:00
|
|
|
{
|
2012-07-04 15:04:37 -07:00
|
|
|
ERR("Can't get linear velocity, body is null.");
|
2012-07-02 19:15:28 -07:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-07-02 19:18:14 -07:00
|
|
|
rate = ephysics_world_rate_get(body->world);
|
|
|
|
if (x) *x = body->rigid_body->getLinearVelocity().getX() * rate;
|
|
|
|
if (y) *y = -body->rigid_body->getLinearVelocity().getY() * rate;
|
2012-07-02 19:15:28 -07:00
|
|
|
}
|
|
|
|
|
2012-07-04 15:04:37 -07:00
|
|
|
EAPI void
|
|
|
|
ephysics_body_angular_velocity_set(EPhysics_Body *body, double z)
|
|
|
|
{
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't set angular velocity, body is null.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
body->rigid_body->setAngularVelocity(btVector3(0, 0, -z/RAD_TO_DEG));
|
|
|
|
DBG("Angular velocity of body %p set to %lf", body, z);
|
|
|
|
}
|
|
|
|
|
2012-07-02 19:18:14 -07:00
|
|
|
EAPI double
|
|
|
|
ephysics_body_angular_velocity_get(const EPhysics_Body *body)
|
2012-07-02 19:15:28 -07:00
|
|
|
{
|
2012-07-02 19:18:14 -07:00
|
|
|
if (!body)
|
2012-07-02 19:15:28 -07:00
|
|
|
{
|
2012-07-04 15:04:37 -07:00
|
|
|
ERR("Can't get angular velocity, body is null.");
|
2012-07-02 19:18:14 -07:00
|
|
|
return 0;
|
2012-07-02 19:15:28 -07:00
|
|
|
}
|
|
|
|
|
2012-07-02 19:18:14 -07:00
|
|
|
return -body->rigid_body->getAngularVelocity().getZ() * RAD_TO_DEG;
|
2012-07-02 19:15:28 -07:00
|
|
|
}
|
|
|
|
|
2012-07-27 07:48:59 -07:00
|
|
|
EAPI void
|
|
|
|
ephysics_body_sleeping_threshold_set(EPhysics_Body *body, double linear_threshold, double angular_threshold)
|
|
|
|
{
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't set sleeping thresholds, body is null.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-08-16 14:35:04 -07:00
|
|
|
_ephysics_body_sleeping_threshold_set(body, linear_threshold,
|
|
|
|
angular_threshold,
|
|
|
|
ephysics_world_rate_get(body->world));
|
2012-07-27 07:48:59 -07:00
|
|
|
}
|
|
|
|
|
2012-08-10 14:03:57 -07:00
|
|
|
EAPI void
|
|
|
|
ephysics_body_sleeping_threshold_get(const EPhysics_Body *body, double *linear_threshold, double *angular_threshold)
|
2012-07-27 07:48:59 -07:00
|
|
|
{
|
|
|
|
double rate;
|
|
|
|
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't get linear sleeping threshold, body is null.");
|
2012-08-10 14:03:57 -07:00
|
|
|
return;
|
2012-07-27 07:48:59 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
rate = ephysics_world_rate_get(body->world);
|
2012-08-10 14:03:57 -07:00
|
|
|
if (linear_threshold)
|
|
|
|
*linear_threshold = body->rigid_body->getLinearSleepingThreshold() * rate;
|
|
|
|
if (angular_threshold)
|
|
|
|
*angular_threshold = body->rigid_body->getAngularSleepingThreshold() *
|
|
|
|
RAD_TO_DEG;
|
2012-07-27 07:48:59 -07:00
|
|
|
}
|
|
|
|
|
2012-07-04 15:04:37 -07:00
|
|
|
EAPI void
|
|
|
|
ephysics_body_stop(EPhysics_Body *body)
|
|
|
|
{
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't stop a null body.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
body->rigid_body->setLinearVelocity(btVector3(0, 0, 0));
|
|
|
|
body->rigid_body->setAngularVelocity(btVector3(0, 0, 0));
|
|
|
|
|
|
|
|
DBG("Body %p stopped", body);
|
|
|
|
}
|
|
|
|
|
2012-07-05 15:52:53 -07:00
|
|
|
EAPI void
|
|
|
|
ephysics_body_damping_set(EPhysics_Body *body, double linear_damping, double angular_damping)
|
|
|
|
{
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't set body damping, body is null.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
body->rigid_body->setDamping(btScalar(linear_damping),
|
|
|
|
btScalar(angular_damping));
|
|
|
|
}
|
|
|
|
|
2012-07-05 15:53:56 -07:00
|
|
|
EAPI void
|
2012-07-06 07:36:40 -07:00
|
|
|
ephysics_body_damping_get(const EPhysics_Body *body, double *linear_damping, double *angular_damping)
|
2012-07-05 15:53:56 -07:00
|
|
|
{
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't get damping, body is null.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (linear_damping) *linear_damping = body->rigid_body->getLinearDamping();
|
|
|
|
if (angular_damping) *angular_damping =
|
|
|
|
body->rigid_body->getAngularDamping();
|
|
|
|
}
|
|
|
|
|
2012-06-26 15:36:12 -07:00
|
|
|
EAPI void
|
|
|
|
ephysics_body_evas_object_update(EPhysics_Body *body)
|
|
|
|
{
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Couldn't update a null body.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
_ephysics_body_evas_object_default_update(body);
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI void
|
2012-07-02 19:09:34 -07:00
|
|
|
ephysics_body_event_callback_add(EPhysics_Body *body, EPhysics_Callback_Body_Type type, EPhysics_Body_Event_Cb func, const void *data)
|
2012-06-26 15:36:12 -07:00
|
|
|
{
|
|
|
|
EPhysics_Body_Callback *cb;
|
|
|
|
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't set body event callback, body is null.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!func)
|
|
|
|
{
|
|
|
|
ERR("Can't set body event callback, function is null.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-07-02 19:09:34 -07:00
|
|
|
if ((type < 0) || (type >= EPHYSICS_CALLBACK_BODY_LAST))
|
2012-06-26 15:36:12 -07:00
|
|
|
{
|
|
|
|
ERR("Can't set body event callback, callback type is wrong.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-08-10 14:04:42 -07:00
|
|
|
cb = (EPhysics_Body_Callback *)calloc(1, sizeof(EPhysics_Body_Callback));
|
2012-06-26 15:36:12 -07:00
|
|
|
if (!cb)
|
|
|
|
{
|
|
|
|
ERR("Can't set body event callback, can't create cb instance.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
cb->func = func;
|
|
|
|
cb->type = type;
|
|
|
|
cb->data = (void *)data;
|
|
|
|
|
|
|
|
body->callbacks = eina_inlist_append(body->callbacks, EINA_INLIST_GET(cb));
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI void *
|
2012-07-02 19:09:34 -07:00
|
|
|
ephysics_body_event_callback_del(EPhysics_Body *body, EPhysics_Callback_Body_Type type, EPhysics_Body_Event_Cb func)
|
2012-06-26 15:36:12 -07:00
|
|
|
{
|
|
|
|
EPhysics_Body_Callback *cb;
|
2012-08-10 14:04:08 -07:00
|
|
|
void *cb_data = NULL;
|
2012-06-26 15:36:12 -07:00
|
|
|
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't delete body event callback, body is null.");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
EINA_INLIST_FOREACH(body->callbacks, cb)
|
|
|
|
{
|
2012-08-10 14:04:08 -07:00
|
|
|
if ((cb->type != type) || (cb->func != func))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
cb_data = cb->data;
|
|
|
|
_ephysics_body_event_callback_del(body, cb);
|
|
|
|
break;
|
|
|
|
|
2012-06-26 15:36:12 -07:00
|
|
|
}
|
|
|
|
|
2012-08-10 14:04:08 -07:00
|
|
|
return cb_data;
|
2012-06-26 15:36:12 -07:00
|
|
|
}
|
|
|
|
|
2012-07-02 19:09:21 -07:00
|
|
|
EAPI void *
|
2012-07-02 19:09:34 -07:00
|
|
|
ephysics_body_event_callback_del_full(EPhysics_Body *body, EPhysics_Callback_Body_Type type, EPhysics_Body_Event_Cb func, void *data)
|
2012-07-02 19:09:21 -07:00
|
|
|
{
|
|
|
|
EPhysics_Body_Callback *cb;
|
2012-08-10 14:04:08 -07:00
|
|
|
void *cb_data = NULL;
|
2012-07-02 19:09:21 -07:00
|
|
|
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't delete body event callback, body is null.");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
EINA_INLIST_FOREACH(body->callbacks, cb)
|
|
|
|
{
|
2012-08-10 14:04:08 -07:00
|
|
|
if ((cb->type != type) || (cb->func != func) || (cb->data != data))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
cb_data = cb->data;
|
|
|
|
_ephysics_body_event_callback_del(body, cb);
|
|
|
|
break;
|
2012-07-02 19:09:21 -07:00
|
|
|
}
|
|
|
|
|
2012-08-10 14:04:08 -07:00
|
|
|
return cb_data;
|
2012-07-02 19:09:21 -07:00
|
|
|
}
|
|
|
|
|
2012-06-26 15:36:12 -07:00
|
|
|
EAPI void
|
|
|
|
ephysics_body_restitution_set(EPhysics_Body *body, double restitution)
|
|
|
|
{
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't set body restitution, body is null.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
body->rigid_body->setRestitution(btScalar(restitution));
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI double
|
|
|
|
ephysics_body_restitution_get(const EPhysics_Body *body)
|
|
|
|
{
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't get body restitution, body is null.");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return body->rigid_body->getRestitution();
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI void
|
|
|
|
ephysics_body_friction_set(EPhysics_Body *body, double friction)
|
|
|
|
{
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't set body friction, body is null.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
body->rigid_body->setFriction(btScalar(friction));
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI double
|
|
|
|
ephysics_body_friction_get(const EPhysics_Body *body)
|
|
|
|
{
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't get body friction, body is null.");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return body->rigid_body->getFriction();
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI EPhysics_World *
|
|
|
|
ephysics_body_world_get(const EPhysics_Body *body)
|
|
|
|
{
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't get the world a null body belongs to.");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return body->world;
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI void
|
|
|
|
ephysics_body_central_impulse_apply(EPhysics_Body *body, double x, double y)
|
|
|
|
{
|
2012-08-20 15:12:14 -07:00
|
|
|
double rate;
|
|
|
|
|
2012-06-26 15:36:12 -07:00
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't apply impulse to a null body.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-08-20 15:12:14 -07:00
|
|
|
rate = ephysics_world_rate_get(body->world);
|
|
|
|
|
2012-06-26 15:36:12 -07:00
|
|
|
body->rigid_body->activate(1);
|
2012-08-20 15:12:14 -07:00
|
|
|
body->rigid_body->applyCentralImpulse(btVector3(x / rate, y / rate, 0));
|
2012-06-26 15:36:12 -07:00
|
|
|
}
|
|
|
|
|
2012-08-20 15:14:25 -07:00
|
|
|
EAPI void
|
|
|
|
ephysics_body_impulse_apply(EPhysics_Body *body, double x, double y, Evas_Coord pos_x, Evas_Coord pos_y)
|
|
|
|
{
|
|
|
|
double rate;
|
|
|
|
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't apply impulse to a null body.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
rate = ephysics_world_rate_get(body->world);
|
|
|
|
|
|
|
|
body->rigid_body->activate(1);
|
|
|
|
body->rigid_body->applyImpulse(btVector3(x / rate, y / rate, 0),
|
|
|
|
btVector3((double) pos_x / rate,
|
|
|
|
(double) pos_y / rate, 0));
|
|
|
|
}
|
|
|
|
|
2012-07-04 15:05:52 -07:00
|
|
|
EAPI void
|
|
|
|
ephysics_body_linear_movement_enable_set(EPhysics_Body *body, Eina_Bool enable_x, Eina_Bool enable_y)
|
|
|
|
{
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't set linear factor on a null body.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
body->rigid_body->setLinearFactor(btVector3(!!enable_x, !!enable_y, 0));
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI void
|
2012-07-06 07:36:40 -07:00
|
|
|
ephysics_body_linear_movement_enable_get(const EPhysics_Body *body, Eina_Bool *enable_x, Eina_Bool *enable_y)
|
2012-07-04 15:05:52 -07:00
|
|
|
{
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't check if linear factor is enabled, body is null.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (enable_x) *enable_x = !!body->rigid_body->getLinearFactor().x();
|
|
|
|
if (enable_y) *enable_y = !!body->rigid_body->getLinearFactor().y();
|
|
|
|
}
|
|
|
|
|
2012-06-26 15:36:12 -07:00
|
|
|
EAPI void
|
|
|
|
ephysics_body_torque_impulse_apply(EPhysics_Body *body, double roll)
|
|
|
|
{
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't apply torque impulse to a null body.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
body->rigid_body->activate(1);
|
2012-08-20 15:13:38 -07:00
|
|
|
body->rigid_body->applyTorqueImpulse(btVector3(0, 0, -roll));
|
2012-06-26 15:36:12 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
EAPI void
|
|
|
|
ephysics_body_rotation_on_z_axis_enable_set(EPhysics_Body *body, Eina_Bool enable)
|
|
|
|
{
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't set rotation on a null body.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!enable)
|
|
|
|
body->rigid_body->setAngularFactor(btVector3(0, 0, 0));
|
|
|
|
else
|
|
|
|
body->rigid_body->setAngularFactor(btVector3(0, 0, 1));
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI Eina_Bool
|
2012-07-06 07:36:40 -07:00
|
|
|
ephysics_body_rotation_on_z_axis_enable_get(const EPhysics_Body *body)
|
2012-06-26 15:36:12 -07:00
|
|
|
{
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't check if rotation is enabled, body is null.");
|
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return !!body->rigid_body->getAngularFactor().z();
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI double
|
2012-07-06 07:36:40 -07:00
|
|
|
ephysics_body_rotation_get(const EPhysics_Body *body)
|
2012-06-26 15:36:12 -07:00
|
|
|
{
|
|
|
|
btTransform trans;
|
|
|
|
double rot;
|
|
|
|
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't get rotation, body is null.");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
body->rigid_body->getMotionState()->getWorldTransform(trans);
|
|
|
|
rot = - trans.getRotation().getAngle() * RAD_TO_DEG *
|
|
|
|
trans.getRotation().getAxis().getZ();
|
|
|
|
|
|
|
|
return rot;
|
|
|
|
}
|
|
|
|
|
2012-08-20 15:14:43 -07:00
|
|
|
EAPI void
|
|
|
|
ephysics_body_rotation_set(EPhysics_Body *body, double rotation)
|
|
|
|
{
|
|
|
|
btTransform trans;
|
|
|
|
btQuaternion quat;
|
|
|
|
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't set rotation, body is null.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
body->rigid_body->activate(1);
|
|
|
|
body->rigid_body->getMotionState()->getWorldTransform(trans);
|
|
|
|
quat.setEuler(0, 0, -rotation / RAD_TO_DEG);
|
|
|
|
trans.setRotation(quat);
|
|
|
|
body->rigid_body->proceedToTransform(trans);
|
|
|
|
body->rigid_body->getMotionState()->setWorldTransform(trans);
|
|
|
|
|
|
|
|
DBG("Body %p rotation set to %lf", body, rotation);
|
|
|
|
}
|
|
|
|
|
2012-07-27 07:47:46 -07:00
|
|
|
EAPI void
|
|
|
|
ephysics_body_data_set(EPhysics_Body *body, void *data)
|
|
|
|
{
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't set data, body is null.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
body->data = data;
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI void *
|
|
|
|
ephysics_body_data_get(const EPhysics_Body *body)
|
|
|
|
{
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't get data, body is null.");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return body->data;
|
|
|
|
}
|
|
|
|
|
2012-08-20 15:15:52 -07:00
|
|
|
EAPI void
|
|
|
|
ephysics_body_central_force_apply(EPhysics_Body *body, double x, double y)
|
|
|
|
{
|
|
|
|
double rate;
|
|
|
|
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't apply force to a null body.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
rate = ephysics_world_rate_get(body->world);
|
|
|
|
ephysics_body_forces_apply(body);
|
|
|
|
body->rigid_body->applyCentralForce(btVector3(x / rate, y / rate, 0));
|
|
|
|
_ephysics_body_forces_update(body);
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI void
|
|
|
|
ephysics_body_force_apply(EPhysics_Body *body, double x, double y, Evas_Coord pos_x, Evas_Coord pos_y)
|
|
|
|
{
|
|
|
|
double rate;
|
|
|
|
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't apply force to a null body.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
rate = ephysics_world_rate_get(body->world);
|
|
|
|
ephysics_body_forces_apply(body);
|
|
|
|
body->rigid_body->applyForce(btVector3(x / rate, y / rate, 0),
|
|
|
|
btVector3((double) pos_x / rate,
|
|
|
|
(double) pos_y / rate, 0));
|
|
|
|
_ephysics_body_forces_update(body);
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI void
|
|
|
|
ephysics_body_torque_apply(EPhysics_Body *body, double torque)
|
|
|
|
{
|
|
|
|
double rate;
|
|
|
|
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't apply force to a null body.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
rate = ephysics_world_rate_get(body->world);
|
|
|
|
ephysics_body_forces_apply(body);
|
|
|
|
body->rigid_body->applyTorque(btVector3(0, 0, -torque));
|
|
|
|
_ephysics_body_forces_update(body);
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI void
|
|
|
|
ephysics_body_forces_get(const EPhysics_Body *body, double *x, double *y, double *torque)
|
|
|
|
{
|
2012-08-20 15:17:34 -07:00
|
|
|
double rate, gx, gy;
|
2012-08-20 15:15:52 -07:00
|
|
|
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't get forces from a null body.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
rate = ephysics_world_rate_get(body->world);
|
2012-08-20 15:17:34 -07:00
|
|
|
ephysics_world_gravity_get(body->world, &gx, &gy);
|
2012-08-20 15:15:52 -07:00
|
|
|
|
2012-08-20 15:17:34 -07:00
|
|
|
if (x) *x = body->force.x * rate + gx;
|
|
|
|
if (y) *y = body->force.y * rate + gy;
|
2012-08-20 15:15:52 -07:00
|
|
|
if (torque) *torque = -body->force.torque;
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI void
|
|
|
|
ephysics_body_forces_clear(EPhysics_Body *body)
|
|
|
|
{
|
|
|
|
if (!body)
|
|
|
|
{
|
|
|
|
ERR("Can't clear forces of a null body.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
body->force.x = 0;
|
|
|
|
body->force.y = 0;
|
|
|
|
body->force.torque = 0;
|
|
|
|
}
|
|
|
|
|
2012-06-26 15:36:12 -07:00
|
|
|
#ifdef __cplusplus
|
|
|
|
}
|
|
|
|
#endif
|