2012-06-26 15:36:12 -07:00
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
# include <config.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include "ephysics_private.h"
|
|
|
|
#include <Ecore.h>
|
|
|
|
#include <Evas.h>
|
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
extern "C" {
|
|
|
|
#endif
|
|
|
|
|
2012-08-22 13:04:39 -07:00
|
|
|
#define DEFAULT_GRAVITY btVector3(0, -9.8, 0)
|
|
|
|
|
2012-10-04 15:38:06 -07:00
|
|
|
typedef struct _Simulation_Msg Simulation_Msg;
|
|
|
|
|
|
|
|
struct _Simulation_Msg {
|
|
|
|
EPhysics_Body *body_0;
|
|
|
|
EPhysics_Body *body_1;
|
|
|
|
btVector3 pos_a;
|
|
|
|
btVector3 pos_b;
|
|
|
|
Eina_Bool tick:1;
|
|
|
|
};
|
|
|
|
|
2012-06-26 15:36:12 -07:00
|
|
|
typedef struct _EPhysics_World_Callback EPhysics_World_Callback;
|
|
|
|
|
|
|
|
struct _EPhysics_World_Callback {
|
|
|
|
EINA_INLIST;
|
|
|
|
void (*func) (void *data, EPhysics_World *world, void *event_info);
|
|
|
|
void *data;
|
2012-07-02 19:09:34 -07:00
|
|
|
EPhysics_Callback_World_Type type;
|
2012-08-10 14:04:22 -07:00
|
|
|
Eina_Bool deleted:1;
|
2012-06-26 15:36:12 -07:00
|
|
|
};
|
|
|
|
|
2012-10-10 13:32:08 -07:00
|
|
|
typedef struct _EPhysics_Light EPhysics_Light;
|
|
|
|
|
|
|
|
struct _EPhysics_Light {
|
|
|
|
Evas_Coord lx;
|
|
|
|
Evas_Coord ly;
|
|
|
|
Evas_Coord lz;
|
|
|
|
int lr;
|
|
|
|
int lg;
|
|
|
|
int lb;
|
|
|
|
int ar;
|
|
|
|
int ag;
|
|
|
|
int ab;
|
|
|
|
Eina_Bool all_bodies:1;
|
|
|
|
};
|
|
|
|
|
2012-06-26 15:36:12 -07:00
|
|
|
struct _EPhysics_World {
|
2012-08-10 14:03:01 -07:00
|
|
|
EINA_INLIST;
|
2012-10-15 14:54:29 -07:00
|
|
|
|
|
|
|
struct {
|
|
|
|
Evas_Coord x;
|
|
|
|
Evas_Coord y;
|
|
|
|
Evas_Coord z;
|
|
|
|
Evas_Coord w;
|
|
|
|
Evas_Coord h;
|
|
|
|
Evas_Coord d;
|
|
|
|
} geometry;
|
|
|
|
|
2012-10-10 13:32:29 -07:00
|
|
|
btBroadphaseInterface *broadphase;
|
|
|
|
btDefaultCollisionConfiguration *collision;
|
|
|
|
btCollisionDispatcher *dispatcher;
|
|
|
|
btSequentialImpulseConstraintSolver *solver;
|
|
|
|
btSoftRigidDynamicsWorld *dynamics_world;
|
|
|
|
btSoftBodyWorldInfo *world_info;
|
|
|
|
btSoftBodySolver *soft_solver;
|
2012-10-04 15:38:00 -07:00
|
|
|
btOverlapFilterCallback *filter_cb;
|
2012-06-26 15:36:12 -07:00
|
|
|
|
2012-10-15 14:54:29 -07:00
|
|
|
EPhysics_Body *boundaries[6];
|
2012-06-26 15:36:12 -07:00
|
|
|
EPhysics_Camera *camera;
|
2012-10-10 13:32:08 -07:00
|
|
|
EPhysics_Light *light;
|
2012-06-26 15:36:12 -07:00
|
|
|
Eina_Inlist *callbacks;
|
2012-08-10 14:03:06 -07:00
|
|
|
Eina_Inlist *bodies;
|
2012-08-10 14:03:39 -07:00
|
|
|
Eina_List *to_delete;
|
2012-08-10 14:04:22 -07:00
|
|
|
Eina_List *cb_to_delete;
|
2012-08-16 14:34:44 -07:00
|
|
|
Eina_List *constraints;
|
2012-10-04 15:38:06 -07:00
|
|
|
Ecore_Thread *simulation_th;
|
|
|
|
Ecore_Thread *cur_th;
|
2012-07-31 12:55:52 -07:00
|
|
|
int max_sub_steps;
|
2012-08-10 14:04:22 -07:00
|
|
|
int cb_walking;
|
2012-08-22 13:04:39 -07:00
|
|
|
int soft_body_ref;
|
2012-10-04 15:38:06 -07:00
|
|
|
int pending_ticks;
|
2012-06-26 15:36:12 -07:00
|
|
|
double last_update;
|
|
|
|
double rate;
|
2012-07-31 12:55:52 -07:00
|
|
|
double fixed_time_step;
|
2012-08-10 14:03:29 -07:00
|
|
|
double max_sleeping_time;
|
2012-10-04 15:38:06 -07:00
|
|
|
Eina_Lock mutex;
|
|
|
|
Eina_Condition condition;
|
2012-06-26 15:36:12 -07:00
|
|
|
Eina_Bool running:1;
|
2012-10-04 15:40:52 -07:00
|
|
|
Eina_Bool ticked:1;
|
2012-06-26 15:36:12 -07:00
|
|
|
Eina_Bool active:1;
|
2012-08-10 14:03:29 -07:00
|
|
|
Eina_Bool deleted:1;
|
2012-07-03 16:20:49 -07:00
|
|
|
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;
|
2012-10-04 15:38:06 -07:00
|
|
|
Eina_Bool pending_simulation:1;
|
2012-06-26 15:36:12 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
static int _ephysics_world_init_count = 0;
|
|
|
|
static int _worlds_running = 0;
|
2012-08-10 14:03:01 -07:00
|
|
|
static Eina_Inlist *_worlds = NULL;
|
2012-08-10 14:03:29 -07:00
|
|
|
static Eina_List *_worlds_to_delete = NULL;
|
2012-06-26 15:36:12 -07:00
|
|
|
static Ecore_Animator *_anim_simulate = NULL;
|
2012-08-10 14:03:29 -07:00
|
|
|
static int _worlds_walking = 0;
|
2012-06-26 15:36:12 -07:00
|
|
|
|
2012-08-22 13:04:39 -07:00
|
|
|
btSoftBodyWorldInfo *
|
|
|
|
ephysics_world_info_get(const EPhysics_World *world)
|
|
|
|
{
|
|
|
|
return world->world_info;
|
|
|
|
}
|
|
|
|
|
2012-07-27 07:49:53 -07:00
|
|
|
struct _ephysics_world_ovelap_filter_cb : public btOverlapFilterCallback
|
|
|
|
{
|
2012-08-10 14:03:39 -07:00
|
|
|
virtual bool needBroadphaseCollision(btBroadphaseProxy* proxy0,
|
|
|
|
btBroadphaseProxy* proxy1) const
|
2012-07-27 07:49:53 -07:00
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2012-08-16 14:35:14 -07:00
|
|
|
static inline void
|
2012-10-10 12:17:44 -07:00
|
|
|
_ephysics_world_gravity_set(EPhysics_World *world, double gx, double gy, double gz, double rate)
|
2012-08-16 14:35:14 -07:00
|
|
|
{
|
2012-08-22 13:04:39 -07:00
|
|
|
btVector3 gravity;
|
|
|
|
|
2012-10-10 12:17:44 -07:00
|
|
|
gravity = btVector3(gx / rate, -gy / rate, gz / rate);
|
2012-08-22 13:04:39 -07:00
|
|
|
world->dynamics_world->setGravity(gravity);
|
|
|
|
world->world_info->m_gravity = gravity;
|
2012-08-16 14:35:14 -07:00
|
|
|
}
|
|
|
|
|
2012-10-04 15:38:06 -07:00
|
|
|
static void
|
|
|
|
_ephysics_world_th_cancel(EPhysics_World *world)
|
|
|
|
{
|
|
|
|
_worlds = eina_inlist_remove(_worlds, EINA_INLIST_GET(world));
|
|
|
|
if (!ecore_thread_cancel(world->simulation_th))
|
|
|
|
eina_condition_signal(&world->condition);
|
|
|
|
}
|
|
|
|
|
2012-08-10 14:04:22 -07:00
|
|
|
static void
|
|
|
|
_ephysics_world_event_callback_call(EPhysics_World *world, EPhysics_Callback_World_Type type, void *event_info)
|
|
|
|
{
|
|
|
|
EPhysics_World_Callback *cb;
|
|
|
|
void *clb;
|
|
|
|
|
|
|
|
world->cb_walking++;
|
|
|
|
EINA_INLIST_FOREACH(world->callbacks, cb)
|
|
|
|
{
|
|
|
|
if ((cb->type == type) && (!cb->deleted))
|
|
|
|
cb->func(cb->data, world, event_info);
|
|
|
|
}
|
|
|
|
world->cb_walking--;
|
|
|
|
|
|
|
|
if (world->cb_walking > 0) return;
|
|
|
|
|
|
|
|
EINA_LIST_FREE(world->cb_to_delete, clb)
|
|
|
|
{
|
|
|
|
cb = (EPhysics_World_Callback *)clb;
|
|
|
|
world->callbacks = eina_inlist_remove(world->callbacks,
|
|
|
|
EINA_INLIST_GET(cb));
|
|
|
|
free(cb);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_ephysics_world_event_callback_del(EPhysics_World *world, EPhysics_World_Callback *cb)
|
|
|
|
{
|
|
|
|
if (cb->deleted) return;
|
|
|
|
|
|
|
|
cb->deleted = EINA_TRUE;
|
|
|
|
|
|
|
|
if (world->cb_walking)
|
|
|
|
{
|
|
|
|
world->cb_to_delete = eina_list_append(world->cb_to_delete, cb);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
world->callbacks = eina_inlist_remove(world->callbacks,
|
|
|
|
EINA_INLIST_GET(cb));
|
|
|
|
free(cb);
|
|
|
|
}
|
|
|
|
|
2012-06-26 15:36:12 -07:00
|
|
|
static void
|
2012-10-04 15:38:06 -07:00
|
|
|
_ephysics_world_tick(btDynamicsWorld *dynamics_world)
|
2012-06-26 15:36:12 -07:00
|
|
|
{
|
2012-07-27 07:50:36 -07:00
|
|
|
Eina_Bool world_active, camera_moved, tx, ty;
|
|
|
|
btCollisionObjectArray objects;
|
2012-10-04 15:40:16 -07:00
|
|
|
btCollisionObject *collision;
|
2012-07-27 07:50:36 -07:00
|
|
|
EPhysics_World *world;
|
|
|
|
EPhysics_Body *body;
|
2012-10-04 15:40:16 -07:00
|
|
|
btRigidBody *rigid_body;
|
2012-06-26 15:36:12 -07:00
|
|
|
|
|
|
|
world = (EPhysics_World *) dynamics_world->getWorldUserInfo();
|
|
|
|
|
2012-07-27 07:50:36 -07:00
|
|
|
world_active = EINA_FALSE;
|
|
|
|
|
|
|
|
ephysics_camera_tracked_body_get(world->camera, &body, &tx, &ty);
|
|
|
|
if ((body) && (tx || ty))
|
|
|
|
{
|
|
|
|
rigid_body = ephysics_body_rigid_body_get(body);
|
2012-08-13 15:24:28 -07:00
|
|
|
if ((rigid_body) && (rigid_body->isActive()))
|
|
|
|
ephysics_camera_target_moved(world->camera, body);
|
2012-07-27 07:50:36 -07:00
|
|
|
}
|
|
|
|
|
2012-08-13 15:24:28 -07:00
|
|
|
camera_moved = ephysics_camera_moved_get(world->camera);
|
|
|
|
|
2012-07-27 07:50:36 -07:00
|
|
|
objects = dynamics_world->getCollisionObjectArray();
|
2012-06-26 15:36:12 -07:00
|
|
|
for (int i = 0; i < objects.size(); i++)
|
|
|
|
{
|
2012-10-04 15:40:16 -07:00
|
|
|
collision = objects[i];
|
|
|
|
|
|
|
|
if (!collision)
|
2012-06-26 15:36:12 -07:00
|
|
|
continue;
|
|
|
|
|
2012-10-04 15:40:16 -07:00
|
|
|
body = (EPhysics_Body *) collision->getUserPointer();
|
|
|
|
if (collision->isActive())
|
2012-06-26 15:36:12 -07:00
|
|
|
{
|
|
|
|
ephysics_body_active_set(body, EINA_TRUE);
|
|
|
|
ephysics_body_evas_object_update_select(body);
|
|
|
|
world_active = EINA_TRUE;
|
|
|
|
}
|
|
|
|
else
|
2012-07-27 07:50:36 -07:00
|
|
|
{
|
|
|
|
ephysics_body_active_set(body, EINA_FALSE);
|
|
|
|
if (camera_moved)
|
|
|
|
ephysics_body_evas_object_update_select(body);
|
|
|
|
}
|
2012-06-26 15:36:12 -07:00
|
|
|
}
|
|
|
|
|
2012-08-13 15:24:28 -07:00
|
|
|
if (camera_moved)
|
|
|
|
{
|
2012-09-04 15:42:10 -07:00
|
|
|
ephysics_camera_moved_set(world->camera, EINA_FALSE);
|
2012-08-13 15:24:28 -07:00
|
|
|
_ephysics_world_event_callback_call(
|
|
|
|
world, EPHYSICS_CALLBACK_WORLD_CAMERA_MOVED, world->camera);
|
|
|
|
}
|
|
|
|
|
2012-10-04 15:38:06 -07:00
|
|
|
if (world->active == world_active) goto body_del;
|
2012-06-26 15:36:12 -07:00
|
|
|
world->active = world_active;
|
2012-10-04 15:38:06 -07:00
|
|
|
if (world_active) goto body_del;
|
2012-06-26 15:36:12 -07:00
|
|
|
|
2012-08-10 14:04:22 -07:00
|
|
|
_ephysics_world_event_callback_call(world, EPHYSICS_CALLBACK_WORLD_STOPPED,
|
|
|
|
NULL);
|
2012-10-04 15:38:06 -07:00
|
|
|
|
|
|
|
body_del:
|
|
|
|
world->pending_ticks--;
|
|
|
|
if (!world->pending_ticks)
|
|
|
|
{
|
|
|
|
void *bd;
|
|
|
|
EINA_LIST_FREE(world->to_delete, bd)
|
|
|
|
ephysics_world_body_del(world, (EPhysics_Body*)bd);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((world->pending_simulation) && (!world->pending_ticks))
|
|
|
|
{
|
|
|
|
world->pending_simulation = EINA_FALSE;
|
|
|
|
eina_condition_signal(&world->condition);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2012-10-04 15:40:52 -07:00
|
|
|
_ephysics_world_tick_dispatch(EPhysics_World *world)
|
2012-10-04 15:38:06 -07:00
|
|
|
{
|
|
|
|
Simulation_Msg *msg;
|
|
|
|
|
2012-10-04 15:40:52 -07:00
|
|
|
if (!world->ticked)
|
|
|
|
return;
|
|
|
|
|
|
|
|
world->ticked = EINA_FALSE;
|
|
|
|
world->pending_ticks++;
|
|
|
|
|
2012-10-04 15:38:06 -07:00
|
|
|
msg = (Simulation_Msg *) calloc(1, sizeof(Simulation_Msg));
|
|
|
|
msg->tick = EINA_TRUE;
|
2012-10-04 15:40:52 -07:00
|
|
|
ecore_thread_feedback(world->cur_th, msg);
|
|
|
|
}
|
2012-10-04 15:38:06 -07:00
|
|
|
|
2012-10-04 15:40:52 -07:00
|
|
|
static void
|
|
|
|
_ephysics_world_tick_cb(btDynamicsWorld *dynamics_world, btScalar timeStep __UNUSED__)
|
|
|
|
{
|
|
|
|
EPhysics_World *world;
|
2012-10-04 15:38:06 -07:00
|
|
|
world = (EPhysics_World *) dynamics_world->getWorldUserInfo();
|
2012-10-04 15:40:52 -07:00
|
|
|
world->ticked = EINA_TRUE;
|
2012-06-26 15:36:12 -07:00
|
|
|
}
|
|
|
|
|
2012-09-12 14:49:47 -07:00
|
|
|
static void
|
|
|
|
_ephysics_world_body_del(EPhysics_World *world, EPhysics_Body *body)
|
|
|
|
{
|
|
|
|
btSoftBody *soft_body;
|
|
|
|
|
2012-10-04 15:40:16 -07:00
|
|
|
if (ephysics_body_rigid_body_get(body))
|
|
|
|
world->dynamics_world->removeRigidBody(ephysics_body_rigid_body_get(body));
|
2012-09-12 14:49:47 -07:00
|
|
|
|
|
|
|
soft_body = ephysics_body_soft_body_get(body);
|
|
|
|
if (soft_body)
|
|
|
|
{
|
|
|
|
world->dynamics_world->removeSoftBody(soft_body);
|
|
|
|
--world->soft_body_ref;
|
|
|
|
}
|
|
|
|
|
|
|
|
world->bodies = eina_inlist_remove(world->bodies, EINA_INLIST_GET(body));
|
|
|
|
ephysics_orphan_body_del(body);
|
|
|
|
}
|
|
|
|
|
|
|
|
Eina_Bool
|
|
|
|
ephysics_world_body_del(EPhysics_World *world, EPhysics_Body *body)
|
|
|
|
{
|
|
|
|
EPhysics_Body *bd;
|
|
|
|
|
2012-10-04 15:38:06 -07:00
|
|
|
if (world->pending_ticks)
|
2012-09-12 14:49:47 -07:00
|
|
|
{
|
|
|
|
world->to_delete = eina_list_append(world->to_delete, body);
|
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
_ephysics_world_body_del(world, body);
|
|
|
|
|
|
|
|
/* Activate all the bodies after a body is deleted.
|
|
|
|
Otherwise it can lead to scenarios when a body 1, below body 2 is deleted
|
|
|
|
and body 2 will stay freezed in the air. Gravity won't start to
|
|
|
|
act over it until it's activated again. */
|
|
|
|
EINA_INLIST_FOREACH(world->bodies, bd)
|
2012-10-04 15:40:16 -07:00
|
|
|
ephysics_body_activate(bd, EINA_TRUE);
|
2012-09-12 14:49:47 -07:00
|
|
|
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
2012-08-10 14:03:29 -07:00
|
|
|
static void
|
|
|
|
_ephysics_world_free(EPhysics_World *world)
|
|
|
|
{
|
|
|
|
EPhysics_World_Callback *cb;
|
|
|
|
EPhysics_Body *body;
|
2012-08-16 14:34:44 -07:00
|
|
|
void *constraint;
|
2012-08-10 14:03:29 -07:00
|
|
|
|
|
|
|
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);
|
2012-09-12 14:49:47 -07:00
|
|
|
_ephysics_world_body_del(world, body);
|
2012-08-10 14:03:29 -07:00
|
|
|
}
|
|
|
|
|
2012-08-16 14:34:44 -07:00
|
|
|
EINA_LIST_FREE(world->constraints, constraint)
|
|
|
|
ephysics_constraint_del((EPhysics_Constraint *)constraint);
|
|
|
|
|
2012-08-10 14:03:29 -07:00
|
|
|
ephysics_camera_del(world->camera);
|
2012-09-12 14:49:47 -07:00
|
|
|
|
2012-10-04 15:38:00 -07:00
|
|
|
delete world->filter_cb;
|
2012-08-10 14:03:29 -07:00
|
|
|
delete world->dynamics_world;
|
|
|
|
delete world->solver;
|
2012-08-10 14:04:16 -07:00
|
|
|
delete world->broadphase;
|
2012-08-10 14:03:29 -07:00
|
|
|
delete world->dispatcher;
|
|
|
|
delete world->collision;
|
2012-08-22 13:04:39 -07:00
|
|
|
delete world->soft_solver;
|
|
|
|
delete world->world_info;
|
2012-08-10 14:03:29 -07:00
|
|
|
|
2012-10-04 15:38:06 -07:00
|
|
|
eina_condition_free(&world->condition);
|
|
|
|
eina_lock_free(&world->mutex);
|
|
|
|
|
2012-10-10 13:32:08 -07:00
|
|
|
if (world->light)
|
|
|
|
free(world->light);
|
|
|
|
|
2012-08-10 14:03:29 -07:00
|
|
|
free(world);
|
|
|
|
INF("World %p deleted.", world);
|
2012-10-04 15:38:11 -07:00
|
|
|
ephysics_dom_count_dec();
|
2012-08-10 14:03:29 -07:00
|
|
|
}
|
|
|
|
|
2012-06-26 15:36:12 -07:00
|
|
|
static Eina_Bool
|
2012-08-21 10:47:29 -07:00
|
|
|
_simulate_worlds(void *data __UNUSED__)
|
2012-06-26 15:36:12 -07:00
|
|
|
{
|
2012-08-10 14:03:01 -07:00
|
|
|
EPhysics_World *world;
|
2012-10-04 15:38:06 -07:00
|
|
|
void *wrld;
|
2012-06-26 15:36:12 -07:00
|
|
|
|
2012-08-10 14:03:29 -07:00
|
|
|
ephysics_init();
|
|
|
|
_worlds_walking++;
|
2012-08-21 10:47:29 -07:00
|
|
|
EINA_INLIST_FOREACH(_worlds, world)
|
2012-06-26 15:36:12 -07:00
|
|
|
{
|
|
|
|
if (!world->running)
|
|
|
|
continue;
|
|
|
|
|
2012-10-04 15:38:06 -07:00
|
|
|
if (world->pending_ticks)
|
2012-09-12 14:49:29 -07:00
|
|
|
{
|
2012-10-04 15:38:06 -07:00
|
|
|
world->pending_simulation = EINA_TRUE;
|
|
|
|
continue;
|
2012-09-12 14:49:29 -07:00
|
|
|
}
|
2012-08-22 13:04:39 -07:00
|
|
|
|
2012-10-04 15:38:06 -07:00
|
|
|
world->pending_simulation = EINA_FALSE;
|
2012-08-10 14:03:39 -07:00
|
|
|
|
2012-10-04 15:38:06 -07:00
|
|
|
eina_condition_signal(&world->condition);
|
2012-06-26 15:36:12 -07:00
|
|
|
}
|
2012-08-10 14:03:29 -07:00
|
|
|
_worlds_walking--;
|
|
|
|
|
|
|
|
if (_worlds_walking > 0)
|
|
|
|
{
|
|
|
|
ephysics_shutdown();
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
EINA_LIST_FREE(_worlds_to_delete, wrld)
|
2012-10-04 15:38:06 -07:00
|
|
|
_ephysics_world_th_cancel((EPhysics_World *)wrld);
|
2012-08-10 14:03:29 -07:00
|
|
|
|
|
|
|
ephysics_shutdown();
|
2012-06-26 15:36:12 -07:00
|
|
|
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool
|
|
|
|
_ephysics_world_contact_processed_cb(btManifoldPoint &cp, void *b0, void *b1)
|
|
|
|
{
|
|
|
|
btRigidBody *rigid_body_0, *rigid_body_1;
|
|
|
|
EPhysics_Body *body_0, *body_1;
|
2012-10-04 15:38:06 -07:00
|
|
|
EPhysics_World *world;
|
|
|
|
Simulation_Msg *msg;
|
2012-06-26 15:36:12 -07:00
|
|
|
|
|
|
|
rigid_body_0 = (btRigidBody *) b0;
|
|
|
|
rigid_body_1 = (btRigidBody *) b1;
|
|
|
|
|
|
|
|
body_0 = (EPhysics_Body *) rigid_body_0->getUserPointer();
|
|
|
|
body_1 = (EPhysics_Body *) rigid_body_1->getUserPointer();
|
|
|
|
|
2012-10-04 15:38:06 -07:00
|
|
|
world = ephysics_body_world_get(body_0);
|
|
|
|
|
|
|
|
msg = (Simulation_Msg *) calloc(1, sizeof(Simulation_Msg));
|
|
|
|
msg->body_0 = body_0;
|
|
|
|
msg->body_1 = body_1;
|
|
|
|
msg->pos_a = cp.getPositionWorldOnA();
|
|
|
|
msg->pos_b = cp.getPositionWorldOnB();
|
|
|
|
ecore_thread_feedback(world->cur_th, msg);
|
2012-07-27 07:49:20 -07:00
|
|
|
|
|
|
|
return EINA_TRUE;
|
2012-06-26 15:36:12 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2012-09-04 15:42:28 -07:00
|
|
|
_ephysics_world_boundary_del_cb(void *data, EPhysics_Body *body, void *event_info __UNUSED__)
|
2012-06-26 15:36:12 -07:00
|
|
|
{
|
|
|
|
EPhysics_World *world = (EPhysics_World *) data;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < EPHYSICS_WORLD_BOUNDARY_LAST; i++)
|
|
|
|
{
|
|
|
|
if (world->boundaries[i] == body)
|
|
|
|
{
|
|
|
|
world->boundaries[i] = NULL;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Eina_Bool
|
2012-08-10 14:03:39 -07:00
|
|
|
ephysics_world_body_add(EPhysics_World *world, EPhysics_Body *body)
|
2012-06-26 15:36:12 -07:00
|
|
|
{
|
2012-08-22 13:04:39 -07:00
|
|
|
if (!eina_inlist_find(world->bodies, EINA_INLIST_GET(body)))
|
|
|
|
world->bodies = eina_inlist_append(world->bodies, EINA_INLIST_GET(body));
|
|
|
|
|
2012-06-26 15:36:12 -07:00
|
|
|
if (eina_error_get())
|
|
|
|
{
|
|
|
|
ERR("Couldn't add body to bodies list.");
|
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
2012-08-10 14:03:39 -07:00
|
|
|
|
|
|
|
world->dynamics_world->addRigidBody(ephysics_body_rigid_body_get(body));
|
2012-06-26 15:36:12 -07:00
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
2012-08-22 13:04:39 -07:00
|
|
|
Eina_Bool
|
|
|
|
ephysics_world_soft_body_add(EPhysics_World *world, EPhysics_Body *body)
|
|
|
|
{
|
|
|
|
if (!eina_inlist_find(world->bodies, EINA_INLIST_GET(body)))
|
|
|
|
world->bodies = eina_inlist_append(world->bodies, EINA_INLIST_GET(body));
|
|
|
|
|
|
|
|
if (eina_error_get())
|
|
|
|
{
|
|
|
|
ERR("Couldn't add body to bodies list.");
|
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
++world->soft_body_ref;
|
|
|
|
world->dynamics_world->addSoftBody(ephysics_body_soft_body_get(body));
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
2012-06-26 15:36:12 -07:00
|
|
|
void
|
2012-08-16 14:34:44 -07:00
|
|
|
ephysics_world_constraint_add(EPhysics_World *world, EPhysics_Constraint *constraint, btTypedConstraint *bt_constraint)
|
2012-06-26 15:36:12 -07:00
|
|
|
{
|
|
|
|
world->dynamics_world->addConstraint(bt_constraint);
|
2012-08-16 14:34:44 -07:00
|
|
|
world->constraints = eina_list_append(world->constraints, constraint);
|
2012-06-26 15:36:12 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2012-08-16 14:34:44 -07:00
|
|
|
ephysics_world_constraint_del(EPhysics_World *world, EPhysics_Constraint *constraint, btTypedConstraint *bt_constraint)
|
2012-06-26 15:36:12 -07:00
|
|
|
{
|
|
|
|
world->dynamics_world->removeConstraint(bt_constraint);
|
2012-08-16 14:34:44 -07:00
|
|
|
world->constraints = eina_list_remove(world->constraints, constraint);
|
2012-06-26 15:36:12 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
ephysics_world_init(void)
|
|
|
|
{
|
|
|
|
if (++_ephysics_world_init_count != 1)
|
|
|
|
return _ephysics_world_init_count;
|
|
|
|
|
|
|
|
gContactProcessedCallback = _ephysics_world_contact_processed_cb;
|
|
|
|
|
|
|
|
INF("EPhysics World initialized.");
|
|
|
|
|
|
|
|
return _ephysics_world_init_count;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
ephysics_world_shutdown(void)
|
|
|
|
{
|
|
|
|
if (--_ephysics_world_init_count != 0)
|
|
|
|
return _ephysics_world_init_count;
|
|
|
|
|
|
|
|
if (_anim_simulate)
|
|
|
|
{
|
|
|
|
ecore_animator_del(_anim_simulate);
|
|
|
|
_anim_simulate = NULL;
|
|
|
|
}
|
|
|
|
|
2012-08-10 14:03:01 -07:00
|
|
|
while (_worlds)
|
2012-06-26 15:36:12 -07:00
|
|
|
{
|
2012-08-10 14:03:01 -07:00
|
|
|
EPhysics_World *world = EINA_INLIST_CONTAINER_GET(
|
|
|
|
_worlds, EPhysics_World);
|
2012-06-26 15:36:12 -07:00
|
|
|
ephysics_world_del(world);
|
|
|
|
}
|
|
|
|
|
|
|
|
_worlds_running = 0;
|
|
|
|
|
|
|
|
INF("EPhysics World shutdown.");
|
|
|
|
|
|
|
|
return _ephysics_world_init_count;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
ephysics_world_boundary_set(EPhysics_World *world, EPhysics_World_Boundary boundary, EPhysics_Body *body)
|
|
|
|
{
|
|
|
|
world->boundaries[boundary] = body;
|
|
|
|
ephysics_body_event_callback_add(body, EPHYSICS_CALLBACK_BODY_DEL,
|
|
|
|
_ephysics_world_boundary_del_cb, world);
|
|
|
|
}
|
|
|
|
|
|
|
|
EPhysics_Body *
|
|
|
|
ephysics_world_boundary_get(const EPhysics_World *world, EPhysics_World_Boundary boundary)
|
|
|
|
{
|
|
|
|
return world->boundaries[boundary];
|
|
|
|
}
|
|
|
|
|
2012-10-04 15:38:06 -07:00
|
|
|
static void
|
|
|
|
_th_simulate(void *data, Ecore_Thread *th)
|
|
|
|
{
|
|
|
|
EPhysics_World *world = (EPhysics_World *) data;
|
|
|
|
|
|
|
|
while (1)
|
|
|
|
{
|
|
|
|
double time_now, delta;
|
|
|
|
EPhysics_Body *body;
|
|
|
|
|
|
|
|
eina_condition_wait(&world->condition);
|
|
|
|
if (ecore_thread_check(th))
|
|
|
|
{
|
|
|
|
INF("Thread canceled by main loop thread");
|
|
|
|
eina_lock_release(&world->mutex);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
world->pending_ticks++;
|
|
|
|
world->cur_th = th;
|
|
|
|
|
|
|
|
EINA_INLIST_FOREACH(world->bodies, body)
|
|
|
|
ephysics_body_forces_apply(body);
|
|
|
|
|
|
|
|
time_now = ecore_time_get();
|
|
|
|
delta = time_now - world->last_update;
|
|
|
|
world->last_update = time_now;
|
|
|
|
|
|
|
|
gDeactivationTime = world->max_sleeping_time;
|
|
|
|
|
|
|
|
if (world->soft_body_ref)
|
|
|
|
{
|
|
|
|
world->dynamics_world->stepSimulation(delta, world->max_sub_steps,
|
|
|
|
world->fixed_time_step);
|
|
|
|
world->world_info->m_sparsesdf.GarbageCollect();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
((btDiscreteDynamicsWorld *)world->dynamics_world)->stepSimulation(
|
|
|
|
delta, world->max_sub_steps, world->fixed_time_step);
|
|
|
|
|
2012-10-04 15:40:52 -07:00
|
|
|
_ephysics_world_tick_dispatch(world);
|
2012-10-04 15:38:06 -07:00
|
|
|
world->pending_ticks--;
|
|
|
|
eina_lock_release(&world->mutex);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_th_msg_cb(void *data, Ecore_Thread *th __UNUSED__, void *msg_data)
|
|
|
|
{
|
|
|
|
EPhysics_World *world = (EPhysics_World *) data;
|
|
|
|
Simulation_Msg *msg = (Simulation_Msg *) msg_data;
|
|
|
|
|
|
|
|
if (msg->tick)
|
|
|
|
_ephysics_world_tick(world->dynamics_world);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ephysics_body_contact_processed(msg->body_0, msg->body_1, msg->pos_a);
|
|
|
|
ephysics_body_contact_processed(msg->body_1, msg->body_0, msg->pos_b);
|
|
|
|
}
|
|
|
|
free(msg);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_th_end_cb(void *data, Ecore_Thread *th)
|
|
|
|
{
|
|
|
|
EPhysics_World *world = (EPhysics_World *) data;
|
|
|
|
INF("World %p simulation thread %p end", world, th);
|
|
|
|
world->simulation_th = NULL;
|
|
|
|
_ephysics_world_free(world);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_th_cancel_cb(void *data, Ecore_Thread *th)
|
|
|
|
{
|
|
|
|
EPhysics_World *world = (EPhysics_World *) data;
|
|
|
|
INF("World %p simulation thread %p canceled", world, th);
|
|
|
|
world->simulation_th = NULL;
|
|
|
|
_ephysics_world_free(world);
|
|
|
|
}
|
|
|
|
|
2012-06-26 15:36:12 -07:00
|
|
|
EAPI EPhysics_World *
|
|
|
|
ephysics_world_new(void)
|
|
|
|
{
|
|
|
|
EPhysics_World *world;
|
|
|
|
|
|
|
|
world = (EPhysics_World *) calloc(1, sizeof(EPhysics_World));
|
|
|
|
if (!world)
|
|
|
|
{
|
|
|
|
ERR("Couldn't create a new world instance.");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
world->camera = ephysics_camera_add(world);
|
|
|
|
if (!world->camera)
|
|
|
|
{
|
|
|
|
ERR("Couldn't create a camera for this world.");
|
|
|
|
goto no_camera;
|
|
|
|
}
|
|
|
|
|
|
|
|
world->broadphase = new btDbvtBroadphase();
|
|
|
|
if (!world->broadphase)
|
|
|
|
{
|
|
|
|
ERR("Couldn't set broadphase.");
|
|
|
|
goto no_broadphase;
|
|
|
|
}
|
|
|
|
|
2012-08-22 13:04:39 -07:00
|
|
|
world->collision = new btSoftBodyRigidBodyCollisionConfiguration();
|
2012-06-26 15:36:12 -07:00
|
|
|
if (!world->collision)
|
|
|
|
{
|
|
|
|
ERR("Couldn't configure collision.");
|
|
|
|
goto no_collision;
|
|
|
|
}
|
|
|
|
|
|
|
|
world->dispatcher = new btCollisionDispatcher(world->collision);
|
|
|
|
if (!world->dispatcher)
|
|
|
|
{
|
|
|
|
ERR("Couldn't create dispatcher.");
|
|
|
|
goto no_dispatcher;
|
|
|
|
}
|
|
|
|
|
|
|
|
world->solver = new btSequentialImpulseConstraintSolver;
|
|
|
|
if (!world->solver)
|
|
|
|
{
|
|
|
|
ERR("Couldn't create solver.");
|
|
|
|
goto no_solver;
|
|
|
|
}
|
|
|
|
|
2012-08-22 13:04:39 -07:00
|
|
|
world->soft_solver = new btDefaultSoftBodySolver();
|
|
|
|
if (!world->soft_solver)
|
|
|
|
{
|
|
|
|
ERR("Couldn't create soft body solver.");
|
|
|
|
goto no_soft_solver;
|
|
|
|
}
|
|
|
|
|
|
|
|
world->dynamics_world = new btSoftRigidDynamicsWorld(
|
2012-06-26 15:36:12 -07:00
|
|
|
world->dispatcher, world->broadphase, world->solver,
|
2012-08-22 13:04:39 -07:00
|
|
|
world->collision, world->soft_solver);
|
2012-06-26 15:36:12 -07:00
|
|
|
if (!world->dynamics_world)
|
|
|
|
{
|
|
|
|
ERR("Couldn't create dynamic world.");
|
|
|
|
goto no_world;
|
|
|
|
}
|
|
|
|
|
2012-08-22 13:04:39 -07:00
|
|
|
world->world_info = new btSoftBodyWorldInfo();
|
|
|
|
if (!world->world_info)
|
|
|
|
{
|
|
|
|
ERR("Couldn't create soft body world info.");
|
|
|
|
goto no_world_info;
|
|
|
|
}
|
|
|
|
|
|
|
|
world->world_info->m_gravity = DEFAULT_GRAVITY;
|
|
|
|
world->world_info->m_broadphase = world->broadphase;
|
|
|
|
world->world_info->m_dispatcher = world->dispatcher;
|
|
|
|
world->world_info->m_sparsesdf.Initialize();
|
|
|
|
|
2012-08-10 14:03:01 -07:00
|
|
|
_worlds = eina_inlist_append(_worlds, EINA_INLIST_GET(world));
|
2012-06-26 15:36:12 -07:00
|
|
|
if (eina_error_get())
|
|
|
|
{
|
|
|
|
ERR("Couldn't add world to worlds list.");
|
|
|
|
goto no_list;
|
|
|
|
}
|
2012-10-04 15:38:06 -07:00
|
|
|
world->simulation_th = ecore_thread_feedback_run(
|
|
|
|
_th_simulate, _th_msg_cb, _th_end_cb, _th_cancel_cb, world, EINA_TRUE);
|
|
|
|
if (!world->simulation_th)
|
|
|
|
{
|
|
|
|
ERR("Failed to create simulation thread.");
|
|
|
|
goto no_thread;
|
|
|
|
}
|
|
|
|
eina_lock_new(&world->mutex);
|
|
|
|
eina_condition_new(&world->condition, &world->mutex);
|
2012-06-26 15:36:12 -07:00
|
|
|
|
2012-07-05 15:53:14 -07:00
|
|
|
world->dynamics_world->getSolverInfo().m_solverMode ^=
|
|
|
|
EPHYSICS_WORLD_SOLVER_SIMD;
|
2012-08-22 13:04:39 -07:00
|
|
|
world->dynamics_world->setGravity(DEFAULT_GRAVITY);
|
2012-07-27 07:49:53 -07:00
|
|
|
|
2012-10-04 15:38:00 -07:00
|
|
|
world->filter_cb = new _ephysics_world_ovelap_filter_cb();
|
|
|
|
if (!world->filter_cb)
|
2012-07-27 07:49:53 -07:00
|
|
|
INF("Couldn't initialize the collision filter.");
|
|
|
|
else
|
2012-10-04 15:38:00 -07:00
|
|
|
world->dynamics_world->getPairCache()->setOverlapFilterCallback(
|
|
|
|
world->filter_cb);
|
2012-07-27 07:49:53 -07:00
|
|
|
|
2012-06-26 15:36:12 -07:00
|
|
|
world->rate = 30;
|
2012-07-31 12:55:52 -07:00
|
|
|
world->max_sub_steps = 3;
|
|
|
|
world->fixed_time_step = 1/60.f;
|
2012-06-26 15:36:12 -07:00
|
|
|
world->dynamics_world->setInternalTickCallback(_ephysics_world_tick_cb,
|
|
|
|
(void *) world);
|
|
|
|
|
2012-07-27 07:48:59 -07:00
|
|
|
world->max_sleeping_time = 2.0;
|
2012-06-26 15:36:12 -07:00
|
|
|
world->running = EINA_TRUE;
|
|
|
|
world->last_update = ecore_time_get();
|
|
|
|
_worlds_running++;
|
|
|
|
if (!_anim_simulate)
|
2012-08-21 10:47:29 -07:00
|
|
|
_anim_simulate = ecore_animator_add(_simulate_worlds, NULL);
|
2012-06-26 15:36:12 -07:00
|
|
|
|
2012-10-04 15:38:11 -07:00
|
|
|
ephysics_dom_count_inc();
|
2012-07-03 16:21:11 -07:00
|
|
|
INF("World %p added.", world);
|
2012-06-26 15:36:12 -07:00
|
|
|
return world;
|
|
|
|
|
2012-10-04 15:38:06 -07:00
|
|
|
no_thread:
|
|
|
|
_worlds = eina_inlist_remove(_worlds, EINA_INLIST_GET(world));
|
2012-06-26 15:36:12 -07:00
|
|
|
no_list:
|
2012-08-22 13:04:39 -07:00
|
|
|
delete world->world_info;
|
|
|
|
no_world_info:
|
2012-06-26 15:36:12 -07:00
|
|
|
delete world->dynamics_world;
|
|
|
|
no_world:
|
2012-08-22 13:04:39 -07:00
|
|
|
delete world->soft_solver;
|
|
|
|
no_soft_solver:
|
2012-06-26 15:36:12 -07:00
|
|
|
delete world->solver;
|
|
|
|
no_solver:
|
|
|
|
delete world->dispatcher;
|
|
|
|
no_dispatcher:
|
|
|
|
delete world->collision;
|
|
|
|
no_collision:
|
|
|
|
delete world->broadphase;
|
|
|
|
no_broadphase:
|
|
|
|
ephysics_camera_del(world->camera);
|
|
|
|
no_camera:
|
|
|
|
free(world);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI Eina_Bool
|
2012-10-04 15:38:06 -07:00
|
|
|
ephysics_world_serialize(EPhysics_World *world, const char *path)
|
2012-06-26 15:36:12 -07:00
|
|
|
{
|
|
|
|
btDefaultSerializer *serializer;
|
|
|
|
FILE *file;
|
|
|
|
|
|
|
|
if (!world)
|
|
|
|
{
|
|
|
|
WRN("Could not serialize, world not provided.");
|
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
|
|
|
|
2012-10-04 15:38:06 -07:00
|
|
|
eina_lock_take(&world->mutex);
|
|
|
|
|
2012-06-26 15:36:12 -07:00
|
|
|
file = fopen(path, "wb");
|
|
|
|
if (!file)
|
|
|
|
{
|
|
|
|
WRN("Could not serialize, could not open file: %s", path);
|
2012-10-04 15:38:06 -07:00
|
|
|
eina_lock_release(&world->mutex);
|
2012-06-26 15:36:12 -07:00
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
serializer = new btDefaultSerializer();
|
|
|
|
world->dynamics_world->serialize(serializer);
|
|
|
|
|
|
|
|
if (!fwrite(serializer->getBufferPointer(),
|
|
|
|
serializer->getCurrentBufferSize(), 1, file))
|
|
|
|
{
|
|
|
|
WRN("Problems on writing to: %s.", path);
|
|
|
|
fclose(file);
|
|
|
|
delete serializer;
|
2012-10-04 15:38:06 -07:00
|
|
|
eina_lock_release(&world->mutex);
|
2012-06-26 15:36:12 -07:00
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
fclose(file);
|
|
|
|
delete serializer;
|
|
|
|
|
2012-07-03 16:21:11 -07:00
|
|
|
INF("Serialization of world %p written to file: %s.", world, path);
|
2012-06-26 15:36:12 -07:00
|
|
|
|
2012-10-04 15:38:06 -07:00
|
|
|
eina_lock_release(&world->mutex);
|
2012-06-26 15:36:12 -07:00
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
2012-10-04 15:38:06 -07:00
|
|
|
static void
|
|
|
|
_ephysics_world_running_set(EPhysics_World *world, Eina_Bool running)
|
|
|
|
{
|
|
|
|
if ((!!running) == world->running) return;
|
|
|
|
|
|
|
|
world->running = !!running;
|
|
|
|
|
|
|
|
if (world->running)
|
|
|
|
{
|
|
|
|
world->last_update = ecore_time_get();
|
|
|
|
_worlds_running++;
|
|
|
|
INF("World unpaused.");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
_worlds_running--;
|
|
|
|
INF("World paused.");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!_worlds_running)
|
|
|
|
{
|
|
|
|
if (_anim_simulate)
|
|
|
|
{
|
|
|
|
ecore_animator_del(_anim_simulate);
|
|
|
|
_anim_simulate = NULL;
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_anim_simulate)
|
|
|
|
return;
|
|
|
|
|
|
|
|
_anim_simulate = ecore_animator_add(_simulate_worlds, NULL);
|
|
|
|
}
|
|
|
|
|
2012-06-26 15:36:12 -07:00
|
|
|
EAPI void
|
|
|
|
ephysics_world_del(EPhysics_World *world)
|
|
|
|
{
|
|
|
|
if (!world)
|
|
|
|
{
|
|
|
|
ERR("Can't delete world, it wasn't provided.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-08-10 14:03:29 -07:00
|
|
|
if (world->deleted) return;
|
|
|
|
|
2012-10-04 15:38:06 -07:00
|
|
|
eina_lock_take(&world->mutex);
|
|
|
|
|
2012-08-10 14:03:29 -07:00
|
|
|
world->deleted = EINA_TRUE;
|
2012-08-10 14:04:22 -07:00
|
|
|
_ephysics_world_event_callback_call(world, EPHYSICS_CALLBACK_WORLD_DEL,
|
|
|
|
NULL);
|
2012-10-04 15:38:06 -07:00
|
|
|
_ephysics_world_running_set(world, EINA_FALSE);
|
2012-06-26 15:36:12 -07:00
|
|
|
|
2012-08-10 14:03:29 -07:00
|
|
|
if (_worlds_walking > 0)
|
2012-08-10 14:03:06 -07:00
|
|
|
{
|
2012-08-10 14:03:29 -07:00
|
|
|
_worlds_to_delete = eina_list_append(_worlds_to_delete, world);
|
|
|
|
INF("World %p marked to delete.", world);
|
2012-10-04 15:38:06 -07:00
|
|
|
eina_lock_release(&world->mutex);
|
2012-08-10 14:03:29 -07:00
|
|
|
return;
|
2012-08-10 14:03:06 -07:00
|
|
|
}
|
2012-06-26 15:36:12 -07:00
|
|
|
|
2012-10-04 15:38:06 -07:00
|
|
|
eina_lock_release(&world->mutex);
|
|
|
|
_ephysics_world_th_cancel(world);
|
2012-06-26 15:36:12 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
EAPI void
|
|
|
|
ephysics_world_running_set(EPhysics_World *world, Eina_Bool running)
|
|
|
|
{
|
|
|
|
if (!world)
|
|
|
|
{
|
|
|
|
ERR("Can't (un)pause world, it wasn't provided.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-10-04 15:38:06 -07:00
|
|
|
eina_lock_take(&world->mutex);
|
|
|
|
_ephysics_world_running_set(world, running);
|
|
|
|
eina_lock_release(&world->mutex);
|
2012-06-26 15:36:12 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
EAPI Eina_Bool
|
|
|
|
ephysics_world_running_get(const EPhysics_World *world)
|
|
|
|
{
|
|
|
|
if (!world)
|
|
|
|
{
|
|
|
|
ERR("No world, no running status for you.");
|
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return world->running;
|
|
|
|
}
|
|
|
|
|
2012-07-27 07:48:59 -07:00
|
|
|
EAPI void
|
|
|
|
ephysics_world_max_sleeping_time_set(EPhysics_World *world, double sleeping_time)
|
|
|
|
{
|
|
|
|
if (!world)
|
|
|
|
{
|
|
|
|
ERR("Can't set the world's max sleeping time, world is null.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-10-04 15:38:06 -07:00
|
|
|
eina_lock_take(&world->mutex);
|
2012-07-27 07:48:59 -07:00
|
|
|
world->max_sleeping_time = sleeping_time;
|
2012-10-04 15:38:06 -07:00
|
|
|
eina_lock_release(&world->mutex);
|
2012-07-27 07:48:59 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
EAPI double
|
|
|
|
ephysics_world_max_sleeping_time_get(const EPhysics_World *world)
|
|
|
|
{
|
|
|
|
if (!world)
|
|
|
|
{
|
|
|
|
ERR("Can't get the world's max sleeping time, world is null.");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return world->max_sleeping_time;
|
|
|
|
}
|
|
|
|
|
2012-06-26 15:36:12 -07:00
|
|
|
EAPI void
|
2012-10-10 12:17:44 -07:00
|
|
|
ephysics_world_gravity_set(EPhysics_World *world, double gx, double gy, double gz)
|
2012-06-26 15:36:12 -07:00
|
|
|
{
|
2012-10-09 13:00:36 -07:00
|
|
|
EPhysics_Body *bd;
|
|
|
|
|
2012-06-26 15:36:12 -07:00
|
|
|
if (!world)
|
|
|
|
{
|
|
|
|
ERR("Can't set gravity, no world provided.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-10-04 15:38:06 -07:00
|
|
|
eina_lock_take(&world->mutex);
|
2012-10-09 13:00:36 -07:00
|
|
|
EINA_INLIST_FOREACH(world->bodies, bd)
|
|
|
|
ephysics_body_activate(bd, EINA_TRUE);
|
2012-10-10 12:17:44 -07:00
|
|
|
_ephysics_world_gravity_set(world, gx, gy, gz, world->rate);
|
|
|
|
DBG("World %p gravity set to X:%lf, Y:%lf, Z: %lf.", world, gx, gy, gz);
|
2012-10-04 15:38:06 -07:00
|
|
|
eina_lock_release(&world->mutex);
|
2012-06-26 15:36:12 -07:00
|
|
|
}
|
|
|
|
|
2012-07-03 16:24:27 -07:00
|
|
|
EAPI void
|
|
|
|
ephysics_world_constraint_solver_iterations_set(EPhysics_World *world, int iterations)
|
|
|
|
{
|
|
|
|
if (!world)
|
|
|
|
{
|
|
|
|
ERR("Can't set constraint solver iterations, world is null.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-10-04 15:38:06 -07:00
|
|
|
eina_lock_take(&world->mutex);
|
2012-07-03 16:24:27 -07:00
|
|
|
world->dynamics_world->getSolverInfo().m_numIterations = iterations;
|
2012-10-04 15:38:06 -07:00
|
|
|
eina_lock_release(&world->mutex);
|
2012-07-03 16:24:27 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
EAPI int
|
2012-07-06 07:36:40 -07:00
|
|
|
ephysics_world_constraint_solver_iterations_get(const EPhysics_World *world)
|
2012-07-03 16:24:27 -07:00
|
|
|
{
|
|
|
|
if (!world)
|
|
|
|
{
|
|
|
|
ERR("Can't get constraint solver iterations, world is null.");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return world->dynamics_world->getSolverInfo().m_numIterations;
|
|
|
|
}
|
|
|
|
|
2012-07-05 15:53:14 -07:00
|
|
|
EAPI void
|
|
|
|
ephysics_world_constraint_solver_mode_enable_set(EPhysics_World *world, EPhysics_World_Solver_Mode solver_mode, Eina_Bool enable)
|
|
|
|
{
|
|
|
|
int current_solver_mode;
|
|
|
|
if (!world)
|
|
|
|
{
|
|
|
|
ERR("Can't enable/disable constraint solver mode, world is null.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-10-04 15:38:06 -07:00
|
|
|
eina_lock_take(&world->mutex);
|
2012-07-05 15:53:14 -07:00
|
|
|
current_solver_mode = world->dynamics_world->getSolverInfo().m_solverMode;
|
|
|
|
if ((enable && !(current_solver_mode & solver_mode)) ||
|
|
|
|
(!enable && (current_solver_mode & solver_mode)))
|
|
|
|
world->dynamics_world->getSolverInfo().m_solverMode ^= solver_mode;
|
2012-10-04 15:38:06 -07:00
|
|
|
eina_lock_release(&world->mutex);
|
2012-07-05 15:53:14 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
EAPI Eina_Bool
|
2012-07-06 07:36:40 -07:00
|
|
|
ephysics_world_constraint_solver_mode_enable_get(const EPhysics_World *world, EPhysics_World_Solver_Mode solver_mode)
|
2012-07-05 15:53:14 -07:00
|
|
|
{
|
|
|
|
if (!world)
|
|
|
|
{
|
|
|
|
ERR("Can't get constraint solver mode status, world is null.");
|
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return world->dynamics_world->getSolverInfo().m_solverMode & solver_mode;
|
|
|
|
}
|
|
|
|
|
2012-06-26 15:36:12 -07:00
|
|
|
EAPI void
|
2012-10-10 12:17:44 -07:00
|
|
|
ephysics_world_gravity_get(const EPhysics_World *world, double *gx, double *gy, double *gz)
|
2012-06-26 15:36:12 -07:00
|
|
|
{
|
|
|
|
btVector3 vector;
|
|
|
|
|
|
|
|
if (!world)
|
|
|
|
{
|
|
|
|
ERR("No world, can't get gravity.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
vector = world->dynamics_world->getGravity();
|
|
|
|
|
2012-07-02 19:17:55 -07:00
|
|
|
if (gx) *gx = vector.x() * world->rate;
|
|
|
|
if (gy) *gy = -vector.y() * world->rate;
|
2012-10-10 12:17:44 -07:00
|
|
|
if (gz) *gz = vector.z() * world->rate;
|
2012-06-26 15:36:12 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
EAPI void
|
|
|
|
ephysics_world_rate_set(EPhysics_World *world, double rate)
|
|
|
|
{
|
2012-08-16 14:35:20 -07:00
|
|
|
EPhysics_Body *body;
|
2012-10-10 12:17:44 -07:00
|
|
|
double gx, gy, gz;
|
2012-08-16 14:35:20 -07:00
|
|
|
void *constraint;
|
|
|
|
Eina_List *l;
|
|
|
|
|
2012-06-26 15:36:12 -07:00
|
|
|
if (!world)
|
|
|
|
{
|
|
|
|
ERR("No world, can't set rate.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (rate <= 0)
|
|
|
|
{
|
|
|
|
ERR("Rate should be a positive value. Keeping the old value: %lf.",
|
|
|
|
world->rate);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-10-04 15:38:06 -07:00
|
|
|
eina_lock_take(&world->mutex);
|
2012-08-16 14:35:20 -07:00
|
|
|
/* Force to recalculate sizes, velocities and accelerations with new rate */
|
2012-10-10 12:17:44 -07:00
|
|
|
ephysics_world_gravity_get(world, &gx, &gy, &gz);
|
|
|
|
_ephysics_world_gravity_set(world, gx, gy, gz, rate);
|
2012-08-16 14:35:20 -07:00
|
|
|
|
|
|
|
EINA_INLIST_FOREACH(world->bodies, body)
|
|
|
|
ephysics_body_recalc(body, rate);
|
|
|
|
|
|
|
|
EINA_LIST_FOREACH(world->constraints, l, constraint)
|
|
|
|
ephysics_constraint_recalc((EPhysics_Constraint *)constraint, rate);
|
|
|
|
|
2012-06-26 15:36:12 -07:00
|
|
|
world->rate = rate;
|
2012-10-04 15:38:06 -07:00
|
|
|
eina_lock_release(&world->mutex);
|
2012-06-26 15:36:12 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
EAPI double
|
|
|
|
ephysics_world_rate_get(const EPhysics_World *world)
|
|
|
|
{
|
|
|
|
if (!world)
|
|
|
|
{
|
|
|
|
ERR("No world, can't get rate.");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return world->rate;
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI EPhysics_Camera *
|
|
|
|
ephysics_world_camera_get(const EPhysics_World *world)
|
|
|
|
{
|
|
|
|
if (!world)
|
|
|
|
{
|
|
|
|
ERR("No world, no camera for you.");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return world->camera;
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI void
|
2012-07-02 19:09:34 -07:00
|
|
|
ephysics_world_event_callback_add(EPhysics_World *world, EPhysics_Callback_World_Type type, EPhysics_World_Event_Cb func, const void *data)
|
2012-06-26 15:36:12 -07:00
|
|
|
{
|
|
|
|
EPhysics_World_Callback *cb;
|
|
|
|
|
|
|
|
if (!world)
|
|
|
|
{
|
|
|
|
ERR("Can't set world event callback, world is null.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!func)
|
|
|
|
{
|
|
|
|
ERR("Can't set world event callback, function is null.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-07-02 19:09:34 -07:00
|
|
|
if ((type < 0) || (type >= EPHYSICS_CALLBACK_WORLD_LAST))
|
2012-06-26 15:36:12 -07:00
|
|
|
{
|
|
|
|
ERR("Can't set world event callback, callback type is wrong.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-08-10 14:04:42 -07:00
|
|
|
cb = (EPhysics_World_Callback *)calloc(1, sizeof(EPhysics_World_Callback));
|
2012-06-26 15:36:12 -07:00
|
|
|
if (!cb)
|
|
|
|
{
|
|
|
|
ERR("Can't set world event callback, can't create cb instance.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
cb->func = func;
|
|
|
|
cb->type = type;
|
|
|
|
cb->data = (void *) data;
|
|
|
|
|
|
|
|
world->callbacks = eina_inlist_append(world->callbacks, EINA_INLIST_GET(cb));
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI void *
|
2012-07-02 19:09:34 -07:00
|
|
|
ephysics_world_event_callback_del(EPhysics_World *world, EPhysics_Callback_World_Type type, EPhysics_World_Event_Cb func)
|
2012-06-26 15:36:12 -07:00
|
|
|
{
|
|
|
|
EPhysics_World_Callback *cb;
|
2012-08-10 14:04:22 -07:00
|
|
|
void *cb_data = NULL;
|
2012-06-26 15:36:12 -07:00
|
|
|
|
|
|
|
if (!world)
|
|
|
|
{
|
|
|
|
ERR("Can't delete world event callback, world is null.");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
EINA_INLIST_FOREACH(world->callbacks, cb)
|
|
|
|
{
|
2012-08-10 14:04:22 -07:00
|
|
|
if ((cb->type != type) || (cb->func != func))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
cb_data = cb->data;
|
|
|
|
_ephysics_world_event_callback_del(world, cb);
|
|
|
|
break;
|
2012-06-26 15:36:12 -07:00
|
|
|
}
|
|
|
|
|
2012-08-10 14:04:22 -07:00
|
|
|
return cb_data;
|
2012-06-26 15:36:12 -07:00
|
|
|
}
|
|
|
|
|
2012-07-02 19:09:12 -07:00
|
|
|
EAPI void *
|
2012-07-02 19:09:34 -07:00
|
|
|
ephysics_world_event_callback_del_full(EPhysics_World *world, EPhysics_Callback_World_Type type, EPhysics_World_Event_Cb func, void *data)
|
2012-07-02 19:09:12 -07:00
|
|
|
{
|
|
|
|
EPhysics_World_Callback *cb;
|
2012-08-10 14:04:22 -07:00
|
|
|
void *cb_data = NULL;
|
2012-07-02 19:09:12 -07:00
|
|
|
|
|
|
|
if (!world)
|
|
|
|
{
|
|
|
|
ERR("Can't delete world event callback, world is null.");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
EINA_INLIST_FOREACH(world->callbacks, cb)
|
|
|
|
{
|
2012-08-10 14:04:22 -07:00
|
|
|
if ((cb->type != type) || (cb->func != func) || (cb->data != data))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
cb_data = cb->data;
|
|
|
|
_ephysics_world_event_callback_del(world, cb);
|
|
|
|
break;
|
2012-07-02 19:09:12 -07:00
|
|
|
}
|
|
|
|
|
2012-08-10 14:04:22 -07:00
|
|
|
return cb_data;
|
2012-07-02 19:09:12 -07:00
|
|
|
}
|
|
|
|
|
2012-08-10 14:03:06 -07:00
|
|
|
EAPI Eina_List *
|
2012-06-26 15:36:12 -07:00
|
|
|
ephysics_world_bodies_get(const EPhysics_World *world)
|
|
|
|
{
|
2012-08-10 14:03:06 -07:00
|
|
|
Eina_List *list = NULL;
|
|
|
|
EPhysics_Body *body;
|
|
|
|
|
2012-06-26 15:36:12 -07:00
|
|
|
if (!world)
|
|
|
|
{
|
|
|
|
ERR("Couldn't get the bodies list, no world provided.");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2012-08-10 14:03:06 -07:00
|
|
|
EINA_INLIST_FOREACH(world->bodies, body)
|
|
|
|
list = eina_list_append(list, body);
|
|
|
|
|
|
|
|
return list;
|
2012-06-26 15:36:12 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
EAPI void
|
2012-10-15 14:54:29 -07:00
|
|
|
ephysics_world_render_geometry_set(EPhysics_World *world, Evas_Coord x, Evas_Coord y, Evas_Coord z, Evas_Coord w, Evas_Coord h, Evas_Coord d)
|
2012-06-26 15:36:12 -07:00
|
|
|
{
|
|
|
|
if (!world)
|
|
|
|
{
|
|
|
|
ERR("Can't set geometry, world wasn't provided.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-10-15 14:54:29 -07:00
|
|
|
if ((w <= 0) || (h <= 0) || (d <= 0))
|
2012-06-26 15:36:12 -07:00
|
|
|
{
|
|
|
|
ERR("Invalid width or height sizes. They must to be positive values.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-10-15 14:54:29 -07:00
|
|
|
world->geometry.x = x;
|
|
|
|
world->geometry.y = y;
|
|
|
|
world->geometry.z = z;
|
|
|
|
world->geometry.w = w;
|
|
|
|
world->geometry.h = h;
|
|
|
|
world->geometry.d = d;
|
2012-06-26 15:36:12 -07:00
|
|
|
|
|
|
|
ephysics_body_world_boundaries_resize(world);
|
2012-07-27 07:50:03 -07:00
|
|
|
ephysics_camera_position_set(world->camera, x, y);
|
2012-06-26 15:36:12 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
EAPI void
|
2012-10-15 14:54:29 -07:00
|
|
|
ephysics_world_render_geometry_get(const EPhysics_World *world, Evas_Coord *x, Evas_Coord *y, Evas_Coord *z, Evas_Coord *w, Evas_Coord *h, Evas_Coord *d)
|
2012-06-26 15:36:12 -07:00
|
|
|
{
|
|
|
|
if (!world)
|
|
|
|
{
|
|
|
|
ERR("Can't get geometry, world is null.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-10-15 14:54:29 -07:00
|
|
|
if (x) *x = world->geometry.x;
|
|
|
|
if (y) *y = world->geometry.y;
|
|
|
|
if (z) *z = world->geometry.z;
|
|
|
|
if (w) *w = world->geometry.w;
|
|
|
|
if (h) *h = world->geometry.h;
|
|
|
|
if (d) *d = world->geometry.d;
|
2012-06-26 15:36:12 -07:00
|
|
|
}
|
|
|
|
|
2012-06-29 15:24:33 -07:00
|
|
|
EAPI void
|
|
|
|
ephysics_world_linear_slop_set(EPhysics_World *world, double linear_slop)
|
|
|
|
{
|
|
|
|
if (!world)
|
|
|
|
{
|
|
|
|
ERR("Can't set linear slop, world is null.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-10-04 15:38:06 -07:00
|
|
|
eina_lock_take(&world->mutex);
|
2012-06-29 15:24:33 -07:00
|
|
|
world->dynamics_world->getSolverInfo().m_linearSlop = btScalar(linear_slop);
|
2012-10-04 15:38:06 -07:00
|
|
|
eina_lock_release(&world->mutex);
|
2012-06-29 15:24:33 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
EAPI double
|
2012-07-06 07:36:40 -07:00
|
|
|
ephysics_world_linear_slop_get(const EPhysics_World *world)
|
2012-06-29 15:24:33 -07:00
|
|
|
{
|
|
|
|
if (!world)
|
|
|
|
{
|
|
|
|
ERR("Can't get linear slop, world is null.");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return world->dynamics_world->getSolverInfo().m_linearSlop;
|
|
|
|
}
|
|
|
|
|
2012-07-03 16:20:49 -07:00
|
|
|
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
|
2012-07-06 07:36:40 -07:00
|
|
|
ephysics_world_bodies_outside_top_autodel_get(const EPhysics_World *world)
|
2012-07-03 16:20:49 -07:00
|
|
|
{
|
|
|
|
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
|
2012-07-06 07:36:40 -07:00
|
|
|
ephysics_world_bodies_outside_bottom_autodel_get(const EPhysics_World *world)
|
2012-07-03 16:20:49 -07:00
|
|
|
{
|
|
|
|
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
|
2012-07-06 07:36:40 -07:00
|
|
|
ephysics_world_bodies_outside_left_autodel_get(const EPhysics_World *world)
|
2012-07-03 16:20:49 -07:00
|
|
|
{
|
|
|
|
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
|
2012-07-06 07:36:40 -07:00
|
|
|
ephysics_world_bodies_outside_right_autodel_get(const EPhysics_World *world)
|
2012-07-03 16:20:49 -07:00
|
|
|
{
|
|
|
|
if (!world)
|
|
|
|
{
|
|
|
|
ERR("Can't get autodelete mode, world is null.");
|
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return world->outside_right;
|
|
|
|
}
|
|
|
|
|
2012-07-31 12:55:52 -07:00
|
|
|
EAPI Eina_Bool
|
2012-07-06 07:36:40 -07:00
|
|
|
ephysics_world_bodies_outside_autodel_get(const EPhysics_World *world)
|
2012-07-03 16:20:49 -07:00
|
|
|
{
|
|
|
|
if (!world)
|
|
|
|
{
|
|
|
|
ERR("Can't get autodelete mode, world is null.");
|
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return world->outside_autodel;
|
|
|
|
}
|
|
|
|
|
2012-07-31 12:55:52 -07:00
|
|
|
EAPI void
|
|
|
|
ephysics_world_simulation_set(EPhysics_World *world, double fixed_time_step, int max_sub_steps)
|
|
|
|
{
|
|
|
|
if (!world)
|
|
|
|
{
|
|
|
|
ERR("Can't set simulation, no world provided.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (max_sub_steps < 1)
|
|
|
|
{
|
|
|
|
ERR("At least one sub step for simulation is required.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ecore_animator_frametime_get() >= max_sub_steps * fixed_time_step)
|
|
|
|
{
|
|
|
|
ERR("Assure frametime < max sub steps * fixed time step.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-10-04 15:38:06 -07:00
|
|
|
eina_lock_take(&world->mutex);
|
2012-07-31 12:55:52 -07:00
|
|
|
world->max_sub_steps = max_sub_steps;
|
|
|
|
world->fixed_time_step = fixed_time_step;
|
|
|
|
|
|
|
|
DBG("World %p simulation set to fixed time step: %lf, max substeps:%i.",
|
|
|
|
world, fixed_time_step, max_sub_steps);
|
2012-10-04 15:38:06 -07:00
|
|
|
eina_lock_release(&world->mutex);
|
2012-07-31 12:55:52 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
EAPI void
|
|
|
|
ephysics_world_simulation_get(const EPhysics_World *world, double *fixed_time_step, int *max_sub_steps)
|
|
|
|
{
|
|
|
|
if (!world)
|
|
|
|
{
|
|
|
|
ERR("No world, can't get simulation configuration.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fixed_time_step) *fixed_time_step = world->fixed_time_step;
|
|
|
|
if (max_sub_steps) *max_sub_steps = world->max_sub_steps;
|
|
|
|
}
|
|
|
|
|
2012-10-04 15:38:06 -07:00
|
|
|
void
|
|
|
|
ephysics_world_lock_take(EPhysics_World *world)
|
|
|
|
{
|
|
|
|
eina_lock_take(&world->mutex);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
ephysics_world_lock_release(EPhysics_World *world)
|
|
|
|
{
|
|
|
|
eina_lock_release(&world->mutex);
|
|
|
|
}
|
|
|
|
|
2012-10-10 13:32:08 -07:00
|
|
|
EAPI void
|
|
|
|
ephysics_world_light_set(EPhysics_World *world,
|
|
|
|
Evas_Coord lx, Evas_Coord ly, Evas_Coord lz,
|
|
|
|
int lr, int lg, int lb,
|
|
|
|
int ar, int ag, int ab)
|
|
|
|
{
|
|
|
|
if (!world)
|
|
|
|
{
|
|
|
|
ERR("No world, can't set light.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!world->light)
|
|
|
|
world->light = (EPhysics_Light *) calloc(1, sizeof(EPhysics_Light));
|
|
|
|
|
|
|
|
if (!world->light)
|
|
|
|
{
|
|
|
|
ERR("Failed to create light.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
world->light->lx = lx;
|
|
|
|
world->light->ly = ly;
|
|
|
|
world->light->lz = lz;
|
|
|
|
world->light->lr = lr;
|
|
|
|
world->light->lg = lg;
|
|
|
|
world->light->lb = lb;
|
|
|
|
world->light->ar = ar;
|
|
|
|
world->light->ag = ag;
|
|
|
|
world->light->ab = ab;
|
|
|
|
world->light->all_bodies = EINA_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI Eina_Bool
|
|
|
|
ephysics_world_light_get(const EPhysics_World *world,
|
|
|
|
Evas_Coord *lx, Evas_Coord *ly, Evas_Coord *lz,
|
|
|
|
int *lr, int *lg, int *lb,
|
|
|
|
int *ar, int *ag, int *ab)
|
|
|
|
{
|
|
|
|
if (!world)
|
|
|
|
{
|
|
|
|
ERR("No world, can't get light.");
|
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!world->light)
|
|
|
|
{
|
|
|
|
INF("Light isn't set.");
|
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (lx) *lx = world->light->lx;
|
|
|
|
if (ly) *ly = world->light->ly;
|
|
|
|
if (lz) *lz = world->light->lz;
|
|
|
|
if (lr) *lr = world->light->lr;
|
|
|
|
if (lg) *lg = world->light->lg;
|
|
|
|
if (lb) *lb = world->light->lb;
|
|
|
|
if (ar) *ar = world->light->ar;
|
|
|
|
if (ag) *ag = world->light->ag;
|
|
|
|
if (ab) *ab = world->light->ab;
|
|
|
|
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI void
|
|
|
|
ephysics_world_light_unset(EPhysics_World *world)
|
|
|
|
{
|
|
|
|
if (!world)
|
|
|
|
{
|
|
|
|
ERR("No world, can't unset light.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!world->light)
|
|
|
|
return;
|
|
|
|
|
|
|
|
free(world->light);
|
|
|
|
world->light = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI void
|
|
|
|
ephysics_world_light_all_bodies_set(EPhysics_World *world, Eina_Bool enable)
|
|
|
|
{
|
|
|
|
if (!world)
|
|
|
|
{
|
|
|
|
ERR("No world, can't set light property.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!world->light)
|
|
|
|
{
|
|
|
|
ERR("Light isn't set, can't apply on bodies");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
world->light->all_bodies = !!enable;
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI Eina_Bool
|
|
|
|
ephysics_world_light_all_bodies_get(const EPhysics_World *world)
|
|
|
|
{
|
|
|
|
if (!world)
|
|
|
|
{
|
|
|
|
ERR("No world, can't get light property.");
|
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!world->light)
|
|
|
|
{
|
|
|
|
INF("Light isn't set, can't get light property");
|
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return world->light->all_bodies;
|
|
|
|
}
|
|
|
|
|
2012-06-26 15:36:12 -07:00
|
|
|
#ifdef __cplusplus
|
|
|
|
}
|
|
|
|
#endif
|