Spinning Topp Logo BlackTopp Studios
inc
entresol.cpp
1 // © Copyright 2010 - 2016 BlackTopp Studios Inc.
2 /* This file is part of The Mezzanine Engine.
3 
4  The Mezzanine Engine is free software: you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation, either version 3 of the License, or
7  (at your option) any later version.
8 
9  The Mezzanine Engine is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You should have received a copy of the GNU General Public License
15  along with The Mezzanine Engine. If not, see <http://www.gnu.org/licenses/>.
16 */
17 /* The original authors have included a copy of the license specified above in the
18  'Docs' folder. See 'gpl.txt'
19 */
20 /* We welcome the use of the Mezzanine engine to anyone, including companies who wish to
21  Build professional software and charge for their product.
22 
23  However there are some practical restrictions, so if your project involves
24  any of the following you should contact us and we will try to work something
25  out:
26  - DRM or Copy Protection of any kind(except Copyrights)
27  - Software Patents You Do Not Wish to Freely License
28  - Any Kind of Linking to Non-GPL licensed Works
29  - Are Currently In Violation of Another Copyright Holder's GPL License
30  - If You want to change our code and not add a few hundred MB of stuff to
31  your distribution
32 
33  These and other limitations could cause serious legal problems if you ignore
34  them, so it is best to simply contact us or the Free Software Foundation, if
35  you have any questions.
36 
37  Joseph Toppi - toppij@gmail.com
38  John Blackwood - makoenergy02@gmail.com
39 */
40 #ifndef _entresol_cpp
41 #define _entresol_cpp
42 ///////////////////////////////////////////////////////////////////////////////
43 //The Entresol that integrates everything
44 //
45 //This is where all the calls to the the underlying libraries should be from.
46 //Entresol is an abstraction layer to all of the non-ui libraries. The ui
47 //layers wx and ogre both have their own main loops, so it is almost mandatory
48 //for other code to interact with those libraries directly.
49 ///////////////////////////////////////////////////////////////////////////////
50 //Includes
51 
52 #include "entresol.h"
53 #include "entresolmanager.h"
54 #include "world.h"
55 
56 // Manager Includes
57 #include "eventmanager.h"
58 #include "Graphics/graphicsmanager.h"
59 #include "Graphics/meshmanager.h"
60 #include "Graphics/scenemanager.h"
61 #include "Graphics/texturemanager.h"
62 #include "Input/inputmanager.h"
63 #include "Network/networkmanager.h"
64 #include "Physics/collisionshapemanager.h"
65 #include "Physics/physicsmanager.h"
67 #include "UI/uimanager.h"
68 
69 #include "Resource/filestream.h"
70 
71 // Enabled implementation includes
72 #ifdef ENABLE_OALS_AUDIO_IMPLEMENTATION
73  #include "Audio/OALS/oalsaudiomanagerfactory.h"
74 #endif // ENABLE_OALS_AUDIO_IMPLEMENTATION
75 
76 #ifdef MEZZLUA51
78 #endif // MEZZLUA51
79 
80 
81 //#include "OgreBspSceneManagerPlugin.h"
82 //#include "OgreCgPlugin.h"
83 //#include "OgreOctreePlugin.h"
84 //#include "OgreOctreeZonePlugin.h"
85 #include "OgreParticleFXPlugin.h"
86 //#include "OgrePCZPlugin.h"
87 
88 #include <SDL.h>
89 #include <Ogre.h>
90 #include <btBulletDynamicsCommon.h>
91 
92 #include <sstream>
93 #include <string>
94 #include <cassert>
95 
96 using namespace std;
97 
98 namespace Mezzanine
99 {
100  template<> Entresol* Singleton<Entresol>::SingletonPtr = NULL;
101  Entresol::ManagerFactoryMap Entresol::ManagerFactories;
102 
103  ///////////////////////////////////////////////////////////////////////////////
104  // Entresol Constructors and Destructors
105 
106  /// @todo In the Entrosol, remove all references to a plugins file
107  Entresol::Entresol()
108  {
109  ManagerVec temp;
110  this->Construct(".","Mezzanine.log",temp);
111  }
112 
113  Entresol::Entresol(const String& EngineDataPath, const Resource::ArchiveType ArchType, const String& InitializerFile)
114  {
115  if( String::npos != InitializerFile.find(".mxi") ) {
116  this->ConstructFromXML(EngineDataPath, ArchType, InitializerFile);
117  }else{
118  MEZZ_EXCEPTION(ExceptionBase::NOT_IMPLEMENTED_EXCEPTION,"Attempting to initialze Mezzanine from an unsupported file type.");
119  }
120  }
121 
122  Entresol::Entresol(ManagerFactoryVec& CustomFactories, const String& EngineDataPath, const Resource::ArchiveType ArchType, const String& InitializerFile)
123  {
124  for(ManagerFactoryVec::iterator it = CustomFactories.begin(); it != CustomFactories.end(); ++it)
125  {
126  this->AddManagerFactory( (*it) );
127  }
128 
129  if( String::npos != InitializerFile.find(".mxi") ) {
130  this->ConstructFromXML(EngineDataPath, ArchType, InitializerFile);
131  }else{
132  MEZZ_EXCEPTION(ExceptionBase::NOT_IMPLEMENTED_EXCEPTION,"Attempting to initialze Mezzanine from an unsupported file type.");
133  }
134  }
135 
136  Entresol::Entresol(const String& EngineDataPath, const String& LogFileName)
137  {
138  ManagerVec temp;
139  this->Construct(EngineDataPath, LogFileName, temp);
140  }
141 
142  Entresol::Entresol(const String& EngineDataPath, const String& LogFileName, const ManagerVec& ManagersToBeAdded)
143  {
144  this->Construct(EngineDataPath, LogFileName, ManagersToBeAdded);
145  }
146 
147  Entresol::~Entresol()
148  {
149  this->Deinitialize();
150 
151  this->DestroyAllWorlds();
152  World::DestroyAllManagerFactories();
153  this->DestroyAllManagers();
154  Entresol::DestroyAllManagerFactories();
155  this->DestroyLogging();
156 
157  this->DestroyOgre();
158  this->DestroySDL();
159  }
160 
161  ///////////////////////////////////////////////////////////////////////////////
162  // Internal Initialization and Deinitialization Methods
163 
164  void Entresol::Construct(const String& EngineDataPath, const String& GraphicsLogFileName, const ManagerVec& ManagersToBeAdded)
165  {
166  //Add default manager factories
167  Entresol::AddAllEngineDefaultManagerFactories();
168  World::AddAllEngineDefaultManagerFactories();
169  //Set some sane Defaults for some values
170  this->ManualLoopBreak = 0;
171 
172  this->SetupOgre();
173  this->SetupLogging(GraphicsLogFileName);
174 
175  // Load the necessary plugins.
176  SubSystemParticleFXPlugin = new Ogre::ParticleFXPlugin();
177  Ogre::Root::getSingleton().installPlugin(SubSystemParticleFXPlugin);
178 
179  //add each manager that was passed in to the manager list
180  for( ConstManagerVecIterator iter = ManagersToBeAdded.begin() ; iter!= ManagersToBeAdded.end() ; iter++ )
181  { this->AddManager(*iter); }
182 
183  //Dummy param list so we can use the auto-added manager types if needed
184  NameValuePairList Params;
185  // Create and add any managers that have not been taken care of yet.
186  if( this->GetManager(ManagerBase::MT_ResourceManager) == 0 ) {
187  Params.push_back( std::pair<String,String>("EngineDataPath",EngineDataPath) );
188  this->CreateManager( "DefaultResourceManager", Params );
189  Params.clear();
190  }
191  if( this->GetManager(ManagerBase::MT_GraphicsManager) == 0 ) {
192  this->CreateManager( "DefaultGraphicsManager", Params );
193  }
194  if( this->GetManager(ManagerBase::MT_EventManager) == 0 ) {
195  this->CreateManager( "DefaultEventManager", Params );
196  }
197  if( this->GetManager(ManagerBase::MT_InputManager) == 0 ) {
198  this->CreateManager( "DefaultInputManager", Params );
199  }
200  if( this->GetManager(ManagerBase::MT_UIManager) == 0 ) {
201  this->CreateManager( "DefaultUIManager", Params );
202  }
203  if( this->GetManager(ManagerBase::MT_MeshManager) == 0 ) {
204  this->CreateManager( "DefaultMeshManager", Params );
205  }
206  if( this->GetManager(ManagerBase::MT_TextureManager) == 0 ) {
207  this->CreateManager( "DefaultTextureManager", Params );
208  }
209  if( this->GetManager(ManagerBase::MT_CollisionShapeManager) == 0 ) {
210  this->CreateManager( "DefaultCollisionShapeManager", Params );
211  }
212 
213  #ifdef ENABLE_OALS_AUDIO_IMPLEMENTATION
214  if( this->GetManager(ManagerBase::MT_AudioManager) == 0 ) {
215  this->CreateManager("OALSAudioManager",Params);
216  }
217  #endif //ENABLE_OALS_AUDIO_IMPLEMENTATION
218 
219  // This Tests various assumptions about the way the platform works, and will not act
220  this->SanityChecks();
221  }
222 
223  void Entresol::ConstructFromXML(const String& EngineDataPath, const Resource::ArchiveType ArchType, const String& InitializerFile)
224  {
225  //Add default manager factories
226  Entresol::AddAllEngineDefaultManagerFactories();
227  World::AddAllEngineDefaultManagerFactories();
228  //Set some sane Defaults for some values.
229  this->ManualLoopBreak = false;
230 
231  // Create Ogre.
232  this->SetupOgre();
233 
234  // Load the necessary plugins.
235  this->SubSystemParticleFXPlugin = new Ogre::ParticleFXPlugin();
236  Ogre::Root::getSingleton().installPlugin(this->SubSystemParticleFXPlugin);
237 
238  // Set up the data we'll be populating.
239  XML::Attribute CurrAttrib;
240  String GUIInit, ResourceInit, PluginsInit, LogFileName;
241  String PluginExtension, PluginPath;
242 
243  // Create or set the resource manager.
244  /// @todo This currently forces our default resource manager to be constructed, which isn't in line with our factory/initiailzation design.
245  /// This should be addressed somehow.
246  if( Resource::ResourceManager::SingletonValid() ) {
247  this->AddManager( Resource::ResourceManager::GetSingletonPtr() );
248  }else{
249  this->AddManager( new Resource::ResourceManager(EngineDataPath, ArchType) );
250  }
251 
252  // Open and load the initializer doc.
253  Resource::ResourceManager* ResourceMan = static_cast<Resource::ResourceManager*>( this->GetManager(ManagerBase::MT_ResourceManager) );
254  Resource::FileStream InitStream(InitializerFile,EngineDataPath);
255  XML::Document InitDoc;
256  XML::ParseResult DocResult = InitDoc.Load(InitStream);
257  if( DocResult.Status != XML::StatusOk ) {
258  StringStream ExceptionStream;
259  ExceptionStream << "Failed to parse XML file \"" << InitializerFile << "\".";
260  MEZZ_EXCEPTION(ExceptionBase::SYNTAX_ERROR_EXCEPTION_XML,ExceptionStream.str());
261  }
262  XML::Node InitRoot = InitDoc.GetChild("InitializerRoot");
263  if( InitRoot.Empty() ) {
264  StringStream ExceptionStream;
265  ExceptionStream << "Failed to find expected Root node in \"" << InitializerFile << "\".";
266  MEZZ_EXCEPTION(ExceptionBase::SYNTAX_ERROR_EXCEPTION_XML,ExceptionStream.str());
267  }
268 
269  // Get the world settings and set them.
270  XML::Node CoreConfig = InitRoot.GetChild("CoreConfig");
271  for( XML::NodeIterator SetIt = CoreConfig.begin() ; SetIt != CoreConfig.end() ; ++SetIt )
272  {
273  String SecName = (*SetIt).Name();
274  if( "FrameSettings" == SecName ) {
275  CurrAttrib = (*SetIt).GetAttribute("TargetFrameRate");
276  if(CurrAttrib.Empty()) {
277  CurrAttrib = (*SetIt).GetAttribute("TargetFrameTime");
278  if(!CurrAttrib.Empty())
279  SetTargetFrameTimeMicroseconds(CurrAttrib.AsWhole());
280  }else{
281  this->SetTargetFrameRate(CurrAttrib.AsWhole());
282  }
283  }else{
284  MEZZ_EXCEPTION(ExceptionBase::SYNTAX_ERROR_EXCEPTION_XML,String("Unknown WorldSetting ")+SecName);
285  }
286 
287  }
288 
289  this->SetupLogging(LogFileName);
290 
291  // Get the other initializer files we'll be using, since we'll need the plugins initializer.
292  XML::Node InitFiles = InitRoot.GetChild("OtherInitializers");
293  for( XML::NodeIterator InitIt = InitFiles.begin() ; InitIt != InitFiles.end() ; ++InitIt )
294  {
295  String InitFileName = (*InitIt).Name();
296  if( "PluginInit" == InitFileName ) {
297  CurrAttrib = (*InitIt).GetAttribute("FileName");
298  if(!CurrAttrib.Empty())
299  PluginsInit = CurrAttrib.AsString();
300  }else if( "ResourceInit" == InitFileName ) {
301  CurrAttrib = (*InitIt).GetAttribute("FileName");
302  if(!CurrAttrib.Empty())
303  ResourceInit = CurrAttrib.AsString();
304  }else if( "GUIInit" == InitFileName ) {
305  CurrAttrib = (*InitIt).GetAttribute("FileName");
306  if(!CurrAttrib.Empty())
307  GUIInit = CurrAttrib.AsString();
308  }
309  }
310 
311  // Create the requested managers and set their necessary values.
312  XML::Node Managers = InitRoot.GetChild("Managers");
313  for( XML::NodeIterator ManIt = Managers.begin() ; ManIt != Managers.end() ; ++ManIt )
314  {
315  this->CreateManager( (*ManIt).Name(), (*ManIt) );
316  }
317 
318  // Load additional resource groups
319  if( !ResourceInit.empty() ) {
320  /// @todo Replace this stack allocated stream for one initialized from the Resource Manager, after the system is ready.
321  Resource::FileStream ResourceStream(ResourceInit,EngineDataPath);
322  XML::Document ResourceDoc;
323  ResourceDoc.Load(ResourceStream);
324  // Get an iterator to the first resource group node, and declare them all.
325  XML::Node ResourceLocations = ResourceDoc.GetChild("ResourceLocations");
326  for( XML::NodeIterator GroupIt = ResourceLocations.begin() ; GroupIt != ResourceLocations.end() ; ++GroupIt )
327  {
328  String GroupName, GroupPath;
329  Resource::ArchiveType GroupType = Resource::AT_Invalid;
330  Boole GroupRecursive = false;
331  // Get the group path
332  CurrAttrib = (*GroupIt).GetAttribute("GroupPath");
333  if(!CurrAttrib.Empty())
334  GroupPath = CurrAttrib.AsString();
335  // Get the group type
336  CurrAttrib = (*GroupIt).GetAttribute("GroupType");
337  if(!CurrAttrib.Empty())
338  GroupType = Resource::ResourceManager::GetArchiveTypeFromString(CurrAttrib.AsString());
339  // Get the group name
340  CurrAttrib = (*GroupIt).GetAttribute("GroupName");
341  if(!CurrAttrib.Empty())
342  GroupName = CurrAttrib.AsString();
343  // Get whether this is recursive
344  CurrAttrib = (*GroupIt).GetAttribute("Recursive");
345  if(!CurrAttrib.Empty())
346  GroupRecursive = StringTools::ConvertToBool(CurrAttrib.AsString());
347  // Finally create the resource location.
348  ResourceMan->AddAssetLocation(GroupPath,GroupType,GroupName,GroupRecursive);
349  }
350  // Get what resource groups should be initialized.
351  XML::Node InitGroups = ResourceDoc.GetChild("InitGroups");
352  for( XML::NodeIterator InitIt = InitGroups.begin() ; InitIt != InitGroups.end() ; ++InitIt )
353  {
354  String GroupName;
355  CurrAttrib = (*InitIt).GetAttribute("GroupName");
356  if(!CurrAttrib.Empty())
357  GroupName = CurrAttrib.AsString();
358  ResourceMan->InitAssetGroup(GroupName);
359  }
360  }
361 
362  // Configure the UI
363  if(!GUIInit.empty()) {
364  /// @todo This is currently not implemented.
365  }
366 
367  this->SanityChecks();
368  }
369 
370  void Entresol::SetupOgre()
371  {
372  if( Ogre::Root::getSingletonPtr() == NULL ) {
373  Ogre::Root* OgreCore = new Ogre::Root("","","");
374  // Sanity checks for Ogre here? It's a singleton so don't need to worry about storing the pointer.
375  }
376  }
377 
378  void Entresol::DestroyOgre()
379  {
380  #ifdef MEZZ_LINUX
381  //assert( !( SDL_WasInit(0) | SDL_INIT_VIDEO ) && "SDL already shut down. SDL Shutdown forces x11 unload, which Ogre needs for it's shutdown." );
382  #endif
383  if( Ogre::Root::getSingletonPtr() != NULL ) {
384  delete Ogre::Root::getSingletonPtr();
385  }
386  if( this->SubSystemParticleFXPlugin != NULL ) {
387  delete this->SubSystemParticleFXPlugin;
388  }
389  }
390 
391  void Entresol::DestroySDL()
392  {
393  #ifdef MEZZ_LINUX
394  // Fail is SDL is de-intialized before Ogre, but only if Ogre has been initialized.
395  assert( NULL == Ogre::Root::getSingletonPtr() // ( (SDL_WasInit(0) | SDL_INIT_VIDEO)
396  && "SDL already shut down. SDL Shutdown forces x11 unload, which Ogre needs for it's shutdown." );
397  #endif
398  SDL_Quit();
399  }
400 
401  void Entresol::SetupLogging(const String& OgreLogFileName)
402  {
403  this->SetupOgreLogging(OgreLogFileName);
404  this->SetupInternalLogging();
405  }
406 
407  void Entresol::SetupOgreLogging(const String& OgreLogFileName)
408  {
409  /// @todo Allow the FrameScheduler Log target to be inspected and changed here
410  Ogre::LogManager* OgreLogs = Ogre::LogManager::getSingletonPtr();
411  if( NULL == OgreLogs ) {
412  OgreLogs = new Ogre::LogManager();
413  }
414 
415  if(!OgreLogFileName.empty()) {
416  OgreLogs->createLog(String("Graphics")+OgreLogFileName,true,true,true);
417  }else{
418  OgreLogs->createLog("GraphicsMezzanine.log",true,true,true);
419  }
420  }
421 
422  void Entresol::SetupInternalLogging()
423  {
424  this->Aggregator = new Threading::LogAggregator();
425  this->Aggregator->SetAggregationTarget(&WorkScheduler);
426  this->WorkScheduler.AddWorkUnitMain(Aggregator, "LogAggregator");
427  }
428 
429  void Entresol::DestroyLogging()
430  {
431  // One last aggregation
432  /*Threading::DefaultThreadSpecificStorage::Type LogResource(&this->WorkScheduler);
433  this->Aggregator->DoWork(LogResource);// */
434  Threading::DefaultThreadSpecificStorage::Type* LogResource = this->WorkScheduler.GetThreadResource();
435  this->WorkScheduler.GetLog() << LogResource->GetUsableLogger().str();
436  LogResource->SwapAllBufferedResources();
437  this->WorkScheduler.GetLog() << LogResource->GetUsableLogger().str();
438  //this->WorkScheduler.ForceLogFlush();
439 
440  this->WorkScheduler.RemoveWorkUnitMain(Aggregator);
441  delete this->Aggregator;
442  }
443 
444  void Entresol::SanityChecks()
445  {
446  // Crossplatform::WaitMilliseconds(1500);
447  //Perform a Test that only needs to be done once for the SDL/userinputevent system.`
448  /*Log("Verifying size of userinput events:");
449  Log(sizeof(Input::InputCode));
450  Log(sizeof(SDL_Scancode));
451  Log(sizeof(int));// */
452  if(sizeof(Input::InputCode) != sizeof(SDL_Scancode)) {
453  MEZZ_EXCEPTION(ExceptionBase::INVALID_STATE_EXCEPTION,"User input subsystem Event Sizes Don't match, userinput subsystem will go be buggier than a highschool fortran class.");
454  }
455 
456  if(sizeof(Input::InputCode) != sizeof(int)) {
457  MEZZ_EXCEPTION(ExceptionBase::INVALID_STATE_EXCEPTION,"Internal User input subsystem Event Sizes Don't match, userinput subsystem cannot function.");
458  }
459  }
460 
461  Boole Entresol::VerifyManagerInitializations()
462  {
463  std::vector<String> ManagerNames;
464  for( ManagerIterator Iter=this->ManagerList.begin(); Iter!=this->ManagerList.end(); ++Iter )
465  {
466  if(!(*Iter)->IsInitialized()) {
467  ManagerNames.push_back( (*Iter)->GetInterfaceTypeAsString() );
468  }
469  }
470 
471  if( ManagerNames.empty() ) {
472  return true;
473  }else{
474  StringStream ExceptionStream;
475  if( 1 == ManagerNames.size() ) {
476  ExceptionStream << "Manager: ";
477  ExceptionStream << ManagerNames.at(0);
478  ExceptionStream << "is not initialized. All managers need to be initiailzed when entering the main loop.";
479  }else{
480  ExceptionStream << "Managers: ";
481  for( std::vector<String>::iterator Iter = ManagerNames.begin() ; Iter != ManagerNames.end() ; ++Iter )
482  {
483  ExceptionStream << (*Iter) << ", ";
484  }
485  ExceptionStream << "are not initialized. All managers need to be initiailzed when entering the main loop.";
486  }
487  MEZZ_EXCEPTION(ExceptionBase::INVALID_STATE_EXCEPTION,ExceptionStream.str());
488  return false;
489  }
490  }
491 
492  ///////////////////////////////////////////////////////////////////////////////
493  // Utility
494 
495  Threading::FrameScheduler& Entresol::GetScheduler()
496  { return this->WorkScheduler; }
497 
498  ///////////////////////////////////////////////////////////////////////////////
499  // Initialization and Deinitialization
500 
501  void Entresol::Initialize(const Boole InitWorlds)
502  {
503  Graphics::GraphicsManager::GetSingletonPtr()->Initialize();
504  for( ManagerIterator Iter = this->ManagerList.begin() ; Iter != this->ManagerList.end() ; ++Iter )
505  {
506  StringStream InitStream;
507  InitStream << "Initializing " << (*Iter)->GetImplementationTypeName() << " as " << (*Iter)->GetInterfaceTypeAsString() << "." << endl;
508  this->_Log( InitStream.str() );
509  if( (*Iter)->GetInterfaceType() != ManagerBase::MT_GraphicsManager ) {
510  (*Iter)->Initialize();
511  }
512  }
513  // Worlds in part depend on Entresol manager functionality, so they must be second.
514  if( InitWorlds ) {
515  for( WorldIterator WorldIt = this->Worlds.begin() ; WorldIt != this->Worlds.end() ; ++WorldIt )
516  {
517  (*WorldIt)->Initialize();
518  }
519  }
520  }
521 
522  void Entresol::Deinitialize()
523  {
524  // Deinit the Worlds first due to dependencies.
525  for( WorldIterator WorldIt = this->Worlds.begin() ; WorldIt != this->Worlds.end() ; ++WorldIt )
526  {
527  (*WorldIt)->Deinitialize();
528  }
529  // Now the Entresol.
530  for( ManagerIterator Iter = this->ManagerList.begin() ; Iter != this->ManagerList.end() ; ++Iter )
531  {
532  StringStream DeinitStream;
533  DeinitStream << "Deinitializing " << (*Iter)->GetImplementationTypeName() << " as " << (*Iter)->GetInterfaceTypeAsString() << "." << endl;
534  this->_Log( DeinitStream.str() );
535  (*Iter)->Deinitialize();
536  }
537  }
538 
539  void Entresol::PreMainLoopInit()
540  {
541  this->VerifyManagerInitializations();
542 
543  for( WorldIterator it = this->Worlds.begin(); it != this->Worlds.end(); it++ )
544  { (*it)->PreMainLoopInit(); }
545  }
546 
547  ///////////////////////////////////////////////////////////////////////////////
548  // MainLoop
549 
550  void Entresol::MainLoop()
551  {
552  this->PreMainLoopInit();
553 
554  while( !this->ManualLoopBreak )
555  { this->DoOneFrame(); } //Main loop
556 
557  this->ManualLoopBreak = 0;
558  }
559 
560  void Entresol::DoOneFrame()
561  {
562  #ifdef MEZZDEBUG
563  WorkScheduler.GetLog() << "<FrameCounterStart Frame=\"" << WorkScheduler.GetFrameCount() << "\" Time=\"" << GetTimeStamp()<< "\" />" << endl;
564  #endif
565  WorkScheduler.RunAllMonopolies(); //1
566  WorkScheduler.CreateThreads(); //2
567  WorkScheduler.RunMainThreadWork();//3
568  WorkScheduler.JoinAllThreads(); //4
569  WorkScheduler.ResetAllWorkUnits();//5
570  #ifdef MEZZDEBUG
571  WorkScheduler.GetLog() << "<FrameCounterPrePause Frame=\"" << WorkScheduler.GetFrameCount() << "\" Time=\"" << GetTimeStamp()<< "\" />" << endl;
572  #endif
573  WorkScheduler.WaitUntilNextFrame(); //6
574  #ifdef MEZZDEBUG
575  WorkScheduler.GetLog() << "<FrameCounterEnd Frame=\"" << WorkScheduler.GetFrameCount() << "\" Time=\"" << GetTimeStamp()<< "\" />" << endl;
576  #endif
577  }
578 
579  void Entresol::BreakMainLoop(Boole Break)
580  {
581  if(Break) {
582  while( !this->ManualLoopBreak )
583  { Threading::AtomicCompareAndSwap32(&this->ManualLoopBreak,0,1); }
584  }else{
585  while( this->ManualLoopBreak )
586  { Threading::AtomicCompareAndSwap32(&this->ManualLoopBreak,1,0); }
587  }
588  }
589 
590  Whole Entresol::GetFrameCount() const
591  { return this->WorkScheduler.GetFrameCount(); }
592 
593  ///////////////////////////////////////////////////////////////////////////////
594  // Simple get and Set functions
595  ///////////////////////////////////////
596 
597  void Entresol::SetTargetFrameRate(const Whole NewFrameRate)
598  { this->SetTargetFrameTimeMicroseconds( Real(1000000) / Real(NewFrameRate) ); }
599 
600  void Entresol::SetTargetFrameTimeMilliseconds(const Whole NewTargetTime)
601  { this->SetTargetFrameTimeMicroseconds( NewTargetTime * 1000 ); }
602 
603  void Entresol::SetTargetFrameTimeMicroseconds(const Whole NewTargetTime)
604  { this->WorkScheduler.SetFrameLength(NewTargetTime); }
605 
606  Whole Entresol::GetTargetFrameTimeMilliseconds() const
607  { return this->WorkScheduler.GetFrameLength()*0.001; }
608 
609  Whole Entresol::GetTargetFrameTimeMicroseconds() const
610  { return this->WorkScheduler.GetFrameLength(); }
611 
612  Whole Entresol::GetLastFrameTimeMilliseconds() const
613  { return this->WorkScheduler.GetLastFrameTime()*0.001; }
614 
615  Whole Entresol::GetLastFrameTimeMicroseconds() const
616  { return this->WorkScheduler.GetLastFrameTime(); }
617 
618  ///////////////////////////////////////////////////////////////////////////////
619  // Factory Management
620 
621  void Entresol::AddManagerFactory(EntresolManagerFactory* ToBeAdded)
622  {
623  Entresol::ManagerFactories.insert(std::pair<String,EntresolManagerFactory*>(ToBeAdded->GetManagerImplName(),ToBeAdded));
624  }
625 
626  void Entresol::RemoveManagerFactory(EntresolManagerFactory* ToBeRemoved)
627  {
628  Entresol::RemoveManagerFactory(ToBeRemoved->GetManagerImplName());
629  }
630 
631  void Entresol::RemoveManagerFactory(const String& ImplName)
632  {
633  ManagerFactoryIterator ManIt = Entresol::ManagerFactories.find(ImplName);
634  if( ManIt != Entresol::ManagerFactories.end() )
635  { Entresol::ManagerFactories.erase(ManIt); }
636  }
637 
638  void Entresol::DestroyManagerFactory(EntresolManagerFactory* ToBeRemoved)
639  {
640  Entresol::DestroyManagerFactory(ToBeRemoved->GetManagerImplName());
641  }
642 
643  void Entresol::DestroyManagerFactory(const String& ImplName)
644  {
645  ManagerFactoryIterator ManIt = Entresol::ManagerFactories.find(ImplName);
646  if( ManIt != Entresol::ManagerFactories.end() ) {
647  delete ManIt->second;
648  Entresol::ManagerFactories.erase(ManIt);
649  }
650  }
651 
652  void Entresol::DestroyAllManagerFactories()
653  {
654  for( ManagerFactoryIterator ManIt = Entresol::ManagerFactories.begin() ; ManIt != Entresol::ManagerFactories.end() ; ++ManIt )
655  { delete (*ManIt).second; }
656  Entresol::ManagerFactories.clear();
657  }
658 
659  void Entresol::AddAllEngineDefaultManagerFactories()
660  {
662  //DefaultCollisionShapeManager
663  ManIt = Entresol::ManagerFactories.find("DefaultCollisionShapeManager");
664  if( ManIt == Entresol::ManagerFactories.end() ) Entresol::AddManagerFactory(new Physics::DefaultCollisionShapeManagerFactory());
665  //DefaultEventManager
666  ManIt = Entresol::ManagerFactories.find("DefaultEventManager");
667  if( ManIt == Entresol::ManagerFactories.end() ) Entresol::AddManagerFactory(new DefaultEventManagerFactory());
668  //DefaultGraphicsManager
669  ManIt = Entresol::ManagerFactories.find("DefaultGraphicsManager");
670  if( ManIt == Entresol::ManagerFactories.end() ) Entresol::AddManagerFactory(new Graphics::DefaultGraphicsManagerFactory());
671  //DefaultInputManager
672  ManIt = Entresol::ManagerFactories.find("DefaultInputManager");
673  if( ManIt == Entresol::ManagerFactories.end() ) Entresol::AddManagerFactory(new Input::DefaultInputManagerFactory());
674  //DefaultMeshManager
675  ManIt = Entresol::ManagerFactories.find("DefaultMeshManager");
676  if( ManIt == Entresol::ManagerFactories.end() ) Entresol::AddManagerFactory(new Graphics::DefaultMeshManagerFactory());
677  //DefaultResourceManager
678  ManIt = Entresol::ManagerFactories.find("DefaultResourceManager");
679  if( ManIt == Entresol::ManagerFactories.end() ) Entresol::AddManagerFactory(new Resource::DefaultResourceManagerFactory());
680  //DefaultTextureManager
681  ManIt = Entresol::ManagerFactories.find("DefaultTextureManager");
682  if( ManIt == Entresol::ManagerFactories.end() ) Entresol::AddManagerFactory(new Graphics::DefaultTextureManagerFactory());
683  //DefaultUIManager
684  ManIt = Entresol::ManagerFactories.find("DefaultUIManager");
685  if( ManIt == Entresol::ManagerFactories.end() ) Entresol::AddManagerFactory(new UI::DefaultUIManagerFactory());
686 
687  #ifdef ENABLE_OALS_AUDIO_IMPLEMENTATION
688  //OALSAudioManager
689  ManIt = Entresol::ManagerFactories.find("OALSAudioManager");
690  if( ManIt == Entresol::ManagerFactories.end() ) Entresol::AddManagerFactory(new Audio::OALS::OALSAudioManagerFactory());
691  #endif //ENABLE_OALS_AUDIO_IMPLEMENTATION
692 
693  #ifdef MEZZNETWORK
694  //DefaultNetworkManager
695  ManIt = Entresol::ManagerFactories.find("DefaultNetworkManager");
696  if( ManIt == Entresol::ManagerFactories.end() ) Entresol::AddManagerFactory(new Network::DefaultNetworkManagerFactory());
697  #endif //MEZZNETWORK
698 
699  #ifdef MEZZLUA51
700  ManIt = Entresol::ManagerFactories.find("Lua51ScriptingEngine");
701  if( ManIt == Entresol::ManagerFactories.end() ) Entresol::AddManagerFactory(new Scripting::Lua::Lua51ScriptingEngineFactory());
702  #endif //MEZZLUA51
703  }
704 
705  ///////////////////////////////////////////////////////////////////////////////
706  // Upper Management
707 
708  EntresolManager* Entresol::CreateManager(const String& ManagerImplName, const NameValuePairList& Params, const Boole AddToWorld)
709  {
710  ManagerFactoryIterator ManIt = Entresol::ManagerFactories.find(ManagerImplName);
711  if( ManIt == Entresol::ManagerFactories.end() ) {
712  MEZZ_EXCEPTION(ExceptionBase::II_IDENTITY_NOT_FOUND_EXCEPTION,"Attempting to create manager of type \"" + ManagerImplName + "\", which has no factory registered.");
713  }
714  EntresolManager* NewMan = (*ManIt).second->CreateManager(Params);
715  if(AddToWorld)
716  this->AddManager(NewMan);
717  return NewMan;
718  }
719 
720  EntresolManager* Entresol::CreateManager(const String& ManagerImplName, const XML::Node& XMLNode, const Boole AddToWorld)
721  {
722  ManagerFactoryIterator ManIt = Entresol::ManagerFactories.find(ManagerImplName);
723  if( ManIt == Entresol::ManagerFactories.end() ) {
724  MEZZ_EXCEPTION(ExceptionBase::II_IDENTITY_NOT_FOUND_EXCEPTION,"Attempting to create manager of type \"" + ManagerImplName + "\", which has no factory registered.");
725  }
726  EntresolManager* NewMan = (*ManIt).second->CreateManager(XMLNode);
727  if(AddToWorld)
728  this->AddManager(NewMan);
729  return NewMan;
730  }
731 
732  void Entresol::DestroyManager(EntresolManager* ToBeDestroyed)
733  {
734  ManagerFactoryIterator ManIt = Entresol::ManagerFactories.find(ToBeDestroyed->GetImplementationTypeName());
735  if( ManIt == Entresol::ManagerFactories.end() ) {
736  MEZZ_EXCEPTION(ExceptionBase::II_IDENTITY_NOT_FOUND_EXCEPTION,"Attempting to destroy manager of type \"" + ToBeDestroyed->GetImplementationTypeName() + "\", which has no factory registered.");
737  }
738  this->RemoveManager(ToBeDestroyed);
739  (*ManIt).second->DestroyManager(ToBeDestroyed);
740  }
741 
742  void Entresol::DestroyAllManagers()
743  {
744  //for( std::list<ManagerBase*>::iterator iter = --this->ManagerList.end(); !ManagerList.empty(); iter = --this->ManagerList.end() ) //Backward
745  /*for( std::list<ManagerBase*>::iterator iter = this->ManagerList.begin(); !ManagerList.empty(); iter = this->ManagerList.begin() ) //forward
746  {
747  ManagerBase* Current = (*iter);
748  #ifdef MEZZDEBUG
749  this->Log("Deleting " + Current->GetInterfaceTypeAsString() + ".");
750  this->DoMainLoopLogging();
751  #endif
752  ManagerFactoryIterator ManIt = Entresol::ManagerFactories.find(Current->GetImplementationTypeName());
753  if( ManIt == Entresol::ManagerFactories.end() ) {
754  MEZZ_EXCEPTION(ExceptionBase::II_IDENTITY_NOT_FOUND_EXCEPTION,"Attempting to destroy manager of type \"" + Current->GetImplementationTypeName() + "\", which has no factory registered.");
755  }else{
756  (*ManIt).second->DestroyManager(Current);
757  }
758  }
759  this->ManagerList.clear();// */
760  while( !(this->ManagerList.empty()) )
761  {
762  EntresolManager* Current = this->ManagerList.front();
763  #ifdef MEZZDEBUG
764  this->_Log("Deleting " + Current->GetInterfaceTypeAsString() + ".\n");
765  #endif
766 
767  ManagerFactoryIterator ManIt = Entresol::ManagerFactories.find(Current->GetImplementationTypeName());
768  if( ManIt == Entresol::ManagerFactories.end() ) {
769  MEZZ_EXCEPTION(ExceptionBase::II_IDENTITY_NOT_FOUND_EXCEPTION,"Attempting to destroy manager of type \"" + Current->GetImplementationTypeName() + "\", which has no factory registered.");
770  }else{
771  (*ManIt).second->DestroyManager(Current);
772  }
773 
774  this->ManagerList.pop_front();
775  }// */
776  }
777 
778  void Entresol::AddManager(EntresolManager* ManagerToAdd)
779  {
780  #ifdef MEZZDEBUG
781  this->_Log("Adding " + ManagerToAdd->GetInterfaceTypeAsString() + ".\n");
782  #endif
783  // We have to verify the manager is unique. A number of issues can arise if a manager is double inserted.
784  for( ManagerIterator ManIter = this->ManagerList.begin() ; ManIter != this->ManagerList.end() ; ++ManIter )
785  {
786  if( (*ManIter) == ManagerToAdd )
787  return;
788  }
789  this->ManagerList.push_back(ManagerToAdd);
790  }
791 
792  EntresolManager* Entresol::GetManager(const Whole RetrieveType, UInt16 WhichOne)
793  {
794  for(ManagerIterator ManIter = this->ManagerList.begin(); ManIter!=this->ManagerList.end(); ++ManIter )
795  {
796  if( (*ManIter)->GetInterfaceType() == RetrieveType ) {
797  if( 0 == WhichOne ) return *ManIter; // we use our copy of WhichOne as a countdown to 0
798  else --WhichOne;
799  }
800  }
801  return NULL;
802  }
803 
804  void Entresol::RemoveManager(EntresolManager* ManagerToRemove)
805  {
806  for( ManagerIterator ManIter = this->ManagerList.begin() ; ManIter != this->ManagerList.end() ; ++ManIter )
807  {
808  if( *ManIter == ManagerToRemove ) {
809  this->ManagerList.erase(ManIter);
810  return;
811  }
812  }
813  }
814 
815  void Entresol::RemoveManager(const Whole RemoveType, UInt16 WhichOne)
816  {
817  for( ManagerIterator ManIter = this->ManagerList.begin(); ManIter!=this->ManagerList.end(); ++ManIter )
818  {
819  if( (*ManIter)->GetInterfaceType() == RemoveType ) {
820  if( 0 == WhichOne ) { // we use our copy of WhichOne as a countdown to 0
821  this->ManagerList.erase(ManIter);
822  return;
823  }else{
824  --WhichOne;
825  }
826  }
827  }
828  }
829 
830  ///////////////////////////////////////////////////////////////////////////////
831  // World Management
832 
833  World* Entresol::CreateWorld(const String& WorldName)
834  {
835  World* NewWorld = new World(WorldName);
836  this->AddWorld(NewWorld);
837  return NewWorld;
838  }
839 
840  World* Entresol::CreateWorld(const String& WorldName, const std::vector <WorldManager*>& ManagerToBeAdded)
841  {
842  World* NewWorld = new World(WorldName, ManagerToBeAdded);
843  this->AddWorld(NewWorld);
844  return NewWorld;
845  }
846 
847  World* Entresol::CreateWorld(const String& WorldName, const Physics::ManagerConstructionInfo& PhysicsInfo,const String& SceneType)
848  {
849  World* NewWorld = new World(WorldName, PhysicsInfo, SceneType );
850  this->AddWorld(NewWorld);
851  return NewWorld;
852  }
853 
854  World* Entresol::CreateWorld(const String& WorldName, const std::vector <WorldManager*>& ManagerToBeAdded,
855  const Physics::ManagerConstructionInfo& PhysicsInfo,const String& SceneType)
856  {
857  World* NewWorld = new World(WorldName, ManagerToBeAdded, PhysicsInfo, SceneType );
858  this->AddWorld(NewWorld);
859  return NewWorld;
860  }
861 
862  void Entresol::AddWorld(World* WorldToBeAdded)
863  {
864  Worlds.push_back(WorldToBeAdded);
865  }
866 
867  World* Entresol::GetWorld(const String& WorldName)
868  {
869  for( ConstWorldIterator it = this->Worlds.begin() ; it != this->Worlds.end() ; it++ )
870  {
871  World* w = (*it);
872  if ( WorldName == w->GetName() ) {
873  return w;
874  }
875  }
876  return NULL;
877  }
878 
879  World* Entresol::GetWorld(const Whole Index)
880  {
881  return this->Worlds.at(Index);
882  }
883 
884  UInt16 Entresol::GetNumWorlds()
885  {
886  return this->Worlds.size();
887  }
888 
889  World* Entresol::RemoveWorld(World* WorldToBeRemoved)
890  {
891  for( WorldIterator it = this->Worlds.begin(); it != this->Worlds.end(); it++ )
892  {
893  World* w = (*it);
894  if ( WorldToBeRemoved == w ) {
895  this->Worlds.erase(it);
896  return w;
897  }
898  }
899  return NULL;
900  }
901 
902  World* Entresol::RemoveWorldByName(const String& WorldName)
903  {
904  for( WorldIterator it = this->Worlds.begin(); it != this->Worlds.end(); it++ )
905  {
906  World* w = (*it);
907  if ( WorldName == w->GetName() ) {
908  this->Worlds.erase(it);
909  return w;
910  }
911  }
912  return NULL;
913  }
914 
915  void Entresol::RemoveAllWorlds()
916  {
917  this->Worlds.clear();
918  }
919 
920  void Entresol::DestroyWorld(World* WorldToBeDestroyed)
921  {
922  for( WorldIterator it = this->Worlds.begin(); it != this->Worlds.end(); it++ )
923  {
924  World* w = (*it);
925  if ( WorldToBeDestroyed == w ) {
926  delete w;
927  this->Worlds.erase(it);
928  return;
929  }
930  }
931  }
932 
933  void Entresol::DestroyWorldByName(const String& WorldName)
934  {
935  for( WorldIterator it = this->Worlds.begin(); it != this->Worlds.end(); it++ )
936  {
937  World* w = (*it);
938  if ( WorldName == w->GetName() ) {
939  delete w;
940  this->Worlds.erase(it);
941  return;
942  }
943  }
944  }
945 
946  void Entresol::DestroyAllWorlds()
947  {
948  for( WorldIterator it = this->Worlds.begin(); it != this->Worlds.end(); it++ )
949  {
950  World* w = (*it);
951  delete w;
952  }
953  this->Worlds.clear();
954  }
955 
956  void Entresol::PauseAllWorlds(Boole Pause)
957  {
958  for( WorldIterator it = this->Worlds.begin(); it != this->Worlds.end(); it++ )
959  {
960  (*it)->PauseWorld(Pause);
961  }
962  }
963 
964  ///////////////////////////////////////////////////////////////////////////////
965  // Internal Logging
966 
967  void Entresol::_LogString(const String& Message)
968  {
969  // if it is in the Audiologs then it has already happened so it needs to be logged first
970  if( Message.size() > 0 )
971  { this->_GetLogStream() << Message; }
972  }
973 
974  Logger& Entresol::_GetLogStream(Threading::ThreadId ID)
975  {
976  Threading::FrameScheduler::Resource* AlmostResults = this->WorkScheduler.GetThreadResource(ID);
977  if(AlmostResults)
978  { return AlmostResults->GetUsableLogger(); }
979  else
980  { MEZZ_EXCEPTION(ExceptionBase::PARAMETERS_RANGE_EXCEPTION, "Could not access thread Specific Logger from invalid thread."); }
981  }
982 
983  Threading::LogAggregator* Entresol::_GetLogAggregator()
984  { return this->Aggregator; }
985 }
986 #endif
A factory responsible for the creation and destruction of the default resourcemanager.
A factory responsible for the creation and destruction of the default networkmanager.
static Entresol * SingletonPtr
The one and only pointer to the single object.
Definition: singleton.h:72
std::stringstream Logger
In case we ever replace the stringstream with another class, this will allow us to swap it out...
Definition: datatypes.h:180
std::vector< EntresolManager * > ManagerVec
Container type for passing pre-created managers into the Entresol upon creation.
Definition: entresol.h:342
bool Boole
Generally acts a single bit, true or false.
Definition: datatypes.h:173
MaxInt GetTimeStamp()
Get a timestamp, in microseconds. This will generally be some multiple of the GetTimeStampResolution ...
This is a base class for factories that construct managers used by the Entresol class.
#define MEZZ_EXCEPTION(num, desc)
An easy way to throw exceptions with rich information.
Definition: exception.h:3048
Declaration of FileStream.
STL namespace.
A factory responsible for the creation and destruction of the default graphicsmanager.
ArchiveType
Used to indicate what kind of resources the Entrosol should look for.
A factory responsible for the creation and destruction of the default MeshManager.
Definition: meshmanager.h:190
virtual String GetImplementationTypeName() const =0
This Allows any manager name to be sent to a stream. Primarily used for logging.
A factory responsible for the creation and destruction of the default TextureManager.
std::stringstream StringStream
A Datatype used for streaming operations with strings.
Definition: datatypes.h:176
This is returned to indicated there where no issues parsing the XML document.
float Real
A Datatype used to represent a real floating point number.
Definition: datatypes.h:141
A thread specific collection of double-buffered and algorithm specific resources. ...
A factory responsible for the creation and destruction of the default collisionshapemanager.
uint16_t UInt16
An 16-bit unsigned integer.
Definition: datatypes.h:122
Int32 AtomicCompareAndSwap32(Int32 *VariableToChange, const Int32 &OldValue, const Int32 &NewValue)
Atomically Compares And Swaps a 32 bit value.
This is the base class for all managers that do no describe properties of a single world...
A light-weight handle for manipulating nodes in DOM tree.
Definition: node.h:89
This is central object in this algorithm, it is responsible for spawning threads and managing the ord...
The defintion of the Resource Manager.
A factory responsible for the creation and destruction of the default scripting engine providing Lua ...
Logger & GetUsableLogger()
Get the usable logger for this thread specific resource.
void PauseWorld(const Boole Pause)
Pauses all animations, particles, and object movement throughout the world.
Definition: world.cpp:162
A factory responsible for the creation and destruction of the default eventmanager.
Definition: eventmanager.h:420
std::list< NameValuePair > NameValuePairList
This is a datatype mostly used for describing settings or parameters that can't be declared in advanc...
Definition: datatypes.h:206
virtual String GetManagerImplName() const =0
Gets the name of the manager that is created by this factory.
Gather all the thread specific logs and commit them to the main log.
A factory responsible for the creation and destruction of the default uimanager.
Definition: uimanager.h:445
WorldContainer::const_iterator ConstWorldIterator
Const Iterator type for Worlds stored by this class.
Definition: entresol.h:352
The bulk of the engine components go in this namspace.
Definition: actor.cpp:56
unsigned long Whole
Whole is an unsigned integer, it will be at least 32bits in size.
Definition: datatypes.h:151
This class represents a world for objects to interact within.
Definition: world.h:74
WorldContainer::iterator WorldIterator
Iterator type for Worlds stored by this class.
Definition: entresol.h:350
const String & GetName() const
Gets the name of this world.
Definition: world.cpp:159
A factory responsible for the creation and destruction of the default inputmanager.
Definition: inputmanager.h:247
The thread ID is a unique identifier for each thread.
Definition: thread.h:209
std::vector< EntresolManagerFactory * > ManagerFactoryVec
Basic container type for factories that construct known manager types.
Definition: entresol.h:330
This file has the interface for the Lua based implementation of the Scripting system.
std::string String
A datatype used to a series of characters.
Definition: datatypes.h:159
ManagerFactoryMap::iterator ManagerFactoryIterator
Iterator type for manager factories stored by this class.
Definition: entresol.h:332
ManagerContainer::iterator ManagerIterator
Iterator type for managers stored by this class.
Definition: entresol.h:338
This is a helper class storing information needed for the construction of a PhysicsManager.
virtual String GetInterfaceTypeAsString() const
Gets a string of the interface type of this manager.
Definition: managerbase.cpp:71