mirror of
https://github.com/love2d/love.git
synced 2026-08-15 15:51:12 +02:00
Add World:rayCastAny and World:rayCastClosest.
They return hit position, normal, and ray fraction (if there is a hit), and also take an optional fixture category bitmask parameter.
This commit is contained in:
@@ -237,6 +237,30 @@ float World::RayCastCallback::ReportFixture(b2Fixture *fixture, const b2Vec2 &po
|
||||
return 0;
|
||||
}
|
||||
|
||||
World::RayCastOneCallback::RayCastOneCallback(uint16 categoryMask, bool any)
|
||||
: hit(false)
|
||||
, hitPoint()
|
||||
, hitNormal()
|
||||
, hitFraction(1.0f)
|
||||
, categoryMask(categoryMask)
|
||||
, any(any)
|
||||
{
|
||||
}
|
||||
|
||||
float World::RayCastOneCallback::ReportFixture(b2Fixture *fixture, const b2Vec2 &point, const b2Vec2 &normal, float fraction)
|
||||
{
|
||||
if (categoryMask != 0xFFFF && (categoryMask & fixture->GetFilterData().categoryBits) == 0)
|
||||
return -1;
|
||||
|
||||
hit = true;
|
||||
hitPoint = point;
|
||||
hitNormal = normal;
|
||||
hitFraction = fraction;
|
||||
|
||||
// Returning the fraction makes sure it doesn't process anything farther away in subsequent iterations.
|
||||
return any ? 0 : fraction;
|
||||
}
|
||||
|
||||
void World::SayGoodbye(b2Fixture *fixture)
|
||||
{
|
||||
Fixture *f = (Fixture *)(fixture->GetUserData().pointer);
|
||||
@@ -612,6 +636,54 @@ int World::rayCast(lua_State *L)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int World::rayCastAny(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);
|
||||
uint16 categoryMaskBits = (uint16)luaL_optinteger(L, 5, 0xFFFF);
|
||||
b2Vec2 v1 = Physics::scaleDown(b2Vec2(x1, y1));
|
||||
b2Vec2 v2 = Physics::scaleDown(b2Vec2(x2, y2));
|
||||
RayCastOneCallback raycast(categoryMaskBits, true);
|
||||
world->RayCast(&raycast, v1, v2);
|
||||
if (raycast.hit)
|
||||
{
|
||||
b2Vec2 hitPoint = Physics::scaleUp(raycast.hitPoint);
|
||||
lua_pushnumber(L, hitPoint.x);
|
||||
lua_pushnumber(L, hitPoint.y);
|
||||
lua_pushnumber(L, raycast.hitNormal.x);
|
||||
lua_pushnumber(L, raycast.hitNormal.y);
|
||||
lua_pushnumber(L, raycast.hitFraction);
|
||||
return 5;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int World::rayCastClosest(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);
|
||||
uint16 categoryMaskBits = (uint16)luaL_optinteger(L, 5, 0xFFFF);
|
||||
b2Vec2 v1 = Physics::scaleDown(b2Vec2(x1, y1));
|
||||
b2Vec2 v2 = Physics::scaleDown(b2Vec2(x2, y2));
|
||||
RayCastOneCallback raycast(categoryMaskBits, false);
|
||||
world->RayCast(&raycast, v1, v2);
|
||||
if (raycast.hit)
|
||||
{
|
||||
b2Vec2 hitPoint = Physics::scaleUp(raycast.hitPoint);
|
||||
lua_pushnumber(L, hitPoint.x);
|
||||
lua_pushnumber(L, hitPoint.y);
|
||||
lua_pushnumber(L, raycast.hitNormal.x);
|
||||
lua_pushnumber(L, raycast.hitNormal.y);
|
||||
lua_pushnumber(L, raycast.hitFraction);
|
||||
return 5;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void World::destroy()
|
||||
{
|
||||
if (world == nullptr)
|
||||
|
||||
@@ -94,8 +94,8 @@ public:
|
||||
{
|
||||
public:
|
||||
QueryCallback(World *world, lua_State *L, int idx);
|
||||
~QueryCallback();
|
||||
virtual bool ReportFixture(b2Fixture *fixture);
|
||||
virtual ~QueryCallback();
|
||||
bool ReportFixture(b2Fixture *fixture) override;
|
||||
private:
|
||||
World *world;
|
||||
lua_State *L;
|
||||
@@ -107,8 +107,8 @@ public:
|
||||
{
|
||||
public:
|
||||
CollectCallback(World *world, lua_State *L);
|
||||
~CollectCallback();
|
||||
virtual bool ReportFixture(b2Fixture *fixture);
|
||||
virtual ~CollectCallback();
|
||||
bool ReportFixture(b2Fixture *fixture) override;
|
||||
private:
|
||||
World *world;
|
||||
lua_State *L;
|
||||
@@ -119,8 +119,8 @@ public:
|
||||
{
|
||||
public:
|
||||
RayCastCallback(World *world, lua_State *L, int idx);
|
||||
~RayCastCallback();
|
||||
virtual float ReportFixture(b2Fixture *fixture, const b2Vec2 &point, const b2Vec2 &normal, float fraction);
|
||||
virtual ~RayCastCallback();
|
||||
float ReportFixture(b2Fixture *fixture, const b2Vec2 &point, const b2Vec2 &normal, float fraction) override;
|
||||
private:
|
||||
World *world;
|
||||
lua_State *L;
|
||||
@@ -128,6 +128,23 @@ public:
|
||||
int userargs;
|
||||
};
|
||||
|
||||
class RayCastOneCallback : public b2RayCastCallback
|
||||
{
|
||||
public:
|
||||
RayCastOneCallback(uint16 categoryMask, bool any);
|
||||
virtual ~RayCastOneCallback() {};
|
||||
float ReportFixture(b2Fixture* fixture, const b2Vec2& point, const b2Vec2& normal, float fraction) override;
|
||||
|
||||
bool hit;
|
||||
b2Vec2 hitPoint;
|
||||
b2Vec2 hitNormal;
|
||||
float hitFraction;
|
||||
|
||||
private:
|
||||
uint16 categoryMask;
|
||||
bool any;
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a new world.
|
||||
**/
|
||||
@@ -298,6 +315,9 @@ public:
|
||||
**/
|
||||
int rayCast(lua_State *L);
|
||||
|
||||
int rayCastAny(lua_State *L);
|
||||
int rayCastClosest(lua_State *L);
|
||||
|
||||
/**
|
||||
* Destroy this world.
|
||||
**/
|
||||
|
||||
@@ -185,7 +185,7 @@ int w_World_queryFixturesInArea(lua_State *L)
|
||||
return t->queryFixturesInArea(L);
|
||||
}
|
||||
|
||||
int w_World_queryBoundingBox(lua_State* 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);
|
||||
@@ -209,6 +209,24 @@ int w_World_rayCast(lua_State *L)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int w_World_rayCastAny(lua_State *L)
|
||||
{
|
||||
World *t = luax_checkworld(L, 1);
|
||||
lua_remove(L, 1);
|
||||
int ret = 0;
|
||||
luax_catchexcept(L, [&]() { ret = t->rayCastAny(L); });
|
||||
return ret;
|
||||
}
|
||||
|
||||
int w_World_rayCastClosest(lua_State *L)
|
||||
{
|
||||
World *t = luax_checkworld(L, 1);
|
||||
lua_remove(L, 1);
|
||||
int ret = 0;
|
||||
luax_catchexcept(L, [&]() { ret = t->rayCastClosest(L); });
|
||||
return ret;
|
||||
}
|
||||
|
||||
int w_World_destroy(lua_State *L)
|
||||
{
|
||||
World *t = luax_checkworld(L, 1);
|
||||
@@ -245,6 +263,8 @@ static const luaL_Reg w_World_functions[] =
|
||||
{ "queryFixturesInArea", w_World_queryFixturesInArea },
|
||||
{ "getFixturesInArea", w_World_getFixturesInArea },
|
||||
{ "rayCast", w_World_rayCast },
|
||||
{ "rayCastAny", w_World_rayCastAny },
|
||||
{ "rayCastClosest", w_World_rayCastClosest },
|
||||
{ "destroy", w_World_destroy },
|
||||
{ "isDestroyed", w_World_isDestroyed },
|
||||
|
||||
|
||||
Reference in New Issue
Block a user