Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/trunk/src/lib/particles/particle_engine.cc @ 5527

Last change on this file since 5527 was 5447, checked in by bensch, 19 years ago

orxonox/trunk: Explosions on Collision (—HACK—)
also made the FastFactory faster, not turning through the GarbageCollector, as it is not necessary. FastFactory also implements a Static Memeber subscriptor-Macro now
last but not least: new Functions in The ParticleEngine, and some revisited

File size: 12.6 KB
Line 
1/*
2   orxonox - the future of 3D-vertical-scrollers
3
4   Copyright (C) 2004 orx
5
6   This program is free software; you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation; either version 2, or (at your option)
9   any later version.
10
11   ### File Specific:
12   main-programmer: ...
13   co-programmer: ...
14*/
15
16#define DEBUG_SPECIAL_MODULE DEBUG_MODULE_GRAPHICS
17
18#include "particle_engine.h"
19
20#include "class_list.h"
21
22#include "list.h"
23#include "debug.h"
24#include "stdlibincl.h"
25#include "load_param.h"
26
27using namespace std;
28
29/**
30 *  standard constructor
31*/
32ParticleEngine::ParticleEngine ()
33{
34   this->setClassID(CL_PARTICLE_ENGINE, "ParticleEngine");
35   this->setName("ParticleEngine");
36
37   this->systemList = new tList<ParticleSystem>;
38   this->emitterList = new tList<ParticleEmitter>;
39   this->connectionList = new tList<ParticleConnection>;
40}
41
42/**
43 *  the singleton reference to this class
44*/
45ParticleEngine* ParticleEngine::singletonRef = NULL;
46
47/**
48 *  deletes all the system, emitters, connections and Lists
49*/
50ParticleEngine::~ParticleEngine ()
51{
52  /// @todo we must not do this, because PNoe does it for us
53  /// or we do this with help from ClassList, which essentially makes much more sense
54
55  // delete all remaining systems
56//   tIterator<ParticleSystem>* sysIt = this->systemList->getIterator();
57//   ParticleSystem* tmpSys = sysIt->firstElement();
58//   while(tmpSys)
59//     {
60//       delete tmpSys;
61//       tmpSys = sysIt->nextElement();
62//     }
63//   delete sysIt;
64   delete this->systemList;
65//
66   // delete all remaining emitters
67   tIterator<ParticleEmitter>* emitIt = this->emitterList->getIterator();
68   ParticleEmitter* tmpEmit = emitIt->firstElement();
69   while(tmpEmit)
70     {
71       delete tmpEmit;
72       tmpEmit = emitIt->nextElement();
73     }
74   delete emitIt;
75   delete this->emitterList;
76
77  // there should be no more Connections
78  if (this->connectionList->getSize() == 0)
79    delete this->connectionList;
80  else
81    PRINTF(2)("The Connection List is not empty. This should not happen.\n");
82
83  ParticleEngine::singletonRef = NULL;
84}
85
86/**
87  \brief loads the ParticleEngines settings and connections between particles and emitters
88* @param root the XML-element to load this from.
89 */
90void ParticleEngine::loadParams(const TiXmlElement* root)
91{
92  const TiXmlElement* element = root->FirstChildElement();
93  while( element != NULL)
94  {
95    LoadParam<ParticleEngine>(element, "connect", this, &ParticleEngine::addConnection, true)
96        .describe("connects an Emitter to a System (emitterName, systemName)");
97    element = element->NextSiblingElement();
98  }
99}
100
101/**
102 *  Adds a System to the System list.
103
104   this is done automatically when creating a ParticleSystem
105*/
106void ParticleEngine::addSystem(ParticleSystem* system)
107{
108  this->systemList->add(system);
109}
110
111/**
112 *  Adds an emitter to the emitterList
113
114   this is done automatically when creating a ParticleEmitter
115*/
116void ParticleEngine::addEmitter(ParticleEmitter* emitter)
117{
118  this->emitterList->add(emitter);
119}
120
121/**
122* @brief Connects a ParticleSystem to a ParticleSystem thus emitting Particles.
123* @param emitter the Emitter to connect to the System
124* @param system the System to connect to the Emitter
125*/
126void ParticleEngine::addConnection(const char* emitter, const char* system)
127{
128  ParticleEmitter* tmpEmit = dynamic_cast<ParticleEmitter*>(ClassList::getObject(emitter, CL_PARTICLE_EMITTER));//this->getEmitterByName(emitter);
129  ParticleSystem* tmpSys = dynamic_cast<ParticleSystem*>(ClassList::getObject(system, CL_PARTICLE_SYSTEM));//this->getSystemByName(system);
130
131  if (tmpEmit != NULL && tmpSys != NULL)
132    this->addConnection(tmpEmit, tmpSys);
133  else
134  {
135    if (tmpEmit == NULL)
136      PRINTF(2)("Emitter %s not found in the List of emitters, not connecting to %s\n", emitter, system);
137    if (tmpEmit == NULL)
138      PRINTF(2)("System %s not found in the List of emitters, not connecting to %s\n", system, emitter);
139  }
140}
141
142/**
143 *  Connects a ParticleSystem to a ParticleSystem thus emitting Particles.
144 * @param emitter the Emitter to connect to the System
145 * @param system the System to connect to the Emitter
146*/
147void ParticleEngine::addConnection(ParticleEmitter* emitter, ParticleSystem* system)
148{
149  // look, if we have already added this connection
150  tIterator<ParticleConnection>* tmpConIt = connectionList->getIterator();
151  ParticleConnection* tmpConnection = tmpConIt->firstElement();
152  while(tmpConnection)
153    {
154      if (tmpConnection->emitter == emitter && tmpConnection->system == system)
155        {
156          PRINTF(2)("Connection between Emitter and System already exists.\n");
157          delete tmpConIt;
158          return;
159        }
160
161      tmpConnection = tmpConIt->nextElement();
162    }
163  delete tmpConIt;
164
165
166
167  ParticleConnection* tmpCon = new ParticleConnection;
168  tmpCon->emitter = emitter;
169  tmpCon->system = system;
170
171  this->connectionList->add(tmpCon);
172}
173
174/**
175 *  Removes a system from the systemList and also removes all Connections to the System
176 * @param system The ParticleSystem to delete
177*/
178bool ParticleEngine::removeSystem(ParticleSystem* system)
179{
180  // remove any connections, that have this system within
181  tIterator<ParticleConnection>* tmpConIt = connectionList->getIterator();
182  ParticleConnection* tmpConnection = tmpConIt->firstElement();
183  while(tmpConnection != NULL)
184    {
185      if (tmpConnection->system == system)
186        this->breakConnection(tmpConnection);
187      tmpConnection = tmpConIt->nextElement();
188    }
189  delete tmpConIt;
190
191  // remove the System from the systemList.
192  this->systemList->remove(system);
193}
194
195/**
196 *  removes an emitter from the emitterList and also from all Connections it is attached to.
197 * @param emitter the ParticleEmitter to remove.
198*/
199bool ParticleEngine::removeEmitter(ParticleEmitter* emitter)
200{
201  // remove any connections, that have this emitter within
202  tIterator<ParticleConnection>* tmpConIt = connectionList->getIterator();
203  ParticleConnection* tmpConnection = tmpConIt->firstElement();
204  while(tmpConnection != NULL)
205    {
206      if (tmpConnection->emitter == emitter)
207        this->breakConnection(tmpConnection);
208      tmpConnection = tmpConIt->nextElement();
209    }
210  delete tmpConIt;
211
212  // remove the emitter from the emitterList
213  this->emitterList->remove(emitter);
214}
215
216
217/**
218 *  removes a Connection between an Emitter and a System
219 * @param connection the connection to remove
220 *
221 * \see bool ParticleEngine::breakConnection(ParticleEmitter* emitter, ParticleSystem* system)
222 */
223bool ParticleEngine::breakConnection(ParticleConnection* connection)
224{
225  this->connectionList->remove(connection);
226  return true;
227}
228
229/**
230 *  removes a Connection between an Emitter and a System
231 * @param emitter The emitter of the connection to remove
232 * @param system The system of the connection to remove
233 * @returns true, if the connection was broken, false if the conntection was not found
234 *
235 * only if both system and emitter are in the connection the Connection will be broken
236*/
237bool ParticleEngine::breakConnection(ParticleEmitter* emitter, ParticleSystem* system)
238{
239  // look, if we have already added this connection
240  tIterator<ParticleConnection>* tmpConIt = connectionList->getIterator();
241  ParticleConnection* tmpConnection = tmpConIt->firstElement();
242  while(tmpConnection)
243    {
244    if (tmpConnection->emitter == emitter && tmpConnection->system == system)
245      {
246        this->breakConnection(tmpConnection);
247        delete tmpConIt;
248        return true;
249      }
250    tmpConnection = tmpConIt->nextElement();
251    }
252  delete tmpConIt;
253  return false;
254}
255
256/**
257 *  removes a Connection between an Emitter and a System
258 * @param emitter The emitter of the connections to remove
259 * @returns the count of connections that were broken, 0 if no conntection was not found
260 */
261unsigned int ParticleEngine::breakConnections(ParticleEmitter* emitter)
262{
263  unsigned int retVal = 0;
264  // look, if we have already added this connection
265  tIterator<ParticleConnection>* tmpConIt = connectionList->getIterator();
266  ParticleConnection* tmpConnection = tmpConIt->firstElement();
267  while(tmpConnection)
268  {
269    if (tmpConnection->emitter == emitter)
270    {
271      this->breakConnection(tmpConnection);
272      retVal++;
273    }
274    tmpConnection = tmpConIt->nextElement();
275  }
276  delete tmpConIt;
277  return retVal;
278}
279
280
281/**
282 *  removes a Connection between an Emitter and a System
283 * @param system The system of the connections to remove
284 * @returns the count of connections that were broken, 0 if no conntection was not found
285 */
286unsigned int ParticleEngine::breakConnections(ParticleSystem* system)
287{
288  unsigned int retVal = 0;
289  // look, if we have already added this connection
290  tIterator<ParticleConnection>* tmpConIt = connectionList->getIterator();
291  ParticleConnection* tmpConnection = tmpConIt->firstElement();
292  while(tmpConnection)
293  {
294    if (tmpConnection->system == system)
295    {
296      this->breakConnection(tmpConnection);
297      retVal++;
298    }
299    tmpConnection = tmpConIt->nextElement();
300  }
301  delete tmpConIt;
302  return retVal;
303}
304
305/**
306 *  this function ticks all the ParticleSystems, so an animation will flow
307 * @param dt passed since last tick
308*/
309void ParticleEngine::tick(float dt)
310{
311  // ticks all the ParticleSystems
312  tIterator<ParticleSystem>* tmpIt = systemList->getIterator();
313  ParticleSystem* tmpSys = tmpIt->firstElement();
314  while(tmpSys)
315    {
316      tmpSys->tick(dt);
317      tmpSys = tmpIt->nextElement();
318    }
319  delete tmpIt;
320
321  // add new Particles to each System connected to an Emitter.
322  tIterator<ParticleConnection>* tmpConIt = connectionList->getIterator();
323  ParticleConnection* tmpConnection = tmpConIt->firstElement();
324  while(tmpConnection)
325    {
326      tmpConnection->emitter->tick(dt, tmpConnection->system);
327      tmpConnection = tmpConIt->nextElement();
328    }
329  delete tmpConIt;
330}
331
332/**
333 *  draws all the systems and their Particles.
334*/
335void ParticleEngine::draw() const
336{
337  tIterator<ParticleSystem>* tmpIt = systemList->getIterator();
338  ParticleSystem* tmpSys = tmpIt->firstElement();
339  while(tmpSys)
340    {
341      tmpSys->draw();
342      tmpSys = tmpIt->nextElement();
343    }
344  delete tmpIt;
345
346}
347
348/**
349 * @param number the n-th system to return
350 * @returns the system called by number or NULL if not found
351*/
352ParticleSystem* ParticleEngine::getSystemByNumber(unsigned int number) const
353{
354  int count = 0;
355  tIterator<ParticleSystem>* tmpIt = systemList->getIterator();
356  ParticleSystem* tmpSys = tmpIt->firstElement();
357  while(tmpSys)
358    {
359      count++;
360      if ( count == number)
361        {
362          delete tmpIt;
363          return tmpSys;
364        }
365      tmpSys = tmpIt->nextElement();
366    }
367  delete tmpIt;
368  return NULL;
369}
370
371/**
372 * @param number the n-th emitter to return
373 * @returns the emitter called by number or NULL if not found
374*/
375ParticleEmitter* ParticleEngine::getEmitterByNumber(unsigned int number) const
376{
377  int count = 0;
378  tIterator<ParticleEmitter>* tmpIt = emitterList->getIterator();
379  ParticleEmitter* tmpEmit = tmpIt->firstElement();
380  while(tmpEmit)
381    {
382      count++;
383      if ( count == number)
384        {
385          delete tmpIt;
386          return tmpEmit;
387        }
388      tmpEmit = tmpIt->nextElement();
389    }
390  delete tmpIt;
391  return NULL;
392}
393
394/**
395 *  outputs some nice debug information
396*/
397void ParticleEngine::debug()
398{
399  PRINT(0)("+-----------------------------------+\n");
400  PRINT(0)("+ PARTICLE-ENGINE DEBUG INFORMATION +\n");
401  PRINT(0)("+-----------------------------------+\n");
402  PRINT(0)(" Reference: %p\n", ParticleEngine::singletonRef);
403  PRINT(0)(" Count: Emitters: %d; Systems: %d, Connections: %d\n",
404  this->emitterList->getSize(), this->systemList->getSize(), this->connectionList->getSize());
405
406  if (this->connectionList->getSize() > 0)
407  {
408    PRINT(0)(" Connections:\n");
409    PRINT(0)(" -----------------------------------\n");
410
411    tIterator<ParticleConnection>* tmpConIt = connectionList->getIterator();
412    ParticleConnection* tmpConnection = tmpConIt->firstElement();
413    while(tmpConnection)
414    {
415      PRINT(0)(" Emitter '%s' emitts into System '%s'\n", tmpConnection->emitter->getName(), tmpConnection->system->getName());
416      tmpConnection = tmpConIt->nextElement();
417    }
418    delete tmpConIt;
419  }
420
421  if (this->systemList->getSize() > 0)
422  {
423    tIterator<ParticleSystem>* tmpIt = systemList->getIterator();
424    ParticleSystem* tmpSys = tmpIt->firstElement();
425    while(tmpSys)
426    {
427      tmpSys->debug();
428      tmpSys = tmpIt->nextElement();
429    }
430    delete tmpIt;
431  }
432  else
433  {
434    PRINT(0)("NO SYSTEMS\n");
435  }
436  if (this->emitterList->getSize() > 0)
437  {
438    tIterator<ParticleEmitter>* tmpIt = emitterList->getIterator();
439    ParticleEmitter* tmpEmit = tmpIt->firstElement();
440    while(tmpEmit)
441    {
442      tmpEmit->debug();
443      tmpEmit = tmpIt->nextElement();
444    }
445    delete tmpIt;
446  }
447  else
448  {
449    PRINTF(0)("NO EMITTERS\n");
450  }
451
452  PRINT(0)("+--------------------------------PE-+\n");
453
454}
455
Note: See TracBrowser for help on using the repository browser.