Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: reverted the last steps, because they created a huge pack of seg-faults

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