Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/OgreMain/src/OgreOverlayManager.cpp @ 1

Last change on this file since 1 was 1, checked in by landauf, 17 years ago
File size: 22.0 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 "OgreOverlayManager.h"
32#include "OgreStringVector.h"
33#include "OgreOverlayContainer.h"
34#include "OgreStringConverter.h"
35#include "OgreLogManager.h"
36#include "OgreSceneManagerEnumerator.h"
37#include "OgreSceneManager.h"
38#include "OgreSceneNode.h"
39#include "OgreEntity.h"
40#include "OgreException.h"
41#include "OgreViewport.h"
42#include "OgreOverlayElementFactory.h"
43
44namespace Ogre {
45
46    //---------------------------------------------------------------------
47    template<> OverlayManager *Singleton<OverlayManager>::ms_Singleton = 0;
48    OverlayManager* OverlayManager::getSingletonPtr(void)
49    {
50        return ms_Singleton;
51    }
52    OverlayManager& OverlayManager::getSingleton(void)
53    { 
54        assert( ms_Singleton );  return ( *ms_Singleton ); 
55    }
56    //---------------------------------------------------------------------
57    OverlayManager::OverlayManager() 
58      : mLastViewportWidth(0), 
59        mLastViewportHeight(0), 
60        mViewportDimensionsChanged(false)
61    {
62
63        // Scripting is supported by this manager
64        mScriptPatterns.push_back("*.overlay");
65                ResourceGroupManager::getSingleton()._registerScriptLoader(this);
66
67    }
68    //---------------------------------------------------------------------
69    OverlayManager::~OverlayManager()
70    {
71                destroyAllOverlayElements(false);
72                destroyAllOverlayElements(true);
73        destroyAll();
74
75        // Unregister with resource group manager
76                ResourceGroupManager::getSingleton()._unregisterScriptLoader(this);
77    }
78    //---------------------------------------------------------------------
79    const StringVector& OverlayManager::getScriptPatterns(void) const
80    {
81        return mScriptPatterns;
82    }
83    //---------------------------------------------------------------------
84    Real OverlayManager::getLoadingOrder(void) const
85    {
86        // Load late
87        return 1100.0f;
88    }
89    //---------------------------------------------------------------------
90    Overlay* OverlayManager::create(const String& name)
91    {
92        Overlay* ret = 0;
93        OverlayMap::iterator i = mOverlayMap.find(name);
94
95        if (i == mOverlayMap.end())
96        {
97            ret = new Overlay(name);
98            assert(ret && "Overlay creation failed");
99            mOverlayMap[name] = ret;
100        }
101        else
102        {
103            OGRE_EXCEPT(Exception::ERR_DUPLICATE_ITEM, 
104                "Overlay with name '" + name + "' already exists!",
105                "OverlayManager::create");
106        }
107
108        return ret;
109
110    }
111    //---------------------------------------------------------------------
112    Overlay* OverlayManager::getByName(const String& name)
113    {
114        OverlayMap::iterator i = mOverlayMap.find(name);
115        if (i == mOverlayMap.end())
116        {
117            return 0;
118        }
119        else
120        {
121            return i->second;
122        }
123
124    }
125    //---------------------------------------------------------------------
126    void OverlayManager::destroy(const String& name)
127    {
128        OverlayMap::iterator i = mOverlayMap.find(name);
129        if (i == mOverlayMap.end())
130        {
131            OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, 
132                "Overlay with name '" + name + "' not found.",
133                "OverlayManager::destroy");
134        }
135        else
136        {
137            delete i->second;
138            mOverlayMap.erase(i);
139        }
140    }
141    //---------------------------------------------------------------------
142    void OverlayManager::destroy(Overlay* overlay)
143    {
144        for (OverlayMap::iterator i = mOverlayMap.begin();
145            i != mOverlayMap.end(); ++i)
146        {
147            if (i->second == overlay)
148            {
149                delete i->second;
150                mOverlayMap.erase(i);
151                return;
152            }
153        }
154
155        OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, 
156            "Overlay not found.",
157            "OverlayManager::destroy");
158    }
159    //---------------------------------------------------------------------
160    void OverlayManager::destroyAll(void)
161    {
162        for (OverlayMap::iterator i = mOverlayMap.begin();
163            i != mOverlayMap.end(); ++i)
164        {
165            delete i->second;
166        }
167        mOverlayMap.clear();
168                mLoadedScripts.clear();
169    }
170    //---------------------------------------------------------------------
171    OverlayManager::OverlayMapIterator OverlayManager::getOverlayIterator(void)
172    {
173        return OverlayMapIterator(mOverlayMap.begin(), mOverlayMap.end());
174    }
175    //---------------------------------------------------------------------
176    void OverlayManager::parseScript(DataStreamPtr& stream, const String& groupName)
177    {
178                // check if we've seen this script before (can happen if included
179                // multiple times)
180                if (!stream->getName().empty() && 
181                        mLoadedScripts.find(stream->getName()) != mLoadedScripts.end())
182                {
183                        LogManager::getSingleton().logMessage( 
184                                "Skipping loading overlay include: '"
185                                + stream->getName() + " as it is already loaded.");
186                        return;
187                }
188            String line;
189            Overlay* pOverlay = 0;
190                bool skipLine;
191
192            while(!stream->eof())
193            {
194                        bool isTemplate = false;
195                        skipLine = false;
196                    line = stream->getLine();
197                    // Ignore comments & blanks
198                    if (!(line.length() == 0 || line.substr(0,2) == "//"))
199                    {
200                                if (line.substr(0,8) == "#include")
201                                {
202                    std::vector<String> params = StringUtil::split(line, "\t\n ()<>");
203                    DataStreamPtr includeStream = 
204                        ResourceGroupManager::getSingleton().openResource(
205                            params[1], groupName);
206                                        parseScript(includeStream, groupName);
207                                        continue;
208                                }
209                            if (!pOverlay)
210                            {
211                                    // No current overlay
212
213                                        // check to see if there is a template
214                                        if (line.substr(0,8) == "template")
215                                        {
216                                                isTemplate = true;
217
218                                        }
219                                        else
220                                        {
221                       
222                                                // So first valid data should be overlay name
223                                                pOverlay = create(line);
224                                                pOverlay->_notifyOrigin(stream->getName());
225                                                // Skip to and over next {
226                                                skipToNextOpenBrace(stream);
227                                                skipLine = true;
228                                        }
229                            }
230                            if ((pOverlay && !skipLine) || isTemplate)
231                            {
232                                    // Already in overlay
233                    std::vector<String> params = StringUtil::split(line, "\t\n ()");
234
235
236                                    if (line == "}")
237                                    {
238                                            // Finished overlay
239                                            pOverlay = 0;
240                                                isTemplate = false;
241                                    }
242                                    else if (parseChildren(stream,line, pOverlay, isTemplate, NULL))
243                                               
244                                    {
245
246                                    }
247                                    else
248                                    {
249                                            // Attribute
250                                                if (!isTemplate)
251                                                {
252                                                        parseAttrib(line, pOverlay);
253                                                }
254                                    }
255
256                            }
257
258                    }
259
260
261            }
262
263                // record as parsed
264                mLoadedScripts.insert(stream->getName());
265
266    }
267    //---------------------------------------------------------------------
268    void OverlayManager::_queueOverlaysForRendering(Camera* cam, 
269        RenderQueue* pQueue, Viewport* vp)
270    {
271        // Flag for update pixel-based GUIElements if viewport has changed dimensions
272        if (mLastViewportWidth != vp->getActualWidth() || 
273            mLastViewportHeight != vp->getActualHeight())
274        {
275            mViewportDimensionsChanged = true;
276            mLastViewportWidth = vp->getActualWidth();
277            mLastViewportHeight = vp->getActualHeight();
278
279        }
280        else
281        {
282            mViewportDimensionsChanged = false;
283        }
284
285        OverlayMap::iterator i, iend;
286        iend = mOverlayMap.end();
287        for (i = mOverlayMap.begin(); i != iend; ++i)
288        {
289            Overlay* o = i->second;
290            o->_findVisibleObjects(cam, pQueue);
291        }
292    }
293    //---------------------------------------------------------------------
294    void OverlayManager::parseNewElement( DataStreamPtr& stream, String& elemType, String& elemName, 
295            bool isContainer, Overlay* pOverlay, bool isTemplate, String templateName, OverlayContainer* container)
296    {
297        String line;
298
299                OverlayElement* newElement = NULL;
300                newElement = 
301                                OverlayManager::getSingleton().createOverlayElementFromTemplate(templateName, elemType, elemName, isTemplate);
302
303                        // do not add a template to an overlay
304
305                // add new element to parent
306                if (container)
307                {
308                        // Attach to container
309                        container->addChild(newElement);
310                }
311                // do not add a template to the overlay. For templates overlay = 0
312                else if (pOverlay)     
313                {
314                        pOverlay->add2D((OverlayContainer*)newElement);
315                }
316
317        while(!stream->eof())
318        {
319            line = stream->getLine();
320            // Ignore comments & blanks
321            if (!(line.length() == 0 || line.substr(0,2) == "//"))
322            {
323                if (line == "}")
324                {
325                    // Finished element
326                    break;
327                }
328                else
329                {
330                    if (isContainer && parseChildren(stream,line, pOverlay, isTemplate, static_cast<OverlayContainer*>(newElement)))
331                    {
332                                            // nested children... don't reparse it
333                    }
334                    else
335                    {
336                        // Attribute
337                        parseElementAttrib(line, pOverlay, newElement);
338                    }
339                }
340            }
341        }
342    }
343
344    //---------------------------------------------------------------------
345    bool OverlayManager::parseChildren( DataStreamPtr& stream, const String& line,
346            Overlay* pOverlay, bool isTemplate, OverlayContainer* parent)
347        {
348                bool ret = false;
349                uint skipParam =0;
350                std::vector<String> params = StringUtil::split(line, "\t\n ()");
351
352                if (isTemplate)
353                {
354                        if (params[0] == "template")
355                        {
356                                skipParam++;            // the first param = 'template' on a new child element
357                        }
358                }
359                                               
360                // top level component cannot be an element, it must be a container unless it is a template
361                if (params[0+skipParam] == "container" || (params[0+skipParam] == "element" && (isTemplate || parent != NULL)) )
362                {
363                        String templateName;
364                        ret = true;
365                        // nested container/element
366                        if (params.size() > 3+skipParam)
367                        {
368                                if (params.size() != 5+skipParam)
369                                {
370                                        LogManager::getSingleton().logMessage( 
371                                                "Bad element/container line: '"
372                                                + line + "' in " + parent->getTypeName()+ " " + parent->getName() +
373                                                ", expecting ':' templateName");
374                                        skipToNextCloseBrace(stream);
375                                        // barf
376                                        return ret;
377                                }
378                                if (params[3+skipParam] != ":")
379                                {
380                                        LogManager::getSingleton().logMessage( 
381                                                "Bad element/container line: '"
382                                                + line + "' in " + parent->getTypeName()+ " " + parent->getName() +
383                                                ", expecting ':' for element inheritance");
384                                        skipToNextCloseBrace(stream);
385                                        // barf
386                                        return ret;
387                                }
388
389                                templateName = params[4+skipParam];
390                        }
391
392                        else if (params.size() != 3+skipParam)
393                        {
394                                LogManager::getSingleton().logMessage( 
395                                        "Bad element/container line: '"
396                                                + line + "' in " + parent->getTypeName()+ " " + parent->getName() +
397                                        ", expecting 'element type(name)'");
398                                skipToNextCloseBrace(stream);
399                                // barf
400                                return ret;
401                        }
402       
403                        skipToNextOpenBrace(stream);
404                        parseNewElement(stream, params[1+skipParam], params[2+skipParam], true, pOverlay, isTemplate, templateName, (OverlayContainer*)parent);
405
406                }
407
408
409                return ret;
410        }
411
412    //---------------------------------------------------------------------
413    void OverlayManager::parseAttrib( const String& line, Overlay* pOverlay)
414    {
415        // Split params on first space
416        std::vector<String> vecparams = StringUtil::split(line, "\t ", 1);
417
418        // Look up first param (command setting)
419                StringUtil::toLowerCase(vecparams[0]);
420        if (vecparams[0] == "zorder")
421        {
422            pOverlay->setZOrder(StringConverter::parseUnsignedInt(vecparams[1]));
423        }
424        else
425        {
426            LogManager::getSingleton().logMessage("Bad overlay attribute line: '"
427                + line + "' for overlay " + pOverlay->getName());
428        }
429    }
430    //---------------------------------------------------------------------
431    void OverlayManager::parseElementAttrib( const String& line, Overlay* pOverlay, OverlayElement* pElement )
432    {
433        // Split params on first space
434        std::vector<String> vecparams = StringUtil::split(line, "\t ", 1);
435
436        // Look up first param (command setting)
437                StringUtil::toLowerCase(vecparams[0]);
438        if (!pElement->setParameter(vecparams[0], vecparams[1]))
439        {
440            // BAD command. BAD!
441            LogManager::getSingleton().logMessage("Bad element attribute line: '"
442                + line + "' for element " + pElement->getName() + " in overlay " + 
443                (!pOverlay ? StringUtil::BLANK : pOverlay->getName()));
444        }
445    }
446    //-----------------------------------------------------------------------
447    void OverlayManager::skipToNextCloseBrace(DataStreamPtr& stream)
448    {
449        String line;
450        while (!stream->eof() && line != "}")
451        {
452            line = stream->getLine();
453        }
454
455    }
456    //-----------------------------------------------------------------------
457    void OverlayManager::skipToNextOpenBrace(DataStreamPtr& stream)
458    {
459        String line;
460        while (!stream->eof() && line != "{")
461        {
462            line = stream->getLine();
463        }
464
465    }
466    //---------------------------------------------------------------------
467    bool OverlayManager::hasViewportChanged(void) const
468    {
469        return mViewportDimensionsChanged;
470    }
471    //---------------------------------------------------------------------
472    int OverlayManager::getViewportHeight(void) const
473    {
474        return mLastViewportHeight;
475    }
476    //---------------------------------------------------------------------
477    int OverlayManager::getViewportWidth(void) const
478    {
479        return mLastViewportWidth;
480    }
481    //---------------------------------------------------------------------
482    Real OverlayManager::getViewportAspectRatio(void) const
483    {
484        return (Real)mLastViewportHeight / (Real)mLastViewportWidth;
485    }
486    //---------------------------------------------------------------------
487        //---------------------------------------------------------------------
488        OverlayManager::ElementMap& OverlayManager::getElementMap(bool isTemplate)
489        {
490                return (isTemplate)?mTemplates:mInstances;
491        }
492
493        //---------------------------------------------------------------------
494        OverlayElement* OverlayManager::createOverlayElementFromTemplate(const String& templateName, const String& typeName, const String& instanceName, bool isTemplate)
495        {
496
497                OverlayElement* newObj  = NULL;
498
499                if (templateName.empty())
500                {
501                        newObj = createOverlayElement(typeName, instanceName, isTemplate);
502                }
503                else
504                {
505                        // no template
506                        OverlayElement* templateGui = getOverlayElement(templateName, true);
507
508                        String typeNameToCreate;
509                        if (typeName.empty())
510                        {
511                                typeNameToCreate = templateGui->getTypeName();
512                        }
513                        else
514                        {
515                                typeNameToCreate = typeName;
516                        }
517
518                        newObj = createOverlayElement(typeNameToCreate, instanceName, isTemplate);
519
520                        ((OverlayContainer*)newObj)->copyFromTemplate(templateGui);
521                }
522
523                return newObj;
524        }
525
526
527        //---------------------------------------------------------------------
528        OverlayElement* OverlayManager::cloneOverlayElementFromTemplate(const String& templateName, const String& instanceName)
529        {
530                OverlayElement* templateGui = getOverlayElement(templateName, true);
531                return templateGui->clone(instanceName);
532        }
533
534        //---------------------------------------------------------------------
535        OverlayElement* OverlayManager::createOverlayElement(const String& typeName, const String& instanceName, bool isTemplate)
536        {
537                return createOverlayElementImpl(typeName, instanceName, getElementMap(isTemplate));
538        }
539
540        //---------------------------------------------------------------------
541        OverlayElement* OverlayManager::createOverlayElementImpl(const String& typeName, const String& instanceName, ElementMap& elementMap)
542        {
543                // Check not duplicated
544                ElementMap::iterator ii = elementMap.find(instanceName);
545                if (ii != elementMap.end())
546                {
547                        OGRE_EXCEPT(Exception::ERR_DUPLICATE_ITEM, "OverlayElement with name " + instanceName +
548                                " already exists.", "OverlayManager::createOverlayElement" );
549                }
550                OverlayElement* newElem = createOverlayElementFromFactory(typeName, instanceName);
551
552                // Register
553                elementMap.insert(ElementMap::value_type(instanceName, newElem));
554
555                return newElem;
556
557
558        }
559
560        //---------------------------------------------------------------------
561        OverlayElement* OverlayManager::createOverlayElementFromFactory(const String& typeName, const String& instanceName)
562        {
563                // Look up factory
564                FactoryMap::iterator fi = mFactories.find(typeName);
565                if (fi == mFactories.end())
566                {
567                        OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, "Cannot locate factory for element type " + typeName,
568                                "OverlayManager::createOverlayElement");
569                }
570
571                // create
572                return fi->second->createOverlayElement(instanceName);
573        }
574
575        //---------------------------------------------------------------------
576        OverlayElement* OverlayManager::getOverlayElement(const String& name, bool isTemplate)
577        {
578                return getOverlayElementImpl(name, getElementMap(isTemplate));
579        }
580        //---------------------------------------------------------------------
581        OverlayElement* OverlayManager::getOverlayElementImpl(const String& name, ElementMap& elementMap)
582        {
583                // Locate instance
584                ElementMap::iterator ii = elementMap.find(name);
585                if (ii == elementMap.end())
586                {
587                        OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, "OverlayElement with name " + name +
588                                " not found.", "OverlayManager::getOverlayElementImpl" );
589                }
590
591                return ii->second;
592        }
593        //---------------------------------------------------------------------
594        void OverlayManager::destroyOverlayElement(const String& instanceName, bool isTemplate)
595        {
596                destroyOverlayElementImpl(instanceName, getElementMap(isTemplate));
597        }
598
599        //---------------------------------------------------------------------
600        void OverlayManager::destroyOverlayElement(OverlayElement* pInstance, bool isTemplate)
601        {
602                destroyOverlayElementImpl(pInstance->getName(), getElementMap(isTemplate));
603        }
604
605        //---------------------------------------------------------------------
606        void OverlayManager::destroyOverlayElementImpl(const String& instanceName, ElementMap& elementMap)
607        {
608                // Locate instance
609                ElementMap::iterator ii = elementMap.find(instanceName);
610                if (ii == elementMap.end())
611                {
612                        OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, "OverlayElement with name " + instanceName +
613                                " not found.", "OverlayManager::destroyOverlayElement" );
614                }
615                // Look up factory
616                const String& typeName = ii->second->getTypeName();
617                FactoryMap::iterator fi = mFactories.find(typeName);
618                if (fi == mFactories.end())
619                {
620                        OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, "Cannot locate factory for element type " + typeName,
621                                "OverlayManager::destroyOverlayElement");
622                }
623
624                fi->second->destroyOverlayElement(ii->second);
625                elementMap.erase(ii);
626        }
627        //---------------------------------------------------------------------
628        void OverlayManager::destroyAllOverlayElements(bool isTemplate)
629        {
630                destroyAllOverlayElementsImpl(getElementMap(isTemplate));
631        }
632        //---------------------------------------------------------------------
633        void OverlayManager::destroyAllOverlayElementsImpl(ElementMap& elementMap)
634        {
635                ElementMap::iterator i;
636
637                while ((i = elementMap.begin()) != elementMap.end())
638                {
639                        OverlayElement* element = i->second;
640
641                        // Get factory to delete
642                        FactoryMap::iterator fi = mFactories.find(element->getTypeName());
643                        if (fi == mFactories.end())
644                        {
645                                OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, "Cannot locate factory for element " 
646                                        + element->getName(),
647                                        "OverlayManager::destroyAllOverlayElements");
648                        }
649
650                        // remove from parent, if any
651                        OverlayContainer* parent;
652                        if ((parent = element->getParent()) != 0)
653                        {
654                                parent->_removeChild(element->getName());
655                        }
656
657                        // children of containers will be auto-removed when container is destroyed.
658                        // destroy the element and remove it from the list
659                        fi->second->destroyOverlayElement(element);
660                        elementMap.erase(i);
661                }
662        }
663        //---------------------------------------------------------------------
664        void OverlayManager::addOverlayElementFactory(OverlayElementFactory* elemFactory)
665        {
666                // Add / replace
667                mFactories[elemFactory->getTypeName()] = elemFactory;
668
669                LogManager::getSingleton().logMessage("OverlayElementFactory for type " + elemFactory->getTypeName()
670                        + " registered.");
671        }
672}
673
Note: See TracBrowser for help on using the repository browser.