Browse Source

Merge pull request #1835 from Klonan/world-get-fixtures-in-area

Added World:getFixturesInArea()
slime73 3 years ago
parent
commit
f1e09ab2e6

+ 3 - 2
changes.txt

@@ -45,6 +45,7 @@ Released: N/A
 * Added love.keyboard.isModifierActive.
 * Added love.keyboard.isModifierActive.
 * Added love.system.getPreferredLocales.
 * Added love.system.getPreferredLocales.
 * Added love.localechanged callback.
 * Added love.localechanged callback.
+* Added World:getFixturesInArea().
 
 
 * Changed the default font from Vera size 12 to Noto Sans size 13.
 * Changed the default font from Vera size 12 to Noto Sans size 13.
 * Changed the Texture class and implementation to no longer have separate Canvas and Image subclasses.
 * Changed the Texture class and implementation to no longer have separate Canvas and Image subclasses.
@@ -165,7 +166,7 @@ Released: 2019-10-27
 * Fixed audio clicks immediately after playing a Source on iOS.
 * Fixed audio clicks immediately after playing a Source on iOS.
 * Fixed Source:play + Source:stop + Source:play looping the first few ms of sound for streaming Sources on iOS.
 * Fixed Source:play + Source:stop + Source:play looping the first few ms of sound for streaming Sources on iOS.
 * Fixed Source:play + Source:seek looping the first few ms of sound for streaming Sources on iOS.
 * Fixed Source:play + Source:seek looping the first few ms of sound for streaming Sources on iOS.
-* Fixed occasional pops in streaming sources on iOS. 
+* Fixed occasional pops in streaming sources on iOS.
 * Fixed love.audio.play(sources) to use previously set playback positions on stopped Sources.
 * Fixed love.audio.play(sources) to use previously set playback positions on stopped Sources.
 * Fixed Source:setEffect(name, true) and Source:getEffect(name) when the effect has no associated Filter.
 * Fixed Source:setEffect(name, true) and Source:getEffect(name) when the effect has no associated Filter.
 * Fixed love.audio.newSource(filename, "queue") to cause a Lua error.
 * Fixed love.audio.newSource(filename, "queue") to cause a Lua error.
@@ -437,7 +438,7 @@ Released: 2016-10-31
 
 
   * Improved performance of Channel methods by roughly 2x in many cases.
   * Improved performance of Channel methods by roughly 2x in many cases.
   * Improved performance of Shader:send when small numbers of arguments are given.
   * Improved performance of Shader:send when small numbers of arguments are given.
-  
+
   * Updated love.filesystem.mount to accept a DroppedFile as the first parameter.
   * Updated love.filesystem.mount to accept a DroppedFile as the first parameter.
   * Updated Shader:send to do type and argument checking based on the specified uniform variable's information instead of the arguments to the function.
   * Updated Shader:send to do type and argument checking based on the specified uniform variable's information instead of the arguments to the function.
   * Updated Shader:send to accept a flat table for matrix uniforms.
   * Updated Shader:send to accept a flat table for matrix uniforms.

+ 36 - 0
src/modules/physics/box2d/World.cpp

@@ -171,6 +171,28 @@ bool World::QueryCallback::ReportFixture(b2Fixture *fixture)
 	return true;
 	return true;
 }
 }
 
 
+World::CollectCallback::CollectCallback(World *world, lua_State *L)
+	: world(world)
+	, L(L)
+{
+	lua_newtable(L);
+}
+
+World::CollectCallback::~CollectCallback()
+{
+}
+
+bool World::CollectCallback::ReportFixture(b2Fixture *f)
+{
+	Fixture *fixture = (Fixture *)world->findObject(f);
+	if (!fixture)
+		throw love::Exception("A fixture has escaped Memoizer!");
+	luax_pushtype(L, fixture);
+	lua_rawseti(L, -2, i);
+	i++;
+	return true;
+}
+
 World::RayCastCallback::RayCastCallback(World *world, lua_State *L, int idx)
 World::RayCastCallback::RayCastCallback(World *world, lua_State *L, int idx)
 	: world(world)
 	: world(world)
 	, L(L)
 	, L(L)
@@ -556,6 +578,20 @@ int World::queryBoundingBox(lua_State *L)
 	return 0;
 	return 0;
 }
 }
 
 
+int World::getFixturesInArea(lua_State *L)
+{
+	float lx = (float)luaL_checknumber(L, 1);
+	float ly = (float)luaL_checknumber(L, 2);
+	float ux = (float)luaL_checknumber(L, 3);
+	float uy = (float)luaL_checknumber(L, 4);
+	b2AABB box;
+	box.lowerBound = Physics::scaleDown(b2Vec2(lx, ly));
+	box.upperBound = Physics::scaleDown(b2Vec2(ux, uy));
+	CollectCallback query(this, L);
+	world->QueryAABB(&query, box);
+	return 1;
+}
+
 int World::rayCast(lua_State *L)
 int World::rayCast(lua_State *L)
 {
 {
 	float x1 = (float)luaL_checknumber(L, 1);
 	float x1 = (float)luaL_checknumber(L, 1);

+ 18 - 1
src/modules/physics/box2d/World.h

@@ -102,6 +102,18 @@ public:
 		int funcidx;
 		int funcidx;
 	};
 	};
 
 
+	class CollectCallback : public b2QueryCallback
+	{
+	public:
+		CollectCallback(World *world, lua_State *L);
+		~CollectCallback();
+		virtual bool ReportFixture(b2Fixture *fixture);
+	private:
+		World *world;
+		lua_State *L;
+		int i = 1;
+	};
+
 	class RayCastCallback : public b2RayCastCallback
 	class RayCastCallback : public b2RayCastCallback
 	{
 	{
 	public:
 	public:
@@ -270,10 +282,15 @@ public:
 	b2Body *getGroundBody() const;
 	b2Body *getGroundBody() const;
 
 
 	/**
 	/**
-	 * Gets all fixtures that overlap a given bounding box.
+	 * Calls a callback on all fixtures that overlap a given bounding box.
 	 **/
 	 **/
 	int queryBoundingBox(lua_State *L);
 	int queryBoundingBox(lua_State *L);
 
 
+	/**
+	 * Gets all fixtures that overlap a given bounding box.
+	 **/
+	int getFixturesInArea(lua_State *L);
+
 	/**
 	/**
 	 * Raycasts the World for all Fixtures in the path of the ray.
 	 * Raycasts the World for all Fixtures in the path of the ray.
 	 **/
 	 **/

+ 10 - 0
src/modules/physics/box2d/wrap_World.cpp

@@ -185,6 +185,15 @@ int w_World_queryBoundingBox(lua_State *L)
 	return t->queryBoundingBox(L);
 	return t->queryBoundingBox(L);
 }
 }
 
 
+int w_World_getFixturesInArea(lua_State *L)
+{
+	World *t = luax_checkworld(L, 1);
+	lua_remove(L, 1);
+	int ret = 0;
+	luax_catchexcept(L, [&](){ ret = t->getFixturesInArea(L); });
+	return ret;
+}
+
 int w_World_rayCast(lua_State *L)
 int w_World_rayCast(lua_State *L)
 {
 {
 	World *t = luax_checkworld(L, 1);
 	World *t = luax_checkworld(L, 1);
@@ -228,6 +237,7 @@ static const luaL_Reg w_World_functions[] =
 	{ "getJoints", w_World_getJoints },
 	{ "getJoints", w_World_getJoints },
 	{ "getContacts", w_World_getContacts },
 	{ "getContacts", w_World_getContacts },
 	{ "queryBoundingBox", w_World_queryBoundingBox },
 	{ "queryBoundingBox", w_World_queryBoundingBox },
+	{ "getFixturesInArea", w_World_getFixturesInArea },
 	{ "rayCast", w_World_rayCast },
 	{ "rayCast", w_World_rayCast },
 	{ "destroy", w_World_destroy },
 	{ "destroy", w_World_destroy },
 	{ "isDestroyed", w_World_isDestroyed },
 	{ "isDestroyed", w_World_isDestroyed },