/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 | | } |