Index: orxonox/trunk/src/util/loading/game_loader.cc
===================================================================
--- orxonox/trunk/src/util/loading/game_loader.cc	(revision 4262)
+++ orxonox/trunk/src/util/loading/game_loader.cc	(revision 4262)
@@ -0,0 +1,318 @@
+
+
+/* 
+   orxonox - the future of 3D-vertical-scrollers
+
+   Copyright (C) 2004 orx
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   ### File Specific:
+   main-programmer: Patrick Boenzli
+   co-programmer: ...
+*/
+
+#include "game_loader.h"
+#include "campaign.h"
+#include "world.h"
+#include "player.h"
+#include "orxonox.h"
+#include "camera.h"
+#include "command_node.h"
+#include "vector.h"
+#include "resource_manager.h"
+#include "factory.h"
+
+#include <string.h>
+
+
+using namespace std;
+
+
+GameLoader* GameLoader::singletonRef = 0;
+
+
+GameLoader::GameLoader () 
+{
+  first = NULL;
+}
+
+
+GameLoader::~GameLoader () {}
+
+
+/**
+   \brief this class is a singleton class
+   \returns an instance of itself
+
+   if you are unsure about singleton classes, check the theory out on the internet :)
+*/
+GameLoader* GameLoader::getInstance()
+{
+  if(singletonRef == NULL)
+    singletonRef = new GameLoader();
+  return singletonRef;
+}
+
+
+ErrorMessage GameLoader::init()
+{
+  if(this->currentCampaign != NULL)
+    this->currentCampaign->init();
+}
+
+
+/**
+   \brief reads a campaign definition file into a campaign class
+   \param filename to be loaded
+   \returns the loaded campaign
+
+   this will interprete the map/campaign files and recursivly load a tree of worlds/campaigns
+*/
+ErrorMessage GameLoader::loadCampaign(const char* name)
+{
+  ErrorMessage errorCode;
+  char* campaignName = ResourceManager::getFullName(name);
+  if (campaignName)
+    {
+      this->currentCampaign = this->fileToCampaign(campaignName);
+      delete campaignName;
+    }
+}
+
+/**
+   \brief loads a debug campaign for test purposes only.
+   \param the identifier of the campaign.
+   \returns error message if not able to do so.
+*/
+ErrorMessage GameLoader::loadDebugCampaign(Uint32 campaignID)
+{
+  switch(campaignID)
+    {
+      /* 
+	 Debug Level 0: Debug level used to test the base frame work.
+	 As you can see, all storyentity data is allocated before game
+	 start. the storyentity will load themselfs shortly before start
+	 through the StoryEntity::init() funtion.
+      */
+    case DEBUG_CAMPAIGN_0:
+      {
+	Campaign* debugCampaign = new Campaign();
+
+	World* world0 = new World(DEBUG_WORLD_0);
+	world0->setNextStoryID(WORLD_ID_1);
+	debugCampaign->addEntity(world0, WORLD_ID_0);
+
+	World* world1 = new World(DEBUG_WORLD_1);
+	world1->setNextStoryID(WORLD_ID_2);
+	debugCampaign->addEntity(world1, WORLD_ID_1);
+
+	World* world2 = new World(DEBUG_WORLD_2);
+	world2->setNextStoryID(WORLD_ID_GAMEEND);
+	debugCampaign->addEntity(world2, WORLD_ID_2);
+
+	this->currentCampaign = debugCampaign;
+	break;
+      }
+    }
+}
+
+ErrorMessage GameLoader::start()
+{
+  if(this->currentCampaign != NULL)
+    this->currentCampaign->start();
+}
+
+
+ErrorMessage GameLoader::stop()
+{
+  if(this->currentCampaign != NULL)
+    this->currentCampaign->stop();
+  this->currentCampaign = NULL;
+}
+
+
+ErrorMessage GameLoader::pause()
+{
+  this->isPaused = true;
+  if(this->currentCampaign != NULL)
+    this->currentCampaign->pause();
+}
+
+
+ErrorMessage GameLoader::resume()
+{
+  this->isPaused = false;
+  if(this->currentCampaign != NULL)
+    this->currentCampaign->resume();
+}
+
+/**
+   \brief release the mem
+ */
+ErrorMessage GameLoader::destroy()
+{}
+
+
+/**
+   \brief reads a campaign definition file into a campaign class
+   \param filename to be loaded
+   \returns the loaded campaign
+
+   this will interprete the map/campaign files and recursivly load a tree of worlds/campaigns
+*/
+Campaign* GameLoader::fileToCampaign(const char *name)
+{
+  /* do not entirely load the campaign. just the current world
+     before start of each world, it has to be initialized so it
+     can load everything it needs into memory then.
+  */
+  
+  if( name == NULL)
+    {
+      PRINTF(2)("No filename specified for loading");
+      return NULL;
+    }
+  
+  TiXmlDocument* XMLDoc = new TiXmlDocument( name);
+  // load the campaign document
+  if( !XMLDoc->LoadFile())
+    {
+      // report an error
+      PRINTF(1)("Could not load XML File %s: %s @ %d:%d\n", name, XMLDoc->ErrorDesc(), XMLDoc->ErrorRow(), XMLDoc->ErrorCol());
+      delete XMLDoc;
+      return NULL;
+    }
+	
+  // check basic validity
+  TiXmlElement* root = XMLDoc->RootElement();
+  assert( root != NULL);
+	
+  if( strcmp( root->Value(), "Campaign"))
+    {
+      // report an error
+      PRINTF(2)("Specified XML File is not an orxonox campaign file (Campaign element missing)\n");
+      delete XMLDoc;
+      return NULL;
+    }
+	
+  // construct campaign
+  Campaign* c = new Campaign( root);
+	
+  // free the XML data
+  delete XMLDoc;
+	
+  return c;
+}
+
+
+/**
+   \brief handle keyboard commands 
+   \param cmd: the command to handle
+   \returns true if the command was handled by the system
+*/
+bool GameLoader::worldCommand (Command* cmd)
+{
+  if( !strcmp( cmd->cmd, CONFIG_NAME_NEXT_WORLD))
+    {
+      if( !cmd->bUp) 
+	{
+	  this->nextLevel();
+	}
+      return true;
+    }
+  else if( !strcmp( cmd->cmd, CONFIG_NAME_PREV_WORLD))
+    {
+      if( !cmd->bUp)
+	{
+	  this->previousLevel();
+	}
+      return true;
+    }
+  else if( !strcmp( cmd->cmd, CONFIG_NAME_PAUSE))
+    {
+      if( !cmd->bUp)
+	{
+	  if(this->isPaused)
+	    this->resume();
+	  else
+	    this->pause();
+	}
+      return true;
+    }
+  else if( !strcmp( cmd->cmd, CONFIG_NAME_QUIT))
+    {
+      if( !cmd->bUp) this->stop();
+      return true;
+    }
+  return false;
+}
+
+
+/*
+  \brief this changes to the next level
+*/
+void GameLoader::nextLevel()
+{
+  if(this->currentCampaign != NULL)
+    this->currentCampaign->nextLevel();
+}
+
+
+/*
+  \brief change to the previous level - not implemented
+
+  this propably useless
+*/
+void GameLoader::previousLevel()
+{
+  if(this->currentCampaign != NULL)
+    this->currentCampaign->previousLevel();
+}
+
+/**
+   \brief add a Factory to the Factory Q
+   \param factory a Factory to be registered
+*/
+void GameLoader::registerFactory( Factory* factory)
+{
+	assert( factory != NULL);
+	
+	PRINTF(4)("Registered factory for '%s'\n", factory->getFactoryName());
+	
+	if( first == NULL) first = factory;
+	else first->registerFactory( factory);
+}
+
+/**
+   \brief load a StoryEntity
+   \param element a XMLElement containing all the needed info
+*/
+BaseObject* GameLoader::fabricate( TiXmlElement* element)
+{
+  assert( element != NULL);
+	
+  if( first == NULL)
+    {
+      PRINTF(1)("GameLoader does not know any factories, fabricate() failed\n");
+      return NULL;
+    }
+	
+  if( element->Value() != NULL)
+    {
+      PRINTF(4)("Attempting fabrication of a '%s'\n", element->Value());
+      BaseObject* b = first->fabricate( element);
+      if( b == NULL) 
+	PRINTF(2)("Failed to fabricate a '%s'\n", element->Value());
+      else 
+	PRINTF(4)("Successfully fabricated a '%s'\n", element->Value());
+      return b;
+    }
+	
+  PRINTF(2)("Fabricate failed, TiXmlElement did not contain a value\n");
+	
+  return NULL;
+}
Index: orxonox/trunk/src/util/loading/game_loader.h
===================================================================
--- orxonox/trunk/src/util/loading/game_loader.h	(revision 4262)
+++ orxonox/trunk/src/util/loading/game_loader.h	(revision 4262)
@@ -0,0 +1,74 @@
+/*! 
+    \file game_loader.h
+    \brief loads campaigns, worlds and all other story_entities
+*/ 
+
+#ifndef _GAME_LOADER_H
+#define _GAME_LOADER_H
+
+//#include "stdincl.h"
+#include "story_def.h"
+#include "comincl.h"
+
+
+//-----------------------------------------------------------------------------
+// Forward declarations
+//-----------------------------------------------------------------------------
+class Campaign;
+class World;
+class Camera;
+class CammandNode;
+class Factory;
+class TiXmlElement;
+class BaseObject;
+
+//! The GameLoader
+/**
+   The game loader loads all game date. this is performed in the following way:
+   1. Read the structure of campaings and worlds
+   2. Create the instances of the tree: here _ALL_ StoryEntities are created
+      also if they are not yet used. the worlds should load their data in
+      the StoryEntity::load() and StoryEntity::init() functions! NOWHERE ELSE!
+      Elsewhere, all the data will be allocated at the beginning... mess...
+   3. StoryEntities are load() and init() before they start
+   4. once the gamloader starts the game there will be a campaing starting a
+      world. this is done by callaing those StoryEntity::start()
+*/
+class GameLoader 
+{
+
+ public:
+  static GameLoader* getInstance();
+
+  ErrorMessage init();
+  ErrorMessage loadCampaign(const char* name);
+  ErrorMessage start();
+  ErrorMessage stop();
+  ErrorMessage pause();
+  ErrorMessage resume();
+  ErrorMessage destroy();
+
+  void nextLevel();
+  void previousLevel();
+
+  bool worldCommand(Command* cmd);
+  ErrorMessage loadDebugCampaign(Uint32 campaignID);
+  
+  void registerFactory( Factory* factory);
+  BaseObject* fabricate( TiXmlElement* data);
+
+ private:
+  GameLoader ();
+  ~GameLoader ();
+  Uint32 startTime; //!> start time of the campaign
+  static GameLoader* singletonRef;
+  bool isPaused;
+
+  Campaign* currentCampaign; //!> the current campaign playing
+  
+  Campaign* fileToCampaign(const char* name);
+
+  Factory* first;
+};
+
+#endif /* _GAME_LOADER_H */
