Browse Source

Rename ParticleSystem:setAreaSpread to setEmissionArea, and move the functionality from setAreaSpreadAngle/setAreSpreadIsRelativeDirection into setEmissionArea. Resolves issue #1311.

Alex Szpakowski 7 years ago
parent
commit
ac52666c6f

+ 55 - 69
src/modules/graphics/ParticleSystem.cpp

@@ -65,9 +65,9 @@ ParticleSystem::ParticleSystem(Texture *texture, uint32 size)
 	, activeParticles(0)
 	, emissionRate(0)
 	, emitCounter(0)
-	, areaSpreadDistribution(DISTRIBUTION_NONE)
-	, areaSpreadAngle(0)
-	, areaSpreadIsRelativeDirection(false)
+	, emissionAreaDistribution(DISTRIBUTION_NONE)
+	, emissionAreaAngle(0)
+	, directionRelativeToEmissionCenter(false)
 	, lifetime(-1)
 	, life(0)
 	, particleLifeMin(0)
@@ -122,10 +122,10 @@ ParticleSystem::ParticleSystem(const ParticleSystem &p)
 	, emitCounter(0.0f)
 	, position(p.position)
 	, prevPosition(p.prevPosition)
-	, areaSpreadDistribution(p.areaSpreadDistribution)
-	, areaSpread(p.areaSpread)
-	, areaSpreadAngle(p.areaSpreadAngle)
-	, areaSpreadIsRelativeDirection(p.areaSpreadIsRelativeDirection)
+	, emissionAreaDistribution(p.emissionAreaDistribution)
+	, emissionArea(p.emissionArea)
+	, emissionAreaAngle(p.emissionAreaAngle)
+	, directionRelativeToEmissionCenter(p.directionRelativeToEmissionCenter)
 	, lifetime(p.lifetime)
 	, life(p.lifetime) // Initialize with the maximum life time.
 	, particleLifeMin(p.particleLifeMin)
@@ -275,61 +275,67 @@ void ParticleSystem::initParticle(Particle *p, float t)
 	// In this switch statement, variables 'rand_y', 'min', and 'max'
 	// are sometimes reused as data stores for performance reasons
 	float rand_x, rand_y;
-	switch (areaSpreadDistribution)
+	float c, s;
+	switch (emissionAreaDistribution)
 	{
 	case DISTRIBUTION_UNIFORM:
-		rand_x = (float) rng.random(-areaSpread.x, areaSpread.x);
-		rand_y = (float) rng.random(-areaSpread.y, areaSpread.y);
-		p->position.x += cosf(areaSpreadAngle) * rand_x - sinf(areaSpreadAngle) * rand_y;
-		p->position.y += sinf(areaSpreadAngle) * rand_x + cosf(areaSpreadAngle) * rand_y;
+		c = cosf(emissionAreaAngle); s = sinf(emissionAreaAngle);
+		rand_x = (float) rng.random(-emissionArea.x, emissionArea.x);
+		rand_y = (float) rng.random(-emissionArea.y, emissionArea.y);
+		p->position.x += c * rand_x - s * rand_y;
+		p->position.y += s * rand_x + c * rand_y;
 		break;
 	case DISTRIBUTION_NORMAL:
-		rand_x = (float) rng.randomNormal(areaSpread.x);
-		rand_y = (float) rng.randomNormal(areaSpread.y);
-		p->position.x += cosf(areaSpreadAngle) * rand_x - sinf(areaSpreadAngle) * rand_y;
-		p->position.y += sinf(areaSpreadAngle) * rand_x + cosf(areaSpreadAngle) * rand_y;
+		c = cosf(emissionAreaAngle); s = sinf(emissionAreaAngle);
+		rand_x = (float) rng.randomNormal(emissionArea.x);
+		rand_y = (float) rng.randomNormal(emissionArea.y);
+		p->position.x += c * rand_x - s * rand_y;
+		p->position.y += s * rand_x + c * rand_y;
 		break;
 	case DISTRIBUTION_ELLIPSE:
+		c = cosf(emissionAreaAngle); s = sinf(emissionAreaAngle);
 		rand_x = (float) rng.random(-1, 1);
 		rand_y = (float) rng.random(-1, 1);
-		min = areaSpread.x * (rand_x * sqrt(1 - 0.5f*pow(rand_y, 2)));
-		max = areaSpread.y * (rand_y * sqrt(1 - 0.5f*pow(rand_x, 2)));
-		p->position.x += cosf(areaSpreadAngle) * min - sinf(areaSpreadAngle) * max;
-		p->position.y += sinf(areaSpreadAngle) * min + cosf(areaSpreadAngle) * max;
+		min = emissionArea.x * (rand_x * sqrt(1 - 0.5f*pow(rand_y, 2)));
+		max = emissionArea.y * (rand_y * sqrt(1 - 0.5f*pow(rand_x, 2)));
+		p->position.x += c * min - s * max;
+		p->position.y += s * min + c * max;
 		break;
 	case DISTRIBUTION_BORDER_ELLIPSE:
+		c = cosf(emissionAreaAngle); s = sinf(emissionAreaAngle);
 		rand_x = (float) rng.random(0, LOVE_M_PI * 2);
-		min = cosf(rand_x) * areaSpread.x;
-		max = sinf(rand_x) * areaSpread.y;
-		p->position.x += cosf(areaSpreadAngle) * min - sinf(areaSpreadAngle) * max;
-		p->position.y += sinf(areaSpreadAngle) * min + cosf(areaSpreadAngle) * max;
+		min = cosf(rand_x) * emissionArea.x;
+		max = sinf(rand_x) * emissionArea.y;
+		p->position.x += c * min - s * max;
+		p->position.y += s * min + c * max;
 		break;
 	case DISTRIBUTION_BORDER_RECTANGLE:
-		rand_x = (float) rng.random((areaSpread.x + areaSpread.y) * -2, (areaSpread.x + areaSpread.y) * 2);
-		rand_y = areaSpread.y * 2;
+		c = cosf(emissionAreaAngle); s = sinf(emissionAreaAngle);
+		rand_x = (float) rng.random((emissionArea.x + emissionArea.y) * -2, (emissionArea.x + emissionArea.y) * 2);
+		rand_y = emissionArea.y * 2;
 		if (rand_x < -rand_y)
 		{
-			min = rand_x + rand_y + areaSpread.x;
-			p->position.x += cosf(areaSpreadAngle) * min - sinf(areaSpreadAngle) * -areaSpread.y;
-			p->position.y += sinf(areaSpreadAngle) * min + cosf(areaSpreadAngle) * -areaSpread.y;
+			min = rand_x + rand_y + emissionArea.x;
+			p->position.x += c * min - s * -emissionArea.y;
+			p->position.y += s * min + c * -emissionArea.y;
 		}
 		else if (rand_x < 0)
 		{
-			max = rand_x + areaSpread.y;
-			p->position.x += cosf(areaSpreadAngle) * -areaSpread.x - sinf(areaSpreadAngle) * max;
-			p->position.y += sinf(areaSpreadAngle) * -areaSpread.x + cosf(areaSpreadAngle) * max;
+			max = rand_x + emissionArea.y;
+			p->position.x += c * -emissionArea.x - s * max;
+			p->position.y += s * -emissionArea.x + c * max;
 		}
 		else if (rand_x < rand_y)
 		{
-			max = rand_x - areaSpread.y;
-			p->position.x += cosf(areaSpreadAngle) * areaSpread.x - sinf(areaSpreadAngle) * max;
-			p->position.y += sinf(areaSpreadAngle) * areaSpread.x + cosf(areaSpreadAngle) * max;
+			max = rand_x - emissionArea.y;
+			p->position.x += c * emissionArea.x - s * max;
+			p->position.y += s * emissionArea.x + c * max;
 		}
 		else
 		{
-			min = rand_x - rand_y - areaSpread.x;
-			p->position.x += cosf(areaSpreadAngle) * min - sinf(areaSpreadAngle) * areaSpread.y;
-			p->position.y += sinf(areaSpreadAngle) * min + cosf(areaSpreadAngle) * areaSpread.y;
+			min = rand_x - rand_y - emissionArea.x;
+			p->position.x += c * min - s * emissionArea.y;
+			p->position.y += s * min + c * emissionArea.y;
 		}
 		break;
 	case DISTRIBUTION_NONE:
@@ -338,7 +344,7 @@ void ParticleSystem::initParticle(Particle *p, float t)
 	}
 
 	// Determine if the origin of each particle is the center of the area
-	if (areaSpreadIsRelativeDirection)
+	if (directionRelativeToEmissionCenter)
 		dir += atan2(p->position.y - pos.y, p->position.x - pos.x);
 
 	p->origin = pos;
@@ -571,40 +577,20 @@ void ParticleSystem::moveTo(float x, float y)
 	position = love::Vector2(x, y);
 }
 
-void ParticleSystem::setAreaSpread(AreaSpreadDistribution distribution, float x, float y)
+void ParticleSystem::setEmissionArea(AreaSpreadDistribution distribution, float x, float y, float angle, bool directionRelativeToCenter)
 {
-	areaSpread = love::Vector2(x, y);
-	areaSpreadDistribution = distribution;
+	emissionArea = love::Vector2(x, y);
+	emissionAreaDistribution = distribution;
+	emissionAreaAngle = angle;
+	directionRelativeToEmissionCenter = directionRelativeToCenter;
 }
 
-ParticleSystem::AreaSpreadDistribution ParticleSystem::getAreaSpreadDistribution() const
+ParticleSystem::AreaSpreadDistribution ParticleSystem::getEmissionArea(love::Vector2 &params, float &angle, bool &directionRelativeToCenter) const
 {
-	return areaSpreadDistribution;
-}
-
-const love::Vector2 &ParticleSystem::getAreaSpreadParameters() const
-{
-	return areaSpread;
-}
-
-void ParticleSystem::setAreaSpreadAngle(float angle)
-{
-	areaSpreadAngle = angle;
-}
-
-float ParticleSystem::getAreaSpreadAngle() const
-{
-	return areaSpreadAngle;
-}
-
-void ParticleSystem::setAreaSpreadIsRelativeDirection(bool isRelativeDirection)
-{
-	areaSpreadIsRelativeDirection = isRelativeDirection;
-}
-
-bool ParticleSystem::getAreaSpreadIsRelativeDirection() const
-{
-	return areaSpreadIsRelativeDirection;
+	params = emissionArea;
+	angle = emissionAreaAngle;
+	directionRelativeToCenter = directionRelativeToEmissionCenter;
+	return emissionAreaDistribution;
 }
 
 void ParticleSystem::setDirection(float direction)

+ 10 - 36
src/modules/graphics/ParticleSystem.h

@@ -202,45 +202,19 @@ public:
 	 * * Normal: Parameters denote the standard deviation in x and y direction. x and y are assumed to be uncorrelated.
 	 * * borderellipse: Parameter causes particle distribution around outside of ellipse
 	 * * borderrectangle: Parameter causes particle distribution around outside of rectangle
+	 * @param distribution Distribution type
 	 * @param x First parameter. Interpretation depends on distribution type.
 	 * @param y Second parameter. Interpretation depends on distribution type.
-	 * @param distribution Distribution type
-	 **/
-	void setAreaSpread(AreaSpreadDistribution distribution, float x, float y);
-
-	/**
-	 * Returns area spread distribution type.
+	 * @param angle The angle of the emission area (in radians).
+	 * @param directionRelativeToCenter whether the initial direction of
+	 *        particles points away from the center of the emission area.
 	 **/
-	AreaSpreadDistribution getAreaSpreadDistribution() const;
+	void setEmissionArea(AreaSpreadDistribution distribution, float x, float y, float angle, bool directionRelativeToCenter);
 
 	/**
 	 * Returns area spread parameters.
 	 **/
-	const love::Vector2 &getAreaSpreadParameters() const;
-
-	/**
-	 * Returns the angle of the area distribution (in radians).
-	 **/
-	float getAreaSpreadAngle() const;
-
-	/**
-	 * Sets the angle of the area distribution
-	 * @param angle The angle (in radians).
-	 **/
-	void setAreaSpreadAngle(float angle);
-
-	/**
-	 * Returns true if particles spawn relative to the center of the 
-	 * shape area or false if they will use the setDirection parameter
-	 **/
-	bool getAreaSpreadIsRelativeDirection() const;
-
-	/**
-	 * Sets if particles starting direction is away from the center of the
-	 * area spread or the setDirection parameter
-	 * @param isRelativeDirection boolean use relative direction from center
-	 **/
-	void setAreaSpreadIsRelativeDirection(bool isRelativeDirection);
+	AreaSpreadDistribution getEmissionArea(love::Vector2 &params, float &angle, bool &directionRelativeToCenter) const;
 
 	/**
 	 * Sets the direction of the particle emitter.
@@ -636,10 +610,10 @@ private:
 	love::Vector2 prevPosition;
 
 	// Emission area spread.
-	AreaSpreadDistribution areaSpreadDistribution;
-	love::Vector2 areaSpread;
-	float areaSpreadAngle;
-	bool areaSpreadIsRelativeDirection;
+	AreaSpreadDistribution emissionAreaDistribution;
+	love::Vector2 emissionArea;
+	float emissionAreaAngle;
+	bool directionRelativeToEmissionCenter;
 
 	// The lifetime of the particle emitter (-1 means infinite) and the life it has left.
 	float lifetime;

+ 69 - 43
src/modules/graphics/wrap_ParticleSystem.cpp

@@ -196,14 +196,16 @@ int w_ParticleSystem_moveTo(lua_State *L)
 	return 0;
 }
 
-int w_ParticleSystem_setAreaSpread(lua_State *L)
+int w_ParticleSystem_setEmissionArea(lua_State *L)
 {
 	ParticleSystem *t = luax_checkparticlesystem(L, 1);
 
 	ParticleSystem::AreaSpreadDistribution distribution = ParticleSystem::DISTRIBUTION_NONE;
 	float x = 0.f, y = 0.f;
+	float angle = 0.0f;
+	bool directionRelativeToCenter = false;
 
-	const char *str = lua_isnoneornil(L, 2) ? 0 : luaL_checkstring(L, 2);
+	const char *str = lua_isnoneornil(L, 2) ? nullptr : luaL_checkstring(L, 2);
 	if (str && !ParticleSystem::getConstant(str, distribution))
 		return luax_enumerror(L, "particle distribution", ParticleSystem::getConstants(distribution), str);
 
@@ -213,55 +215,32 @@ int w_ParticleSystem_setAreaSpread(lua_State *L)
 		y = (float) luaL_checknumber(L, 4);
 		if (x < 0.0f || y < 0.0f)
 			return luaL_error(L, "Invalid area spread parameters (must be >= 0)");
+
+		angle = (float) luaL_optnumber(L, 5, 0.0f);
+		directionRelativeToCenter = luax_optboolean(L, 6, false);
 	}
 
-	t->setAreaSpread(distribution, x, y);
+	t->setEmissionArea(distribution, x, y, angle, directionRelativeToCenter);
 	return 0;
 }
 
-int w_ParticleSystem_getAreaSpread(lua_State *L)
+int w_ParticleSystem_getEmissionArea(lua_State *L)
 {
 	ParticleSystem *t = luax_checkparticlesystem(L, 1);
-	ParticleSystem::AreaSpreadDistribution distribution = t-> getAreaSpreadDistribution();
+	love::Vector2 p;
+	float angle;
+	bool directionRelativeToCenter;
+	ParticleSystem::AreaSpreadDistribution distribution = t->getEmissionArea(p, angle, directionRelativeToCenter);
 	const char *str;
 	ParticleSystem::getConstant(distribution, str);
-	const love::Vector2 &p = t->getAreaSpreadParameters();
 
 	lua_pushstring(L, str);
 	lua_pushnumber(L, p.x);
 	lua_pushnumber(L, p.y);
+	lua_pushnumber(L, angle);
+	luax_pushboolean(L, directionRelativeToCenter);
 
-	return 3;
-}
-
-int w_ParticleSystem_setAreaSpreadAngle(lua_State *L)
-{
-	ParticleSystem *t = luax_checkparticlesystem(L, 1);
-	float arg1 = (float)luaL_checknumber(L, 2);
-	t->setAreaSpreadAngle(arg1);
-	return 0;
-}
-
-int w_ParticleSystem_getAreaSpreadAngle(lua_State *L)
-{
-	ParticleSystem *t = luax_checkparticlesystem(L, 1);
-	lua_pushnumber(L, t->getAreaSpreadAngle());
-	return 1;
-}
-
-int w_ParticleSystem_setAreaSpreadIsRelativeDirection(lua_State *L)
-{
-	ParticleSystem *t = luax_checkparticlesystem(L, 1);
-	bool arg1 = luax_checkboolean(L, 2);
-	t->setAreaSpreadIsRelativeDirection(arg1);
-	return 0;
-}
-
-int w_ParticleSystem_getAreaSpreadIsRelativeDirection(lua_State *L)
-{
-	ParticleSystem *t = luax_checkparticlesystem(L, 1);
-	luax_pushboolean(L, t->getAreaSpreadIsRelativeDirection());
-	return 1;
+	return 5;
 }
 
 int w_ParticleSystem_setDirection(lua_State *L)
@@ -734,6 +713,52 @@ int w_ParticleSystem_update(lua_State *L)
 	return 0;
 }
 
+// Deprecated functions.
+
+int w_ParticleSystem_setAreaSpread(lua_State *L)
+{
+	luax_markdeprecated(L, "ParticleSystem:setAreaSpread", API_METHOD, DEPRECATED_REPLACED, "ParticleSystem:setEmissionArea");
+
+	ParticleSystem *t = luax_checkparticlesystem(L, 1);
+
+	ParticleSystem::AreaSpreadDistribution distribution = ParticleSystem::DISTRIBUTION_NONE;
+	float x = 0.f, y = 0.f;
+
+	const char *str = lua_isnoneornil(L, 2) ? 0 : luaL_checkstring(L, 2);
+	if (str && !ParticleSystem::getConstant(str, distribution))
+		return luax_enumerror(L, "particle distribution", ParticleSystem::getConstants(distribution), str);
+
+	if (distribution != ParticleSystem::DISTRIBUTION_NONE)
+	{
+		x = (float) luaL_checknumber(L, 3);
+		y = (float) luaL_checknumber(L, 4);
+		if (x < 0.0f || y < 0.0f)
+			return luaL_error(L, "Invalid area spread parameters (must be >= 0)");
+	}
+
+	t->setEmissionArea(distribution, x, y, 0.0f, false);
+	return 0;
+}
+
+int w_ParticleSystem_getAreaSpread(lua_State *L)
+{
+	luax_markdeprecated(L, "ParticleSystem:getAreaSpread", API_METHOD, DEPRECATED_REPLACED, "ParticleSystem:getEmissionArea");
+
+	ParticleSystem *t = luax_checkparticlesystem(L, 1);
+	love::Vector2 p;
+	float angle;
+	bool unused;
+	ParticleSystem::AreaSpreadDistribution distribution = t->getEmissionArea(p, angle, unused);
+	const char *str;
+	ParticleSystem::getConstant(distribution, str);
+
+	lua_pushstring(L, str);
+	lua_pushnumber(L, p.x);
+	lua_pushnumber(L, p.y);
+
+	return 3;
+}
+
 static const luaL_Reg w_ParticleSystem_functions[] =
 {
 	{ "clone", w_ParticleSystem_clone },
@@ -752,12 +777,8 @@ static const luaL_Reg w_ParticleSystem_functions[] =
 	{ "setPosition", w_ParticleSystem_setPosition },
 	{ "getPosition", w_ParticleSystem_getPosition },
 	{ "moveTo", w_ParticleSystem_moveTo },
-	{ "setAreaSpread", w_ParticleSystem_setAreaSpread },
-	{ "getAreaSpread", w_ParticleSystem_getAreaSpread },
-	{ "setAreaSpreadAngle", w_ParticleSystem_setAreaSpreadAngle },
-	{ "getAreaSpreadAngle", w_ParticleSystem_getAreaSpreadAngle },
-	{ "setAreaSpreadIsRelativeDirection", w_ParticleSystem_setAreaSpreadIsRelativeDirection },
-	{ "getAreaSpreadIsRelativeDirection", w_ParticleSystem_getAreaSpreadIsRelativeDirection },
+	{ "setEmissionArea", w_ParticleSystem_setEmissionArea },
+	{ "getEmissionArea", w_ParticleSystem_getEmissionArea },
 	{ "setDirection", w_ParticleSystem_setDirection },
 	{ "getDirection", w_ParticleSystem_getDirection },
 	{ "setSpread", w_ParticleSystem_setSpread },
@@ -800,6 +821,11 @@ static const luaL_Reg w_ParticleSystem_functions[] =
 	{ "isPaused", w_ParticleSystem_isPaused },
 	{ "isStopped", w_ParticleSystem_isStopped },
 	{ "update", w_ParticleSystem_update },
+
+	// Deprecated.
+	{ "setAreaSpread", w_ParticleSystem_setAreaSpread },
+	{ "getAreaSpread", w_ParticleSystem_getAreaSpread },
+
 	{ 0, 0 }
 };