diff --git a/src/api/physics.c b/src/api/physics.c index e8effa49..db22eed4 100644 --- a/src/api/physics.c +++ b/src/api/physics.c @@ -57,6 +57,7 @@ int l_lovrPhysicsNewWorld(lua_State* L) { } World* world = lovrWorldCreate(xg, yg, zg, allowSleep, tags, tagCount); luax_pushobject(L, world); + lovrRelease(world); return 1; } diff --git a/src/api/types/world.c b/src/api/types/world.c index f7d85191..3d7e5e10 100644 --- a/src/api/types/world.c +++ b/src/api/types/world.c @@ -44,6 +44,7 @@ int l_lovrWorldNewCollider(lua_State* L) { float z = luaL_optnumber(L, 4, 0); Collider* collider = lovrColliderCreate(world, x, y, z); luax_pushobject(L, collider); + lovrRelease(collider); return 1; } @@ -58,6 +59,7 @@ int l_lovrWorldNewBoxCollider(lua_State* L) { Collider* collider = lovrColliderCreate(world, x, y, z); lovrColliderAddShape(collider, lovrBoxShapeCreate(sx, sy, sz)); luax_pushobject(L, collider); + lovrRelease(collider); return 1; } @@ -71,6 +73,7 @@ int l_lovrWorldNewCapsuleCollider(lua_State* L) { Collider* collider = lovrColliderCreate(world, x, y, z); lovrColliderAddShape(collider, lovrCapsuleShapeCreate(radius, length)); luax_pushobject(L, collider); + lovrRelease(collider); return 1; } @@ -84,6 +87,7 @@ int l_lovrWorldNewCylinderCollider(lua_State* L) { Collider* collider = lovrColliderCreate(world, x, y, z); lovrColliderAddShape(collider, lovrCylinderShapeCreate(radius, length)); luax_pushobject(L, collider); + lovrRelease(collider); return 1; } @@ -96,6 +100,7 @@ int l_lovrWorldNewSphereCollider(lua_State* L) { Collider* collider = lovrColliderCreate(world, x, y, z); lovrColliderAddShape(collider, lovrSphereShapeCreate(radius)); luax_pushobject(L, collider); + lovrRelease(collider); return 1; } diff --git a/src/physics/physics.c b/src/physics/physics.c index 5abe1fd2..e842a63d 100644 --- a/src/physics/physics.c +++ b/src/physics/physics.c @@ -85,6 +85,12 @@ void lovrWorldDestroyData(World* world) { world->space = NULL; } + while (world->head) { + Collider* next = world->head->next; + lovrColliderDestroyData(world->head); + world->head = next; + } + if (world->id) { dWorldDestroy(world->id); 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) { - lovrAssert(world, "No world specified"); Collider* collider = lovrAlloc(Collider, lovrColliderDestroy); if (!collider) return NULL; @@ -283,6 +288,18 @@ Collider* lovrColliderCreate(World* world, float x, float y, float 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; } @@ -295,10 +312,20 @@ void lovrColliderDestroy(void* ref) { } void lovrColliderDestroyData(Collider* collider) { - if (collider->body) { - dBodyDestroy(collider->body); - collider->body = NULL; + if (!collider->body) { + return; } + + 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) { diff --git a/src/physics/physics.h b/src/physics/physics.h index 406bd097..233d7c21 100644 --- a/src/physics/physics.h +++ b/src/physics/physics.h @@ -25,6 +25,8 @@ typedef enum { JOINT_SLIDER } JointType; +typedef struct Collider Collider; + typedef struct { Ref ref; dWorldID id; @@ -33,19 +35,22 @@ typedef struct { vec_void_t overlaps; map_int_t tags; uint16_t masks[MAX_TAGS]; + Collider* head; } World; -typedef struct { +struct Collider { Ref ref; dBodyID body; World* world; + Collider* prev; + Collider* next; void* userdata; int tag; vec_void_t shapes; vec_void_t joints; float friction; float restitution; -} Collider; +}; typedef struct { Ref ref;