Browse Source

Added Body:setUserData and Body:getUserData (resolves issue #853_

Alex Szpakowski 11 years ago
parent
commit
fe5e7c17e7

+ 1 - 1
src/common/Reference.cpp

@@ -26,7 +26,7 @@ namespace love
 const char REFERENCE_TABLE_NAME[] = "love-references";
 
 Reference::Reference()
-	: L(0)
+	: L(nullptr)
 	, idx(LUA_REFNIL)
 {
 }

+ 3 - 3
src/modules/graphics/opengl/Canvas.cpp

@@ -129,7 +129,7 @@ struct FramebufferStrategyGL3 : public FramebufferStrategy
 		glGenRenderbuffers(1, &stencil);
 		glBindRenderbuffer(GL_RENDERBUFFER, stencil);
 
-		if (samples > 0)
+		if (samples > 1)
 			glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, GL_DEPTH_STENCIL, width, height);
 		else
 			glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_STENCIL, width, height);
@@ -249,7 +249,7 @@ struct FramebufferStrategyPackedEXT : public FramebufferStrategy
 		glGenRenderbuffersEXT(1, &stencil);
 		glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, stencil);
 
-		if (samples > 0)
+		if (samples > 1)
 		{
 			glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, samples,
 			                                    GL_DEPTH_STENCIL, width, height);
@@ -358,7 +358,7 @@ struct FramebufferStrategyEXT : public FramebufferStrategyPackedEXT
 		glGenRenderbuffersEXT(1, &stencil);
 		glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, stencil);
 
-		if (samples > 0)
+		if (samples > 1)
 		{
 			glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, samples,
 			                                    GL_STENCIL_INDEX, width, height);

+ 43 - 1
src/modules/physics/box2d/Body.cpp

@@ -37,10 +37,14 @@ namespace box2d
 
 Body::Body(World *world, b2Vec2 p, Body::Type type)
 	: world(world)
+	, udata(nullptr)
 {
+	udata = new bodyudata();
+	udata->ref = nullptr;
 	world->retain();
 	b2BodyDef def;
 	def.position = Physics::scaleDown(p);
+	def.userData = (void *) udata;
 	body = world->world->CreateBody(&def);
 	// Box2D body holds a reference to the love Body.
 	this->retain();
@@ -50,7 +54,9 @@ Body::Body(World *world, b2Vec2 p, Body::Type type)
 
 Body::Body(b2Body *b)
 	: body(b)
+	, udata(nullptr)
 {
+	udata = (bodyudata *) b->GetUserData();
 	world = (World *)Memoizer::find(b->GetWorld());
 	world->retain();
 	// Box2D body holds a reference to the love Body.
@@ -60,8 +66,10 @@ Body::Body(b2Body *b)
 
 Body::~Body()
 {
+	if (udata != nullptr)
+		delete udata->ref;
+	delete udata;
 	world->release();
-	body = 0;
 }
 
 float Body::getX()
@@ -469,6 +477,40 @@ void Body::destroy()
 	this->release();
 }
 
+int Body::setUserData(lua_State *L)
+{
+	love::luax_assert_argc(L, 1, 1);
+
+	if (udata == nullptr)
+	{
+		udata = new bodyudata();
+		body->SetUserData((void *) udata);
+	}
+
+	if (udata->ref != nullptr)
+	{
+		// We set the Reference's lua_State to this one before deleting it, so
+		// it unrefs using the current lua_State's stack. This is necessary
+		// if setUserData is called in a coroutine.
+		udata->ref->setL(L);
+		delete udata->ref;
+	}
+
+	udata->ref = new Reference(L);
+
+	return 0;
+}
+
+int Body::getUserData(lua_State *L)
+{
+	if (udata != nullptr && udata->ref != nullptr)
+		udata->ref->push(L);
+	else
+		lua_pushnil(L);
+
+	return 1;
+}
+
 } // box2d
 } // physics
 } // love

+ 26 - 1
src/modules/physics/box2d/Body.h

@@ -41,6 +41,16 @@ class World;
 class Shape;
 class Fixture;
 
+/**
+ * This struct is stored in a void pointer in the Box2D Body class. For now, all
+ * we need is a Lua reference to arbitrary data, but we might need more later.
+ **/
+struct bodyudata
+{
+	// Reference to arbitrary data.
+	Reference *ref;
+};
+
 /**
  * A Body is an entity which has position and orientation
  * in world space. A Body does have collision geometry
@@ -388,6 +398,18 @@ public:
 	 **/
 	void destroy();
 
+	/**
+	 * This function stores an in-C reference to
+	 * arbitrary Lua data in the Box2D Body object.
+	 **/
+	int setUserData(lua_State *L);
+
+	/**
+	 * Gets the data set with setData. If no
+	 * data is set, nil is returned.
+	 **/
+	int getUserData(lua_State *L);
+
 private:
 
 	/**
@@ -408,7 +430,10 @@ private:
 	// This ensures that a World only can be destroyed
 	// once all bodies have been destroyed too.
 	World *world;
-};
+
+	bodyudata *udata;
+
+}; // Body
 
 } // box2d
 } // physics

+ 0 - 3
src/modules/physics/box2d/Fixture.h

@@ -123,9 +123,6 @@ public:
 	/**
 	 * This function stores an in-C reference to
 	 * arbitrary Lua data in the Box2D Fixture object.
-	 *
-	 * The data set here will be passed to the collision
-	 * handler when collisions occur.
 	 **/
 	int setUserData(lua_State *L);
 

+ 16 - 0
src/modules/physics/box2d/wrap_Body.cpp

@@ -538,6 +538,20 @@ int w_Body_destroy(lua_State *L)
 	return 0;
 }
 
+int w_Body_setUserData(lua_State *L)
+{
+	Body *t = luax_checkbody(L, 1);
+	lua_remove(L, 1);
+	return t->setUserData(L);
+}
+
+int w_Body_getUserData(lua_State *L)
+{
+	Body *t = luax_checkbody(L, 1);
+	lua_remove(L, 1);
+	return t->getUserData(L);
+}
+
 static const luaL_Reg functions[] =
 {
 	{ "getX", w_Body_getX },
@@ -592,6 +606,8 @@ static const luaL_Reg functions[] =
 	{ "isFixedRotation", w_Body_isFixedRotation },
 	{ "getFixtureList", w_Body_getFixtureList },
 	{ "destroy", w_Body_destroy },
+	{ "setUserData", w_Body_setUserData },
+	{ "getUserData", w_Body_getUserData },
 	{ 0, 0 }
 };
 

+ 2 - 0
src/modules/physics/box2d/wrap_Body.h

@@ -85,6 +85,8 @@ int w_Body_setFixedRotation(lua_State *L);
 int w_Body_isFixedRotation(lua_State *L);
 int w_Body_getFixtureList(lua_State *L);
 int w_Body_destroy(lua_State *L);
+int w_Body_setUserData(lua_State *L);
+int w_Body_getUserData(lua_State *L);
 extern "C" int luaopen_body(lua_State *L);
 
 } // box2d