1 /*
2 -----------------------------------------------------------------------------
3 This source file is part of OGRE
4 (Object-oriented Graphics Rendering Engine)
5 For the latest info, see http://www.ogre3d.org
6 
7 Copyright (c) 2000-2014 Torus Knot Software Ltd
8 
9 Permission is hereby granted, free of charge, to any person obtaining a copy
10 of this software and associated documentation files (the "Software"), to deal
11 in the Software without restriction, including without limitation the rights
12 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 copies of the Software, and to permit persons to whom the Software is
14 furnished to do so, subject to the following conditions:
15 
16 The above copyright notice and this permission notice shall be included in
17 all copies or substantial portions of the Software.
18 
19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 THE SOFTWARE.
26 -----------------------------------------------------------------------------
27 */
28 // Ogre includes
29 #include "OgreStableHeaders.h"
30 
31 #include "OgreRenderWindow.h"
32 #include "OgreControllerManager.h"
33 #include "OgreDynLibManager.h"
34 #include "OgreDynLib.h"
35 #include "OgreConfigFile.h"
36 #include "OgreRenderSystemCapabilitiesManager.h"
37 #include "OgreSkeletonManager.h"
38 #include "OgreConfigDialog.h"
39 #include "OgrePlugin.h"
40 #include "OgreShadowVolumeExtrudeProgram.h"
41 #include "OgreResourceBackgroundQueue.h"
42 #include "OgreEntity.h"
43 #include "OgreBillboardSet.h"
44 #include "OgreBillboardChain.h"
45 #include "OgreRibbonTrail.h"
46 #include "OgreLight.h"
47 #include "OgreRenderQueueInvocation.h"
48 #include "OgreConvexBody.h"
49 #include "OgreTimer.h"
50 #include "OgreFrameListener.h"
51 #include "OgreLodStrategyManager.h"
52 #include "OgreFileSystemLayer.h"
53 #include "OgreSceneLoaderManager.h"
54 
55 #if OGRE_NO_DDS_CODEC == 0
56 #include "OgreDDSCodec.h"
57 #endif
58 
59 #include "OgreHardwareBufferManager.h"
60 #include "OgreHighLevelGpuProgramManager.h"
61 #include "OgreExternalTextureSourceManager.h"
62 #include "OgreCompositorManager.h"
63 
64 #if OGRE_NO_PVRTC_CODEC == 0
65 #  include "OgrePVRTCCodec.h"
66 #endif
67 #if OGRE_NO_ETC_CODEC == 0
68 #  include "OgreETCCodec.h"
69 #endif
70 #if OGRE_NO_ASTC_CODEC == 0
71 #  include "OgreASTCCodec.h"
72 #endif
73 
74 #if OGRE_PLATFORM == OGRE_PLATFORM_APPLE || OGRE_PLATFORM == OGRE_PLATFORM_APPLE_IOS
75 #include "macUtils.h"
76 #endif
77 
78 #if OGRE_PLATFORM == OGRE_PLATFORM_ANDROID
79 #include "Android/OgreAndroidLogListener.h"
80 #endif
81 
82 namespace Ogre {
83     //-----------------------------------------------------------------------
84     template<> Root* Singleton<Root>::msSingleton = 0;
getSingletonPtr(void)85     Root* Root::getSingletonPtr(void)
86     {
87         return msSingleton;
88     }
getSingleton(void)89     Root& Root::getSingleton(void)
90     {
91         assert( msSingleton );  return ( *msSingleton );
92     }
93 
94     typedef void (*DLL_START_PLUGIN)(void);
95     typedef void (*DLL_STOP_PLUGIN)(void);
96 
97     //-----------------------------------------------------------------------
Root(const String & pluginFileName,const String & configFileName,const String & logFileName)98     Root::Root(const String& pluginFileName, const String& configFileName,
99         const String& logFileName)
100       : mQueuedEnd(false)
101       , mNextFrame(0)
102       , mFrameSmoothingTime(0.0f)
103       , mRemoveQueueStructuresOnClear(false)
104       , mDefaultMinPixelSize(0)
105       , mNextMovableObjectTypeFlag(1)
106       , mIsInitialised(false)
107       , mIsBlendIndicesGpuRedundant(true)
108       , mIsBlendWeightsGpuRedundant(true)
109     {
110         // superclass will do singleton checking
111 
112         // Init
113         mActiveRenderer = 0;
114         mVersion = StringConverter::toString(OGRE_VERSION_MAJOR) + "." +
115             StringConverter::toString(OGRE_VERSION_MINOR) + "." +
116             StringConverter::toString(OGRE_VERSION_PATCH) +
117             OGRE_VERSION_SUFFIX + " " +
118             "(" + OGRE_VERSION_NAME + ")";
119         mConfigFileName = configFileName;
120 
121         // Create log manager and default log file if there is no log manager yet
122         if(!LogManager::getSingletonPtr())
123         {
124             mLogManager.reset(new LogManager());
125 
126 #if OGRE_PLATFORM == OGRE_PLATFORM_EMSCRIPTEN
127             // suppress writing log to Emscripten virtual FS, improves performance
128             mLogManager->createLog(logFileName, true, true, true);
129 #else
130             mLogManager->createLog(logFileName, true, true);
131 #endif
132         }
133 
134 #if OGRE_PLATFORM == OGRE_PLATFORM_ANDROID
135         mAndroidLogger.reset(new AndroidLogListener());
136         mLogManager->getDefaultLog()->addListener(mAndroidLogger.get());
137 #endif
138 
139         mDynLibManager.reset(new DynLibManager());
140         mArchiveManager.reset(new ArchiveManager());
141         mResourceGroupManager.reset(new ResourceGroupManager());
142 
143         // WorkQueue (note: users can replace this if they want)
144         DefaultWorkQueue* defaultQ = OGRE_NEW DefaultWorkQueue("Root");
145         // never process responses in main thread for longer than 10ms by default
146         defaultQ->setResponseProcessingTimeLimit(10);
147         // match threads to hardware
148         int threadCount = OGRE_THREAD_HARDWARE_CONCURRENCY;
149         // but clamp it at 2 by default - we dont scale much beyond that currently
150         // yet it helps on android where it needlessly burns CPU
151         threadCount = Math::Clamp(threadCount, 1, 2);
152         defaultQ->setWorkerThreadCount(threadCount);
153 
154         // only allow workers to access rendersystem if threadsupport is 1
155         defaultQ->setWorkersCanAccessRenderSystem(OGRE_THREAD_SUPPORT == 1);
156         mWorkQueue.reset(defaultQ);
157 
158         // ResourceBackgroundQueue
159         mResourceBackgroundQueue.reset(new ResourceBackgroundQueue());
160 
161         // Create SceneManager enumerator (note - will be managed by singleton)
162         mSceneManagerEnum.reset(new SceneManagerEnumerator());
163         mShadowTextureManager.reset(new ShadowTextureManager());
164         mRenderSystemCapabilitiesManager.reset(new RenderSystemCapabilitiesManager());
165         mMaterialManager.reset(new MaterialManager());
166         mMeshManager.reset(new MeshManager());
167         mSkeletonManager.reset(new SkeletonManager());
168         mParticleManager.reset(new ParticleSystemManager());
169         mTimer.reset(new Timer());
170         mLodStrategyManager.reset(new LodStrategyManager());
171 
172 #if OGRE_PROFILING
173         // Profiler
174         mProfiler.reset(new Profiler());
175         Profiler::getSingleton().setTimer(mTimer.get());
176 #endif
177 
178 
179         mFileSystemArchiveFactory.reset(new FileSystemArchiveFactory());
180         ArchiveManager::getSingleton().addArchiveFactory( mFileSystemArchiveFactory.get() );
181 #   if OGRE_NO_ZIP_ARCHIVE == 0
182         mZipArchiveFactory.reset(new ZipArchiveFactory());
183         ArchiveManager::getSingleton().addArchiveFactory( mZipArchiveFactory.get() );
184         mEmbeddedZipArchiveFactory.reset(new EmbeddedZipArchiveFactory());
185         ArchiveManager::getSingleton().addArchiveFactory( mEmbeddedZipArchiveFactory.get() );
186 #   endif
187 
188 #if OGRE_NO_DDS_CODEC == 0
189         // Register image codecs
190         DDSCodec::startup();
191 #endif
192 #if OGRE_NO_PVRTC_CODEC == 0
193         PVRTCCodec::startup();
194 #endif
195 #if OGRE_NO_ETC_CODEC == 0
196         ETCCodec::startup();
197 #endif
198 #if OGRE_NO_ASTC_CODEC == 0
199         ASTCCodec::startup();
200 #endif
201 
202         mHighLevelGpuProgramManager.reset(new HighLevelGpuProgramManager());
203         mExternalTextureSourceManager.reset(new ExternalTextureSourceManager());
204         mCompositorManager.reset(new CompositorManager());
205         mCompilerManager.reset(new ScriptCompilerManager());
206         mSceneLoaderManager.reset(new SceneLoaderManager());
207 
208         // Auto window
209         mAutoWindow = 0;
210 
211         // instantiate and register base movable factories
212         mEntityFactory.reset(new EntityFactory());
213         addMovableObjectFactory(mEntityFactory.get());
214         mLightFactory.reset(new LightFactory());
215         addMovableObjectFactory(mLightFactory.get());
216         mBillboardSetFactory.reset(new BillboardSetFactory());
217         addMovableObjectFactory(mBillboardSetFactory.get());
218         mManualObjectFactory.reset(new ManualObjectFactory());
219         addMovableObjectFactory(mManualObjectFactory.get());
220         mBillboardChainFactory.reset(new BillboardChainFactory());
221         addMovableObjectFactory(mBillboardChainFactory.get());
222         mRibbonTrailFactory.reset(new RibbonTrailFactory());
223         addMovableObjectFactory(mRibbonTrailFactory.get());
224 
225         // Load plugins
226         if (!pluginFileName.empty())
227             loadPlugins(pluginFileName);
228 
229         LogManager::getSingleton().logMessage("*-*-* OGRE Initialising");
230         LogManager::getSingleton().logMessage("*-*-* Version " + mVersion);
231 
232         // Can't create managers until initialised
233         mControllerManager = 0;
234 
235         mFirstTimePostWindowInit = false;
236     }
237 
238     //-----------------------------------------------------------------------
~Root()239     Root::~Root()
240     {
241         shutdown();
242 
243         destroyAllRenderQueueInvocationSequences();
244 
245 #if OGRE_NO_DDS_CODEC == 0
246         DDSCodec::shutdown();
247 #endif
248 #if OGRE_NO_PVRTC_CODEC == 0
249         PVRTCCodec::shutdown();
250 #endif
251 #if OGRE_NO_ETC_CODEC == 0
252         ETCCodec::shutdown();
253 #endif
254 #if OGRE_NO_ASTC_CODEC == 0
255         ASTCCodec::shutdown();
256 #endif
257 		mCompositorManager.reset(); // needs rendersystem
258         mParticleManager.reset(); // may use plugins
259         unloadPlugins();
260 
261         mAutoWindow = 0;
262 
263         StringInterface::cleanupDictionary();
264 
265 #if OGRE_PLATFORM == OGRE_PLATFORM_ANDROID
266         mLogManager->getDefaultLog()->removeListener(mAndroidLogger.get());
267 #endif
268     }
269 
270     //-----------------------------------------------------------------------
saveConfig(void)271     void Root::saveConfig(void)
272     {
273 #if OGRE_PLATFORM == OGRE_PLATFORM_EMSCRIPTEN
274         OGRE_EXCEPT(Exception::ERR_CANNOT_WRITE_TO_FILE, "saveConfig is not supported",
275             "Root::saveConfig");
276 #endif
277 #if OGRE_PLATFORM == OGRE_PLATFORM_APPLE_IOS
278         // Check the Documents directory within the application sandbox
279         Ogre::String outBaseName, extension, configFileName;
280         Ogre::StringUtil::splitFilename(mConfigFileName, outBaseName, extension);
281         configFileName = iOSDocumentsDirectory() + "/" + outBaseName;
282 		std::ofstream of(configFileName.c_str());
283         if (of.is_open())
284             mConfigFileName = configFileName;
285         else
286             mConfigFileName.clear();
287 #else
288         if (mConfigFileName.empty())
289             return;
290 
291         std::ofstream of(mConfigFileName.c_str());
292 #endif
293         if (!of)
294             OGRE_EXCEPT(Exception::ERR_CANNOT_WRITE_TO_FILE, "Cannot create settings file.",
295             "Root::saveConfig");
296 
297         if (mActiveRenderer)
298         {
299             of << "Render System=" << mActiveRenderer->getName() << std::endl;
300         }
301         else
302         {
303             of << "Render System=" << std::endl;
304         }
305 
306         for (RenderSystemList::const_iterator pRend = getAvailableRenderers().begin(); pRend != getAvailableRenderers().end(); ++pRend)
307         {
308             RenderSystem* rs = *pRend;
309             of << std::endl;
310             of << "[" << rs->getName() << "]" << std::endl;
311             const ConfigOptionMap& opts = rs->getConfigOptions();
312             for (ConfigOptionMap::const_iterator pOpt = opts.begin(); pOpt != opts.end(); ++pOpt)
313             {
314                 of << pOpt->first << "=" << pOpt->second.currentValue << std::endl;
315             }
316         }
317 
318         of.close();
319 
320     }
321     //-----------------------------------------------------------------------
restoreConfig(void)322     bool Root::restoreConfig(void)
323     {
324 #if OGRE_PLATFORM == OGRE_PLATFORM_EMSCRIPTEN
325         OGRE_EXCEPT(Exception::ERR_CANNOT_WRITE_TO_FILE, "restoreConfig is not supported",
326             "Root::restoreConfig");
327 #endif
328 
329 #if OGRE_PLATFORM == OGRE_PLATFORM_APPLE_IOS
330         // Read the config from Documents first(user config) if it exists on iOS.
331         // If it doesn't exist or is invalid then use mConfigFileName
332 
333         Ogre::String outBaseName, extension, configFileName;
334         Ogre::StringUtil::splitFilename(mConfigFileName, outBaseName, extension);
335         configFileName = iOSDocumentsDirectory() + "/" + outBaseName;
336 
337         std::ifstream fp;
338         fp.open(configFileName.c_str(), std::ios::in);
339         if(fp.is_open())
340         {
341             // A config file exists in the users Documents dir, we'll use it
342             mConfigFileName = configFileName;
343         }
344         else
345         {
346             std::ifstream configFp;
347 
348             // This might be the first run because there is no config file in the
349             // Documents directory.  It could also mean that a config file isn't being used at all
350 
351             // Try the path passed into initialise
352             configFp.open(mConfigFileName.c_str(), std::ios::in);
353 
354             // If we can't open this file then we have no default config file to work with
355             // Use the documents dir then.
356             if(!configFp.is_open())
357             {
358                 // Check to see if one was included in the app bundle
359                 mConfigFileName = macBundlePath() + "/ogre.cfg";
360 
361                 configFp.open(mConfigFileName.c_str(), std::ios::in);
362 
363                 // If we can't open this file then we have no default config file to work with
364                 // Use the Documents dir then.
365                 if(!configFp.is_open())
366                     mConfigFileName = configFileName;
367             }
368 
369             configFp.close();
370         }
371 
372         fp.close();
373 #endif
374 
375         if (mConfigFileName.empty ())
376             return true;
377 
378         // Restores configuration from saved state
379         // Returns true if a valid saved configuration is
380         //   available, and false if no saved config is
381         //   stored, or if there has been a problem
382         ConfigFile cfg;
383 
384         try {
385             // Don't trim whitespace
386             cfg.load(mConfigFileName, "\t:=", false);
387         }
388         catch (FileNotFoundException&)
389         {
390             return false;
391         }
392 
393         ConfigFile::SettingsBySection_::const_iterator seci;
394         for(seci = cfg.getSettingsBySection().begin(); seci != cfg.getSettingsBySection().end(); ++seci) {
395             const ConfigFile::SettingsMultiMap& settings = seci->second;
396             const String& renderSystem = seci->first;
397 
398             RenderSystem* rs = getRenderSystemByName(renderSystem);
399             if (!rs)
400             {
401                 // Unrecognised render system
402                 continue;
403             }
404 
405             ConfigFile::SettingsMultiMap::const_iterator i;
406             for (i = settings.begin(); i != settings.end(); ++i)
407             {
408                 rs->setConfigOption(i->first, i->second);
409             }
410         }
411 
412         RenderSystem* rs = getRenderSystemByName(cfg.getSetting("Render System"));
413         if (!rs)
414         {
415             // Unrecognised render system
416             return false;
417         }
418 
419         String err = rs->validateConfigOptions();
420         if (err.length() > 0)
421             return false;
422 
423         setRenderSystem(rs);
424 
425         // Successful load
426         return true;
427 
428     }
429 
430     //-----------------------------------------------------------------------
showConfigDialog(ConfigDialog * dialog)431     bool Root::showConfigDialog(ConfigDialog* dialog) {
432         if(dialog) {
433             restoreConfig();
434 
435             if (dialog->display()) {
436                 saveConfig();
437                 return true;
438             }
439 
440             return false;
441         }
442 
443         // just select the first available render system
444         if (!mRenderers.empty())
445         {
446             setRenderSystem(mRenderers.front());
447             return true;
448         }
449 
450         return false;
451     }
452 
453     //-----------------------------------------------------------------------
getAvailableRenderers(void)454     const RenderSystemList& Root::getAvailableRenderers(void)
455     {
456         // Returns a vector of renders
457 
458         return mRenderers;
459 
460     }
461 
462     //-----------------------------------------------------------------------
getRenderSystemByName(const String & name)463     RenderSystem* Root::getRenderSystemByName(const String& name)
464     {
465         if (name.empty())
466         {
467             // No render system
468             return NULL;
469         }
470 
471         RenderSystemList::const_iterator pRend;
472         for (pRend = getAvailableRenderers().begin(); pRend != getAvailableRenderers().end(); ++pRend)
473         {
474             RenderSystem* rs = *pRend;
475             if (rs->getName() == name)
476                 return rs;
477         }
478 
479         // Unrecognised render system
480         return NULL;
481     }
482 
483     //-----------------------------------------------------------------------
setRenderSystem(RenderSystem * system)484     void Root::setRenderSystem(RenderSystem* system)
485     {
486         // Sets the active rendering system
487         // Can be called direct or will be called by
488         //   standard config dialog
489 
490         // Is there already an active renderer?
491         // If so, disable it and init the new one
492         if( mActiveRenderer && mActiveRenderer != system )
493         {
494             mActiveRenderer->shutdown();
495         }
496 
497         mActiveRenderer = system;
498         // Tell scene managers
499         if(mSceneManagerEnum)
500             mSceneManagerEnum->setRenderSystem(system);
501 
502         if(RenderSystem::Listener* ls = RenderSystem::getSharedListener())
503             ls->eventOccurred("RenderSystemChanged");
504     }
505     //-----------------------------------------------------------------------
addRenderSystem(RenderSystem * newRend)506     void Root::addRenderSystem(RenderSystem *newRend)
507     {
508         mRenderers.push_back(newRend);
509     }
510     //-----------------------------------------------------------------------
_getCurrentSceneManager(void) const511     SceneManager* Root::_getCurrentSceneManager(void) const
512     {
513         if (mSceneManagerStack.empty())
514             return 0;
515         else
516             return mSceneManagerStack.back();
517     }
518     //-----------------------------------------------------------------------
_pushCurrentSceneManager(SceneManager * sm)519     void Root::_pushCurrentSceneManager(SceneManager* sm)
520     {
521         mSceneManagerStack.push_back(sm);
522     }
523     //-----------------------------------------------------------------------
_popCurrentSceneManager(SceneManager * sm)524     void Root::_popCurrentSceneManager(SceneManager* sm)
525     {
526         assert (_getCurrentSceneManager() == sm && "Mismatched push/pop of SceneManager");
527 
528         mSceneManagerStack.pop_back();
529     }
530     //-----------------------------------------------------------------------
getRenderSystem(void)531     RenderSystem* Root::getRenderSystem(void)
532     {
533         // Gets the currently active renderer
534         return mActiveRenderer;
535 
536     }
537 
538     //-----------------------------------------------------------------------
initialise(bool autoCreateWindow,const String & windowTitle,const String & customCapabilitiesConfig)539     RenderWindow* Root::initialise(bool autoCreateWindow, const String& windowTitle, const String& customCapabilitiesConfig)
540     {
541         if (!mActiveRenderer)
542             OGRE_EXCEPT(Exception::ERR_INVALID_STATE,
543             "Cannot initialise - no render "
544             "system has been selected.", "Root::initialise");
545 
546         if (!mControllerManager)
547             mControllerManager.reset(new ControllerManager());
548 
549         // .rendercaps manager
550         RenderSystemCapabilitiesManager& rscManager = RenderSystemCapabilitiesManager::getSingleton();
551         // caller wants to load custom RenderSystemCapabilities form a config file
552         if(!customCapabilitiesConfig.empty())
553         {
554             ConfigFile cfg;
555             cfg.load(customCapabilitiesConfig, "\t:=", false);
556 
557             // Capabilities Database setting must be in the same format as
558             // resources.cfg in Ogre examples.
559             const ConfigFile::SettingsMultiMap& dbs = cfg.getSettings("Capabilities Database");
560             for(ConfigFile::SettingsMultiMap::const_iterator it = dbs.begin(); it != dbs.end(); ++it)
561             {
562                 const String& archType = it->first;
563 #if OGRE_PLATFORM == OGRE_PLATFORM_APPLE || OGRE_PLATFORM == OGRE_PLATFORM_APPLE_IOS
564                 String filename = it->second;
565 
566                 // Only adjust relative directories
567                 if (!StringUtil::startsWith(filename, "/", false))
568                 {
569                     filename = StringUtil::replaceAll(filename, "../", "");
570                     filename = String(macBundlePath() + "/Contents/Resources/" + filename);
571                 }
572 #else
573                 String filename = it->second;
574 #endif
575 
576                 rscManager.parseCapabilitiesFromArchive(filename, archType, true);
577             }
578 
579             String capsName = cfg.getSetting("Custom Capabilities");
580             // The custom capabilities have been parsed, let's retrieve them
581             RenderSystemCapabilities* rsc = rscManager.loadParsedCapabilities(capsName);
582             if(rsc == 0)
583             {
584                 OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND,
585                     String("Cannot load a RenderSystemCapability named ") + capsName,
586                     "Root::initialise");
587             }
588 
589             // Tell RenderSystem to use the comon rsc
590             useCustomRenderSystemCapabilities(rsc);
591         }
592 
593 
594         PlatformInformation::log(LogManager::getSingleton().getDefaultLog());
595         mAutoWindow =  mActiveRenderer->_initialise(autoCreateWindow, windowTitle);
596 
597 
598         if (autoCreateWindow && !mFirstTimePostWindowInit)
599         {
600             oneTimePostWindowInit();
601             mAutoWindow->_setPrimary();
602         }
603 
604         // Initialise timer
605         mTimer->reset();
606 
607         // Init pools
608         ConvexBody::_initialisePool();
609 
610         mIsInitialised = true;
611 
612         return mAutoWindow;
613 
614     }
615     //-----------------------------------------------------------------------
useCustomRenderSystemCapabilities(RenderSystemCapabilities * capabilities)616     void Root::useCustomRenderSystemCapabilities(RenderSystemCapabilities* capabilities)
617     {
618         mActiveRenderer->useCustomRenderSystemCapabilities(capabilities);
619     }
620     //-----------------------------------------------------------------------
addSceneManagerFactory(SceneManagerFactory * fact)621     void Root::addSceneManagerFactory(SceneManagerFactory* fact)
622     {
623         mSceneManagerEnum->addFactory(fact);
624     }
625     //-----------------------------------------------------------------------
removeSceneManagerFactory(SceneManagerFactory * fact)626     void Root::removeSceneManagerFactory(SceneManagerFactory* fact)
627     {
628         mSceneManagerEnum->removeFactory(fact);
629     }
630     //-----------------------------------------------------------------------
getSceneManagerMetaData(const String & typeName) const631     const SceneManagerMetaData* Root::getSceneManagerMetaData(const String& typeName) const
632     {
633         return mSceneManagerEnum->getMetaData(typeName);
634     }
635     //-----------------------------------------------------------------------
636     SceneManagerEnumerator::MetaDataIterator
getSceneManagerMetaDataIterator(void) const637     Root::getSceneManagerMetaDataIterator(void) const
638     {
639         return mSceneManagerEnum->getMetaDataIterator();
640     }
641     //-----------------------------------------------------------------------
642     const SceneManagerEnumerator::MetaDataList&
getSceneManagerMetaData(void) const643     Root::getSceneManagerMetaData(void) const
644     {
645         return mSceneManagerEnum->getMetaData();
646     }
647     //-----------------------------------------------------------------------
createSceneManager(const String & typeName,const String & instanceName)648     SceneManager* Root::createSceneManager(const String& typeName,
649         const String& instanceName)
650     {
651         return mSceneManagerEnum->createSceneManager(typeName, instanceName);
652     }
653     //-----------------------------------------------------------------------
destroySceneManager(SceneManager * sm)654     void Root::destroySceneManager(SceneManager* sm)
655     {
656         mSceneManagerEnum->destroySceneManager(sm);
657     }
658     //-----------------------------------------------------------------------
getSceneManager(const String & instanceName) const659     SceneManager* Root::getSceneManager(const String& instanceName) const
660     {
661         return mSceneManagerEnum->getSceneManager(instanceName);
662     }
663     //---------------------------------------------------------------------
hasSceneManager(const String & instanceName) const664     bool Root::hasSceneManager(const String& instanceName) const
665     {
666         return mSceneManagerEnum->hasSceneManager(instanceName);
667     }
668     //-----------------------------------------------------------------------
getSceneManagerIterator(void)669     SceneManagerEnumerator::SceneManagerIterator Root::getSceneManagerIterator(void)
670     {
671         return mSceneManagerEnum->getSceneManagerIterator();
672     }
673     //-----------------------------------------------------------------------
getSceneManagers(void) const674     const SceneManagerEnumerator::Instances& Root::getSceneManagers(void) const
675     {
676         return mSceneManagerEnum->getSceneManagers();
677     }
678     //-----------------------------------------------------------------------
getTextureManager(void)679     TextureManager* Root::getTextureManager(void)
680     {
681         return &TextureManager::getSingleton();
682     }
683     //-----------------------------------------------------------------------
getMeshManager(void)684     MeshManager* Root::getMeshManager(void)
685     {
686         return &MeshManager::getSingleton();
687     }
688     //-----------------------------------------------------------------------
addFrameListener(FrameListener * newListener)689     void Root::addFrameListener(FrameListener* newListener)
690     {
691         mRemovedFrameListeners.erase(newListener);
692         mAddedFrameListeners.insert(newListener);
693     }
694     //-----------------------------------------------------------------------
removeFrameListener(FrameListener * oldListener)695     void Root::removeFrameListener(FrameListener* oldListener)
696     {
697         mAddedFrameListeners.erase(oldListener);
698         mRemovedFrameListeners.insert(oldListener);
699     }
700     //-----------------------------------------------------------------------
_syncAddedRemovedFrameListeners()701     void Root::_syncAddedRemovedFrameListeners()
702     {
703         for (std::set<FrameListener*>::iterator i = mRemovedFrameListeners.begin(); i != mRemovedFrameListeners.end(); ++i)
704             mFrameListeners.erase(*i);
705         mRemovedFrameListeners.clear();
706 
707         for (std::set<FrameListener*>::iterator i = mAddedFrameListeners.begin(); i != mAddedFrameListeners.end(); ++i)
708             mFrameListeners.insert(*i);
709         mAddedFrameListeners.clear();
710     }
711     //-----------------------------------------------------------------------
_fireFrameStarted(FrameEvent & evt)712     bool Root::_fireFrameStarted(FrameEvent& evt)
713     {
714         OgreProfileBeginGroup("Frame", OGREPROF_GENERAL);
715         _syncAddedRemovedFrameListeners();
716 
717         // Tell all listeners
718         for (std::set<FrameListener*>::iterator i = mFrameListeners.begin(); i != mFrameListeners.end(); ++i)
719         {
720             if(mRemovedFrameListeners.find(*i) != mRemovedFrameListeners.end())
721                 continue;
722 
723             if (!(*i)->frameStarted(evt))
724                 return false;
725         }
726 
727         return true;
728     }
729     //-----------------------------------------------------------------------
_fireFrameRenderingQueued(FrameEvent & evt)730     bool Root::_fireFrameRenderingQueued(FrameEvent& evt)
731     {
732         // Increment next frame number
733         ++mNextFrame;
734         _syncAddedRemovedFrameListeners();
735 
736         // Tell all listeners
737         for (std::set<FrameListener*>::iterator i = mFrameListeners.begin(); i != mFrameListeners.end(); ++i)
738         {
739             if(mRemovedFrameListeners.find(*i) != mRemovedFrameListeners.end())
740                 continue;
741 
742             if (!(*i)->frameRenderingQueued(evt))
743                 return false;
744         }
745 
746         return true;
747     }
748     //-----------------------------------------------------------------------
_fireFrameEnded(FrameEvent & evt)749     bool Root::_fireFrameEnded(FrameEvent& evt)
750     {
751         _syncAddedRemovedFrameListeners();
752 
753         // Tell all listeners
754         bool ret = true;
755         for (std::set<FrameListener*>::iterator i = mFrameListeners.begin(); i != mFrameListeners.end(); ++i)
756         {
757             if(mRemovedFrameListeners.find(*i) != mRemovedFrameListeners.end())
758                 continue;
759 
760             if (!(*i)->frameEnded(evt))
761             {
762                 ret = false;
763                 break;
764             }
765         }
766 
767         // Tell buffer manager to free temp buffers used this frame
768         if (HardwareBufferManager::getSingletonPtr())
769             HardwareBufferManager::getSingleton()._releaseBufferCopies();
770 
771         // Tell the queue to process responses
772         mWorkQueue->processResponses();
773 
774         OgreProfileEndGroup("Frame", OGREPROF_GENERAL);
775 
776         return ret;
777     }
778     //-----------------------------------------------------------------------
_fireFrameStarted()779     bool Root::_fireFrameStarted()
780     {
781         FrameEvent evt;
782         populateFrameEvent(FETT_STARTED, evt);
783 
784         return _fireFrameStarted(evt);
785     }
786     //-----------------------------------------------------------------------
_fireFrameRenderingQueued()787     bool Root::_fireFrameRenderingQueued()
788     {
789         FrameEvent evt;
790         populateFrameEvent(FETT_QUEUED, evt);
791 
792         return _fireFrameRenderingQueued(evt);
793     }
794     //-----------------------------------------------------------------------
_fireFrameEnded()795     bool Root::_fireFrameEnded()
796     {
797         FrameEvent evt;
798         populateFrameEvent(FETT_ENDED, evt);
799         return _fireFrameEnded(evt);
800     }
801     //---------------------------------------------------------------------
populateFrameEvent(FrameEventTimeType type,FrameEvent & evtToUpdate)802     void Root::populateFrameEvent(FrameEventTimeType type, FrameEvent& evtToUpdate)
803     {
804         unsigned long now = mTimer->getMilliseconds();
805         evtToUpdate.timeSinceLastEvent = calculateEventTime(now, FETT_ANY);
806         evtToUpdate.timeSinceLastFrame = calculateEventTime(now, type);
807     }
808     //-----------------------------------------------------------------------
calculateEventTime(unsigned long now,FrameEventTimeType type)809     Real Root::calculateEventTime(unsigned long now, FrameEventTimeType type)
810     {
811         // Calculate the average time passed between events of the given type
812         // during the last mFrameSmoothingTime seconds.
813 
814         EventTimesQueue& times = mEventTimes[type];
815         times.push_back(now);
816 
817         if(times.size() == 1)
818             return 0;
819 
820         // Times up to mFrameSmoothingTime seconds old should be kept
821         unsigned long discardThreshold =
822             static_cast<unsigned long>(mFrameSmoothingTime * 1000.0f);
823 
824         // Find the oldest time to keep
825         EventTimesQueue::iterator it = times.begin(),
826             end = times.end()-2; // We need at least two times
827         while(it != end)
828         {
829             if (now - *it > discardThreshold)
830                 ++it;
831             else
832                 break;
833         }
834 
835         // Remove old times
836         times.erase(times.begin(), it);
837 
838         return Real(times.back() - times.front()) / ((times.size()-1) * 1000);
839     }
840     //-----------------------------------------------------------------------
queueEndRendering(bool state)841     void Root::queueEndRendering(bool state /* = true */)
842     {
843         mQueuedEnd = state;
844     }
845     //-----------------------------------------------------------------------
endRenderingQueued(void)846     bool Root::endRenderingQueued(void)
847     {
848         return mQueuedEnd;
849     }
850     //-----------------------------------------------------------------------
startRendering(void)851     void Root::startRendering(void)
852     {
853         OgreAssert(mActiveRenderer != 0, "no RenderSystem");
854 
855         mActiveRenderer->_initRenderTargets();
856 
857         // Clear event times
858         clearEventTimes();
859 
860         // Infinite loop, until broken out of by frame listeners
861         // or break out by calling queueEndRendering()
862         mQueuedEnd = false;
863 
864         while( !mQueuedEnd )
865         {
866             if (!renderOneFrame())
867                 break;
868         }
869     }
870     //-----------------------------------------------------------------------
renderOneFrame(void)871     bool Root::renderOneFrame(void)
872     {
873         if(!_fireFrameStarted())
874             return false;
875 
876         if (!_updateAllRenderTargets())
877             return false;
878 
879         return _fireFrameEnded();
880     }
881     //---------------------------------------------------------------------
renderOneFrame(Real timeSinceLastFrame)882     bool Root::renderOneFrame(Real timeSinceLastFrame)
883     {
884         FrameEvent evt;
885         evt.timeSinceLastFrame = timeSinceLastFrame;
886 
887         unsigned long now = mTimer->getMilliseconds();
888         evt.timeSinceLastEvent = calculateEventTime(now, FETT_ANY);
889 
890         if(!_fireFrameStarted(evt))
891             return false;
892 
893         if (!_updateAllRenderTargets(evt))
894             return false;
895 
896         now = mTimer->getMilliseconds();
897         evt.timeSinceLastEvent = calculateEventTime(now, FETT_ANY);
898 
899         return _fireFrameEnded(evt);
900     }
901     //-----------------------------------------------------------------------
shutdown(void)902     void Root::shutdown(void)
903     {
904         if(mActiveRenderer)
905             mActiveRenderer->_setViewport(NULL);
906 
907         // Since background thread might be access resources,
908         // ensure shutdown before destroying resource manager.
909         mResourceBackgroundQueue->shutdown();
910         mWorkQueue->shutdown();
911 
912         if(mSceneManagerEnum)
913             mSceneManagerEnum->shutdownAll();
914         if(mFirstTimePostWindowInit)
915         {
916             shutdownPlugins();
917             mParticleManager->removeAllTemplates(true);
918             mFirstTimePostWindowInit = false;
919         }
920         mSceneManagerEnum.reset();
921         mShadowTextureManager.reset();
922 
923         ShadowVolumeExtrudeProgram::shutdown();
924         ResourceGroupManager::getSingleton().shutdownAll();
925 
926         // Destroy pools
927         ConvexBody::_destroyPool();
928 
929 
930         mIsInitialised = false;
931 
932         LogManager::getSingleton().logMessage("*-*-* OGRE Shutdown");
933     }
934     //-----------------------------------------------------------------------
loadPlugins(const String & pluginsfile)935     void Root::loadPlugins( const String& pluginsfile )
936     {
937         StringVector pluginList;
938         String pluginDir;
939         ConfigFile cfg;
940 
941         try {
942             cfg.load( pluginsfile );
943         }
944         catch (Exception& e)
945         {
946             LogManager::getSingleton().logMessage("automatic plugin loading disabled: "+e.getDescription());
947             return;
948         }
949 
950         pluginDir = cfg.getSetting("PluginFolder");
951         pluginList = cfg.getMultiSetting("Plugin");
952 
953         StringUtil::trim(pluginDir);
954         if(pluginDir.empty() || pluginDir[0] == '.')
955         {
956             // resolve relative path with regards to configfile
957             String baseDir, filename;
958             StringUtil::splitFilename(pluginsfile, filename, baseDir);
959             pluginDir = baseDir + pluginDir;
960         }
961 
962         pluginDir = FileSystemLayer::resolveBundlePath(pluginDir);
963 
964         if (!pluginDir.empty() && *pluginDir.rbegin() != '/' && *pluginDir.rbegin() != '\\')
965         {
966 #if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 || OGRE_PLATFORM == OGRE_PLATFORM_WINRT
967             pluginDir += "\\";
968 #elif OGRE_PLATFORM == OGRE_PLATFORM_LINUX
969             pluginDir += "/";
970 #endif
971         }
972 
973         for( StringVector::iterator it = pluginList.begin(); it != pluginList.end(); ++it )
974         {
975             loadPlugin(pluginDir + (*it));
976         }
977 
978     }
979     //-----------------------------------------------------------------------
shutdownPlugins(void)980     void Root::shutdownPlugins(void)
981     {
982         // NB Shutdown plugins in reverse order to enforce dependencies
983         for (PluginInstanceList::reverse_iterator i = mPlugins.rbegin(); i != mPlugins.rend(); ++i)
984         {
985             (*i)->shutdown();
986         }
987     }
988     //-----------------------------------------------------------------------
initialisePlugins(void)989     void Root::initialisePlugins(void)
990     {
991         for (PluginInstanceList::iterator i = mPlugins.begin(); i != mPlugins.end(); ++i)
992         {
993             (*i)->initialise();
994         }
995     }
996     //-----------------------------------------------------------------------
unloadPlugins(void)997     void Root::unloadPlugins(void)
998     {
999 #if OGRE_PLATFORM != OGRE_PLATFORM_EMSCRIPTEN
1000         // unload dynamic libs first
1001         for (PluginLibList::reverse_iterator i = mPluginLibs.rbegin(); i != mPluginLibs.rend(); ++i)
1002         {
1003             // Call plugin shutdown
1004             #ifdef __GNUC__
1005             __extension__
1006             #endif
1007             DLL_STOP_PLUGIN pFunc = reinterpret_cast<DLL_STOP_PLUGIN>((*i)->getSymbol("dllStopPlugin"));
1008             // this will call uninstallPlugin
1009             pFunc();
1010             // Unload library & destroy
1011             DynLibManager::getSingleton().unload(*i);
1012 
1013         }
1014         mPluginLibs.clear();
1015 
1016         // now deal with any remaining plugins that were registered through other means
1017         for (PluginInstanceList::reverse_iterator i = mPlugins.rbegin(); i != mPlugins.rend(); ++i)
1018         {
1019             // Note this does NOT call uninstallPlugin - this shutdown is for the
1020             // detail objects
1021             (*i)->uninstall();
1022         }
1023         mPlugins.clear();
1024 #endif
1025     }
1026     //---------------------------------------------------------------------
createFileStream(const String & filename,const String & groupName,bool overwrite,const String & locationPattern)1027     DataStreamPtr Root::createFileStream(const String& filename, const String& groupName,
1028         bool overwrite, const String& locationPattern)
1029     {
1030         // Does this file include path specifiers?
1031         String path, basename;
1032         StringUtil::splitFilename(filename, basename, path);
1033 
1034         // no path elements, try the resource system first
1035         DataStreamPtr stream;
1036         if (path.empty())
1037         {
1038             try
1039             {
1040                 stream = ResourceGroupManager::getSingleton().createResource(
1041                     filename, groupName, overwrite, locationPattern);
1042             }
1043             catch (...) {}
1044 
1045         }
1046 
1047         if (!stream)
1048         {
1049             // save direct in filesystem
1050             std::fstream* fs = OGRE_NEW_T(std::fstream, MEMCATEGORY_GENERAL);
1051             fs->open(filename.c_str(), std::ios::out | std::ios::binary);
1052             if (!*fs)
1053             {
1054                 OGRE_DELETE_T(fs, basic_fstream, MEMCATEGORY_GENERAL);
1055                 OGRE_EXCEPT(Exception::ERR_CANNOT_WRITE_TO_FILE,
1056                             "Can't open " + filename + " for writing");
1057             }
1058 
1059             stream = DataStreamPtr(OGRE_NEW FileStreamDataStream(filename, fs));
1060         }
1061 
1062         return stream;
1063 
1064     }
1065     //---------------------------------------------------------------------
openFileStream(const String & filename,const String & groupName)1066     DataStreamPtr Root::openFileStream(const String& filename, const String& groupName)
1067     {
1068         auto ret = ResourceGroupManager::getSingleton().openResource(filename, groupName, NULL, false);
1069         if(ret)
1070             return ret;
1071 
1072         // try direct
1073         std::ifstream *ifs = OGRE_NEW_T(std::ifstream, MEMCATEGORY_GENERAL);
1074         ifs->open(filename.c_str(), std::ios::in | std::ios::binary);
1075         if(!*ifs)
1076         {
1077             OGRE_DELETE_T(ifs, basic_ifstream, MEMCATEGORY_GENERAL);
1078             OGRE_EXCEPT(Exception::ERR_FILE_NOT_FOUND, "'" + filename + "' file not found!");
1079         }
1080         return DataStreamPtr(OGRE_NEW FileStreamDataStream(filename, ifs));
1081     }
1082     //-----------------------------------------------------------------------
convertColourValue(const ColourValue & colour,uint32 * pDest)1083     void Root::convertColourValue(const ColourValue& colour, uint32* pDest)
1084     {
1085         assert(mActiveRenderer != 0);
1086         mActiveRenderer->convertColourValue(colour, pDest);
1087     }
1088     //-----------------------------------------------------------------------
getAutoCreatedWindow(void)1089     RenderWindow* Root::getAutoCreatedWindow(void)
1090     {
1091         return mAutoWindow;
1092     }
1093     //-----------------------------------------------------------------------
createRenderWindow(const String & name,unsigned int width,unsigned int height,bool fullScreen,const NameValuePairList * miscParams)1094     RenderWindow* Root::createRenderWindow(const String &name, unsigned int width, unsigned int height,
1095             bool fullScreen, const NameValuePairList *miscParams)
1096     {
1097         if (!mIsInitialised)
1098         {
1099             OGRE_EXCEPT(Exception::ERR_INVALID_STATE,
1100             "Cannot create window - Root has not been initialised! "
1101             "Make sure to call Root::initialise before creating a window.", "Root::createRenderWindow");
1102         }
1103         if (!mActiveRenderer)
1104         {
1105             OGRE_EXCEPT(Exception::ERR_INVALID_STATE,
1106             "Cannot create window - no render "
1107             "system has been selected.", "Root::createRenderWindow");
1108         }
1109         RenderWindow* ret;
1110         ret = mActiveRenderer->_createRenderWindow(name, width, height, fullScreen, miscParams);
1111 
1112         // Initialisation for classes dependent on first window created
1113         if(!mFirstTimePostWindowInit)
1114         {
1115             oneTimePostWindowInit();
1116             ret->_setPrimary();
1117         }
1118 
1119         return ret;
1120 
1121     }
1122     //-----------------------------------------------------------------------
createRenderWindows(const RenderWindowDescriptionList & renderWindowDescriptions,RenderWindowList & createdWindows)1123     bool Root::createRenderWindows(const RenderWindowDescriptionList& renderWindowDescriptions,
1124         RenderWindowList& createdWindows)
1125     {
1126         if (!mIsInitialised)
1127         {
1128             OGRE_EXCEPT(Exception::ERR_INVALID_STATE,
1129             "Cannot create window - Root has not been initialised! "
1130             "Make sure to call Root::initialise before creating a window.", "Root::createRenderWindows");
1131         }
1132         if (!mActiveRenderer)
1133         {
1134             OGRE_EXCEPT(Exception::ERR_INVALID_STATE,
1135                 "Cannot create render windows - no render "
1136                 "system has been selected.", "Root::createRenderWindows");
1137         }
1138 
1139         bool success;
1140 
1141         success = mActiveRenderer->_createRenderWindows(renderWindowDescriptions, createdWindows);
1142         if(success && !mFirstTimePostWindowInit)
1143         {
1144             oneTimePostWindowInit();
1145             createdWindows[0]->_setPrimary();
1146         }
1147 
1148         return success;
1149     }
1150     //-----------------------------------------------------------------------
detachRenderTarget(RenderTarget * target)1151     RenderTarget* Root::detachRenderTarget(RenderTarget* target)
1152     {
1153         if (!mActiveRenderer)
1154         {
1155             OGRE_EXCEPT(Exception::ERR_INVALID_STATE,
1156             "Cannot detach target - no render "
1157             "system has been selected.", "Root::detachRenderTarget");
1158         }
1159 
1160         return mActiveRenderer->detachRenderTarget( target->getName() );
1161     }
1162     //-----------------------------------------------------------------------
detachRenderTarget(const String & name)1163     RenderTarget* Root::detachRenderTarget(const String &name)
1164     {
1165         if (!mActiveRenderer)
1166         {
1167             OGRE_EXCEPT(Exception::ERR_INVALID_STATE,
1168             "Cannot detach target - no render "
1169             "system has been selected.", "Root::detachRenderTarget");
1170         }
1171 
1172         return mActiveRenderer->detachRenderTarget( name );
1173     }
1174     //-----------------------------------------------------------------------
destroyRenderTarget(RenderTarget * target)1175     void Root::destroyRenderTarget(RenderTarget* target)
1176     {
1177         detachRenderTarget(target);
1178         OGRE_DELETE target;
1179     }
1180     //-----------------------------------------------------------------------
destroyRenderTarget(const String & name)1181     void Root::destroyRenderTarget(const String &name)
1182     {
1183         RenderTarget* target = getRenderTarget(name);
1184         destroyRenderTarget(target);
1185     }
1186     //-----------------------------------------------------------------------
getRenderTarget(const String & name)1187     RenderTarget* Root::getRenderTarget(const String &name)
1188     {
1189         if (!mActiveRenderer)
1190         {
1191             OGRE_EXCEPT(Exception::ERR_INVALID_STATE,
1192             "Cannot get target - no render "
1193             "system has been selected.", "Root::getRenderTarget");
1194         }
1195 
1196         return mActiveRenderer->getRenderTarget(name);
1197     }
1198     //---------------------------------------------------------------------
installPlugin(Plugin * plugin)1199     void Root::installPlugin(Plugin* plugin)
1200     {
1201         LogManager::getSingleton().logMessage("Installing plugin: " + plugin->getName());
1202 
1203         mPlugins.push_back(plugin);
1204         plugin->install();
1205 
1206         // if rendersystem is already initialised, call rendersystem init too
1207         if (mIsInitialised)
1208         {
1209             plugin->initialise();
1210         }
1211 
1212         LogManager::getSingleton().logMessage("Plugin successfully installed");
1213     }
1214     //---------------------------------------------------------------------
uninstallPlugin(Plugin * plugin)1215     void Root::uninstallPlugin(Plugin* plugin)
1216     {
1217         LogManager::getSingleton().logMessage("Uninstalling plugin: " + plugin->getName());
1218         PluginInstanceList::iterator i =
1219             std::find(mPlugins.begin(), mPlugins.end(), plugin);
1220         if (i != mPlugins.end())
1221         {
1222             if (mIsInitialised)
1223                 plugin->shutdown();
1224             plugin->uninstall();
1225             mPlugins.erase(i);
1226         }
1227         LogManager::getSingleton().logMessage("Plugin successfully uninstalled");
1228 
1229     }
1230     //-----------------------------------------------------------------------
loadPlugin(const String & pluginName)1231     void Root::loadPlugin(const String& pluginName)
1232     {
1233 #if OGRE_PLATFORM != OGRE_PLATFORM_EMSCRIPTEN
1234         // Load plugin library
1235         DynLib* lib = DynLibManager::getSingleton().load( pluginName );
1236         // Store for later unload
1237         // Check for existence, because if called 2+ times DynLibManager returns existing entry
1238         if (std::find(mPluginLibs.begin(), mPluginLibs.end(), lib) == mPluginLibs.end())
1239         {
1240             mPluginLibs.push_back(lib);
1241 
1242             // Call startup function
1243                         #ifdef __GNUC__
1244                         __extension__
1245                         #endif
1246             DLL_START_PLUGIN pFunc = (DLL_START_PLUGIN)lib->getSymbol("dllStartPlugin");
1247 
1248             if (!pFunc)
1249                 OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, "Cannot find symbol dllStartPlugin in library " + pluginName,
1250                     "Root::loadPlugin");
1251 
1252             // This must call installPlugin
1253             pFunc();
1254         }
1255 #endif
1256     }
1257     //-----------------------------------------------------------------------
unloadPlugin(const String & pluginName)1258     void Root::unloadPlugin(const String& pluginName)
1259     {
1260 #if OGRE_PLATFORM != OGRE_PLATFORM_EMSCRIPTEN
1261         PluginLibList::iterator i;
1262 
1263         for (i = mPluginLibs.begin(); i != mPluginLibs.end(); ++i)
1264         {
1265             if ((*i)->getName() == pluginName)
1266             {
1267                 // Call plugin shutdown
1268                                 #ifdef __GNUC__
1269                                 __extension__
1270                                 #endif
1271                 DLL_STOP_PLUGIN pFunc = (DLL_STOP_PLUGIN)(*i)->getSymbol("dllStopPlugin");
1272                 // this must call uninstallPlugin
1273                 pFunc();
1274                 // Unload library (destroyed by DynLibManager)
1275                 DynLibManager::getSingleton().unload(*i);
1276                 mPluginLibs.erase(i);
1277                 return;
1278             }
1279 
1280         }
1281 #endif
1282     }
1283     //-----------------------------------------------------------------------
getTimer(void)1284     Timer* Root::getTimer(void)
1285     {
1286         return mTimer.get();
1287     }
1288     //-----------------------------------------------------------------------
oneTimePostWindowInit(void)1289     void Root::oneTimePostWindowInit(void)
1290     {
1291         if (!mFirstTimePostWindowInit)
1292         {
1293             // Background loader
1294             mResourceBackgroundQueue->initialise();
1295             mWorkQueue->startup();
1296             // Initialise material manager
1297             mMaterialManager->initialise();
1298             // Init particle systems manager
1299             mParticleManager->_initialise();
1300             // Init mesh manager
1301             MeshManager::getSingleton()._initialise();
1302             // Init plugins - after window creation so rsys resources available
1303             initialisePlugins();
1304             mFirstTimePostWindowInit = true;
1305         }
1306 
1307     }
1308     //-----------------------------------------------------------------------
_updateAllRenderTargets(void)1309     bool Root::_updateAllRenderTargets(void)
1310     {
1311         // update all targets but don't swap buffers
1312         mActiveRenderer->_updateAllRenderTargets(false);
1313         // give client app opportunity to use queued GPU time
1314         bool ret = _fireFrameRenderingQueued();
1315         // block for final swap
1316         mActiveRenderer->_swapAllRenderTargetBuffers();
1317 
1318         // This belongs here, as all render targets must be updated before events are
1319         // triggered, otherwise targets could be mismatched.  This could produce artifacts,
1320         // for instance, with shadows.
1321         SceneManagerEnumerator::Instances::const_iterator it, end = getSceneManagers().end();
1322         for (it = getSceneManagers().begin(); it != end; ++it)
1323             it->second->_handleLodEvents();
1324 
1325         return ret;
1326     }
1327     //---------------------------------------------------------------------
_updateAllRenderTargets(FrameEvent & evt)1328     bool Root::_updateAllRenderTargets(FrameEvent& evt)
1329     {
1330         // update all targets but don't swap buffers
1331         mActiveRenderer->_updateAllRenderTargets(false);
1332         // give client app opportunity to use queued GPU time
1333         bool ret = _fireFrameRenderingQueued(evt);
1334         // block for final swap
1335         mActiveRenderer->_swapAllRenderTargetBuffers();
1336 
1337         // This belongs here, as all render targets must be updated before events are
1338         // triggered, otherwise targets could be mismatched.  This could produce artifacts,
1339         // for instance, with shadows.
1340         SceneManagerEnumerator::Instances::const_iterator it, end = getSceneManagers().end();
1341         for (it = getSceneManagers().begin(); it != end; ++it)
1342             it->second->_handleLodEvents();
1343 
1344         return ret;
1345     }
1346     //-----------------------------------------------------------------------
clearEventTimes(void)1347     void Root::clearEventTimes(void)
1348     {
1349         // Clear event times
1350         for(int i=0; i<FETT_COUNT; ++i)
1351             mEventTimes[i].clear();
1352     }
1353     //---------------------------------------------------------------------
addMovableObjectFactory(MovableObjectFactory * fact,bool overrideExisting)1354     void Root::addMovableObjectFactory(MovableObjectFactory* fact,
1355         bool overrideExisting)
1356     {
1357         MovableObjectFactoryMap::iterator facti = mMovableObjectFactoryMap.find(
1358             fact->getType());
1359         if (!overrideExisting && facti != mMovableObjectFactoryMap.end())
1360         {
1361             OGRE_EXCEPT(Exception::ERR_DUPLICATE_ITEM,
1362                 "A factory of type '" + fact->getType() + "' already exists.",
1363                 "Root::addMovableObjectFactory");
1364         }
1365 
1366         if (fact->requestTypeFlags())
1367         {
1368             if (facti != mMovableObjectFactoryMap.end() && facti->second->requestTypeFlags())
1369             {
1370                 // Copy type flags from the factory we're replacing
1371                 fact->_notifyTypeFlags(facti->second->getTypeFlags());
1372             }
1373             else
1374             {
1375                 // Allocate new
1376                 fact->_notifyTypeFlags(_allocateNextMovableObjectTypeFlag());
1377             }
1378         }
1379 
1380         // Save
1381         mMovableObjectFactoryMap[fact->getType()] = fact;
1382 
1383         LogManager::getSingleton().logMessage("MovableObjectFactory for type '" +
1384             fact->getType() + "' registered.");
1385 
1386     }
1387     //---------------------------------------------------------------------
hasMovableObjectFactory(const String & typeName) const1388     bool Root::hasMovableObjectFactory(const String& typeName) const
1389     {
1390         return !(mMovableObjectFactoryMap.find(typeName) == mMovableObjectFactoryMap.end());
1391     }
1392     //---------------------------------------------------------------------
getMovableObjectFactory(const String & typeName)1393     MovableObjectFactory* Root::getMovableObjectFactory(const String& typeName)
1394     {
1395         MovableObjectFactoryMap::iterator i =
1396             mMovableObjectFactoryMap.find(typeName);
1397         if (i == mMovableObjectFactoryMap.end())
1398         {
1399             OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND,
1400                 "MovableObjectFactory of type " + typeName + " does not exist",
1401                 "Root::getMovableObjectFactory");
1402         }
1403         return i->second;
1404     }
1405     //---------------------------------------------------------------------
_allocateNextMovableObjectTypeFlag(void)1406     uint32 Root::_allocateNextMovableObjectTypeFlag(void)
1407     {
1408         if (mNextMovableObjectTypeFlag == SceneManager::USER_TYPE_MASK_LIMIT)
1409         {
1410             OGRE_EXCEPT(Exception::ERR_DUPLICATE_ITEM,
1411                 "Cannot allocate a type flag since "
1412                 "all the available flags have been used.",
1413                 "Root::_allocateNextMovableObjectTypeFlag");
1414 
1415         }
1416         uint32 ret = mNextMovableObjectTypeFlag;
1417         mNextMovableObjectTypeFlag <<= 1;
1418         return ret;
1419 
1420     }
1421     //---------------------------------------------------------------------
removeMovableObjectFactory(MovableObjectFactory * fact)1422     void Root::removeMovableObjectFactory(MovableObjectFactory* fact)
1423     {
1424         MovableObjectFactoryMap::iterator i = mMovableObjectFactoryMap.find(
1425             fact->getType());
1426         if (i != mMovableObjectFactoryMap.end())
1427         {
1428             mMovableObjectFactoryMap.erase(i);
1429         }
1430 
1431     }
1432     //---------------------------------------------------------------------
1433     Root::MovableObjectFactoryIterator
getMovableObjectFactoryIterator(void) const1434     Root::getMovableObjectFactoryIterator(void) const
1435     {
1436         return MovableObjectFactoryIterator(mMovableObjectFactoryMap.begin(),
1437             mMovableObjectFactoryMap.end());
1438 
1439     }
1440     //---------------------------------------------------------------------
createRenderQueueInvocationSequence(const String & name)1441     RenderQueueInvocationSequence* Root::createRenderQueueInvocationSequence(
1442         const String& name)
1443     {
1444         RenderQueueInvocationSequenceMap::iterator i =
1445             mRQSequenceMap.find(name);
1446         if (i != mRQSequenceMap.end())
1447         {
1448             OGRE_EXCEPT(Exception::ERR_DUPLICATE_ITEM,
1449                 "RenderQueueInvocationSequence with the name " + name +
1450                     " already exists.",
1451                 "Root::createRenderQueueInvocationSequence");
1452         }
1453         RenderQueueInvocationSequence* ret = OGRE_NEW RenderQueueInvocationSequence(name);
1454         mRQSequenceMap[name] = ret;
1455         return ret;
1456     }
1457     //---------------------------------------------------------------------
getRenderQueueInvocationSequence(const String & name)1458     RenderQueueInvocationSequence* Root::getRenderQueueInvocationSequence(
1459         const String& name)
1460     {
1461         RenderQueueInvocationSequenceMap::iterator i =
1462             mRQSequenceMap.find(name);
1463         if (i == mRQSequenceMap.end())
1464         {
1465             OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND,
1466                 "RenderQueueInvocationSequence with the name " + name +
1467                 " not found.",
1468                 "Root::getRenderQueueInvocationSequence");
1469         }
1470         return i->second;
1471     }
1472     //---------------------------------------------------------------------
destroyRenderQueueInvocationSequence(const String & name)1473     void Root::destroyRenderQueueInvocationSequence(
1474         const String& name)
1475     {
1476         RenderQueueInvocationSequenceMap::iterator i =
1477             mRQSequenceMap.find(name);
1478         if (i != mRQSequenceMap.end())
1479         {
1480             OGRE_DELETE i->second;
1481             mRQSequenceMap.erase(i);
1482         }
1483     }
1484     //---------------------------------------------------------------------
destroyAllRenderQueueInvocationSequences(void)1485     void Root::destroyAllRenderQueueInvocationSequences(void)
1486     {
1487         for (RenderQueueInvocationSequenceMap::iterator i = mRQSequenceMap.begin();
1488             i != mRQSequenceMap.end(); ++i)
1489         {
1490             OGRE_DELETE i->second;
1491         }
1492         mRQSequenceMap.clear();
1493     }
1494 
1495     //---------------------------------------------------------------------
getDisplayMonitorCount() const1496     unsigned int Root::getDisplayMonitorCount() const
1497     {
1498         if (!mActiveRenderer)
1499         {
1500             OGRE_EXCEPT(Exception::ERR_INVALID_STATE,
1501                 "Cannot get display monitor count "
1502                 "No render system has been selected.", "Root::getDisplayMonitorCount");
1503         }
1504 
1505         return mActiveRenderer->getDisplayMonitorCount();
1506 
1507     }
1508     //---------------------------------------------------------------------
setWorkQueue(WorkQueue * queue)1509     void Root::setWorkQueue(WorkQueue* queue)
1510     {
1511         if (mWorkQueue.get() != queue)
1512         {
1513             mWorkQueue.reset(queue);
1514             if (mIsInitialised)
1515                 mWorkQueue->startup();
1516 
1517         }
1518     }
1519 
1520 
1521 
1522 }
1523