Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/core5/src/libraries/core/BaseObject.cc @ 5866

Last change on this file since 5866 was 5866, checked in by landauf, 15 years ago

some cleanup in the eventsystem. not sure if everything still works, but there are more changes to come.

  • Property svn:eol-style set to native
File size: 12.6 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
36#include <tinyxml/tinyxml.h>
37
38#include "util/StringUtils.h"
39#include "CoreIncludes.h"
40#include "Event.h"
41#include "EventIncludes.h"
42#include "Functor.h"
43#include "Iterator.h"
44#include "Template.h"
45#include "XMLFile.h"
46#include "XMLNameListener.h"
47#include "XMLPort.h"
48
49namespace orxonox
50{
51    CreateFactory(BaseObject);
52
53    /**
54        @brief Constructor: Registers the object in the BaseObject-list.
55    */
56    BaseObject::BaseObject(BaseObject* creator) : bInitialized_(false)
57    {
58        RegisterRootObject(BaseObject);
59
60        this->bInitialized_ = true;
61
62        this->bActive_ = true;
63        this->bVisible_ = true;
64        this->oldGametype_ = 0;
65
66        this->lastLoadedXMLElement_ = 0;
67
68        this->functorSetMainState_ = 0;
69        this->functorGetMainState_ = 0;
70
71        this->setCreator(creator);
72        if (this->creator_)
73        {
74            this->setFile(this->creator_->getFile());
75            this->setNamespace(this->creator_->getNamespace());
76            this->setScene(this->creator_->getScene(), this->creator_->getSceneID());
77            this->setGametype(this->creator_->getGametype());
78        }
79        else
80        {
81            this->file_ = 0;
82            this->namespace_ = 0;
83            this->scene_ = 0;
84            this->sceneID_ = OBJECTID_UNKNOWN;
85            this->gametype_ = 0;
86        }
87    }
88
89    /**
90        @brief Destructor
91    */
92    BaseObject::~BaseObject()
93    {
94        if (this->isInitialized())
95        {
96            for (std::map<BaseObject*, std::string>::const_iterator it = this->eventSources_.begin(); it != this->eventSources_.end(); )
97                this->removeEventSource((it++)->first);
98
99            for (std::set<BaseObject*>::const_iterator it = this->eventListeners_.begin(); it != this->eventListeners_.end(); )
100                (*(it++))->removeEventSource(this);
101
102            for (std::map<std::string, EventContainer*>::const_iterator it = this->eventContainers_.begin(); it != this->eventContainers_.end(); ++it)
103                delete it->second;
104
105            if (this->functorSetMainState_)
106                delete this->functorSetMainState_;
107            if (this->functorGetMainState_)
108                delete this->functorGetMainState_;
109        }
110    }
111
112    /**
113        @brief XML loading and saving.
114        @param xmlelement The XML-element
115        @param loading Loading (true) or saving (false)
116        @return The XML-element
117    */
118    void BaseObject::XMLPort(Element& xmlelement, XMLPort::Mode mode)
119    {
120        XMLPortParam(BaseObject, "name", setXMLName, getName, xmlelement, mode);
121        XMLPortParam(BaseObject, "visible", setVisible, isVisible, xmlelement, mode);
122        XMLPortParam(BaseObject, "active", setActive, isActive, xmlelement, mode);
123        XMLPortParam(BaseObject, "mainstate", setMainStateName, getMainStateName, xmlelement, mode);
124
125        XMLPortObjectTemplate(BaseObject, Template, "templates", addTemplate, getTemplate, xmlelement, mode, Template*);
126
127        Element* events = xmlelement.FirstChildElement("events", false);
128
129        if (events)
130        {
131            std::list<std::string> eventnames;
132
133            if (mode == XMLPort::LoadObject || mode == XMLPort::ExpandObject)
134            {
135                for (ticpp::Iterator<ticpp::Element> child = events->FirstChildElement(false); child != child.end(); child++)
136                    eventnames.push_back(child->Value());
137            }
138            else if (mode == XMLPort::SaveObject)
139            {
140                for (std::map<std::string, XMLPortObjectContainer*>::const_iterator it = this->getIdentifier()->getXMLPortEventMapBegin(); it != this->getIdentifier()->getXMLPortEventMapEnd(); ++it)
141                    eventnames.push_back(it->first);
142            }
143
144            for (std::list<std::string>::iterator it = eventnames.begin(); it != eventnames.end(); ++it)
145            {
146                std::string sectionname = (*it);
147                ExecutorMember<BaseObject>* loadexecutor = createExecutor(createFunctor(&BaseObject::addEventSource), std::string( "BaseObject" ) + "::" + "addEventSource");
148                ExecutorMember<BaseObject>* saveexecutor = createExecutor(createFunctor(&BaseObject::getEventSource), std::string( "BaseObject" ) + "::" + "getEventSource");
149                loadexecutor->setDefaultValue(1, sectionname);
150                saveexecutor->setDefaultValue(1, sectionname);
151
152                XMLPortClassObjectContainer<BaseObject, BaseObject>* container = 0;
153                container = static_cast<XMLPortClassObjectContainer<BaseObject, BaseObject>*>(this->getIdentifier()->getXMLPortEventContainer(sectionname));
154                if (!container)
155                {
156                    container = new XMLPortClassObjectContainer<BaseObject, BaseObject>(sectionname, this->getIdentifier(), loadexecutor, saveexecutor, false, true);
157                    this->getIdentifier()->addXMLPortEventContainer(sectionname, container);
158                }
159                container->port(this, *events, mode);
160            }
161        }
162    }
163
164    /**
165        @brief Loads the name of the object through XML and calls all XMLNameListener.
166        @param name The name of the object
167    */
168    void BaseObject::setXMLName(const std::string& name)
169    {
170        this->setName(name);
171
172        for (ObjectList<XMLNameListener>::iterator it = ObjectList<XMLNameListener>::begin(); it != ObjectList<XMLNameListener>::end(); ++it)
173            it->loadedNewXMLName(this);
174    }
175
176    /**
177        @brief Returns the levelfile that loaded this object.
178        @return The levelfile
179    */
180    const std::string& BaseObject::getFilename() const
181    {
182        if (this->file_)
183            return this->file_->getFilename();
184        else
185            return BLANKSTRING;
186    }
187
188    /**
189        @brief Adds a Template to the object.
190        @param name The name of the Template
191    */
192    void BaseObject::addTemplate(const std::string& name)
193    {
194        Template* temp = Template::getTemplate(name);
195        if (temp)
196            this->addTemplate(temp);
197        else
198            COUT(1) << "Error: \"" << name << "\" is not a valid Template name (in class: " << this->getIdentifier()->getName() << ", name: " << this->getName() << ")." << std::endl;
199    }
200
201    /**
202        @brief Adds a Template to the object.
203        @param temp The Template
204    */
205    void BaseObject::addTemplate(Template* temp)
206    {
207        this->templates_.insert(temp);
208        temp->applyOn(this);
209    }
210
211    /**
212        @brief Returns the Template with the given index.
213        @param index The index
214    */
215    Template* BaseObject::getTemplate(unsigned int index) const
216    {
217        unsigned int i = 0;
218        for (std::set<Template*>::const_iterator it = this->templates_.begin(); it != this->templates_.end(); ++it)
219        {
220            if (i == index)
221                return (*it);
222            i++;
223        }
224        return 0;
225    }
226
227    /**
228        @brief Adds a new event source for a specific state.
229        @param source The object which sends events to this object
230        @param state The state of this object which will be affected by the events
231    */
232    void BaseObject::addEventSource(BaseObject* source, const std::string& state)
233    {
234        this->eventSources_[source] = state;
235        source->registerEventListener(this);
236    }
237
238    /**
239        @brief Removes an eventsource (but doesn't unregister itself at the source).
240    */
241    void BaseObject::removeEventSource(BaseObject* source)
242    {
243        this->eventSources_.erase(source);
244        source->unregisterEventListener(this);
245    }
246
247    /**
248        @brief Returns an eventsource with a given index.
249    */
250    BaseObject* BaseObject::getEventSource(unsigned int index, const std::string& state) const
251    {
252        unsigned int i = 0;
253        for (std::map<BaseObject*, std::string>::const_iterator it = this->eventSources_.begin(); it != this->eventSources_.end(); ++it)
254        {
255            if (it->second != state)
256                continue;
257           
258            if (i == index)
259                return it->first;
260            ++i;
261        }
262        return 0;
263    }
264
265    void BaseObject::addEventContainer(const std::string& sectionname, EventContainer* container)
266    {
267        std::map<std::string, EventContainer*>::const_iterator it = this->eventContainers_.find(sectionname);
268        if (it != this->eventContainers_.end())
269        {
270            COUT(2) << "Warning: Overwriting EventContainer in class " << this->getIdentifier()->getName() << "." << std::endl;
271            delete (it->second);
272        }
273
274        this->eventContainers_[sectionname] = container;
275    }
276
277    EventContainer* BaseObject::getEventContainer(const std::string& sectionname) const
278    {
279        std::map<std::string, EventContainer*>::const_iterator it = this->eventContainers_.find(sectionname);
280        if (it != this->eventContainers_.end())
281            return ((*it).second);
282        else
283            return 0;
284    }
285
286    /**
287        @brief Fires an event (without a state).
288    */
289    void BaseObject::fireEvent()
290    {
291        this->fireEvent(true);
292        this->fireEvent(false);
293    }
294
295    /**
296        @brief Fires an event which activates or deactivates a state.
297    */
298    void BaseObject::fireEvent(bool activate)
299    {
300        this->fireEvent(activate, this);
301    }
302
303    /**
304        @brief Fires an event which activates or deactivates a state with agiven originator (the object which sends the event).
305    */
306    void BaseObject::fireEvent(bool activate, BaseObject* originator)
307    {
308        Event event(activate, originator);
309
310        for (std::set<BaseObject*>::iterator it = this->eventListeners_.begin(); it != this->eventListeners_.end(); ++it)
311        {
312            event.sectionname_ = (*it)->eventSources_[this];
313            (*it)->processEvent(event);
314        }
315    }
316
317    /**
318        @brief Fires an event, using the Event struct.
319    */
320    void BaseObject::fireEvent(Event& event)
321    {
322        for (std::set<BaseObject*>::iterator it = this->eventListeners_.begin(); it != this->eventListeners_.end(); ++it)
323            (*it)->processEvent(event);
324    }
325
326    void BaseObject::processEvent(Event& event)
327    {
328        ORXONOX_SET_EVENT(BaseObject, "activity", setActive, event);
329        ORXONOX_SET_EVENT(BaseObject, "visibility", setVisible, event);
330    }
331
332    void BaseObject::setMainStateName(const std::string& name)
333    {
334        if (this->mainStateName_ != name)
335        {
336            this->mainStateName_ = name;
337            if (this->functorSetMainState_)
338                delete this->functorSetMainState_;
339            if (this->functorGetMainState_)
340                delete this->functorGetMainState_;
341            this->changedMainState();
342            if (!this->functorSetMainState_)
343                COUT(2) << "Warning: \"" << name << "\" is not a valid MainState." << std::endl;
344        }
345    }
346
347    void BaseObject::setMainState(bool state)
348    {
349        if (this->functorSetMainState_)
350            (*this->functorSetMainState_)(state);
351        else
352            COUT(2) << "Warning: No MainState defined in object \"" << this->getName() << "\" (" << this->getIdentifier()->getName() << ")" << std::endl;
353    }
354
355    bool BaseObject::getMainState() const
356    {
357        if (this->functorGetMainState_)
358        {
359            (*this->functorGetMainState_)();
360            return this->functorGetMainState_->getReturnvalue();
361        }
362        else
363        {
364            COUT(2) << "Warning: No MainState defined in object \"" << this->getName() << "\" (" << this->getIdentifier()->getName() << ")" << std::endl;
365            return false;
366        }
367    }
368
369    void BaseObject::changedMainState()
370    {
371        SetMainState(BaseObject, "activity",   setActive,  isActive);
372        SetMainState(BaseObject, "visibility", setVisible, isVisible);
373    }
374}
Note: See TracBrowser for help on using the repository browser.