mirror of
https://github.com/love2d/love.git
synced 2026-08-16 00:02:12 +02:00
Allow Fixture:setUserData and Fixture:getUserData to be called in coroutines (resolves issue #850.)
Bad things will still happen if you call them from a love Thread which didn't create the World and the Fixture object. Don't do it!
This commit is contained in:
@@ -64,21 +64,31 @@ void Reference::unref()
|
||||
}
|
||||
}
|
||||
|
||||
void Reference::push()
|
||||
void Reference::push(lua_State *newL)
|
||||
{
|
||||
if (idx != LUA_REFNIL)
|
||||
{
|
||||
luax_insist(L, LUA_REGISTRYINDEX, REFERENCE_TABLE_NAME);
|
||||
lua_rawgeti(L, -1, idx);
|
||||
lua_remove(L, -2);
|
||||
luax_insist(newL, LUA_REGISTRYINDEX, REFERENCE_TABLE_NAME);
|
||||
lua_rawgeti(newL, -1, idx);
|
||||
lua_remove(newL, -2);
|
||||
}
|
||||
else
|
||||
lua_pushnil(L);
|
||||
lua_pushnil(newL);
|
||||
}
|
||||
|
||||
lua_State *Reference::getL()
|
||||
void Reference::push()
|
||||
{
|
||||
push(L);
|
||||
}
|
||||
|
||||
lua_State *Reference::getL() const
|
||||
{
|
||||
return L;
|
||||
}
|
||||
|
||||
void Reference::setL(lua_State *newL)
|
||||
{
|
||||
L = newL;
|
||||
}
|
||||
|
||||
} // love
|
||||
|
||||
+17
-1
@@ -63,6 +63,14 @@ public:
|
||||
**/
|
||||
void unref();
|
||||
|
||||
/**
|
||||
* Pushes the referred value onto the stack of a different coroutine
|
||||
* in the same main Lua state.
|
||||
* THIS SHOULD NOT BE USED FOR DIFFERENT LUA STATES (created with
|
||||
* luaL_newstate)! Only with different coroutines!
|
||||
**/
|
||||
void push(lua_State *newL);
|
||||
|
||||
/**
|
||||
* Pushes the referred value onto the stack.
|
||||
**/
|
||||
@@ -72,7 +80,15 @@ public:
|
||||
* Gets the Lua state associated with this
|
||||
* reference.
|
||||
**/
|
||||
lua_State *getL();
|
||||
lua_State *getL() const;
|
||||
|
||||
/**
|
||||
* Associates a new Lua state with this reference.
|
||||
* THIS IS DANGEROUS! It is only designed to be
|
||||
* used with different coroutines from the same
|
||||
* main Lua state!
|
||||
**/
|
||||
void setL(lua_State *newL);
|
||||
|
||||
private:
|
||||
|
||||
|
||||
@@ -39,10 +39,10 @@ namespace box2d
|
||||
|
||||
Fixture::Fixture(Body *body, Shape *shape, float density)
|
||||
: body(body)
|
||||
, fixture(NULL)
|
||||
, fixture(nullptr)
|
||||
{
|
||||
data = new fixtureudata();
|
||||
data->ref = 0;
|
||||
data->ref = nullptr;
|
||||
b2FixtureDef def;
|
||||
def.shape = shape->shape;
|
||||
def.userData = (void *)data;
|
||||
@@ -65,13 +65,10 @@ Fixture::Fixture(b2Fixture *f)
|
||||
|
||||
Fixture::~Fixture()
|
||||
{
|
||||
if (data->ref != 0)
|
||||
if (data != nullptr)
|
||||
delete data->ref;
|
||||
|
||||
delete data;
|
||||
data = NULL;
|
||||
|
||||
fixture = NULL;
|
||||
}
|
||||
|
||||
Shape::Type Fixture::getType() const
|
||||
@@ -127,14 +124,14 @@ Body *Fixture::getBody() const
|
||||
Shape *Fixture::getShape() const
|
||||
{
|
||||
if (!fixture->GetShape())
|
||||
return NULL;
|
||||
return nullptr;
|
||||
|
||||
return new Shape(fixture->GetShape(), false);
|
||||
}
|
||||
|
||||
bool Fixture::isValid() const
|
||||
{
|
||||
return fixture != 0;
|
||||
return fixture != nullptr;
|
||||
}
|
||||
|
||||
void Fixture::setFilterData(int *v)
|
||||
@@ -230,21 +227,24 @@ int Fixture::setUserData(lua_State *L)
|
||||
{
|
||||
love::luax_assert_argc(L, 1, 1);
|
||||
|
||||
if (data->ref != 0)
|
||||
if (data->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.
|
||||
data->ref->setL(L);
|
||||
delete data->ref;
|
||||
data->ref = 0;
|
||||
}
|
||||
|
||||
data->ref = new Reference(L);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Fixture::getUserData(lua_State *L)
|
||||
{
|
||||
love::luax_assert_argc(L, 0, 0);
|
||||
if (data->ref != 0)
|
||||
data->ref->push();
|
||||
if (data->ref != nullptr)
|
||||
data->ref->push(L);
|
||||
else
|
||||
lua_pushnil(L);
|
||||
|
||||
@@ -311,10 +311,10 @@ void Fixture::destroy(bool implicit)
|
||||
return;
|
||||
}
|
||||
|
||||
if (!implicit && fixture != 0)
|
||||
if (!implicit && fixture != nullptr)
|
||||
body->body->DestroyFixture(fixture);
|
||||
Memoizer::remove(fixture);
|
||||
fixture = NULL;
|
||||
fixture = nullptr;
|
||||
|
||||
// Box2D fixture destroyed. Release its reference to the love Fixture.
|
||||
this->release();
|
||||
|
||||
Reference in New Issue
Block a user