Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/core2/src/orxonox/core/XMLPort.h @ 878

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

added boolean bApplyLoaderMask to the XMLPortObject macro to determine whether the ClassTreeMask from the Loader should be applied or not (the idea is: objects included in excluded objects are excluded too, no matter what the mask sais. but objects included in a namespace or directly in a level-file are filtered by the mask.)

File size: 14.2 KB
Line 
1/*
2 *   ORXONOX - the hottest 3D action shooter ever to exist
3 *
4 *
5 *   License notice:
6 *
7 *   This program is free software; you can redistribute it and/or
8 *   modify it under the terms of the GNU General Public License
9 *   as published by the Free Software Foundation; either version 2
10 *   of the License, or (at your option) any later version.
11 *
12 *   This program is distributed in the hope that it will be useful,
13 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
14 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 *   GNU General Public License for more details.
16 *
17 *   You should have received a copy of the GNU General Public License
18 *   along with this program; if not, write to the Free Software
19 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
20 *
21 *   Author:
22 *      Fabian 'x3n' Landau
23 *   Co-authors:
24 *      ...
25 *
26 */
27
28#ifndef _XMLPort_H__
29#define _XMLPort_H__
30
31#include "util/XMLIncludes.h"
32#include "util/MultiTypeMath.h"
33#include "util/tinyxml/ticpp.h"
34#include "util/SubString.h"
35#include "Functor.h"
36#include "Debug.h"
37#include "CoreIncludes.h"
38#include "BaseObject.h"
39
40#include "CorePrereqs.h"
41
42
43#define XMLPortParam(classname, paramname, loadfunction, savefunction, xmlelement, loading) \
44    orxonox::XMLPortClassParamContainer<classname>* xmlcontainer##loadfunction##savefunction = (orxonox::XMLPortClassParamContainer<classname>*)(this->getIdentifier()->getXMLPortParamContainer(paramname)); \
45    if (!xmlcontainer##loadfunction##savefunction) \
46    { \
47        xmlcontainer##loadfunction##savefunction = new orxonox::XMLPortClassParamContainer<classname>(this->getIdentifier()->getName(), std::string(paramname), createFunctor(&classname::loadfunction), createFunctor(&classname::savefunction)); \
48        this->getIdentifier()->addXMLPortParamContainer(paramname, xmlcontainer##loadfunction##savefunction); \
49    } \
50    xmlcontainer##loadfunction##savefunction->port(this, xmlelement, loading)
51
52#define XMLPortParamLoadOnly(classname, paramname, loadfunction, xmlelement, loading) \
53    orxonox::XMLPortClassParamContainer<classname>* xmlcontainer##loadfunction##savefunction = (orxonox::XMLPortClassParamContainer<classname>*)(this->getIdentifier()->getXMLPortParamContainer(paramname)); \
54    if (!xmlcontainer##loadfunction##savefunction) \
55    { \
56        xmlcontainer##loadfunction##savefunction = new orxonox::XMLPortClassParamContainer<classname>(this->getIdentifier()->getName(), std::string(paramname), createFunctor(&classname::loadfunction), 0); \
57        this->getIdentifier()->addXMLPortParamContainer(paramname, xmlcontainer##loadfunction##savefunction); \
58    } \
59    xmlcontainer##loadfunction##savefunction->port(this, xmlelement, loading)
60
61#define XMLPortObject(classname, objectclass, sectionname, loadfunction, savefunction, xmlelement, loading, bApplyLoaderMask) \
62    orxonox::XMLPortClassObjectContainer<classname, objectclass>* xmlcontainer##loadfunction##savefunction = (orxonox::XMLPortClassObjectContainer<classname, objectclass>*)(this->getIdentifier()->getXMLPortObjectContainer(sectionname)); \
63    if (!xmlcontainer##loadfunction##savefunction) \
64    { \
65        xmlcontainer##loadfunction##savefunction = new orxonox::XMLPortClassObjectContainer<classname, objectclass>(this->getIdentifier()->getName(), std::string(sectionname), &classname::loadfunction, &classname::savefunction, bApplyLoaderMask); \
66        this->getIdentifier()->addXMLPortObjectContainer(sectionname, xmlcontainer##loadfunction##savefunction); \
67    } \
68    xmlcontainer##loadfunction##savefunction->port(this, xmlelement, loading)
69
70
71namespace orxonox
72{
73    // ###############################
74    // ###  XMLPortParamContainer  ###
75    // ###############################
76    class _CoreExport XMLPortParamContainer
77    {
78        public:
79            XMLPortParamContainer();
80
81            inline const std::string& getName() const
82                { return this->paramname_; }
83
84            XMLPortParamContainer& description(const std::string description);
85            const std::string& getDescription();
86
87            XMLPortParamContainer& defaultValues(const MultiTypeMath& param1 = MT_null, const MultiTypeMath& param2 = MT_null, const MultiTypeMath& param3 = MT_null, const MultiTypeMath& param4 = MT_null, const MultiTypeMath& param5 = MT_null)
88            {
89                this->defaultValues_[0] = param1;
90                this->defaultValues_[1] = param2;
91                this->defaultValues_[2] = param3;
92                this->defaultValues_[3] = param4;
93                this->defaultValues_[4] = param5;
94
95                return (*this);
96            }
97
98        protected:
99            std::string classname_;
100            std::string paramname_;
101            MultiTypeMath defaultValues_[5];
102
103        private:
104            LanguageEntryLabel description_;
105            bool bAddedDescription_;
106            bool bAddedDefaultValues_;
107    };
108
109    template <class T>
110    class XMLPortClassParamContainer : public XMLPortParamContainer
111    {
112        public:
113            XMLPortClassParamContainer(const std::string classname, const std::string paramname, FunctorMember<T>* loadfunction, FunctorMember<T>* savefunction)
114            {
115                this->classname_ = classname;
116                this->paramname_ = paramname;
117                this->loadfunction_ = loadfunction;
118                this->savefunction_ = savefunction;
119            }
120
121            XMLPortParamContainer& port(T* object, Element& xmlelement, bool loading)
122            {
123                if (loading)
124                {
125                    try
126                    {
127                        std::string attribute = xmlelement.GetAttribute(this->paramname_);
128                        if (attribute.size() > 0)
129                        {
130                            SubString tokens(attribute, ",", SubString::WhiteSpaces, false, '\\', '"', '(', ')', '\0');
131                            if ((unsigned int)tokens.size() >= (unsigned int)this->loadfunction_->getParamCount())
132                            {
133                                COUT(5) << object->getLoaderIndentation() << "Loading parameter " << this->paramname_ << " in " << this->classname_ << " (objectname " << object->getName() << ") with ";
134                                if (this->loadfunction_->getParamCount() == 1)
135                                {
136                                    COUT(5) << "1 parameter (using whole string):" << std::endl;
137                                    COUT(5) << object->getLoaderIndentation() << "  " << attribute << std::endl;
138                                    (*this->loadfunction_)(object, MultiTypeMath(attribute));
139                                }
140                                else
141                                {
142                                    COUT(5) << tokens.size() << " parameter (using MultiTypeMath)." << std::endl;
143                                    MultiTypeMath param1 = MT_null, param2 = MT_null, param3 = MT_null, param4 = MT_null, param5 = MT_null;
144                                    if (tokens.size() >= 1) param1 = tokens[0];
145                                    if (tokens.size() >= 2) param2 = tokens[1];
146                                    if (tokens.size() >= 3) param3 = tokens[2];
147                                    if (tokens.size() >= 4) param4 = tokens[3];
148                                    if (tokens.size() >= 5) param5 = tokens[4];
149                                    COUT(5) << object->getLoaderIndentation() << "  " << attribute << std::endl;
150                                    COUT(5) << object->getLoaderIndentation() << "  " << param1 << ", " << param2 << ", " << param3 << ", " << param4 << ", " << param5 << std::endl;
151
152                                    (*this->loadfunction_)(object, param1, param2, param3, param4, param5);
153                                }
154                            }
155                            else
156                            {
157                                COUT(2) << object->getLoaderIndentation() << "Warning: Parameter \"" << this->paramname_ << "\" in \"" << this->classname_ << "\" (objectname: " << object->getName() << ") is incomplete and couln't be loaded." << std::endl;
158                            }
159                        }
160                    }
161                    catch(ticpp::Exception& ex)
162                    {
163                        COUT(1) << std::endl;
164                        COUT(1) << "An error occurred in XMLPort.h while loading attribute '" << this->paramname_ << "' of '" << this->classname_ << "' (objectname: " << object->getName() << ") in " << object->getLevelfile() << ":" << std::endl;
165                        COUT(1) << ex.what() << std::endl;
166                    }
167                }
168                else
169                {
170                    if (this->savefunction_)
171                    {
172//                        xmlelement.SetAttribute(this->paramname_, "...");
173                    }
174                }
175
176                return (*this);
177            }
178
179        private:
180            FunctorMember<T>* loadfunction_;
181            FunctorMember<T>* savefunction_;
182    };
183
184
185    // ################################
186    // ###  XMLPortObjectContainer  ###
187    // ################################
188    class _CoreExport XMLPortObjectContainer
189    {
190        public:
191            XMLPortObjectContainer();
192
193            inline const std::string& getName() const
194                { return this->sectionname_; }
195
196            XMLPortObjectContainer& description(const std::string description);
197            const std::string& getDescription();
198            bool identifierIsIncludedInLoaderMask(const Identifier* identifier);
199
200        protected:
201            std::string classname_;
202            std::string sectionname_;
203            bool bApplyLoaderMask_;
204
205        private:
206            LanguageEntryLabel description_;
207            bool bAddedDescription_;
208    };
209
210    template <class T, class O>
211    class XMLPortClassObjectContainer : public XMLPortObjectContainer
212    {
213        public:
214            XMLPortClassObjectContainer(const std::string classname, const std::string sectionname, void (T::*loadfunction)(O*), const O* (T::*savefunction)(unsigned int) const, bool bApplyLoaderMask)
215            {
216                this->classname_ = classname;
217                this->sectionname_ = sectionname;
218                this->loadfunction_ = loadfunction;
219                this->savefunction_ = savefunction;
220                this->bApplyLoaderMask_ = bApplyLoaderMask;
221            }
222
223            XMLPortObjectContainer& port(T* object, Element& xmlelement, bool loading)
224            {
225                if (loading)
226                {
227                    try
228                    {
229                        Element* xmlsubelement;
230                        if (this->sectionname_ != "")
231                            xmlsubelement = xmlelement.FirstChildElement(this->sectionname_, false);
232                        else
233                            xmlsubelement = &xmlelement;
234
235                        if (xmlsubelement)
236                        {
237                            for (ticpp::Iterator<ticpp::Element> child = xmlsubelement->FirstChildElement(false); child != child.end(); child++)
238                            {
239                                Identifier* identifier = ID(child->Value());
240                                if (identifier)
241                                {
242                                    if (identifier->isA(Class(O)))
243                                    {
244                                        if (this->identifierIsIncludedInLoaderMask(identifier))
245                                        {
246                                            COUT(4) << object->getLoaderIndentation() << "fabricating " << child->Value() << "..." << std::endl;
247                                            O* newObject = (O*)identifier->fabricate();
248                                            newObject->setLoaderIndentation(object->getLoaderIndentation() + "  ");
249                                            newObject->setLevel(object->getLevel());
250                                            newObject->XMLPort(*child, true);
251                                            COUT(4) << object->getLoaderIndentation() << "assigning " << child->Value() << " (objectname " << newObject->getName() << ") to " << this->classname_ << " (objectname " << object->getName() << ")" << std::endl;
252                                            (*object.*this->loadfunction_)(newObject);
253                                            COUT(5) << "  ...fabricated " << child->Value() << " (objectname " << newObject->getName() << ")." << std::endl;
254                                        }
255                                    }
256                                    else
257                                    {
258                                        COUT(2) << object->getLoaderIndentation() << "Warning: '" << child->Value() << "' is not a '" << Class(O)->getName() << "'." << std::endl;
259                                    }
260                                }
261                                else
262                                {
263                                    COUT(2) << object->getLoaderIndentation() << "Warning: '" << child->Value() << "' is not a valid classname." << std::endl;
264                                }
265                            }
266                        }
267                    }
268                    catch(ticpp::Exception& ex)
269                    {
270                        COUT(1) << std::endl;
271                        COUT(1) << "An error occurred in XMLPort.h while loading a '" << Class(O)->getName() << "' in '" << this->sectionname_ << "' of '" << this->classname_ << "' (objectname: " << object->getName() << ") in " << object->getLevelfile() << ":" << std::endl;
272                        COUT(1) << ex.what() << std::endl;
273                    }
274                }
275                else
276                {
277                }
278
279                return (*this);
280            }
281
282        private:
283            void     (T::*loadfunction_)(O*);
284            const O* (T::*savefunction_)(unsigned int) const;
285    };
286}
287
288#endif /* _XMLPort_H__ */
Note: See TracBrowser for help on using the repository browser.