[3482] | 1 | |
---|
| 2 | |
---|
| 3 | /* |
---|
| 4 | orxonox - the future of 3D-vertical-scrollers |
---|
| 5 | |
---|
| 6 | Copyright (C) 2004 orx |
---|
| 7 | |
---|
| 8 | This program is free software; you can redistribute it and/or modify |
---|
| 9 | it under the terms of the GNU General Public License as published by |
---|
| 10 | the Free Software Foundation; either version 2, or (at your option) |
---|
| 11 | any later version. |
---|
| 12 | |
---|
| 13 | ### File Specific: |
---|
| 14 | main-programmer: Christian Meyer |
---|
| 15 | co-programmer: ... |
---|
| 16 | */ |
---|
| 17 | |
---|
| 18 | |
---|
| 19 | #include "levelfactory.h" |
---|
| 20 | |
---|
| 21 | using namespace std; |
---|
| 22 | |
---|
| 23 | /* -------------------------------------------------- |
---|
| 24 | * LevelFactory |
---|
| 25 | * -------------------------------------------------- |
---|
| 26 | */ |
---|
| 27 | |
---|
| 28 | LevelFactory* LevelFactory::singletonRef = NULL; |
---|
| 29 | |
---|
| 30 | LevelFactory* LevelFactory::getInstance () |
---|
| 31 | { |
---|
| 32 | if (singletonRef == NULL) |
---|
| 33 | singletonRef = new LevelFactory(); |
---|
| 34 | return singletonRef; |
---|
| 35 | } |
---|
| 36 | |
---|
| 37 | /** |
---|
| 38 | \brief loads a level from an XMLFile and feeds it into the world |
---|
| 39 | \param filename the XML file to be parsed |
---|
| 40 | |
---|
| 41 | */ |
---|
| 42 | int LevelFactory::loadXMLFile( char* filename) |
---|
| 43 | { |
---|
| 44 | TiXMLDocument* XMLDoc = new TiXMLDocument( filename); |
---|
| 45 | // load the level document |
---|
| 46 | if( !XMLDoc.LoadFile()) |
---|
| 47 | { |
---|
[3496] | 48 | // report an error |
---|
| 49 | PRINTF(ERR)("Error loading XML File: %s @ %d:%d\n", XMLDoc.ErrorDesc(), XMLDoc.ErrorRow(), XMLDoc.ErrorCol()); |
---|
| 50 | delete XMLDoc; |
---|
[3482] | 51 | return -1; |
---|
| 52 | } |
---|
| 53 | |
---|
| 54 | // get orxonox simpleton |
---|
[3496] | 55 | Orxonox* orx = Orxonox::getInstance(); |
---|
| 56 | |
---|
[3482] | 57 | // find the world |
---|
[3496] | 58 | World world = orx->getWorld; |
---|
| 59 | |
---|
| 60 | // check basic validity |
---|
| 61 | TiXMLElement* element = XMLDoc.RootElement(); |
---|
| 62 | TiXMLNode* comment = element->FirstChild( COMMENT); |
---|
| 63 | |
---|
| 64 | if( comment == NULL || ( !strcmp( comment->Value(), "OrxoLev"))) |
---|
| 65 | { |
---|
| 66 | // report an error |
---|
| 67 | PRINTF(ERR)("Specified XML File is not an orxonox data file (OrxoLev comment missing)\n"); |
---|
| 68 | delete XMLDoc; |
---|
| 69 | return -1; |
---|
| 70 | } |
---|
| 71 | |
---|
[3482] | 72 | // start loading objects into world |
---|
[3496] | 73 | loadFromXMLElement( element), world, NULL); |
---|
| 74 | |
---|
[3482] | 75 | // free the XML data |
---|
[3496] | 76 | delete XMLDoc; |
---|
[3482] | 77 | } |
---|
| 78 | |
---|
| 79 | /** |
---|
[3496] | 80 | \brief recursive XML document parsing and loading function |
---|
| 81 | \param root the XML Element to be parsed |
---|
| 82 | \param world the world where the loaded objects shall be spawned |
---|
| 83 | \param parent the object that is parent to all objects in current element |
---|
| 84 | */ |
---|
| 85 | |
---|
| 86 | void loadFromXMLElement( TiXMLElement* root, World* world, BaseObject* parent) |
---|
| 87 | { |
---|
| 88 | TiXMLElement *child, *sibling; |
---|
| 89 | BaseObject* object; |
---|
| 90 | LoadParameters* data; |
---|
| 91 | void* data; |
---|
| 92 | |
---|
| 93 | if( root == NULL) |
---|
| 94 | { |
---|
| 95 | PRINTF(ERR)("LevelFactory tried to load from a NULL element\n"); |
---|
| 96 | return; |
---|
| 97 | } |
---|
| 98 | |
---|
| 99 | // load root first |
---|
| 100 | |
---|
| 101 | // check for LevelFactory integrity |
---|
| 102 | if( first == NULL) |
---|
| 103 | { |
---|
| 104 | PRINTF(ERR)("LevelFactory does not know any ObjectFactories, loading not possible\n"); |
---|
| 105 | return; |
---|
| 106 | } |
---|
| 107 | |
---|
| 108 | // gather & compile attributes |
---|
| 109 | data = new LoadParameters( root); |
---|
| 110 | |
---|
| 111 | // load the object |
---|
| 112 | object = first->load( root->Value(), data); |
---|
| 113 | |
---|
| 114 | // get rid of parameters |
---|
| 115 | delete data; |
---|
| 116 | |
---|
| 117 | if( object != NULL) |
---|
| 118 | { |
---|
| 119 | // set parent |
---|
| 120 | |
---|
| 121 | // spawn object |
---|
| 122 | world->spawn( object); |
---|
| 123 | PRINTF(INFO)("Successfully loaded a '%s'\n", root->value()); |
---|
| 124 | } |
---|
| 125 | else |
---|
| 126 | { |
---|
| 127 | PRINTF(ERR)("No ObjectFactory found to load '%s'\n", root->value()) |
---|
| 128 | } |
---|
| 129 | |
---|
| 130 | // walk children |
---|
| 131 | child = root->FirstChildElement(); |
---|
| 132 | if( child != NULL) loadFromXMLElement( child, world, object); |
---|
| 133 | |
---|
| 134 | // siblings third |
---|
| 135 | sibling = root->NextSiblingElement(); |
---|
| 136 | if( sibling != NULL) loadFromXMLElement( sibling, world, parent); |
---|
| 137 | } |
---|
| 138 | |
---|
| 139 | /** |
---|
[3482] | 140 | \brief constructor |
---|
| 141 | |
---|
| 142 | set everything to zero |
---|
| 143 | */ |
---|
| 144 | LevelFactory::LevelFactory () |
---|
| 145 | { |
---|
| 146 | // clear the Factory Q |
---|
| 147 | first = NULL; |
---|
| 148 | } |
---|
| 149 | |
---|
| 150 | /** |
---|
| 151 | \brief deconstructor |
---|
| 152 | |
---|
| 153 | kills the Q and the singletonRef |
---|
| 154 | */ |
---|
| 155 | LevelFactory::LevelFactory () |
---|
| 156 | { |
---|
| 157 | singletonRef = NULL; |
---|
| 158 | delete first; |
---|
| 159 | } |
---|
| 160 | |
---|
| 161 | /** |
---|
| 162 | \brief register an ObjectFactory to the LevelFactory |
---|
| 163 | \param factory an ObjectFactory to be registered |
---|
| 164 | */ |
---|
| 165 | void LevelFactory::registerFactory( ObjectFactory* factory) |
---|
| 166 | { |
---|
[3496] | 167 | // just to see whether it works |
---|
| 168 | PRINTF(INFO)("'%s' registered to LevelFactory\n", factory->getClassname()); |
---|
[3482] | 169 | if( first == NULL) first = factory; |
---|
| 170 | else first->registerFactory( factory); |
---|
| 171 | } |
---|
| 172 | |
---|
| 173 | /* -------------------------------------------------- |
---|
| 174 | * ObjectFactory |
---|
| 175 | * -------------------------------------------------- |
---|
| 176 | */ |
---|
| 177 | |
---|
| 178 | /** |
---|
| 179 | \brief constructor |
---|
| 180 | |
---|
| 181 | set everything to zero and define classname |
---|
| 182 | */ |
---|
| 183 | ObjectFactory::ObjectFactory () |
---|
| 184 | { |
---|
| 185 | classname = "NULL" |
---|
| 186 | next = NULL; |
---|
| 187 | } |
---|
| 188 | |
---|
| 189 | /** |
---|
| 190 | \brief constructor |
---|
| 191 | |
---|
| 192 | clear the Q |
---|
| 193 | */ |
---|
| 194 | ObjectFactory::~ObjectFactory () |
---|
| 195 | { |
---|
| 196 | delete next; |
---|
| 197 | } |
---|
| 198 | |
---|
| 199 | /** |
---|
| 200 | \brief used to run through the Q to find a factory that can load the specified object |
---|
| 201 | */ |
---|
[3497] | 202 | BaseObject* ObjectFactory::loadObject( char* name, LoadParameters* data) |
---|
[3482] | 203 | { |
---|
| 204 | if( !strcmp( name, classname)) return fabricateObject( data); |
---|
| 205 | else if( next != NULL) return next->loadObject( name, data); |
---|
| 206 | else return NULL; |
---|
| 207 | } |
---|
| 208 | |
---|
| 209 | /** |
---|
| 210 | \brief generates the associated object from data |
---|
| 211 | */ |
---|
[3497] | 212 | BaseObject* ObjectFactory::fabricateObject( LoadParameters* data) |
---|
[3482] | 213 | { |
---|
| 214 | return NULL; |
---|
| 215 | } |
---|
| 216 | |
---|
| 217 | /** |
---|
| 218 | \brief add an ObjectFactory to the ObjectFactory Q |
---|
| 219 | \param factory an ObjectFactory to be registered |
---|
| 220 | */ |
---|
| 221 | void ObjectFactory::registerFactory( ObjectFactory* factory) |
---|
| 222 | { |
---|
| 223 | if( next == NULL) next = factory; |
---|
| 224 | else next->registerFactory( factory); |
---|
| 225 | } |
---|
| 226 | |
---|
| 227 | /** |
---|
| 228 | \brief make this particular factory known to the LevelFactory |
---|
| 229 | */ |
---|
| 230 | void ObjectFactory::initialize() |
---|
| 231 | { |
---|
| 232 | LevelFactory* fct = LevelFactory::getInstance(); |
---|
| 233 | fct.registerFactory( this); |
---|
| 234 | } |
---|
[3496] | 235 | |
---|
| 236 | /* -------------------------------------------------- |
---|
| 237 | * LoadParameters |
---|
| 238 | * -------------------------------------------------- |
---|
| 239 | */ |
---|
| 240 | |
---|
| 241 | const char* LoadParameters::grabParameter( const char* name) |
---|
| 242 | { |
---|
| 243 | return root->Attribute( name); |
---|
| 244 | } |
---|
| 245 | |
---|
| 246 | const char* LoadParameters::grabParameter( const char* name, int* i) |
---|
| 247 | { |
---|
| 248 | return root->Attribute( name, i); |
---|
| 249 | } |
---|
| 250 | |
---|
| 251 | const char* LoadParameters::grabParameter( const char* name, double* d) |
---|
| 252 | { |
---|
| 253 | return root->Attribute( name, d); |
---|
| 254 | } |
---|