mirror of
https://github.com/love2d/love.git
synced 2026-08-17 11:00:31 +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;
|
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)
|
void World::SayGoodbye(b2Fixture *fixture)
|
||||||
{
|
{
|
||||||
Fixture *f = (Fixture *)(fixture->GetUserData().pointer);
|
Fixture *f = (Fixture *)(fixture->GetUserData().pointer);
|
||||||
@@ -612,6 +636,54 @@ int World::rayCast(lua_State *L)
|
|||||||
return 0;
|
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()
|
void World::destroy()
|
||||||
{
|
{
|
||||||
if (world == nullptr)
|
if (world == nullptr)
|
||||||
|
|||||||
@@ -94,8 +94,8 @@ public:
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
QueryCallback(World *world, lua_State *L, int idx);
|
QueryCallback(World *world, lua_State *L, int idx);
|
||||||
~QueryCallback();
|
virtual ~QueryCallback();
|
||||||
virtual bool ReportFixture(b2Fixture *fixture);
|
bool ReportFixture(b2Fixture *fixture) override;
|
||||||
private:
|
private:
|
||||||
World *world;
|
World *world;
|
||||||
lua_State *L;
|
lua_State *L;
|
||||||
@@ -107,8 +107,8 @@ public:
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CollectCallback(World *world, lua_State *L);
|
CollectCallback(World *world, lua_State *L);
|
||||||
~CollectCallback();
|
virtual ~CollectCallback();
|
||||||
virtual bool ReportFixture(b2Fixture *fixture);
|
bool ReportFixture(b2Fixture *fixture) override;
|
||||||
private:
|
private:
|
||||||
World *world;
|
World *world;
|
||||||
lua_State *L;
|
lua_State *L;
|
||||||
@@ -119,8 +119,8 @@ public:
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
RayCastCallback(World *world, lua_State *L, int idx);
|
RayCastCallback(World *world, lua_State *L, int idx);
|
||||||
~RayCastCallback();
|
virtual ~RayCastCallback();
|
||||||
virtual float ReportFixture(b2Fixture *fixture, const b2Vec2 &point, const b2Vec2 &normal, float fraction);
|
float ReportFixture(b2Fixture *fixture, const b2Vec2 &point, const b2Vec2 &normal, float fraction) override;
|
||||||
private:
|
private:
|
||||||
World *world;
|
World *world;
|
||||||
lua_State *L;
|
lua_State *L;
|
||||||
@@ -128,6 +128,23 @@ public:
|
|||||||
int userargs;
|
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.
|
* Creates a new world.
|
||||||
**/
|
**/
|
||||||
@@ -298,6 +315,9 @@ public:
|
|||||||
**/
|
**/
|
||||||
int rayCast(lua_State *L);
|
int rayCast(lua_State *L);
|
||||||
|
|
||||||
|
int rayCastAny(lua_State *L);
|
||||||
|
int rayCastClosest(lua_State *L);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Destroy this world.
|
* Destroy this world.
|
||||||
**/
|
**/
|
||||||
|
|||||||
@@ -185,7 +185,7 @@ int w_World_queryFixturesInArea(lua_State *L)
|
|||||||
return t->queryFixturesInArea(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");
|
luax_markdeprecated(L, 1, "World:queryBoundingBox", API_METHOD, DEPRECATED_RENAMED, "World:queryFixturesInArea");
|
||||||
return w_World_queryFixturesInArea(L);
|
return w_World_queryFixturesInArea(L);
|
||||||
@@ -209,6 +209,24 @@ int w_World_rayCast(lua_State *L)
|
|||||||
return ret;
|
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)
|
int w_World_destroy(lua_State *L)
|
||||||
{
|
{
|
||||||
World *t = luax_checkworld(L, 1);
|
World *t = luax_checkworld(L, 1);
|
||||||
@@ -245,6 +263,8 @@ static const luaL_Reg w_World_functions[] =
|
|||||||
{ "queryFixturesInArea", w_World_queryFixturesInArea },
|
{ "queryFixturesInArea", w_World_queryFixturesInArea },
|
||||||
{ "getFixturesInArea", w_World_getFixturesInArea },
|
{ "getFixturesInArea", w_World_getFixturesInArea },
|
||||||
{ "rayCast", w_World_rayCast },
|
{ "rayCast", w_World_rayCast },
|
||||||
|
{ "rayCastAny", w_World_rayCastAny },
|
||||||
|
{ "rayCastClosest", w_World_rayCastClosest },
|
||||||
{ "destroy", w_World_destroy },
|
{ "destroy", w_World_destroy },
|
||||||
{ "isDestroyed", w_World_isDestroyed },
|
{ "isDestroyed", w_World_isDestroyed },
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user