Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 6511 was 5654, checked in by bensch, 19 years ago

orxonox/trunk: cycle-loading of LoadParam works…

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  LOAD_PARAM_START_CYCLE(root, element);
93  {
94    LoadParam_CYCLE(element, "connect", this, ParticleEngine, addConnection)
95        .describe("connects an Emitter to a System (emitterName, systemName)");
96  }
97  LOAD_PARAM_END_CYCLE(element);
98}
99
100/**
101 *  Adds a System to the System list.
102
103   this is done automatically when creating a ParticleSystem
104*/
105void ParticleEngine::addSystem(ParticleSystem* system)
106{
107  this->systemList->add(system);
108}
109
110/**
111 *  Adds an emitter to the emitterList
112
113   this is done automatically when creating a ParticleEmitter
114*/
115void ParticleEngine::addEmitter(ParticleEmitter* emitter)
116{
117  this->emitterList->add(emitter);
118}
119
120/**
121* @brief Connects a ParticleSystem to a ParticleSystem thus emitting Particles.
122* @param emitter the Emitter to connect to the System
123* @param system the System to connect to the Emitter
124*/
125void ParticleEngine::addConnection(const char* emitter, const char* system)
126{
127  ParticleEmitter* tmpEmit = dynamic_cast<ParticleEmitter*>(ClassList::getObject(emitter, CL_PARTICLE_EMITTER));//this->getEmitterByName(emitter);
128  ParticleSystem* tmpSys = dynamic_cast<ParticleSystem*>(ClassList::getObject(system, CL_PARTICLE_SYSTEM));//this->getSystemByName(system);
129
130  if (tmpEmit != NULL && tmpSys != NULL)
131    this->addConnection(tmpEmit, tmpSys);
132  else
133  {
134    if (tmpEmit == NULL)
135      PRINTF(2)("Emitter %s not found in the List of emitters, not connecting to %s\n", emitter, system);
136    if (tmpEmit == NULL)
137      PRINTF(2)("System %s not found in the List of emitters, not connecting to %s\n", system, emitter);
138  }
139}
140
141/**
142 *  Connects a ParticleSystem to a ParticleSystem thus emitting Particles.
143 * @param emitter the Emitter to connect to the System
144 * @param system the System to connect to the Emitter
145*/
146void ParticleEngine::addConnection(ParticleEmitter* emitter, ParticleSystem* system)
147{
148  // look, if we have already added this connection
149  tIterator<ParticleConnection>* tmpConIt = connectionList->getIterator();
150  ParticleConnection* tmpConnection = tmpConIt->firstElement();
151  while(tmpConnection)
152    {
153      if (tmpConnection->emitter == emitter && tmpConnection->system == system)
154        {
155          PRINTF(2)("Connection between Emitter and System already exists.\n");
156          delete tmpConIt;
157          return;
158        }
159
160      tmpConnection = tmpConIt->nextElement();
161    }
162  delete tmpConIt;
163
164
165
166  ParticleConnection* tmpCon = new ParticleConnection;
167  tmpCon->emitter = emitter;
168  tmpCon->system = system;
169
170  this->connectionList->add(tmpCon);
171}
172
173/**
174 *  Removes a system from the systemList and also removes all Connections to the System
175 * @param system The ParticleSystem to delete
176*/
177bool ParticleEngine::removeSystem(ParticleSystem* system)
178{
179  // remove any connections, that have this system within
180  tIterator<ParticleConnection>* tmpConIt = connectionList->getIterator();
181  ParticleConnection* tmpConnection = tmpConIt->firstElement();
182  while(tmpConnection != NULL)
183    {
184      if (tmpConnection->system == system)
185        this->breakConnection(tmpConnection);
186      tmpConnection = tmpConIt->nextElement();
187    }
188  delete tmpConIt;
189
190  // remove the System from the systemList.
191  this->systemList->remove(system);
192}
193
194/**
195 *  removes an emitter from the emitterList and also from all Connections it is attached to.
196 * @param emitter the ParticleEmitter to remove.
197*/
198bool ParticleEngine::removeEmitter(ParticleEmitter* emitter)
199{
200  // remove any connections, that have this emitter within
201  tIterator<ParticleConnection>* tmpConIt = connectionList->getIterator();
202  ParticleConnection* tmpConnection = tmpConIt->firstElement();
203  while(tmpConnection != NULL)
204    {
205      if (tmpConnection->emitter == emitter)
206        this->breakConnection(tmpConnection);
207      tmpConnection = tmpConIt->nextElement();
208    }
209  delete tmpConIt;
210
211  // remove the emitter from the emitterList
212  this->emitterList->remove(emitter);
213}
214
215
216/**
217 *  removes a Connection between an Emitter and a System
218 * @param connection the connection to remove
219 *
220 * \see bool ParticleEngine::breakConnection(ParticleEmitter* emitter, ParticleSystem* system)
221 */
222bool ParticleEngine::breakConnection(ParticleConnection* connection)
223{
224  this->connectionList->remove(connection);
225  return true;
226}
227
228/**
229 *  removes a Connection between an Emitter and a System
230 * @param emitter The emitter of the connection to remove
231 * @param system The system of the connection to remove
232 * @returns true, if the connection was broken, false if the conntection was not found
233 *
234 * only if both system and emitter are in the connection the Connection will be broken
235*/
236bool ParticleEngine::breakConnection(ParticleEmitter* emitter, ParticleSystem* system)
237{
238  // look, if we have already added this connection
239  tIterator<ParticleConnection>* tmpConIt = connectionList->getIterator();
240  ParticleConnection* tmpConnection = tmpConIt->firstElement();
241  while(tmpConnection)
242    {
243    if (tmpConnection->emitter == emitter && tmpConnection->system == system)
244      {
245        this->breakConnection(tmpConnection);
246        delete tmpConIt;
247        return true;
248      }
249    tmpConnection = tmpConIt->nextElement();
250    }
251  delete tmpConIt;
252  return false;
253}
254
255/**
256 *  removes a Connection between an Emitter and a System
257 * @param emitter The emitter of the connections to remove
258 * @returns the count of connections that were broken, 0 if no conntection was not found
259 */
260unsigned int ParticleEngine::breakConnections(ParticleEmitter* emitter)
261{
262  unsigned int retVal = 0;
263  // look, if we have already added this connection
264  tIterator<ParticleConnection>* tmpConIt = connectionList->getIterator();
265  ParticleConnection* tmpConnection = tmpConIt->firstElement();
266  while(tmpConnection)
267  {
268    if (tmpConnection->emitter == emitter)
269    {
270      this->breakConnection(tmpConnection);
271      retVal++;
272    }
273    tmpConnection = tmpConIt->nextElement();
274  }
275  delete tmpConIt;
276  return retVal;
277}
278
279
280/**
281 *  removes a Connection between an Emitter and a System
282 * @param system The system of the connections to remove
283 * @returns the count of connections that were broken, 0 if no conntection was not found
284 */
285unsigned int ParticleEngine::breakConnections(ParticleSystem* system)
286{
287  unsigned int retVal = 0;
288  // look, if we have already added this connection
289  tIterator<ParticleConnection>* tmpConIt = connectionList->getIterator();
290  ParticleConnection* tmpConnection = tmpConIt->firstElement();
291  while(tmpConnection)
292  {
293    if (tmpConnection->system == system)
294    {
295      this->breakConnection(tmpConnection);
296      retVal++;
297    }
298    tmpConnection = tmpConIt->nextElement();
299  }
300  delete tmpConIt;
301  return retVal;
302}
303
304/**
305 *  this function ticks all the ParticleSystems, so an animation will flow
306 * @param dt passed since last tick
307*/
308void ParticleEngine::tick(float dt)
309{
310  // ticks all the ParticleSystems
311  tIterator<ParticleSystem>* tmpIt = systemList->getIterator();
312  ParticleSystem* tmpSys = tmpIt->firstElement();
313  while(tmpSys)
314    {
315      tmpSys->tick(dt);
316      tmpSys = tmpIt->nextElement();
317    }
318  delete tmpIt;
319
320  // add new Particles to each System connected to an Emitter.
321  tIterator<ParticleConnection>* tmpConIt = connectionList->getIterator();
322  ParticleConnection* tmpConnection = tmpConIt->firstElement();
323  while(tmpConnection)
324    {
325      tmpConnection->emitter->tick(dt, tmpConnection->system);
326      tmpConnection = tmpConIt->nextElement();
327    }
328  delete tmpConIt;
329}
330
331/**
332 *  draws all the systems and their Particles.
333*/
334void ParticleEngine::draw() const
335{
336  tIterator<ParticleSystem>* tmpIt = systemList->getIterator();
337  ParticleSystem* tmpSys = tmpIt->firstElement();
338  while(tmpSys)
339    {
340      tmpSys->draw();
341      tmpSys = tmpIt->nextElement();
342    }
343  delete tmpIt;
344
345}
346
347/**
348 * @param number the n-th system to return
349 * @returns the system called by number or NULL if not found
350*/
351ParticleSystem* ParticleEngine::getSystemByNumber(unsigned int number) const
352{
353  int count = 0;
354  tIterator<ParticleSystem>* tmpIt = systemList->getIterator();
355  ParticleSystem* tmpSys = tmpIt->firstElement();
356  while(tmpSys)
357    {
358      count++;
359      if ( count == number)
360        {
361          delete tmpIt;
362          return tmpSys;
363        }
364      tmpSys = tmpIt->nextElement();
365    }
366  delete tmpIt;
367  return NULL;
368}
369
370/**
371 * @param number the n-th emitter to return
372 * @returns the emitter called by number or NULL if not found
373*/
374ParticleEmitter* ParticleEngine::getEmitterByNumber(unsigned int number) const
375{
376  int count = 0;
377  tIterator<ParticleEmitter>* tmpIt = emitterList->getIterator();
378  ParticleEmitter* tmpEmit = tmpIt->firstElement();
379  while(tmpEmit)
380    {
381      count++;
382      if ( count == number)
383        {
384          delete tmpIt;
385          return tmpEmit;
386        }
387      tmpEmit = tmpIt->nextElement();
388    }
389  delete tmpIt;
390  return NULL;
391}
392
393/**
394 *  outputs some nice debug information
395*/
396void ParticleEngine::debug()
397{
398  PRINT(0)("+-----------------------------------+\n");
399  PRINT(0)("+ PARTICLE-ENGINE DEBUG INFORMATION +\n");
400  PRINT(0)("+-----------------------------------+\n");
401  PRINT(0)(" Reference: %p\n", ParticleEngine::singletonRef);
402  PRINT(0)(" Count: Emitters: %d; Systems: %d, Connections: %d\n",
403  this->emitterList->getSize(), this->systemList->getSize(), this->connectionList->getSize());
404
405  if (this->connectionList->getSize() > 0)
406  {
407    PRINT(0)(" Connections:\n");
408    PRINT(0)(" -----------------------------------\n");
409
410    tIterator<ParticleConnection>* tmpConIt = connectionList->getIterator();
411    ParticleConnection* tmpConnection = tmpConIt->firstElement();
412    while(tmpConnection)
413    {
414      PRINT(0)(" Emitter '%s' emitts into System '%s'\n", tmpConnection->emitter->getName(), tmpConnection->system->getName());
415      tmpConnection = tmpConIt->nextElement();
416    }
417    delete tmpConIt;
418  }
419
420  if (this->systemList->getSize() > 0)
421  {
422    tIterator<ParticleSystem>* tmpIt = systemList->getIterator();
423    ParticleSystem* tmpSys = tmpIt->firstElement();
424    while(tmpSys)
425    {
426      tmpSys->debug();
427      tmpSys = tmpIt->nextElement();
428    }
429    delete tmpIt;
430  }
431  else
432  {
433    PRINT(0)("NO SYSTEMS\n");
434  }
435  if (this->emitterList->getSize() > 0)
436  {
437    tIterator<ParticleEmitter>* tmpIt = emitterList->getIterator();
438    ParticleEmitter* tmpEmit = tmpIt->firstElement();
439    while(tmpEmit)
440    {
441      tmpEmit->debug();
442      tmpEmit = tmpIt->nextElement();
443    }
444    delete tmpIt;
445  }
446  else
447  {
448    PRINTF(0)("NO EMITTERS\n");
449  }
450
451  PRINT(0)("+--------------------------------PE-+\n");
452
453}
454
Note: See TracBrowser for help on using the repository browser.