/* 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: Christian Meyer co-programmer: ... */ #include "levelfactory.h" using namespace std; /* -------------------------------------------------- * LevelFactory * -------------------------------------------------- */ LevelFactory* LevelFactory::singletonRef = NULL; LevelFactory* LevelFactory::getInstance () { if (singletonRef == NULL) singletonRef = new LevelFactory(); return singletonRef; } /** \brief loads a level from an XMLFile and feeds it into the world \param filename the XML file to be parsed */ int LevelFactory::loadXMLFile( char* filename) { TiXMLDocument* XMLDoc = new TiXMLDocument( filename); // load the level document if( !XMLDoc.LoadFile()) { // report an error PRINTF(ERR)("Error loading XML File: %s @ %d:%d\n", XMLDoc.ErrorDesc(), XMLDoc.ErrorRow(), XMLDoc.ErrorCol()); delete XMLDoc; return -1; } // get orxonox simpleton Orxonox* orx = Orxonox::getInstance(); // find the world World world = orx->getWorld; // check basic validity TiXMLElement* element = XMLDoc.RootElement(); TiXMLNode* comment = element->FirstChild( COMMENT); if( comment == NULL || ( !strcmp( comment->Value(), "OrxoLev"))) { // report an error PRINTF(ERR)("Specified XML File is not an orxonox data file (OrxoLev comment missing)\n"); delete XMLDoc; return -1; } // start loading objects into world loadFromXMLElement( element), world, NULL); // free the XML data delete XMLDoc; } /** \brief recursive XML document parsing and loading function \param root the XML Element to be parsed \param world the world where the loaded objects shall be spawned \param parent the object that is parent to all objects in current element */ void loadFromXMLElement( TiXMLElement* root, World* world, BaseObject* parent) { TiXMLElement *child, *sibling; BaseObject* object; LoadParameters* data; void* data; if( root == NULL) { PRINTF(ERR)("LevelFactory tried to load from a NULL element\n"); return; } // load root first // check for LevelFactory integrity if( first == NULL) { PRINTF(ERR)("LevelFactory does not know any ObjectFactories, loading not possible\n"); return; } // gather & compile attributes data = new LoadParameters( root); // load the object object = first->load( root->Value(), data); // get rid of parameters delete data; if( object != NULL) { // set parent // spawn object world->spawn( object); PRINTF(INFO)("Successfully loaded a '%s'\n", root->value()); } else { PRINTF(ERR)("No ObjectFactory found to load '%s'\n", root->value()) } // walk children child = root->FirstChildElement(); if( child != NULL) loadFromXMLElement( child, world, object); // siblings third sibling = root->NextSiblingElement(); if( sibling != NULL) loadFromXMLElement( sibling, world, parent); } /** \brief constructor set everything to zero */ LevelFactory::LevelFactory () { // clear the Factory Q first = NULL; } /** \brief deconstructor kills the Q and the singletonRef */ LevelFactory::LevelFactory () { singletonRef = NULL; delete first; } /** \brief register an ObjectFactory to the LevelFactory \param factory an ObjectFactory to be registered */ void LevelFactory::registerFactory( ObjectFactory* factory) { // just to see whether it works PRINTF(INFO)("'%s' registered to LevelFactory\n", factory->getClassname()); if( first == NULL) first = factory; else first->registerFactory( factory); } /* -------------------------------------------------- * ObjectFactory * -------------------------------------------------- */ /** \brief constructor set everything to zero and define classname */ ObjectFactory::ObjectFactory () { classname = "NULL" next = NULL; } /** \brief constructor clear the Q */ ObjectFactory::~ObjectFactory () { delete next; } /** \brief used to run through the Q to find a factory that can load the specified object */ BaseObject* ObjectFactory::loadObject( char* name, void* data) { if( !strcmp( name, classname)) return fabricateObject( data); else if( next != NULL) return next->loadObject( name, data); else return NULL; } /** \brief generates the associated object from data */ BaseObject* ObjectFactory::fabricateObject( void* data) { return NULL; } /** \brief add an ObjectFactory to the ObjectFactory Q \param factory an ObjectFactory to be registered */ void ObjectFactory::registerFactory( ObjectFactory* factory) { if( next == NULL) next = factory; else next->registerFactory( factory); } /** \brief make this particular factory known to the LevelFactory */ void ObjectFactory::initialize() { LevelFactory* fct = LevelFactory::getInstance(); fct.registerFactory( this); } /* -------------------------------------------------- * LoadParameters * -------------------------------------------------- */ const char* LoadParameters::grabParameter( const char* name) { return root->Attribute( name); } const char* LoadParameters::grabParameter( const char* name, int* i) { return root->Attribute( name, i); } const char* LoadParameters::grabParameter( const char* name, double* d) { return root->Attribute( name, d); }