Patch 2793067: fix trunk with OGRE_THREAD_SUPPORT=1 on non-Windows platforms (don...
[ogre3d.git] / OgreMain / src / OgreRoot.cpp
blob339d416c51518e9aa7c37aa3f2920b022f82f588
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
7 Copyright (c) 2000-2006 Torus Knot Software Ltd
8 Also see acknowledgements in Readme.html
10 This program is free software; you can redistribute it and/or modify it under
11 the terms of the GNU Lesser General Public License as published by the Free Software
12 Foundation; either version 2 of the License, or (at your option) any later
13 version.
15 This program is distributed in the hope that it will be useful, but WITHOUT
16 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
19 You should have received a copy of the GNU Lesser General Public License along with
20 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
21 Place - Suite 330, Boston, MA 02111-1307, USA, or go to
22 http://www.gnu.org/copyleft/lesser.txt.
24 You may alternatively use this source under the terms of a specific version of
25 the OGRE Unrestricted License provided you have obtained such a license from
26 Torus Knot Software Ltd.
27 -----------------------------------------------------------------------------
29 // Ogre includes
30 #include "OgreStableHeaders.h"
32 #include "OgreRoot.h"
34 #include "OgreRenderSystem.h"
35 #include "OgreRenderWindow.h"
36 #include "OgreException.h"
37 #include "OgreControllerManager.h"
38 #include "OgreLogManager.h"
39 #include "OgreMath.h"
40 #include "OgreDynLibManager.h"
41 #include "OgreDynLib.h"
42 #include "OgreConfigFile.h"
43 #include "OgreMaterialManager.h"
44 #include "OgreRenderSystemCapabilitiesManager.h"
45 #include "OgreMeshManager.h"
46 #include "OgreTextureManager.h"
47 #include "OgreParticleSystemManager.h"
48 #include "OgreSkeletonManager.h"
49 #include "OgreOverlayElementFactory.h"
50 #include "OgreOverlayManager.h"
51 #include "OgreProfiler.h"
52 #include "OgreErrorDialog.h"
53 #include "OgreConfigDialog.h"
54 #include "OgreStringConverter.h"
55 #include "OgreArchiveManager.h"
56 #include "OgrePlugin.h"
57 #include "OgreZip.h"
58 #include "OgreFileSystem.h"
59 #include "OgreShadowVolumeExtrudeProgram.h"
60 #include "OgreResourceBackgroundQueue.h"
61 #include "OgreEntity.h"
62 #include "OgreBillboardSet.h"
63 #include "OgreBillboardChain.h"
64 #include "OgreRibbonTrail.h"
65 #include "OgreLight.h"
66 #include "OgreManualObject.h"
67 #include "OgreRenderQueueInvocation.h"
68 #include "OgrePlatformInformation.h"
69 #include "OgreConvexBody.h"
71 #if OGRE_NO_FREEIMAGE == 0
72 #include "OgreFreeImageCodec.h"
73 #endif
74 #if OGRE_NO_DEVIL == 0
75 #include "OgreILCodecs.h"
76 #endif
77 #if OGRE_NO_DDS_CODEC == 0
78 #include "OgreDDSCodec.h"
79 #endif
81 #include "OgreFontManager.h"
82 #include "OgreHardwareBufferManager.h"
84 #include "OgreOverlay.h"
85 #include "OgreHighLevelGpuProgramManager.h"
87 #include "OgreExternalTextureSourceManager.h"
88 #include "OgreCompositorManager.h"
90 #include "OgreScriptCompiler.h"
92 #include "OgreWindowEventUtilities.h"
94 namespace Ogre {
95 //-----------------------------------------------------------------------
96 template<> Root* Singleton<Root>::ms_Singleton = 0;
97 Root* Root::getSingletonPtr(void)
99 return ms_Singleton;
101 Root& Root::getSingleton(void)
103 assert( ms_Singleton ); return ( *ms_Singleton );
106 typedef void (*DLL_START_PLUGIN)(void);
107 typedef void (*DLL_STOP_PLUGIN)(void);
110 //-----------------------------------------------------------------------
111 Root::Root(const String& pluginFileName, const String& configFileName,
112 const String& logFileName)
113 : mLogManager(0)
114 , mRenderSystemCapabilitiesManager(0)
115 , mNextFrame(0)
116 , mFrameSmoothingTime(0.0f)
117 , mNextMovableObjectTypeFlag(1)
118 , mIsInitialised(false)
120 // superclass will do singleton checking
121 String msg;
123 // Init
124 mActiveRenderer = 0;
125 mVersion = StringConverter::toString(OGRE_VERSION_MAJOR) + "." +
126 StringConverter::toString(OGRE_VERSION_MINOR) + "." +
127 StringConverter::toString(OGRE_VERSION_PATCH) +
128 OGRE_VERSION_SUFFIX + " " +
129 "(" + OGRE_VERSION_NAME + ")";
130 mConfigFileName = configFileName;
132 // Create log manager and default log file if there is no log manager yet
133 if(LogManager::getSingletonPtr() == 0)
135 mLogManager = OGRE_NEW LogManager();
136 mLogManager->createLog(logFileName, true, true);
139 // Dynamic library manager
140 mDynLibManager = OGRE_NEW DynLibManager();
142 mArchiveManager = OGRE_NEW ArchiveManager();
144 // ResourceGroupManager
145 mResourceGroupManager = OGRE_NEW ResourceGroupManager();
147 // ResourceBackgroundQueue
148 mResourceBackgroundQueue = OGRE_NEW ResourceBackgroundQueue();
150 // Create SceneManager enumerator (note - will be managed by singleton)
151 mSceneManagerEnum = OGRE_NEW SceneManagerEnumerator();
152 mCurrentSceneManager = NULL;
154 mShadowTextureManager = OGRE_NEW ShadowTextureManager();
156 mRenderSystemCapabilitiesManager = OGRE_NEW RenderSystemCapabilitiesManager();
158 // ..material manager
159 mMaterialManager = OGRE_NEW MaterialManager();
161 // Mesh manager
162 mMeshManager = OGRE_NEW MeshManager();
164 // Skeleton manager
165 mSkeletonManager = OGRE_NEW SkeletonManager();
167 // ..particle system manager
168 mParticleManager = OGRE_NEW ParticleSystemManager();
170 // Compiler manager
171 //mCompilerManager = OGRE_NEW ScriptCompilerManager();
173 mTimer = OGRE_NEW Timer();
175 // Overlay manager
176 mOverlayManager = OGRE_NEW OverlayManager();
178 mPanelFactory = OGRE_NEW PanelOverlayElementFactory();
179 mOverlayManager->addOverlayElementFactory(mPanelFactory);
181 mBorderPanelFactory = OGRE_NEW BorderPanelOverlayElementFactory();
182 mOverlayManager->addOverlayElementFactory(mBorderPanelFactory);
184 mTextAreaFactory = OGRE_NEW TextAreaOverlayElementFactory();
185 mOverlayManager->addOverlayElementFactory(mTextAreaFactory);
186 // Font manager
187 mFontManager = OGRE_NEW FontManager();
189 // Lod strategy manager
190 mLodStrategyManager = OGRE_NEW LodStrategyManager();
192 #if OGRE_PROFILING
193 // Profiler
194 mProfiler = OGRE_NEW Profiler();
195 Profiler::getSingleton().setTimer(mTimer);
196 #endif
197 mFileSystemArchiveFactory = OGRE_NEW FileSystemArchiveFactory();
198 ArchiveManager::getSingleton().addArchiveFactory( mFileSystemArchiveFactory );
199 mZipArchiveFactory = OGRE_NEW ZipArchiveFactory();
200 ArchiveManager::getSingleton().addArchiveFactory( mZipArchiveFactory );
201 #if OGRE_NO_FREEIMAGE == 0
202 // Register image codecs
203 FreeImageCodec::startup();
204 #endif
205 #if OGRE_NO_DEVIL == 0
206 // Register image codecs
207 ILCodecs::registerCodecs();
208 #endif
209 #if OGRE_NO_DDS_CODEC == 0
210 // Register image codecs
211 DDSCodec::startup();
212 #endif
214 mHighLevelGpuProgramManager = OGRE_NEW HighLevelGpuProgramManager();
216 mExternalTextureSourceManager = OGRE_NEW ExternalTextureSourceManager();
217 mCompositorManager = OGRE_NEW CompositorManager();
219 mCompilerManager = OGRE_NEW ScriptCompilerManager();
221 // Auto window
222 mAutoWindow = 0;
224 // instantiate and register base movable factories
225 mEntityFactory = OGRE_NEW EntityFactory();
226 addMovableObjectFactory(mEntityFactory);
227 mLightFactory = OGRE_NEW LightFactory();
228 addMovableObjectFactory(mLightFactory);
229 mBillboardSetFactory = OGRE_NEW BillboardSetFactory();
230 addMovableObjectFactory(mBillboardSetFactory);
231 mManualObjectFactory = OGRE_NEW ManualObjectFactory();
232 addMovableObjectFactory(mManualObjectFactory);
233 mBillboardChainFactory = OGRE_NEW BillboardChainFactory();
234 addMovableObjectFactory(mBillboardChainFactory);
235 mRibbonTrailFactory = OGRE_NEW RibbonTrailFactory();
236 addMovableObjectFactory(mRibbonTrailFactory);
238 // Load plugins
239 if (!pluginFileName.empty())
240 loadPlugins(pluginFileName);
242 LogManager::getSingleton().logMessage("*-*-* OGRE Initialising");
243 msg = "*-*-* Version " + mVersion;
244 LogManager::getSingleton().logMessage(msg);
246 // Can't create managers until initialised
247 mControllerManager = 0;
249 mFirstTimePostWindowInit = false;
253 //-----------------------------------------------------------------------
254 Root::~Root()
256 shutdown();
257 OGRE_DELETE mSceneManagerEnum;
258 OGRE_DELETE mShadowTextureManager;
259 OGRE_DELETE mRenderSystemCapabilitiesManager;
261 destroyAllRenderQueueInvocationSequences();
262 OGRE_DELETE mCompositorManager;
263 OGRE_DELETE mExternalTextureSourceManager;
264 #if OGRE_NO_FREEIMAGE == 0
265 FreeImageCodec::shutdown();
266 #endif
267 #if OGRE_NO_DEVIL == 0
268 ILCodecs::deleteCodecs();
269 #endif
270 #if OGRE_NO_DDS_CODEC == 0
271 DDSCodec::shutdown();
272 #endif
273 #if OGRE_PROFILING
274 OGRE_DELETE mProfiler;
275 #endif
276 OGRE_DELETE mOverlayManager;
277 OGRE_DELETE mFontManager;
278 OGRE_DELETE mLodStrategyManager;
279 OGRE_DELETE mArchiveManager;
280 OGRE_DELETE mZipArchiveFactory;
281 OGRE_DELETE mFileSystemArchiveFactory;
282 OGRE_DELETE mSkeletonManager;
283 OGRE_DELETE mMeshManager;
284 OGRE_DELETE mParticleManager;
285 //OGRE_DELETE mCompilerManager;
287 if( mControllerManager )
288 OGRE_DELETE mControllerManager;
289 if (mHighLevelGpuProgramManager)
290 OGRE_DELETE mHighLevelGpuProgramManager;
292 OGRE_DELETE mTextAreaFactory;
293 OGRE_DELETE mBorderPanelFactory;
294 OGRE_DELETE mPanelFactory;
296 unloadPlugins();
297 OGRE_DELETE mMaterialManager;
298 Pass::processPendingPassUpdates(); // make sure passes are cleaned
299 OGRE_DELETE mResourceBackgroundQueue;
300 OGRE_DELETE mResourceGroupManager;
302 OGRE_DELETE mEntityFactory;
303 OGRE_DELETE mLightFactory;
304 OGRE_DELETE mBillboardSetFactory;
305 OGRE_DELETE mManualObjectFactory;
306 OGRE_DELETE mBillboardChainFactory;
307 OGRE_DELETE mRibbonTrailFactory;
309 OGRE_DELETE mTimer;
311 OGRE_DELETE mDynLibManager;
312 OGRE_DELETE mLogManager;
314 OGRE_DELETE mCompilerManager;
316 mAutoWindow = 0;
317 mFirstTimePostWindowInit = false;
320 StringInterface::cleanupDictionary ();
323 //-----------------------------------------------------------------------
324 void Root::saveConfig(void)
326 if (mConfigFileName.empty ())
327 return;
329 std::ofstream of(mConfigFileName.c_str());
331 if (!of)
332 OGRE_EXCEPT(Exception::ERR_CANNOT_WRITE_TO_FILE, "Cannot create settings file.",
333 "Root::saveConfig");
335 if (mActiveRenderer)
337 of << "Render System=" << mActiveRenderer->getName() << std::endl;
339 else
341 of << "Render System=" << std::endl;
344 for (RenderSystemList::const_iterator pRend = getAvailableRenderers().begin(); pRend != getAvailableRenderers().end(); ++pRend)
346 RenderSystem* rs = *pRend;
347 of << std::endl;
348 of << "[" << rs->getName() << "]" << std::endl;
349 const ConfigOptionMap& opts = rs->getConfigOptions();
350 for (ConfigOptionMap::const_iterator pOpt = opts.begin(); pOpt != opts.end(); ++pOpt)
352 of << pOpt->first << "=" << pOpt->second.currentValue << std::endl;
356 of.close();
359 //-----------------------------------------------------------------------
360 bool Root::restoreConfig(void)
362 if (mConfigFileName.empty ())
363 return true;
365 // Restores configuration from saved state
366 // Returns true if a valid saved configuration is
367 // available, and false if no saved config is
368 // stored, or if there has been a problem
369 ConfigFile cfg;
371 try {
372 // Don't trim whitespace
373 cfg.load(mConfigFileName, "\t:=", false);
375 catch (Exception& e)
377 if (e.getNumber() == Exception::ERR_FILE_NOT_FOUND)
379 return false;
381 else
383 throw;
387 ConfigFile::SectionIterator iSection = cfg.getSectionIterator();
388 while (iSection.hasMoreElements())
390 const String& renderSystem = iSection.peekNextKey();
391 const ConfigFile::SettingsMultiMap& settings = *iSection.getNext();
393 RenderSystem* rs = getRenderSystemByName(renderSystem);
394 if (!rs)
396 // Unrecognised render system
397 continue;
400 ConfigFile::SettingsMultiMap::const_iterator i;
401 for (i = settings.begin(); i != settings.end(); ++i)
403 rs->setConfigOption(i->first, i->second);
407 RenderSystem* rs = getRenderSystemByName(cfg.getSetting("Render System"));
408 if (!rs)
410 // Unrecognised render system
411 return false;
414 setRenderSystem(rs);
416 // Successful load
417 return true;
421 //-----------------------------------------------------------------------
422 bool Root::showConfigDialog(void)
424 // Displays the standard config dialog
425 // Will use stored defaults if available
426 ConfigDialog* dlg;
427 bool isOk;
429 restoreConfig();
431 dlg = OGRE_NEW ConfigDialog();
433 if ((isOk = dlg->display()))
434 saveConfig();
436 OGRE_DELETE dlg;
437 return isOk;
440 //-----------------------------------------------------------------------
441 const RenderSystemList& Root::getAvailableRenderers(void)
443 // Returns a vector of renders
445 return mRenderers;
449 //-----------------------------------------------------------------------
450 RenderSystem* Root::getRenderSystemByName(const String& name)
452 if (name.empty())
454 // No render system
455 return NULL;
458 RenderSystemList::const_iterator pRend;
459 for (pRend = getAvailableRenderers().begin(); pRend != getAvailableRenderers().end(); ++pRend)
461 RenderSystem* rs = *pRend;
462 if (rs->getName() == name)
463 return rs;
466 // Unrecognised render system
467 return NULL;
470 //-----------------------------------------------------------------------
471 void Root::setRenderSystem(RenderSystem* system)
473 // Sets the active rendering system
474 // Can be called direct or will be called by
475 // standard config dialog
477 // Is there already an active renderer?
478 // If so, disable it and init the new one
479 if( mActiveRenderer && mActiveRenderer != system )
481 mActiveRenderer->shutdown();
484 mActiveRenderer = system;
485 // Tell scene managers
486 SceneManagerEnumerator::getSingleton().setRenderSystem(system);
489 //-----------------------------------------------------------------------
490 void Root::addRenderSystem(RenderSystem *newRend)
492 mRenderers.push_back(newRend);
494 //-----------------------------------------------------------------------
495 void Root::_setCurrentSceneManager(SceneManager* sm)
497 mCurrentSceneManager = sm;
499 //-----------------------------------------------------------------------
500 RenderSystem* Root::getRenderSystem(void)
502 // Gets the currently active renderer
503 return mActiveRenderer;
507 //-----------------------------------------------------------------------
508 RenderWindow* Root::initialise(bool autoCreateWindow, const String& windowTitle, const String& customCapabilitiesConfig)
510 if (!mActiveRenderer)
511 OGRE_EXCEPT(Exception::ERR_INVALID_STATE,
512 "Cannot initialise - no render "
513 "system has been selected.", "Root::initialise");
515 if (!mControllerManager)
516 mControllerManager = OGRE_NEW ControllerManager();
518 // .rendercaps manager
519 RenderSystemCapabilitiesManager& rscManager = RenderSystemCapabilitiesManager::getSingleton();
520 // caller wants to load custom RenderSystemCapabilities form a config file
521 if(customCapabilitiesConfig != StringUtil::BLANK)
523 ConfigFile cfg;
524 cfg.load(customCapabilitiesConfig, "\t:=", false);
526 // Capabilities Database setting must be in the same format as
527 // resources.cfg in Ogre examples.
528 ConfigFile::SettingsIterator iter = cfg.getSettingsIterator("Capabilities Database");
529 while(iter.hasMoreElements())
531 String archType = iter.peekNextKey();
532 String filename = iter.getNext();
534 rscManager.parseCapabilitiesFromArchive(filename, archType, true);
537 String capsName = cfg.getSetting("Custom Capabilities");
538 // The custom capabilities have been parsed, let's retrieve them
539 RenderSystemCapabilities* rsc = rscManager.loadParsedCapabilities(capsName);
540 if(rsc == 0)
542 OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND,
543 String("Cannot load a RenderSystemCapability named ") + capsName,
544 "Root::initialise");
547 // Tell RenderSystem to use the comon rsc
548 useCustomRenderSystemCapabilities(rsc);
552 PlatformInformation::log(LogManager::getSingleton().getDefaultLog());
553 mAutoWindow = mActiveRenderer->_initialise(autoCreateWindow, windowTitle);
556 if (autoCreateWindow && !mFirstTimePostWindowInit)
558 oneTimePostWindowInit();
559 mAutoWindow->_setPrimary();
562 // Initialise timer
563 mTimer->reset();
565 // Init pools
566 ConvexBody::_initialisePool();
568 mIsInitialised = true;
570 return mAutoWindow;
573 //-----------------------------------------------------------------------
574 void Root::useCustomRenderSystemCapabilities(RenderSystemCapabilities* capabilities)
576 mActiveRenderer->useCustomRenderSystemCapabilities(capabilities);
578 //-----------------------------------------------------------------------
579 String Root::getErrorDescription(long errorNumber)
582 // Pass to render system
583 if (mActiveRenderer)
584 return mActiveRenderer->getErrorDescription(errorNumber);
585 else
586 return "";
589 //-----------------------------------------------------------------------
590 void Root::addSceneManagerFactory(SceneManagerFactory* fact)
592 mSceneManagerEnum->addFactory(fact);
594 //-----------------------------------------------------------------------
595 void Root::removeSceneManagerFactory(SceneManagerFactory* fact)
597 mSceneManagerEnum->removeFactory(fact);
599 //-----------------------------------------------------------------------
600 const SceneManagerMetaData* Root::getSceneManagerMetaData(const String& typeName) const
602 return mSceneManagerEnum->getMetaData(typeName);
604 //-----------------------------------------------------------------------
605 SceneManagerEnumerator::MetaDataIterator
606 Root::getSceneManagerMetaDataIterator(void) const
608 return mSceneManagerEnum->getMetaDataIterator();
611 //-----------------------------------------------------------------------
612 SceneManager* Root::createSceneManager(const String& typeName,
613 const String& instanceName)
615 return mSceneManagerEnum->createSceneManager(typeName, instanceName);
617 //-----------------------------------------------------------------------
618 SceneManager* Root::createSceneManager(SceneTypeMask typeMask,
619 const String& instanceName)
621 return mSceneManagerEnum->createSceneManager(typeMask, instanceName);
623 //-----------------------------------------------------------------------
624 void Root::destroySceneManager(SceneManager* sm)
626 mSceneManagerEnum->destroySceneManager(sm);
628 //-----------------------------------------------------------------------
629 SceneManager* Root::getSceneManager(const String& instanceName) const
631 return mSceneManagerEnum->getSceneManager(instanceName);
633 //-----------------------------------------------------------------------
634 SceneManagerEnumerator::SceneManagerIterator Root::getSceneManagerIterator(void)
636 return mSceneManagerEnum->getSceneManagerIterator();
638 //-----------------------------------------------------------------------
639 TextureManager* Root::getTextureManager(void)
641 return &TextureManager::getSingleton();
643 //-----------------------------------------------------------------------
644 MeshManager* Root::getMeshManager(void)
646 return &MeshManager::getSingleton();
648 //-----------------------------------------------------------------------
649 void Root::addFrameListener(FrameListener* newListener)
651 // Check if the specified listener is scheduled for removal
652 set<FrameListener *>::type::iterator i = mRemovedFrameListeners.find(newListener);
654 // If yes, cancel the removal. Otherwise add it to other listeners.
655 if (i != mRemovedFrameListeners.end())
656 mRemovedFrameListeners.erase(*i);
657 else
658 mFrameListeners.insert(newListener); // Insert, unique only (set)
661 //-----------------------------------------------------------------------
662 void Root::removeFrameListener(FrameListener* oldListener)
664 // Remove, 1 only (set)
665 mRemovedFrameListeners.insert(oldListener);
667 //-----------------------------------------------------------------------
668 bool Root::_fireFrameStarted(FrameEvent& evt)
670 OgreProfileBeginGroup("Frame", OGREPROF_GENERAL);
672 // Remove all marked listeners
673 set<FrameListener*>::type::iterator i;
674 for (i = mRemovedFrameListeners.begin();
675 i != mRemovedFrameListeners.end(); i++)
677 mFrameListeners.erase(*i);
679 mRemovedFrameListeners.clear();
681 // Tell all listeners
682 for (i= mFrameListeners.begin(); i != mFrameListeners.end(); ++i)
684 if (!(*i)->frameStarted(evt))
685 return false;
688 return true;
691 //-----------------------------------------------------------------------
692 bool Root::_fireFrameRenderingQueued(FrameEvent& evt)
694 // Increment next frame number
695 ++mNextFrame;
697 // Remove all marked listeners
698 set<FrameListener*>::type::iterator i;
699 for (i = mRemovedFrameListeners.begin();
700 i != mRemovedFrameListeners.end(); i++)
702 mFrameListeners.erase(*i);
704 mRemovedFrameListeners.clear();
706 // Tell all listeners
707 for (i= mFrameListeners.begin(); i != mFrameListeners.end(); ++i)
709 if (!(*i)->frameRenderingQueued(evt))
710 return false;
713 return true;
716 //-----------------------------------------------------------------------
717 bool Root::_fireFrameEnded(FrameEvent& evt)
719 // Remove all marked listeners
720 set<FrameListener*>::type::iterator i;
721 for (i = mRemovedFrameListeners.begin();
722 i != mRemovedFrameListeners.end(); i++)
724 mFrameListeners.erase(*i);
726 mRemovedFrameListeners.clear();
728 // Tell all listeners
729 bool ret = true;
730 for (i= mFrameListeners.begin(); i != mFrameListeners.end(); ++i)
732 if (!(*i)->frameEnded(evt))
734 ret = false;
735 break;
739 // Tell buffer manager to free temp buffers used this frame
740 if (HardwareBufferManager::getSingletonPtr())
741 HardwareBufferManager::getSingleton()._releaseBufferCopies();
743 // Also tell the ResourceBackgroundQueue to propagate background load events
744 ResourceBackgroundQueue::getSingleton()._fireOnFrameCallbacks();
746 OgreProfileEndGroup("Frame", OGREPROF_GENERAL);
748 return ret;
750 //-----------------------------------------------------------------------
751 bool Root::_fireFrameStarted()
753 FrameEvent evt;
754 populateFrameEvent(FETT_STARTED, evt);
756 return _fireFrameStarted(evt);
758 //-----------------------------------------------------------------------
759 bool Root::_fireFrameRenderingQueued()
761 FrameEvent evt;
762 populateFrameEvent(FETT_QUEUED, evt);
764 return _fireFrameRenderingQueued(evt);
766 //-----------------------------------------------------------------------
767 bool Root::_fireFrameEnded()
769 FrameEvent evt;
770 populateFrameEvent(FETT_ENDED, evt);
771 return _fireFrameEnded(evt);
773 //---------------------------------------------------------------------
774 void Root::populateFrameEvent(FrameEventTimeType type, FrameEvent& evtToUpdate)
776 unsigned long now = mTimer->getMilliseconds();
777 evtToUpdate.timeSinceLastEvent = calculateEventTime(now, FETT_ANY);
778 evtToUpdate.timeSinceLastFrame = calculateEventTime(now, type);
780 //-----------------------------------------------------------------------
781 Real Root::calculateEventTime(unsigned long now, FrameEventTimeType type)
783 // Calculate the average time passed between events of the given type
784 // during the last mFrameSmoothingTime seconds.
786 EventTimesQueue& times = mEventTimes[type];
787 times.push_back(now);
789 if(times.size() == 1)
790 return 0;
792 // Times up to mFrameSmoothingTime seconds old should be kept
793 unsigned long discardThreshold =
794 static_cast<unsigned long>(mFrameSmoothingTime * 1000.0f);
796 // Find the oldest time to keep
797 EventTimesQueue::iterator it = times.begin(),
798 end = times.end()-2; // We need at least two times
799 while(it != end)
801 if (now - *it > discardThreshold)
802 ++it;
803 else
804 break;
807 // Remove old times
808 times.erase(times.begin(), it);
810 return Real(times.back() - times.front()) / ((times.size()-1) * 1000);
812 //-----------------------------------------------------------------------
813 void Root::queueEndRendering(void)
815 mQueuedEnd = true;
817 //-----------------------------------------------------------------------
818 void Root::startRendering(void)
820 assert(mActiveRenderer != 0);
822 mActiveRenderer->_initRenderTargets();
824 // Clear event times
825 clearEventTimes();
827 // Infinite loop, until broken out of by frame listeners
828 // or break out by calling queueEndRendering()
829 mQueuedEnd = false;
831 while( !mQueuedEnd )
833 //Pump messages in all registered RenderWindow windows
834 WindowEventUtilities::messagePump();
836 if (!renderOneFrame())
837 break;
840 //-----------------------------------------------------------------------
841 bool Root::renderOneFrame(void)
843 if(!_fireFrameStarted())
844 return false;
846 if (!_updateAllRenderTargets())
847 return false;
849 return _fireFrameEnded();
851 //---------------------------------------------------------------------
852 bool Root::renderOneFrame(Real timeSinceLastFrame)
854 FrameEvent evt;
855 evt.timeSinceLastFrame = timeSinceLastFrame;
857 unsigned long now = mTimer->getMilliseconds();
858 evt.timeSinceLastEvent = calculateEventTime(now, FETT_ANY);
860 if(!_fireFrameStarted(evt))
861 return false;
863 if (!_updateAllRenderTargets(evt))
864 return false;
866 now = mTimer->getMilliseconds();
867 evt.timeSinceLastEvent = calculateEventTime(now, FETT_ANY);
869 return _fireFrameEnded(evt);
871 //-----------------------------------------------------------------------
872 void Root::shutdown(void)
874 SceneManagerEnumerator::getSingleton().shutdownAll();
875 shutdownPlugins();
877 ShadowVolumeExtrudeProgram::shutdown();
878 mResourceBackgroundQueue->shutdown();
879 ResourceGroupManager::getSingleton().shutdownAll();
881 // Destroy pools
882 ConvexBody::_destroyPool();
885 mIsInitialised = false;
887 LogManager::getSingleton().logMessage("*-*-* OGRE Shutdown");
889 //-----------------------------------------------------------------------
890 void Root::loadPlugins( const String& pluginsfile )
892 StringVector pluginList;
893 String pluginDir;
894 ConfigFile cfg;
896 try {
897 cfg.load( pluginsfile );
899 catch (Exception)
901 LogManager::getSingleton().logMessage(pluginsfile + " not found, automatic plugin loading disabled.");
902 return;
905 pluginDir = cfg.getSetting("PluginFolder"); // Ignored on Mac OS X, uses Resources/ directory
906 pluginList = cfg.getMultiSetting("Plugin");
908 #if OGRE_PLATFORM != OGRE_PLATFORM_APPLE
909 if (pluginDir.empty())
911 // User didn't specify plugins folder, try current one
912 pluginDir = ".";
914 #endif
916 char last_char = pluginDir[pluginDir.length()-1];
917 if (last_char != '/' && last_char != '\\')
919 #if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
920 pluginDir += "\\";
921 #elif OGRE_PLATFORM == OGRE_PLATFORM_LINUX
922 pluginDir += "/";
923 #endif
926 for( StringVector::iterator it = pluginList.begin(); it != pluginList.end(); ++it )
928 loadPlugin(pluginDir + (*it));
932 //-----------------------------------------------------------------------
933 void Root::shutdownPlugins(void)
935 // NB Shutdown plugins in reverse order to enforce dependencies
936 for (PluginInstanceList::reverse_iterator i = mPlugins.rbegin(); i != mPlugins.rend(); ++i)
938 (*i)->shutdown();
941 //-----------------------------------------------------------------------
942 void Root::initialisePlugins(void)
944 for (PluginInstanceList::iterator i = mPlugins.begin(); i != mPlugins.end(); ++i)
946 (*i)->initialise();
949 //-----------------------------------------------------------------------
950 void Root::unloadPlugins(void)
952 // unload dynamic libs first
953 for (PluginLibList::reverse_iterator i = mPluginLibs.rbegin(); i != mPluginLibs.rend(); ++i)
955 // Call plugin shutdown
956 DLL_STOP_PLUGIN pFunc = (DLL_STOP_PLUGIN)(*i)->getSymbol("dllStopPlugin");
957 // this will call uninstallPlugin
958 pFunc();
959 // Unload library & destroy
960 DynLibManager::getSingleton().unload(*i);
963 mPluginLibs.clear();
965 // now deal with any remaining plugins that were registered through other means
966 for (PluginInstanceList::reverse_iterator i = mPlugins.rbegin(); i != mPlugins.rend(); ++i)
968 // Note this does NOT call uninstallPlugin - this shutdown is for the
969 // detail objects
970 (*i)->uninstall();
972 mPlugins.clear();
975 //-----------------------------------------------------------------------
976 void Root::addResourceLocation(const String& name, const String& locType,
977 const String& groupName, bool recursive)
979 ResourceGroupManager::getSingleton().addResourceLocation(
980 name, locType, groupName, recursive);
982 //-----------------------------------------------------------------------
983 void Root::removeResourceLocation(const String& name, const String& groupName)
985 ResourceGroupManager::getSingleton().removeResourceLocation(
986 name, groupName);
988 //-----------------------------------------------------------------------
989 void Root::convertColourValue(const ColourValue& colour, uint32* pDest)
991 assert(mActiveRenderer != 0);
992 mActiveRenderer->convertColourValue(colour, pDest);
994 //-----------------------------------------------------------------------
995 RenderWindow* Root::getAutoCreatedWindow(void)
997 return mAutoWindow;
999 //-----------------------------------------------------------------------
1000 RenderWindow* Root::createRenderWindow(const String &name, unsigned int width, unsigned int height,
1001 bool fullScreen, const NameValuePairList *miscParams)
1003 if (!mActiveRenderer)
1005 OGRE_EXCEPT(Exception::ERR_INVALID_STATE,
1006 "Cannot create window - no render "
1007 "system has been selected.", "Root::createRenderWindow");
1009 RenderWindow* ret;
1010 ret = mActiveRenderer->_createRenderWindow(name, width, height, fullScreen, miscParams);
1012 // Initialisation for classes dependent on first window created
1013 if(!mFirstTimePostWindowInit)
1015 oneTimePostWindowInit();
1016 ret->_setPrimary();
1019 return ret;
1022 //-----------------------------------------------------------------------
1023 bool Root::createRenderWindows(const RenderWindowDescriptionList& renderWindowDescriptions,
1024 RenderWindowList& createdWindows)
1026 if (!mActiveRenderer)
1028 OGRE_EXCEPT(Exception::ERR_INVALID_STATE,
1029 "Cannot create render windows - no render "
1030 "system has been selected.", "Root::createRenderWindows");
1033 bool success;
1035 success = mActiveRenderer->_createRenderWindows(renderWindowDescriptions, createdWindows);
1036 if(success && !mFirstTimePostWindowInit)
1038 oneTimePostWindowInit();
1039 createdWindows[0]->_setPrimary();
1042 return success;
1044 //-----------------------------------------------------------------------
1045 void Root::detachRenderTarget(RenderTarget* target)
1047 if (!mActiveRenderer)
1049 OGRE_EXCEPT(Exception::ERR_INVALID_STATE,
1050 "Cannot create window - no render "
1051 "system has been selected.", "Root::destroyRenderWindow");
1054 mActiveRenderer->detachRenderTarget( target->getName() );
1056 //-----------------------------------------------------------------------
1057 void Root::detachRenderTarget(const String &name)
1059 if (!mActiveRenderer)
1061 OGRE_EXCEPT(Exception::ERR_INVALID_STATE,
1062 "Cannot create window - no render "
1063 "system has been selected.", "Root::destroyRenderWindow");
1066 mActiveRenderer->detachRenderTarget( name );
1068 //-----------------------------------------------------------------------
1069 RenderTarget* Root::getRenderTarget(const String &name)
1071 if (!mActiveRenderer)
1073 OGRE_EXCEPT(Exception::ERR_INVALID_STATE,
1074 "Cannot create window - no render "
1075 "system has been selected.", "Root::getRenderWindow");
1078 return mActiveRenderer->getRenderTarget(name);
1080 //---------------------------------------------------------------------
1081 void Root::installPlugin(Plugin* plugin)
1083 LogManager::getSingleton().logMessage("Installing plugin: " + plugin->getName());
1085 mPlugins.push_back(plugin);
1086 plugin->install();
1088 // if rendersystem is already initialised, call rendersystem init too
1089 if (mIsInitialised)
1091 plugin->initialise();
1094 LogManager::getSingleton().logMessage("Plugin successfully installed");
1096 //---------------------------------------------------------------------
1097 void Root::uninstallPlugin(Plugin* plugin)
1099 LogManager::getSingleton().logMessage("Uninstalling plugin: " + plugin->getName());
1100 PluginInstanceList::iterator i =
1101 std::find(mPlugins.begin(), mPlugins.end(), plugin);
1102 if (i != mPlugins.end())
1104 if (mIsInitialised)
1105 plugin->shutdown();
1106 plugin->uninstall();
1107 mPlugins.erase(i);
1109 LogManager::getSingleton().logMessage("Plugin successfully uninstalled");
1112 //-----------------------------------------------------------------------
1113 void Root::loadPlugin(const String& pluginName)
1115 // Load plugin library
1116 DynLib* lib = DynLibManager::getSingleton().load( pluginName );
1117 // Store for later unload
1118 // Check for existence, because if called 2+ times DynLibManager returns existing entry
1119 if (std::find(mPluginLibs.begin(), mPluginLibs.end(), lib) == mPluginLibs.end())
1121 mPluginLibs.push_back(lib);
1123 // Call startup function
1124 DLL_START_PLUGIN pFunc = (DLL_START_PLUGIN)lib->getSymbol("dllStartPlugin");
1126 if (!pFunc)
1127 OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, "Cannot find symbol dllStartPlugin in library " + pluginName,
1128 "Root::loadPlugin");
1130 // This must call installPlugin
1131 pFunc();
1135 //-----------------------------------------------------------------------
1136 void Root::unloadPlugin(const String& pluginName)
1138 PluginLibList::iterator i;
1140 for (i = mPluginLibs.begin(); i != mPluginLibs.end(); ++i)
1142 if ((*i)->getName() == pluginName)
1144 // Call plugin shutdown
1145 DLL_STOP_PLUGIN pFunc = (DLL_STOP_PLUGIN)(*i)->getSymbol("dllStopPlugin");
1146 // this must call uninstallPlugin
1147 pFunc();
1148 // Unload library (destroyed by DynLibManager)
1149 DynLibManager::getSingleton().unload(*i);
1150 mPluginLibs.erase(i);
1151 return;
1156 //-----------------------------------------------------------------------
1157 Timer* Root::getTimer(void)
1159 return mTimer;
1161 //-----------------------------------------------------------------------
1162 void Root::oneTimePostWindowInit(void)
1164 if (!mFirstTimePostWindowInit)
1166 // Background loader
1167 mResourceBackgroundQueue->initialise();
1168 // Initialise material manager
1169 mMaterialManager->initialise();
1170 // Init particle systems manager
1171 mParticleManager->_initialise();
1172 // Init mesh manager
1173 MeshManager::getSingleton()._initialise();
1174 // Init plugins - after window creation so rsys resources available
1175 initialisePlugins();
1176 mFirstTimePostWindowInit = true;
1180 //-----------------------------------------------------------------------
1181 bool Root::_updateAllRenderTargets(void)
1183 // update all targets but don't swap buffers
1184 mActiveRenderer->_updateAllRenderTargets(false);
1185 // give client app opportunity to use queued GPU time
1186 bool ret = _fireFrameRenderingQueued();
1187 // block for final swap
1188 mActiveRenderer->_swapAllRenderTargetBuffers(mActiveRenderer->getWaitForVerticalBlank());
1190 // This belongs here, as all render targets must be updated before events are
1191 // triggered, otherwise targets could be mismatched. This could produce artifacts,
1192 // for instance, with shadows.
1193 for (SceneManagerEnumerator::SceneManagerIterator it = getSceneManagerIterator(); it.hasMoreElements(); it.moveNext())
1194 it.peekNextValue()->_handleLodEvents();
1196 return ret;
1198 //---------------------------------------------------------------------
1199 bool Root::_updateAllRenderTargets(FrameEvent& evt)
1201 // update all targets but don't swap buffers
1202 mActiveRenderer->_updateAllRenderTargets(false);
1203 // give client app opportunity to use queued GPU time
1204 bool ret = _fireFrameRenderingQueued(evt);
1205 // block for final swap
1206 mActiveRenderer->_swapAllRenderTargetBuffers(mActiveRenderer->getWaitForVerticalBlank());
1208 // This belongs here, as all render targets must be updated before events are
1209 // triggered, otherwise targets could be mismatched. This could produce artifacts,
1210 // for instance, with shadows.
1211 for (SceneManagerEnumerator::SceneManagerIterator it = getSceneManagerIterator(); it.hasMoreElements(); it.moveNext())
1212 it.peekNextValue()->_handleLodEvents();
1214 return ret;
1216 //-----------------------------------------------------------------------
1217 void Root::clearEventTimes(void)
1219 // Clear event times
1220 for(int i=0; i<FETT_COUNT; ++i)
1221 mEventTimes[i].clear();
1223 //---------------------------------------------------------------------
1224 void Root::addMovableObjectFactory(MovableObjectFactory* fact,
1225 bool overrideExisting)
1227 MovableObjectFactoryMap::iterator facti = mMovableObjectFactoryMap.find(
1228 fact->getType());
1229 if (!overrideExisting && facti != mMovableObjectFactoryMap.end())
1231 OGRE_EXCEPT(Exception::ERR_DUPLICATE_ITEM,
1232 "A factory of type '" + fact->getType() + "' already exists.",
1233 "Root::addMovableObjectFactory");
1236 if (fact->requestTypeFlags())
1238 if (facti != mMovableObjectFactoryMap.end() && facti->second->requestTypeFlags())
1240 // Copy type flags from the factory we're replacing
1241 fact->_notifyTypeFlags(facti->second->getTypeFlags());
1243 else
1245 // Allocate new
1246 fact->_notifyTypeFlags(_allocateNextMovableObjectTypeFlag());
1250 // Save
1251 mMovableObjectFactoryMap[fact->getType()] = fact;
1253 LogManager::getSingleton().logMessage("MovableObjectFactory for type '" +
1254 fact->getType() + "' registered.");
1257 //---------------------------------------------------------------------
1258 bool Root::hasMovableObjectFactory(const String& typeName) const
1260 return !(mMovableObjectFactoryMap.find(typeName) == mMovableObjectFactoryMap.end());
1262 //---------------------------------------------------------------------
1263 MovableObjectFactory* Root::getMovableObjectFactory(const String& typeName)
1265 MovableObjectFactoryMap::iterator i =
1266 mMovableObjectFactoryMap.find(typeName);
1267 if (i == mMovableObjectFactoryMap.end())
1269 OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND,
1270 "MovableObjectFactory of type " + typeName + " does not exist",
1271 "Root::getMovableObjectFactory");
1273 return i->second;
1275 //---------------------------------------------------------------------
1276 uint32 Root::_allocateNextMovableObjectTypeFlag(void)
1278 if (mNextMovableObjectTypeFlag == SceneManager::USER_TYPE_MASK_LIMIT)
1280 OGRE_EXCEPT(Exception::ERR_DUPLICATE_ITEM,
1281 "Cannot allocate a type flag since "
1282 "all the available flags have been used.",
1283 "Root::_allocateNextMovableObjectTypeFlag");
1286 uint32 ret = mNextMovableObjectTypeFlag;
1287 mNextMovableObjectTypeFlag <<= 1;
1288 return ret;
1291 //---------------------------------------------------------------------
1292 void Root::removeMovableObjectFactory(MovableObjectFactory* fact)
1294 MovableObjectFactoryMap::iterator i = mMovableObjectFactoryMap.find(
1295 fact->getType());
1296 if (i != mMovableObjectFactoryMap.end())
1298 mMovableObjectFactoryMap.erase(i);
1302 //---------------------------------------------------------------------
1303 Root::MovableObjectFactoryIterator
1304 Root::getMovableObjectFactoryIterator(void) const
1306 return MovableObjectFactoryIterator(mMovableObjectFactoryMap.begin(),
1307 mMovableObjectFactoryMap.end());
1310 //---------------------------------------------------------------------
1311 RenderQueueInvocationSequence* Root::createRenderQueueInvocationSequence(
1312 const String& name)
1314 RenderQueueInvocationSequenceMap::iterator i =
1315 mRQSequenceMap.find(name);
1316 if (i != mRQSequenceMap.end())
1318 OGRE_EXCEPT(Exception::ERR_DUPLICATE_ITEM,
1319 "RenderQueueInvocationSequence with the name " + name +
1320 " already exists.",
1321 "Root::createRenderQueueInvocationSequence");
1323 RenderQueueInvocationSequence* ret = OGRE_NEW RenderQueueInvocationSequence(name);
1324 mRQSequenceMap[name] = ret;
1325 return ret;
1327 //---------------------------------------------------------------------
1328 RenderQueueInvocationSequence* Root::getRenderQueueInvocationSequence(
1329 const String& name)
1331 RenderQueueInvocationSequenceMap::iterator i =
1332 mRQSequenceMap.find(name);
1333 if (i == mRQSequenceMap.end())
1335 OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND,
1336 "RenderQueueInvocationSequence with the name " + name +
1337 " not found.",
1338 "Root::getRenderQueueInvocationSequence");
1340 return i->second;
1342 //---------------------------------------------------------------------
1343 void Root::destroyRenderQueueInvocationSequence(
1344 const String& name)
1346 RenderQueueInvocationSequenceMap::iterator i =
1347 mRQSequenceMap.find(name);
1348 if (i != mRQSequenceMap.end())
1350 OGRE_DELETE i->second;
1351 mRQSequenceMap.erase(i);
1354 //---------------------------------------------------------------------
1355 void Root::destroyAllRenderQueueInvocationSequences(void)
1357 for (RenderQueueInvocationSequenceMap::iterator i = mRQSequenceMap.begin();
1358 i != mRQSequenceMap.end(); ++i)
1360 OGRE_DELETE i->second;
1362 mRQSequenceMap.clear();
1365 //---------------------------------------------------------------------
1366 unsigned int Root::getDisplayMonitorCount() const
1368 if (!mActiveRenderer)
1370 OGRE_EXCEPT(Exception::ERR_INVALID_STATE,
1371 "Cannot get display monitor count "
1372 "No render system has been selected.", "Root::getDisplayMonitorCount");
1375 return mActiveRenderer->getDisplayMonitorCount();
1378 //---------------------------------------------------------------------