mirror of
https://github.com/love2d/love.git
synced 2026-08-20 04:30:09 +02:00
Added all callbacks to World.
This commit is contained in:
@@ -23,6 +23,7 @@
|
|||||||
// LOVE
|
// LOVE
|
||||||
#include "Module.h"
|
#include "Module.h"
|
||||||
#include "Object.h"
|
#include "Object.h"
|
||||||
|
#include "Reference.h"
|
||||||
|
|
||||||
// STD
|
// STD
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
@@ -53,6 +54,19 @@ namespace love
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference * luax_refif(lua_State * L, int type)
|
||||||
|
{
|
||||||
|
Reference * r = 0;
|
||||||
|
|
||||||
|
// Create a reference only if the test succeeds.
|
||||||
|
if(lua_type(L, -1) == type)
|
||||||
|
r = new Reference(L);
|
||||||
|
else // Pop the value even if it fails (but also if it succeeds).
|
||||||
|
lua_pop(L, 1);
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
void luax_printstack(lua_State * L)
|
void luax_printstack(lua_State * L)
|
||||||
{
|
{
|
||||||
for(int i = 1;i<=lua_gettop(L);i++)
|
for(int i = 1;i<=lua_gettop(L);i++)
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ namespace love
|
|||||||
{
|
{
|
||||||
// Forward declarations.
|
// Forward declarations.
|
||||||
class Module;
|
class Module;
|
||||||
|
class Reference;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registries represent special tables which can be accessed with
|
* Registries represent special tables which can be accessed with
|
||||||
@@ -68,6 +69,14 @@ namespace love
|
|||||||
int value;
|
int value;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a reference to the top stack element (-1) if the value
|
||||||
|
* is of the specified type. If the value is incorrect, zero is returned.
|
||||||
|
*
|
||||||
|
* In any case, the top stack element is popped, regardless of its type.
|
||||||
|
**/
|
||||||
|
Reference * luax_refif(lua_State * L, int type);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prints the current contents of the stack. Only useful for debugging.
|
* Prints the current contents of the stack. Only useful for debugging.
|
||||||
* @param L The Lua state.
|
* @param L The Lua state.
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
|
|
||||||
#include "Shape.h"
|
#include "Shape.h"
|
||||||
#include "Contact.h"
|
#include "Contact.h"
|
||||||
|
#include <common/Reference.h>
|
||||||
|
|
||||||
namespace love
|
namespace love
|
||||||
{
|
{
|
||||||
@@ -30,74 +31,18 @@ namespace physics
|
|||||||
namespace box2d
|
namespace box2d
|
||||||
{
|
{
|
||||||
|
|
||||||
World::World(b2AABB aabb)
|
World::ContactCallback::ContactCallback()
|
||||||
: add_ref(0), meter(DEFAULT_METER)
|
: 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)
|
World::ContactCallback::~ContactCallback()
|
||||||
: add_ref(0), meter(DEFAULT_METER)
|
|
||||||
{
|
{
|
||||||
world = new b2World(scaleDown(aabb), scaleDown(gravity), sleep);
|
if(ref != 0)
|
||||||
world->SetContactListener(this);
|
delete ref;
|
||||||
add_contacts.reserve(10);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
World::~World()
|
void World::ContactCallback::add(World * world, const b2ContactPoint* point)
|
||||||
{
|
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* We must copy contacts, since we're not allowed to process
|
* We must copy contacts, since we're not allowed to process
|
||||||
@@ -105,33 +50,128 @@ namespace box2d
|
|||||||
* pretty much guarantees segfault. ^^
|
* pretty much guarantees segfault. ^^
|
||||||
**/
|
**/
|
||||||
|
|
||||||
if(add_ref != 0)
|
if(ref != 0)
|
||||||
add_contacts.push_back(new Contact(this, point));
|
contacts.push_back(new Contact(world, point));
|
||||||
}
|
}
|
||||||
|
|
||||||
int World::setCallback(lua_State * L)
|
void World::ContactCallback::process()
|
||||||
{
|
{
|
||||||
luax_assert_argc(L, 1, 1);
|
// Process contacts.
|
||||||
luax_assert_function(L, -1);
|
if(ref != 0)
|
||||||
|
|
||||||
if(add_ref != 0)
|
|
||||||
{
|
{
|
||||||
delete add_ref;
|
lua_State * L = ref->getL();
|
||||||
add_ref = 0;
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int World::getCallback(lua_State * L)
|
int World::getCallbacks(lua_State * L)
|
||||||
{
|
{
|
||||||
if(add_ref != 0)
|
add.ref ? add.ref->push() : lua_pushnil(L);
|
||||||
add_ref->push();
|
persist.ref ? persist.ref->push() : lua_pushnil(L);
|
||||||
else
|
remove.ref ? remove.ref->push() : lua_pushnil(L);
|
||||||
lua_pushnil(L);
|
result.ref ? result.ref->push() : lua_pushnil(L);
|
||||||
|
return lua_gettop(L);
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void World::setGravity(float x, float y)
|
void World::setGravity(float x, float y)
|
||||||
|
|||||||
@@ -60,16 +60,26 @@ namespace box2d
|
|||||||
friend class MouseJoint;
|
friend class MouseJoint;
|
||||||
friend class Body;
|
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:
|
private:
|
||||||
|
|
||||||
// Pointer to the Box2D world.
|
// Pointer to the Box2D world.
|
||||||
b2World * world;
|
b2World * world;
|
||||||
|
|
||||||
// Contact callbacks.
|
// Contact callbacks.
|
||||||
Reference * add_ref;
|
ContactCallback add, persist, remove, result;
|
||||||
|
|
||||||
// Contacts buffers.
|
|
||||||
std::vector<Contact *> add_contacts;
|
|
||||||
|
|
||||||
// The length of one meter in pixels.
|
// The length of one meter in pixels.
|
||||||
int meter;
|
int meter;
|
||||||
@@ -109,18 +119,22 @@ namespace box2d
|
|||||||
|
|
||||||
// From b2ContactListener
|
// From b2ContactListener
|
||||||
void Add(const b2ContactPoint* point);
|
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
|
* Receives up to four Lua functions as arguments. Each function is
|
||||||
* stores it for use when a collision occurs.
|
* 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
|
* Returns the functions previously set by setCallbacks.
|
||||||
* handling, or nil if there is none.
|
|
||||||
**/
|
**/
|
||||||
int getCallback(lua_State * L);
|
int getCallbacks(lua_State * L);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the current gravity of the World.
|
* Sets the current gravity of the World.
|
||||||
|
|||||||
@@ -40,18 +40,18 @@ namespace box2d
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int w_World_setCallback(lua_State * L)
|
int w_World_setCallbacks(lua_State * L)
|
||||||
{
|
{
|
||||||
World * t = luax_checkworld(L, 1);
|
World * t = luax_checkworld(L, 1);
|
||||||
lua_remove(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);
|
World * t = luax_checkworld(L, 1);
|
||||||
lua_remove(L, 1);
|
lua_remove(L, 1);
|
||||||
return t->getCallback(L);
|
return t->getCallbacks(L);
|
||||||
}
|
}
|
||||||
|
|
||||||
int w_World_setGravity(lua_State * L)
|
int w_World_setGravity(lua_State * L)
|
||||||
@@ -116,8 +116,8 @@ namespace box2d
|
|||||||
|
|
||||||
static const luaL_Reg functions[] = {
|
static const luaL_Reg functions[] = {
|
||||||
{ "update", w_World_update },
|
{ "update", w_World_update },
|
||||||
{ "setCallback", w_World_setCallback },
|
{ "setCallbacks", w_World_setCallbacks },
|
||||||
{ "getCallback", w_World_getCallback },
|
{ "getCallbacks", w_World_getCallbacks },
|
||||||
{ "setGravity", w_World_setGravity },
|
{ "setGravity", w_World_setGravity },
|
||||||
{ "getGravity", w_World_getGravity },
|
{ "getGravity", w_World_getGravity },
|
||||||
{ "setAllowSleep", w_World_setAllowSleep },
|
{ "setAllowSleep", w_World_setAllowSleep },
|
||||||
|
|||||||
@@ -33,8 +33,8 @@ namespace box2d
|
|||||||
{
|
{
|
||||||
World * luax_checkworld(lua_State * L, int idx);
|
World * luax_checkworld(lua_State * L, int idx);
|
||||||
int w_World_update(lua_State * L);
|
int w_World_update(lua_State * L);
|
||||||
int w_World_setCallback(lua_State * L);
|
int w_World_setCallbacks(lua_State * L);
|
||||||
int w_World_getCallback(lua_State * L);
|
int w_World_getCallbacks(lua_State * L);
|
||||||
int w_World_setGravity(lua_State * L);
|
int w_World_setGravity(lua_State * L);
|
||||||
int w_World_getGravity(lua_State * L);
|
int w_World_getGravity(lua_State * L);
|
||||||
int w_World_setAllowSleep(lua_State * L);
|
int w_World_setAllowSleep(lua_State * L);
|
||||||
|
|||||||
Reference in New Issue
Block a user