love.physics: simplify Body and Shape API.

#1130

- Shapes are now directly attached to Bodies when they're created (similar to love 0.7 and older).
- Fixtures are removed.
- All methods that were in Fixtures now exist in Shapes.
- All APIs that used or returned a Fixture now do the same with a Shape.

- Add new love.physics.new*Shape variants that take a Body as the first parameter.
- Deprecate the new*Shape APIs that don't take a Body.
- Deprecate love.physics.newFixture (the deprecated function now returns a Shape).
- Replace Body:getFixture and Body:getFixtures with Body:getShape and Body:getShapes (Body:getFixtures is deprecated).
- Replace World:queryFixturesInArea and World:getFixturesInArea with World:queryShapesInArea and World:getShapesInArea (queryFixturesInArea is deprecated).
- Replace Contact:getFixtures with Contact:getShapes (Contact:getFixtures is deprecated).
- Replace all love.physics callback Fixture parameters with Shape parameters.
- Deprecate ChainShape:getChildEdge.
This commit is contained in:
Sasha Szpakowski
2023-10-07 15:17:24 -03:00
parent 2702004bb2
commit ac9ae82524
35 changed files with 1137 additions and 1236 deletions
+11 -11
View File
@@ -23,12 +23,12 @@
#include "common/math.h"
#include "Shape.h"
#include "Fixture.h"
#include "World.h"
#include "Physics.h"
// Needed for luax_pushjoint.
#include "wrap_Joint.h"
#include "wrap_Shape.h"
namespace love
{
@@ -461,20 +461,20 @@ World *Body::getWorld() const
return world;
}
Fixture *Body::getFixture() const
Shape *Body::getShape() const
{
b2Fixture *f = body->GetFixtureList();
if (f == nullptr)
return nullptr;
Fixture *fixture = (Fixture *)(f->GetUserData().pointer);
if (!fixture)
throw love::Exception("A fixture has escaped Memoizer!");
Shape *shape = (Shape *)(f->GetUserData().pointer);
if (!shape)
throw love::Exception("A Shape has escaped Memoizer!");
return fixture;
return shape;
}
int Body::getFixtures(lua_State *L) const
int Body::getShapes(lua_State *L) const
{
lua_newtable(L);
b2Fixture *f = body->GetFixtureList();
@@ -483,10 +483,10 @@ int Body::getFixtures(lua_State *L) const
{
if (!f)
break;
Fixture *fixture = (Fixture *)(f->GetUserData().pointer);
if (!fixture)
throw love::Exception("A fixture has escaped Memoizer!");
luax_pushtype(L, fixture);
Shape *shape = (Shape *)(f->GetUserData().pointer);
if (!shape)
throw love::Exception("A Shape has escaped Memoizer!");
luax_pushshape(L, shape);
lua_rawseti(L, -2, i);
i++;
}
+4 -7
View File
@@ -39,7 +39,6 @@ namespace box2d
// Forward declarations.
class World;
class Shape;
class Fixture;
/**
* A Body is an entity which has position and orientation
@@ -57,7 +56,6 @@ public:
friend class CircleShape;
friend class PolygonShape;
friend class Shape;
friend class Fixture;
// Public because joints et al ask for b2body
b2Body *body;
@@ -391,15 +389,14 @@ public:
World *getWorld() const;
/**
* Gets the first Fixture attached to this Body.
* Gets the first Shape attached to this Body.
**/
Fixture *getFixture() const;
Shape *getShape() const;
/**
* Get an array of all the Fixtures attached to this Body.
* @return An array of Fixtures.
* Get an array of all the Shapes attached to this Body.
**/
int getFixtures(lua_State *L) const;
int getShapes(lua_State *L) const;
/**
* Get an array of all Joints attached to this Body.
+14 -15
View File
@@ -34,8 +34,8 @@ namespace box2d
love::Type ChainShape::type("ChainShape", &Shape::type);
ChainShape::ChainShape(b2ChainShape *c, bool own)
: Shape(c, own)
ChainShape::ChainShape(Body *body, const b2ChainShape &c)
: Shape(body, c)
{
}
@@ -45,6 +45,7 @@ ChainShape::~ChainShape()
void ChainShape::setNextVertex(float x, float y)
{
throwIfShapeNotValid();
b2Vec2 v(x, y);
b2ChainShape *c = (b2ChainShape *)shape;
c->m_nextVertex = Physics::scaleDown(v);
@@ -52,6 +53,7 @@ void ChainShape::setNextVertex(float x, float y)
void ChainShape::setPreviousVertex(float x, float y)
{
throwIfShapeNotValid();
b2Vec2 v(x, y);
b2ChainShape *c = (b2ChainShape *)shape;
c->m_prevVertex = Physics::scaleDown(v);
@@ -59,44 +61,40 @@ void ChainShape::setPreviousVertex(float x, float y)
b2Vec2 ChainShape::getNextVertex() const
{
throwIfShapeNotValid();
b2ChainShape *c = (b2ChainShape *)shape;
return Physics::scaleUp(c->m_nextVertex);
}
b2Vec2 ChainShape::getPreviousVertex() const
{
throwIfShapeNotValid();
b2ChainShape *c = (b2ChainShape *)shape;
return Physics::scaleUp(c->m_prevVertex);
}
EdgeShape *ChainShape::getChildEdge(int index) const
{
throwIfShapeNotValid();
b2ChainShape *c = (b2ChainShape *)shape;
b2EdgeShape *e = new b2EdgeShape;
try
{
c->GetChildEdge(e, index);
}
catch (love::Exception &)
{
delete e;
throw;
}
b2EdgeShape e;
c->GetChildEdge(&e, index);
return new EdgeShape(e, true);
return new EdgeShape(nullptr, e);
}
int ChainShape::getVertexCount() const
{
throwIfShapeNotValid();
b2ChainShape *c = (b2ChainShape *)shape;
return c->m_count;
}
b2Vec2 ChainShape::getPoint(int index) const
{
throwIfShapeNotValid();
b2ChainShape *c = (b2ChainShape *)shape;
if (index < 0 || index >= c->m_count)
throw love::Exception("Physics error: index out of bounds");
@@ -106,6 +104,7 @@ b2Vec2 ChainShape::getPoint(int index) const
const b2Vec2 *ChainShape::getPoints() const
{
throwIfShapeNotValid();
b2ChainShape *c = (b2ChainShape *)shape;
return c->m_vertices;
}
+1 -1
View File
@@ -45,7 +45,7 @@ public:
* Create a new ChainShape from a Box2D chain shape.
* @param c The chain shape.
**/
ChainShape(b2ChainShape *c, bool own = true);
ChainShape(Body *body, const b2ChainShape &c);
virtual ~ChainShape();
+6 -2
View File
@@ -34,8 +34,8 @@ namespace box2d
love::Type CircleShape::type("CircleShape", &Shape::type);
CircleShape::CircleShape(b2CircleShape *c, bool own)
: Shape(c, own)
CircleShape::CircleShape(Body *body, const b2CircleShape &c)
: Shape(body, c)
{
}
@@ -45,16 +45,19 @@ CircleShape::~CircleShape()
float CircleShape::getRadius() const
{
throwIfShapeNotValid();
return Physics::scaleUp(shape->m_radius);
}
void CircleShape::setRadius(float r)
{
throwIfShapeNotValid();
shape->m_radius = Physics::scaleDown(r);
}
void CircleShape::getPoint(float &x_o, float &y_o) const
{
throwIfShapeNotValid();
b2CircleShape *c = (b2CircleShape *) shape;
x_o = Physics::scaleUp(c->m_p.x);
y_o = Physics::scaleUp(c->m_p.y);
@@ -62,6 +65,7 @@ void CircleShape::getPoint(float &x_o, float &y_o) const
void CircleShape::setPoint(float x, float y)
{
throwIfShapeNotValid();
b2CircleShape *c = (b2CircleShape *) shape;
c->m_p = Physics::scaleDown(b2Vec2(x, y));
}
+1 -1
View File
@@ -50,7 +50,7 @@ public:
* Create a new CircleShape from the a Box2D CircleShape definition.
* @param c The CircleShape definition.
**/
CircleShape(b2CircleShape *c, bool own = true);
CircleShape(Body *body, const b2CircleShape &c);
virtual ~CircleShape();
+8 -9
View File
@@ -35,7 +35,6 @@ Contact::Contact(World *world, b2Contact *contact)
: contact(contact)
, world(world)
{
//contact->user
world->registerObject(contact, this);
}
@@ -46,16 +45,16 @@ Contact::~Contact()
void Contact::invalidate()
{
if (contact != NULL)
if (contact != nullptr)
{
world->unregisterObject(contact);
contact = NULL;
contact = nullptr;
}
}
bool Contact::isValid()
{
return contact != NULL;
return contact != nullptr;
}
int Contact::getPositions(lua_State *L)
@@ -144,13 +143,13 @@ void Contact::getChildren(int &childA, int &childB)
childB = contact->GetChildIndexB();
}
void Contact::getFixtures(Fixture *&fixtureA, Fixture *&fixtureB)
void Contact::getShapes(Shape *&shapeA, Shape *&shapeB)
{
fixtureA = (Fixture *) (contact->GetFixtureA()->GetUserData().pointer);
fixtureB = (Fixture *) (contact->GetFixtureB()->GetUserData().pointer);
shapeA = (Shape *) (contact->GetFixtureA()->GetUserData().pointer);
shapeB = (Shape *) (contact->GetFixtureB()->GetUserData().pointer);
if (!fixtureA || !fixtureB)
throw love::Exception("A fixture has escaped Memoizer!");
if (!shapeA || !shapeB)
throw love::Exception("A Shape has escaped Memoizer!");
}
} // box2d
+2 -2
View File
@@ -151,9 +151,9 @@ public:
void getChildren(int &childA, int &childB);
/**
* Gets the Fixtures associated with this Contact.
* Gets the Shapes associated with this Contact.
**/
void getFixtures(Fixture *&fixtureA, Fixture *&fixtureB);
void getShapes(Shape *&shapeA, Shape *&shapeB);
private:
+7 -4
View File
@@ -34,8 +34,8 @@ namespace box2d
love::Type EdgeShape::type("EdgeShape", &Shape::type);
EdgeShape::EdgeShape(b2EdgeShape *e, bool own)
: Shape(e, own)
EdgeShape::EdgeShape(Body *body, const b2EdgeShape &e)
: Shape(body, e)
{
}
@@ -45,6 +45,7 @@ EdgeShape::~EdgeShape()
void EdgeShape::setNextVertex(float x, float y)
{
throwIfShapeNotValid();
b2EdgeShape *e = (b2EdgeShape *)shape;
b2Vec2 v(x, y);
e->m_vertex3 = Physics::scaleDown(v);
@@ -52,13 +53,14 @@ void EdgeShape::setNextVertex(float x, float y)
b2Vec2 EdgeShape::getNextVertex() const
{
throwIfShapeNotValid();
b2EdgeShape *e = (b2EdgeShape *)shape;
return Physics::scaleUp(e->m_vertex3);
}
void EdgeShape::setPreviousVertex(float x, float y)
{
throwIfShapeNotValid();
b2EdgeShape *e = (b2EdgeShape *)shape;
b2Vec2 v(x, y);
e->m_vertex0 = Physics::scaleDown(v);
@@ -66,13 +68,14 @@ void EdgeShape::setPreviousVertex(float x, float y)
b2Vec2 EdgeShape::getPreviousVertex() const
{
throwIfShapeNotValid();
b2EdgeShape *e = (b2EdgeShape *)shape;
return Physics::scaleUp(e->m_vertex0);
}
int EdgeShape::getPoints(lua_State *L)
{
throwIfShapeNotValid();
b2EdgeShape *e = (b2EdgeShape *)shape;
b2Vec2 v1 = Physics::scaleUp(e->m_vertex1);
b2Vec2 v2 = Physics::scaleUp(e->m_vertex2);
+1 -1
View File
@@ -45,7 +45,7 @@ public:
* Create a new EdgeShape from a Box2D edge shape.
* @param e The edge shape.
**/
EdgeShape(b2EdgeShape *e, bool own = true);
EdgeShape(Body *body, const b2EdgeShape &e);
virtual ~EdgeShape();
-349
View File
@@ -1,349 +0,0 @@
/**
* Copyright (c) 2006-2023 LOVE Development Team
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
**/
#include "Fixture.h"
// Module
#include "Body.h"
#include "World.h"
#include "Physics.h"
// STD
#include <bitset>
namespace love
{
namespace physics
{
namespace box2d
{
love::Type Fixture::type("Fixture", &Object::type);
Fixture::Fixture(Body *body, Shape *shape, float density)
: body(body)
, fixture(nullptr)
{
b2FixtureDef def;
def.shape = shape->shape;
def.userData.pointer = (uintptr_t)this;
def.density = density;
fixture = body->body->CreateFixture(&def);
this->retain();
}
Fixture::~Fixture()
{
if (ref)
delete ref;
}
void Fixture::checkCreateShape()
{
if (shape.get() != nullptr || fixture == nullptr || fixture->GetShape() == nullptr)
return;
b2Shape *bshape = fixture->GetShape();
switch (bshape->GetType())
{
case b2Shape::e_circle:
shape.set(new CircleShape((b2CircleShape *) bshape, false), Acquire::NORETAIN);
break;
case b2Shape::e_edge:
shape.set(new EdgeShape((b2EdgeShape *) bshape, false), Acquire::NORETAIN);
break;
case b2Shape::e_polygon:
shape.set(new PolygonShape((b2PolygonShape *) bshape, false), Acquire::NORETAIN);
break;
case b2Shape::e_chain:
shape.set(new ChainShape((b2ChainShape *) bshape, false), Acquire::NORETAIN);
break;
default:
break;
}
}
Shape::Type Fixture::getType()
{
checkCreateShape();
if (shape.get() == nullptr)
return Shape::SHAPE_INVALID;
else
return shape->getType();
}
void Fixture::setFriction(float friction)
{
fixture->SetFriction(friction);
}
void Fixture::setRestitution(float restitution)
{
fixture->SetRestitution(restitution);
}
void Fixture::setDensity(float density)
{
fixture->SetDensity(density);
}
void Fixture::setSensor(bool sensor)
{
fixture->SetSensor(sensor);
}
float Fixture::getFriction() const
{
return fixture->GetFriction();
}
float Fixture::getRestitution() const
{
return fixture->GetRestitution();
}
float Fixture::getDensity() const
{
return fixture->GetDensity();
}
bool Fixture::isSensor() const
{
return fixture->IsSensor();
}
Body *Fixture::getBody() const
{
return body;
}
Shape *Fixture::getShape()
{
checkCreateShape();
return shape;
}
bool Fixture::isValid() const
{
return fixture != nullptr;
}
void Fixture::setFilterData(int *v)
{
b2Filter f;
f.categoryBits = (uint16) v[0];
f.maskBits = (uint16) v[1];
f.groupIndex = (int16) v[2];
fixture->SetFilterData(f);
}
void Fixture::getFilterData(int *v)
{
b2Filter f = fixture->GetFilterData();
v[0] = (int) f.categoryBits;
v[1] = (int) f.maskBits;
v[2] = (int) f.groupIndex;
}
int Fixture::setCategory(lua_State *L)
{
b2Filter f = fixture->GetFilterData();
f.categoryBits = (uint16)getBits(L);
fixture->SetFilterData(f);
return 0;
}
int Fixture::setMask(lua_State *L)
{
b2Filter f = fixture->GetFilterData();
f.maskBits = ~(uint16)getBits(L);
fixture->SetFilterData(f);
return 0;
}
void Fixture::setGroupIndex(int index)
{
b2Filter f = fixture->GetFilterData();
f.groupIndex = (uint16)index;
fixture->SetFilterData(f);
}
int Fixture::getGroupIndex() const
{
b2Filter f = fixture->GetFilterData();
return f.groupIndex;
}
int Fixture::getCategory(lua_State *L)
{
return pushBits(L, fixture->GetFilterData().categoryBits);
}
int Fixture::getMask(lua_State *L)
{
return pushBits(L, ~(fixture->GetFilterData().maskBits));
}
uint16 Fixture::getBits(lua_State *L)
{
// Get number of args.
bool istable = lua_istable(L, 1);
int argc = istable ? (int) luax_objlen(L, 1) : lua_gettop(L);
// The new bitset.
std::bitset<16> b;
for (int i = 1; i <= argc; i++)
{
size_t bpos = 0;
if (istable)
{
lua_rawgeti(L, 1, i);
bpos = (size_t) (lua_tointeger(L, -1) - 1);
lua_pop(L, 1);
}
else
bpos = (size_t) (lua_tointeger(L, i) - 1);
if (bpos >= 16)
luaL_error(L, "Values must be in range 1-16.");
b.set(bpos, true);
}
return (uint16)b.to_ulong();
}
int Fixture::pushBits(lua_State *L, uint16 bits)
{
// Create a bitset.
std::bitset<16> b((int)bits);
// Push all set bits.
for (int i = 0; i<16; i++)
if (b.test(i))
lua_pushinteger(L, i+1);
// Count number of set bits.
return (int)b.count();
}
int Fixture::setUserData(lua_State *L)
{
love::luax_assert_argc(L, 1, 1);
if(!ref)
ref = new Reference();
ref->ref(L);
return 0;
}
int Fixture::getUserData(lua_State *L)
{
if (ref != nullptr)
ref->push(L);
else
lua_pushnil(L);
return 1;
}
bool Fixture::testPoint(float x, float y) const
{
return fixture->TestPoint(Physics::scaleDown(b2Vec2(x, y)));
}
int Fixture::rayCast(lua_State *L) const
{
float p1x = Physics::scaleDown((float)luaL_checknumber(L, 1));
float p1y = Physics::scaleDown((float)luaL_checknumber(L, 2));
float p2x = Physics::scaleDown((float)luaL_checknumber(L, 3));
float p2y = Physics::scaleDown((float)luaL_checknumber(L, 4));
float maxFraction = (float)luaL_checknumber(L, 5);
int childIndex = (int) luaL_optinteger(L, 6, 1) - 1; // Convert from 1-based index
b2RayCastInput input;
input.p1.Set(p1x, p1y);
input.p2.Set(p2x, p2y);
input.maxFraction = maxFraction;
b2RayCastOutput output;
if (!fixture->RayCast(&output, input, childIndex))
return 0; // Nothing hit.
lua_pushnumber(L, output.normal.x);
lua_pushnumber(L, output.normal.y);
lua_pushnumber(L, output.fraction);
return 3;
}
int Fixture::getBoundingBox(lua_State *L) const
{
int childIndex = (int) luaL_optinteger(L, 1, 1) - 1; // Convert from 1-based index
b2AABB box;
luax_catchexcept(L, [&]() { box = fixture->GetAABB(childIndex); });
box = Physics::scaleUp(box);
lua_pushnumber(L, box.lowerBound.x);
lua_pushnumber(L, box.lowerBound.y);
lua_pushnumber(L, box.upperBound.x);
lua_pushnumber(L, box.upperBound.y);
return 4;
}
int Fixture::getMassData(lua_State *L) const
{
b2MassData data;
fixture->GetMassData(&data);
b2Vec2 center = Physics::scaleUp(data.center);
lua_pushnumber(L, center.x);
lua_pushnumber(L, center.y);
lua_pushnumber(L, data.mass);
lua_pushnumber(L, data.I);
return 4;
}
void Fixture::destroy(bool implicit)
{
if (body->world->world->IsLocked())
{
// Called during time step. Save reference for destruction afterwards.
this->retain();
body->world->destructFixtures.push_back(this);
return;
}
shape.set(nullptr);
if (!implicit && fixture != nullptr)
body->body->DestroyFixture(fixture);
fixture = nullptr;
// Remove userdata reference to avoid it sticking around after GC
if (ref)
ref->unref();
// Box2D fixture destroyed. Release its reference to the love Fixture.
this->release();
}
} // box2d
} // physics
} // love
-216
View File
@@ -1,216 +0,0 @@
/**
* Copyright (c) 2006-2023 LOVE Development Team
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
**/
#ifndef LOVE_PHYSICS_BOX2D_FIXTURE_H
#define LOVE_PHYSICS_BOX2D_FIXTURE_H
// LOVE
#include "physics/Shape.h"
#include "physics/box2d/Body.h"
#include "physics/box2d/Shape.h"
#include "common/Object.h"
#include "common/Reference.h"
// Box2D
#include <box2d/Box2D.h>
namespace love
{
namespace physics
{
namespace box2d
{
class World;
/**
* A Fixture is used to attach a shape to a body for collision detection.
* A Fixture inherits its transform from its parent. Fixtures hold
* additional non-geometric data such as friction, collision filters,
* etc.
**/
class Fixture : public Object
{
public:
friend class Physics;
static love::Type type;
/**
* Creates a Fixture.
**/
Fixture(Body *body, Shape *shape, float density);
virtual ~Fixture();
/**
* Gets the type of the Fixture's Shape. Useful for
* debug drawing.
**/
Shape::Type getType();
/**
* Gets the Shape attached to this Fixture.
**/
Shape *getShape();
/**
* Returns true if the fixture is active in a Box2D world.
**/
bool isValid() const;
/**
* Checks whether this Fixture acts as a sensor.
* @return True if sensor, false otherwise.
**/
bool isSensor() const;
/**
* Set whether this Fixture should be a sensor or not.
* @param sensor True if sensor, false if not.
**/
void setSensor(bool sensor);
/**
* Gets the Body this Fixture is attached to.
**/
Body *getBody() const;
/**
* Sets the filter data. An integer array is used even though the
* first two elements are unsigned shorts. The elements are:
* category (16-bits), mask (16-bits) and group (32-bits/int).
**/
void setFilterData(int *v);
/**
* Gets the filter data. An integer array is used even though the
* first two elements are unsigned shorts. The elements are:
* category (16-bits), mask (16-bits) and group (32-bits/int).
**/
void getFilterData(int *v);
/**
* This function stores an in-C reference to
* arbitrary Lua data in the Box2D Fixture 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);
/**
* Sets the friction of the Fixture.
* @param friction The new friction.
**/
void setFriction(float friction);
/**
* Sets the restitution for the Fixture.
* @param restitution The restitution.
**/
void setRestitution(float restitution);
/**
* Sets the density of the Fixture.
* @param density The density of the Fixture.
**/
void setDensity(float density);
/**
* Gets the friction of the Fixture.
* @returns The friction.
**/
float getFriction() const;
/**
* Gets the restitution of the Fixture.
* @return The restitution of the Fixture.
**/
float getRestitution() const;
/**
* Gets the density of the Fixture.
* @return The density.
**/
float getDensity() const;
/**
* Checks if a point is inside the Fixture.
* @param x The x-component of the point.
* @param y The y-component of the point.
**/
bool testPoint(float x, float y) const;
/**
* Cast a ray against this Fixture.
**/
int rayCast(lua_State *L) const;
void setGroupIndex(int index);
int getGroupIndex() const;
int setCategory(lua_State *L);
int setMask(lua_State *L);
int getCategory(lua_State *L);
int getMask(lua_State *L);
uint16 getBits(lua_State *L);
int pushBits(lua_State *L, uint16 bits);
/**
* Gets the bounding box for this Fixture.
* The function returns eight values which can be
* passed directly to love.graphics.polygon.
**/
int getBoundingBox(lua_State *L) const;
/**
* Gets the mass data for this Fixture.
* This operation may be expensive.
**/
int getMassData(lua_State *L) const;
/**
* Destroys this fixture.
**/
void destroy(bool implicit = false);
protected:
void checkCreateShape();
Body *body;
b2Fixture *fixture;
// Reference to arbitrary data.
Reference* ref = nullptr;
StrongRef<Shape> shape;
};
} // box2d
} // physics
} // love
#endif // LOVE_PHYSICS_BOX2D_FIXTURE_H
+72 -63
View File
@@ -35,6 +35,7 @@ namespace box2d
float Physics::meter = Physics::DEFAULT_METER;
Physics::Physics()
: blockAllocator()
{
meter = DEFAULT_METER;
}
@@ -66,8 +67,7 @@ Body *Physics::newBody(World *world, Body::Type type)
Body *Physics::newCircleBody(World *world, Body::Type type, float x, float y, float radius)
{
StrongRef<Body> body(newBody(world, x, y, type), Acquire::NORETAIN);
StrongRef<CircleShape> shape(newCircleShape(0, 0, radius), Acquire::NORETAIN);
StrongRef<Fixture> fixture(newFixture(body, shape, 1.0f), Acquire::NORETAIN);
StrongRef<CircleShape> shape(newCircleShape(body, 0, 0, radius), Acquire::NORETAIN);
body->retain();
return body.get();
}
@@ -75,8 +75,7 @@ Body *Physics::newCircleBody(World *world, Body::Type type, float x, float y, fl
Body *Physics::newRectangleBody(World *world, Body::Type type, float x, float y, float w, float h, float angle)
{
StrongRef<Body> body(newBody(world, x, y, type), Acquire::NORETAIN);
StrongRef<PolygonShape> shape(newRectangleShape(0, 0, w, h, angle), Acquire::NORETAIN);
StrongRef<Fixture> fixture(newFixture(body, shape, 1.0f), Acquire::NORETAIN);
StrongRef<PolygonShape> shape(newRectangleShape(body, 0, 0, w, h, angle), Acquire::NORETAIN);
body->retain();
return body.get();
}
@@ -93,8 +92,7 @@ Body *Physics::newPolygonBody(World *world, Body::Type type, const Vector2 *coor
localcoords.push_back(coords[i] - origin);
StrongRef<Body> body(newBody(world, origin.x, origin.y, type), Acquire::NORETAIN);
StrongRef<PolygonShape> shape(newPolygonShape(localcoords.data(), count), Acquire::NORETAIN);
StrongRef<Fixture> fixture(newFixture(body, shape, 1.0f), Acquire::NORETAIN);
StrongRef<PolygonShape> shape(newPolygonShape(body, localcoords.data(), count), Acquire::NORETAIN);
body->retain();
return body.get();
}
@@ -104,8 +102,7 @@ Body *Physics::newEdgeBody(World *world, Body::Type type, float x1, float y1, fl
float wx = (x2 - x1) / 2.0f;
float wy = (y2 - y1) / 2.0f;
StrongRef<Body> body(newBody(world, wx, wy, type), Acquire::NORETAIN);
StrongRef<EdgeShape> shape(newEdgeShape(x1 - wx, y1 - wy, x2 - wx, y2 - wy, oneSided), Acquire::NORETAIN);
StrongRef<Fixture> fixture(newFixture(body, shape, 1.0f), Acquire::NORETAIN);
StrongRef<EdgeShape> shape(newEdgeShape(body, x1 - wx, y1 - wy, x2 - wx, y2 - wy, oneSided), Acquire::NORETAIN);
body->retain();
return body.get();
}
@@ -122,44 +119,75 @@ Body *Physics::newChainBody(World *world, Body::Type type, bool loop, const Vect
localcoords.push_back(coords[i] - origin);
StrongRef<Body> body(newBody(world, origin.x, origin.y, type), Acquire::NORETAIN);
StrongRef<ChainShape> shape(newChainShape(loop, localcoords.data(), count), Acquire::NORETAIN);
StrongRef<Fixture> fixture(newFixture(body, shape, 1.0f), Acquire::NORETAIN);
StrongRef<ChainShape> shape(newChainShape(body, loop, localcoords.data(), count), Acquire::NORETAIN);
body->retain();
return body.get();
}
CircleShape *Physics::newCircleShape(float x, float y, float radius)
Shape *Physics::newAttachedShape(Body *body, Shape *prototype, float density)
{
b2CircleShape *s = new b2CircleShape();
s->m_p = Physics::scaleDown(b2Vec2(x, y));
s->m_radius = Physics::scaleDown(radius);
return new CircleShape(s);
if (prototype->isValid())
throw love::Exception("The given Shape must not be part of the World.");
Shape *shape = nullptr;
switch (prototype->getType())
{
case Shape::SHAPE_CIRCLE:
shape = new CircleShape(body, *(b2CircleShape *) prototype->shape);
break;
case Shape::SHAPE_POLYGON:
shape = new PolygonShape(body, *(b2PolygonShape *) prototype->shape);
break;
case Shape::SHAPE_EDGE:
shape = new EdgeShape(body, *(b2EdgeShape *) prototype->shape);
break;
case Shape::SHAPE_CHAIN:
shape = new ChainShape(body, *(b2ChainShape *) prototype->shape);
break;
default:
throw love::Exception("Unknown shape type.");
break;
}
shape->setDensity(density);
body->resetMassData();
return shape;
}
PolygonShape *Physics::newRectangleShape(float x, float y, float w, float h, float angle)
CircleShape *Physics::newCircleShape(Body *body, float x, float y, float radius)
{
b2PolygonShape *s = new b2PolygonShape();
s->SetAsBox(Physics::scaleDown(w/2.0f), Physics::scaleDown(h/2.0f), Physics::scaleDown(b2Vec2(x, y)), angle);
return new PolygonShape(s);
b2CircleShape s;
s.m_p = Physics::scaleDown(b2Vec2(x, y));
s.m_radius = Physics::scaleDown(radius);
return new CircleShape(body, s);
}
EdgeShape *Physics::newEdgeShape(float x1, float y1, float x2, float y2, bool oneSided)
PolygonShape *Physics::newRectangleShape(Body *body, float x, float y, float w, float h, float angle)
{
b2EdgeShape *s = new b2EdgeShape();
b2PolygonShape s;
s.SetAsBox(Physics::scaleDown(w/2.0f), Physics::scaleDown(h/2.0f), Physics::scaleDown(b2Vec2(x, y)), angle);
return new PolygonShape(body, s);
}
EdgeShape *Physics::newEdgeShape(Body *body, float x1, float y1, float x2, float y2, bool oneSided)
{
b2EdgeShape s;
if (oneSided)
{
b2Vec2 v1 = Physics::scaleDown(b2Vec2(x1, y1));
b2Vec2 v2 = Physics::scaleDown(b2Vec2(x2, y2));
s->SetOneSided(v1, v1, v2, v2);
s.SetOneSided(v1, v1, v2, v2);
}
else
{
s->SetTwoSided(Physics::scaleDown(b2Vec2(x1, y1)), Physics::scaleDown(b2Vec2(x2, y2)));
s.SetTwoSided(Physics::scaleDown(b2Vec2(x1, y1)), Physics::scaleDown(b2Vec2(x2, y2)));
}
return new EdgeShape(s);
return new EdgeShape(body, s);
}
PolygonShape *Physics::newPolygonShape(const Vector2 *coords, int count)
PolygonShape *Physics::newPolygonShape(Body *body, const Vector2 *coords, int count)
{
// 3 to 8 (b2_maxPolygonVertices) vertices
if (count < 3)
@@ -172,44 +200,28 @@ PolygonShape *Physics::newPolygonShape(const Vector2 *coords, int count)
for (int i = 0; i < count; i++)
vecs[i] = Physics::scaleDown(b2Vec2(coords[i].x, coords[i].y));
b2PolygonShape *s = new b2PolygonShape();
b2PolygonShape s;
try
{
s->Set(vecs, count);
}
catch (love::Exception &)
{
delete s;
throw;
}
s.Set(vecs, count);
return new PolygonShape(s);
return new PolygonShape(body, s);
}
ChainShape *Physics::newChainShape(bool loop, const Vector2 *coords, int count)
ChainShape *Physics::newChainShape(Body *body, bool loop, const Vector2 *coords, int count)
{
std::vector<b2Vec2> vecs;
for (int i = 0; i < count; i++)
vecs.push_back(Physics::scaleDown(b2Vec2(coords[i].x, coords[i].y)));
b2ChainShape *s = new b2ChainShape();
b2ChainShape s;
try
{
if (loop)
s->CreateLoop(vecs.data(), count);
else
s->CreateChain(vecs.data(), count, vecs[0], vecs[count - 1]);
}
catch (love::Exception &)
{
delete s;
throw;
}
if (loop)
s.CreateLoop(vecs.data(), count);
else
s.CreateChain(vecs.data(), count, vecs[0], vecs[count - 1]);
return new ChainShape(s);
return new ChainShape(body, s);
}
DistanceJoint *Physics::newDistanceJoint(Body *body1, Body *body2, float x1, float y1, float x2, float y2, bool collideConnected)
@@ -287,16 +299,10 @@ MotorJoint *Physics::newMotorJoint(Body *body1, Body *body2, float correctionFac
return new MotorJoint(body1, body2, correctionFactor, collideConnected);
}
Fixture *Physics::newFixture(Body *body, Shape *shape, float density)
{
return new Fixture(body, shape, density);
}
int Physics::getDistance(lua_State *L)
{
Fixture *fixtureA = luax_checktype<Fixture>(L, 1);
Fixture *fixtureB = luax_checktype<Fixture>(L, 2);
Shape *shapeA = luax_checktype<Shape>(L, 1);
Shape *shapeB = luax_checktype<Shape>(L, 2);
b2DistanceProxy pA, pB;
b2DistanceInput i;
b2DistanceOutput o;
@@ -304,12 +310,15 @@ int Physics::getDistance(lua_State *L)
c.count = 0;
luax_catchexcept(L, [&]() {
pA.Set(fixtureA->fixture->GetShape(), 0);
pB.Set(fixtureB->fixture->GetShape(), 0);
if (!shapeA->isValid() || !shapeB->isValid())
throw love::Exception("The given Shape is not active in the physics World.");
pA.Set(shapeA->fixture->GetShape(), 0);
pB.Set(shapeB->fixture->GetShape(), 0);
i.proxyA = pA;
i.proxyB = pB;
i.transformA = fixtureA->fixture->GetBody()->GetTransform();
i.transformB = fixtureB->fixture->GetBody()->GetTransform();
i.transformA = shapeA->fixture->GetBody()->GetTransform();
i.transformB = shapeB->fixture->GetBody()->GetTransform();
i.useRadii = true;
b2Distance(&o, &c, &i);
});
+16 -19
View File
@@ -28,7 +28,6 @@
#include "World.h"
#include "Contact.h"
#include "Body.h"
#include "Fixture.h"
#include "Shape.h"
#include "CircleShape.h"
#include "PolygonShape.h"
@@ -95,9 +94,9 @@ public:
Body *newBody(World *world, Body::Type type);
/**
* Convenience functions for creating a Body, Shape, and Fixture all in one
* call. The body's world position is the center/average of the given
* coordinates, and the shape is centered at the local origin.
* Convenience functions for creating a Body and Shape all in one call. The
* body's world position is the center/average of the given coordinates,
* and the shape is centered at the local origin.
**/
Body *newCircleBody(World *world, Body::Type type, float x, float y, float radius);
Body *newRectangleBody(World *world, Body::Type type, float x, float y, float w, float h, float angle);
@@ -105,13 +104,16 @@ public:
Body *newEdgeBody(World *world, Body::Type type, float x1, float y1, float x2, float y2, bool oneSided);
Body *newChainBody(World *world, Body::Type type, bool loop, const Vector2 *coords, int count);
// Necessary to support the deprecated newFixture API.
Shape *newAttachedShape(Body *body, Shape *prototype, float density);
/**
* Creates a new CircleShape at (x,y) in local coordinates.
* @param x The offset along the x-axis.
* @param y The offset along the y-axis.
* @param radius The radius of the circle.
**/
CircleShape *newCircleShape(float x, float y, float radius);
CircleShape *newCircleShape(Body *body, float x, float y, float radius);
/**
* Shorthand for creating rectangular PolygonShapes. The rectangle
@@ -122,7 +124,7 @@ public:
* @param h The height of the rectangle.
* @param angle The angle of the rectangle. (rad)
**/
PolygonShape *newRectangleShape(float x, float y, float w, float h, float angle);
PolygonShape *newRectangleShape(Body *body, float x, float y, float w, float h, float angle);
/**
* Creates a new EdgeShape. The edge will be created from
@@ -132,18 +134,17 @@ public:
* @param x2 The x coordinate of the second point.
* @param y2 The y coordinate of the second point.
**/
EdgeShape *newEdgeShape(float x1, float y1, float x2, float y2, bool oneSided);
EdgeShape *newEdgeShape(Body *body, float x1, float y1, float x2, float y2, bool oneSided);
/**
* Creates a new PolygonShape from a variable number of vertices.
**/
//int newPolygonShape(lua_State *L);
PolygonShape *newPolygonShape(const Vector2 *coords, int count);
PolygonShape *newPolygonShape(Body *body, const Vector2 *coords, int count);
/**
* Creates a new ChainShape from a variable number of vertices.
**/
ChainShape *newChainShape(bool loop, const Vector2 *coords, int count);
ChainShape *newChainShape(Body *body, bool loop, const Vector2 *coords, int count);
/**
* Creates a new DistanceJoint connecting body1 with body2.
@@ -263,15 +264,6 @@ public:
MotorJoint *newMotorJoint(Body *body1, Body *body2);
MotorJoint *newMotorJoint(Body *body1, Body *body2, float correctionFactor, bool collideConnected);
/**
* Creates a new Fixture attaching shape to body.
* @param body The body to attach the Fixture to.
* @param shape The shape to attach to the Fixture,
* @param density The density of the Fixture.
**/
Fixture *newFixture(Body *body, Shape *shape, float density);
/**
* Calculates the distance between two Fixtures.
* @param fixtureA The first Fixture.
@@ -393,10 +385,15 @@ public:
**/
static void computeAngularFrequency(float &frequency, float &ratio, float stiffness, float damping, b2Body *bodyA, b2Body *bodyB);
b2BlockAllocator *getBlockAllocator() { return &blockAllocator; }
private:
// The length of one meter in pixels.
static float meter;
b2BlockAllocator blockAllocator;
}; // Physics
} // box2d
+4 -2
View File
@@ -34,8 +34,8 @@ namespace box2d
love::Type PolygonShape::type("PolygonShape", &Shape::type);
PolygonShape::PolygonShape(b2PolygonShape *p, bool own)
: Shape(p, own)
PolygonShape::PolygonShape(Body *body, const b2PolygonShape &p)
: Shape(body, p)
{
}
@@ -45,6 +45,7 @@ PolygonShape::~PolygonShape()
int PolygonShape::getPoints(lua_State *L)
{
throwIfShapeNotValid();
love::luax_assert_argc(L, 0);
b2PolygonShape *p = (b2PolygonShape *)shape;
int count = p->m_count;
@@ -59,6 +60,7 @@ int PolygonShape::getPoints(lua_State *L)
bool PolygonShape::validate() const
{
throwIfShapeNotValid();
b2PolygonShape *p = (b2PolygonShape *)shape;
return p->Validate();
}
+1 -1
View File
@@ -48,7 +48,7 @@ public:
* Create a new PolygonShape from a Box2D polygon definition.
* @param p The polygon definition.
**/
PolygonShape(b2PolygonShape *p, bool own = true);
PolygonShape(Body *body, const b2PolygonShape &p);
virtual ~PolygonShape();
+367 -28
View File
@@ -35,54 +35,348 @@ namespace physics
namespace box2d
{
Shape::Shape()
Shape::Shape(Body *body, const b2Shape &shape)
: shape(nullptr)
, own(false)
, shapeType(SHAPE_INVALID)
, body(body)
, fixture(nullptr)
{
}
if (body)
{
b2FixtureDef def;
def.shape = &shape;
def.userData.pointer = (uintptr_t)this;
def.density = 1.0f;
fixture = body->body->CreateFixture(&def);
this->shape = fixture->GetShape();
retain(); // Shape::destroy does the release().
}
else
{
// Path to support deprecated APIs.
auto physics = Module::getInstance<Physics>(Module::M_PHYSICS);
this->shape = shape.Clone(physics->getBlockAllocator());
own = true;
}
Shape::Shape(b2Shape *shape, bool own)
: shape(shape)
, own(own)
{
switch (this->shape->GetType())
{
case b2Shape::e_circle:
shapeType = SHAPE_CIRCLE;
break;
case b2Shape::e_polygon:
shapeType = SHAPE_POLYGON;
break;
case b2Shape::e_edge:
shapeType = SHAPE_EDGE;
break;
case b2Shape::e_chain:
shapeType = SHAPE_CHAIN;
break;
default:
shapeType = SHAPE_INVALID;
break;
}
}
Shape::~Shape()
{
if (shape && own)
delete shape;
{
auto physics = Module::getInstance<Physics>(Module::M_PHYSICS);
auto allocator = physics->getBlockAllocator();
// Taken from b2Fixture::Destroy. Not very pretty...
switch (shapeType)
{
case SHAPE_CIRCLE:
{
b2CircleShape *s = (b2CircleShape*)shape;
s->~b2CircleShape();
allocator->Free(s, sizeof(b2CircleShape));
break;
}
case SHAPE_EDGE:
{
b2EdgeShape *s = (b2EdgeShape*)shape;
s->~b2EdgeShape();
allocator->Free(s, sizeof(b2EdgeShape));
break;
}
case SHAPE_POLYGON:
{
b2PolygonShape *s = (b2PolygonShape*)shape;
s->~b2PolygonShape();
allocator->Free(s, sizeof(b2PolygonShape));
break;
}
case SHAPE_CHAIN:
{
b2ChainShape *s = (b2ChainShape*)shape;
s->~b2ChainShape();
allocator->Free(s, sizeof(b2ChainShape));
break;
}
default:
break;
}
}
if (ref)
delete ref;
}
void Shape::destroy(bool implicit)
{
if (fixture == nullptr)
return;
if (body->world->world->IsLocked())
{
// Called during time step. Save reference for destruction afterwards.
this->retain();
body->world->destructShapes.push_back(this);
return;
}
if (!implicit && fixture != nullptr)
body->body->DestroyFixture(fixture);
fixture = nullptr;
shape = nullptr;
body = nullptr;
// Remove userdata reference to avoid it sticking around after GC
if (ref)
ref->unref();
// Box2D fixture destroyed. Release its reference to the love Shape.
release();
}
void Shape::throwIfFixtureNotValid() const
{
if (fixture == nullptr)
throw love::Exception("Shape must be active in the physics World to use this method.");
}
void Shape::throwIfShapeNotValid() const
{
if (shape == nullptr)
throw love::Exception("Cannot call this method on a destroyed Shape.");
}
Shape::Type Shape::getType() const
{
switch (shape->GetType())
{
case b2Shape::e_circle:
return SHAPE_CIRCLE;
case b2Shape::e_polygon:
return SHAPE_POLYGON;
case b2Shape::e_edge:
return SHAPE_EDGE;
case b2Shape::e_chain:
return SHAPE_CHAIN;
default:
return SHAPE_INVALID;
}
return shapeType;
}
void Shape::setFriction(float friction)
{
throwIfFixtureNotValid();
fixture->SetFriction(friction);
}
void Shape::setRestitution(float restitution)
{
throwIfFixtureNotValid();
fixture->SetRestitution(restitution);
}
void Shape::setDensity(float density)
{
throwIfFixtureNotValid();
fixture->SetDensity(density);
}
void Shape::setSensor(bool sensor)
{
throwIfFixtureNotValid();
fixture->SetSensor(sensor);
}
float Shape::getFriction() const
{
throwIfFixtureNotValid();
return fixture->GetFriction();
}
float Shape::getRestitution() const
{
throwIfFixtureNotValid();
return fixture->GetRestitution();
}
float Shape::getDensity() const
{
throwIfFixtureNotValid();
return fixture->GetDensity();
}
bool Shape::isSensor() const
{
throwIfFixtureNotValid();
return fixture->IsSensor();
}
Body *Shape::getBody() const
{
return body;
}
float Shape::getRadius() const
{
throwIfShapeNotValid();
return Physics::scaleUp(shape->m_radius);
}
int Shape::getChildCount() const
{
throwIfShapeNotValid();
return shape->GetChildCount();
}
void Shape::setFilterData(int *v)
{
throwIfFixtureNotValid();
b2Filter f;
f.categoryBits = (uint16) v[0];
f.maskBits = (uint16) v[1];
f.groupIndex = (int16) v[2];
fixture->SetFilterData(f);
}
void Shape::getFilterData(int *v)
{
throwIfFixtureNotValid();
b2Filter f = fixture->GetFilterData();
v[0] = (int) f.categoryBits;
v[1] = (int) f.maskBits;
v[2] = (int) f.groupIndex;
}
int Shape::setCategory(lua_State *L)
{
throwIfFixtureNotValid();
b2Filter f = fixture->GetFilterData();
f.categoryBits = (uint16)getBits(L);
fixture->SetFilterData(f);
return 0;
}
int Shape::setMask(lua_State *L)
{
throwIfFixtureNotValid();
b2Filter f = fixture->GetFilterData();
f.maskBits = ~(uint16)getBits(L);
fixture->SetFilterData(f);
return 0;
}
void Shape::setGroupIndex(int index)
{
throwIfFixtureNotValid();
b2Filter f = fixture->GetFilterData();
f.groupIndex = (uint16)index;
fixture->SetFilterData(f);
}
int Shape::getGroupIndex() const
{
throwIfFixtureNotValid();
b2Filter f = fixture->GetFilterData();
return f.groupIndex;
}
int Shape::getCategory(lua_State *L)
{
throwIfFixtureNotValid();
return pushBits(L, fixture->GetFilterData().categoryBits);
}
int Shape::getMask(lua_State *L)
{
throwIfFixtureNotValid();
return pushBits(L, ~(fixture->GetFilterData().maskBits));
}
uint16 Shape::getBits(lua_State *L)
{
// Get number of args.
bool istable = lua_istable(L, 1);
int argc = istable ? (int) luax_objlen(L, 1) : lua_gettop(L);
// The new bitset.
std::bitset<16> b;
for (int i = 1; i <= argc; i++)
{
size_t bpos = 0;
if (istable)
{
lua_rawgeti(L, 1, i);
bpos = (size_t) (lua_tointeger(L, -1) - 1);
lua_pop(L, 1);
}
else
bpos = (size_t) (lua_tointeger(L, i) - 1);
if (bpos >= 16)
luaL_error(L, "Values must be in range 1-16.");
b.set(bpos, true);
}
return (uint16)b.to_ulong();
}
int Shape::pushBits(lua_State *L, uint16 bits)
{
// Create a bitset.
std::bitset<16> b((int)bits);
// Push all set bits.
for (int i = 0; i<16; i++)
if (b.test(i))
lua_pushinteger(L, i+1);
// Count number of set bits.
return (int)b.count();
}
int Shape::setUserData(lua_State *L)
{
love::luax_assert_argc(L, 1, 1);
if(!ref)
ref = new Reference();
ref->ref(L);
return 0;
}
int Shape::getUserData(lua_State *L)
{
if (ref != nullptr)
ref->push(L);
else
lua_pushnil(L);
return 1;
}
bool Shape::testPoint(float x, float y) const
{
throwIfFixtureNotValid();
return fixture->TestPoint(Physics::scaleDown(b2Vec2(x, y)));
}
bool Shape::testPoint(float x, float y, float r, float px, float py) const
{
throwIfShapeNotValid();
b2Vec2 point(px, py);
b2Transform transform(Physics::scaleDown(b2Vec2(x, y)), b2Rot(r));
return shape->TestPoint(transform, Physics::scaleDown(point));
@@ -95,18 +389,34 @@ int Shape::rayCast(lua_State *L) const
float p2x = Physics::scaleDown((float)luaL_checknumber(L, 3));
float p2y = Physics::scaleDown((float)luaL_checknumber(L, 4));
float maxFraction = (float)luaL_checknumber(L, 5);
float x = Physics::scaleDown((float)luaL_checknumber(L, 6));
float y = Physics::scaleDown((float)luaL_checknumber(L, 7));
float r = (float)luaL_checknumber(L, 8);
int childIndex = (int) luaL_optinteger(L, 9, 1) - 1; // Convert from 1-based index
b2RayCastInput input;
b2RayCastOutput output;
input.p1.Set(p1x, p1y);
input.p2.Set(p2x, p2y);
input.maxFraction = maxFraction;
b2Transform transform(b2Vec2(x, y), b2Rot(r));
b2RayCastOutput output;
if (!shape->RayCast(&output, input, transform, childIndex))
return 0; // No hit.
if (lua_isnoneornil(L, 7))
{
throwIfFixtureNotValid();
int childIndex = (int) luaL_optinteger(L, 6, 1) - 1; // Convert from 1-based index
if (!fixture->RayCast(&output, input, childIndex))
return 0; // Nothing hit.
}
else
{
throwIfShapeNotValid();
float x = Physics::scaleDown((float)luaL_checknumber(L, 6));
float y = Physics::scaleDown((float)luaL_checknumber(L, 7));
float r = (float)luaL_checknumber(L, 8);
int childIndex = (int) luaL_optinteger(L, 9, 1) - 1; // Convert from 1-based index
b2Transform transform(b2Vec2(x, y), b2Rot(r));
if (!shape->RayCast(&output, input, transform, childIndex))
return 0; // No hit.
}
lua_pushnumber(L, output.normal.x);
lua_pushnumber(L, output.normal.y);
lua_pushnumber(L, output.fraction);
@@ -115,6 +425,7 @@ int Shape::rayCast(lua_State *L) const
int Shape::computeAABB(lua_State *L) const
{
throwIfShapeNotValid();
float x = Physics::scaleDown((float)luaL_checknumber(L, 1));
float y = Physics::scaleDown((float)luaL_checknumber(L, 2));
float r = (float)luaL_checknumber(L, 3);
@@ -132,6 +443,7 @@ int Shape::computeAABB(lua_State *L) const
int Shape::computeMass(lua_State *L) const
{
throwIfShapeNotValid();
float density = (float)luaL_checknumber(L, 1);
b2MassData data;
shape->ComputeMass(&data, density);
@@ -143,6 +455,33 @@ int Shape::computeMass(lua_State *L) const
return 4;
}
int Shape::getBoundingBox(lua_State *L) const
{
throwIfFixtureNotValid();
int childIndex = (int) luaL_optinteger(L, 1, 1) - 1; // Convert from 1-based index
b2AABB box;
luax_catchexcept(L, [&]() { box = fixture->GetAABB(childIndex); });
box = Physics::scaleUp(box);
lua_pushnumber(L, box.lowerBound.x);
lua_pushnumber(L, box.lowerBound.y);
lua_pushnumber(L, box.upperBound.x);
lua_pushnumber(L, box.upperBound.y);
return 4;
}
int Shape::getMassData(lua_State *L) const
{
throwIfFixtureNotValid();
b2MassData data;
fixture->GetMassData(&data);
b2Vec2 center = Physics::scaleUp(data.center);
lua_pushnumber(L, center.x);
lua_pushnumber(L, center.y);
lua_pushnumber(L, data.mass);
lua_pushnumber(L, data.I);
return 4;
}
} // box2d
} // physics
} // love
+127 -5
View File
@@ -24,6 +24,7 @@
// LOVE
#include "physics/Shape.h"
#include "physics/box2d/Body.h"
#include "common/Reference.h"
// Box2D
#include <box2d/Box2D.h>
@@ -45,34 +46,155 @@ class Shape : public love::physics::Shape
{
public:
friend class Fixture;
friend class Physics;
/**
* Creates a Shape.
**/
Shape();
Shape(b2Shape *shape, bool own = true);
Shape(Body *body, const b2Shape &shape);
virtual ~Shape();
void destroy(bool implicit = false);
/**
* Returns true if the shape is active in a Box2D world.
**/
bool isValid() const { return fixture != nullptr; }
/**
* Returns true if the shape has not been destroyed.
**/
bool isShapeValid() const { return shape != nullptr; }
/**
* Checks whether this Shape acts as a sensor.
**/
bool isSensor() const;
/**
* Set whether this Shape should be a sensor or not.
**/
void setSensor(bool sensor);
/**
* Gets the Body this Shape is attached to.
**/
Body *getBody() const;
/**
* Sets the filter data. An integer array is used even though the
* first two elements are unsigned shorts. The elements are:
* category (16-bits), mask (16-bits) and group (32-bits/int).
**/
void setFilterData(int *v);
/**
* Gets the filter data. An integer array is used even though the
* first two elements are unsigned shorts. The elements are:
* category (16-bits), mask (16-bits) and group (32-bits/int).
**/
void getFilterData(int *v);
/**
* This function stores an in-C reference to
* arbitrary Lua data in the Shape object.
**/
int setUserData(lua_State *L);
/**
* Gets the data set with setUserData. If no
* data is set, nil is returned.
**/
int getUserData(lua_State *L);
/**
* Sets the friction of the Shape.
**/
void setFriction(float friction);
/**
* Sets the restitution for the Shape.
**/
void setRestitution(float restitution);
/**
* Sets the density of the Shape.
**/
void setDensity(float density);
/**
* Gets the friction of the Shape.
**/
float getFriction() const;
/**
* Gets the restitution of the Shape.
**/
float getRestitution() const;
/**
* Gets the density of the Shape.
**/
float getDensity() const;
/**
* Checks if a point is inside the Shape.
**/
bool testPoint(float x, float y) const;
bool testPoint(float x, float y, float r, float px, float py) const;
/**
* Gets the type of Shape. Useful for
* debug drawing.
**/
Type getType() const;
float getRadius() const;
int getChildCount() const;
bool testPoint(float x, float y, float r, float px, float py) const;
int rayCast(lua_State *L) const;
int computeAABB(lua_State *L) const;
int computeMass(lua_State *L) const;
void setGroupIndex(int index);
int getGroupIndex() const;
int setCategory(lua_State *L);
int setMask(lua_State *L);
int getCategory(lua_State *L);
int getMask(lua_State *L);
uint16 getBits(lua_State *L);
int pushBits(lua_State *L, uint16 bits);
/**
* Gets the bounding box for this Shape.
**/
int getBoundingBox(lua_State *L) const;
/**
* Gets the mass data for this Shape.
* This operation may be expensive.
**/
int getMassData(lua_State *L) const;
void throwIfFixtureNotValid() const;
void throwIfShapeNotValid() const;
protected:
// The Box2D shape.
b2Shape *shape;
bool own;
};
Shape::Type shapeType;
Body *body;
b2Fixture *fixture;
// Reference to arbitrary data.
Reference* ref = nullptr;
}; // Shape
} // box2d
} // physics
+40 -40
View File
@@ -20,7 +20,6 @@
#include "World.h"
#include "Fixture.h"
#include "Shape.h"
#include "Contact.h"
#include "Physics.h"
@@ -28,6 +27,7 @@
// Needed for World::getJoints. It should be moved to wrapper code...
#include "wrap_Joint.h"
#include "wrap_Shape.h"
namespace love
{
@@ -58,22 +58,22 @@ void World::ContactCallback::process(b2Contact *contact, const b2ContactImpulse
{
ref->push(L);
// Push first fixture.
// Push first shape.
{
Fixture *a = (Fixture *)(contact->GetFixtureA()->GetUserData().pointer);
Shape *a = (Shape *)(contact->GetFixtureA()->GetUserData().pointer);
if (a != nullptr)
luax_pushtype(L, a);
luax_pushshape(L, a);
else
throw love::Exception("A fixture has escaped Memoizer!");
throw love::Exception("A Shape has escaped Memoizer!");
}
// Push second fixture.
// Push second shape.
{
Fixture *b = (Fixture *)(contact->GetFixtureB()->GetUserData().pointer);
Shape *b = (Shape *)(contact->GetFixtureB()->GetUserData().pointer);
if (b != nullptr)
luax_pushtype(L, b);
luax_pushshape(L, b);
else
throw love::Exception("A fixture has escaped Memoizer!");
throw love::Exception("A Shape has escaped Memoizer!");
}
Contact *cobj = (Contact *)world->findObject(contact);
@@ -112,7 +112,7 @@ World::ContactFilter::~ContactFilter()
delete ref;
}
bool World::ContactFilter::process(Fixture *a, Fixture *b)
bool World::ContactFilter::process(Shape *a, Shape *b)
{
// Handle masks, reimplemented from the manual
int filterA[3], filterB[3];
@@ -133,8 +133,8 @@ bool World::ContactFilter::process(Fixture *a, Fixture *b)
if (ref != nullptr && L != nullptr)
{
ref->push(L);
luax_pushtype(L, a);
luax_pushtype(L, b);
luax_pushshape(L, a);
luax_pushshape(L, b);
lua_call(L, 2, 1);
return luax_toboolean(L, -1);
}
@@ -159,10 +159,10 @@ bool World::QueryCallback::ReportFixture(b2Fixture *fixture)
if (L != nullptr)
{
lua_pushvalue(L, funcidx);
Fixture *f = (Fixture *)(fixture->GetUserData().pointer);
Shape *f = (Shape *)(fixture->GetUserData().pointer);
if (!f)
throw love::Exception("A fixture has escaped Memoizer!");
luax_pushtype(L, f);
throw love::Exception("A Shape has escaped Memoizer!");
luax_pushshape(L, f);
for (int i = 1; i <= userargs; i++)
lua_pushvalue(L, funcidx + i);
lua_call(L, 1 + userargs, 1);
@@ -191,10 +191,10 @@ bool World::CollectCallback::ReportFixture(b2Fixture *f)
if (categoryMask != 0xFFFF && (categoryMask & f->GetFilterData().categoryBits) == 0)
return true;
Fixture *fixture = (Fixture *)(f->GetUserData().pointer);
if (!fixture)
throw love::Exception("A fixture has escaped Memoizer!");
luax_pushtype(L, fixture);
Shape *shape = (Shape *)(f->GetUserData().pointer);
if (!shape)
throw love::Exception("A Shape has escaped Memoizer!");
luax_pushshape(L, shape);
lua_rawseti(L, -2, i);
i++;
return true;
@@ -218,10 +218,10 @@ float World::RayCastCallback::ReportFixture(b2Fixture *fixture, const b2Vec2 &po
if (L != nullptr)
{
lua_pushvalue(L, funcidx);
Fixture *f = (Fixture *)(fixture->GetUserData().pointer);
Shape *f = (Shape *)(fixture->GetUserData().pointer);
if (!f)
throw love::Exception("A fixture has escaped Memoizer!");
luax_pushtype(L, f);
throw love::Exception("A Shape has escaped Memoizer!");
luax_pushshape(L, f);
b2Vec2 scaledPoint = Physics::scaleUp(point);
lua_pushnumber(L, scaledPoint.x);
lua_pushnumber(L, scaledPoint.y);
@@ -267,9 +267,9 @@ float World::RayCastOneCallback::ReportFixture(b2Fixture *fixture, const b2Vec2
void World::SayGoodbye(b2Fixture *fixture)
{
Fixture *f = (Fixture *)(fixture->GetUserData().pointer);
Shape *s = (Shape *)(fixture->GetUserData().pointer);
// Hint implicit destruction with true.
if (f) f->destroy(true);
if (s) s->destroy(true);
}
void World::SayGoodbye(b2Joint *joint)
@@ -336,11 +336,11 @@ void World::update(float dt, int velocityIterations, int positionIterations)
// Release for reference in vector.
b->release();
}
for (Fixture *f : destructFixtures)
for (Shape *s : destructShapes)
{
if (f->isValid()) f->destroy();
if (s->isValid()) s->destroy();
// Release for reference in vector.
f->release();
s->release();
}
for (Joint *j : destructJoints)
{
@@ -349,7 +349,7 @@ void World::update(float dt, int velocityIterations, int positionIterations)
j->release();
}
destructBodies.clear();
destructFixtures.clear();
destructShapes.clear();
destructJoints.clear();
if (destructWorld)
@@ -384,11 +384,11 @@ void World::PostSolve(b2Contact *contact, const b2ContactImpulse *impulse)
bool World::ShouldCollide(b2Fixture *fixtureA, b2Fixture *fixtureB)
{
// Fixtures should be memoized, if we created them
Fixture *a = (Fixture *)(fixtureA->GetUserData().pointer);
Fixture *b = (Fixture *)(fixtureB->GetUserData().pointer);
// Shapes should be memoized, if we created them
Shape *a = (Shape *)(fixtureA->GetUserData().pointer);
Shape *b = (Shape *)(fixtureB->GetUserData().pointer);
if (!a || !b)
throw love::Exception("A fixture has escaped Memoizer!");
throw love::Exception("A Shape has escaped Memoizer!");
return filter.process(a, b);
}
@@ -597,7 +597,7 @@ b2Body *World::getGroundBody() const
return groundBody;
}
int World::queryFixturesInArea(lua_State *L)
int World::queryShapesInArea(lua_State *L)
{
b2AABB box;
float lx = (float)luaL_checknumber(L, 1);
@@ -612,7 +612,7 @@ int World::queryFixturesInArea(lua_State *L)
return 0;
}
int World::getFixturesInArea(lua_State *L)
int World::getShapesInArea(lua_State *L)
{
float lx = (float)luaL_checknumber(L, 1);
float ly = (float)luaL_checknumber(L, 2);
@@ -654,10 +654,10 @@ int World::rayCastAny(lua_State *L)
world->RayCast(&raycast, v1, v2);
if (raycast.hitFixture)
{
Fixture *f = (Fixture *)(raycast.hitFixture->GetUserData().pointer);
Shape *f = (Shape *)(raycast.hitFixture->GetUserData().pointer);
if (f == nullptr)
return luaL_error(L, "A fixture has escaped Memoizer!");
luax_pushtype(L, f);
return luaL_error(L, "A Shape has escaped Memoizer!");
luax_pushshape(L, f);
b2Vec2 hitPoint = Physics::scaleUp(raycast.hitPoint);
lua_pushnumber(L, hitPoint.x);
@@ -683,10 +683,10 @@ int World::rayCastClosest(lua_State *L)
world->RayCast(&raycast, v1, v2);
if (raycast.hitFixture)
{
Fixture *f = (Fixture *)(raycast.hitFixture->GetUserData().pointer);
Shape *f = (Shape *)(raycast.hitFixture->GetUserData().pointer);
if (f == nullptr)
return luaL_error(L, "A fixture has escaped Memoizer!");
luax_pushtype(L, f);
return luaL_error(L, "A Shape has escaped Memoizer!");
luax_pushshape(L, f);
b2Vec2 hitPoint = Physics::scaleUp(raycast.hitPoint);
lua_pushnumber(L, hitPoint.x);
+7 -8
View File
@@ -42,7 +42,6 @@ namespace box2d
class Contact;
class Body;
class Fixture;
class Joint;
/**
@@ -65,7 +64,7 @@ public:
friend class DistanceJoint;
friend class MouseJoint;
friend class Body;
friend class Fixture;
friend class Shape;
static love::Type type;
@@ -87,7 +86,7 @@ public:
lua_State *L;
ContactFilter();
~ContactFilter();
bool process(Fixture *a, Fixture *b);
bool process(Shape *a, Shape *b);
};
class QueryCallback : public b2QueryCallback
@@ -302,14 +301,14 @@ public:
b2Body *getGroundBody() const;
/**
* Calls a callback on all fixtures that overlap a given bounding box.
* Calls a callback on all Shapes that overlap a given bounding box.
**/
int queryFixturesInArea(lua_State *L);
int queryShapesInArea(lua_State *L);
/**
* Gets all fixtures that overlap a given bounding box.
* Gets all Shapes that overlap a given bounding box.
**/
int getFixturesInArea(lua_State *L);
int getShapesInArea(lua_State *L);
/**
* Raycasts the World for all Fixtures in the path of the ray.
@@ -338,7 +337,7 @@ private:
// The list of to be destructed bodies.
std::vector<Body *> destructBodies;
std::vector<Fixture *> destructFixtures;
std::vector<Shape *> destructShapes;
std::vector<Joint *> destructJoints;
bool destructWorld;
+18 -8
View File
@@ -20,6 +20,7 @@
#include "wrap_Body.h"
#include "wrap_Physics.h"
#include "wrap_Shape.h"
namespace love
{
@@ -599,26 +600,32 @@ int w_Body_getWorld(lua_State *L)
return 1;
}
int w_Body_getFixture(lua_State *L)
int w_Body_getShape(lua_State *L)
{
Body *t = luax_checkbody(L, 1);
Fixture *f = t->getFixture();
if (f)
luax_pushtype(L, f);
Shape *s = t->getShape();
if (s)
luax_pushshape(L, s);
else
lua_pushnil(L);
return 1;
}
int w_Body_getFixtures(lua_State *L)
int w_Body_getShapes(lua_State *L)
{
Body *t = luax_checkbody(L, 1);
lua_remove(L, 1);
int n = 0;
luax_catchexcept(L, [&](){ n = t->getFixtures(L); });
luax_catchexcept(L, [&](){ n = t->getShapes(L); });
return n;
}
int w_Body_getFixtures(lua_State *L)
{
luax_markdeprecated(L, 1, "Body:getFixtures", API_METHOD, DEPRECATED_REPLACED, "Body:getShapes");
return w_Body_getShapes(L);
}
int w_Body_getJoints(lua_State *L)
{
Body *t = luax_checkbody(L, 1);
@@ -724,8 +731,8 @@ static const luaL_Reg w_Body_functions[] =
{ "isFixedRotation", w_Body_isFixedRotation },
{ "isTouching", w_Body_isTouching },
{ "getWorld", w_Body_getWorld },
{ "getFixture", w_Body_getFixture },
{ "getFixtures", w_Body_getFixtures },
{ "getShape", w_Body_getShape },
{ "getShapes", w_Body_getShapes },
{ "getJoints", w_Body_getJoints },
{ "getContacts", w_Body_getContacts },
{ "destroy", w_Body_destroy },
@@ -733,6 +740,9 @@ static const luaL_Reg w_Body_functions[] =
{ "setUserData", w_Body_setUserData },
{ "getUserData", w_Body_getUserData },
// Deprecated
{ "getFixtures", w_Body_getFixtures },
{ 0, 0 }
};
+10 -5
View File
@@ -54,9 +54,10 @@ int w_ChainShape_setPreviousVertex(lua_State *L)
int w_ChainShape_getChildEdge(lua_State *L)
{
luax_markdeprecated(L, 1, "ChainShape:getChildEdge", API_METHOD, DEPRECATED_NO_REPLACEMENT, nullptr);
ChainShape *c = luax_checkchainshape(L, 1);
int index = (int) luaL_checkinteger(L, 2) - 1; // Convert from 1-based index
EdgeShape *e = 0;
EdgeShape *e = nullptr;
luax_catchexcept(L, [&](){ e = c->getChildEdge(index); });
luax_pushtype(L, e);
e->release();
@@ -66,7 +67,8 @@ int w_ChainShape_getChildEdge(lua_State *L)
int w_ChainShape_getVertexCount(lua_State *L)
{
ChainShape *c = luax_checkchainshape(L, 1);
int count = c->getVertexCount();
int count = 0;
luax_catchexcept(L, [&]() { count = c->getVertexCount(); });
lua_pushinteger(L, count);
return 1;
}
@@ -85,7 +87,8 @@ int w_ChainShape_getPoint(lua_State *L)
int w_ChainShape_getNextVertex(lua_State *L)
{
ChainShape *c = luax_checkchainshape(L, 1);
b2Vec2 v = c->getNextVertex();
b2Vec2 v;
luax_catchexcept(L, [&]() { v = c->getNextVertex(); });
lua_pushnumber(L, v.x);
lua_pushnumber(L, v.y);
return 2;
@@ -94,7 +97,8 @@ int w_ChainShape_getNextVertex(lua_State *L)
int w_ChainShape_getPreviousVertex(lua_State *L)
{
ChainShape *c = luax_checkchainshape(L, 1);
b2Vec2 v = c->getPreviousVertex();
b2Vec2 v;
luax_catchexcept(L, [&]() { v = c->getPreviousVertex(); });
lua_pushnumber(L, v.x);
lua_pushnumber(L, v.y);
return 2;
@@ -103,7 +107,8 @@ int w_ChainShape_getPreviousVertex(lua_State *L)
int w_ChainShape_getPoints(lua_State *L)
{
ChainShape *c = luax_checkchainshape(L, 1);
const b2Vec2 *verts = c->getPoints();
const b2Vec2 *verts;
luax_catchexcept(L, [&]() { verts = c->getPoints(); });
int count = c->getVertexCount();
if (!lua_checkstack(L, count*2))
return luaL_error(L, "Too many return values");
@@ -35,7 +35,9 @@ CircleShape *luax_checkcircleshape(lua_State *L, int idx)
int w_CircleShape_getRadius(lua_State *L)
{
CircleShape *c = luax_checkcircleshape(L, 1);
lua_pushnumber(L, c->getRadius());
float r = 0;
luax_catchexcept(L, [&]() { r = c->getRadius(); });
lua_pushnumber(L, r);
return 1;
}
@@ -43,7 +45,7 @@ int w_CircleShape_setRadius(lua_State *L)
{
CircleShape *c = luax_checkcircleshape(L, 1);
float r = (float)luaL_checknumber(L, 2);
c->setRadius(r);
luax_catchexcept(L, [&]() { c->setRadius(r); });
return 0;
}
@@ -51,7 +53,7 @@ int w_CircleShape_getPoint(lua_State *L)
{
CircleShape *c = luax_checkcircleshape(L, 1);
float x, y;
c->getPoint(x, y);
luax_catchexcept(L, [&]() { c->getPoint(x, y); });
lua_pushnumber(L, x);
lua_pushnumber(L, y);
return 2;
+18 -8
View File
@@ -19,7 +19,7 @@
**/
#include "wrap_Contact.h"
#include "Fixture.h"
#include "wrap_Shape.h"
namespace love
{
@@ -139,18 +139,24 @@ int w_Contact_getChildren(lua_State *L)
return 2;
}
int w_Contact_getFixtures(lua_State *L)
int w_Contact_getShapes(lua_State *L)
{
Contact *t = luax_checkcontact(L, 1);
Fixture *a = nullptr;
Fixture *b = nullptr;
luax_catchexcept(L, [&](){ t->getFixtures(a, b); });
Shape *a = nullptr;
Shape *b = nullptr;
luax_catchexcept(L, [&](){ t->getShapes(a, b); });
luax_pushtype(L, a);
luax_pushtype(L, b);
luax_pushshape(L, a);
luax_pushshape(L, b);
return 2;
}
int w_Contact_getFixtures(lua_State *L)
{
luax_markdeprecated(L, 1, "Contact:getFixtures", API_METHOD, DEPRECATED_REPLACED, "Contact:getShapes");
return w_Contact_getShapes(L);
}
int w_Contact_isDestroyed(lua_State *L)
{
Contact *c = luax_checktype<Contact>(L, 1);
@@ -174,8 +180,12 @@ static const luaL_Reg w_Contact_functions[] =
{ "setTangentSpeed", w_Contact_setTangentSpeed },
{ "getTangentSpeed", w_Contact_getTangentSpeed },
{ "getChildren", w_Contact_getChildren },
{ "getFixtures", w_Contact_getFixtures },
{ "getShapes", w_Contact_getShapes },
{ "isDestroyed", w_Contact_isDestroyed },
// Deprecated
{ "getFixtures", w_Contact_getFixtures },
{ 0, 0 }
};
+9 -5
View File
@@ -37,7 +37,7 @@ int w_EdgeShape_setNextVertex(lua_State *L)
EdgeShape *t = luax_checkedgeshape(L, 1);
float x = (float)luaL_checknumber(L, 2);
float y = (float)luaL_checknumber(L, 3);
t->setNextVertex(x, y);
luax_catchexcept(L, [&]() { t->setNextVertex(x, y); });
return 0;
}
@@ -46,14 +46,15 @@ int w_EdgeShape_setPreviousVertex(lua_State *L)
EdgeShape *t = luax_checkedgeshape(L, 1);
float x = (float)luaL_checknumber(L, 2);
float y = (float)luaL_checknumber(L, 3);
t->setPreviousVertex(x, y);
luax_catchexcept(L, [&]() { t->setPreviousVertex(x, y); });
return 0;
}
int w_EdgeShape_getNextVertex(lua_State *L)
{
EdgeShape *t = luax_checkedgeshape(L, 1);
b2Vec2 v = t->getNextVertex();
b2Vec2 v;
luax_catchexcept(L, [&]() { v = t->getNextVertex(); });
lua_pushnumber(L, v.x);
lua_pushnumber(L, v.y);
return 2;
@@ -62,7 +63,8 @@ int w_EdgeShape_getNextVertex(lua_State *L)
int w_EdgeShape_getPreviousVertex(lua_State *L)
{
EdgeShape *t = luax_checkedgeshape(L, 1);
b2Vec2 v = t->getPreviousVertex();
b2Vec2 v;
luax_catchexcept(L, [&]() { v = t->getPreviousVertex(); });
lua_pushnumber(L, v.x);
lua_pushnumber(L, v.y);
return 2;
@@ -72,7 +74,9 @@ int w_EdgeShape_getPoints(lua_State *L)
{
EdgeShape *t = luax_checkedgeshape(L, 1);
lua_remove(L, 1);
return t->getPoints(L);
int ret = 0;
luax_catchexcept(L, [&]() { ret = t->getPoints(L); });
return ret;
}
static const luaL_Reg w_EdgeShape_functions[] =
-311
View File
@@ -1,311 +0,0 @@
/**
* Copyright (c) 2006-2023 LOVE Development Team
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
**/
#include "wrap_Fixture.h"
#include "common/StringMap.h"
namespace love
{
namespace physics
{
namespace box2d
{
Fixture *luax_checkfixture(lua_State *L, int idx)
{
Fixture *f = luax_checktype<Fixture>(L, idx);
if (!f->isValid())
luaL_error(L, "Attempt to use destroyed fixture.");
return f;
}
int w_Fixture_getType(lua_State *L)
{
Fixture *t = luax_checkfixture(L, 1);
const char *type = "";
Shape::getConstant(t->getType(), type);
lua_pushstring(L, type);
return 1;
}
int w_Fixture_setFriction(lua_State *L)
{
Fixture *t = luax_checkfixture(L, 1);
float arg1 = (float)luaL_checknumber(L, 2);
t->setFriction(arg1);
return 0;
}
int w_Fixture_setRestitution(lua_State *L)
{
Fixture *t = luax_checkfixture(L, 1);
float arg1 = (float)luaL_checknumber(L, 2);
t->setRestitution(arg1);
return 0;
}
int w_Fixture_setDensity(lua_State *L)
{
Fixture *t = luax_checkfixture(L, 1);
float arg1 = (float)luaL_checknumber(L, 2);
luax_catchexcept(L, [&](){ t->setDensity(arg1); });
return 0;
}
int w_Fixture_setSensor(lua_State *L)
{
Fixture *t = luax_checkfixture(L, 1);
bool arg1 = luax_checkboolean(L, 2);
t->setSensor(arg1);
return 0;
}
int w_Fixture_getFriction(lua_State *L)
{
Fixture *t = luax_checkfixture(L, 1);
lua_pushnumber(L, t->getFriction());
return 1;
}
int w_Fixture_getRestitution(lua_State *L)
{
Fixture *t = luax_checkfixture(L, 1);
lua_pushnumber(L, t->getRestitution());
return 1;
}
int w_Fixture_getDensity(lua_State *L)
{
Fixture *t = luax_checkfixture(L, 1);
lua_pushnumber(L, t->getDensity());
return 1;
}
int w_Fixture_isSensor(lua_State *L)
{
Fixture *t = luax_checkfixture(L, 1);
luax_pushboolean(L, t->isSensor());
return 1;
}
int w_Fixture_getBody(lua_State *L)
{
Fixture *t = luax_checkfixture(L, 1);
Body *body = t->getBody();
if (body == 0)
return 0;
luax_pushtype(L, body);
return 1;
}
int w_Fixture_getShape(lua_State *L)
{
Fixture *t = luax_checkfixture(L, 1);
Shape * shape = t->getShape();
if (shape == nullptr)
return 0;
switch (shape->getType())
{
case Shape::SHAPE_EDGE:
luax_pushtype(L, dynamic_cast<EdgeShape *>(shape));
break;
case Shape::SHAPE_CHAIN:
luax_pushtype(L, dynamic_cast<ChainShape *>(shape));
break;
case Shape::SHAPE_CIRCLE:
luax_pushtype(L, dynamic_cast<CircleShape *>(shape));
break;
case Shape::SHAPE_POLYGON:
luax_pushtype(L, dynamic_cast<PolygonShape *>(shape));
break;
default:
luax_pushtype(L, shape);
break;
}
return 1;
}
int w_Fixture_testPoint(lua_State *L)
{
Fixture *t = luax_checkfixture(L, 1);
float x = (float)luaL_checknumber(L, 2);
float y = (float)luaL_checknumber(L, 3);
luax_pushboolean(L, t->testPoint(x, y));
return 1;
}
int w_Fixture_rayCast(lua_State *L)
{
Fixture *t = luax_checkfixture(L, 1);
lua_remove(L, 1);
int ret = 0;
luax_catchexcept(L, [&](){ ret = t->rayCast(L); });
return ret;
}
int w_Fixture_setFilterData(lua_State *L)
{
Fixture *t = luax_checkfixture(L, 1);
int v[3];
v[0] = (int) luaL_checkinteger(L, 2);
v[1] = (int) luaL_checkinteger(L, 3);
v[2] = (int) luaL_checkinteger(L, 4);
t->setFilterData(v);
return 0;
}
int w_Fixture_getFilterData(lua_State *L)
{
Fixture *t = luax_checkfixture(L, 1);
int v[3];
t->getFilterData(v);
lua_pushinteger(L, v[0]);
lua_pushinteger(L, v[1]);
lua_pushinteger(L, v[2]);
return 3;
}
int w_Fixture_setCategory(lua_State *L)
{
Fixture *t = luax_checkfixture(L, 1);
lua_remove(L, 1);
return t->setCategory(L);
}
int w_Fixture_getCategory(lua_State *L)
{
Fixture *t = luax_checkfixture(L, 1);
lua_remove(L, 1);
return t->getCategory(L);
}
int w_Fixture_setMask(lua_State *L)
{
Fixture *t = luax_checkfixture(L, 1);
lua_remove(L, 1);
return t->setMask(L);
}
int w_Fixture_getMask(lua_State *L)
{
Fixture *t = luax_checkfixture(L, 1);
lua_remove(L, 1);
return t->getMask(L);
}
int w_Fixture_setUserData(lua_State *L)
{
Fixture *t = luax_checkfixture(L, 1);
lua_remove(L, 1);
return t->setUserData(L);
}
int w_Fixture_getUserData(lua_State *L)
{
Fixture *t = luax_checkfixture(L, 1);
lua_remove(L, 1);
return t->getUserData(L);
}
int w_Fixture_getBoundingBox(lua_State *L)
{
Fixture *t = luax_checkfixture(L, 1);
lua_remove(L, 1);
return t->getBoundingBox(L);
}
int w_Fixture_getMassData(lua_State *L)
{
Fixture *t = luax_checkfixture(L, 1);
lua_remove(L, 1);
return t->getMassData(L);
}
int w_Fixture_getGroupIndex(lua_State *L)
{
Fixture *t = luax_checkfixture(L, 1);
int i = t->getGroupIndex();
lua_pushinteger(L, i);
return 1;
}
int w_Fixture_setGroupIndex(lua_State *L)
{
Fixture *t = luax_checkfixture(L, 1);
int i = (int) luaL_checkinteger(L, 2);
t->setGroupIndex(i);
return 0;
}
int w_Fixture_destroy(lua_State *L)
{
Fixture *t = luax_checkfixture(L, 1);
luax_catchexcept(L, [&](){ t->destroy(); });
return 0;
}
int w_Fixture_isDestroyed(lua_State *L)
{
Fixture *f = luax_checktype<Fixture>(L, 1);
luax_pushboolean(L, !f->isValid());
return 1;
}
static const luaL_Reg w_Fixture_functions[] =
{
{ "getType", w_Fixture_getType },
{ "setFriction", w_Fixture_setFriction },
{ "setRestitution", w_Fixture_setRestitution },
{ "setDensity", w_Fixture_setDensity },
{ "setSensor", w_Fixture_setSensor },
{ "getFriction", w_Fixture_getFriction },
{ "getRestitution", w_Fixture_getRestitution },
{ "getDensity", w_Fixture_getDensity },
{ "getBody", w_Fixture_getBody },
{ "getShape", w_Fixture_getShape },
{ "isSensor", w_Fixture_isSensor },
{ "testPoint", w_Fixture_testPoint },
{ "rayCast", w_Fixture_rayCast },
{ "setFilterData", w_Fixture_setFilterData },
{ "getFilterData", w_Fixture_getFilterData },
{ "setCategory", w_Fixture_setCategory },
{ "getCategory", w_Fixture_getCategory },
{ "setMask", w_Fixture_setMask },
{ "getMask", w_Fixture_getMask },
{ "setUserData", w_Fixture_setUserData },
{ "getUserData", w_Fixture_getUserData },
{ "getBoundingBox", w_Fixture_getBoundingBox },
{ "getMassData", w_Fixture_getMassData },
{ "getGroupIndex", w_Fixture_getGroupIndex },
{ "setGroupIndex", w_Fixture_setGroupIndex },
{ "destroy", w_Fixture_destroy },
{ "isDestroyed", w_Fixture_isDestroyed },
{ 0, 0 }
};
extern "C" int luaopen_fixture(lua_State *L)
{
return luax_register_type(L, &Fixture::type, w_Fixture_functions, nullptr);
}
} // box2d
} // physics
} // love
-43
View File
@@ -1,43 +0,0 @@
/**
* Copyright (c) 2006-2023 LOVE Development Team
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
**/
#ifndef LOVE_PHYSICS_BOX2D_WRAP_FIXTURE_H
#define LOVE_PHYSICS_BOX2D_WRAP_FIXTURE_H
// LOVE
#include "common/runtime.h"
#include "Fixture.h"
#include "wrap_Physics.h"
namespace love
{
namespace physics
{
namespace box2d
{
Fixture *luax_checkfixture(lua_State *L, int idx);
extern "C" int luaopen_fixture(lua_State *L);
} // box2d
} // physics
} // love
#endif // LOVE_PHYSICS_BOX2D_WRAP_FIXTURE_H
+80 -47
View File
@@ -23,7 +23,6 @@
#include "wrap_World.h"
#include "wrap_Contact.h"
#include "wrap_Body.h"
#include "wrap_Fixture.h"
#include "wrap_Shape.h"
#include "wrap_CircleShape.h"
#include "wrap_PolygonShape.h"
@@ -256,36 +255,56 @@ int w_newChainBody(lua_State *L)
int w_newFixture(lua_State *L)
{
luax_markdeprecated(L, 1, "love.physics.newFixture", API_FUNCTION, DEPRECATED_REPLACED, "love.physics.newCircle/Rectangle/Polygon/Edge/ChainShape");
Body *body = luax_checkbody(L, 1);
Shape *shape = luax_checkshape(L, 2);
float density = (float)luaL_optnumber(L, 3, 1.0f);
Fixture *fixture;
luax_catchexcept(L, [&](){ fixture = instance()->newFixture(body, shape, density); });
luax_pushtype(L, fixture);
fixture->release();
Shape *newShape;
luax_catchexcept(L, [&]() {
newShape = instance()->newAttachedShape(body, shape, density);
newShape->setDensity(density);
body->resetMassData();
});
luax_pushshape(L, newShape);
newShape->release();
return 1;
}
static Body *luax_optbodyforshape(lua_State *L, int idx, const char *name)
{
if (luax_istype(L, idx, Body::type))
return luax_checkbody(L, idx);
luax_markdeprecated(L, 1, name, API_FUNCTION_VARIANT, DEPRECATED_REPLACED, "variant with Body parameter");
return nullptr;
}
int w_newCircleShape(lua_State *L)
{
int top = lua_gettop(L);
Body *body = luax_optbodyforshape(L, 1, "love.physics.newCircleShape");
int bodyidx = body ? 1 : 0;
int top = lua_gettop(L) - bodyidx;
if (top == 1)
{
float radius = (float)luaL_checknumber(L, 1);
float radius = (float)luaL_checknumber(L, bodyidx + 1);
CircleShape *shape;
luax_catchexcept(L, [&](){ shape = instance()->newCircleShape(0, 0, radius); });
luax_catchexcept(L, [&](){ shape = instance()->newCircleShape(body, 0, 0, radius); });
luax_pushtype(L, shape);
shape->release();
return 1;
}
else if (top == 3)
{
float x = (float)luaL_checknumber(L, 1);
float y = (float)luaL_checknumber(L, 2);
float radius = (float)luaL_checknumber(L, 3);
float x = (float)luaL_checknumber(L, bodyidx + 1);
float y = (float)luaL_checknumber(L, bodyidx + 2);
float radius = (float)luaL_checknumber(L, bodyidx + 3);
CircleShape *shape;
luax_catchexcept(L, [&](){ shape = instance()->newCircleShape(x, y, radius); });
luax_catchexcept(L, [&](){ shape = instance()->newCircleShape(body, x, y, radius); });
luax_pushtype(L, shape);
shape->release();
return 1;
@@ -296,27 +315,30 @@ int w_newCircleShape(lua_State *L)
int w_newRectangleShape(lua_State *L)
{
int top = lua_gettop(L);
Body *body = luax_optbodyforshape(L, 1, "love.physics.newRectangleShape");
int bodyidx = body ? 1 : 0;
int top = lua_gettop(L) - bodyidx;
if (top == 2)
{
float w = (float)luaL_checknumber(L, 1);
float h = (float)luaL_checknumber(L, 2);
float w = (float)luaL_checknumber(L, bodyidx + 1);
float h = (float)luaL_checknumber(L, bodyidx + 2);
PolygonShape *shape;
luax_catchexcept(L, [&](){ shape = instance()->newRectangleShape(0, 0, w, h, 0); });
luax_catchexcept(L, [&](){ shape = instance()->newRectangleShape(body, 0, 0, w, h, 0); });
luax_pushtype(L, shape);
shape->release();
return 1;
}
else if (top == 4 || top == 5)
{
float x = (float)luaL_checknumber(L, 1);
float y = (float)luaL_checknumber(L, 2);
float w = (float)luaL_checknumber(L, 3);
float h = (float)luaL_checknumber(L, 4);
float angle = (float)luaL_optnumber(L, 5, 0);
float x = (float)luaL_checknumber(L, bodyidx + 1);
float y = (float)luaL_checknumber(L, bodyidx + 2);
float w = (float)luaL_checknumber(L, bodyidx + 3);
float h = (float)luaL_checknumber(L, bodyidx + 4);
float angle = (float)luaL_optnumber(L, bodyidx + 5, 0);
PolygonShape *shape;
luax_catchexcept(L, [&](){ shape = instance()->newRectangleShape(x, y, w, h, angle); });
luax_catchexcept(L, [&](){ shape = instance()->newRectangleShape(body, x, y, w, h, angle); });
luax_pushtype(L, shape);
shape->release();
return 1;
@@ -327,13 +349,16 @@ int w_newRectangleShape(lua_State *L)
int w_newEdgeShape(lua_State *L)
{
float x1 = (float)luaL_checknumber(L, 1);
float y1 = (float)luaL_checknumber(L, 2);
float x2 = (float)luaL_checknumber(L, 3);
float y2 = (float)luaL_checknumber(L, 4);
bool oneSided = luax_optboolean(L, 5, false);
Body *body = luax_optbodyforshape(L, 1, "love.physics.newEdgeShape");
int bodyidx = body ? 1 : 0;
float x1 = (float)luaL_checknumber(L, bodyidx + 1);
float y1 = (float)luaL_checknumber(L, bodyidx + 2);
float x2 = (float)luaL_checknumber(L, bodyidx + 3);
float y2 = (float)luaL_checknumber(L, bodyidx + 4);
bool oneSided = luax_optboolean(L, bodyidx + 5, false);
EdgeShape *shape;
luax_catchexcept(L, [&](){ shape = instance()->newEdgeShape(x1, y1, x2, y2, oneSided); });
luax_catchexcept(L, [&](){ shape = instance()->newEdgeShape(body, x1, y1, x2, y2, oneSided); });
luax_pushtype(L, shape);
shape->release();
return 1;
@@ -341,12 +366,15 @@ int w_newEdgeShape(lua_State *L)
int w_newPolygonShape(lua_State *L)
{
int argc = lua_gettop(L);
Body *body = luax_optbodyforshape(L, 1, "love.physics.newPolygonShape");
int bodyidx = body ? 1 : 0;
bool istable = lua_istable(L, 1);
int argc = lua_gettop(L) - bodyidx;
bool istable = lua_istable(L, bodyidx + 1);
if (istable)
argc = (int)luax_objlen(L, 1);
argc = (int)luax_objlen(L, bodyidx + 1);
if (argc % 2 != 0)
return luaL_error(L, "Number of vertex components must be a multiple of two.");
@@ -358,8 +386,8 @@ int w_newPolygonShape(lua_State *L)
{
for (int i = 0; i < vcount; i++)
{
lua_rawgeti(L, 1, 1 + i * 2);
lua_rawgeti(L, 1, 2 + i * 2);
lua_rawgeti(L, bodyidx + 1, 1 + i * 2);
lua_rawgeti(L, bodyidx + 1, 2 + i * 2);
float x = (float)luaL_checknumber(L, -2);
float y = (float)luaL_checknumber(L, -1);
coords.emplace_back(x, y);
@@ -370,14 +398,14 @@ int w_newPolygonShape(lua_State *L)
{
for (int i = 0; i < vcount; i++)
{
float x = (float)luaL_checknumber(L, 1 + i * 2);
float y = (float)luaL_checknumber(L, 2 + i * 2);
float x = (float)luaL_checknumber(L, bodyidx + 1 + i * 2);
float y = (float)luaL_checknumber(L, bodyidx + 2 + i * 2);
coords.emplace_back(x, y);
}
}
PolygonShape *shape = nullptr;
luax_catchexcept(L, [&](){ shape = instance()->newPolygonShape(coords.data(), (int)coords.size()); });
luax_catchexcept(L, [&](){ shape = instance()->newPolygonShape(body, coords.data(), (int)coords.size()); });
luax_pushtype(L, shape);
shape->release();
return 1;
@@ -385,26 +413,29 @@ int w_newPolygonShape(lua_State *L)
int w_newChainShape(lua_State *L)
{
int argc = lua_gettop(L) - 1; // first argument is looping
Body *body = luax_optbodyforshape(L, 1, "love.physics.newChainShape");
int bodyidx = body ? 1 : 0;
bool istable = lua_istable(L, 2);
int argc = lua_gettop(L) - 1 - bodyidx; // first argument is looping
bool istable = lua_istable(L, bodyidx + 2);
if (istable)
argc = (int)luax_objlen(L, 2);
argc = (int)luax_objlen(L, bodyidx + 2);
if (argc == 0 || argc % 2 != 0)
return luaL_error(L, "Number of vertex components must be a multiple of two.");
int vcount = argc / 2;
bool loop = luax_checkboolean(L, 1);
bool loop = luax_checkboolean(L, bodyidx + 1);
std::vector<Vector2> coords;
if (istable)
{
for (int i = 0; i < vcount; i++)
{
lua_rawgeti(L, 2, 1 + i * 2);
lua_rawgeti(L, 2, 2 + i * 2);
lua_rawgeti(L, bodyidx + 2, 1 + i * 2);
lua_rawgeti(L, bodyidx + 2, 2 + i * 2);
float x = (float)lua_tonumber(L, -2);
float y = (float)lua_tonumber(L, -1);
coords.emplace_back(x, y);
@@ -415,14 +446,14 @@ int w_newChainShape(lua_State *L)
{
for (int i = 0; i < vcount; i++)
{
float x = (float)luaL_checknumber(L, 2 + i * 2);
float y = (float)luaL_checknumber(L, 3 + i * 2);
float x = (float)luaL_checknumber(L, bodyidx + 2 + i * 2);
float y = (float)luaL_checknumber(L, bodyidx + 3 + i * 2);
coords.emplace_back(x, y);
}
}
ChainShape *shape = nullptr;
luax_catchexcept(L, [&]() { shape = instance()->newChainShape(loop, coords.data(), coords.size()); });
luax_catchexcept(L, [&]() { shape = instance()->newChainShape(body, loop, coords.data(), coords.size()); });
luax_pushtype(L, shape);
shape->release();
return 1;
@@ -824,7 +855,6 @@ static const luaL_Reg functions[] =
{ "newPolygonBody", w_newPolygonBody },
{ "newEdgeBody", w_newEdgeBody },
{ "newChainBody", w_newChainBody },
{ "newFixture", w_newFixture },
{ "newCircleShape", w_newCircleShape },
{ "newRectangleShape", w_newRectangleShape },
{ "newPolygonShape", w_newPolygonShape },
@@ -848,6 +878,10 @@ static const luaL_Reg functions[] =
{ "computeLinearFrequency", w_computeLinearFrequency },
{ "computeAngularStiffness", w_computeAngularStiffness },
{ "computeAngularFrequency", w_computeAngularFrequency },
// Deprecated
{ "newFixture", w_newFixture },
{ 0, 0 },
};
@@ -856,7 +890,6 @@ static const lua_CFunction types[] =
luaopen_world,
luaopen_contact,
luaopen_body,
luaopen_fixture,
luaopen_shape,
luaopen_circleshape,
luaopen_polygonshape,
@@ -36,13 +36,17 @@ int w_PolygonShape_getPoints(lua_State *L)
{
PolygonShape *t = luax_checkpolygonshape(L, 1);
lua_remove(L, 1);
return t->getPoints(L);
int ret = 0;
luax_catchexcept(L, [&]() { ret = t->getPoints(L); });
return ret;
}
int w_PolygonShape_validate(lua_State *L)
{
PolygonShape *t = luax_checkpolygonshape(L, 1);
luax_pushboolean(L, t->validate());
bool valid = false;
luax_catchexcept(L, [&]() { valid = t->validate(); });
luax_pushboolean(L, valid);
return 1;
}
+285 -8
View File
@@ -33,6 +33,35 @@ Shape *luax_checkshape(lua_State *L, int idx)
return luax_checktype<Shape>(L, idx);
}
void luax_pushshape(lua_State *L, Shape *shape)
{
if (shape != nullptr)
{
switch (shape->getType())
{
case Shape::SHAPE_CIRCLE:
luax_pushtype(L, (CircleShape *) shape);
break;
case Shape::SHAPE_POLYGON:
luax_pushtype(L, (PolygonShape *) shape);
break;
case Shape::SHAPE_EDGE:
luax_pushtype(L, (EdgeShape *) shape);
break;
case Shape::SHAPE_CHAIN:
luax_pushtype(L, (ChainShape *) shape);
break;
default:
luax_pushtype(L, shape);
break;
}
}
else
{
lua_pushnil(L);
}
}
int w_Shape_getType(lua_State *L)
{
Shape *t = luax_checkshape(L, 1);
@@ -45,7 +74,8 @@ int w_Shape_getType(lua_State *L)
int w_Shape_getRadius(lua_State *L)
{
Shape *t = luax_checkshape(L, 1);
float radius = t->getRadius();
float radius = 0;
luax_catchexcept(L, [&]() { radius = t->getRadius(); });
lua_pushnumber(L, radius);
return 1;
}
@@ -53,20 +83,115 @@ int w_Shape_getRadius(lua_State *L)
int w_Shape_getChildCount(lua_State *L)
{
Shape *t = luax_checkshape(L, 1);
int childCount = t->getChildCount();
int childCount = 0;
luax_catchexcept(L, [&]() { childCount = t->getChildCount(); });
lua_pushinteger(L, childCount);
return 1;
}
int w_Shape_setFriction(lua_State *L)
{
Shape *t = luax_checkshape(L, 1);
float arg1 = (float)luaL_checknumber(L, 2);
luax_catchexcept(L, [&]() { t->setFriction(arg1); });
return 0;
}
int w_Shape_setRestitution(lua_State *L)
{
Shape *t = luax_checkshape(L, 1);
float arg1 = (float)luaL_checknumber(L, 2);
luax_catchexcept(L, [&]() { t->setRestitution(arg1); });
return 0;
}
int w_Shape_setDensity(lua_State *L)
{
Shape *t = luax_checkshape(L, 1);
float arg1 = (float)luaL_checknumber(L, 2);
luax_catchexcept(L, [&](){ t->setDensity(arg1); });
return 0;
}
int w_Shape_setSensor(lua_State *L)
{
Shape *t = luax_checkshape(L, 1);
bool arg1 = luax_checkboolean(L, 2);
luax_catchexcept(L, [&]() { t->setSensor(arg1); });
return 0;
}
int w_Shape_getFriction(lua_State *L)
{
Shape *t = luax_checkshape(L, 1);
float friction = 0;
luax_catchexcept(L, [&]() { friction = t->getFriction(); });
lua_pushnumber(L, friction);
return 1;
}
int w_Shape_getRestitution(lua_State *L)
{
Shape *t = luax_checkshape(L, 1);
float r = 0;
luax_catchexcept(L, [&]() { r = t->getRestitution(); });
lua_pushnumber(L, r);
return 1;
}
int w_Shape_getDensity(lua_State *L)
{
Shape *t = luax_checkshape(L, 1);
float d = 0;
luax_catchexcept(L, [&]() { d = t->getDensity(); });
lua_pushnumber(L, d);
return 1;
}
int w_Shape_isSensor(lua_State *L)
{
Shape *t = luax_checkshape(L, 1);
bool sensor = false;
luax_catchexcept(L, [&]() { sensor = t->isSensor(); });
luax_pushboolean(L, sensor);
return 1;
}
int w_Shape_getBody(lua_State *L)
{
Shape *t = luax_checkshape(L, 1);
Body *body = t->getBody();
if (body == nullptr)
return 0;
luax_pushtype(L, body);
return 1;
}
int w_Shape_getShape(lua_State *L)
{
luax_markdeprecated(L, 1, "Fixture:getShape", API_METHOD, DEPRECATED_NO_REPLACEMENT, nullptr);
Shape *t = luax_checkshape(L, 1);
luax_pushshape(L, t);
return 1;
}
int w_Shape_testPoint(lua_State *L)
{
Shape *t = luax_checkshape(L, 1);
float x = (float)luaL_checknumber(L, 2);
float y = (float)luaL_checknumber(L, 3);
float r = (float)luaL_checknumber(L, 4);
float px = (float)luaL_checknumber(L, 5);
float py = (float)luaL_checknumber(L, 6);
bool result = t->testPoint(x, y, r, px, py);
bool result = false;
if (!lua_isnoneornil(L, 4))
{
float r = (float)luaL_checknumber(L, 4);
float px = (float)luaL_checknumber(L, 5);
float py = (float)luaL_checknumber(L, 6);
result = luax_catchexcept(L, [&]() { t->testPoint(x, y, r, px, py); });
}
else
{
result = luax_catchexcept(L, [&]() { t->testPoint(x, y); });
}
lua_pushboolean(L, result);
return 1;
}
@@ -84,14 +209,143 @@ int w_Shape_computeAABB(lua_State *L)
{
Shape *t = luax_checkshape(L, 1);
lua_remove(L, 1);
return t->computeAABB(L);
int ret = 0;
luax_catchexcept(L, [&]() { ret = t->computeAABB(L); });
return ret;
}
int w_Shape_computeMass(lua_State *L)
{
Shape *t = luax_checkshape(L, 1);
lua_remove(L, 1);
return t->computeMass(L);
int ret = 0;
luax_catchexcept(L, [&]() { ret = t->computeMass(L); });
return ret;
}
int w_Shape_setFilterData(lua_State *L)
{
Shape *t = luax_checkshape(L, 1);
int v[3];
v[0] = (int) luaL_checkinteger(L, 2);
v[1] = (int) luaL_checkinteger(L, 3);
v[2] = (int) luaL_checkinteger(L, 4);
luax_catchexcept(L, [&]() { t->setFilterData(v); });
return 0;
}
int w_Shape_getFilterData(lua_State *L)
{
Shape *t = luax_checkshape(L, 1);
int v[3];
luax_catchexcept(L, [&]() { t->getFilterData(v); });
lua_pushinteger(L, v[0]);
lua_pushinteger(L, v[1]);
lua_pushinteger(L, v[2]);
return 3;
}
int w_Shape_setCategory(lua_State *L)
{
Shape *t = luax_checkshape(L, 1);
lua_remove(L, 1);
int ret = 0;
luax_catchexcept(L, [&]() { ret = t->setCategory(L); });
return ret;
}
int w_Shape_getCategory(lua_State *L)
{
Shape *t = luax_checkshape(L, 1);
lua_remove(L, 1);
int ret = 0;
luax_catchexcept(L, [&]() { ret = t->getCategory(L); });
return ret;
}
int w_Shape_setMask(lua_State *L)
{
Shape *t = luax_checkshape(L, 1);
lua_remove(L, 1);
int ret = 0;
luax_catchexcept(L, [&]() { ret = t->setMask(L); });
return ret;
}
int w_Shape_getMask(lua_State *L)
{
Shape *t = luax_checkshape(L, 1);
lua_remove(L, 1);
int ret = 0;
luax_catchexcept(L, [&]() { ret = t->getMask(L); });
return ret;
}
int w_Shape_setUserData(lua_State *L)
{
Shape *t = luax_checkshape(L, 1);
lua_remove(L, 1);
int ret = 0;
luax_catchexcept(L, [&]() { ret = t->setUserData(L); });
return ret;
}
int w_Shape_getUserData(lua_State *L)
{
Shape *t = luax_checkshape(L, 1);
lua_remove(L, 1);
int ret = 0;
luax_catchexcept(L, [&]() { ret = t->getUserData(L); });
return ret;
}
int w_Shape_getBoundingBox(lua_State *L)
{
Shape *t = luax_checkshape(L, 1);
lua_remove(L, 1);
int ret = 0;
luax_catchexcept(L, [&]() { ret = t->getBoundingBox(L); });
return ret;
}
int w_Shape_getMassData(lua_State *L)
{
Shape *t = luax_checkshape(L, 1);
lua_remove(L, 1);
int ret = 0;
luax_catchexcept(L, [&]() { ret = t->getMassData(L); });
return ret;
}
int w_Shape_getGroupIndex(lua_State *L)
{
Shape *t = luax_checkshape(L, 1);
int i = 0;
luax_catchexcept(L, [&]() { i = t->getGroupIndex(); });
lua_pushinteger(L, i);
return 1;
}
int w_Shape_setGroupIndex(lua_State *L)
{
Shape *t = luax_checkshape(L, 1);
int i = (int) luaL_checkinteger(L, 2);
luax_catchexcept(L, [&]() { t->setGroupIndex(i); });
return 0;
}
int w_Shape_destroy(lua_State *L)
{
Shape *t = luax_checkshape(L, 1);
luax_catchexcept(L, [&](){ t->destroy(); });
return 0;
}
int w_Shape_isDestroyed(lua_State *L)
{
Shape *f = luax_checktype<Shape>(L, 1);
luax_pushboolean(L, !f->isValid());
return 1;
}
const luaL_Reg w_Shape_functions[] =
@@ -99,10 +353,33 @@ const luaL_Reg w_Shape_functions[] =
{ "getType", w_Shape_getType },
{ "getRadius", w_Shape_getRadius },
{ "getChildCount", w_Shape_getChildCount },
{ "setFriction", w_Shape_setFriction },
{ "setRestitution", w_Shape_setRestitution },
{ "setDensity", w_Shape_setDensity },
{ "setSensor", w_Shape_setSensor },
{ "getFriction", w_Shape_getFriction },
{ "getRestitution", w_Shape_getRestitution },
{ "getDensity", w_Shape_getDensity },
{ "getBody", w_Shape_getBody },
{ "isSensor", w_Shape_isSensor },
{ "testPoint", w_Shape_testPoint },
{ "rayCast", w_Shape_rayCast },
{ "computeAABB", w_Shape_computeAABB },
{ "computeMass", w_Shape_computeMass },
{ "setFilterData", w_Shape_setFilterData },
{ "getFilterData", w_Shape_getFilterData },
{ "setCategory", w_Shape_setCategory },
{ "getCategory", w_Shape_getCategory },
{ "setMask", w_Shape_setMask },
{ "getMask", w_Shape_getMask },
{ "setUserData", w_Shape_setUserData },
{ "getUserData", w_Shape_getUserData },
{ "getBoundingBox", w_Shape_getBoundingBox },
{ "getMassData", w_Shape_getMassData },
{ "getGroupIndex", w_Shape_getGroupIndex },
{ "setGroupIndex", w_Shape_setGroupIndex },
{ "destroy", w_Shape_destroy },
{ "isDestroyed", w_Shape_isDestroyed },
{ 0, 0 }
};
+1
View File
@@ -34,6 +34,7 @@ namespace box2d
{
Shape *luax_checkshape(lua_State *L, int idx);
void luax_pushshape(lua_State *L, Shape *shape);
extern "C" int luaopen_shape(lua_State *L);
extern const luaL_Reg w_Shape_functions[];
+8 -8
View File
@@ -178,25 +178,25 @@ int w_World_getContacts(lua_State *L)
return ret;
}
int w_World_queryFixturesInArea(lua_State *L)
int w_World_queryShapesInArea(lua_State *L)
{
World *t = luax_checkworld(L, 1);
lua_remove(L, 1);
return t->queryFixturesInArea(L);
return t->queryShapesInArea(L);
}
int w_World_queryBoundingBox(lua_State *L)
{
luax_markdeprecated(L, 1, "World:queryBoundingBox", API_METHOD, DEPRECATED_RENAMED, "World:queryFixturesInArea");
return w_World_queryFixturesInArea(L);
luax_markdeprecated(L, 1, "World:queryBoundingBox", API_METHOD, DEPRECATED_RENAMED, "World:queryShapesInArea");
return w_World_queryShapesInArea(L);
}
int w_World_getFixturesInArea(lua_State *L)
int w_World_getShapesInArea(lua_State *L)
{
World *t = luax_checkworld(L, 1);
lua_remove(L, 1);
int ret = 0;
luax_catchexcept(L, [&](){ ret = t->getFixturesInArea(L); });
luax_catchexcept(L, [&](){ ret = t->getShapesInArea(L); });
return ret;
}
@@ -260,8 +260,8 @@ static const luaL_Reg w_World_functions[] =
{ "getBodies", w_World_getBodies },
{ "getJoints", w_World_getJoints },
{ "getContacts", w_World_getContacts },
{ "queryFixturesInArea", w_World_queryFixturesInArea },
{ "getFixturesInArea", w_World_getFixturesInArea },
{ "queryShapesInArea", w_World_queryShapesInArea },
{ "getShapesInArea", w_World_getShapesInArea },
{ "rayCast", w_World_rayCast },
{ "rayCastAny", w_World_rayCastAny },
{ "rayCastClosest", w_World_rayCastClosest },