MezzanineEngine 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
entresol.cpp
1 // © Copyright 2010 - 2014 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 /// @todo Remove #include "mezzanine.h" and just include what is required. Waiting for multithreaded refactor, because we will have to do this again after that.
53 #include "mezzanine.h"
54 
55 //Enabled implementation includes
56 #ifdef ENABLE_OALS_AUDIO_IMPLEMENTATION
57  // Permit the factories to be visible so they can be auto-added.
58  #include "Audio/OALS/oalsaudiomanagerfactory.h"
59  #include "Audio/OALS/oalssoundscapemanagerfactory.h"
60 #endif //ENABLE_OALS_AUDIO_IMPLEMENTATION
61 
62 //#include "OgreBspSceneManagerPlugin.h"
63 //#include "OgreCgPlugin.h"
64 //#include "OgreOctreePlugin.h"
65 //#include "OgreOctreeZonePlugin.h"
66 #include "OgreParticleFXPlugin.h"
67 //#include "OgrePCZPlugin.h"
68 
69 #include <SDL.h>
70 #include <Ogre.h>
71 #include <btBulletDynamicsCommon.h>
72 
73 #include <sstream>
74 #include <string>
75 
76 using namespace std;
77 
78 namespace Mezzanine
79 {
80  template<> Entresol* Singleton<Entresol>::SingletonPtr = NULL;
81 
82  namespace
83  {
84  // Since there doesn't seem to be anyway to check if the ogre root exists yet.
85  // if a you haven't made an ogre root, then Ogre::Root::getSingletonPtr(); appears to return gibberish rather that a zero.
86  Ogre::Root* OgreCore = NULL;
87  }
88 
89 
90  ///////////////////////////////////////////////////////////////////////////////
91  // Construction and Destruction Helpers
92 
93  void Entresol::SetupLogging(const String& LogFileName)
94  {
95  /// @todo Allow the FrameScheduler Log target to be inspected and changed here
96  Ogre::LogManager* OgreLogs = Ogre::LogManager::getSingletonPtr();
97  if( NULL == OgreLogs )
98  { OgreLogs = new Ogre::LogManager(); }
99 
100  if(!LogFileName.empty())
101  {
102  OgreLogs->createLog(String("Graphics")+LogFileName,true,true);
103  }
104  else
105  {
106  OgreLogs->createLog("GraphicsMezzanine.log",true,true);
107  }
108  this->Aggregator = new Threading::LogAggregator();
109  Aggregator->SetAggregationTarget(&WorkScheduler);
110  this->WorkScheduler.AddWorkUnitMain(Aggregator, "LogAggregator");
111  }
112 
113  void Entresol::DestroyLogging()
114  {
115  this->WorkScheduler.RemoveWorkUnitMain(Aggregator);
116  delete Aggregator;
117  }
118 
119  void Entresol::SetupOgre()
120  {
121  if ( NULL == OgreCore )
122  { OgreCore = new Ogre::Root("","",""); }
123  else
124  { OgreCore = Ogre::Root::getSingletonPtr(); }
125  }
126 
127  void Entresol::DestroyOgre()
128  {
129  //Ogre::Root::getSingleton().shutdown();
130  delete Ogre::Root::getSingletonPtr(); // This should be done by the shutdown method shouldn't it?
131  OgreCore = 0;
132  delete SubSystemParticleFXPlugin;
133  }
134 
135  ///////////////////////////////////////////////////////////////////////////////
136  // Mezzanine constructors
137 
138  /// @TODO In the Entrosol, reomves all references to a plugins file
139  Entresol::Entresol()
140  {
142  std::vector <ManagerBase*> temp;
143 
144  this->Construct(PhysicsInfo,"DefaultSceneManager",".","Mezzanine.log",temp);
145  }
146 
147 
148  Entresol::Entresol(const String& EngineDataPath, const Mezzanine::ArchiveType ArchType, const String& InitializerFile)
149  {
150  if(String::npos != InitializerFile.find(".mxi"))
151  { ConstructFromXML(EngineDataPath, ArchType, InitializerFile); }
152  else
153  { MEZZ_EXCEPTION(Exception::NOT_IMPLEMENTED_EXCEPTION,"Attempting to initialze Mezzanine from an unsupported file type."); }
154  }
155 
156  Entresol::Entresol(std::vector<ManagerFactory*>& CustomFactories, const String& EngineDataPath, const Mezzanine::ArchiveType ArchType, const String& InitializerFile)
157  {
158  for(std::vector<ManagerFactory*>::iterator it = CustomFactories.begin(); it != CustomFactories.end(); ++it)
159  {
160  AddManagerFactory( (*it) );
161  }
162 
163  if(String::npos != InitializerFile.find(".mxi"))
164  { ConstructFromXML(EngineDataPath, ArchType, InitializerFile); }
165  else
166  { MEZZ_EXCEPTION(Exception::NOT_IMPLEMENTED_EXCEPTION,"Attempting to initialze Mezzanine from an unsupported file type."); }
167  }
168 
169 
170  Entresol::Entresol( const Physics::ManagerConstructionInfo& PhysicsInfo,
171  const String& SceneType,
172  const String& EngineDataPath,
173  const String& LogFileName)
174  {
175  std::vector <ManagerBase*> temp;
176  this->Construct(PhysicsInfo,
177  SceneType,
178  EngineDataPath,
179  LogFileName,
180  temp );
181  }
182 
183  Entresol::Entresol( const Physics::ManagerConstructionInfo& PhysicsInfo,
184  const String& SceneType,
185  const String& EngineDataPath,
186  const String& LogFileName,
187  const std::vector <ManagerBase*>& ManagerToBeAdded)
188  {
189  this->Construct(PhysicsInfo,
190  SceneType,
191  EngineDataPath,
192  LogFileName,
193  ManagerToBeAdded );
194 
195  }
196 
197  void Entresol::Construct( const Physics::ManagerConstructionInfo& PhysicsInfo,
198  const String& SceneType,
199  const String& EngineDataPath,
200  const String& LogFileName,
201  const std::vector <ManagerBase*>& ManagerToBeAdded )
202 
203  {
204  //Add default manager factories
205  AddAllEngineDefaultManagerFactories();
206  //Set some sane Defaults for some values
207  this->ManualLoopBreak = 0;
208 
209  SetupOgre();
210  SetupLogging(LogFileName);
211 
212  // Load the necessary plugins.
213  SubSystemParticleFXPlugin = new Ogre::ParticleFXPlugin();
214  Ogre::Root::getSingleton().installPlugin(SubSystemParticleFXPlugin);
215 
216  //add each manager that was passed in to the manager list
217  for(std::vector<ManagerBase*>::const_iterator iter = ManagerToBeAdded.begin(); iter!= ManagerToBeAdded.end(); iter++)
218  { this->AddManager(*iter); }
219 
220  //Dummy param list so we can use the auto-added manager types if needed
221  NameValuePairList Params;
222  // ©reate and add any managers that have not been taken care of yet.
223  if(this->GetActorManager()==0)
224  { this->AddManager(new ActorManager()); }
225  if(this->GetAreaEffectManager()==0)
226  { this->AddManager(new AreaEffectManager()); }
227  if(this->GetResourceManager()==0)
228  { this->AddManager(new ResourceManager(EngineDataPath)); }
229  if(this->GetGraphicsManager()==0)
230  { this->AddManager(new Graphics::GraphicsManager()); }
231  if(this->GetEventManager()==0)
232  { this->AddManager(new EventManager()); }
233  if(this->GetInputManager()==0)
234  { this->AddManager(new Input::InputManager()); }
235  if(this->GetPhysicsManager()==0)
236  { this->AddManager(new Physics::PhysicsManager(PhysicsInfo)); }
237  if(this->GetSceneManager()==0)
238  { this->AddManager(new Graphics::SceneManager(SceneType)); }
239  if(this->GetUIManager()==0)
240  { this->AddManager(new UI::UIManager()); }
241  if(this->GetMeshManager()==0)
242  { this->AddManager(new Graphics::MeshManager()); }
243  if(this->GetCollisionShapeManager()==0)
244  { this->AddManager(new Physics::CollisionShapeManager()); }
245  if(this->GetCameraManager()==0)
246  { this->AddManager(new Graphics::CameraManager()); }
247  if(this->GetDebrisManager()==0)
248  { this->AddManager(new DebrisManager()); }
249  #ifdef ENABLE_OALS_AUDIO_IMPLEMENTATION
250  if(this->GetAudioManager()==0)
251  { this->AddManager( this->CreateManager("OALSAudioManager",Params,false) ); }
252  if(this->GetSoundScapeManager()==0)
253  { this->AddManager( this->CreateManager("OALSSoundScapeManager",Params,false) ); }
254  #endif //ENABLE_OALS_AUDIO_IMPLEMENTATION
255 
256  // This Tests various assumptions about the way the platform works, and will not act
257  SanityChecks();
258  }
259 
260  void Entresol::ConstructFromXML(const String& EngineDataPath, const Mezzanine::ArchiveType ArchType, const String& InitializerFile)
261  {
262  //Add default manager factories
263  AddAllEngineDefaultManagerFactories();
264  //Set some sane Defaults for some values.
265  this->ManualLoopBreak = false;
266 
267  // Create Ogre.
268  SetupOgre();
269 
270  // Load the necessary plugins.
271  SubSystemParticleFXPlugin = new Ogre::ParticleFXPlugin();
272  Ogre::Root::getSingleton().installPlugin(SubSystemParticleFXPlugin);
273 
274  // Set up the data we'll be populating.
275  XML::Attribute CurrAttrib;
276  String GUIInit, ResourceInit, PluginsInit, LogFileName;
277  String PluginExtension, PluginPath;
278 
279  // Create or set the resource manager.
280  /// @todo This currently forces our default resource manager to be constructed, which isn't in line with our factory/initiailzation design.
281  /// This should be addressed somehow.
282  if(ResourceManager::SingletonValid())
283  { AddManager(ResourceManager::GetSingletonPtr()); }
284  else
285  { AddManager(new ResourceManager(EngineDataPath, ArchType)); }
286 
287  // Open and load the initializer doc.
288  ResourceManager* ResourceMan = GetResourceManager();
289  /// @todo Replace this stack allocated stream for one initialized from the Resource Manager, after the system is ready.
290  Resource::FileStream InitStream(InitializerFile,EngineDataPath);
291  XML::Document InitDoc;
292  XML::ParseResult DocResult = InitDoc.Load(InitStream);
293  if( DocResult.Status != XML::StatusOk )
294  {
295  StringStream ExceptionStream;
296  ExceptionStream << "Failed to parse XML file \"" << InitializerFile << "\".";
297  MEZZ_EXCEPTION(Exception::SYNTAX_ERROR_EXCEPTION_XML,ExceptionStream.str());
298  }
299  XML::Node InitRoot = InitDoc.GetChild("InitializerRoot");
300  if( InitRoot.Empty() )
301  {
302  StringStream ExceptionStream;
303  ExceptionStream << "Failed to find expected Root node in \"" << InitializerFile << "\".";
304  MEZZ_EXCEPTION(Exception::SYNTAX_ERROR_EXCEPTION_XML,ExceptionStream.str());
305  }
306 
307  // Get the world settings and set them.
308  XML::Node WorldSettings = InitRoot.GetChild("WorldSettings");
309  for( XML::NodeIterator SetIt = WorldSettings.begin() ; SetIt != WorldSettings.end() ; ++SetIt )
310  {
311  String SecName = (*SetIt).Name();
312  if( "FrameSettings" == SecName )
313  {
314  CurrAttrib = (*SetIt).GetAttribute("TargetFrameRate");
315  if(CurrAttrib.Empty())
316  {
317  CurrAttrib = (*SetIt).GetAttribute("TargetFrameTime");
318  if(!CurrAttrib.Empty())
319  SetTargetFrameTimeMicroseconds(CurrAttrib.AsWhole());
320  }else{
321  this->SetTargetFrameRate(CurrAttrib.AsWhole());
322  }
323  }
324  else
325  {
326  MEZZ_EXCEPTION(Exception::SYNTAX_ERROR_EXCEPTION_XML,String("Unknown WorldSetting ")+SecName);
327  }
328 
329  }
330 
331  SetupLogging(LogFileName);
332 
333  // Get the other initializer files we'll be using, since we'll need the plugins initializer.
334  XML::Node InitFiles = InitRoot.GetChild("OtherInitializers");
335  for( XML::NodeIterator InitIt = InitFiles.begin() ; InitIt != InitFiles.end() ; ++InitIt )
336  {
337  String InitFileName = (*InitIt).Name();
338  if( "PluginInit" == InitFileName )
339  {
340  CurrAttrib = (*InitIt).GetAttribute("FileName");
341  if(!CurrAttrib.Empty())
342  PluginsInit = CurrAttrib.AsString();
343  }
344  else if( "ResourceInit" == InitFileName )
345  {
346  CurrAttrib = (*InitIt).GetAttribute("FileName");
347  if(!CurrAttrib.Empty())
348  ResourceInit = CurrAttrib.AsString();
349  }
350  else if( "GUIInit" == InitFileName )
351  {
352  CurrAttrib = (*InitIt).GetAttribute("FileName");
353  if(!CurrAttrib.Empty())
354  GUIInit = CurrAttrib.AsString();
355  }
356  }
357 
358  // Load additional resource groups
359  /*if(!ResourceInit.empty())
360  {
361  /// @todo Replace this stack allocated stream for one initialized from the Resource Manager, after the system is ready.
362  Resource::FileStream ResourceStream(ResourceInit,EngineDataPath);
363  XML::Document ResourceDoc;
364  ResourceDoc.Load(ResourceStream);
365  // Get an iterator to the first resource group node, and declare them all.
366  XML::Node ResourceLocations = ResourceDoc.GetChild("ResourceLocations");
367  for( XML::NodeIterator GroupIt = ResourceLocations.begin() ; GroupIt != ResourceLocations.end() ; ++GroupIt )
368  {
369  String GroupName, GroupType, GroupPath;
370  bool GroupRecursive = false;
371  // Get the group path
372  CurrAttrib = (*GroupIt).GetAttribute("GroupPath");
373  if(!CurrAttrib.Empty())
374  GroupPath = CurrAttrib.AsString();
375  // Get the group type
376  CurrAttrib = (*GroupIt).GetAttribute("GroupType");
377  if(!CurrAttrib.Empty())
378  GroupType = CurrAttrib.AsString();
379  // Get the group name
380  CurrAttrib = (*GroupIt).GetAttribute("GroupName");
381  if(!CurrAttrib.Empty())
382  GroupName = CurrAttrib.AsString();
383  // Get whether this is recursive
384  CurrAttrib = (*GroupIt).GetAttribute("Recursive");
385  if(!CurrAttrib.Empty())
386  GroupRecursive = StringTool::ConvertToBool(CurrAttrib.AsString());
387  // Finally create the resource location.
388  ResourceMan->AddAssetLocation(GroupPath,GroupType,GroupName,GroupRecursive);
389  }
390  // Get what resource groups should be initialized.
391  XML::Node InitGroups = ResourceDoc.GetChild("InitGroups");
392  for( XML::NodeIterator InitIt = InitGroups.begin() ; InitIt != InitGroups.end() ; ++InitIt )
393  {
394  String GroupName;
395  CurrAttrib = (*InitIt).GetAttribute("GroupName");
396  if(!CurrAttrib.Empty())
397  GroupName = CurrAttrib.AsString();
398  ResourceMan->InitAssetGroup(GroupName);
399  }
400  }//*/
401 
402  // Create the requested managers and set their necessary values.
403  XML::Node Managers = InitRoot.GetChild("Managers");
404  for( XML::NodeIterator ManIt = Managers.begin() ; ManIt != Managers.end() ; ++ManIt )
405  {
406  CreateManager( (*ManIt).Name(), (*ManIt) );
407  }
408 
409  // Load additional resource groups
410  if(!ResourceInit.empty())
411  {
412  /// @todo Replace this stack allocated stream for one initialized from the Resource Manager, after the system is ready.
413  Resource::FileStream ResourceStream(ResourceInit,EngineDataPath);
414  XML::Document ResourceDoc;
415  ResourceDoc.Load(ResourceStream);
416  // Get an iterator to the first resource group node, and declare them all.
417  XML::Node ResourceLocations = ResourceDoc.GetChild("ResourceLocations");
418  for( XML::NodeIterator GroupIt = ResourceLocations.begin() ; GroupIt != ResourceLocations.end() ; ++GroupIt )
419  {
420  String GroupName, GroupPath;
421  ArchiveType GroupType;
422  bool GroupRecursive = false;
423  // Get the group path
424  CurrAttrib = (*GroupIt).GetAttribute("GroupPath");
425  if(!CurrAttrib.Empty())
426  GroupPath = CurrAttrib.AsString();
427  // Get the group type
428  CurrAttrib = (*GroupIt).GetAttribute("GroupType");
429  if(!CurrAttrib.Empty())
430  GroupType = ResourceManager::GetArchiveTypeFromString(CurrAttrib.AsString());
431  // Get the group name
432  CurrAttrib = (*GroupIt).GetAttribute("GroupName");
433  if(!CurrAttrib.Empty())
434  GroupName = CurrAttrib.AsString();
435  // Get whether this is recursive
436  CurrAttrib = (*GroupIt).GetAttribute("Recursive");
437  if(!CurrAttrib.Empty())
438  GroupRecursive = StringTools::ConvertToBool(CurrAttrib.AsString());
439  // Finally create the resource location.
440  ResourceMan->AddAssetLocation(GroupPath,GroupType,GroupName,GroupRecursive);
441  }
442  // Get what resource groups should be initialized.
443  XML::Node InitGroups = ResourceDoc.GetChild("InitGroups");
444  for( XML::NodeIterator InitIt = InitGroups.begin() ; InitIt != InitGroups.end() ; ++InitIt )
445  {
446  String GroupName;
447  CurrAttrib = (*InitIt).GetAttribute("GroupName");
448  if(!CurrAttrib.Empty())
449  GroupName = CurrAttrib.AsString();
450  ResourceMan->InitAssetGroup(GroupName);
451  }
452  }
453 
454  // Configure the UI
455  if(!GUIInit.empty())
456  {
457  /// @todo This is currently not implemented.
458  }
459 
460  SanityChecks();
461  }
462 
463 
464  void Entresol::SanityChecks()
465  {
466  // ©rossplatform::WaitMilliseconds(1500);
467  //Perform a Test that only needs to be done once for the SDL/userinputevent system.`
468  /*Log("Verifying size of userinput events:");
469  Log(sizeof(Input::InputCode));
470  Log(sizeof(SDL_Scancode));
471  Log(sizeof(int));//*/
472  if(sizeof(Input::InputCode) != sizeof(SDL_Scancode))
473  {
474  MEZZ_EXCEPTION(Exception::INVALID_STATE_EXCEPTION,"User input subsystem Event Sizes Don't match, userinput subsystem will go be buggier than a highschool fortran class.");
475  }
476 
477  if(sizeof(Input::InputCode) != sizeof(int))
478  {
479  MEZZ_EXCEPTION(Exception::INVALID_STATE_EXCEPTION,"Internal User input subsystem Event Sizes Don't match, userinput subsystem cannot function.");
480  }
481  }
482 
483  bool Entresol::VerifyManagerInitializations()
484  {
485  std::vector<String> ManagerNames;
486  for (std::list< ManagerBase* >::iterator Iter=this->ManagerList.begin(); Iter!=this->ManagerList.end(); ++Iter )
487  {
488  if(!(*Iter)->IsInitialized())
489  {
490  ManagerNames.push_back( (*Iter)->GetInterfaceTypeAsString() );
491  }
492  }
493 
494  if(ManagerNames.empty())
495  {
496  return true;
497  }else{
498  StringStream ExceptionStream;
499  if(1 == ManagerNames.size())
500  {
501  ExceptionStream << "Manager: ";
502  ExceptionStream << ManagerNames.at(0);
503  ExceptionStream << "is not initialized. All managers need to be initiailzed when entering the main loop.";
504  }else{
505  ExceptionStream << "Managers: ";
506  for( std::vector<String>::iterator Iter = ManagerNames.begin() ; Iter != ManagerNames.end() ; ++Iter )
507  {
508  ExceptionStream << (*Iter) << ", ";
509  }
510  ExceptionStream << "are not initialized. All managers need to be initiailzed when entering the main loop.";
511  }
512  MEZZ_EXCEPTION(Exception::INVALID_STATE_EXCEPTION,ExceptionStream.str());
513  return false;
514  }
515  }
516 
517  ///////////////////////////////////////////////////////////////////////////////
518  //tears the world down
519  Entresol::~Entresol()
520  {
521  DestroyAllManagers();
522  DestroyAllManagerFactories();
523  DestroyLogging();
524 
525  SDL_Quit();
526 
527  DestroyOgre();
528  }
529 
530  ///////////////////////////////////////////////////////////////////////////////
531  // Utility
532 
533  void Entresol::PauseWorld(bool Pause)
534  {
535  this->GetPhysicsManager()->PauseSimulation(Pause);
536  this->GetSceneManager()->PauseAllParticles(Pause);
537  }
538 
539  ///////////////////////////////////////////////////////////////////////////////
540  // Logging
541 
542  void Entresol::LogString(const String& Message)
543  {
544  // if it is in the Audiologs then it has already happened so it needs to be logged first
545  if(Message.size()>0)
546  { this->GetLogStream() << Message; }
547  }
548 
549  Logger& Entresol::GetLogStream(Threading::ThreadId ID)
550  {
551  Threading::FrameScheduler::Resource* AlmostResults = this->WorkScheduler.GetThreadResource(ID);
552  if(AlmostResults)
553  { return AlmostResults->GetUsableLogger(); }
554  else
555  { MEZZ_EXCEPTION(Exception::PARAMETERS_RANGE_EXCEPTION, "Could not access thread Specific Logger from invalid thread."); }
556  }
557 
558  Threading::LogAggregator* Entresol::GetLogAggregator()
559  { return this->Aggregator; }
560 
561  ///////////////////////////////////////////////////////////////////////////////
562  // Initialization
563  ///////////////////////////////////////
564 
565  void Entresol::EngineInit( const bool &CallMainLoop )
566  {
567  for (std::list< ManagerBase* >::iterator Iter=this->ManagerList.begin(); Iter!=this->ManagerList.end(); ++Iter )
568  {
569  StringStream InitStream;
570  InitStream << "Initializing " << (*Iter)->GetInterfaceTypeAsString() << "." << endl;
571  this->Log(InitStream.str());
572  if((*Iter)->GetInterfaceType() != ManagerBase::MT_GraphicsManager)
573  {
574  (*Iter)->Initialize();
575  }
576  }
577  Graphics::GraphicsManager::GetSingletonPtr()->Initialize();
578 
579  if(CallMainLoop)
580  {
581  this->MainLoop();
582  }
583  }
584 
585  ///////////////////////////////////////////////////////////////////////////////
586  // MainLoop
587  ///////////////////////////////////////
588 
589  Threading::FrameScheduler& Entresol::GetScheduler()
590  { return this->WorkScheduler; }
591 
592  void Entresol::MainLoop()
593  {
594  this->PreMainLoopInit();
595 
596  while(!ManualLoopBreak)
597  { DoOneFrame(); } //Main loop
598 
599  ManualLoopBreak = 0;
600  }
601 
602  void Entresol::PreMainLoopInit()
603  {
604  VerifyManagerInitializations();
605  this->GetPhysicsManager()->MainLoopInitialize();
606  this->GetAreaEffectManager()->MainLoopInitialize();
607  }
608 
609  void Entresol::DoOneFrame()
610  {
611  #ifdef MEZZDEBUG
612  WorkScheduler.GetLog() << "<FrameCounterStart Frame=\"" << WorkScheduler.GetFrameCount() << "\" Time=\"" << GetTimeStamp()<< "\" />" << endl;
613  #endif
614  WorkScheduler.RunAllMonopolies(); //1
615  WorkScheduler.CreateThreads(); //2
616  WorkScheduler.RunMainThreadWork();//3
617  WorkScheduler.JoinAllThreads(); //4
618  WorkScheduler.ResetAllWorkUnits();//5
619  #ifdef MEZZDEBUG
620  WorkScheduler.GetLog() << "<FrameCounterPrePause Frame=\"" << WorkScheduler.GetFrameCount() << "\" Time=\"" << GetTimeStamp()<< "\" />" << endl;
621  #endif
622  WorkScheduler.WaitUntilNextFrame(); //6
623  #ifdef MEZZDEBUG
624  WorkScheduler.GetLog() << "<FrameCounterEnd Frame=\"" << WorkScheduler.GetFrameCount() << "\" Time=\"" << GetTimeStamp()<< "\" />" << endl;
625  #endif
626  }
627 
628  void Entresol::BreakMainLoop(Boolean Break)
629  {
630  if(Break)
631  {
632  while(!ManualLoopBreak)
633  { Threading::AtomicCompareAndSwap32(&ManualLoopBreak,0,1); }
634  } else {
635  while(ManualLoopBreak)
636  { Threading::AtomicCompareAndSwap32(&ManualLoopBreak,1,0); }
637  }
638  }
639 
640  Whole Entresol::GetFrameCount() const
641  { return WorkScheduler.GetFrameCount(); }
642 
643  ///////////////////////////////////////////////////////////////////////////////
644  // Simple get and Set functions
645  ///////////////////////////////////////
646 
647  void Entresol::SetTargetFrameRate(const Whole NewFrameRate)
648  { this->SetTargetFrameTimeMicroseconds( Real(1000000) / Real(NewFrameRate) ); }
649 
650  void Entresol::SetTargetFrameTimeMilliseconds(const Whole NewTargetTime)
651  { this->SetTargetFrameTimeMicroseconds( NewTargetTime * 1000 ); }
652 
653  void Entresol::SetTargetFrameTimeMicroseconds(const Whole NewTargetTime)
654  { WorkScheduler.SetFrameLength(NewTargetTime); }
655 
656  Whole Entresol::GetTargetFrameTimeMilliseconds() const
657  { return WorkScheduler.GetFrameLength()/1000; }
658 
659  Whole Entresol::GetTargetFrameTimeMicroseconds() const
660  { return WorkScheduler.GetFrameLength(); }
661 
662  Whole Entresol::GetLastFrameTimeMilliseconds() const
663  { return WorkScheduler.GetLastFrameTime()/1000; }
664 
665  Whole Entresol::GetLastFrameTimeMicroseconds() const
666  { return WorkScheduler.GetLastFrameTime(); }
667 
668  ///////////////////////////////////////////////////////////////////////////////
669  // Factory Management
670 
671  void Entresol::AddManagerFactory(ManagerFactory* ToBeAdded)
672  {
673  this->ManagerFactories.insert(std::pair<String,ManagerFactory*>(ToBeAdded->GetManagerTypeName(),ToBeAdded));
674  }
675 
676  void Entresol::RemoveManagerFactory(ManagerFactory* ToBeRemoved)
677  {
678  this->RemoveManagerFactory(ToBeRemoved->GetManagerTypeName());
679  }
680 
681  void Entresol::RemoveManagerFactory(const String& ImplName)
682  {
683  ManagerFactoryIterator ManIt = this->ManagerFactories.find(ImplName);
684  if( ManIt != this->ManagerFactories.end() )
685  { this->ManagerFactories.erase(ManIt); }
686  }
687 
688  void Entresol::DestroyManagerFactory(ManagerFactory* ToBeRemoved)
689  {
690  this->DestroyManagerFactory(ToBeRemoved->GetManagerTypeName());
691  }
692 
693  void Entresol::DestroyManagerFactory(const String& ImplName)
694  {
695  ManagerFactoryIterator ManIt = this->ManagerFactories.find(ImplName);
696  if( ManIt != this->ManagerFactories.end() ) {
697  delete ManIt->second;
698  this->ManagerFactories.erase(ManIt);
699  }
700  }
701 
702  void Entresol::DestroyAllManagerFactories()
703  {
704  for( ManagerFactoryIterator ManIt = this->ManagerFactories.begin() ; ManIt != this->ManagerFactories.end() ; ++ManIt )
705  { delete (*ManIt).second; }
706  this->ManagerFactories.clear();
707  }
708 
709  void Entresol::AddAllEngineDefaultManagerFactories()
710  {
711  ManagerFactoryIterator ManIt;
712  //DefaultActorManager
713  ManIt = this->ManagerFactories.find("DefaultActorManager");
714  if( ManIt == this->ManagerFactories.end() ) this->AddManagerFactory(new DefaultActorManagerFactory());
715  //DefaultAreaEffectManager
716  ManIt = this->ManagerFactories.find("DefaultAreaEffectManager");
717  if( ManIt == this->ManagerFactories.end() ) this->AddManagerFactory(new DefaultAreaEffectManagerFactory());
718  //DefaultCameraManager
719  ManIt = this->ManagerFactories.find("DefaultCameraManager");
720  if( ManIt == this->ManagerFactories.end() ) this->AddManagerFactory(new Graphics::DefaultCameraManagerFactory());
721  //DefaultCollisionShapeManager
722  ManIt = this->ManagerFactories.find("DefaultCollisionShapeManager");
723  if( ManIt == this->ManagerFactories.end() ) this->AddManagerFactory(new Physics::DefaultCollisionShapeManagerFactory());
724  //DefaultDebrisManager
725  ManIt = this->ManagerFactories.find("DefaultDebrisManager");
726  if( ManIt == this->ManagerFactories.end() ) this->AddManagerFactory(new DefaultDebrisManagerFactory());
727  //DefaultEventManager
728  ManIt = this->ManagerFactories.find("DefaultEventManager");
729  if( ManIt == this->ManagerFactories.end() ) this->AddManagerFactory(new DefaultEventManagerFactory());
730  //DefaultGraphicsManager
731  ManIt = this->ManagerFactories.find("DefaultGraphicsManager");
732  if( ManIt == this->ManagerFactories.end() ) this->AddManagerFactory(new Graphics::DefaultGraphicsManagerFactory());
733  //DefaultInputManager
734  ManIt = this->ManagerFactories.find("DefaultInputManager");
735  if( ManIt == this->ManagerFactories.end() ) this->AddManagerFactory(new Input::DefaultInputManagerFactory());
736  //DefaultMeshManager
737  ManIt = this->ManagerFactories.find("DefaultMeshManager");
738  if( ManIt == this->ManagerFactories.end() ) this->AddManagerFactory(new Graphics::DefaultMeshManagerFactory());
739  //DefaultNetworkManager
740  ManIt = this->ManagerFactories.find("DefaultNetworkManager");
741  if( ManIt == this->ManagerFactories.end() ) this->AddManagerFactory(new DefaultNetworkManagerFactory());
742  //DefaultPhysicsManager
743  ManIt = this->ManagerFactories.find("DefaultPhysicsManager");
744  if( ManIt == this->ManagerFactories.end() ) this->AddManagerFactory(new Physics::DefaultPhysicsManagerFactory());
745  //DefaultResourceManager
746  ManIt = this->ManagerFactories.find("DefaultResourceManager");
747  if( ManIt == this->ManagerFactories.end() ) this->AddManagerFactory(new DefaultResourceManagerFactory());
748  //DefaultSceneManager
749  ManIt = this->ManagerFactories.find("DefaultSceneManager");
750  if( ManIt == this->ManagerFactories.end() ) this->AddManagerFactory(new Graphics::DefaultSceneManagerFactory());
751  //DefaultTerrainManager
752  ManIt = this->ManagerFactories.find("DefaultTerrainManager");
753  if( ManIt == this->ManagerFactories.end() ) this->AddManagerFactory(new DefaultTerrainManagerFactory());
754  //DefaultUIManager
755  ManIt = this->ManagerFactories.find("DefaultUIManager");
756  if( ManIt == this->ManagerFactories.end() ) this->AddManagerFactory(new UI::DefaultUIManagerFactory());
757 
758  #ifdef ENABLE_OALS_AUDIO_IMPLEMENTATION
759  //OALSAudioManager
760  ManIt = this->ManagerFactories.find("OALSAudioManager");
761  if( ManIt == this->ManagerFactories.end() ) this->AddManagerFactory(new Audio::OALS::OALSAudioManagerFactory());
762  //OALSSoundScapeManager
763  ManIt = this->ManagerFactories.find("OALSSoundScapeManager");
764  if( ManIt == this->ManagerFactories.end() ) this->AddManagerFactory(new Audio::OALS::OALSSoundScapeManagerFactory());
765  #endif //ENABLE_OALS_AUDIO_IMPLEMENTATION
766  }
767 
768  ///////////////////////////////////////////////////////////////////////////////
769  // Upper Management
770 
771  ManagerBase* Entresol::CreateManager(const String& ManagerImplName, NameValuePairList& Params, bool AddToWorld)
772  {
773  ManagerFactoryIterator ManIt = this->ManagerFactories.find(ManagerImplName);
774  if( ManIt == this->ManagerFactories.end() )
775  {
776  MEZZ_EXCEPTION(Exception::II_IDENTITY_NOT_FOUND_EXCEPTION,"Attempting to create manager of type \"" + ManagerImplName + "\", which has no factory registered.");
777  }
778  ManagerBase* NewMan = (*ManIt).second->CreateManager(Params);
779  if(AddToWorld)
780  this->AddManager(NewMan);
781  return NewMan;
782  }
783 
784  ManagerBase* Entresol::CreateManager(const String& ManagerImplName, XML::Node& XMLNode, bool AddToWorld)
785  {
786  ManagerFactoryIterator ManIt = this->ManagerFactories.find(ManagerImplName);
787  if( ManIt == this->ManagerFactories.end() )
788  {
789  MEZZ_EXCEPTION(Exception::II_IDENTITY_NOT_FOUND_EXCEPTION,"Attempting to create manager of type \"" + ManagerImplName + "\", which has no factory registered.");
790  }
791  ManagerBase* NewMan = (*ManIt).second->CreateManager(XMLNode);
792  if(AddToWorld)
793  this->AddManager(NewMan);
794  return NewMan;
795  }
796 
797  void Entresol::DestroyManager(ManagerBase* ToBeDestroyed)
798  {
799  ManagerFactoryIterator ManIt = this->ManagerFactories.find(ToBeDestroyed->GetImplementationTypeName());
800  if( ManIt == this->ManagerFactories.end() )
801  {
802  MEZZ_EXCEPTION(Exception::II_IDENTITY_NOT_FOUND_EXCEPTION,"Attempting to destroy manager of type \"" + ToBeDestroyed->GetImplementationTypeName() + "\", which has no factory registered.");
803  }
804  this->RemoveManager(ToBeDestroyed);
805  (*ManIt).second->DestroyManager(ToBeDestroyed);
806  }
807 
808  void Entresol::DestroyAllManagers()
809  {
810  //for( std::list<ManagerBase*>::iterator iter = --this->ManagerList.end(); !ManagerList.empty(); iter = --this->ManagerList.end() ) //Backward
811  /*for( std::list<ManagerBase*>::iterator iter = this->ManagerList.begin(); !ManagerList.empty(); iter = this->ManagerList.begin() ) //forward
812  {
813  ManagerBase* Current = (*iter);
814  #ifdef MEZZDEBUG
815  this->Log("Deleting " + Current->GetInterfaceTypeAsString() + ".");
816  this->DoMainLoopLogging();
817  #endif
818  ManagerFactoryIterator ManIt = this->ManagerFactories.find(Current->GetImplementationTypeName());
819  if( ManIt == this->ManagerFactories.end() ) {
820  MEZZ_EXCEPTION(Exception::II_IDENTITY_NOT_FOUND_EXCEPTION,"Attempting to destroy manager of type \"" + Current->GetImplementationTypeName() + "\", which has no factory registered.");
821  }else{
822  (*ManIt).second->DestroyManager(Current);
823  }
824  }
825  this->ManagerList.clear();//*/
826  while( !(this->ManagerList.empty()) )
827  {
828  ManagerBase* Current = this->ManagerList.front();
829  #ifdef MEZZDEBUG
830  this->Log("Deleting " + Current->GetInterfaceTypeAsString() + ".");
831  #endif
832 
833  ManagerFactoryIterator ManIt = this->ManagerFactories.find(Current->GetImplementationTypeName());
834  if( ManIt == this->ManagerFactories.end() ) {
835  MEZZ_EXCEPTION(Exception::II_IDENTITY_NOT_FOUND_EXCEPTION,"Attempting to destroy manager of type \"" + Current->GetImplementationTypeName() + "\", which has no factory registered.");
836  }else{
837  (*ManIt).second->DestroyManager(Current);
838  }
839 
840  this->ManagerList.pop_front();
841  }//*/
842  }
843 
844  void Entresol::AddManager(ManagerBase* ManagerToAdd)
845  {
846  #ifdef MEZZDEBUG
847  this->Log("Adding " + ManagerToAdd->GetInterfaceTypeAsString() + ".\n");
848  #endif
849  // We have to verify the manager is unique. A number of issues can arrise if a manager is double inserted.
850  for( std::list< ManagerBase* >::iterator ManIter = this->ManagerList.begin() ; ManIter != this->ManagerList.end() ; ++ManIter )
851  {
852  if( (*ManIter) == ManagerToAdd )
853  return;
854  }
855  this->ManagerList.push_back(ManagerToAdd);
856  }
857 
858  ManagerBase* Entresol::GetManager(const ManagerBase::ManagerType RetrieveType, UInt16 WhichOne)
859  {
860  for(std::list< ManagerBase* >::iterator ManIter = this->ManagerList.begin(); ManIter!=this->ManagerList.end(); ++ManIter )
861  {
862  if( (*ManIter)->GetInterfaceType() == RetrieveType )
863  {
864  if( 0 == WhichOne ) return *ManIter; // we use our copy of WhichOne as a countdown to 0
865  else --WhichOne;
866  }
867  }
868  return NULL;
869  }
870 
871  void Entresol::RemoveManager(ManagerBase* ManagerToRemove)
872  {
873  for( std::list< ManagerBase* >::iterator ManIter = this->ManagerList.begin() ; ManIter != this->ManagerList.end() ; ++ManIter )
874  {
875  if( *ManIter == ManagerToRemove )
876  {
877  this->ManagerList.erase(ManIter);
878  return;
879  }
880  }
881  }
882 
883  void Entresol::RemoveManager(const ManagerBase::ManagerType ManagersToRemoveType, UInt16 WhichOne)
884  {
885  for(std::list< ManagerBase* >::iterator ManIter = this->ManagerList.begin(); ManIter!=this->ManagerList.end(); ++ManIter )
886  {
887  if( (*ManIter)->GetInterfaceType() == ManagersToRemoveType )
888  {
889  if(0==WhichOne) // we use our copy of WhichOne as a countdown to 0
890  {
891  this->ManagerList.erase(ManIter);
892  return;
893  }else{
894  --WhichOne;
895  }
896  }
897  }
898  }
899 
900  ActorManager* Entresol::GetActorManager(const UInt16 WhichOne)
901  {
902  return dynamic_cast<ActorManager*>( this->GetManager(ManagerBase::MT_ActorManager, WhichOne) );
903  }
904 
905  AreaEffectManager* Entresol::GetAreaEffectManager(const UInt16 WhichOne)
906  {
907  return dynamic_cast<AreaEffectManager*>( this->GetManager(ManagerBase::MT_AreaEffectManager, WhichOne) );
908  }
909 
910  Audio::AudioManager* Entresol::GetAudioManager(const UInt16 WhichOne)
911  {
912  return dynamic_cast<Audio::AudioManager*>( this->GetManager(ManagerBase::MT_AudioManager, WhichOne) );
913  }
914 
915  Graphics::CameraManager* Entresol::GetCameraManager(const UInt16 WhichOne)
916  {
917  return dynamic_cast<Graphics::CameraManager*>( this->GetManager(ManagerBase::MT_CameraManager, WhichOne) );
918  }
919 
920  Physics::CollisionShapeManager* Entresol::GetCollisionShapeManager(const UInt16 WhichOne)
921  {
922  return dynamic_cast<Physics::CollisionShapeManager*>( this->GetManager(ManagerBase::MT_CollisionShapeManager, WhichOne) );
923  }
924 
925  DebrisManager* Entresol::GetDebrisManager(const UInt16 WhichOne)
926  {
927  return dynamic_cast<DebrisManager*>( this->GetManager(ManagerBase::MT_DebrisManager, WhichOne) );
928  }
929 
930  EventManager* Entresol::GetEventManager(const UInt16 WhichOne)
931  {
932  return dynamic_cast<EventManager*>( this->GetManager(ManagerBase::MT_EventManager, WhichOne) );
933  }
934 
935  Graphics::GraphicsManager* Entresol::GetGraphicsManager(const UInt16 WhichOne)
936  {
937  return dynamic_cast<Graphics::GraphicsManager*>( this->GetManager(ManagerBase::MT_GraphicsManager, WhichOne) );
938  }
939 
940  Input::InputManager* Entresol::GetInputManager(const UInt16 WhichOne)
941  {
942  return dynamic_cast<Input::InputManager*>( this->GetManager(ManagerBase::MT_InputManager, WhichOne) );
943  }
944 
945  Graphics::MeshManager* Entresol::GetMeshManager(const UInt16 WhichOne)
946  {
947  return dynamic_cast<Graphics::MeshManager*>( this->GetManager(ManagerBase::MT_MeshManager, WhichOne) );
948  }
949  #ifdef MEZZNETWORK
950  NetworkManager* Entresol::GetNetworkManager(const UInt16 WhichOne)
951  {
952  return dynamic_cast<NetworkManager*>( this->GetManager(ManagerBase::MT_NetworkManager, WhichOne) );
953  }
954  #endif
955  Physics::PhysicsManager* Entresol::GetPhysicsManager(const UInt16 WhichOne)
956  {
957  return dynamic_cast<Physics::PhysicsManager*>( this->GetManager(ManagerBase::MT_PhysicsManager, WhichOne) );
958  }
959 
960  Graphics::SceneManager* Entresol::GetSceneManager(const UInt16 WhichOne)
961  {
962  return dynamic_cast<Graphics::SceneManager*>( this->GetManager(ManagerBase::MT_SceneManager, WhichOne) );
963  }
964 
965  Audio::SoundScapeManager* Entresol::GetSoundScapeManager(const UInt16 WhichOne)
966  {
967  return dynamic_cast<Audio::SoundScapeManager*>( this->GetManager(ManagerBase::MT_SoundScapeManager, WhichOne) );
968  }
969 
970  ResourceManager* Entresol::GetResourceManager(const UInt16 WhichOne)
971  {
972  return dynamic_cast<ResourceManager*>( this->GetManager(ManagerBase::MT_ResourceManager, WhichOne) );
973  }
974 
975  UI::UIManager* Entresol::GetUIManager(const UInt16 WhichOne)
976  {
977  return dynamic_cast<UI::UIManager*>( this->GetManager(ManagerBase::MT_UIManager, WhichOne) );
978  }
979 
980 }
981 #endif