Fix world/collider memory leaks;

This commit is contained in:
bjorn 2018-08-18 21:16:19 -07:00
parent d2b6def5c2
commit 1f00948da0
4 changed files with 44 additions and 6 deletions

View File

@ -57,6 +57,7 @@ int l_lovrPhysicsNewWorld(lua_State* L) {
} }
World* world = lovrWorldCreate(xg, yg, zg, allowSleep, tags, tagCount); World* world = lovrWorldCreate(xg, yg, zg, allowSleep, tags, tagCount);
luax_pushobject(L, world); luax_pushobject(L, world);
lovrRelease(world);
return 1; return 1;
} }

View File

@ -44,6 +44,7 @@ int l_lovrWorldNewCollider(lua_State* L) {
float z = luaL_optnumber(L, 4, 0); float z = luaL_optnumber(L, 4, 0);
Collider* collider = lovrColliderCreate(world, x, y, z); Collider* collider = lovrColliderCreate(world, x, y, z);
luax_pushobject(L, collider); luax_pushobject(L, collider);
lovrRelease(collider);
return 1; return 1;
} }
@ -58,6 +59,7 @@ int l_lovrWorldNewBoxCollider(lua_State* L) {
Collider* collider = lovrColliderCreate(world, x, y, z); Collider* collider = lovrColliderCreate(world, x, y, z);
lovrColliderAddShape(collider, lovrBoxShapeCreate(sx, sy, sz)); lovrColliderAddShape(collider, lovrBoxShapeCreate(sx, sy, sz));
luax_pushobject(L, collider); luax_pushobject(L, collider);
lovrRelease(collider);
return 1; return 1;
} }
@ -71,6 +73,7 @@ int l_lovrWorldNewCapsuleCollider(lua_State* L) {
Collider* collider = lovrColliderCreate(world, x, y, z); Collider* collider = lovrColliderCreate(world, x, y, z);
lovrColliderAddShape(collider, lovrCapsuleShapeCreate(radius, length)); lovrColliderAddShape(collider, lovrCapsuleShapeCreate(radius, length));
luax_pushobject(L, collider); luax_pushobject(L, collider);
lovrRelease(collider);
return 1; return 1;
} }
@ -84,6 +87,7 @@ int l_lovrWorldNewCylinderCollider(lua_State* L) {
Collider* collider = lovrColliderCreate(world, x, y, z); Collider* collider = lovrColliderCreate(world, x, y, z);
lovrColliderAddShape(collider, lovrCylinderShapeCreate(radius, length)); lovrColliderAddShape(collider, lovrCylinderShapeCreate(radius, length));
luax_pushobject(L, collider); luax_pushobject(L, collider);
lovrRelease(collider);
return 1; return 1;
} }
@ -96,6 +100,7 @@ int l_lovrWorldNewSphereCollider(lua_State* L) {
Collider* collider = lovrColliderCreate(world, x, y, z); Collider* collider = lovrColliderCreate(world, x, y, z);
lovrColliderAddShape(collider, lovrSphereShapeCreate(radius)); lovrColliderAddShape(collider, lovrSphereShapeCreate(radius));
luax_pushobject(L, collider); luax_pushobject(L, collider);
lovrRelease(collider);
return 1; return 1;
} }

View File

@ -85,6 +85,12 @@ void lovrWorldDestroyData(World* world) {
world->space = NULL; world->space = NULL;
} }
while (world->head) {
Collider* next = world->head->next;
lovrColliderDestroyData(world->head);
world->head = next;
}
if (world->id) { if (world->id) {
dWorldDestroy(world->id); dWorldDestroy(world->id);
world->id = NULL; world->id = NULL;
@ -268,7 +274,6 @@ int lovrWorldIsCollisionEnabledBetween(World* world, const char* tag1, const cha
} }
Collider* lovrColliderCreate(World* world, float x, float y, float z) { Collider* lovrColliderCreate(World* world, float x, float y, float z) {
lovrAssert(world, "No world specified");
Collider* collider = lovrAlloc(Collider, lovrColliderDestroy); Collider* collider = lovrAlloc(Collider, lovrColliderDestroy);
if (!collider) return NULL; if (!collider) return NULL;
@ -283,6 +288,18 @@ Collider* lovrColliderCreate(World* world, float x, float y, float z) {
lovrColliderSetPosition(collider, x, y, z); lovrColliderSetPosition(collider, x, y, z);
// Adjust the world's collider list
if (!collider->world->head) {
collider->world->head = collider;
} else {
collider->next = collider->world->head;
collider->next->prev = collider;
collider->world->head = collider;
}
// The world owns a reference to the collider
lovrRetain(collider);
return collider; return collider;
} }
@ -295,10 +312,20 @@ void lovrColliderDestroy(void* ref) {
} }
void lovrColliderDestroyData(Collider* collider) { void lovrColliderDestroyData(Collider* collider) {
if (collider->body) { if (!collider->body) {
dBodyDestroy(collider->body); return;
collider->body = NULL;
} }
dBodyDestroy(collider->body);
collider->body = NULL;
if (collider->next) collider->next->prev = collider->prev;
if (collider->prev) collider->prev->next = collider->next;
if (collider->world->head == collider) collider->world->head = collider->next;
collider->next = collider->prev = NULL;
// If the Collider is destroyed, the world lets go of its reference to this Collider
lovrRelease(collider);
} }
World* lovrColliderGetWorld(Collider* collider) { World* lovrColliderGetWorld(Collider* collider) {

View File

@ -25,6 +25,8 @@ typedef enum {
JOINT_SLIDER JOINT_SLIDER
} JointType; } JointType;
typedef struct Collider Collider;
typedef struct { typedef struct {
Ref ref; Ref ref;
dWorldID id; dWorldID id;
@ -33,19 +35,22 @@ typedef struct {
vec_void_t overlaps; vec_void_t overlaps;
map_int_t tags; map_int_t tags;
uint16_t masks[MAX_TAGS]; uint16_t masks[MAX_TAGS];
Collider* head;
} World; } World;
typedef struct { struct Collider {
Ref ref; Ref ref;
dBodyID body; dBodyID body;
World* world; World* world;
Collider* prev;
Collider* next;
void* userdata; void* userdata;
int tag; int tag;
vec_void_t shapes; vec_void_t shapes;
vec_void_t joints; vec_void_t joints;
float friction; float friction;
float restitution; float restitution;
} Collider; };
typedef struct { typedef struct {
Ref ref; Ref ref;