/* orxonox - the future of 3D-vertical-scrollers Copyright (C) 2004 orx This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. ### File Specific: main-programmer: ... co-programmer: ... */ #define DEBUG_SPECIAL_MODULE DEBUG_MODULE_PARTICLE #include "particle_engine.h" #include "particle_system.h" #include "particle_emitter.h" #include "list.h" #include "debug.h" #include "stdlibincl.h" using namespace std; /** \brief standard constructor */ ParticleEngine::ParticleEngine () { this->setClassID(CL_PARTICLE_ENGINE, "ParticleEngine"); this->systemList = new tList; this->emitterList = new tList; this->connectionList = new tList; } /** \brief the singleton reference to this class */ ParticleEngine* ParticleEngine::singletonRef = NULL; /** \brief deletes all the system, emitters, connections and Lists */ ParticleEngine::~ParticleEngine () { // delete all remaining systems tIterator* sysIt = this->systemList->getIterator(); ParticleSystem* tmpSys = sysIt->nextElement(); while(tmpSys) { delete tmpSys; tmpSys = sysIt->nextElement(); } delete sysIt; delete this->systemList; // delete all remaining emitters tIterator* emitIt = this->emitterList->getIterator(); ParticleEmitter* tmpEmit = emitIt->nextElement(); while(tmpEmit) { delete tmpEmit; tmpEmit = emitIt->nextElement(); } delete emitIt; delete this->emitterList; // there should be no more Connections if (this->connectionList->getSize() == 0) delete this->connectionList; else PRINTF(2)("The Connection List is not empty. This should not happen.\n"); ParticleEngine::singletonRef = NULL; } /** \brief Adds a System to the System list. this is done automatically when creating a ParticleSystem */ void ParticleEngine::addSystem(ParticleSystem* system) { this->systemList->add(system); } /** \brief Adds an emitter to the emitterList this is done automatically when creating a ParticleEmitter */ void ParticleEngine::addEmitter(ParticleEmitter* emitter) { this->emitterList->add(emitter); } /** \brief Connects a ParticleSystem to a ParticleSystem thus emitting Particles. \param emitter the Emitter to connect to the System \param system the System to connect to the Emitter */ void ParticleEngine::addConnection(ParticleEmitter* emitter, ParticleSystem* system) { // look, if we have already added this connection tIterator* tmpConIt = connectionList->getIterator(); ParticleConnection* tmpConnection = tmpConIt->nextElement(); while(tmpConnection) { if (tmpConnection->emitter == emitter && tmpConnection->system == system) { PRINTF(2)("Connection between Emitter and System already added\n"); delete tmpConIt; return; } tmpConnection = tmpConIt->nextElement(); } delete tmpConIt; ParticleConnection* tmpCon = new ParticleConnection; tmpCon->emitter = emitter; tmpCon->system = system; this->connectionList->add(tmpCon); } /** \brief Removes a system from the systemList and also removes all Connections to the System \param system The ParticleSystem to delete */ bool ParticleEngine::removeSystem(ParticleSystem* system) { // remove any connections, that have this system within tIterator* tmpConIt = connectionList->getIterator(); ParticleConnection* tmpConnection = tmpConIt->nextElement(); while(tmpConnection) { if (tmpConnection->system == system) this->breakConnection(tmpConnection); tmpConnection = tmpConIt->nextElement(); } delete tmpConIt; // remove the System from the systemList. this->systemList->remove(system); } /** \brief removes an emitter from the emitterList and also from all Connections it is attached to. \param emitter the ParticleEmitter to remove. */ bool ParticleEngine::removeEmitter(ParticleEmitter* emitter) { // remove any connections, that have this emitter within tIterator* tmpConIt = connectionList->getIterator(); ParticleConnection* tmpConnection = tmpConIt->nextElement(); while(tmpConnection) { if (tmpConnection->emitter == emitter) this->breakConnection(tmpConnection); tmpConnection = tmpConIt->nextElement(); } delete tmpConIt; // remove the emitter from the emitterList this->emitterList->remove(emitter); } /** \brief removes a Connection between an Emitter and a System \param emitter The emitter of the connection to remove \param system The system of the connection to remove \returns true, if the connection was broken, false if the conntection was not found only if both system and emitter are in the connection the Connection will be broken */ bool ParticleEngine::breakConnection(ParticleEmitter* emitter, ParticleSystem* system) { // look, if we have already added this connection tIterator* tmpConIt = connectionList->getIterator(); ParticleConnection* tmpConnection = tmpConIt->nextElement(); while(tmpConnection) { if (tmpConnection->emitter == emitter && tmpConnection->system == system) { this->breakConnection(tmpConnection); delete tmpConIt; return true; } tmpConnection = tmpConIt->nextElement(); } delete tmpConIt; return false; } /** \brief removes a Connection between an Emitter and a System \param connection the connection to remove \see bool ParticleEngine::breakConnection(ParticleEmitter* emitter, ParticleSystem* system) */ bool ParticleEngine::breakConnection(ParticleConnection* connection) { this->connectionList->remove(connection); return true; } /** \brief this function ticks all the ParticleSystems, so an animation will flow \param dt passed since last tick */ void ParticleEngine::tick(float dt) { // ticks all the ParticleSystems tIterator* tmpIt = systemList->getIterator(); ParticleSystem* tmpSys = tmpIt->nextElement(); while(tmpSys) { tmpSys->tick(dt); tmpSys = tmpIt->nextElement(); } delete tmpIt; // add new Particles to each System connected to an Emitter. tIterator* tmpConIt = connectionList->getIterator(); ParticleConnection* tmpConnection = tmpConIt->nextElement(); while(tmpConnection) { tmpConnection->emitter->tick(dt, tmpConnection->system); tmpConnection = tmpConIt->nextElement(); } delete tmpConIt; } /** \brief draws all the systems and their Particles. */ void ParticleEngine::draw() const { tIterator* tmpIt = systemList->getIterator(); ParticleSystem* tmpSys = tmpIt->nextElement(); while(tmpSys) { tmpSys->draw(); tmpSys = tmpIt->nextElement(); } delete tmpIt; } /** \param systemName the name of the system to search for \returns the system called by systemName or NULL if not found */ ParticleSystem* ParticleEngine::getSystemByName(const char* systemName) const { tIterator* tmpIt = systemList->getIterator(); ParticleSystem* tmpSys = tmpIt->nextElement(); while(tmpSys) { if (!strcmp(systemName, tmpSys->getName())) { delete tmpIt; return tmpSys; } tmpSys = tmpIt->nextElement(); } delete tmpIt; return NULL; } /** \param number the n-th system to return \returns the system called by number or NULL if not found */ ParticleSystem* ParticleEngine::getSystemByNumber(unsigned int number) const { int count = 0; tIterator* tmpIt = systemList->getIterator(); ParticleSystem* tmpSys = tmpIt->nextElement(); while(tmpSys) { count++; if ( count == number) { delete tmpIt; return tmpSys; } tmpSys = tmpIt->nextElement(); } delete tmpIt; return NULL; } /** \param emitterName the name of the emitter to search for \returns the emitter called by emitterName or NULL if not found */ ParticleEmitter* ParticleEngine::getEmitterByName(const char* emitterName) const { tIterator* tmpIt = emitterList->getIterator(); ParticleEmitter* tmpEmit = tmpIt->nextElement(); while(tmpEmit) { if (!strcmp(emitterName, tmpEmit->getName())) { delete tmpIt; return tmpEmit; } tmpEmit = tmpIt->nextElement(); } delete tmpIt; return NULL; } /** \param number the n-th emitter to return \returns the emitter called by number or NULL if not found */ ParticleEmitter* ParticleEngine::getEmitterByNumber(unsigned int number) const { int count = 0; tIterator* tmpIt = emitterList->getIterator(); ParticleEmitter* tmpEmit = tmpIt->nextElement(); while(tmpEmit) { count++; if ( count == number) { delete tmpIt; return tmpEmit; } tmpEmit = tmpIt->nextElement(); } delete tmpIt; return NULL; } /** \brief outputs some nice debug information */ void ParticleEngine::debug(void) { PRINT(0)("+-----------------------------------+\n"); PRINT(0)("+ PARTICLE-ENGINE DEBUG INFORMATION +\n"); PRINT(0)("+-----------------------------------+\n"); PRINT(0)(" Reference: %p\n", ParticleEngine::singletonRef); PRINT(0)(" Count: Emitters: %d; Systems: %d, Connections: %d\n", this->emitterList->getSize(), this->systemList->getSize(), this->connectionList->getSize()); if (this->connectionList->getSize() > 0) { PRINT(0)(" Connections:\n"); PRINT(0)(" -----------------------------------\n"); tIterator* tmpConIt = connectionList->getIterator(); ParticleConnection* tmpConnection = tmpConIt->nextElement(); while(tmpConnection) { PRINT(0)(" Emitter '%s' emitts into System '%s'\n", tmpConnection->emitter->getName(), tmpConnection->system->getName()); tmpConnection = tmpConIt->nextElement(); } delete tmpConIt; } if (this->systemList->getSize() > 0) { tIterator* tmpIt = systemList->getIterator(); ParticleSystem* tmpSys = tmpIt->nextElement(); while(tmpSys) { tmpSys->debug(); tmpSys = tmpIt->nextElement(); } delete tmpIt; } PRINT(0)("+--------------------------------PE-+\n"); }