Coverage Report

Created: 2025-12-25 06:30

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ogre/OgreMain/src/OgreRoot.cpp
Line
Count
Source
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 <memory>
30
31
#include "OgreStableHeaders.h"
32
33
#include "OgreRenderWindow.h"
34
#include "OgreControllerManager.h"
35
#include "OgreDynLibManager.h"
36
#include "OgreDynLib.h"
37
#include "OgreConfigFile.h"
38
#include "OgreRenderSystemCapabilitiesManager.h"
39
#include "OgreSkeletonManager.h"
40
#include "OgreConfigDialog.h"
41
#include "OgrePlugin.h"
42
#include "OgreShadowVolumeExtrudeProgram.h"
43
#include "OgreResourceBackgroundQueue.h"
44
#include "OgreBillboardSet.h"
45
#include "OgreBillboardChain.h"
46
#include "OgreRibbonTrail.h"
47
#include "OgreConvexBody.h"
48
#include "OgreTimer.h"
49
#include "OgreFrameListener.h"
50
#include "OgreLodStrategyManager.h"
51
#include "OgreFileSystemLayer.h"
52
#include "OgreStaticGeometry.h"
53
#include "OgreSceneManagerEnumerator.h"
54
55
#if OGRE_NO_DDS_CODEC == 0
56
#include "OgreDDSCodec.h"
57
#endif
58
59
#include "OgreHardwareBufferManager.h"
60
#include "OgreGpuProgramManager.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;
85
    Root* Root::getSingletonPtr(void)
86
0
    {
87
0
        return msSingleton;
88
0
    }
89
    Root& Root::getSingleton(void)
90
0
    {
91
0
        assert( msSingleton );  return ( *msSingleton );
92
0
    }
93
94
    typedef void (*DLL_START_PLUGIN)(void);
95
    typedef void (*DLL_STOP_PLUGIN)(void);
96
97
    //-----------------------------------------------------------------------
98
    Root::Root(const String& pluginFileName, const String& configFileName,
99
        const String& logFileName)
100
0
      : mQueuedEnd(false)
101
0
      , mCurrentSceneManager(NULL)
102
0
      , mNextFrame(0)
103
0
      , mFrameSmoothingTime(0.0f)
104
0
      , mRemoveQueueStructuresOnClear(false)
105
0
      , mDefaultMinPixelSize(0)
106
0
      , mNextMovableObjectTypeFlag(1)
107
0
      , mIsInitialised(false)
108
0
      , mIsBlendIndicesGpuRedundant(true)
109
0
      , mIsBlendWeightsGpuRedundant(true)
110
0
    {
111
        // superclass will do singleton checking
112
113
        // Init
114
0
        mActiveRenderer = 0;
115
0
        mVersion = StringConverter::toString(OGRE_VERSION_MAJOR) + "." +
116
0
            StringConverter::toString(OGRE_VERSION_MINOR) + "." +
117
0
            StringConverter::toString(OGRE_VERSION_PATCH) +
118
0
            OGRE_VERSION_SUFFIX + " " +
119
0
            "(" + OGRE_VERSION_NAME + ")";
120
0
        mConfigFileName = configFileName;
121
122
        // Create log manager and default log file if there is no log manager yet
123
0
        if(!LogManager::getSingletonPtr())
124
0
        {
125
0
            mLogManager = std::make_unique<LogManager>();
126
127
#if OGRE_PLATFORM == OGRE_PLATFORM_EMSCRIPTEN
128
            // suppress writing log to Emscripten virtual FS, improves performance
129
            mLogManager->createLog(logFileName, true, true, true);
130
#else
131
0
            mLogManager->createLog(logFileName, true, true);
132
0
#endif
133
134
#if OGRE_PLATFORM == OGRE_PLATFORM_ANDROID
135
            mAndroidLogger.reset(new AndroidLogListener());
136
            mLogManager->getDefaultLog()->addListener(mAndroidLogger.get());
137
#endif
138
0
        }
139
140
0
        mDynLibManager = std::make_unique<DynLibManager>();
141
0
        mArchiveManager = std::make_unique<ArchiveManager>();
142
0
        mResourceGroupManager = std::make_unique<ResourceGroupManager>();
143
144
        // WorkQueue (note: users can replace this if they want)
145
0
        DefaultWorkQueue* defaultQ = OGRE_NEW DefaultWorkQueue("Root");
146
        // match threads to hardware
147
0
        int threadCount = OGRE_THREAD_HARDWARE_CONCURRENCY;
148
        // but clamp it at 2 by default - we dont scale much beyond that currently
149
        // yet it helps on android where it needlessly burns CPU
150
0
        threadCount = Math::Clamp(threadCount, 1, 2);
151
0
        defaultQ->setWorkerThreadCount(threadCount);
152
153
        // only allow workers to access rendersystem if threadsupport is 1
154
0
        defaultQ->setWorkersCanAccessRenderSystem(OGRE_THREAD_SUPPORT == 1);
155
0
        mWorkQueue.reset(defaultQ);
156
157
        // ResourceBackgroundQueue
158
0
        mResourceBackgroundQueue = std::make_unique<ResourceBackgroundQueue>();
159
160
        // Create SceneManager enumerator (note - will be managed by singleton)
161
0
        mSceneManagerEnum = std::make_unique<SceneManagerEnumerator>();
162
0
        mShadowTextureManager = std::make_unique<ShadowTextureManager>();
163
0
        mRenderSystemCapabilitiesManager = std::make_unique<RenderSystemCapabilitiesManager>();
164
0
        mMaterialManager = std::make_unique<MaterialManager>();
165
0
        mMeshManager = std::make_unique<MeshManager>();
166
0
        mSkeletonManager = std::make_unique<SkeletonManager>();
167
0
        mParticleManager = std::make_unique<ParticleSystemManager>();
168
0
        mTimer = std::make_unique<Timer>();
169
0
        mLodStrategyManager = std::make_unique<LodStrategyManager>();
170
171
#if OGRE_PROFILING
172
        // Profiler
173
        mProfiler.reset(new Profiler());
174
        Profiler::getSingleton().setTimer(mTimer.get());
175
#endif
176
177
178
0
        mFileSystemArchiveFactory = std::make_unique<FileSystemArchiveFactory>();
179
0
        ArchiveManager::getSingleton().addArchiveFactory( mFileSystemArchiveFactory.get() );
180
0
#   if OGRE_NO_ZIP_ARCHIVE == 0
181
0
        mZipArchiveFactory = std::make_unique<ZipArchiveFactory>();
182
0
        ArchiveManager::getSingleton().addArchiveFactory( mZipArchiveFactory.get() );
183
0
        mEmbeddedZipArchiveFactory = std::make_unique<EmbeddedZipArchiveFactory>();
184
0
        ArchiveManager::getSingleton().addArchiveFactory( mEmbeddedZipArchiveFactory.get() );
185
0
#   endif
186
187
0
#if OGRE_NO_DDS_CODEC == 0
188
        // Register image codecs
189
0
        DDSCodec::startup();
190
0
#endif
191
#if OGRE_NO_PVRTC_CODEC == 0
192
        PVRTCCodec::startup();
193
#endif
194
0
#if OGRE_NO_ETC_CODEC == 0
195
0
        ETCCodec::startup();
196
0
#endif
197
0
#if OGRE_NO_ASTC_CODEC == 0
198
0
        ASTCCodec::startup();
199
0
#endif
200
201
0
        mGpuProgramManager = std::make_unique<GpuProgramManager>();
202
0
        mExternalTextureSourceManager = std::make_unique<ExternalTextureSourceManager>();
203
0
        mCompositorManager = std::make_unique<CompositorManager>();
204
0
        mCompilerManager = std::make_unique<ScriptCompilerManager>();
205
206
        // Auto window
207
0
        mAutoWindow = 0;
208
209
        // instantiate and register base movable factories
210
0
        mEntityFactory = std::make_unique<EntityFactory>();
211
0
        addMovableObjectFactory(mEntityFactory.get());
212
0
        mLightFactory = std::make_unique<LightFactory>();
213
0
        addMovableObjectFactory(mLightFactory.get());
214
0
        mBillboardSetFactory = std::make_unique<BillboardSetFactory>();
215
0
        addMovableObjectFactory(mBillboardSetFactory.get());
216
0
        mManualObjectFactory = std::make_unique<ManualObjectFactory>();
217
0
        addMovableObjectFactory(mManualObjectFactory.get());
218
0
        mBillboardChainFactory = std::make_unique<BillboardChainFactory>();
219
0
        addMovableObjectFactory(mBillboardChainFactory.get());
220
0
        mRibbonTrailFactory = std::make_unique<RibbonTrailFactory>();
221
0
        addMovableObjectFactory(mRibbonTrailFactory.get());
222
0
        mStaticGeometryFactory = std::make_unique<StaticGeometryFactory>();
223
0
        addMovableObjectFactory(mStaticGeometryFactory.get());
224
0
        mRectangle2DFactory = std::make_unique<Rectangle2DFactory>();
225
0
        addMovableObjectFactory(mRectangle2DFactory.get());
226
227
        // Load plugins
228
0
        if (!pluginFileName.empty())
229
0
            loadPlugins(pluginFileName);
230
231
0
        LogManager::getSingleton().logMessage("*-*-* OGRE Initialising");
232
0
        LogManager::getSingleton().logMessage("*-*-* Version " + mVersion);
233
234
        // Can't create managers until initialised
235
0
        mControllerManager = 0;
236
237
0
        mFirstTimePostWindowInit = false;
238
0
    }
239
240
    //-----------------------------------------------------------------------
241
    Root::~Root()
242
0
    {
243
0
        shutdown();
244
245
0
#if OGRE_NO_DDS_CODEC == 0
246
0
        DDSCodec::shutdown();
247
0
#endif
248
#if OGRE_NO_PVRTC_CODEC == 0
249
        PVRTCCodec::shutdown();
250
#endif
251
0
#if OGRE_NO_ETC_CODEC == 0
252
0
        ETCCodec::shutdown();
253
0
#endif
254
0
#if OGRE_NO_ASTC_CODEC == 0
255
0
        ASTCCodec::shutdown();
256
0
#endif
257
0
    mCompositorManager.reset(); // needs rendersystem
258
0
        mParticleManager.reset(); // may use plugins
259
0
        mMaterialManager.reset(); // may use GPU program manager
260
0
        mGpuProgramManager.reset(); // may use plugins
261
0
        unloadPlugins();
262
263
0
        mAutoWindow = 0;
264
265
0
        StringInterface::cleanupDictionary();
266
267
#if OGRE_PLATFORM == OGRE_PLATFORM_ANDROID
268
  if(mAndroidLogger)
269
  {
270
            mLogManager->getDefaultLog()->removeListener(mAndroidLogger.get());
271
  }
272
#endif
273
0
    }
274
275
    //-----------------------------------------------------------------------
276
    void Root::saveConfig(void)
277
0
    {
278
#if OGRE_PLATFORM == OGRE_PLATFORM_EMSCRIPTEN
279
        OGRE_EXCEPT(Exception::ERR_CANNOT_WRITE_TO_FILE, "saveConfig is not supported",
280
            "Root::saveConfig");
281
#endif
282
#if OGRE_PLATFORM == OGRE_PLATFORM_APPLE_IOS
283
        // Check the Documents directory within the application sandbox
284
        Ogre::String outBaseName, extension, configFileName;
285
        Ogre::StringUtil::splitFilename(mConfigFileName, outBaseName, extension);
286
        configFileName = iOSDocumentsDirectory() + "/" + outBaseName;
287
    std::ofstream of(configFileName.c_str());
288
        if (of.is_open())
289
            mConfigFileName = configFileName;
290
        else
291
            mConfigFileName.clear();
292
#else
293
0
        if (mConfigFileName.empty())
294
0
            return;
295
296
0
        std::ofstream of(mConfigFileName.c_str());
297
0
#endif
298
0
        if (!of)
299
0
            OGRE_EXCEPT(Exception::ERR_CANNOT_WRITE_TO_FILE, "Cannot create settings file.",
300
0
            "Root::saveConfig");
301
302
0
        if (mActiveRenderer)
303
0
        {
304
0
            of << "Render System=" << mActiveRenderer->getName() << std::endl;
305
0
        }
306
0
        else
307
0
        {
308
0
            of << "Render System=" << std::endl;
309
0
        }
310
311
0
        for (const auto& r : getAvailableRenderers())
312
0
        {
313
0
            of << std::endl;
314
0
            of << "[" << r->getName() << "]" << std::endl;
315
0
            for (const auto& o : r->getConfigOptions()) {
316
0
                of << o.first << "=" << o.second.currentValue << std::endl;
317
0
            }
318
0
        }
319
320
0
        of.close();
321
322
0
    }
323
    //-----------------------------------------------------------------------
324
    bool Root::restoreConfig(void)
325
0
    {
326
#if OGRE_PLATFORM == OGRE_PLATFORM_APPLE_IOS
327
        // Read the config from Documents first(user config) if it exists on iOS.
328
        // If it doesn't exist or is invalid then use mConfigFileName
329
330
        Ogre::String outBaseName, extension, configFileName;
331
        Ogre::StringUtil::splitFilename(mConfigFileName, outBaseName, extension);
332
        configFileName = iOSDocumentsDirectory() + "/" + outBaseName;
333
334
        std::ifstream fp;
335
        fp.open(configFileName.c_str(), std::ios::in);
336
        if(fp.is_open())
337
        {
338
            // A config file exists in the users Documents dir, we'll use it
339
            mConfigFileName = configFileName;
340
        }
341
        else
342
        {
343
            std::ifstream configFp;
344
345
            // This might be the first run because there is no config file in the
346
            // Documents directory.  It could also mean that a config file isn't being used at all
347
348
            // Try the path passed into initialise
349
            configFp.open(mConfigFileName.c_str(), std::ios::in);
350
351
            // If we can't open this file then we have no default config file to work with
352
            // Use the documents dir then.
353
            if(!configFp.is_open())
354
            {
355
                // Check to see if one was included in the app bundle
356
                mConfigFileName = macBundlePath() + "/ogre.cfg";
357
358
                configFp.open(mConfigFileName.c_str(), std::ios::in);
359
360
                // If we can't open this file then we have no default config file to work with
361
                // Use the Documents dir then.
362
                if(!configFp.is_open())
363
                    mConfigFileName = configFileName;
364
            }
365
366
            configFp.close();
367
        }
368
369
        fp.close();
370
#endif
371
372
0
        if (mConfigFileName.empty ())
373
0
            return true;
374
375
        // Restores configuration from saved state
376
        // Returns true if a valid saved configuration is
377
        //   available, and false if no saved config is
378
        //   stored, or if there has been a problem
379
0
        ConfigFile cfg;
380
381
0
        try {
382
            // Don't trim whitespace
383
0
            cfg.load(mConfigFileName, "\t:=", false);
384
0
        }
385
0
        catch (FileNotFoundException&)
386
0
        {
387
0
            return false;
388
0
        }
389
390
0
        bool optionError = false;
391
0
        for(auto& seci : cfg.getSettingsBySection()) {
392
0
            const ConfigFile::SettingsMultiMap& settings = seci.second;
393
0
            const String& renderSystem = seci.first;
394
395
0
            RenderSystem* rs = getRenderSystemByName(renderSystem);
396
0
            if (!rs)
397
0
            {
398
                // Unrecognised render system
399
0
                continue;
400
0
            }
401
402
0
            for (const auto& p : settings)
403
0
            {
404
0
                try
405
0
                {
406
0
                    rs->setConfigOption(p.first, p.second);
407
0
                }
408
0
                catch(const InvalidParametersException& e)
409
0
                {
410
0
                    LogManager::getSingleton().logError(e.getDescription());
411
0
                    optionError = true;
412
0
                    continue;
413
0
                }
414
0
            }
415
0
        }
416
417
0
        RenderSystem* rs = getRenderSystemByName(cfg.getSetting("Render System"));
418
0
        if (!rs)
419
0
        {
420
            // Unrecognised render system
421
0
            return false;
422
0
        }
423
424
0
        String err = rs->validateConfigOptions();
425
0
        if (err.length() > 0)
426
0
            return false;
427
428
0
        setRenderSystem(rs);
429
430
        // Successful load
431
0
        return !optionError;
432
0
    }
433
434
    //-----------------------------------------------------------------------
435
0
    bool Root::showConfigDialog(ConfigDialog* dialog) {
436
0
        if(dialog) {
437
0
            if(!mActiveRenderer)
438
0
                restoreConfig();
439
440
0
            if (dialog->display()) {
441
0
                saveConfig();
442
0
                return true;
443
0
            }
444
445
0
            return false;
446
0
        }
447
448
        // just select the first available render system
449
0
        if (!mRenderers.empty())
450
0
        {
451
0
            setRenderSystem(mRenderers.front());
452
0
            return true;
453
0
        }
454
455
0
        return false;
456
0
    }
457
458
    //-----------------------------------------------------------------------
459
    const RenderSystemList& Root::getAvailableRenderers(void)
460
0
    {
461
        // Returns a vector of renders
462
463
0
        return mRenderers;
464
465
0
    }
466
467
    //-----------------------------------------------------------------------
468
    RenderSystem* Root::getRenderSystemByName(const String& name)
469
0
    {
470
0
        if (name.empty())
471
0
        {
472
            // No render system
473
0
            return NULL;
474
0
        }
475
476
0
        for (auto *rs : getAvailableRenderers())
477
0
        {
478
0
            if (rs->getName() == name)
479
0
                return rs;
480
0
        }
481
482
        // Unrecognised render system
483
0
        return NULL;
484
0
    }
485
486
    //-----------------------------------------------------------------------
487
    void Root::setRenderSystem(RenderSystem* system)
488
0
    {
489
        // Sets the active rendering system
490
        // Can be called direct or will be called by
491
        //   standard config dialog
492
493
        // Is there already an active renderer?
494
        // If so, disable it and init the new one
495
0
        if( mActiveRenderer && mActiveRenderer != system )
496
0
        {
497
0
            mActiveRenderer->shutdown();
498
0
        }
499
500
0
        mActiveRenderer = system;
501
        // Tell scene managers
502
0
        if(mSceneManagerEnum)
503
0
            mSceneManagerEnum->setRenderSystem(system);
504
505
0
        if(RenderSystem::Listener* ls = RenderSystem::getSharedListener())
506
0
            ls->eventOccurred("RenderSystemChanged");
507
0
    }
508
    //-----------------------------------------------------------------------
509
    void Root::addRenderSystem(RenderSystem *newRend)
510
0
    {
511
0
        mRenderers.push_back(newRend);
512
0
    }
513
    //-----------------------------------------------------------------------
514
    RenderSystem* Root::getRenderSystem(void)
515
0
    {
516
        // Gets the currently active renderer
517
0
        return mActiveRenderer;
518
519
0
    }
520
521
    //-----------------------------------------------------------------------
522
    RenderWindow* Root::initialise(bool autoCreateWindow, const String& windowTitle)
523
0
    {
524
0
        OgreAssert(mActiveRenderer, "Cannot initialise");
525
526
0
        if (!mControllerManager)
527
0
            mControllerManager = std::make_unique<ControllerManager>();
528
529
0
        PlatformInformation::log(LogManager::getSingleton().getDefaultLog());
530
0
        mActiveRenderer->_initialise();
531
532
        // Initialise timer
533
0
        mTimer->reset();
534
535
        // Init pools
536
0
        ConvexBody::_initialisePool();
537
538
0
        mIsInitialised = true;
539
540
0
        if (autoCreateWindow)
541
0
        {
542
0
            LogManager::getSingleton().logWarning(
543
0
                "Root::initialise: autoCreateWindow is deprecated, use createRenderWindow instead");
544
0
            auto desc = mActiveRenderer->getRenderWindowDescription();
545
0
            desc.name = windowTitle;
546
0
            mAutoWindow = createRenderWindow(desc);
547
0
        }
548
549
0
        return mAutoWindow;
550
551
0
    }
552
    //-----------------------------------------------------------------------
553
    void Root::useCustomRenderSystemCapabilities(RenderSystemCapabilities* capabilities)
554
0
    {
555
0
        mActiveRenderer->useCustomRenderSystemCapabilities(capabilities);
556
0
    }
557
    //-----------------------------------------------------------------------
558
    void Root::addSceneManagerFactory(SceneManagerFactory* fact)
559
0
    {
560
0
        mSceneManagerEnum->addFactory(fact);
561
0
    }
562
    //-----------------------------------------------------------------------
563
    void Root::removeSceneManagerFactory(SceneManagerFactory* fact)
564
0
    {
565
0
        mSceneManagerEnum->removeFactory(fact);
566
0
    }
567
    //-----------------------------------------------------------------------
568
0
    const StringVector& Root::getSceneManagerTypes(void) const { return mSceneManagerEnum->getMetaData(); }
569
    //-----------------------------------------------------------------------
570
    SceneManager* Root::createSceneManager(const String& typeName, const String& instanceName)
571
0
    {
572
0
        return mSceneManagerEnum->createSceneManager(typeName, instanceName);
573
0
    }
574
    //-----------------------------------------------------------------------
575
    void Root::destroySceneManager(SceneManager* sm)
576
0
    {
577
0
        mSceneManagerEnum->destroySceneManager(sm);
578
0
    }
579
    //-----------------------------------------------------------------------
580
    SceneManager* Root::getSceneManager(const String& instanceName) const
581
0
    {
582
0
        return mSceneManagerEnum->getSceneManager(instanceName);
583
0
    }
584
    //---------------------------------------------------------------------
585
    bool Root::hasSceneManager(const String& instanceName) const
586
0
    {
587
0
        return mSceneManagerEnum->hasSceneManager(instanceName);
588
0
    }
589
    //-----------------------------------------------------------------------
590
0
    const SceneManagerInstanceMap& Root::getSceneManagers(void) const { return mSceneManagerEnum->getSceneManagers(); }
591
    //-----------------------------------------------------------------------
592
    TextureManager* Root::getTextureManager(void)
593
0
    {
594
0
        return &TextureManager::getSingleton();
595
0
    }
596
    //-----------------------------------------------------------------------
597
    MeshManager* Root::getMeshManager(void)
598
0
    {
599
0
        return &MeshManager::getSingleton();
600
0
    }
601
    //-----------------------------------------------------------------------
602
    void Root::addFrameListener(FrameListener* newListener)
603
0
    {
604
0
        mRemovedFrameListeners.erase(newListener);
605
0
        mAddedFrameListeners.insert(newListener);
606
0
    }
607
    //-----------------------------------------------------------------------
608
    void Root::removeFrameListener(FrameListener* oldListener)
609
0
    {
610
0
        mAddedFrameListeners.erase(oldListener);
611
0
        mRemovedFrameListeners.insert(oldListener);
612
0
    }
613
    //-----------------------------------------------------------------------
614
    void Root::_syncAddedRemovedFrameListeners()
615
0
    {
616
0
        for (auto& l : mRemovedFrameListeners)
617
0
            mFrameListeners.erase(l);
618
0
        mRemovedFrameListeners.clear();
619
620
0
        for (auto& l : mAddedFrameListeners)
621
0
            mFrameListeners.insert(l);
622
0
        mAddedFrameListeners.clear();
623
0
    }
624
    //-----------------------------------------------------------------------
625
    bool Root::_fireFrameStarted(FrameEvent& evt)
626
0
    {
627
0
        OgreProfileBeginGroup("Frame", OGREPROF_GENERAL);
628
0
        _syncAddedRemovedFrameListeners();
629
630
        // Tell all listeners
631
0
        for (auto *l : mFrameListeners)
632
0
        {
633
0
            if(mRemovedFrameListeners.find(l) != mRemovedFrameListeners.end())
634
0
                continue;
635
636
0
            if (!l->frameStarted(evt))
637
0
                return false;
638
0
        }
639
640
0
        return true;
641
0
    }
642
    //-----------------------------------------------------------------------
643
    bool Root::_fireFrameRenderingQueued(FrameEvent& evt)
644
0
    {
645
        // Increment next frame number
646
0
        ++mNextFrame;
647
0
        _syncAddedRemovedFrameListeners();
648
649
        // Tell all listeners
650
0
        for (auto *l : mFrameListeners)
651
0
        {
652
0
            if(mRemovedFrameListeners.find(l) != mRemovedFrameListeners.end())
653
0
                continue;
654
655
0
            if (!l->frameRenderingQueued(evt))
656
0
                return false;
657
0
        }
658
659
0
        return true;
660
0
    }
661
    //-----------------------------------------------------------------------
662
    bool Root::_fireFrameEnded(FrameEvent& evt)
663
0
    {
664
0
        _syncAddedRemovedFrameListeners();
665
666
        // Tell all listeners
667
0
        bool ret = true;
668
0
        for (auto *l : mFrameListeners)
669
0
        {
670
0
            if(mRemovedFrameListeners.find(l) != mRemovedFrameListeners.end())
671
0
                continue;
672
673
0
            if (!l->frameEnded(evt))
674
0
            {
675
0
                ret = false;
676
0
                break;
677
0
            }
678
0
        }
679
680
        // Tell buffer manager to free temp buffers used this frame
681
0
        if (HardwareBufferManager::getSingletonPtr())
682
0
            HardwareBufferManager::getSingleton()._releaseBufferCopies();
683
684
        // Tell the queue to process responses
685
0
        mWorkQueue->processMainThreadTasks();
686
687
0
        OgreProfileEndGroup("Frame", OGREPROF_GENERAL);
688
689
0
        return ret;
690
0
    }
691
    //-----------------------------------------------------------------------
692
    bool Root::_fireFrameStarted()
693
0
    {
694
0
        FrameEvent evt;
695
0
        populateFrameEvent(FETT_STARTED, evt);
696
697
0
        return _fireFrameStarted(evt);
698
0
    }
699
    //-----------------------------------------------------------------------
700
    bool Root::_fireFrameRenderingQueued()
701
0
    {
702
0
        FrameEvent evt;
703
0
        populateFrameEvent(FETT_QUEUED, evt);
704
705
0
        return _fireFrameRenderingQueued(evt);
706
0
    }
707
    //-----------------------------------------------------------------------
708
    bool Root::_fireFrameEnded()
709
0
    {
710
0
        FrameEvent evt;
711
0
        populateFrameEvent(FETT_ENDED, evt);
712
0
        return _fireFrameEnded(evt);
713
0
    }
714
    //---------------------------------------------------------------------
715
    void Root::populateFrameEvent(FrameEventTimeType type, FrameEvent& evtToUpdate)
716
0
    {
717
0
        unsigned long now = mTimer->getMilliseconds();
718
0
        evtToUpdate.timeSinceLastEvent = calculateEventTime(now, FETT_ANY);
719
0
        evtToUpdate.timeSinceLastFrame = calculateEventTime(now, type);
720
0
    }
721
    //-----------------------------------------------------------------------
722
    Real Root::calculateEventTime(unsigned long now, FrameEventTimeType type)
723
0
    {
724
        // Calculate the average time passed between events of the given type
725
        // during the last mFrameSmoothingTime seconds.
726
727
0
        EventTimesQueue& times = mEventTimes[type];
728
0
        times.push_back(now);
729
730
0
        if(times.size() == 1)
731
0
            return 0;
732
733
        // Times up to mFrameSmoothingTime seconds old should be kept
734
0
        unsigned long discardThreshold =
735
0
            static_cast<unsigned long>(mFrameSmoothingTime * 1000.0f);
736
737
        // Find the oldest time to keep
738
0
        EventTimesQueue::iterator it = times.begin(),
739
0
            end = times.end()-2; // We need at least two times
740
0
        while(it != end)
741
0
        {
742
0
            if (now - *it > discardThreshold)
743
0
                ++it;
744
0
            else
745
0
                break;
746
0
        }
747
748
        // Remove old times
749
0
        times.erase(times.begin(), it);
750
751
0
        return Real(times.back() - times.front()) / ((times.size()-1) * 1000);
752
0
    }
753
    //-----------------------------------------------------------------------
754
    void Root::queueEndRendering(bool state /* = true */)
755
0
    {
756
0
        mQueuedEnd = state;
757
0
    }
758
    //-----------------------------------------------------------------------
759
    bool Root::endRenderingQueued(void)
760
0
    {
761
0
        return mQueuedEnd;
762
0
    }
763
    //-----------------------------------------------------------------------
764
    void Root::startRendering(void)
765
0
    {
766
0
        OgreAssert(mActiveRenderer, "no RenderSystem");
767
768
0
        mActiveRenderer->_initRenderTargets();
769
770
        // Clear event times
771
0
        clearEventTimes();
772
773
        // Infinite loop, until broken out of by frame listeners
774
        // or break out by calling queueEndRendering()
775
0
        mQueuedEnd = false;
776
777
0
        while( !mQueuedEnd )
778
0
        {
779
0
            if (!renderOneFrame())
780
0
                break;
781
0
        }
782
0
    }
783
    //-----------------------------------------------------------------------
784
    bool Root::renderOneFrame(void)
785
0
    {
786
0
        if(!_fireFrameStarted())
787
0
            return false;
788
789
0
        if (!_updateAllRenderTargets())
790
0
            return false;
791
792
0
        return _fireFrameEnded();
793
0
    }
794
    //---------------------------------------------------------------------
795
    bool Root::renderOneFrame(Real timeSinceLastFrame)
796
0
    {
797
0
        FrameEvent evt;
798
0
        evt.timeSinceLastFrame = timeSinceLastFrame;
799
800
0
        unsigned long now = mTimer->getMilliseconds();
801
0
        evt.timeSinceLastEvent = calculateEventTime(now, FETT_ANY);
802
803
0
        if(!_fireFrameStarted(evt))
804
0
            return false;
805
806
0
        if (!_updateAllRenderTargets(evt))
807
0
            return false;
808
809
0
        now = mTimer->getMilliseconds();
810
0
        evt.timeSinceLastEvent = calculateEventTime(now, FETT_ANY);
811
812
0
        return _fireFrameEnded(evt);
813
0
    }
814
    //-----------------------------------------------------------------------
815
    void Root::shutdown(void)
816
0
    {
817
0
        if(mActiveRenderer)
818
0
            mActiveRenderer->_setViewport(NULL);
819
820
        // Since background thread might be access resources,
821
        // ensure shutdown before destroying resource manager.
822
0
        mWorkQueue->shutdown();
823
824
0
        if(mSceneManagerEnum)
825
0
            mSceneManagerEnum->shutdownAll();
826
0
        if(mFirstTimePostWindowInit)
827
0
        {
828
0
            shutdownPlugins();
829
0
            mParticleManager->removeAllTemplates(true);
830
0
            mFirstTimePostWindowInit = false;
831
0
        }
832
0
        mSceneManagerEnum.reset();
833
0
        mShadowTextureManager.reset();
834
835
0
        ShadowVolumeExtrudeProgram::shutdown();
836
0
        ResourceGroupManager::getSingleton().shutdownAll();
837
838
        // Destroy pools
839
0
        ConvexBody::_destroyPool();
840
841
842
0
        mIsInitialised = false;
843
844
0
        LogManager::getSingleton().logMessage("*-*-* OGRE Shutdown");
845
0
    }
846
    //-----------------------------------------------------------------------
847
    void Root::loadPlugins( const String& pluginsfile )
848
0
    {
849
0
        StringVector pluginList;
850
0
        String pluginDir;
851
0
        ConfigFile cfg;
852
853
0
        try {
854
0
            cfg.load( pluginsfile );
855
0
        }
856
0
        catch (Exception& e)
857
0
        {
858
0
            LogManager::getSingleton().logError(e.getDescription()+" - skipping automatic plugin loading");
859
0
            return;
860
0
        }
861
862
0
        pluginDir = cfg.getSetting("PluginFolder");
863
0
        pluginList = cfg.getMultiSetting("Plugin");
864
865
0
        StringUtil::trim(pluginDir);
866
0
        if(pluginDir.empty() || pluginDir[0] == '.')
867
0
        {
868
            // resolve relative path with regards to configfile
869
0
            String baseDir, filename;
870
0
            StringUtil::splitFilename(pluginsfile, filename, baseDir);
871
0
            pluginDir = baseDir + pluginDir;
872
0
        }
873
874
0
        if(char* val = getenv("OGRE_PLUGIN_DIR"))
875
0
        {
876
0
            pluginDir = val;
877
0
            LogManager::getSingleton().logMessage(
878
0
                "setting PluginFolder from OGRE_PLUGIN_DIR environment variable");
879
0
        }
880
881
0
        pluginDir = FileSystemLayer::resolveBundlePath(pluginDir);
882
883
0
        if (!pluginDir.empty() && *pluginDir.rbegin() != '/' && *pluginDir.rbegin() != '\\')
884
0
        {
885
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 || OGRE_PLATFORM == OGRE_PLATFORM_WINRT
886
            pluginDir += "\\";
887
#else
888
0
            pluginDir += "/";
889
0
#endif
890
0
        }
891
892
0
        for(auto& p : pluginList)
893
0
        {
894
0
            loadPlugin(pluginDir + p);
895
0
        }
896
0
    }
897
    //-----------------------------------------------------------------------
898
    void Root::shutdownPlugins(void)
899
0
    {
900
        // NB Shutdown plugins in reverse order to enforce dependencies
901
0
        for (PluginInstanceList::reverse_iterator i = mPlugins.rbegin(); i != mPlugins.rend(); ++i)
902
0
        {
903
0
            (*i)->shutdown();
904
0
        }
905
0
    }
906
    //-----------------------------------------------------------------------
907
    void Root::initialisePlugins(void)
908
0
    {
909
0
        for (auto *p : mPlugins)
910
0
        {
911
0
            p->initialise();
912
0
        }
913
0
    }
914
    //-----------------------------------------------------------------------
915
    void Root::unloadPlugins(void)
916
0
    {
917
0
#if OGRE_PLATFORM != OGRE_PLATFORM_EMSCRIPTEN
918
        // unload dynamic libs first
919
0
        for (PluginLibList::reverse_iterator i = mPluginLibs.rbegin(); i != mPluginLibs.rend(); ++i)
920
0
        {
921
            // Call plugin shutdown
922
0
            #ifdef __GNUC__
923
0
            __extension__
924
0
            #endif
925
0
            DLL_STOP_PLUGIN pFunc = reinterpret_cast<DLL_STOP_PLUGIN>((*i)->getSymbol("dllStopPlugin"));
926
            // this will call uninstallPlugin
927
0
            pFunc();
928
            // Unload library & destroy
929
0
            DynLibManager::getSingleton().unload(*i);
930
931
0
        }
932
0
        mPluginLibs.clear();
933
934
        // now deal with any remaining plugins that were registered through other means
935
0
        for (PluginInstanceList::reverse_iterator i = mPlugins.rbegin(); i != mPlugins.rend(); ++i)
936
0
        {
937
            // Note this does NOT call uninstallPlugin - this shutdown is for the
938
            // detail objects
939
0
            (*i)->uninstall();
940
0
        }
941
0
        mPlugins.clear();
942
0
#endif
943
0
    }
944
    //---------------------------------------------------------------------
945
    DataStreamPtr Root::createFileStream(const String& filename, const String& groupName,
946
        bool overwrite, const String& locationPattern)
947
0
    {
948
        // Does this file include path specifiers?
949
0
        String path, basename;
950
0
        StringUtil::splitFilename(filename, basename, path);
951
952
        // no path elements, try the resource system first
953
0
        DataStreamPtr stream;
954
0
        if (path.empty())
955
0
        {
956
0
            try
957
0
            {
958
0
                stream = ResourceGroupManager::getSingleton().createResource(
959
0
                    filename, groupName, overwrite, locationPattern);
960
0
            }
961
0
            catch (...) {}
962
963
0
        }
964
965
0
        if (!stream)
966
0
        {
967
            // save direct in filesystem
968
0
            stream = _openFileStream(filename, std::ios::out | std::ios::binary);
969
0
        }
970
971
0
        return stream;
972
973
0
    }
974
    //---------------------------------------------------------------------
975
    DataStreamPtr Root::openFileStream(const String& filename, const String& groupName)
976
0
    {
977
0
        DataStreamPtr ret;
978
0
        if(auto rgm = ResourceGroupManager::getSingletonPtr())
979
0
            ret = rgm->openResource(filename, groupName, NULL, false);
980
981
0
        if(ret)
982
0
            return ret;
983
984
0
        return _openFileStream(filename, std::ios::in | std::ios::binary);
985
0
    }
986
    //-----------------------------------------------------------------------
987
    RenderWindow* Root::getAutoCreatedWindow(void)
988
0
    {
989
0
        return mAutoWindow;
990
0
    }
991
    //-----------------------------------------------------------------------
992
    RenderWindow* Root::createRenderWindow(const String &name, unsigned int width, unsigned int height,
993
            bool fullScreen, const NameValuePairList *miscParams)
994
0
    {
995
0
        OgreAssert(mIsInitialised,
996
0
                   "Cannot create window! Make sure to call Root::initialise before creating a window");
997
0
        OgreAssert(mActiveRenderer, "Cannot create window");
998
999
0
        RenderWindow* ret;
1000
0
        ret = mActiveRenderer->_createRenderWindow(name, width, height, fullScreen, miscParams);
1001
1002
        // Initialisation for classes dependent on first window created
1003
0
        if(!mFirstTimePostWindowInit)
1004
0
        {
1005
0
            oneTimePostWindowInit();
1006
0
            ret->_setPrimary();
1007
0
        }
1008
1009
0
        return ret;
1010
1011
0
    }
1012
    //-----------------------------------------------------------------------
1013
    RenderTarget* Root::detachRenderTarget(RenderTarget* target)
1014
0
    {
1015
0
        OgreAssert(mActiveRenderer, "Cannot detach target");
1016
0
        return mActiveRenderer->detachRenderTarget( target->getName() );
1017
0
    }
1018
    //-----------------------------------------------------------------------
1019
    RenderTarget* Root::detachRenderTarget(const String &name)
1020
0
    {
1021
0
        OgreAssert(mActiveRenderer, "Cannot detach target");
1022
0
        return mActiveRenderer->detachRenderTarget( name );
1023
0
    }
1024
    //-----------------------------------------------------------------------
1025
    void Root::destroyRenderTarget(RenderTarget* target)
1026
0
    {
1027
0
        detachRenderTarget(target);
1028
0
        OGRE_DELETE target;
1029
0
    }
1030
    //-----------------------------------------------------------------------
1031
    void Root::destroyRenderTarget(const String &name)
1032
0
    {
1033
0
        RenderTarget* target = getRenderTarget(name);
1034
0
        destroyRenderTarget(target);
1035
0
    }
1036
    //-----------------------------------------------------------------------
1037
    RenderTarget* Root::getRenderTarget(const String &name)
1038
0
    {
1039
0
        OgreAssert(mActiveRenderer, "Cannot get target");
1040
0
        return mActiveRenderer->getRenderTarget(name);
1041
0
    }
1042
    //---------------------------------------------------------------------
1043
    void Root::installPlugin(Plugin* plugin)
1044
0
    {
1045
0
        LogManager::getSingleton().logMessage("Installing plugin: " + plugin->getName());
1046
1047
0
        mPlugins.push_back(plugin);
1048
0
        plugin->install();
1049
1050
        // if rendersystem is already initialised, call rendersystem init too
1051
0
        if (mIsInitialised)
1052
0
        {
1053
0
            plugin->initialise();
1054
0
        }
1055
1056
0
        LogManager::getSingleton().logMessage("Plugin successfully installed");
1057
0
    }
1058
    //---------------------------------------------------------------------
1059
    void Root::uninstallPlugin(Plugin* plugin)
1060
0
    {
1061
0
        LogManager::getSingleton().logMessage("Uninstalling plugin: " + plugin->getName());
1062
0
        PluginInstanceList::iterator i =
1063
0
            std::find(mPlugins.begin(), mPlugins.end(), plugin);
1064
0
        if (i != mPlugins.end())
1065
0
        {
1066
0
            if (mIsInitialised)
1067
0
                plugin->shutdown();
1068
0
            plugin->uninstall();
1069
0
            mPlugins.erase(i);
1070
0
        }
1071
0
        LogManager::getSingleton().logMessage("Plugin successfully uninstalled");
1072
1073
0
    }
1074
    //-----------------------------------------------------------------------
1075
    void Root::loadPlugin(const String& pluginName)
1076
0
    {
1077
0
#if OGRE_PLATFORM != OGRE_PLATFORM_EMSCRIPTEN
1078
        // Load plugin library
1079
0
        DynLib* lib = DynLibManager::getSingleton().load( pluginName );
1080
        // Store for later unload
1081
        // Check for existence, because if called 2+ times DynLibManager returns existing entry
1082
0
        if (std::find(mPluginLibs.begin(), mPluginLibs.end(), lib) == mPluginLibs.end())
1083
0
        {
1084
0
            mPluginLibs.push_back(lib);
1085
1086
            // Call startup function
1087
0
                        #ifdef __GNUC__
1088
0
                        __extension__
1089
0
                        #endif
1090
0
            DLL_START_PLUGIN pFunc = (DLL_START_PLUGIN)lib->getSymbol("dllStartPlugin");
1091
1092
0
            if (!pFunc)
1093
0
                OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, "Cannot find symbol dllStartPlugin in library " + pluginName,
1094
0
                    "Root::loadPlugin");
1095
1096
            // This must call installPlugin
1097
0
            pFunc();
1098
0
        }
1099
0
#endif
1100
0
    }
1101
    //-----------------------------------------------------------------------
1102
    void Root::unloadPlugin(const String& pluginName)
1103
0
    {
1104
0
#if OGRE_PLATFORM != OGRE_PLATFORM_EMSCRIPTEN
1105
0
        PluginLibList::iterator i;
1106
1107
0
        for (i = mPluginLibs.begin(); i != mPluginLibs.end(); ++i)
1108
0
        {
1109
0
            if ((*i)->getName() == pluginName)
1110
0
            {
1111
                // Call plugin shutdown
1112
0
                                #ifdef __GNUC__
1113
0
                                __extension__
1114
0
                                #endif
1115
0
                DLL_STOP_PLUGIN pFunc = (DLL_STOP_PLUGIN)(*i)->getSymbol("dllStopPlugin");
1116
                // this must call uninstallPlugin
1117
0
                pFunc();
1118
                // Unload library (destroyed by DynLibManager)
1119
0
                DynLibManager::getSingleton().unload(*i);
1120
0
                mPluginLibs.erase(i);
1121
0
                return;
1122
0
            }
1123
1124
0
        }
1125
0
#endif
1126
0
    }
1127
    //-----------------------------------------------------------------------
1128
    Timer* Root::getTimer(void)
1129
0
    {
1130
0
        return mTimer.get();
1131
0
    }
1132
    //-----------------------------------------------------------------------
1133
    void Root::oneTimePostWindowInit(void)
1134
0
    {
1135
        // log RenderSystem caps
1136
0
        mActiveRenderer->getCapabilities()->log(LogManager::getSingleton().getDefaultLog());
1137
1138
        // Background loader
1139
0
        mWorkQueue->startup();
1140
        // Initialise material manager
1141
0
        mMaterialManager->initialise();
1142
        // Init particle systems manager
1143
0
        mParticleManager->_initialise();
1144
        // Init mesh manager
1145
0
        MeshManager::getSingleton()._initialise();
1146
        // Init plugins - after window creation so rsys resources available
1147
0
        initialisePlugins();
1148
0
        mFirstTimePostWindowInit = true;
1149
0
    }
1150
    //-----------------------------------------------------------------------
1151
    bool Root::_updateAllRenderTargets(void)
1152
0
    {
1153
        // update all targets but don't swap buffers
1154
0
        mActiveRenderer->_updateAllRenderTargets(false);
1155
        // give client app opportunity to use queued GPU time
1156
0
        bool ret = _fireFrameRenderingQueued();
1157
        // block for final swap
1158
0
        mActiveRenderer->_swapAllRenderTargetBuffers();
1159
1160
        // This belongs here, as all render targets must be updated before events are
1161
        // triggered, otherwise targets could be mismatched.  This could produce artifacts,
1162
        // for instance, with shadows.
1163
0
        for (const auto& m : getSceneManagers())
1164
0
            m.second->_handleLodEvents();
1165
1166
0
        return ret;
1167
0
    }
1168
    //---------------------------------------------------------------------
1169
    bool Root::_updateAllRenderTargets(FrameEvent& evt)
1170
0
    {
1171
        // update all targets but don't swap buffers
1172
0
        mActiveRenderer->_updateAllRenderTargets(false);
1173
        // give client app opportunity to use queued GPU time
1174
0
        bool ret = _fireFrameRenderingQueued(evt);
1175
        // block for final swap
1176
0
        mActiveRenderer->_swapAllRenderTargetBuffers();
1177
1178
        // This belongs here, as all render targets must be updated before events are
1179
        // triggered, otherwise targets could be mismatched.  This could produce artifacts,
1180
        // for instance, with shadows.
1181
0
        for (const auto& m : getSceneManagers())
1182
0
            m.second->_handleLodEvents();
1183
1184
0
        return ret;
1185
0
    }
1186
    //-----------------------------------------------------------------------
1187
    void Root::clearEventTimes(void)
1188
0
    {
1189
        // Clear event times
1190
0
        for(int i=0; i<FETT_COUNT; ++i)
1191
0
            mEventTimes[i].clear();
1192
0
    }
1193
    //---------------------------------------------------------------------
1194
    void Root::addMovableObjectFactory(MovableObjectFactory* fact,
1195
        bool overrideExisting)
1196
0
    {
1197
0
        MovableObjectFactoryMap::iterator facti = mMovableObjectFactoryMap.find(
1198
0
            fact->getType());
1199
0
        if (!overrideExisting && facti != mMovableObjectFactoryMap.end())
1200
0
        {
1201
0
            OGRE_EXCEPT(Exception::ERR_DUPLICATE_ITEM,
1202
0
                "A factory of type '" + fact->getType() + "' already exists.",
1203
0
                "Root::addMovableObjectFactory");
1204
0
        }
1205
1206
0
        if (fact->requestTypeFlags())
1207
0
        {
1208
0
            if (facti != mMovableObjectFactoryMap.end() && facti->second->requestTypeFlags())
1209
0
            {
1210
                // Copy type flags from the factory we're replacing
1211
0
                fact->_notifyTypeFlags(facti->second->getTypeFlags());
1212
0
            }
1213
0
            else
1214
0
            {
1215
                // Allocate new
1216
0
                fact->_notifyTypeFlags(_allocateNextMovableObjectTypeFlag());
1217
0
            }
1218
0
        }
1219
1220
        // Save
1221
0
        mMovableObjectFactoryMap[fact->getType()] = fact;
1222
1223
0
        LogManager::getSingleton().logMessage("MovableObjectFactory for type '" +
1224
0
            fact->getType() + "' registered.");
1225
1226
0
    }
1227
    //---------------------------------------------------------------------
1228
    bool Root::hasMovableObjectFactory(const String& typeName) const
1229
0
    {
1230
0
        return !(mMovableObjectFactoryMap.find(typeName) == mMovableObjectFactoryMap.end());
1231
0
    }
1232
    //---------------------------------------------------------------------
1233
    MovableObjectFactory* Root::getMovableObjectFactory(const String& typeName)
1234
0
    {
1235
0
        MovableObjectFactoryMap::iterator i =
1236
0
            mMovableObjectFactoryMap.find(typeName);
1237
0
        if (i == mMovableObjectFactoryMap.end())
1238
0
        {
1239
0
            OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND,
1240
0
                "MovableObjectFactory of type " + typeName + " does not exist",
1241
0
                "Root::getMovableObjectFactory");
1242
0
        }
1243
0
        return i->second;
1244
0
    }
1245
    //---------------------------------------------------------------------
1246
    uint32 Root::_allocateNextMovableObjectTypeFlag(void)
1247
0
    {
1248
0
        if (mNextMovableObjectTypeFlag == SceneManager::USER_TYPE_MASK_LIMIT)
1249
0
        {
1250
0
            OGRE_EXCEPT(Exception::ERR_DUPLICATE_ITEM,
1251
0
                "Cannot allocate a type flag since "
1252
0
                "all the available flags have been used.",
1253
0
                "Root::_allocateNextMovableObjectTypeFlag");
1254
1255
0
        }
1256
0
        uint32 ret = mNextMovableObjectTypeFlag;
1257
0
        mNextMovableObjectTypeFlag <<= 1;
1258
0
        return ret;
1259
1260
0
    }
1261
    //---------------------------------------------------------------------
1262
    void Root::removeMovableObjectFactory(MovableObjectFactory* fact)
1263
0
    {
1264
0
        MovableObjectFactoryMap::iterator i = mMovableObjectFactoryMap.find(
1265
0
            fact->getType());
1266
0
        if (i != mMovableObjectFactoryMap.end())
1267
0
        {
1268
0
            mMovableObjectFactoryMap.erase(i);
1269
0
        }
1270
1271
0
    }
1272
    //---------------------------------------------------------------------
1273
    Root::MovableObjectFactoryIterator
1274
    Root::getMovableObjectFactoryIterator(void) const
1275
0
    {
1276
0
        return MovableObjectFactoryIterator(mMovableObjectFactoryMap.begin(),
1277
0
            mMovableObjectFactoryMap.end());
1278
1279
0
    }
1280
    //---------------------------------------------------------------------
1281
    void Root::setWorkQueue(WorkQueue* queue)
1282
0
    {
1283
0
        if (mWorkQueue.get() != queue)
1284
0
        {
1285
0
            mWorkQueue.reset(queue);
1286
0
            if (mIsInitialised)
1287
0
                mWorkQueue->startup();
1288
1289
0
        }
1290
0
    }
1291
}