Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/objecthierarchy2/src/core/BaseObject.cc @ 2680

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

Update your media repository and delete keybindings.ini if you want to use boost (space).

  • Added new class "Engine" to control the speed of a SpaceShip (Engine is an Item, MultiStateEngine is a specialized version of Engine)
  • Added FadingBillboard, a billboard with the ability to fade in and out smoothly when activated/deactivated.
  • Several changes in Backlight, it's now a child of FadingBillboard
  • Some changes concerning local control in ControllableEntity
  • Fixed a bug in WorldEntity caused by different destruction order of attached objects on server and client
  • Added a "MainState" to BaseObject. An object has several states (activity, visibility, …) and one of it can be defined as "MainState" in the XML file. Other objects can change this state without knowing which state it really is (used by MultiStateEngine).
  • Property svn:eol-style set to native
File size: 11.2 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/**
30    @file
31    @brief Implementation of the BaseObject class.
32*/
33
34#include "BaseObject.h"
35#include "tinyxml/tinyxml.h"
36#include "CoreIncludes.h"
37#include "EventIncludes.h"
38#include "Functor.h"
39#include "XMLPort.h"
40#include "XMLFile.h"
41#include "XMLNameListener.h"
42#include "Template.h"
43#include "util/String.h"
44#include "util/mbool.h"
45
46namespace orxonox
47{
48    CreateFactory(BaseObject);
49
50    /**
51        @brief Constructor: Registers the object in the BaseObject-list.
52    */
53    BaseObject::BaseObject(BaseObject* creator) : bInitialized_(false)
54    {
55        RegisterRootObject(BaseObject);
56
57        this->bInitialized_ = true;
58
59        this->bActive_ = true;
60        this->bVisible_ = true;
61        this->oldGametype_ = 0;
62
63        this->functorSetMainState_ = 0;
64        this->functorGetMainState_ = 0;
65
66        this->setCreator(creator);
67        if (this->creator_)
68        {
69            this->setFile(this->creator_->getFile());
70            this->setNamespace(this->creator_->getNamespace());
71            this->setScene(this->creator_->getScene());
72            this->setGametype(this->creator_->getGametype());
73        }
74        else
75        {
76            this->file_ = 0;
77            this->namespace_ = 0;
78            this->scene_ = 0;
79            this->gametype_ = 0;
80        }
81    }
82
83    /**
84        @brief Destructor
85    */
86    BaseObject::~BaseObject()
87    {
88        if (this->isInitialized())
89        {
90            for (std::list<BaseObject*>::const_iterator it = this->events_.begin(); it != this->events_.end(); ++it)
91                (*it)->unregisterEventListener(this);
92
93            for (std::map<BaseObject*, std::string>::const_iterator it = this->eventListeners_.begin(); it != this->eventListeners_.end(); ++it)
94                it->first->removeEvent(this);
95
96            if (this->functorSetMainState_)
97                delete this->functorSetMainState_;
98            if (this->functorGetMainState_)
99                delete this->functorGetMainState_;
100        }
101    }
102
103    /**
104        @brief XML loading and saving.
105        @param xmlelement The XML-element
106        @param loading Loading (true) or saving (false)
107        @return The XML-element
108    */
109    void BaseObject::XMLPort(Element& xmlelement, XMLPort::Mode mode)
110    {
111        XMLPortParam(BaseObject, "name", setXMLName, getName, xmlelement, mode);
112        XMLPortParam(BaseObject, "visible", setVisible, isVisible, xmlelement, mode);
113        XMLPortParam(BaseObject, "active", setActive, isActive, xmlelement, mode);
114        XMLPortParam(BaseObject, "mainstate", setMainStateName, getMainStateName, xmlelement, mode);
115
116        XMLPortObjectTemplate(BaseObject, Template, "templates", addTemplate, getTemplate, xmlelement, mode, Template*);
117
118        Element* events = xmlelement.FirstChildElement("events", false);
119
120        if (events)
121        {
122            std::list<std::string> eventnames;
123
124            if (mode == XMLPort::LoadObject || mode == XMLPort::ExpandObject)
125            {
126                for (ticpp::Iterator<ticpp::Element> child = events->FirstChildElement(false); child != child.end(); child++)
127                    eventnames.push_back(child->Value());
128            }
129            else if (mode == XMLPort::SaveObject)
130            {
131                for (std::map<std::string, XMLPortObjectContainer*>::const_iterator it = this->getIdentifier()->getXMLPortEventMapBegin(); it != this->getIdentifier()->getXMLPortEventMapEnd(); ++it)
132                    eventnames.push_back(it->first);
133            }
134
135            for (std::list<std::string>::iterator it = eventnames.begin(); it != eventnames.end(); ++it)
136            {
137                std::string sectionname = (*it);
138                ExecutorMember<BaseObject>* loadexecutor = createExecutor(createFunctor(&BaseObject::addEvent), std::string( "BaseObject" ) + "::" + "addEvent");
139                ExecutorMember<BaseObject>* saveexecutor = createExecutor(createFunctor(&BaseObject::getEvent), std::string( "BaseObject" ) + "::" + "getEvent");
140                loadexecutor->setDefaultValue(1, sectionname);
141
142                XMLPortClassObjectContainer<BaseObject, BaseObject>* container = 0;
143                container = (XMLPortClassObjectContainer<BaseObject, BaseObject>*)(this->getIdentifier()->getXMLPortEventContainer(sectionname));
144                if (!container)
145                {
146                    container = new XMLPortClassObjectContainer<BaseObject, BaseObject>(sectionname, this->getIdentifier(), loadexecutor, saveexecutor, false, true);
147                    this->getIdentifier()->addXMLPortEventContainer(sectionname, container);
148                }
149                container->port(this, *events, mode);
150            }
151        }
152    }
153
154    /**
155        @brief Loads the name of the object through XML and calls all XMLNameListener.
156        @param name The name of the object
157    */
158    void BaseObject::setXMLName(const std::string& name)
159    {
160        this->setName(name);
161
162        for (ObjectList<XMLNameListener>::iterator it = ObjectList<XMLNameListener>::begin(); it != ObjectList<XMLNameListener>::end(); ++it)
163            it->loadedNewXMLName(this);
164    }
165
166    /**
167        @brief Returns the levelfile that loaded this object.
168        @return The levelfile
169    */
170    const std::string& BaseObject::getFilename() const
171    {
172        if (this->file_)
173            return this->file_->getFilename();
174        else
175            return BLANKSTRING;
176    }
177
178    /**
179        @brief Adds a Template to the object.
180        @param name The name of the Template
181    */
182    void BaseObject::addTemplate(const std::string& name)
183    {
184        Template* temp = Template::getTemplate(name);
185        if (temp)
186            this->addTemplate(temp);
187        else
188            COUT(1) << "Error: \"" << name << "\" is not a valid Template name (in class: " << this->getIdentifier()->getName() << ", name: " << this->getName() << ")." << std::endl;
189    }
190
191    /**
192        @brief Adds a Template to the object.
193        @param temp The Template
194    */
195    void BaseObject::addTemplate(Template* temp)
196    {
197        this->templates_.insert(temp);
198        temp->applyOn(this);
199    }
200
201    /**
202        @brief Returns the Template with the given index.
203        @param index The index
204    */
205    Template* BaseObject::getTemplate(unsigned int index) const
206    {
207        unsigned int i = 0;
208        for (std::set<Template*>::const_iterator it = this->templates_.begin(); it != this->templates_.end(); ++it)
209        {
210            if (i == index)
211                return (*it);
212            i++;
213        }
214        return 0;
215    }
216
217    void BaseObject::addEvent(BaseObject* event, const std::string& sectionname)
218    {
219        event->registerEventListener(this, sectionname);
220        this->events_.push_back(event);
221    }
222
223    void BaseObject::removeEvent(BaseObject* event)
224    {
225        this->events_.remove(event);
226    }
227
228    BaseObject* BaseObject::getEvent(unsigned int index) const
229    {
230        unsigned int i = 0;
231        for (std::list<BaseObject*>::const_iterator it = this->events_.begin(); it != this->events_.end(); ++it)
232        {
233            if (i == index)
234                return (*it);
235            ++i;
236        }
237        return 0;
238    }
239
240    void BaseObject::addEventContainer(const std::string& sectionname, EventContainer* container)
241    {
242        std::map<std::string, EventContainer*>::const_iterator it = this->eventContainers_.find(sectionname);
243        if (it != this->eventContainers_.end())
244        {
245            COUT(2) << "Warning: Overwriting EventContainer in class " << this->getIdentifier()->getName() << "." << std::endl;
246            delete (it->second);
247        }
248
249        this->eventContainers_[sectionname] = container;
250    }
251
252    EventContainer* BaseObject::getEventContainer(const std::string& sectionname) const
253    {
254        std::map<std::string, EventContainer*>::const_iterator it = this->eventContainers_.find(sectionname);
255        if (it != this->eventContainers_.end())
256            return ((*it).second);
257        else
258            return 0;
259    }
260
261    void BaseObject::fireEvent()
262    {
263        this->fireEvent(true);
264        this->fireEvent(false);
265    }
266
267    void BaseObject::fireEvent(bool activate)
268    {
269        this->fireEvent(activate, this);
270    }
271
272    void BaseObject::fireEvent(bool activate, BaseObject* originator)
273    {
274        Event event(activate, originator);
275
276        for (std::map<BaseObject*, std::string>::iterator it = this->eventListeners_.begin(); it != this->eventListeners_.end(); ++it)
277        {
278            event.sectionname_ = it->second;
279            it->first->processEvent(event);
280        }
281    }
282
283    void BaseObject::fireEvent(Event& event)
284    {
285        for (std::map<BaseObject*, std::string>::iterator it = this->eventListeners_.begin(); it != this->eventListeners_.end(); ++it)
286            it->first->processEvent(event);
287    }
288
289    void BaseObject::processEvent(Event& event)
290    {
291        SetEvent(BaseObject, "activity", setActive, event);
292        SetEvent(BaseObject, "visibility", setVisible, event);
293    }
294
295    void BaseObject::setMainStateName(const std::string& name)
296    {
297        if (this->mainStateName_ != name)
298        {
299            this->mainStateName_ = name;
300            if (this->functorSetMainState_)
301                delete this->functorSetMainState_;
302            if (this->functorGetMainState_)
303                delete this->functorGetMainState_;
304            this->changedMainState();
305            if (!this->functorSetMainState_)
306                COUT(2) << "Warning: \"" << name << "\" is not a valid MainState." << std::endl;
307        }
308    }
309
310    void BaseObject::setMainState(bool state)
311    {
312        if (this->functorSetMainState_)
313            (*this->functorSetMainState_)(state);
314        else
315            COUT(2) << "Warning: No MainState defined in object \"" << this->getName() << "\" (" << this->getIdentifier()->getName() << ")" << std::endl;
316    }
317
318    bool BaseObject::getMainState() const
319    {
320        if (this->functorGetMainState_)
321        {
322            (*this->functorGetMainState_)();
323            return this->functorGetMainState_->getReturnvalue();
324        }
325        else
326        {
327            COUT(2) << "Warning: No MainState defined in object \"" << this->getName() << "\" (" << this->getIdentifier()->getName() << ")" << std::endl;
328            return false;
329        }
330    }
331
332    void BaseObject::changedMainState()
333    {
334        SetMainState(BaseObject, "activity",   setActive,  isActive);
335        SetMainState(BaseObject, "visibility", setVisible, isVisible);
336    }
337}
Note: See TracBrowser for help on using the repository browser.