From da4b99de2cf290ccdd22587a8c50aeeadd5ac957 Mon Sep 17 00:00:00 2001
From: Stijn Buys <ingar@osirion.org>
Date: Sat, 20 Dec 2008 21:32:51 +0000
Subject: single file particle scripts

---
 src/render/particles.cc | 145 ++++++++++++++++++++++++++++++++++--------------
 src/render/particles.h  |  23 ++++++--
 src/render/render.cc    |  13 +++--
 src/render/renderext.cc |   5 +-
 4 files changed, 135 insertions(+), 51 deletions(-)

(limited to 'src/render')

diff --git a/src/render/particles.cc b/src/render/particles.cc
index f9271ab..3a9521b 100644
--- a/src/render/particles.cc
+++ b/src/render/particles.cc
@@ -31,6 +31,31 @@ Particle::Particle(const math::Vector3f &location, const math::Axis &axis, float
 
 ParticleScript::Registry ParticleScript::particles_registry;
 
+void ParticleScript::list()
+{
+	std::string str;
+	for (Registry::iterator it = particles_registry.begin(); it != particles_registry.end(); it++) {
+		
+		ParticleScript *script = (*it).second;
+		switch (script->type()) {
+			case Flame:
+				str.assign("flame");
+				break;
+			case Jet:
+				str.assign("jet");
+				break;
+			case Spray:
+				str.assign("spray");
+				break;
+			case Trail:
+				str.assign("trail");
+				break;
+		}
+		con_print << "  " << script->label() << " " << str << std::endl;
+		con_print << particles_registry.size() << " particle scripts" << std::endl;
+	}
+}
+
 void ParticleScript::clear()
 {
 	for (Registry::iterator it = particles_registry.begin(); it != particles_registry.end(); it++) {
@@ -50,22 +75,24 @@ ParticleScript *ParticleScript::find(const std::string &label)
 		return 0;
 	}
 }
-	
-void ParticleScript::init()
-{
-	clear();
 
-	ParticleScript *script = 0;
+ParticleScript *ParticleScript::load(const std::string &label)
+{
+	ParticleScript *script = find(label);
+	if (script)
+		return script;
 
 	filesystem::IniFile inifile;
-	inifile.open("particles");
+
+	inifile.open("particles/" + label);
 
 	if (!inifile.is_open()) {
-		con_error << "Could not open " << inifile.name() << std::endl;
-		return;
+		con_warn << "Could not open " << inifile.name() << std::endl;
+		return 0;
 	}
 
-	con_print << "^BLoading particle systems..." << std::endl;
+	script = new ParticleScript(label);
+	con_debug << "  " << inifile.name() << std::endl;
 
 	std::string strval;
 
@@ -73,29 +100,16 @@ void ParticleScript::init()
 
 		if (inifile.got_section()) {
 			if (inifile.got_section("particles")) {
-				if (script) {
-					if (script->label().size()) {
-						if (find(script->label())) {
-							con_warn << "Duplicate particle system '" << script->label() << "'" << std::endl;
-							delete script;
-						} else {
-							particles_registry[script->label()] = script;
-						}
-					} else {
-						con_warn << "Particle system without label" << std::endl;
-						delete script;
-					}
-				}
-				script = new ParticleScript();
+				continue;
+			} else {
+				inifile.unknown_section();
 			}
 
 		} else if (inifile.got_key()) {
 
 			if (inifile.in_section("particles")) {
 
-				if (inifile.got_key_string("label", script->particles_label)) {
-					continue;
-				} else if (inifile.got_key_string("type", strval)) {
+				if (inifile.got_key_string("type", strval)) {
 					aux::to_label(strval);
 					if (strval.compare("flame") == 0) {
 						script->particles_type = ParticleScript::Flame;
@@ -132,28 +146,17 @@ void ParticleScript::init()
 			}
 		}
 	}
+
 	inifile.close();
 
-	if (script) {
-		if (script->label().size()) {
-			if (find(script->label())) {
-				con_warn << "Duplicate particle system '" << script->label() << "'" << std::endl;
-				delete script;
-			} else {
-				particles_registry[script->label()] = script;
-			}
-		} else {
-			con_warn << "Particle system without label" << std::endl;
-			delete script;
-		}
-	}
+	particles_registry[script->label()] = script;
 
-	con_debug << "  " << inifile.name() << " " << particles_registry.size() << " " << aux::plural("particle system", particles_registry.size()) << std::endl;
+	return script;
 }
 
 /* ---- class ParticleScript --------------------------------------- */
 
-ParticleScript::ParticleScript()
+ParticleScript::ParticleScript(const std::string label) : particles_label(label)
 {
 	particles_radius = 1.0f;
 	particles_alpha = 1.0f;
@@ -324,6 +327,66 @@ void Jet::draw(float elapsed) {
 		gl::end();
 	}
 }
+/* ---- class Spray ------------------------------------------------ */
+
+Spray::Spray(ParticleScript *script, core::Entity *entity, model::Particles *modelclass) :
+		ParticleSystem(script, entity, modelclass) {
+}
+
+Spray::~Spray()
+{}
+
+void Spray::draw(float elapsed) {
+	if (!particlesystem_script)
+		return;
+
+	ParticleSystem::draw(elapsed);
+
+	math::Vector3f quad[4];
+
+	if (particlesystem_stream.size()) {
+		Textures::bind(particlesystem_texture);
+		gl::begin(gl::Quads);
+
+		for (Stream::iterator it = particlesystem_stream.begin(); it != particlesystem_stream.end(); it++) {
+			Particle *particle = (*it);
+			
+			quad[0].assign(Camera::axis().up() - Camera::axis().left());
+			quad[1].assign(Camera::axis().up() + Camera::axis().left());
+			quad[2].assign(Camera::axis().up() * -1 + Camera::axis().left());
+			quad[3].assign(Camera::axis().up() * -1 - Camera::axis().left());
+			
+			float t = now - particle->time();
+			float f = 0;
+
+			if (t < particlesystem_script->timeout() * 0.1f) {
+				f = t / (0.1f * particlesystem_script->timeout());
+			} else {
+				t = t - particlesystem_script->timeout() * 0.1f;
+				f = t / (0.9f * particlesystem_script->timeout());
+				f = 1.0 - f;
+			}
+
+			f *= f;
+			float radius = particlesystem_script->radius() * f;
+			color.a = f * particlesystem_script->alpha();
+			gl::color(color);
+	
+			glTexCoord2f(0,1);
+			gl::vertex(particle->location() + quad[0] * radius);
+			glTexCoord2f(0,0);
+			gl::vertex(particle->location() + quad[1] * radius);
+			glTexCoord2f(1,0);
+			gl::vertex(particle->location() + quad[2] * radius);
+			glTexCoord2f(1,1);
+			gl::vertex(particle->location() + quad[3] * radius);
+			Stats::quads++;
+		}
+
+		gl::end();
+	}
+}
+
 
 /* ---- class Trail ------------------------------------------------ */
 
diff --git a/src/render/particles.h b/src/render/particles.h
index 9c9d44b..88789a5 100644
--- a/src/render/particles.h
+++ b/src/render/particles.h
@@ -45,7 +45,7 @@ protected:
 class ParticleScript {
 public:
 
-	enum Type {Jet=0, Trail=1, Flame=2 };
+	enum Type {Jet=0, Trail=1, Flame=2, Spray=3 };
 
 	inline const Type type() const { return particles_type; }
 
@@ -66,15 +66,16 @@ public:
 	inline float alpha() const { return particles_alpha; }
 
 	inline float offset() const { return particles_offset; }
-
-	static ParticleScript *find(const std::string &label);
 	
-	static void init();
+	static ParticleScript *load(const std::string &label);
 
 	static void clear();
 
+	static void list();
 private:
-	ParticleScript();
+	static ParticleScript *find(const std::string &label);
+
+	ParticleScript(const std::string label);
 	~ParticleScript();
 
 	std::string	particles_label;
@@ -171,6 +172,18 @@ public:
 	virtual void draw(float elapsed);
 };
 
+/* ---- class Spray ----------------------------------------------- */
+
+/// spray style particles
+class Spray : public ParticleSystem
+{
+public:
+	Spray(ParticleScript *script, core::Entity *entity, model::Particles *modelclass);
+	virtual ~Spray();
+	
+	virtual void draw(float elapsed);
+};
+
 /* ---- class Trail ------------------------------------------------ */
 
 /// trail style particles, like an engine trail
diff --git a/src/render/render.cc b/src/render/render.cc
index 1abd197..dcede48 100644
--- a/src/render/render.cc
+++ b/src/render/render.cc
@@ -37,6 +37,11 @@ void func_list_textures(std::string const &args)
 	Textures::list();
 }
 
+void func_list_particles(std::string const &args)
+{
+	ParticleScript::list();
+}
+
 void init(int width, int height) 
 {
 	con_print << "^BInitializing renderer..." << std::endl;
@@ -56,8 +61,6 @@ void init(int width, int height)
 
 	Dust::init();
 
-	ParticleScript::init();
-
 	// size of the vertex array in megabytes
 	r_arraysize = core::Cvar::get("r_arraysize", 0.0f , core::Cvar::Archive);
 	r_arraysize->set_info("[int] size of the vertex array in Mb");
@@ -95,6 +98,9 @@ void init(int width, int height)
 	// engine functions
 	core::Func *func = core::Func::add("list_textures", func_list_textures);
 	func->set_info("list loaded textures");
+
+	func = core::Func::add("list_particles", func_list_particles);
+	func->set_info("list loaded particle scripts");
 }
 
 // unload game assets (zone change)
@@ -177,8 +183,6 @@ void reset()
 
 	Textures::init();
 
-	ParticleScript::init();
-
 	size_t mb = (size_t) r_arraysize->value();
 	if (mb < 4 * sizeof(float))
 		mb = 4 * sizeof(float);
@@ -199,6 +203,7 @@ void shutdown()
 {
 	con_print << "^BShutting down renderer..." << std::endl;
 
+	core::Func::remove("list_particles");
 	core::Func::remove("list_textures");
 
 	clear();
diff --git a/src/render/renderext.cc b/src/render/renderext.cc
index d2d5a71..7c514df 100644
--- a/src/render/renderext.cc
+++ b/src/render/renderext.cc
@@ -57,7 +57,7 @@ RenderExt::RenderExt(core::Entity *entity) : core::Extension(core::Extension::Re
 			model::Particles *particlesystem = (*pit);
 
 			// load particle systems			
-			ParticleScript *script = ParticleScript::find(particlesystem->script());
+			ParticleScript *script = ParticleScript::load(particlesystem->script());
 			if (script) {
 				if (script->type() == render::ParticleScript::Trail) {
 					Trail *trail = new Trail(script, entity, particlesystem);
@@ -65,6 +65,9 @@ RenderExt::RenderExt(core::Entity *entity) : core::Extension(core::Extension::Re
 				} else if (script->type() == render::ParticleScript::Jet) {
 					Jet *jet = new Jet(script, entity, particlesystem);
 					state_particles.push_back(jet);
+				} else if (script->type() == render::ParticleScript::Spray) {
+					Spray *spray = new Spray(script, entity, particlesystem);
+					state_particles.push_back(spray);
 				} else if (script->type() == render::ParticleScript::Flame) {
 					Flame *flame = new Flame(script, entity, particlesystem);
 					state_particles.push_back(flame);
-- 
cgit v1.2.3