source: OGRE/trunk/ogre_changes/Ogre1.2/OgreMain/src/OgreParticleSystemManager.cpp @ 2343

Revision 2343, 23.5 KB checked in by szirmay, 17 years ago (diff)
Line 
1/*
2-----------------------------------------------------------------------------
3This source file is part of OGRE
4    (Object-oriented Graphics Rendering Engine)
5For the latest info, see http://www.ogre3d.org/
6
7Copyright (c) 2000-2005 The OGRE Team
8Also see acknowledgements in Readme.html
9
10This program is free software; you can redistribute it and/or modify it under
11the terms of the GNU Lesser General Public License as published by the Free Software
12Foundation; either version 2 of the License, or (at your option) any later
13version.
14
15This program is distributed in the hope that it will be useful, but WITHOUT
16ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
18
19You should have received a copy of the GNU Lesser General Public License along with
20this program; if not, write to the Free Software Foundation, Inc., 59 Temple
21Place - Suite 330, Boston, MA 02111-1307, USA, or go to
22http://www.gnu.org/copyleft/lesser.txt.
23-----------------------------------------------------------------------------
24*/
25#include "OgreStableHeaders.h"
26
27#include "OgreParticleSystemManager.h"
28#include "OgreParticleEmitterFactory.h"
29#include "OgreParticleAffectorFactory.h"
30#include "OgreException.h"
31#include "OgreRoot.h"
32#include "OgreLogManager.h"
33#include "OgreString.h"
34#include "OgreParticleSystemRenderer.h"
35#include "OgreBillboardParticleRenderer.h"
36#include "OgreStringConverter.h"
37
38#ifdef GAMETOOLS_ILLUMINATION_MODULE
39        #include "SpriteParticleRenderer.h"
40#endif
41
42namespace Ogre {
43    //-----------------------------------------------------------------------
44    // Shortcut to set up billboard particle renderer
45    BillboardParticleRendererFactory* mBillboardRendererFactory = 0;
46    //-----------------------------------------------------------------------
47
48#ifdef GAMETOOLS_ILLUMINATION_MODULE
49        //-----------------------------------------------------------------------
50    // Shortcut to set up sprite particle renderer
51        SpriteParticleRendererFactory* mSpriteRendererFactory = 0;
52    //-----------------------------------------------------------------------
53#endif
54
55    template<> ParticleSystemManager* Singleton<ParticleSystemManager>::ms_Singleton = 0;
56    ParticleSystemManager* ParticleSystemManager::getSingletonPtr(void)
57    {
58        return ms_Singleton;
59    }
60    ParticleSystemManager& ParticleSystemManager::getSingleton(void)
61    { 
62        assert( ms_Singleton );  return ( *ms_Singleton ); 
63    }
64    //-----------------------------------------------------------------------
65    ParticleSystemManager::ParticleSystemManager()
66    {
67        mScriptPatterns.push_back("*.particle");
68        ResourceGroupManager::getSingleton()._registerScriptLoader(this);
69                mFactory = new ParticleSystemFactory();
70                Root::getSingleton().addMovableObjectFactory(mFactory);
71    }
72    //-----------------------------------------------------------------------
73    ParticleSystemManager::~ParticleSystemManager()
74    {
75        // Destroy all templates
76        ParticleTemplateMap::iterator t;
77        for (t = mSystemTemplates.begin(); t != mSystemTemplates.end(); ++t)
78        {
79            delete t->second;
80        }
81        mSystemTemplates.clear();
82        ResourceGroupManager::getSingleton()._unregisterScriptLoader(this);
83        // delete billboard factory
84        if (mBillboardRendererFactory)
85                {
86            delete mBillboardRendererFactory;
87                        mBillboardRendererFactory = 0;
88                }
89
90#ifdef GAMETOOLS_ILLUMINATION_MODULE
91                // delete billboard factory
92        if (mSpriteRendererFactory)
93                {
94            delete mSpriteRendererFactory;
95                        mSpriteRendererFactory = 0;
96                }
97#endif
98
99                if (mFactory)
100                {
101                        // delete particle system factory
102                        Root::getSingleton().removeMovableObjectFactory(mFactory);
103                        delete mFactory;
104                        mFactory = 0;
105                }
106
107    }
108    //-----------------------------------------------------------------------
109    const StringVector& ParticleSystemManager::getScriptPatterns(void) const
110    {
111        return mScriptPatterns;
112    }
113    //-----------------------------------------------------------------------
114    Real ParticleSystemManager::getLoadingOrder(void) const
115    {
116        /// Load late
117        return 1000.0f;
118    }
119    //-----------------------------------------------------------------------
120    void ParticleSystemManager::parseScript(DataStreamPtr& stream, const String& groupName)
121    {
122        String line;
123        ParticleSystem* pSys;
124        std::vector<String> vecparams;
125
126        pSys = 0;
127
128        while(!stream->eof())
129        {
130            line = stream->getLine();
131            // Ignore comments & blanks
132            if (!(line.length() == 0 || line.substr(0,2) == "//"))
133            {
134                if (pSys == 0)
135                {
136                    // No current system
137                    // So first valid data should be a system name
138                    pSys = createTemplate(line, groupName);
139                                        pSys->_notifyOrigin(stream->getName());
140                    // Skip to and over next {
141                    skipToNextOpenBrace(stream);
142                }
143                else
144                {
145                    // Already in a system
146                    if (line == "}")
147                    {
148                        // Finished system
149                        pSys = 0;
150                    }
151                    else if (line.substr(0,7) == "emitter")
152                    {
153                        // new emitter
154                        // Get typename
155                        vecparams = StringUtil::split(line, "\t ");
156                        if (vecparams.size() < 2)
157                        {
158                            // Oops, bad emitter
159                            LogManager::getSingleton().logMessage("Bad particle system emitter line: '"
160                                + line + "' in " + pSys->getName());
161                            skipToNextCloseBrace(stream);
162
163                        }
164                        skipToNextOpenBrace(stream);
165                        parseNewEmitter(vecparams[1], stream, pSys);
166
167                    }
168                    else if (line.substr(0,8) == "affector")
169                    {
170                        // new affector
171                        // Get typename
172                        vecparams = StringUtil::split(line, "\t ");
173                        if (vecparams.size() < 2)
174                        {
175                            // Oops, bad emitter
176                            LogManager::getSingleton().logMessage("Bad particle system affector line: '"
177                                + line + "' in " + pSys->getName());
178                            skipToNextCloseBrace(stream);
179
180                        }
181                        skipToNextOpenBrace(stream);
182                        parseNewAffector(vecparams[1],stream, pSys);
183                    }
184                    else
185                    {
186                        // Attribute
187                        parseAttrib(line, pSys);
188                    }
189
190                }
191
192            }
193
194
195        }
196
197
198    }
199    //-----------------------------------------------------------------------
200    void ParticleSystemManager::addEmitterFactory(ParticleEmitterFactory* factory)
201    {
202        String name = factory->getName();
203        mEmitterFactories[name] = factory;
204        LogManager::getSingleton().logMessage("Particle Emitter Type '" + name + "' registered");
205    }
206    //-----------------------------------------------------------------------
207    void ParticleSystemManager::addAffectorFactory(ParticleAffectorFactory* factory)
208    {
209        String name = factory->getName();
210        mAffectorFactories[name] = factory;
211        LogManager::getSingleton().logMessage("Particle Affector Type '" + name + "' registered");
212    }
213        //-----------------------------------------------------------------------
214        void ParticleSystemManager::addRendererFactory(ParticleSystemRendererFactory* factory)
215        {
216        String name = factory->getType();
217        mRendererFactories[name] = factory;
218        LogManager::getSingleton().logMessage("Particle Renderer Type '" + name + "' registered");
219        }
220        //-----------------------------------------------------------------------
221    void ParticleSystemManager::addTemplate(const String& name, ParticleSystem* sysTemplate)
222    {
223                // check name
224                if (mSystemTemplates.find(name) != mSystemTemplates.end())
225                {
226                        OGRE_EXCEPT(Exception::ERR_DUPLICATE_ITEM,
227                                "ParticleSystem template with name '" + name + "' already exists.",
228                                "ParticleSystemManager::addTemplate");
229                }
230
231        mSystemTemplates[name] = sysTemplate;
232    }
233
234#ifdef GAMETOOLS_ILLUMINATION_MODULE
235        void ParticleSystemManager::removeTemplate(const String& name, bool deleteTemplate)
236    {
237        ParticleTemplateMap::iterator itr = mSystemTemplates.find(name);
238        if (itr == mSystemTemplates.end())
239            OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND,
240                "ParticleSystem template with name '" + name + "' cannot be found.",
241                "ParticleSystemManager::removeTemplate");
242
243        if (deleteTemplate)
244            delete itr->second;
245
246        mSystemTemplates.erase(itr);
247    }
248    //-----------------------------------------------------------------------
249    void ParticleSystemManager::removeAllTemplates(bool deleteTemplate)
250    {
251        if (deleteTemplate)
252        {
253            ParticleTemplateMap::iterator itr;
254            for (itr = mSystemTemplates.begin(); itr != mSystemTemplates.end(); ++itr)
255                delete itr->second;
256        }
257
258        mSystemTemplates.clear();
259    }
260#endif
261
262    //-----------------------------------------------------------------------
263    ParticleSystem* ParticleSystemManager::createTemplate(const String& name,
264        const String& resourceGroup)
265    {
266                // check name
267                if (mSystemTemplates.find(name) != mSystemTemplates.end())
268                {
269                        OGRE_EXCEPT(Exception::ERR_DUPLICATE_ITEM,
270                                "ParticleSystem template with name '" + name + "' already exists.",
271                                "ParticleSystemManager::createTemplate");
272                }
273
274        ParticleSystem* tpl = new ParticleSystem(name, resourceGroup);
275        addTemplate(name, tpl);
276        return tpl;
277
278    }
279    //-----------------------------------------------------------------------
280    ParticleSystem* ParticleSystemManager::getTemplate(const String& name)
281    {
282        ParticleTemplateMap::iterator i = mSystemTemplates.find(name);
283        if (i != mSystemTemplates.end())
284        {
285            return i->second;
286        }
287        else
288        {
289            return 0;
290        }
291    }
292        //-----------------------------------------------------------------------
293    ParticleSystem* ParticleSystemManager::createSystemImpl(const String& name,
294                size_t quota, const String& resourceGroup)
295    {
296        ParticleSystem* sys = new ParticleSystem(name, resourceGroup);
297        sys->setParticleQuota(quota);
298        return sys;
299    }
300    //-----------------------------------------------------------------------
301    ParticleSystem* ParticleSystemManager::createSystemImpl(const String& name,
302                const String& templateName)
303    {
304        // Look up template
305        ParticleSystem* pTemplate = getTemplate(templateName);
306        if (!pTemplate)
307        {
308            OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Cannot find required template '" + templateName + "'", "ParticleSystemManager::createSystem");
309        }
310
311        ParticleSystem* sys = createSystemImpl(name, pTemplate->getParticleQuota(),
312            pTemplate->getResourceGroupName());
313        // Copy template settings
314        *sys = *pTemplate;
315        return sys;
316       
317    }
318    //-----------------------------------------------------------------------
319    void ParticleSystemManager::destroySystemImpl(ParticleSystem* sys)
320        {
321                delete sys;
322        }
323    //-----------------------------------------------------------------------
324    ParticleEmitter* ParticleSystemManager::_createEmitter(
325        const String& emitterType, ParticleSystem* psys)
326    {
327        // Locate emitter type
328        ParticleEmitterFactoryMap::iterator pFact = mEmitterFactories.find(emitterType);
329
330        if (pFact == mEmitterFactories.end())
331        {
332            OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Cannot find requested emitter type.",
333                "ParticleSystemManager::_createEmitter");
334        }
335
336        return pFact->second->createEmitter(psys);
337    }
338    //-----------------------------------------------------------------------
339    void ParticleSystemManager::_destroyEmitter(ParticleEmitter* emitter)
340    {
341        // Destroy using the factory which created it
342        ParticleEmitterFactoryMap::iterator pFact = mEmitterFactories.find(emitter->getType());
343
344        if (pFact == mEmitterFactories.end())
345        {
346            OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Cannot find emitter factory to destroy emitter.",
347                "ParticleSystemManager::_destroyEmitter");
348        }
349
350        pFact->second->destroyEmitter(emitter);
351    }
352    //-----------------------------------------------------------------------
353    ParticleAffector* ParticleSystemManager::_createAffector(
354        const String& affectorType, ParticleSystem* psys)
355    {
356        // Locate affector type
357        ParticleAffectorFactoryMap::iterator pFact = mAffectorFactories.find(affectorType);
358
359        if (pFact == mAffectorFactories.end())
360        {
361            OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Cannot find requested affector type.",
362                "ParticleSystemManager::_createAffector");
363        }
364
365        return pFact->second->createAffector(psys);
366
367    }
368    //-----------------------------------------------------------------------
369    void ParticleSystemManager::_destroyAffector(ParticleAffector* affector)
370    {
371        // Destroy using the factory which created it
372        ParticleAffectorFactoryMap::iterator pFact = mAffectorFactories.find(affector->getType());
373
374        if (pFact == mAffectorFactories.end())
375        {
376            OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Cannot find affector factory to destroy affector.",
377                "ParticleSystemManager::_destroyAffector");
378        }
379
380        pFact->second->destroyAffector(affector);
381    }
382    //-----------------------------------------------------------------------
383    ParticleSystemRenderer* ParticleSystemManager::_createRenderer(const String& rendererType)
384        {
385        // Locate affector type
386        ParticleSystemRendererFactoryMap::iterator pFact = mRendererFactories.find(rendererType);
387
388        if (pFact == mRendererFactories.end())
389        {
390            OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Cannot find requested renderer type.",
391                "ParticleSystemManager::_createRenderer");
392        }
393
394        return pFact->second->createInstance(rendererType);
395        }
396        //-----------------------------------------------------------------------
397    void ParticleSystemManager::_destroyRenderer(ParticleSystemRenderer* renderer)
398        {
399        // Destroy using the factory which created it
400        ParticleSystemRendererFactoryMap::iterator pFact = mRendererFactories.find(renderer->getType());
401
402        if (pFact == mRendererFactories.end())
403        {
404            OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Cannot find renderer factory to destroy renderer.",
405                "ParticleSystemManager::_destroyRenderer");
406        }
407
408        pFact->second->destroyInstance(renderer);
409        }
410    //-----------------------------------------------------------------------
411    void ParticleSystemManager::_initialise(void)
412    {
413        // Create Billboard renderer factory
414        mBillboardRendererFactory = new BillboardParticleRendererFactory();
415        addRendererFactory(mBillboardRendererFactory);
416
417#ifdef GAMETOOLS_ILLUMINATION_MODULE
418                // Create Billboard renderer factory
419        mSpriteRendererFactory = new SpriteParticleRendererFactory();
420        addRendererFactory(mSpriteRendererFactory);
421#endif
422    }
423    //-----------------------------------------------------------------------
424    void ParticleSystemManager::parseNewEmitter(const String& type, DataStreamPtr& stream, ParticleSystem* sys)
425    {
426        // Create new emitter
427        ParticleEmitter* pEmit = sys->addEmitter(type);
428        // Parse emitter details
429        String line;
430
431        while(!stream->eof())
432        {
433            line = stream->getLine();
434            // Ignore comments & blanks
435            if (!(line.length() == 0 || line.substr(0,2) == "//"))
436            {
437                if (line == "}")
438                {
439                    // Finished emitter
440                    break;
441                }
442                else
443                {
444                    // Attribute
445                                        StringUtil::toLowerCase(line);
446                    parseEmitterAttrib(line, pEmit);
447                }
448            }
449        }
450
451
452       
453    }
454    //-----------------------------------------------------------------------
455    void ParticleSystemManager::parseNewAffector(const String& type, DataStreamPtr& stream, ParticleSystem* sys)
456    {
457        // Create new affector
458        ParticleAffector* pAff = sys->addAffector(type);
459        // Parse affector details
460        String line;
461
462        while(!stream->eof())
463        {
464            line = stream->getLine();
465            // Ignore comments & blanks
466            if (!(line.length() == 0 || line.substr(0,2) == "//"))
467            {
468                if (line == "}")
469                {
470                    // Finished affector
471                    break;
472                }
473                else
474                {
475                    // Attribute
476                                        StringUtil::toLowerCase(line);
477                    parseAffectorAttrib(line, pAff);
478                }
479            }
480        }
481    }
482    //-----------------------------------------------------------------------
483    void ParticleSystemManager::parseAttrib(const String& line, ParticleSystem* sys)
484    {
485        std::vector<String> vecparams;
486
487        // Split params on space
488        vecparams = StringUtil::split(line, "\t ", 1);
489
490        // Look up first param (command setting)
491        if (!sys->setParameter(vecparams[0], vecparams[1]))
492        {
493            // Attribute not supported by particle system, try the renderer
494            ParticleSystemRenderer* renderer = sys->getRenderer();
495            if (renderer)
496            {
497                if (!renderer->setParameter(vecparams[0], vecparams[1]))
498                {
499                    LogManager::getSingleton().logMessage("Bad particle system attribute line: '"
500                        + line + "' in " + sys->getName() + " (tried renderer)");
501                }
502            }
503            else
504            {
505                // BAD command. BAD!
506                LogManager::getSingleton().logMessage("Bad particle system attribute line: '"
507                    + line + "' in " + sys->getName() + " (no renderer)");
508            }
509        }
510    }
511    //-----------------------------------------------------------------------
512    void ParticleSystemManager::parseEmitterAttrib(const String& line, ParticleEmitter* emit)
513    {
514        std::vector<String> vecparams;
515
516        // Split params on first space
517        vecparams = StringUtil::split(line, "\t ", 1);
518
519        // Look up first param (command setting)
520        if (!emit->setParameter(vecparams[0], vecparams[1]))
521        {
522            // BAD command. BAD!
523            LogManager::getSingleton().logMessage("Bad particle emitter attribute line: '"
524                + line + "' for emitter " + emit->getType());
525        }
526    }
527    //-----------------------------------------------------------------------
528    void ParticleSystemManager::parseAffectorAttrib(const String& line, ParticleAffector* aff)
529    {
530        std::vector<String> vecparams;
531
532        // Split params on space
533        vecparams = StringUtil::split(line, "\t ", 1);
534
535        // Look up first param (command setting)
536        if (!aff->setParameter(vecparams[0], vecparams[1]))
537        {
538            // BAD command. BAD!
539            LogManager::getSingleton().logMessage("Bad particle affector attribute line: '"
540                + line + "' for affector " + aff->getType());
541        }
542    }
543    //-----------------------------------------------------------------------
544    void ParticleSystemManager::skipToNextCloseBrace(DataStreamPtr& stream)
545    {
546        String line = "";
547        while (!stream->eof() && line != "}")
548        {
549            line = stream->getLine();
550        }
551
552    }
553    //-----------------------------------------------------------------------
554    void ParticleSystemManager::skipToNextOpenBrace(DataStreamPtr& stream)
555    {
556        String line = "";
557        while (!stream->eof() && line != "{")
558        {
559            line = stream->getLine();
560        }
561
562    }
563        //-----------------------------------------------------------------------
564        ParticleSystemManager::ParticleAffectorFactoryIterator
565        ParticleSystemManager::getAffectorFactoryIterator(void)
566        {
567                return ParticleAffectorFactoryIterator(
568                        mAffectorFactories.begin(), mAffectorFactories.end());
569        }
570        //-----------------------------------------------------------------------
571        ParticleSystemManager::ParticleEmitterFactoryIterator
572        ParticleSystemManager::getEmitterFactoryIterator(void)
573        {
574                return ParticleEmitterFactoryIterator(
575                        mEmitterFactories.begin(), mEmitterFactories.end());
576        }
577        //-----------------------------------------------------------------------
578        ParticleSystemManager::ParticleRendererFactoryIterator
579        ParticleSystemManager::getRendererFactoryIterator(void)
580        {
581                return ParticleRendererFactoryIterator(
582                        mRendererFactories.begin(), mRendererFactories.end());
583        }
584        //-----------------------------------------------------------------------
585    //-----------------------------------------------------------------------
586    //-----------------------------------------------------------------------
587        String ParticleSystemFactory::FACTORY_TYPE_NAME = "ParticleSystem";
588    //-----------------------------------------------------------------------
589        MovableObject* ParticleSystemFactory::createInstanceImpl( const String& name,
590                        const NameValuePairList* params)
591        {
592                if (params != 0)
593                {
594                        NameValuePairList::const_iterator ni = params->find("templateName");
595                        if (ni != params->end())
596                        {
597                                String templateName = ni->second;
598                                // create using manager
599                                return ParticleSystemManager::getSingleton().createSystemImpl(
600                                                name, templateName);
601                        }
602                }
603                // Not template based, look for quota & resource name
604                size_t quota = 500;
605                String resourceGroup = ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME;
606                if (params != 0)
607                {
608                        NameValuePairList::const_iterator ni = params->find("quota");
609                        if (ni != params->end())
610                        {
611                                quota = StringConverter::parseUnsignedInt(ni->second);
612                        }
613                        ni = params->find("resourceGroup");
614                        if (ni != params->end())
615                        {
616                                resourceGroup = ni->second;
617                        }
618                }
619                // create using manager
620                return ParticleSystemManager::getSingleton().createSystemImpl(
621                                name, quota, resourceGroup);
622                               
623
624        }
625    //-----------------------------------------------------------------------
626        const String& ParticleSystemFactory::getType(void) const
627        {
628                return FACTORY_TYPE_NAME;
629        }
630    //-----------------------------------------------------------------------
631        void ParticleSystemFactory::destroyInstance( MovableObject* obj)
632        {
633                // use manager
634                ParticleSystemManager::getSingleton().destroySystemImpl(
635                        static_cast<ParticleSystem*>(obj));
636
637        }
638    //-----------------------------------------------------------------------
639}
Note: See TracBrowser for help on using the repository browser.