Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

Ignore:
Timestamp:
Feb 14, 2009, 10:17:35 PM (16 years ago)
Author:
rgrieder
Message:

Merged presentation branch back to trunk.

Location:
code/trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • code/trunk

  • code/trunk/src/core/XMLPort.h

    r2171 r2662  
    4343#include "CorePrereqs.h"
    4444
     45#include <cassert>
    4546#include "util/Debug.h"
    4647#include "util/Exception.h"
     
    7475    static ExecutorMember<classname>* xmlcontainer##loadfunction##savefunction##saveexecutor = orxonox::createExecutor(orxonox::createFunctor(&classname::savefunction), std::string( #classname ) + "::" + #savefunction); \
    7576    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
    7697/**
    7798    @brief This is the same as XMLPortParam, but you can set the template arguments needed to store the loadfunction.
     
    161182        ClassIdentifier<classname>::getIdentifier()->addXMLPortParamContainer(paramname, containername); \
    162183    } \
    163     containername->port((BaseObject*)this, object, xmlelement, mode)
     184    containername->port(static_cast<BaseObject*>(this), object, xmlelement, mode)
    164185
    165186// --------------------
     
    175196    @param xmlelement The XMLElement (recieved through the XMLPort function)
    176197    @param mode The mode (load/save) (received through the XMLPort function)
    177     @param bApplyLoaderMask If this is true, an added sub-object only gets loaded if 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)
    179200
    180201    bApplyLoaderMask is usually false for the following reason:
     
    183204    Of course, if there are "standalone" weapons in the level, they wont be loaded.
    184205
    185     If bLoadBefore, an added object already has all attributes set (like it's name). This is most
     206    If bLoadBefore is true, an added object already has all attributes set (like it's name). This is most
    186207    likely the best option, so this is usually true.
    187208
     
    222243    Note that "weapons" is the subsection. This allows you to add more types of sub-objects. In our example,
    223244    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.
    225246*/
    226247#define XMLPortObjectExtended(classname, objectclass, sectionname, loadfunction, savefunction, xmlelement, mode, bApplyLoaderMask, bLoadBefore) \
     
    329350            }
    330351
     352            ~XMLPortClassParamContainer()
     353            {
     354                assert(this->loadexecutor_);
     355                delete this->loadexecutor_;
     356                if (this->saveexecutor_)
     357                    delete this->saveexecutor_;
     358            }
     359
    331360            XMLPortParamContainer& port(BaseObject* owner, T* object, Element& xmlelement, XMLPort::Mode mode)
    332361            {
     362                OrxAssert(owner, "XMLPortParamContainer must have a BaseObject as owner.");
    333363                this->owner_ = owner;
    334364                this->parseParams_.object = object;
     
    336366                this->parseParams_.mode = mode;
    337367
    338                 if (mode == XMLPort::LoadObject)
     368                if ((mode == XMLPort::LoadObject) || (mode == XMLPort::ExpandObject))
    339369                {
    340370                    try
    341371                    {
    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()))
    344392                        {
    345393                            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))
    347395                                this->parseResult_ = PR_finished;
    348396                            else
    349397                                this->parseResult_ = PR_waiting_for_default_values;
    350398                        }
     399                        else if (mode == XMLPort::ExpandObject)
     400                            this->parseResult_ = PR_finished;
    351401                        else
    352402                            this->parseResult_ = PR_waiting_for_default_values;
     
    471521            }
    472522
     523            ~XMLPortClassObjectContainer()
     524            {
     525                assert(this->loadexecutor_);
     526                delete this->loadexecutor_;
     527                if (this->saveexecutor_)
     528                    delete this->saveexecutor_;
     529            }
     530
    473531            XMLPortObjectContainer& port(T* object, Element& xmlelement, XMLPort::Mode mode)
    474532            {
    475                 if (mode == XMLPort::LoadObject)
     533                if ((mode == XMLPort::LoadObject) || (mode == XMLPort::ExpandObject))
    476534                {
    477535                    try
     
    588646            ExecutorMember<T>* saveexecutor_;
    589647    };
     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    };
    590687}
    591688
Note: See TracChangeset for help on using the changeset viewer.