particle_manager.cpp

Go to the documentation of this file.
00001 
00002 //            Copyright (C) 2004-2007 by The Allacrost Project
00003 //                         All Rights Reserved
00004 //
00005 // This code is licensed under the GNU GPL version 2. It is free software 
00006 // and you may modify it and/or redistribute it under the terms of this license.
00007 // See http://www.gnu.org/copyleft/gpl.html for details.
00009 
00010 #include "particle_manager.h"
00011 #include "particle_effect.h"
00012 #include "particle_system.h"
00013 #include "particle_keyframe.h"
00014 #include "video.h"
00015 #include "script.h"
00016 #include <iostream>
00017 
00018 extern "C" {
00019   #include <lua.h>
00020   #include <lauxlib.h>
00021   #include <lualib.h>
00022 }
00023 
00024 
00025 using namespace std;
00026 using namespace hoa_script;
00027 using namespace hoa_video;
00028 
00029 
00030 #define LOAD_INT(str, var)  \
00031 { \
00032   lua_pushstring(L, str); \
00033   lua_gettable(L, -2); \
00034   if(!lua_isnumber(L, -1))  \
00035   {\
00036     if(VIDEO_DEBUG) \
00037       cerr << "VIDEO ERROR: could not load parameter " << str << " in ParticleManager::LoadEffect()!" << endl; \
00038     return false; \
00039   }\
00040   (var) = (int32)lua_tonumber(L, -1);\
00041   lua_pop(L, 1); \
00042 }
00043 
00044 
00045 #define LOAD_FLOAT(str, var)  \
00046 { \
00047   lua_pushstring(L, str); \
00048   lua_gettable(L, -2); \
00049   if(!lua_isnumber(L, -1))  \
00050   {\
00051     if(VIDEO_DEBUG) \
00052       cerr << "VIDEO ERROR: could not load parameter " << str << " in ParticleManager::LoadEffect()!" << endl; \
00053     return false; \
00054   }\
00055   (var) = (float)lua_tonumber(L, -1);\
00056   lua_pop(L, 1); \
00057 }
00058 
00059 
00060 #define LOAD_BOOL(str, var)  \
00061 { \
00062   lua_pushstring(L, str); \
00063   lua_gettable(L, -2); \
00064   if(!lua_isnumber(L, -1))  \
00065   {\
00066     if(VIDEO_DEBUG) \
00067       cerr << "VIDEO ERROR: could not load parameter " << str << " in ParticleManager::LoadEffect()!" << endl; \
00068     return false; \
00069   }\
00070   (var) = (bool)lua_tonumber(L, -1);\
00071   lua_pop(L, 1); \
00072 }
00073 
00074 
00075 #define LOAD_STRING(str, var)  \
00076 { \
00077   lua_pushstring(L, str); \
00078   lua_gettable(L, -2); \
00079   if(!lua_isstring(L, -1))  \
00080   {\
00081     if(VIDEO_DEBUG) \
00082       cerr << "VIDEO ERROR: could not load parameter " << str << " in ParticleManager::LoadEffect()!" << endl; \
00083     return false; \
00084   }\
00085   var = string(lua_tostring(L, -1));\
00086   lua_pop(L, 1); \
00087 }
00088 
00089 
00090 #define LOAD_COLOR(str, var)  \
00091 { \
00092   lua_pushstring(L, str); \
00093   lua_gettable(L, -2); \
00094   if(!lua_istable(L, -1))  \
00095   {\
00096     if(VIDEO_DEBUG) \
00097       cerr << "VIDEO ERROR: could not load parameter " << str << " in ParticleManager::LoadEffect()!" << endl; \
00098     return false; \
00099   }\
00100   int32 num_color_components = luaL_getn(L, -1); \
00101   if(num_color_components != 4)\
00102   {\
00103     if(VIDEO_DEBUG) \
00104       cerr << "VIDEO ERROR: wrong number of components while loading color " << str << " in ParticleManager::LoadEffect()!" << endl; \
00105     return false; \
00106   }\
00107   for(int32 cmp = 1; cmp <= 4; ++cmp) \
00108   {\
00109     lua_rawgeti(L, -1, cmp);\
00110     if(!lua_isnumber(L, -1)) \
00111     {\
00112       if(VIDEO_DEBUG) \
00113         cerr << "VIDEO ERROR: lua_isnumber() returned false while trying to load " << str << " in ParticleManager::LoadEffect()!" << endl; \
00114       return false; \
00115     }\
00116     var[cmp-1] = (float)lua_tonumber(L, -1);\
00117     lua_pop(L, 1);\
00118   }\
00119   lua_pop(L, 1); \
00120 }
00121 
00122 
00123 
00124 namespace hoa_video
00125 {
00126 
00127 namespace private_video
00128 {
00129 
00130 
00131 //-----------------------------------------------------------------------------
00132 // Loads the effect, returns false on failure. This is a temporary function, until
00133 // the GameScript code is finished
00134 //-----------------------------------------------------------------------------
00135 
00136 bool TEMP_LoadEffectHelper(const string &filename, lua_State *L, ParticleEffectDef *def)
00137 {
00138   if(!L)
00139   {
00140     if(VIDEO_DEBUG)
00141       cerr << "VIDEO ERROR: lua_open() failed in ParticleManager::LoadEffect()!" << endl;
00142     return false;
00143   }
00144   
00145   luaopen_base(L);
00146   luaopen_io(L);
00147   luaopen_string(L);
00148   luaopen_math(L);
00149   
00150   if(luaL_loadfile(L, filename.c_str()) || lua_pcall(L, 0, 0, 0))
00151   {
00152     cerr << "VIDEO ERROR: could not load particle effect " << filename << " :: " << lua_tostring(L, -1) << endl;        
00153     return false;
00154   }
00155 
00156   
00157   lua_getglobal(L, "systems");
00158   if(!lua_istable(L, -1))
00159   {
00160     if(VIDEO_DEBUG)
00161       cerr << "VIDEO ERROR: could not find 'systems' in particle effect " << filename << endl;
00162     return false;
00163   }
00164 
00165   
00166   int32 num_systems = luaL_getn(L, -1);
00167   
00168   if(num_systems < 1)
00169   {
00170     if(VIDEO_DEBUG)
00171       cerr << "VIDEO ERROR: num_systems less than 1 while opening particle effect " << filename << endl;
00172     return false;
00173   }
00174 
00175   for(int32 sys = 1; sys <= num_systems; ++sys)
00176   {
00177     // open the table for the sys'th system
00178     lua_rawgeti(L, -1, sys);
00179     if(!lua_istable(L, -1))
00180     {
00181       if(VIDEO_DEBUG)
00182         cerr << "VIDEO ERROR: could not find system #" << sys << " in particle effect " << filename << endl;
00183       return false;
00184     }
00185     
00186     // open up the emitter table
00187     lua_pushstring(L, "emitter");
00188     lua_gettable(L, -2);
00189     if(!lua_istable(L, -1))
00190     {
00191       if(VIDEO_DEBUG)
00192         cerr << "VIDEO ERROR: could not find emitter in system #" << sys << " in particle effect " << filename << endl;
00193       return false;
00194     }
00195     
00196     ParticleSystemDef *sys_def = new ParticleSystemDef;
00197     
00198     LOAD_FLOAT("x", sys_def->emitter._x);
00199     LOAD_FLOAT("y", sys_def->emitter._y);
00200     LOAD_FLOAT("x2", sys_def->emitter._x2);
00201     LOAD_FLOAT("y2", sys_def->emitter._y2);
00202     LOAD_FLOAT("center_x", sys_def->emitter._center_x);
00203     LOAD_FLOAT("center_y", sys_def->emitter._center_y);
00204     LOAD_FLOAT("x_variation", sys_def->emitter._x_variation);
00205     LOAD_FLOAT("y_variation", sys_def->emitter._y_variation);
00206     LOAD_FLOAT("radius", sys_def->emitter._radius);
00207     
00208     string shape_string;
00209     LOAD_STRING("shape", shape_string);
00210     
00211     if(!strcasecmp(shape_string.c_str(), "point"))
00212       sys_def->emitter._shape = EMITTER_SHAPE_POINT;
00213     else if(!strcasecmp(shape_string.c_str(), "line"))
00214       sys_def->emitter._shape = EMITTER_SHAPE_LINE;
00215     else if(!strcasecmp(shape_string.c_str(), "circle outline"))
00216       sys_def->emitter._shape = EMITTER_SHAPE_CIRCLE;
00217     else if(!strcasecmp(shape_string.c_str(), "circle"))
00218       sys_def->emitter._shape = EMITTER_SHAPE_FILLED_CIRCLE;
00219     else if(!strcasecmp(shape_string.c_str(), "rectangle"))
00220       sys_def->emitter._shape = EMITTER_SHAPE_FILLED_RECTANGLE;
00221     
00222     LOAD_BOOL("omnidirectional", sys_def->emitter._omnidirectional);
00223     LOAD_FLOAT("orientation", sys_def->emitter._orientation);
00224     LOAD_FLOAT("outer_cone", sys_def->emitter._outer_cone);
00225     LOAD_FLOAT("inner_cone", sys_def->emitter._inner_cone);
00226     LOAD_FLOAT("initial_speed", sys_def->emitter._initial_speed);
00227     LOAD_FLOAT("initial_speed_variation", sys_def->emitter._initial_speed_variation);
00228     LOAD_FLOAT("emission_rate", sys_def->emitter._emission_rate);
00229     LOAD_FLOAT("start_time", sys_def->emitter._start_time);
00230     
00231     string emitter_mode_string;
00232     LOAD_STRING("emitter_mode", emitter_mode_string);
00233     
00234     if(!strcasecmp(emitter_mode_string.c_str(), "looping"))
00235       sys_def->emitter._emitter_mode = EMITTER_MODE_LOOPING;
00236     else if(!strcasecmp(emitter_mode_string.c_str(), "one shot"))
00237       sys_def->emitter._emitter_mode = EMITTER_MODE_ONE_SHOT;
00238     else if(!strcasecmp(emitter_mode_string.c_str(), "burst"))
00239       sys_def->emitter._emitter_mode = EMITTER_MODE_BURST;
00240     else //.. if(!strcasecmp(emitter_mode_string.c_str(), "always"))
00241       sys_def->emitter._emitter_mode = EMITTER_MODE_ALWAYS;
00242     
00243     string spin_string;
00244     LOAD_STRING("spin", spin_string);
00245     
00246     if(!strcasecmp(spin_string.c_str(), "random"))
00247       sys_def->emitter._spin = EMITTER_SPIN_RANDOM;
00248     else if(!strcasecmp(spin_string.c_str(), "counterclockwise"))
00249       sys_def->emitter._spin = EMITTER_SPIN_COUNTERCLOCKWISE;
00250     else //..if(!strcasecmp(spin_string.c_str(), "clockwise"))
00251       sys_def->emitter._spin = EMITTER_SPIN_CLOCKWISE;
00252 
00253     // OK! done loading the emitter data. Now, load the keyframes
00254     
00255     lua_pop(L, 1);   // pop the emitter table
00256     lua_pushstring(L, "keyframes");
00257     lua_gettable(L, -2);
00258     
00259     if(!lua_istable(L, -1))
00260     {
00261       if(VIDEO_DEBUG)
00262         cerr << "VIDEO ERROR: could not locate keyframes while loading particle effect " << filename << endl;
00263       return false;
00264     }
00265 
00266     int32 num_keyframes = luaL_getn(L, -1);       
00267     
00268     sys_def->keyframes.resize(num_keyframes);
00269     
00270     
00271     for(int32 kf = 0; kf < num_keyframes; ++kf)
00272     {
00273       sys_def->keyframes[kf] = new ParticleKeyframe;
00274       
00275       // get the kf'th keyframe table
00276       lua_rawgeti(L, -1, kf+1);
00277       
00278       LOAD_FLOAT("size_x", sys_def->keyframes[kf]->size_x);
00279       LOAD_FLOAT("size_y", sys_def->keyframes[kf]->size_y);
00280       LOAD_COLOR("color", sys_def->keyframes[kf]->color);
00281       LOAD_FLOAT("rotation_speed", sys_def->keyframes[kf]->rotation_speed);
00282       LOAD_FLOAT("size_variation_x", sys_def->keyframes[kf]->size_variation_x);
00283       LOAD_FLOAT("size_variation_y", sys_def->keyframes[kf]->size_variation_y);
00284       LOAD_COLOR("color_variation", sys_def->keyframes[kf]->color_variation);
00285       LOAD_FLOAT("rotation_speed_variation", sys_def->keyframes[kf]->rotation_speed_variation);
00286       LOAD_FLOAT("time", sys_def->keyframes[kf]->time);
00287       
00288       // pop the current keyframe
00289       lua_pop(L, 1);      
00290     }
00291     
00292     // pop the keyframes table
00293     lua_pop(L, 1);
00294     
00295     lua_pushstring(L, "animation_frames");
00296     lua_gettable(L, -2);
00297     
00298     if(!lua_istable(L, -1))
00299     {
00300       if(VIDEO_DEBUG)
00301         cerr << "VIDEO ERROR: could not locate 'animation_frames' in the effect file " << filename << endl;
00302       return false;
00303     }
00304 
00305     int32 num_animation_frames = luaL_getn(L, -1);
00306     
00307     if(num_animation_frames < 1)
00308     {
00309       if(VIDEO_DEBUG)
00310         cerr << "VIDEO ERROR: the 'animation_frames' table was empty in effect file " << filename << endl;
00311       return false;
00312     }
00313     
00314     for(int32 n_frame = 0; n_frame < num_animation_frames; ++n_frame)
00315     {
00316       lua_rawgeti(L, -1, n_frame+1);
00317       
00318       if(!lua_isstring(L, -1))
00319       {
00320         if(VIDEO_DEBUG)
00321           cerr << "VIDEO ERROR: encountered a non-string element in animation frames array, in effect file " << filename << endl;
00322         return false;
00323       }     
00324       
00325       string anim_filename = lua_tostring(L, -1);
00326       sys_def->animation_frame_filenames.push_back(anim_filename);
00327       
00328       // pop the current animation frame filename
00329       lua_pop(L, 1);
00330     }
00331     
00332     // pop the animation_frames table
00333     lua_pop(L, 1);
00334     
00335     lua_pushstring(L, "animation_frame_times");
00336     lua_gettable(L, -2);
00337     
00338     if(!lua_istable(L, -1))
00339     {
00340       if(VIDEO_DEBUG)
00341         cerr << "VIDEO ERROR: could not locate 'animation_frame_times' in the effect file " << filename << endl;
00342       return false;
00343     }
00344 
00345     int32 num_animation_frame_times = luaL_getn(L, -1);
00346     
00347     if(num_animation_frame_times < 1)
00348     {
00349       if(VIDEO_DEBUG)
00350         cerr << "VIDEO ERROR: the 'animation_frame_times' table was empty in effect file " << filename << endl;
00351       return false;
00352     }
00353     
00354     for(int32 n_frame_time = 0; n_frame_time < num_animation_frame_times; ++n_frame_time)
00355     {
00356       lua_rawgeti(L, -1, n_frame_time+1);
00357       
00358       if(!lua_isnumber(L, -1))
00359       {
00360         if(VIDEO_DEBUG)
00361           cerr << "VIDEO ERROR: encountered a non-numeric element in animation frame times array, in effect file " << filename << endl;
00362         return false;
00363       }     
00364       
00365       int32 anim_frame_time = (int32)lua_tonumber(L, -1);
00366       sys_def->animation_frame_times.push_back(anim_frame_time);
00367       
00368       // pop the current animation frame time
00369       lua_pop(L, 1);
00370     }
00371     
00372     // pop the animation_frame times table
00373     lua_pop(L, 1);
00374     
00375     LOAD_BOOL("enabled", sys_def->enabled);
00376     LOAD_INT ("blend_mode", sys_def->blend_mode);
00377     LOAD_FLOAT("system_lifetime", sys_def->system_lifetime);
00378 
00379     LOAD_FLOAT("particle_lifetime", sys_def->particle_lifetime);
00380     LOAD_FLOAT("particle_lifetime_variation", sys_def->particle_lifetime_variation);
00381     LOAD_INT  ("max_particles", sys_def->max_particles);    
00382     LOAD_FLOAT("damping", sys_def->damping);
00383     LOAD_FLOAT("damping_variation", sys_def->damping_variation);
00384     LOAD_FLOAT("acceleration_x", sys_def->acceleration_x);
00385     LOAD_FLOAT("acceleration_y", sys_def->acceleration_y);
00386     LOAD_FLOAT("acceleration_variation_x", sys_def->acceleration_variation_x);
00387     LOAD_FLOAT("acceleration_variation_y", sys_def->acceleration_variation_y);
00388     LOAD_FLOAT("wind_velocity_x", sys_def->wind_velocity_x);
00389     LOAD_FLOAT("wind_velocity_y", sys_def->wind_velocity_y);
00390     LOAD_FLOAT("wind_velocity_variation_x", sys_def->wind_velocity_variation_x);
00391     LOAD_FLOAT("wind_velocity_variation_y", sys_def->wind_velocity_variation_y);
00392     LOAD_BOOL ("wave_motion_used", sys_def->wave_motion_used);
00393     LOAD_FLOAT("wave_length", sys_def->wave_length);
00394     LOAD_FLOAT("wave_length_variation", sys_def->wave_length_variation);
00395     LOAD_FLOAT("wave_amplitude", sys_def->wave_amplitude);
00396     LOAD_FLOAT("wave_amplitude_variation", sys_def->wave_amplitude_variation);
00397     LOAD_FLOAT("tangential_acceleration", sys_def->tangential_acceleration);
00398     LOAD_FLOAT("tangential_acceleration_variation", sys_def->tangential_acceleration_variation);
00399     LOAD_FLOAT("radial_acceleration", sys_def->radial_acceleration);
00400     LOAD_FLOAT("radial_acceleration_variation", sys_def->radial_acceleration_variation);
00401     LOAD_BOOL ("user_defined_attractor", sys_def->user_defined_attractor);
00402     LOAD_FLOAT("attractor_falloff", sys_def->attractor_falloff);
00403     LOAD_BOOL ("rotation_used", sys_def->rotation_used);
00404     LOAD_BOOL ("rotate_to_velocity", sys_def->rotate_to_velocity);
00405     LOAD_BOOL ("speed_scale_used", sys_def->speed_scale_used);
00406     LOAD_FLOAT("speed_scale", sys_def->speed_scale);
00407     LOAD_FLOAT("min_speed_scale", sys_def->min_speed_scale);    
00408     LOAD_FLOAT("max_speed_scale", sys_def->max_speed_scale);
00409     LOAD_BOOL ("smooth_animation", sys_def->smooth_animation);
00410     LOAD_BOOL ("modify_stencil", sys_def->modify_stencil);
00411     
00412     string stencil_op_string;
00413     LOAD_STRING("stencil_op", stencil_op_string);   
00414     
00415     if(!strcasecmp(stencil_op_string.c_str(), "incr"))
00416       sys_def->stencil_op = VIDEO_STENCIL_OP_INCREASE;
00417     else if(!strcasecmp(stencil_op_string.c_str(), "decr"))
00418       sys_def->stencil_op = VIDEO_STENCIL_OP_DECREASE;
00419     else if(!strcasecmp(stencil_op_string.c_str(), "zero"))
00420       sys_def->stencil_op = VIDEO_STENCIL_OP_ZERO;
00421     else //..if(!strcasecmp(stencil_op_string.c_str(), "one"))
00422       sys_def->stencil_op = VIDEO_STENCIL_OP_ONE;
00423     
00424     LOAD_BOOL("use_stencil", sys_def->use_stencil);
00425     LOAD_FLOAT("scene_lighting", sys_def->scene_lighting);
00426     LOAD_BOOL ("random_initial_angle", sys_def->random_initial_angle);
00427 
00428     // pop the system table
00429     lua_pop(L, 1);
00430     
00431     def->_systems.push_back(sys_def);   
00432   }
00433 
00434   return true;
00435 }
00436 
00437 
00438 //-----------------------------------------------------------------------------
00439 // LoadEffect: loads an effect definition from disk given the filename
00440 //             Returns NULL if there is a problem with loading
00441 //-----------------------------------------------------------------------------
00442 
00443 ParticleEffectDef *ParticleManager::LoadEffect(const std::string &filename)
00444 {
00445   ParticleEffectDef *def = new ParticleEffectDef;
00446   lua_State *L = lua_open();
00447 
00448   bool could_load = TEMP_LoadEffectHelper(filename, L, def);  
00449 
00450   if(!could_load)
00451   {
00452     lua_close(L);
00453     delete def;
00454     return NULL;
00455   }
00456   
00457   return def;
00458 }
00459 
00460 
00461 //-----------------------------------------------------------------------------
00462 // AddEffect: adds a new particle effect to the list
00463 //-----------------------------------------------------------------------------
00464 
00465 ParticleEffectID ParticleManager::AddEffect(const ParticleEffectDef *def, float x, float y)
00466 {
00467   if(!def)
00468   {
00469     if(VIDEO_DEBUG)
00470       cerr << "VIDEO ERROR: ParticleManager::AddEffect() failed because def was NULL!" << endl;
00471     return VIDEO_INVALID_EFFECT;
00472   }
00473     
00474   if(def->_systems.empty())
00475   {
00476     if(VIDEO_DEBUG)
00477       cerr << "VIDEO ERROR: ParticleManager::AddEffect() failed because def->_systems was empty!" << endl;
00478     return VIDEO_INVALID_EFFECT;
00479   }
00480   
00481   ParticleEffect *effect = _CreateEffect(def);
00482   if(!effect)
00483   {
00484     if(VIDEO_DEBUG)
00485       cerr << "VIDEO ERROR: could not create particle effect in ParticleManager::AddEffect()!" << endl;
00486     return VIDEO_INVALID_EFFECT;
00487   }
00488   
00489   effect->Move(x, y); 
00490   _effects[_current_id] = effect;
00491   
00492   ++_current_id;
00493   
00494   return _current_id - 1;
00495 };
00496 
00497 
00498 //-----------------------------------------------------------------------------
00499 // Draw: draws all particle effects
00500 //-----------------------------------------------------------------------------
00501 
00502 bool ParticleManager::Draw()
00503 {
00504   VideoManager->PushState();
00505   VideoManager->SetCoordSys(CoordSys(0.0f, 1024.0f, 768.0f, 0.0f));
00506   VideoManager->EnableScissoring(false);  
00507   
00508   map<ParticleEffectID, ParticleEffect *>::iterator iEffect = _effects.begin();
00509 
00510   glClearStencil(0);
00511   glClear(GL_STENCIL_BUFFER_BIT);
00512   
00513   bool success = true;
00514   
00515   while(iEffect != _effects.end())
00516   {
00517     if(!(iEffect->second)->_Draw())
00518     {
00519       success = false;
00520       if(VIDEO_DEBUG)
00521         cerr << "VIDEO ERROR: effect failed to draw in ParticleManager::Draw()!" << endl;
00522     }
00523     ++iEffect;
00524   }
00525   
00526   VideoManager->PopState();
00527   return success;
00528 }
00529 
00530 
00531 //-----------------------------------------------------------------------------
00532 // Update: updates all particle effects
00533 //-----------------------------------------------------------------------------
00534 
00535 bool ParticleManager::Update(int32 frame_time)
00536 {
00537   float frame_time_seconds = static_cast<float>(frame_time) / 1000.0f;
00538   
00539   map<ParticleEffectID, ParticleEffect *>::iterator iEffect = _effects.begin();
00540   
00541   bool success = true;
00542   
00543   _num_particles = 0;
00544   
00545   while(iEffect != _effects.end())
00546   {
00547     if(!(iEffect->second)->IsAlive())
00548     {
00549       (iEffect->second)->_Destroy();
00550       
00551       map<ParticleEffectID, ParticleEffect *>::iterator iEffectNext = iEffect;
00552       ++iEffectNext;
00553           
00554       _effects.erase(iEffect);
00555       iEffect = iEffectNext;
00556     }
00557     else
00558     {
00559       if(!(iEffect->second)->_Update(frame_time_seconds))
00560       {
00561         success = false;
00562         if(VIDEO_DEBUG)
00563           cerr << "VIDEO ERROR: effect failed to update in ParticleManager::Update()!" << endl;
00564       }
00565       
00566       _num_particles += iEffect->second->GetNumParticles();
00567       ++iEffect;
00568     }
00569   }
00570   
00571   return success;
00572 }
00573 
00574 
00575 //-----------------------------------------------------------------------------
00576 // StopAll: stops all particle effects
00577 //-----------------------------------------------------------------------------
00578 
00579 void ParticleManager::StopAll(bool kill_immediate)
00580 {
00581   map<ParticleEffectID, ParticleEffect *>::iterator iEffect = _effects.begin();
00582   
00583   while(iEffect != _effects.end())
00584   {
00585     (iEffect->second)->Stop(kill_immediate);
00586   }
00587 }
00588 
00589 
00590 //-----------------------------------------------------------------------------
00591 // Destroy: destroys all particle effects
00592 //-----------------------------------------------------------------------------
00593 
00594 void ParticleManager::Destroy()
00595 {
00596   map<ParticleEffectID, ParticleEffect *>::iterator iEffect = _effects.begin();
00597   
00598   while(iEffect != _effects.end())
00599   {
00600     (iEffect->second)->_Destroy();
00601     delete (iEffect->second);
00602     ++iEffect;
00603   }
00604   
00605   _effects.clear();
00606 }
00607 
00608 
00609 //-----------------------------------------------------------------------------
00610 // GetEffect: returns a pointer to the effect with the given ID. Only valid
00611 //            up until the next call to ParticleManager::Update(). In other words,
00612 //            don't store any pointers yourself, store the ID and call GetEffect()
00613 //
00614 //            Returns NULL if the effect cannot be found (perhaps it died)
00615 //-----------------------------------------------------------------------------
00616 
00617 ParticleEffect *ParticleManager::GetEffect(ParticleEffectID id)
00618 {
00619   map<ParticleEffectID, ParticleEffect *>::iterator iEffect = _effects.find(id);
00620   if(iEffect == _effects.end())
00621     return NULL;
00622   else
00623     return iEffect->second;
00624 }
00625 
00626 
00627 //-----------------------------------------------------------------------------
00628 // GetNumParticles: returns the entire number of live particles between all
00629 //                  currently displaying effects
00630 //-----------------------------------------------------------------------------
00631 
00632 int32 ParticleManager::GetNumParticles()
00633 {
00634   return _num_particles;
00635 }
00636 
00637 
00638 //-----------------------------------------------------------------------------
00639 // _CreateEffect: helper to AddEffect(), does the job of initializing a new effect
00640 //                given its definition. Returns NULL on failure
00641 //
00642 //                NOTE: assumes that def isn't NULL and def->_systems is non-empty
00643 //-----------------------------------------------------------------------------
00644 
00645 ParticleEffect *ParticleManager::_CreateEffect(const ParticleEffectDef *def)
00646 {
00647   list<ParticleSystemDef *>::const_iterator iSystem = def->_systems.begin();
00648   list<ParticleSystemDef *>::const_iterator iEnd = def->_systems.end();
00649   
00650   ParticleEffect *effect = new ParticleEffect;
00651   
00652   
00653   // store pointer of effect properties
00654   
00655   effect->_effect_def = def;
00656   
00657   
00658   // initialize systems
00659   
00660   while(iSystem != iEnd)
00661   {
00662     if((*iSystem)->enabled)
00663     {
00664       ParticleSystem *sys = new ParticleSystem;
00665       if(!sys->Create(*iSystem))
00666       {
00667         // if a system could not be created then we bail out
00668         sys->Destroy();
00669         delete sys;
00670         
00671         list<ParticleSystem *>::iterator iEffectSystem = effect->_systems.begin();
00672         list<ParticleSystem *>::iterator iEffectEnd = effect->_systems.end();
00673         
00674         while(iEffectSystem != iEffectEnd)
00675         {
00676           (*iEffectSystem)->Destroy();
00677           delete (*iEffectSystem);
00678           ++iEffectSystem;
00679         }
00680         
00681         if(VIDEO_DEBUG)
00682           cerr << "VIDEO ERROR: sys->Create() returned false while trying to create effect!" << endl;
00683         return NULL;
00684         
00685       }
00686       effect->_systems.push_back(sys);
00687     }
00688     ++iSystem;
00689   }
00690   
00691   effect->_alive = true;
00692   effect->_age = 0.0f;
00693   return effect;
00694 }
00695 
00696 
00697 }  // namespace private_video
00698 }  // namespace hoa_video

Generated on Fri Jul 6 23:11:20 2007 for Hero of Allacrost by  doxygen 1.5.1