Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/OgreMain/src/OgreParticleSystemManager.cpp @ 5

Last change on this file since 5 was 5, checked in by anonymous, 17 years ago

=hoffentlich gehts jetzt

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