From d4f9da2f3c19511b028da2569d7b6a8d1371e135 Mon Sep 17 00:00:00 2001 From: Stijn Buys Date: Sun, 20 Jan 2013 21:37:11 +0000 Subject: Major overhaul of the particle system back-end, support multiple ejectors per particle system. --- src/render/particlesystemscript.cc | 313 +++++++++++++++++++++++++++++++++++++ 1 file changed, 313 insertions(+) create mode 100644 src/render/particlesystemscript.cc (limited to 'src/render/particlesystemscript.cc') diff --git a/src/render/particlesystemscript.cc b/src/render/particlesystemscript.cc new file mode 100644 index 0000000..98c0a2d --- /dev/null +++ b/src/render/particlesystemscript.cc @@ -0,0 +1,313 @@ +/* + render/particlesystemscript.cc + This file is part of the Osirion project and is distributed under + the terms of the GNU General Public License version 2 +*/ + +#include "render/particlesystemscript.h" +#include "render/textures.h" + +namespace render +{ + +/* ---- static ParticleSystemScript registry ---------------------------------- */ + +ParticleSystemScript::Registry ParticleSystemScript::script_registry; + +void ParticleSystemScript::list() +{ + + for (Registry::const_iterator it = script_registry.begin(); it != script_registry.end(); ++it) { + + const ParticleSystemScript *script = (*it).second; + std::string strval; + + for (Ejectors::const_iterator eit = script->script_ejectors.begin(); eit != script->script_ejectors.end(); ++eit) { + const ParticleEjectorScript *ejector = (*eit); + + switch (ejector->type()) { + case ParticleEjectorScript::Flame: + strval.append(" flame"); + break; + case ParticleEjectorScript::Flare: + strval.append(" flare"); + break; + case ParticleEjectorScript::Jet: + strval.append(" jet"); + break; + case ParticleEjectorScript::Spray: + strval.append(" spray"); + break; + case ParticleEjectorScript::Trail: + strval.append(" trail"); + break; + } + } + con_print << " " << script->label() << strval << " " << script->script_ejectors.size() << " " << aux::plural("ejector", script->script_ejectors.size()) << std::endl; + } + con_print << script_registry.size() << " particle scripts" << std::endl; +} + +void ParticleSystemScript::clear() +{ + for (Registry::iterator it = script_registry.begin(); it != script_registry.end(); it++) { + delete(*it).second; + (*it).second = 0; + } + script_registry.clear(); +} + +ParticleSystemScript *ParticleSystemScript::find(const std::string &label) +{ + Registry::iterator it = script_registry.find(label); + + if (it != script_registry.end()) { + return (*it).second; + } else { + return 0; + } +} + +ParticleSystemScript *ParticleSystemScript::load(const std::string &label) +{ + ParticleSystemScript *script = find(label); + if (script) { + return script; + } + + filesystem::IniFile inifile; + inifile.open("particles/" + label); + if (!inifile.is_open()) { + con_warn << "Could not open " << inifile.name() << std::endl; + return 0; + } + + ParticleEjectorScript *ejector = 0; + std::string strval; + float pitch, yaw, roll = 0.0f; + float f; + bool b; + long l; + + while (inifile.getline()) { + + if (inifile.got_section()) { + + if (inifile.got_section("particles")) { + if (!script) { + script = new ParticleSystemScript(label); + script_registry[script->label()] = script; + } + ejector = 0; + continue; + } else if (inifile.got_section("ejector")) { + if (script) { + ejector = script->add_ejector(); + } else { + inifile.unknown_error("ejector section without particles section"); + } + } else { + inifile.unknown_section(); + } + + } else if (inifile.got_key()) { + + if (inifile.in_section("particles")) { + inifile.unknown_key(); + + } else if (inifile.in_section("ejector") && ejector) { + + if (inifile.got_key_string("type", strval)) { + aux::to_label(strval); + if (strval.compare("jet") == 0) { + ejector->set_type(ParticleEjectorScript::Jet); + } else if (strval.compare("trail") == 0) { + ejector->set_type(ParticleEjectorScript::Trail); + } else if (strval.compare("flame") == 0) { + ejector->set_type(ParticleEjectorScript::Flame); + } else if (strval.compare("spray") == 0) { + ejector->set_type(ParticleEjectorScript::Spray); + } else if (strval.compare("flare") == 0) { + ejector->set_type(ParticleEjectorScript::Flare); + } else { + inifile.unknown_value(); + } + continue; + + } else if (inifile.got_key_string("cull", strval)) { + aux::to_label(strval); + if (strval.compare("none") == 0) { + ejector->set_cull(model::CullNone); + } else if (strval.compare("back") == 0) { + ejector->set_cull(model::CullBack); + } else if (strval.compare("front") == 0) { + ejector->set_cull(model::CullFront); + } else { + inifile.unknown_value(); + } + continue; + + } else if (inifile.got_key_string("texture", strval)) { + ejector->set_texture("textures/" + strval); + Textures::load(ejector->texture()); + continue; + + } else if (inifile.got_key_float("speed", f)) { + // convert speed from meters/second to game units/second + ejector->set_speed(f * 0.01f); + continue; + + } else if (inifile.got_key_float("offset", f)) { + math::clamp(f, 0.0f, 1.0f); + ejector->set_offset(f); + continue; + + } else if (inifile.got_key_vector3f_opt("alpha", ejector->get_alpha_vec())) { + math::clamp(ejector->get_alpha_vec()[0], 0.0f, 1.0f); + math::clamp(ejector->get_alpha_vec()[1], 0.0f, 1.0f); + math::clamp(ejector->get_alpha_vec()[2], 0.0f, 1.0f); + continue; + + } else if (inifile.got_key_vector3f_opt("radius", ejector->get_radius_vec())) { + ejector->get_radius_vec() *= model::SCALE; + continue; + + } else if (inifile.got_key_float("spawnradius", f)) { + ejector->set_spawn_radius(f * model::SCALE); + continue; + + } else if (inifile.got_key_float("cone", f)) { + ejector->set_cone(f); + continue; + + } else if (inifile.got_key_long("interval", l)) { + ejector->set_interval((unsigned long) l); + continue; + + } else if (inifile.got_key_long("lifespan", l)) { + ejector->set_lifespan((unsigned long) l); + continue; + + } else if (inifile.got_key_color("color", ejector->get_color())) { + continue; + + } else if (inifile.got_key_bool("engine", b)) { + ejector->set_engine(b); + continue; + + } else if (inifile.got_key_bool("thrust", b)) { + ejector->set_thrust(b); + continue; + + } else if (inifile.got_key_bool("entity", b)) { + ejector->set_entity(b); + continue; + + } else if (inifile.got_key_bool("entitysecond", b)) { + ejector->set_entity_second(b); + continue; + + } else if (inifile.got_key_bool("entitythird", b)) { + if (b) { + ejector->set_entity(true); + ejector->set_entity_second(true); + } + continue; + + } else if (inifile.got_key_float("angle", yaw)) { + + if (yaw == model::ANGLEUP) { + ejector->get_axis().change_pitch(-90.0f); + } else if (yaw == model::ANGLEDOWN) { + ejector->get_axis().change_pitch(90.0f); + } else { + ejector->get_axis().change_direction(yaw); + } + continue; + + } else if (inifile.got_key("angles")) { + + std::istringstream str(inifile.value()); + if (str >> pitch >> yaw >> roll) { + ejector->get_axis().assign(yaw, pitch, roll); + } else { + inifile.unknown_value(); + } + continue; + + } else if (inifile.got_key_float("pitch", pitch)) { + ejector->get_axis().change_pitch(-pitch); + continue; + + } else if (inifile.got_key_float("yaw", yaw)) { + ejector->get_axis().change_direction(yaw); + continue; + + } else if (inifile.got_key_float("roll", roll)) { + ejector->get_axis().change_roll(-roll); + continue; + + } else { + inifile.unknown_key(); + } + } + } + } + + inifile.close(); + +#ifdef HAVE_DEBUG_MESSAGES + if (script) { + strval.clear(); + for (Ejectors::const_iterator eit = script->script_ejectors.begin(); eit != script->script_ejectors.end(); ++eit) { + const ParticleEjectorScript *ejector = (*eit); + + switch (ejector->type()) { + case ParticleEjectorScript::Flame: + strval.append(" flame"); + break; + case ParticleEjectorScript::Flare: + strval.append(" flare"); + break; + case ParticleEjectorScript::Jet: + strval.append(" jet"); + break; + case ParticleEjectorScript::Spray: + strval.append(" spray"); + break; + case ParticleEjectorScript::Trail: + strval.append(" trail"); + break; + } + } + con_debug << " " << script->label() << strval << " " << script->script_ejectors.size() << " " << aux::plural("ejector", script->script_ejectors.size()) << std::endl; + } +#endif + return script; +} + +/* ---- class ParticleSystemScript --------------------------------------- */ + +ParticleSystemScript::ParticleSystemScript(const std::string & label) : script_label(label) +{ + +} + +ParticleSystemScript::~ParticleSystemScript() +{ + for (Ejectors::iterator it = script_ejectors.begin(); it != script_ejectors.end(); ++it) + { + delete (*it); + (*it) = 0; + } + script_ejectors.clear(); +} + +ParticleEjectorScript *ParticleSystemScript::add_ejector() +{ + ParticleEjectorScript *ejector = new ParticleEjectorScript(); + script_ejectors.push_back(ejector); + return ejector; +} + +} \ No newline at end of file -- cgit v1.2.3