Added all callbacks to World.

This commit is contained in:
rude
2009-08-15 14:29:47 +02:00
parent 579f9c75db
commit d4a97d49f3
6 changed files with 174 additions and 97 deletions
+119 -79
View File
@@ -22,6 +22,7 @@
#include "Shape.h"
#include "Contact.h"
#include <common/Reference.h>
namespace love
{
@@ -30,74 +31,18 @@ namespace physics
namespace box2d
{
World::World(b2AABB aabb)
: add_ref(0), meter(DEFAULT_METER)
World::ContactCallback::ContactCallback()
: ref(0)
{
world = new b2World(scaleDown(aabb), b2Vec2(0,0), true);
world->SetContactListener(this);
add_contacts.reserve(10);
}
World::World(b2AABB aabb, b2Vec2 gravity, bool sleep)
: add_ref(0), meter(DEFAULT_METER)
World::ContactCallback::~ContactCallback()
{
world = new b2World(scaleDown(aabb), scaleDown(gravity), sleep);
world->SetContactListener(this);
add_contacts.reserve(10);
if(ref != 0)
delete ref;
}
World::~World()
{
if(add_ref != 0)
delete add_ref;
delete world;
}
void World::update(float dt)
{
world->Step(dt, 10);
// Process contacts.
if(add_ref != 0)
{
lua_State * L = add_ref->getL();
for(int i = 0;i<(int)add_contacts.size();i++)
{
// Push the function.
add_ref->push();
// Push first userdata.
{
shapeudata * d = (shapeudata *)(add_contacts[i]->point.shape1->GetUserData());
if(d->ref != 0)
d->ref->push();
else
lua_pushnil(L);
}
// Push first userdata.
{
shapeudata * d = (shapeudata *)(add_contacts[i]->point.shape2->GetUserData());
if(d->ref != 0)
d->ref->push();
else
lua_pushnil(L);
}
luax_newtype(L, "Contact", (PHYSICS_CONTACT_T), (void*)add_contacts[i], false);
lua_call(L, 3, 0);
}
// Clear contacts.
for(int i = 0;i<(int)add_contacts.size();i++)
delete add_contacts[i];
add_contacts.clear();
}
}
void World::Add(const b2ContactPoint* point)
void World::ContactCallback::add(World * world, const b2ContactPoint* point)
{
/**
* We must copy contacts, since we're not allowed to process
@@ -105,33 +50,128 @@ namespace box2d
* pretty much guarantees segfault. ^^
**/
if(add_ref != 0)
add_contacts.push_back(new Contact(this, point));
if(ref != 0)
contacts.push_back(new Contact(world, point));
}
int World::setCallback(lua_State * L)
void World::ContactCallback::process()
{
luax_assert_argc(L, 1, 1);
luax_assert_function(L, -1);
if(add_ref != 0)
// Process contacts.
if(ref != 0)
{
delete add_ref;
add_ref = 0;
lua_State * L = ref->getL();
for(int i = 0;i<(int)contacts.size();i++)
{
// Push the function.
ref->push();
// Push first userdata.
{
shapeudata * d = (shapeudata *)(contacts[i]->point.shape1->GetUserData());
if(d->ref != 0)
d->ref->push();
else
lua_pushnil(L);
}
// Push first userdata.
{
shapeudata * d = (shapeudata *)(contacts[i]->point.shape2->GetUserData());
if(d->ref != 0)
d->ref->push();
else
lua_pushnil(L);
}
luax_newtype(L, "Contact", (PHYSICS_CONTACT_T), (void*)contacts[i], false);
lua_call(L, 3, 0);
}
// Clear contacts.
for(int i = 0;i<(int)contacts.size();i++)
delete contacts[i];
contacts.clear();
}
}
World::World(b2AABB aabb)
: meter(DEFAULT_METER)
{
world = new b2World(scaleDown(aabb), b2Vec2(0,0), true);
world->SetContactListener(this);
}
World::World(b2AABB aabb, b2Vec2 gravity, bool sleep)
: meter(DEFAULT_METER)
{
world = new b2World(scaleDown(aabb), scaleDown(gravity), sleep);
world->SetContactListener(this);
}
World::~World()
{
delete world;
}
void World::update(float dt)
{
world->Step(dt, 10);
add.process();
persist.process();
remove.process();
result.process();
}
void World::Add(const b2ContactPoint* point)
{
add.add(this, point);
}
void World::Persist(const b2ContactPoint* point)
{
persist.add(this, point);
}
void World::Remove(const b2ContactPoint* point)
{
remove.add(this, point);
}
void World::Result(const b2ContactPoint* point)
{
result.add(this, point);
}
int World::setCallbacks(lua_State * L)
{
int n = lua_gettop(L);
luax_assert_argc(L, 1, 4);
switch(n)
{
case 4:
result.ref = luax_refif(L, LUA_TFUNCTION);
case 3:
remove.ref = luax_refif(L, LUA_TFUNCTION);
case 2:
persist.ref = luax_refif(L, LUA_TFUNCTION);
case 1:
add.ref = luax_refif(L, LUA_TFUNCTION);
}
add_ref = new Reference(L);
return 0;
}
int World::getCallback(lua_State * L)
int World::getCallbacks(lua_State * L)
{
if(add_ref != 0)
add_ref->push();
else
lua_pushnil(L);
return 1;
add.ref ? add.ref->push() : lua_pushnil(L);
persist.ref ? persist.ref->push() : lua_pushnil(L);
remove.ref ? remove.ref->push() : lua_pushnil(L);
result.ref ? result.ref->push() : lua_pushnil(L);
return lua_gettop(L);
}
void World::setGravity(float x, float y)
+24 -10
View File
@@ -60,16 +60,26 @@ namespace box2d
friend class MouseJoint;
friend class Body;
public:
class ContactCallback
{
public:
Reference * ref;
std::vector<Contact *> contacts;
ContactCallback();
~ContactCallback();
void add(World * world, const b2ContactPoint* point);
void process();
};
private:
// Pointer to the Box2D world.
b2World * world;
// Contact callbacks.
Reference * add_ref;
// Contacts buffers.
std::vector<Contact *> add_contacts;
ContactCallback add, persist, remove, result;
// The length of one meter in pixels.
int meter;
@@ -109,18 +119,22 @@ namespace box2d
// From b2ContactListener
void Add(const b2ContactPoint* point);
void Persist(const b2ContactPoint* point);
void Remove(const b2ContactPoint* point);
void Result(const b2ContactPoint* point);
/**
* Recieves a Lua function as argument, and
* stores it for use when a collision occurs.
* Receives up to four Lua functions as arguments. Each function is
* collision callback for the four events (in order): add, persist,
* remove and result. The value "nil" is accepted if one or more events
* are uninteresting.
**/
int setCallback(lua_State * L);
int setCallbacks(lua_State * L);
/**
* Returns the stored Lua function for collision
* handling, or nil if there is none.
* Returns the functions previously set by setCallbacks.
**/
int getCallback(lua_State * L);
int getCallbacks(lua_State * L);
/**
* Sets the current gravity of the World.
+6 -6
View File
@@ -40,18 +40,18 @@ namespace box2d
return 0;
}
int w_World_setCallback(lua_State * L)
int w_World_setCallbacks(lua_State * L)
{
World * t = luax_checkworld(L, 1);
lua_remove(L, 1);
return t->setCallback(L);
return t->setCallbacks(L);
}
int w_World_getCallback(lua_State * L)
int w_World_getCallbacks(lua_State * L)
{
World * t = luax_checkworld(L, 1);
lua_remove(L, 1);
return t->getCallback(L);
return t->getCallbacks(L);
}
int w_World_setGravity(lua_State * L)
@@ -116,8 +116,8 @@ namespace box2d
static const luaL_Reg functions[] = {
{ "update", w_World_update },
{ "setCallback", w_World_setCallback },
{ "getCallback", w_World_getCallback },
{ "setCallbacks", w_World_setCallbacks },
{ "getCallbacks", w_World_getCallbacks },
{ "setGravity", w_World_setGravity },
{ "getGravity", w_World_getGravity },
{ "setAllowSleep", w_World_setAllowSleep },
+2 -2
View File
@@ -33,8 +33,8 @@ namespace box2d
{
World * luax_checkworld(lua_State * L, int idx);
int w_World_update(lua_State * L);
int w_World_setCallback(lua_State * L);
int w_World_getCallback(lua_State * L);
int w_World_setCallbacks(lua_State * L);
int w_World_getCallbacks(lua_State * L);
int w_World_setGravity(lua_State * L);
int w_World_getGravity(lua_State * L);
int w_World_setAllowSleep(lua_State * L);