Changeset 2662 for code/trunk/src/core/XMLPort.h
- Timestamp:
- Feb 14, 2009, 10:17:35 PM (16 years ago)
- Location:
- code/trunk
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
code/trunk
- Property svn:mergeinfo changed
-
code/trunk/src/core/XMLPort.h
r2171 r2662 43 43 #include "CorePrereqs.h" 44 44 45 #include <cassert> 45 46 #include "util/Debug.h" 46 47 #include "util/Exception.h" … … 74 75 static ExecutorMember<classname>* xmlcontainer##loadfunction##savefunction##saveexecutor = orxonox::createExecutor(orxonox::createFunctor(&classname::savefunction), std::string( #classname ) + "::" + #savefunction); \ 75 76 XMLPortParamGeneric(xmlcontainer##loadfunction##savefunction, classname, classname, this, paramname, xmlcontainer##loadfunction##savefunction##loadexecutor, xmlcontainer##loadfunction##savefunction##saveexecutor, xmlelement, mode) 77 78 /** 79 @brief Declares an XML attribute with a name, which will be set through a variable. 80 @param classname The name of the class owning this param 81 @param paramname The name of the attribute 82 @param variable Name of the variable used to save and load the value 83 @param xmlelement The XMLElement, you get this from the XMLPort function 84 @param mode The mode (load or save), you get this from the XMLPort function 85 86 In the XML file, a param or attribute will be set like this: 87 <classname paramname="value" /> 88 89 The macro will then store "value" in the variable or read it when saving. 90 */ 91 #define XMLPortParamVariable(classname, paramname, variable, xmlelement, mode) \ 92 XMLPortVariableHelperClass xmlcontainer##variable##dummy((void*)&variable); \ 93 static ExecutorMember<orxonox::XMLPortVariableHelperClass>* xmlcontainer##variable##loadexecutor = static_cast<ExecutorMember<orxonox::XMLPortVariableHelperClass>*>(orxonox::createExecutor(orxonox::createFunctor(orxonox::XMLPortVariableHelperClass::getLoader(variable)), std::string( #classname ) + "::" + #variable + "loader")); \ 94 static ExecutorMember<orxonox::XMLPortVariableHelperClass>* xmlcontainer##variable##saveexecutor = static_cast<ExecutorMember<orxonox::XMLPortVariableHelperClass>*>(orxonox::createExecutor(orxonox::createFunctor(orxonox::XMLPortVariableHelperClass::getSaver (variable)), std::string( #classname ) + "::" + #variable + "saver" )); \ 95 XMLPortParamGeneric(xmlcontainer##variable, classname, orxonox::XMLPortVariableHelperClass, &xmlcontainer##variable##dummy, paramname, xmlcontainer##variable##loadexecutor, xmlcontainer##variable##saveexecutor, xmlelement, mode) 96 76 97 /** 77 98 @brief This is the same as XMLPortParam, but you can set the template arguments needed to store the loadfunction. … … 161 182 ClassIdentifier<classname>::getIdentifier()->addXMLPortParamContainer(paramname, containername); \ 162 183 } \ 163 containername->port( (BaseObject*)this, object, xmlelement, mode)184 containername->port(static_cast<BaseObject*>(this), object, xmlelement, mode) 164 185 165 186 // -------------------- … … 175 196 @param xmlelement The XMLElement (recieved through the XMLPort function) 176 197 @param mode The mode (load/save) (received through the XMLPort function) 177 @param bApplyLoaderMask If this is true, an added sub-object only gets loadedif it's class is included in the Loaders ClassTreeMask (this is usually false)178 @param bLoadBefore If this is true, the sub- cobject gets loaded (through XMLPort) BEFORE it gets added to the main class (this is usually true)198 @param bApplyLoaderMask If this is true, an added sub-object gets loaded only if it's class is included in the Loaders ClassTreeMask (this is usually false) 199 @param bLoadBefore If this is true, the sub-object gets loaded (through XMLPort) BEFORE it gets added to the main class (this is usually true) 179 200 180 201 bApplyLoaderMask is usually false for the following reason: … … 183 204 Of course, if there are "standalone" weapons in the level, they wont be loaded. 184 205 185 If bLoadBefore , an added object already has all attributes set (like it's name). This is most206 If bLoadBefore is true, an added object already has all attributes set (like it's name). This is most 186 207 likely the best option, so this is usually true. 187 208 … … 222 243 Note that "weapons" is the subsection. This allows you to add more types of sub-objects. In our example, 223 244 you could add pilots, blinking lights or other stuff. If you don't want a subsection, just use "" (an 224 empty string). The you can add sub-objects directly into the mainclass.245 empty string). Then you can add sub-objects directly into the mainclass. 225 246 */ 226 247 #define XMLPortObjectExtended(classname, objectclass, sectionname, loadfunction, savefunction, xmlelement, mode, bApplyLoaderMask, bLoadBefore) \ … … 329 350 } 330 351 352 ~XMLPortClassParamContainer() 353 { 354 assert(this->loadexecutor_); 355 delete this->loadexecutor_; 356 if (this->saveexecutor_) 357 delete this->saveexecutor_; 358 } 359 331 360 XMLPortParamContainer& port(BaseObject* owner, T* object, Element& xmlelement, XMLPort::Mode mode) 332 361 { 362 OrxAssert(owner, "XMLPortParamContainer must have a BaseObject as owner."); 333 363 this->owner_ = owner; 334 364 this->parseParams_.object = object; … … 336 366 this->parseParams_.mode = mode; 337 367 338 if ( mode == XMLPort::LoadObject)368 if ((mode == XMLPort::LoadObject) || (mode == XMLPort::ExpandObject)) 339 369 { 340 370 try 341 371 { 342 std::string attribute = xmlelement.GetAttribute(this->paramname_); 343 if ((attribute.size() > 0) || (this->loadexecutor_->allDefaultValuesSet())) 372 if (this->owner_->lastLoadedXMLElement_ != &xmlelement) 373 { 374 this->owner_->xmlAttributes_.clear(); 375 // Iterate through the attributes manually in order to make them case insensitive 376 Attribute* attribute = xmlelement.FirstAttribute(false); 377 while (attribute != 0) 378 { 379 this->owner_->xmlAttributes_[getLowercase(attribute->Name())] = attribute->Value(); 380 attribute = attribute->Next(false); 381 } 382 this->owner_->lastLoadedXMLElement_ = &xmlelement; 383 } 384 std::map<std::string, std::string>::const_iterator it = this->owner_->xmlAttributes_.find(getLowercase(this->paramname_)); 385 std::string attributeValue(""); 386 if (it != this->owner_->xmlAttributes_.end()) 387 attributeValue = it->second; 388 389 // TODO: Checking the iterator would be better since then we can have strings with value "" as well. 390 // Unfortunately this does not seem to work with the Executor parser yet. 391 if ((!attributeValue.empty()) || ((mode != XMLPort::ExpandObject) && this->loadexecutor_->allDefaultValuesSet())) 344 392 { 345 393 COUT(5) << this->owner_->getLoaderIndentation() << "Loading parameter " << this->paramname_ << " in " << this->identifier_->getName() << " (objectname " << this->owner_->getName() << ")." << std::endl << this->owner_->getLoaderIndentation(); 346 if (this->loadexecutor_->parse(object, attribute , ","))394 if (this->loadexecutor_->parse(object, attributeValue, ",") || (mode == XMLPort::ExpandObject)) 347 395 this->parseResult_ = PR_finished; 348 396 else 349 397 this->parseResult_ = PR_waiting_for_default_values; 350 398 } 399 else if (mode == XMLPort::ExpandObject) 400 this->parseResult_ = PR_finished; 351 401 else 352 402 this->parseResult_ = PR_waiting_for_default_values; … … 471 521 } 472 522 523 ~XMLPortClassObjectContainer() 524 { 525 assert(this->loadexecutor_); 526 delete this->loadexecutor_; 527 if (this->saveexecutor_) 528 delete this->saveexecutor_; 529 } 530 473 531 XMLPortObjectContainer& port(T* object, Element& xmlelement, XMLPort::Mode mode) 474 532 { 475 if ( mode == XMLPort::LoadObject)533 if ((mode == XMLPort::LoadObject) || (mode == XMLPort::ExpandObject)) 476 534 { 477 535 try … … 588 646 ExecutorMember<T>* saveexecutor_; 589 647 }; 648 649 650 // #################################### 651 // ### XMLPortVariableHelperClass ### 652 // #################################### 653 /** 654 @brief 655 Helper class to load and save simple variables with XMLPort. 656 657 getLoader and getSaver were necessary to get the type T with 658 the help of template function type deduction (const T& is unused). 659 These functions return the adress of save<T> or load<T>. 660 */ 661 class XMLPortVariableHelperClass 662 { 663 public: 664 XMLPortVariableHelperClass(void* var) 665 : variable_(var) 666 { } 667 668 template <class T> 669 void load(const T& value) 670 { *((T*)this->variable_) = value; } 671 672 template <class T> 673 const T& save() 674 { return *((T*)this->variable_); } 675 676 template <class T> 677 static void (XMLPortVariableHelperClass::*getLoader(const T& var))(const T& value) 678 { return &XMLPortVariableHelperClass::load<T>; } 679 680 template <class T> 681 static const T& (XMLPortVariableHelperClass::*getSaver(const T& var))() 682 { return &XMLPortVariableHelperClass::save<T>; } 683 684 private: 685 void* variable_; 686 }; 590 687 } 591 688
Note: See TracChangeset
for help on using the changeset viewer.