/* 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::Sprite: strval.append(" sprites"); break; case ParticleEjectorScript::Flare: strval.append(" flares"); break; case ParticleEjectorScript::Trail: strval.append(" trail"); break; case ParticleEjectorScript::Flame: strval.append(" flame"); break; case ParticleEjectorScript::Streak: strval.append(" streaks"); 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("sprites")) { if (script) { ejector = script->add_ejector(); ejector->set_type(ParticleEjectorScript::Sprite); } else { inifile.unknown_error("ejector section without particles section"); } } else if (inifile.got_section("flares")) { if (script) { ejector = script->add_ejector(); ejector->set_type(ParticleEjectorScript::Flare); } else { inifile.unknown_error("ejector section without particles section"); } } else if (inifile.got_section("trail")) { if (script) { ejector = script->add_ejector(); ejector->set_type(ParticleEjectorScript::Trail); } else { inifile.unknown_error("ejector section without particles section"); } } else if (inifile.got_section("flame")) { if (script) { ejector = script->add_ejector(); ejector->set_type(ParticleEjectorScript::Flame); } else { inifile.unknown_error("ejector section without particles section"); } } else if (inifile.got_section("streaks")) { if (script) { ejector = script->add_ejector(); ejector->set_type(ParticleEjectorScript::Streak); } 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 (script) { if (inifile.in_section("sprites") || inifile.in_section("flares") || inifile.in_section("trail") || inifile.in_section("flame") || inifile.in_section("streaks")) { 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_vector2f_opt("speed", ejector->get_speed_vec())) { // convert speed from meters/second to game units/second ejector->get_speed_vec() *= 0.01f; continue; } else if (inifile.got_key_vector2f_opt("tailspeed", ejector->get_tailspeed_vec())) { // convert tail speed from meters/second to game units/second ejector->get_tailspeed_vec() *= 0.01f; continue; } else if (inifile.got_key_float("acceleration", f)) { // convert speed from meters/second to game units/second ejector->set_acceleration(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_long("timeout", l)) { ejector->set_timeout((unsigned long) l); continue; } else if (inifile.got_key_color("color", ejector->get_color())) { continue; } else if (inifile.got_key_color("colorsecond", ejector->get_color_second())) { ejector->set_color_interpolated(true); 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("impulse", b)) { ejector->set_impulse(b); continue; } else if (inifile.got_key_bool("explosion", b)) { ejector->set_explosion(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_bool("attached", b)) { ejector->set_attached(b); continue; } else if (inifile.got_key_bool("scaled", b)) { ejector->set_scaled(b); 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::Sprite: strval.append(" sprites"); break; case ParticleEjectorScript::Flare: strval.append(" flares"); break; case ParticleEjectorScript::Trail: strval.append(" trail"); break; case ParticleEjectorScript::Flame: strval.append(" flame"); break; case ParticleEjectorScript::Streak: strval.append(" streaks"); 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; } }