Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/core3/src/core/XMLPort.h @ 1858

Last change on this file since 1858 was 1716, checked in by landauf, 16 years ago

Added new 'MultiType', replacing MultiTypePrimitive, MultiTypeString and MultiTypeMath. MultiType can hold all types MultiTypeMath was able to hold, namely all primitives, pointers, string and several math objects (vector2, 3 and 4, quaternion, colourvalue, radian, degree).

The new MultiType has a completely changed behaviour, I'll explain this on a wiki page somewhen.
But to say the most important things in a few words:
The MultiType has a fixed type. This type is determined by the first assigned value (by using setValue(value), operator=(value) or MultiType(value)). Every other value getting assigned later, will be converted to the first type. But you can change the type (setType<T>()), convert the value (convert<T>()) or force the type of a newly assigned value manually (setValue<T>(value)) by using template functions.

In contrast, the old MultiTypeMath changed it's internal type whenever a new type was assigned. So be aware of this important change.

At the moment I can't see any issues, but there might very well be several problems yet to discover, so further tests will be done.

  • Property svn:eol-style set to native
File size: 20.9 KB
Line 
1/*
2 *   ORXONOX - the hottest 3D action shooter ever to exist
3 *                    > www.orxonox.net <
4 *
5 *
6 *   License notice:
7 *
8 *   This program is free software; you can redistribute it and/or
9 *   modify it under the terms of the GNU General Public License
10 *   as published by the Free Software Foundation; either version 2
11 *   of the License, or (at your option) any later version.
12 *
13 *   This program is distributed in the hope that it will be useful,
14 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 *   GNU General Public License for more details.
17 *
18 *   You should have received a copy of the GNU General Public License
19 *   along with this program; if not, write to the Free Software
20 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21 *
22 *   Author:
23 *      Fabian 'x3n' Landau
24 *   Co-authors:
25 *      ...
26 *
27 */
28
29#ifndef _XMLPort_H__
30#define _XMLPort_H__
31
32#include "CorePrereqs.h"
33
34#include "util/Debug.h"
35#include "util/XMLIncludes.h"
36#include "util/MultiType.h"
37#include "tinyxml/ticpp.h"
38#include "Executor.h"
39#include "CoreIncludes.h"
40#include "BaseObject.h"
41
42
43#define XMLPortParam(classname, paramname, loadfunction, savefunction, xmlelement, mode) \
44    XMLPortParamGeneric(xmlcontainer##loadfunction##savefunction, classname, classname, this, paramname, orxonox::createExecutor(orxonox::createFunctor(&classname::loadfunction), std::string( #classname ) + "::" + #loadfunction), orxonox::createExecutor(orxonox::createFunctor(&classname::savefunction), std::string( #classname ) + "::" + #savefunction), xmlelement, mode)
45#define XMLPortParamTemplate(classname, paramname, loadfunction, savefunction, xmlelement, mode, ...) \
46    XMLPortParamGeneric(xmlcontainer##loadfunction##savefunction, classname, classname, this, paramname, orxonox::createExecutor(orxonox::createFunctor< __VA_ARGS__ >(&classname::loadfunction), std::string( #classname ) + "::" + #loadfunction), orxonox::createExecutor(orxonox::createFunctor(&classname::savefunction), std::string( #classname ) + "::" + #savefunction), xmlelement, mode)
47
48#define XMLPortParamLoadOnly(classname, paramname, loadfunction, xmlelement, mode) \
49    XMLPortParamGeneric(xmlcontainer##loadfunction##0, classname, classname, this, paramname, orxonox::createExecutor(orxonox::createFunctor(&classname::loadfunction), std::string( #classname ) + "::" + #loadfunction), 0, xmlelement, mode)
50#define XMLPortParamLoadOnlyTemplate(classname, paramname, loadfunction, xmlelement, mode, ...) \
51    XMLPortParamGeneric(xmlcontainer##loadfunction##0, classname, classname, this, paramname, orxonox::createExecutor(orxonox::createFunctor< __VA_ARGS__ >(&classname::loadfunction), std::string( #classname ) + "::" + #loadfunction), 0, xmlelement, mode)
52
53#define XMLPortParamExtern(classname, externclass, object, paramname, loadfunction, savefunction, xmlelement, mode) \
54    XMLPortParamGeneric(xmlcontainer##loadfunction##savefunction, classname, externclass, object, paramname, orxonox::createExecutor(orxonox::createFunctor(&externclass::loadfunction), std::string( #externclass ) + "::" + #loadfunction), orxonox::createExecutor(orxonox::createFunctor(&externclass::savefunction), std::string( #externclass ) + "::" + #savefunction), xmlelement, mode);
55#define XMLPortParamExternTemplate(classname, externclass, object, paramname, loadfunction, savefunction, xmlelement, mode, ...) \
56    XMLPortParamGeneric(xmlcontainer##loadfunction##savefunction, classname, externclass, object, paramname, orxonox::createExecutor(orxonox::createFunctor< __VA_ARGS__ >(&externclass::loadfunction), std::string( #externclass ) + "::" + #loadfunction), orxonox::createExecutor(orxonox::createFunctor(&externclass::savefunction), std::string( #externclass ) + "::" + #savefunction), xmlelement, mode);
57
58#define XMLPortParamGeneric(containername, classname, objectclass, object, paramname, loadexecutor, saveexecutor, xmlelement, mode) \
59    orxonox::XMLPortClassParamContainer<objectclass>* containername = (orxonox::XMLPortClassParamContainer<objectclass>*)(ClassIdentifier<classname>::getIdentifier()->getXMLPortParamContainer(paramname)); \
60    if (!containername) \
61    { \
62        containername = new orxonox::XMLPortClassParamContainer<objectclass>(std::string(paramname), ClassIdentifier<classname>::getIdentifier(), loadexecutor, saveexecutor); \
63        ClassIdentifier<classname>::getIdentifier()->addXMLPortParamContainer(paramname, containername); \
64    } \
65    containername->port((BaseObject*)this, object, xmlelement, mode)
66
67
68#define XMLPortObject(classname, objectclass, sectionname, loadfunction, savefunction, xmlelement, mode, bApplyLoaderMask, bLoadBefore) \
69    XMLPortObjectGeneric(xmlcontainer##loadfunction##savefunction, classname, objectclass, sectionname, orxonox::createExecutor(orxonox::createFunctor(&classname::loadfunction), std::string( #classname ) + "::" + #loadfunction), orxonox::createExecutor(orxonox::createFunctor(&classname::savefunction), std::string( #classname ) + "::" + #savefunction), xmlelement, mode, bApplyLoaderMask, bLoadBefore)
70#define XMLPortObjectTemplate(classname, objectclass, sectionname, loadfunction, savefunction, xmlelement, mode, bApplyLoaderMask, bLoadBefore, ...) \
71    XMLPortObjectGeneric(xmlcontainer##loadfunction##savefunction, classname, objectclass, sectionname, orxonox::createExecutor(orxonox::createFunctor< __VA_ARGS__ >(&classname::loadfunction), std::string( #classname ) + "::" + #loadfunction), orxonox::createExecutor(orxonox::createFunctor(&classname::savefunction), std::string( #classname ) + "::" + #savefunction), xmlelement, mode, bApplyLoaderMask, bLoadBefore)
72
73#define XMLPortObjectGeneric(containername, classname, objectclass, sectionname, loadexecutor, saveexecutor, xmlelement, mode, bApplyLoaderMask, bLoadBefore) \
74    orxonox::XMLPortClassObjectContainer<classname, objectclass>* containername = (orxonox::XMLPortClassObjectContainer<classname, objectclass>*)(ClassIdentifier<classname>::getIdentifier()->getXMLPortObjectContainer(sectionname)); \
75    if (!containername) \
76    { \
77        containername = new orxonox::XMLPortClassObjectContainer<classname, objectclass>(std::string(sectionname), ClassIdentifier<classname>::getIdentifier(), loadexecutor, saveexecutor, bApplyLoaderMask, bLoadBefore); \
78        ClassIdentifier<classname>::getIdentifier()->addXMLPortObjectContainer(sectionname, containername); \
79    } \
80    containername->port(this, xmlelement, mode)
81
82
83namespace orxonox
84{
85    // ###############################
86    // ###  XMLPortParamContainer  ###
87    // ###############################
88    class _CoreExport XMLPortParamContainer
89    {
90    public:
91        enum ParseResult
92        {
93            PR_not_started,
94            PR_finished,
95            PR_waiting_for_default_values
96        };
97
98        public:
99            XMLPortParamContainer()
100                { this->parseResult_ = PR_not_started; }
101            virtual ~XMLPortParamContainer() {}
102
103            inline const std::string& getName() const
104                { return this->paramname_; }
105
106            virtual XMLPortParamContainer& description(const std::string description) = 0;
107            virtual const std::string& getDescription() = 0;
108
109            virtual XMLPortParamContainer& defaultValue(unsigned int index, const MultiType& param) = 0;
110            virtual XMLPortParamContainer& defaultValues(const MultiType& param1) = 0;
111            virtual XMLPortParamContainer& defaultValues(const MultiType& param1, const MultiType& param2) = 0;
112            virtual XMLPortParamContainer& defaultValues(const MultiType& param1, const MultiType& param2, const MultiType& param3) = 0;
113            virtual XMLPortParamContainer& defaultValues(const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4) = 0;
114            virtual XMLPortParamContainer& defaultValues(const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4, const MultiType& param5) = 0;
115
116        protected:
117            std::string paramname_;
118            ParseResult parseResult_;
119            Identifier* identifier_;
120            BaseObject* owner_;
121    };
122
123    template <class T>
124    class XMLPortClassParamContainer : public XMLPortParamContainer
125    {
126        struct ParseParams
127        {
128            T* object;
129            Element* xmlelement;
130            XMLPort::Mode mode;
131        };
132
133        public:
134            XMLPortClassParamContainer(const std::string paramname, Identifier* identifier, ExecutorMember<T>* loadexecutor, ExecutorMember<T>* saveexecutor)
135            {
136                this->paramname_ = paramname;
137                this->identifier_ = identifier;
138                this->loadexecutor_ = loadexecutor;
139                this->saveexecutor_ = saveexecutor;
140            }
141
142            XMLPortParamContainer& port(BaseObject* owner, T* object, Element& xmlelement, XMLPort::Mode mode)
143            {
144                this->owner_ = owner;
145                this->parseParams_.object = object;
146                this->parseParams_.xmlelement = &xmlelement;
147                this->parseParams_.mode = mode;
148
149                if (mode == XMLPort::LoadObject)
150                {
151                    try
152                    {
153                        std::string attribute = xmlelement.GetAttribute(this->paramname_);
154                        if ((attribute.size() > 0) || (this->loadexecutor_->allDefaultValuesSet()))
155                        {
156                            COUT(5) << this->owner_->getLoaderIndentation() << "Loading parameter " << this->paramname_ << " in " << this->identifier_->getName() << " (objectname " << this->owner_->getName() << ")." << std::endl << this->owner_->getLoaderIndentation();
157                            if (this->loadexecutor_->parse(object, attribute, ","))
158                                this->parseResult_ = PR_finished;
159                            else
160                                this->parseResult_ = PR_waiting_for_default_values;
161                        }
162                    }
163                    catch (ticpp::Exception& ex)
164                    {
165                        COUT(1) << std::endl;
166                        COUT(1) << "An error occurred in XMLPort.h while loading attribute '" << this->paramname_ << "' of '" << this->identifier_->getName() << "' (objectname: " << this->owner_->getName() << ") in " << this->owner_->getLevelfile() << ":" << std::endl;
167                        COUT(1) << ex.what() << std::endl;
168                    }
169                }
170                else
171                {
172                    if (this->saveexecutor_)
173                    {
174//                        xmlelement.SetAttribute(this->paramname_, "...");
175                    }
176                }
177
178                return (*this);
179            }
180
181            XMLPortParamContainer& port(BaseObject* owner, const ParseParams& parseParams)
182            {
183                return this->port(owner, parseParams.object, *parseParams.xmlelement, parseParams.mode);
184            }
185
186            XMLPortParamContainer& portIfWaitingForDefaultValues(const ParseResult& result, const ParseParams& params)
187            {
188                if (result == PR_waiting_for_default_values)
189                    return this->port(this->owner_, params);
190                else
191                    return (*this);
192            }
193
194            virtual XMLPortParamContainer& description(const std::string description)
195                { this->loadexecutor_->setDescription(description); return (*this); }
196            virtual const std::string& getDescription()
197                { return this->loadexecutor_->getDescription(); }
198
199            virtual XMLPortParamContainer& defaultValue(unsigned int index, const MultiType& param)
200            {
201                if (!this->loadexecutor_->defaultValueSet(index))
202                    this->loadexecutor_->setDefaultValue(index, param);
203                return this->portIfWaitingForDefaultValues(this->parseResult_, this->parseParams_);
204            }
205            virtual XMLPortParamContainer& defaultValues(const MultiType& param1)
206            {
207                if (!this->loadexecutor_->defaultValueSet(0))
208                    this->loadexecutor_->setDefaultValues(param1);
209                return this->portIfWaitingForDefaultValues(this->parseResult_, this->parseParams_);
210            }
211            virtual XMLPortParamContainer& defaultValues(const MultiType& param1, const MultiType& param2)
212            {
213                if ((!this->loadexecutor_->defaultValueSet(0)) || (!this->loadexecutor_->defaultValueSet(1)))
214                    this->loadexecutor_->setDefaultValues(param1, param2);
215                return this->portIfWaitingForDefaultValues(this->parseResult_, this->parseParams_);
216            }
217            virtual XMLPortParamContainer& defaultValues(const MultiType& param1, const MultiType& param2, const MultiType& param3)
218            {
219                if ((!this->loadexecutor_->defaultValueSet(0)) || (!this->loadexecutor_->defaultValueSet(1)) || (!this->loadexecutor_->defaultValueSet(2)))
220                    this->loadexecutor_->setDefaultValues(param1, param2, param3);
221                return this->portIfWaitingForDefaultValues(this->parseResult_, this->parseParams_);
222            }
223            virtual XMLPortParamContainer& defaultValues(const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4)
224            {
225                if ((!this->loadexecutor_->defaultValueSet(0)) || (!this->loadexecutor_->defaultValueSet(1)) || (!this->loadexecutor_->defaultValueSet(2)) || (!this->loadexecutor_->defaultValueSet(3)))
226                    this->loadexecutor_->setDefaultValues(param1, param2, param3, param4);
227                return this->portIfWaitingForDefaultValues(this->parseResult_, this->parseParams_);
228            }
229            virtual XMLPortParamContainer& defaultValues(const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4, const MultiType& param5)
230            {
231                if ((!this->loadexecutor_->defaultValueSet(0)) || (!this->loadexecutor_->defaultValueSet(1)) || (!this->loadexecutor_->defaultValueSet(2)) || (!this->loadexecutor_->defaultValueSet(3)) || (!this->loadexecutor_->defaultValueSet(4)))
232                    this->loadexecutor_->setDefaultValues(param1, param2, param3, param4, param5);
233                return this->portIfWaitingForDefaultValues(this->parseResult_, this->parseParams_);
234            }
235
236        private:
237            ExecutorMember<T>* loadexecutor_;
238            ExecutorMember<T>* saveexecutor_;
239            ParseParams parseParams_;
240    };
241
242
243    // ################################
244    // ###  XMLPortObjectContainer  ###
245    // ################################
246    class _CoreExport XMLPortObjectContainer
247    {
248        public:
249            XMLPortObjectContainer()
250                { this->bApplyLoaderMask_ = false; }
251            virtual ~XMLPortObjectContainer() {}
252
253            inline const std::string& getName() const
254                { return this->sectionname_; }
255
256            virtual XMLPortObjectContainer& description(const std::string description) = 0;
257            virtual const std::string& getDescription() = 0;
258
259            bool identifierIsIncludedInLoaderMask(const Identifier* identifier);
260
261        protected:
262            std::string sectionname_;
263            bool bApplyLoaderMask_;
264            bool bLoadBefore_;
265            Identifier* identifier_;
266    };
267
268    template <class T, class O>
269    class XMLPortClassObjectContainer : public XMLPortObjectContainer
270    {
271        public:
272            XMLPortClassObjectContainer(const std::string sectionname, Identifier* identifier, ExecutorMember<T>* loadexecutor, ExecutorMember<T>* saveexecutor, bool bApplyLoaderMask, bool bLoadBefore)
273            {
274                this->sectionname_ = sectionname;
275                this->identifier_ = identifier;
276                this->loadexecutor_ = loadexecutor;
277                this->saveexecutor_ = saveexecutor;
278                this->bApplyLoaderMask_ = bApplyLoaderMask;
279                this->bLoadBefore_ = bLoadBefore;
280            }
281
282            XMLPortObjectContainer& port(T* object, Element& xmlelement, XMLPort::Mode mode)
283            {
284                if (mode == XMLPort::LoadObject)
285                {
286                    try
287                    {
288                        Element* xmlsubelement;
289                        if ((this->sectionname_ != "") && (this->sectionname_.size() > 0))
290                            xmlsubelement = xmlelement.FirstChildElement(this->sectionname_, false);
291                        else
292                            xmlsubelement = &xmlelement;
293
294                        if (xmlsubelement)
295                        {
296                            for (ticpp::Iterator<ticpp::Element> child = xmlsubelement->FirstChildElement(false); child != child.end(); child++)
297                            {
298                                Identifier* identifier = ID(child->Value());
299                                if (identifier)
300                                {
301                                    if (identifier->isA(Class(O)))
302                                    {
303                                        if (this->identifierIsIncludedInLoaderMask(identifier))
304                                        {
305                                            COUT(4) << ((BaseObject*)object)->getLoaderIndentation() << "fabricating " << child->Value() << "..." << std::endl;
306
307                                            BaseObject* newObject = identifier->fabricate();
308                                            newObject->setLoaderIndentation(((BaseObject*)object)->getLoaderIndentation() + "  ");
309                                            newObject->setLevel(((BaseObject*)object)->getLevel());
310                                            newObject->setNamespace(((BaseObject*)object)->getNamespace());
311
312                                            if (this->bLoadBefore_)
313                                            {
314                                                newObject->XMLPort(*child, XMLPort::LoadObject);
315                                                COUT(4) << ((BaseObject*)object)->getLoaderIndentation() << "assigning " << child->Value() << " (objectname " << newObject->getName() << ") to " << this->identifier_->getName() << " (objectname " << ((BaseObject*)object)->getName() << ")" << std::endl;
316                                            }
317                                            else
318                                            {
319                                                COUT(4) << ((BaseObject*)object)->getLoaderIndentation() << "assigning " << child->Value() << " (object not yet loaded) to " << this->identifier_->getName() << " (objectname " << ((BaseObject*)object)->getName() << ")" << std::endl;
320                                            }
321
322                                            COUT(5) << ((BaseObject*)object)->getLoaderIndentation();
323                                            (*this->loadexecutor_)(object, newObject);
324
325                                            if (!this->bLoadBefore_)
326                                                newObject->XMLPort(*child, XMLPort::LoadObject);
327
328                                            COUT(5) << ((BaseObject*)object)->getLoaderIndentation() << "...fabricated " << child->Value() << " (objectname " << newObject->getName() << ")." << std::endl;
329                                        }
330                                    }
331                                    else
332                                    {
333                                        COUT(2) << ((BaseObject*)object)->getLoaderIndentation() << "Warning: '" << child->Value() << "' is not a '" << Class(O)->getName() << "'." << std::endl;
334                                    }
335                                }
336                                else
337                                {
338                                    COUT(2) << object->getLoaderIndentation() << "Warning: '" << child->Value() << "' is not a valid classname." << std::endl;
339                                }
340                            }
341                        }
342                    }
343                    catch (ticpp::Exception& ex)
344                    {
345                        COUT(1) << std::endl;
346                        COUT(1) << "An error occurred in XMLPort.h while loading a '" << Class(O)->getName() << "' in '" << this->sectionname_ << "' of '" << this->identifier_->getName() << "' (objectname: " << ((BaseObject*)object)->getName() << ") in " << object->getLevelfile() << ":" << std::endl;
347                        COUT(1) << ex.what() << std::endl;
348                    }
349                }
350                else
351                {
352                }
353
354                return (*this);
355            }
356
357            virtual XMLPortObjectContainer& description(const std::string description)
358                { this->loadexecutor_->setDescription(description); return (*this); }
359            virtual const std::string& getDescription()
360                { return this->loadexecutor_->getDescription(); }
361
362        private:
363            ExecutorMember<T>* loadexecutor_;
364            ExecutorMember<T>* saveexecutor_;
365    };
366}
367
368#endif /* _XMLPort_H__ */
Note: See TracBrowser for help on using the repository browser.