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

Revision 768, 22.6 KB checked in by szirmay, 18 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    ParticleSystem* ParticleSystemManager::createTemplate(const String& name,
235        const String& resourceGroup)
236    {
237                // check name
238                if (mSystemTemplates.find(name) != mSystemTemplates.end())
239                {
240                        OGRE_EXCEPT(Exception::ERR_DUPLICATE_ITEM,
241                                "ParticleSystem template with name '" + name + "' already exists.",
242                                "ParticleSystemManager::createTemplate");
243                }
244
245        ParticleSystem* tpl = new ParticleSystem(name, resourceGroup);
246        addTemplate(name, tpl);
247        return tpl;
248
249    }
250    //-----------------------------------------------------------------------
251    ParticleSystem* ParticleSystemManager::getTemplate(const String& name)
252    {
253        ParticleTemplateMap::iterator i = mSystemTemplates.find(name);
254        if (i != mSystemTemplates.end())
255        {
256            return i->second;
257        }
258        else
259        {
260            return 0;
261        }
262    }
263        //-----------------------------------------------------------------------
264    ParticleSystem* ParticleSystemManager::createSystemImpl(const String& name,
265                size_t quota, const String& resourceGroup)
266    {
267        ParticleSystem* sys = new ParticleSystem(name, resourceGroup);
268        sys->setParticleQuota(quota);
269        return sys;
270    }
271    //-----------------------------------------------------------------------
272    ParticleSystem* ParticleSystemManager::createSystemImpl(const String& name,
273                const String& templateName)
274    {
275        // Look up template
276        ParticleSystem* pTemplate = getTemplate(templateName);
277        if (!pTemplate)
278        {
279            OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Cannot find required template '" + templateName + "'", "ParticleSystemManager::createSystem");
280        }
281
282        ParticleSystem* sys = createSystemImpl(name, pTemplate->getParticleQuota(),
283            pTemplate->getResourceGroupName());
284        // Copy template settings
285        *sys = *pTemplate;
286        return sys;
287       
288    }
289    //-----------------------------------------------------------------------
290    void ParticleSystemManager::destroySystemImpl(ParticleSystem* sys)
291        {
292                delete sys;
293        }
294    //-----------------------------------------------------------------------
295    ParticleEmitter* ParticleSystemManager::_createEmitter(
296        const String& emitterType, ParticleSystem* psys)
297    {
298        // Locate emitter type
299        ParticleEmitterFactoryMap::iterator pFact = mEmitterFactories.find(emitterType);
300
301        if (pFact == mEmitterFactories.end())
302        {
303            OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Cannot find requested emitter type.",
304                "ParticleSystemManager::_createEmitter");
305        }
306
307        return pFact->second->createEmitter(psys);
308    }
309    //-----------------------------------------------------------------------
310    void ParticleSystemManager::_destroyEmitter(ParticleEmitter* emitter)
311    {
312        // Destroy using the factory which created it
313        ParticleEmitterFactoryMap::iterator pFact = mEmitterFactories.find(emitter->getType());
314
315        if (pFact == mEmitterFactories.end())
316        {
317            OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Cannot find emitter factory to destroy emitter.",
318                "ParticleSystemManager::_destroyEmitter");
319        }
320
321        pFact->second->destroyEmitter(emitter);
322    }
323    //-----------------------------------------------------------------------
324    ParticleAffector* ParticleSystemManager::_createAffector(
325        const String& affectorType, ParticleSystem* psys)
326    {
327        // Locate affector type
328        ParticleAffectorFactoryMap::iterator pFact = mAffectorFactories.find(affectorType);
329
330        if (pFact == mAffectorFactories.end())
331        {
332            OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Cannot find requested affector type.",
333                "ParticleSystemManager::_createAffector");
334        }
335
336        return pFact->second->createAffector(psys);
337
338    }
339    //-----------------------------------------------------------------------
340    void ParticleSystemManager::_destroyAffector(ParticleAffector* affector)
341    {
342        // Destroy using the factory which created it
343        ParticleAffectorFactoryMap::iterator pFact = mAffectorFactories.find(affector->getType());
344
345        if (pFact == mAffectorFactories.end())
346        {
347            OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Cannot find affector factory to destroy affector.",
348                "ParticleSystemManager::_destroyAffector");
349        }
350
351        pFact->second->destroyAffector(affector);
352    }
353    //-----------------------------------------------------------------------
354    ParticleSystemRenderer* ParticleSystemManager::_createRenderer(const String& rendererType)
355        {
356        // Locate affector type
357        ParticleSystemRendererFactoryMap::iterator pFact = mRendererFactories.find(rendererType);
358
359        if (pFact == mRendererFactories.end())
360        {
361            OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Cannot find requested renderer type.",
362                "ParticleSystemManager::_createRenderer");
363        }
364
365        return pFact->second->createInstance(rendererType);
366        }
367        //-----------------------------------------------------------------------
368    void ParticleSystemManager::_destroyRenderer(ParticleSystemRenderer* renderer)
369        {
370        // Destroy using the factory which created it
371        ParticleSystemRendererFactoryMap::iterator pFact = mRendererFactories.find(renderer->getType());
372
373        if (pFact == mRendererFactories.end())
374        {
375            OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Cannot find renderer factory to destroy renderer.",
376                "ParticleSystemManager::_destroyRenderer");
377        }
378
379        pFact->second->destroyInstance(renderer);
380        }
381    //-----------------------------------------------------------------------
382    void ParticleSystemManager::_initialise(void)
383    {
384        // Create Billboard renderer factory
385        mBillboardRendererFactory = new BillboardParticleRendererFactory();
386        addRendererFactory(mBillboardRendererFactory);
387
388#ifdef GAMETOOLS_ILLUMINATION_MODULE
389                // Create Billboard renderer factory
390        mSpriteRendererFactory = new SpriteParticleRendererFactory();
391        addRendererFactory(mSpriteRendererFactory);
392#endif
393    }
394    //-----------------------------------------------------------------------
395    void ParticleSystemManager::parseNewEmitter(const String& type, DataStreamPtr& stream, ParticleSystem* sys)
396    {
397        // Create new emitter
398        ParticleEmitter* pEmit = sys->addEmitter(type);
399        // Parse emitter details
400        String line;
401
402        while(!stream->eof())
403        {
404            line = stream->getLine();
405            // Ignore comments & blanks
406            if (!(line.length() == 0 || line.substr(0,2) == "//"))
407            {
408                if (line == "}")
409                {
410                    // Finished emitter
411                    break;
412                }
413                else
414                {
415                    // Attribute
416                                        StringUtil::toLowerCase(line);
417                    parseEmitterAttrib(line, pEmit);
418                }
419            }
420        }
421
422
423       
424    }
425    //-----------------------------------------------------------------------
426    void ParticleSystemManager::parseNewAffector(const String& type, DataStreamPtr& stream, ParticleSystem* sys)
427    {
428        // Create new affector
429        ParticleAffector* pAff = sys->addAffector(type);
430        // Parse affector details
431        String line;
432
433        while(!stream->eof())
434        {
435            line = stream->getLine();
436            // Ignore comments & blanks
437            if (!(line.length() == 0 || line.substr(0,2) == "//"))
438            {
439                if (line == "}")
440                {
441                    // Finished affector
442                    break;
443                }
444                else
445                {
446                    // Attribute
447                                        StringUtil::toLowerCase(line);
448                    parseAffectorAttrib(line, pAff);
449                }
450            }
451        }
452    }
453    //-----------------------------------------------------------------------
454    void ParticleSystemManager::parseAttrib(const String& line, ParticleSystem* sys)
455    {
456        std::vector<String> vecparams;
457
458        // Split params on space
459        vecparams = StringUtil::split(line, "\t ", 1);
460
461        // Look up first param (command setting)
462        if (!sys->setParameter(vecparams[0], vecparams[1]))
463        {
464            // Attribute not supported by particle system, try the renderer
465            ParticleSystemRenderer* renderer = sys->getRenderer();
466            if (renderer)
467            {
468                if (!renderer->setParameter(vecparams[0], vecparams[1]))
469                {
470                    LogManager::getSingleton().logMessage("Bad particle system attribute line: '"
471                        + line + "' in " + sys->getName() + " (tried renderer)");
472                }
473            }
474            else
475            {
476                // BAD command. BAD!
477                LogManager::getSingleton().logMessage("Bad particle system attribute line: '"
478                    + line + "' in " + sys->getName() + " (no renderer)");
479            }
480        }
481    }
482    //-----------------------------------------------------------------------
483    void ParticleSystemManager::parseEmitterAttrib(const String& line, ParticleEmitter* emit)
484    {
485        std::vector<String> vecparams;
486
487        // Split params on first space
488        vecparams = StringUtil::split(line, "\t ", 1);
489
490        // Look up first param (command setting)
491        if (!emit->setParameter(vecparams[0], vecparams[1]))
492        {
493            // BAD command. BAD!
494            LogManager::getSingleton().logMessage("Bad particle emitter attribute line: '"
495                + line + "' for emitter " + emit->getType());
496        }
497    }
498    //-----------------------------------------------------------------------
499    void ParticleSystemManager::parseAffectorAttrib(const String& line, ParticleAffector* aff)
500    {
501        std::vector<String> vecparams;
502
503        // Split params on space
504        vecparams = StringUtil::split(line, "\t ", 1);
505
506        // Look up first param (command setting)
507        if (!aff->setParameter(vecparams[0], vecparams[1]))
508        {
509            // BAD command. BAD!
510            LogManager::getSingleton().logMessage("Bad particle affector attribute line: '"
511                + line + "' for affector " + aff->getType());
512        }
513    }
514    //-----------------------------------------------------------------------
515    void ParticleSystemManager::skipToNextCloseBrace(DataStreamPtr& stream)
516    {
517        String line = "";
518        while (!stream->eof() && line != "}")
519        {
520            line = stream->getLine();
521        }
522
523    }
524    //-----------------------------------------------------------------------
525    void ParticleSystemManager::skipToNextOpenBrace(DataStreamPtr& stream)
526    {
527        String line = "";
528        while (!stream->eof() && line != "{")
529        {
530            line = stream->getLine();
531        }
532
533    }
534        //-----------------------------------------------------------------------
535        ParticleSystemManager::ParticleAffectorFactoryIterator
536        ParticleSystemManager::getAffectorFactoryIterator(void)
537        {
538                return ParticleAffectorFactoryIterator(
539                        mAffectorFactories.begin(), mAffectorFactories.end());
540        }
541        //-----------------------------------------------------------------------
542        ParticleSystemManager::ParticleEmitterFactoryIterator
543        ParticleSystemManager::getEmitterFactoryIterator(void)
544        {
545                return ParticleEmitterFactoryIterator(
546                        mEmitterFactories.begin(), mEmitterFactories.end());
547        }
548        //-----------------------------------------------------------------------
549        ParticleSystemManager::ParticleRendererFactoryIterator
550        ParticleSystemManager::getRendererFactoryIterator(void)
551        {
552                return ParticleRendererFactoryIterator(
553                        mRendererFactories.begin(), mRendererFactories.end());
554        }
555        //-----------------------------------------------------------------------
556    //-----------------------------------------------------------------------
557    //-----------------------------------------------------------------------
558        String ParticleSystemFactory::FACTORY_TYPE_NAME = "ParticleSystem";
559    //-----------------------------------------------------------------------
560        MovableObject* ParticleSystemFactory::createInstanceImpl( const String& name,
561                        const NameValuePairList* params)
562        {
563                if (params != 0)
564                {
565                        NameValuePairList::const_iterator ni = params->find("templateName");
566                        if (ni != params->end())
567                        {
568                                String templateName = ni->second;
569                                // create using manager
570                                return ParticleSystemManager::getSingleton().createSystemImpl(
571                                                name, templateName);
572                        }
573                }
574                // Not template based, look for quota & resource name
575                size_t quota = 500;
576                String resourceGroup = ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME;
577                if (params != 0)
578                {
579                        NameValuePairList::const_iterator ni = params->find("quota");
580                        if (ni != params->end())
581                        {
582                                quota = StringConverter::parseUnsignedInt(ni->second);
583                        }
584                        ni = params->find("resourceGroup");
585                        if (ni != params->end())
586                        {
587                                resourceGroup = ni->second;
588                        }
589                }
590                // create using manager
591                return ParticleSystemManager::getSingleton().createSystemImpl(
592                                name, quota, resourceGroup);
593                               
594
595        }
596    //-----------------------------------------------------------------------
597        const String& ParticleSystemFactory::getType(void) const
598        {
599                return FACTORY_TYPE_NAME;
600        }
601    //-----------------------------------------------------------------------
602        void ParticleSystemFactory::destroyInstance( MovableObject* obj)
603        {
604                // use manager
605                ParticleSystemManager::getSingleton().destroySystemImpl(
606                        static_cast<ParticleSystem*>(obj));
607
608        }
609    //-----------------------------------------------------------------------
610}
Note: See TracBrowser for help on using the repository browser.