Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

Ignore:
Timestamp:
Oct 13, 2009, 5:05:17 PM (15 years ago)
Author:
dafrick
Message:

Hopefully merged trunk successfully into pickup branch.

Location:
code/branches/pickup
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • code/branches/pickup

  • code/branches/pickup/src/libraries/core/BaseObject.cc

    r5781 r5935  
    6363        this->bVisible_ = true;
    6464        this->oldGametype_ = 0;
     65        this->bRegisteredEventStates_ = false;
    6566
    6667        this->lastLoadedXMLElement_ = 0;
    6768
    68         this->functorSetMainState_ = 0;
    69         this->functorGetMainState_ = 0;
     69        this->mainStateFunctor_ = 0;
    7070
    7171        this->setCreator(creator);
     
    7474            this->setFile(this->creator_->getFile());
    7575            this->setNamespace(this->creator_->getNamespace());
    76             this->setScene(this->creator_->getScene());
     76            this->setScene(this->creator_->getScene(), this->creator_->getSceneID());
    7777            this->setGametype(this->creator_->getGametype());
    7878        }
     
    8282            this->namespace_ = 0;
    8383            this->scene_ = 0;
     84            this->sceneID_ = OBJECTID_UNKNOWN;
    8485            this->gametype_ = 0;
    8586        }
     
    9394        if (this->isInitialized())
    9495        {
    95             for (std::list<BaseObject*>::const_iterator it = this->events_.begin(); it != this->events_.end(); ++it)
    96                 (*it)->unregisterEventListener(this);
    97 
    98             for (std::map<BaseObject*, std::string>::const_iterator it = this->eventListeners_.begin(); it != this->eventListeners_.end(); ++it)
    99                 it->first->removeEvent(this);
    100 
    101             if (this->functorSetMainState_)
    102                 delete this->functorSetMainState_;
    103             if (this->functorGetMainState_)
    104                 delete this->functorGetMainState_;
     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, EventState*>::const_iterator it = this->eventStates_.begin(); it != this->eventStates_.end(); ++it)
     103                delete it->second;
    105104        }
    106105    }
     
    110109        @param xmlelement The XML-element
    111110        @param loading Loading (true) or saving (false)
    112         @return The XML-element
    113111    */
    114112    void BaseObject::XMLPort(Element& xmlelement, XMLPort::Mode mode)
     
    120118
    121119        XMLPortObjectTemplate(BaseObject, Template, "templates", addTemplate, getTemplate, xmlelement, mode, Template*);
    122 
    123         Element* events = xmlelement.FirstChildElement("events", false);
    124 
     120        XMLPortObject(BaseObject, BaseObject, "eventlisteners", addEventListener, getEventListener, xmlelement, mode);
     121       
     122        Element* events = 0;
     123        if (mode == XMLPort::LoadObject || mode == XMLPort::ExpandObject)
     124            events = xmlelement.FirstChildElement("events", false);
     125        else if (mode == XMLPort::SaveObject)
     126            {}
    125127        if (events)
    126         {
    127             std::list<std::string> eventnames;
    128 
    129             if (mode == XMLPort::LoadObject || mode == XMLPort::ExpandObject)
    130             {
    131                 for (ticpp::Iterator<ticpp::Element> child = events->FirstChildElement(false); child != child.end(); child++)
    132                     eventnames.push_back(child->Value());
    133             }
    134             else if (mode == XMLPort::SaveObject)
    135             {
    136                 for (std::map<std::string, XMLPortObjectContainer*>::const_iterator it = this->getIdentifier()->getXMLPortEventMapBegin(); it != this->getIdentifier()->getXMLPortEventMapEnd(); ++it)
    137                     eventnames.push_back(it->first);
    138             }
    139 
    140             for (std::list<std::string>::iterator it = eventnames.begin(); it != eventnames.end(); ++it)
    141             {
    142                 std::string sectionname = (*it);
    143                 ExecutorMember<BaseObject>* loadexecutor = createExecutor(createFunctor(&BaseObject::addEvent), std::string( "BaseObject" ) + "::" + "addEvent");
    144                 ExecutorMember<BaseObject>* saveexecutor = createExecutor(createFunctor(&BaseObject::getEvent), std::string( "BaseObject" ) + "::" + "getEvent");
    145                 loadexecutor->setDefaultValue(1, sectionname);
    146 
    147                 XMLPortClassObjectContainer<BaseObject, BaseObject>* container = 0;
    148                 container = (XMLPortClassObjectContainer<BaseObject, BaseObject>*)(this->getIdentifier()->getXMLPortEventContainer(sectionname));
    149                 if (!container)
    150                 {
    151                     container = new XMLPortClassObjectContainer<BaseObject, BaseObject>(sectionname, this->getIdentifier(), loadexecutor, saveexecutor, false, true);
    152                     this->getIdentifier()->addXMLPortEventContainer(sectionname, container);
    153                 }
    154                 container->port(this, *events, mode);
    155             }
    156         }
     128            this->XMLEventPort(*events, mode);
     129    }
     130
     131    /**
     132        @brief Defines the possible event states of this object and parses eventsources from an XML file.
     133        @param xmlelement The XML-element
     134        @param loading Loading (true) or saving (false)
     135    */
     136    void BaseObject::XMLEventPort(Element& xmlelement, XMLPort::Mode mode)
     137    {
     138        XMLPortEventState(BaseObject, BaseObject, "activity", setActive, xmlelement, mode);
     139        XMLPortEventState(BaseObject, BaseObject, "visibility", setVisible, xmlelement, mode);
     140        XMLPortEventState(BaseObject, BaseObject, "mainstate", setMainState, xmlelement, mode);
     141       
     142        this->bRegisteredEventStates_ = true;
    157143    }
    158144
     
    220206    }
    221207
    222     void BaseObject::addEvent(BaseObject* event, const std::string& sectionname)
    223     {
    224         event->registerEventListener(this, sectionname);
    225         this->events_.push_back(event);
    226     }
    227 
    228     void BaseObject::removeEvent(BaseObject* event)
    229     {
    230         this->events_.remove(event);
    231     }
    232 
    233     BaseObject* BaseObject::getEvent(unsigned int index) const
     208    /**
     209        @brief Adds a new event source for a specific state.
     210        @param source The object which sends events to this object
     211        @param state The state of this object which will be affected by the events
     212    */
     213    void BaseObject::addEventSource(BaseObject* source, const std::string& state)
     214    {
     215        this->eventSources_[source] = state;
     216        source->registerEventListener(this);
     217    }
     218
     219    /**
     220        @brief Removes an eventsource (but doesn't unregister itself at the source).
     221    */
     222    void BaseObject::removeEventSource(BaseObject* source)
     223    {
     224        this->eventSources_.erase(source);
     225        source->unregisterEventListener(this);
     226    }
     227
     228    /**
     229        @brief Returns an eventsource with a given index.
     230    */
     231    BaseObject* BaseObject::getEventSource(unsigned int index, const std::string& state) const
    234232    {
    235233        unsigned int i = 0;
    236         for (std::list<BaseObject*>::const_iterator it = this->events_.begin(); it != this->events_.end(); ++it)
    237         {
     234        for (std::map<BaseObject*, std::string>::const_iterator it = this->eventSources_.begin(); it != this->eventSources_.end(); ++it)
     235        {
     236            if (it->second != state)
     237                continue;
     238           
    238239            if (i == index)
    239                 return (*it);
     240                return it->first;
    240241            ++i;
    241242        }
     
    243244    }
    244245
    245     void BaseObject::addEventContainer(const std::string& sectionname, EventContainer* container)
    246     {
    247         std::map<std::string, EventContainer*>::const_iterator it = this->eventContainers_.find(sectionname);
    248         if (it != this->eventContainers_.end())
    249         {
    250             COUT(2) << "Warning: Overwriting EventContainer in class " << this->getIdentifier()->getName() << "." << std::endl;
     246    /**
     247        @brief Adds an object which listens to the events of this object. The events are sent to the other objects mainstate.
     248    */
     249    void BaseObject::addEventListener(BaseObject* listener)
     250    {
     251        this->eventListenersXML_.insert(listener);
     252        listener->addEventSource(this, "mainstate");
     253    }
     254   
     255    /**
     256        @brief Returns an event listener with a given index.
     257    */
     258    BaseObject* BaseObject::getEventListener(unsigned int index) const
     259    {
     260        unsigned int i = 0;
     261        for (std::set<BaseObject*>::const_iterator it = this->eventListenersXML_.begin(); it != this->eventListenersXML_.end(); ++it)
     262        {
     263            if (i == index)
     264                return *it;
     265            ++i;
     266        }
     267        return 0;
     268    }
     269
     270    /**
     271        @brief Adds a new event-state to the object. Event-states are states which can be changed by events.
     272        @param name  The name of the event
     273        @param state The object containing information about the event-state
     274    */
     275    void BaseObject::addEventState(const std::string& name, EventState* state)
     276    {
     277        std::map<std::string, EventState*>::const_iterator it = this->eventStates_.find(name);
     278        if (it != this->eventStates_.end())
     279        {
     280            COUT(2) << "Warning: Overwriting EventState in class " << this->getIdentifier()->getName() << "." << std::endl;
    251281            delete (it->second);
    252282        }
    253283
    254         this->eventContainers_[sectionname] = container;
    255     }
    256 
    257     EventContainer* BaseObject::getEventContainer(const std::string& sectionname) const
    258     {
    259         std::map<std::string, EventContainer*>::const_iterator it = this->eventContainers_.find(sectionname);
    260         if (it != this->eventContainers_.end())
     284        this->eventStates_[name] = state;
     285    }
     286
     287    /**
     288        @brief Returns the event-state with the given name.
     289    */
     290    EventState* BaseObject::getEventState(const std::string& name) const
     291    {
     292        std::map<std::string, EventState*>::const_iterator it = this->eventStates_.find(name);
     293        if (it != this->eventStates_.end())
    261294            return ((*it).second);
    262295        else
     
    264297    }
    265298
    266     void BaseObject::fireEvent()
    267     {
    268         this->fireEvent(true);
    269         this->fireEvent(false);
    270     }
    271 
    272     void BaseObject::fireEvent(bool activate)
    273     {
    274         this->fireEvent(activate, this);
    275     }
    276 
    277     void BaseObject::fireEvent(bool activate, BaseObject* originator)
    278     {
    279         Event event(activate, originator);
    280 
    281         for (std::map<BaseObject*, std::string>::iterator it = this->eventListeners_.begin(); it != this->eventListeners_.end(); ++it)
    282         {
    283             event.sectionname_ = it->second;
    284             it->first->processEvent(event);
    285         }
    286     }
    287 
     299    /**
     300        @brief Fires an event (without a state).
     301    */
     302    void BaseObject::fireEvent(const std::string& name)
     303    {
     304        this->fireEvent(true, name);
     305        this->fireEvent(false, name);
     306    }
     307
     308    /**
     309        @brief Fires an event which activates or deactivates a state.
     310    */
     311    void BaseObject::fireEvent(bool activate, const std::string& name)
     312    {
     313        this->fireEvent(activate, this, name);
     314    }
     315
     316    /**
     317        @brief Fires an event which activates or deactivates a state with agiven originator (the object which triggered the event).
     318    */
     319    void BaseObject::fireEvent(bool activate, BaseObject* originator, const std::string& name)
     320    {
     321        Event event(activate, originator, name);
     322
     323        for (std::set<BaseObject*>::iterator it = this->eventListeners_.begin(); it != this->eventListeners_.end(); ++it)
     324        {
     325            event.statename_ = (*it)->eventSources_[this];
     326            (*it)->processEvent(event);
     327        }
     328    }
     329
     330    /**
     331        @brief Fires an event, using the Event struct.
     332    */
    288333    void BaseObject::fireEvent(Event& event)
    289334    {
    290         for (std::map<BaseObject*, std::string>::iterator it = this->eventListeners_.begin(); it != this->eventListeners_.end(); ++it)
    291             it->first->processEvent(event);
    292     }
    293 
     335        for (std::set<BaseObject*>::iterator it = this->eventListeners_.begin(); it != this->eventListeners_.end(); ++it)
     336            (*it)->processEvent(event);
     337    }
     338
     339    /**
     340        @brief Processing an event by calling the right main state.
     341        @param event The event struct which contains the information about the event
     342    */
    294343    void BaseObject::processEvent(Event& event)
    295344    {
    296         ORXONOX_SET_EVENT(BaseObject, "activity", setActive, event);
    297         ORXONOX_SET_EVENT(BaseObject, "visibility", setVisible, event);
    298     }
    299 
    300     void BaseObject::setMainStateName(const std::string& name)
    301     {
    302         if (this->mainStateName_ != name)
    303         {
    304             this->mainStateName_ = name;
    305             if (this->functorSetMainState_)
    306                 delete this->functorSetMainState_;
    307             if (this->functorGetMainState_)
    308                 delete this->functorGetMainState_;
    309             this->changedMainState();
    310             if (!this->functorSetMainState_)
    311                 COUT(2) << "Warning: \"" << name << "\" is not a valid MainState." << std::endl;
    312         }
    313     }
    314 
     345        this->registerEventStates();
     346       
     347        std::map<std::string, EventState*>::const_iterator it = this->eventStates_.find(event.statename_);
     348        if (it != this->eventStates_.end())
     349            it->second->process(event, this);
     350        else if (event.statename_ != "")
     351            COUT(2) << "Warning: \"" << event.statename_ << "\" is not a valid state in object \"" << this->getName() << "\" of class " << this->getIdentifier()->getName() << "." << std::endl;
     352        else
     353            COUT(2) << "Warning: Event with invalid source sent to object \"" << this->getName() << "\" of class " << this->getIdentifier()->getName() << "." << std::endl;
     354    }
     355
     356    /**
     357        @brief Sets the main state of the object to a given boolean value.
     358       
     359        Note: The main state of an object can be set with the @ref setMainStateName function.
     360        It's part of the eventsystem and used for event forwarding (when the target object can't specify a specific state,
     361        the main state is used by default).
     362    */
    315363    void BaseObject::setMainState(bool state)
    316364    {
    317         if (this->functorSetMainState_)
    318             (*this->functorSetMainState_)(state);
     365        if (this->mainStateFunctor_)
     366        {
     367            if (this->mainStateFunctor_->getParamCount() == 0)
     368            {
     369                if (state)
     370                    (*this->mainStateFunctor_)();
     371            }
     372            else
     373            {
     374                (*this->mainStateFunctor_)(state);
     375            }
     376        }
    319377        else
    320378            COUT(2) << "Warning: No MainState defined in object \"" << this->getName() << "\" (" << this->getIdentifier()->getName() << ")" << std::endl;
    321379    }
    322380
    323     bool BaseObject::getMainState() const
    324     {
    325         if (this->functorGetMainState_)
    326         {
    327             (*this->functorGetMainState_)();
    328             return this->functorGetMainState_->getReturnvalue();
    329         }
    330         else
    331         {
    332             COUT(2) << "Warning: No MainState defined in object \"" << this->getName() << "\" (" << this->getIdentifier()->getName() << ")" << std::endl;
    333             return false;
    334         }
    335     }
    336 
    337     void BaseObject::changedMainState()
    338     {
    339         SetMainState(BaseObject, "activity",   setActive,  isActive);
    340         SetMainState(BaseObject, "visibility", setVisible, isVisible);
     381    /**
     382        @brief This function gets called if the main state name of the object changes.
     383    */
     384    void BaseObject::changedMainStateName()
     385    {
     386        this->mainStateFunctor_ = 0;
     387
     388        if (this->mainStateName_ != "")
     389        {
     390            this->registerEventStates();
     391           
     392            std::map<std::string, EventState*>::const_iterator it = this->eventStates_.find(this->mainStateName_);
     393            if (it != this->eventStates_.end() && it->second->getFunctor())
     394            {
     395                if (it->second->getFunctor()->getParamCount() <= 1)
     396                    this->mainStateFunctor_ = it->second->getFunctor();
     397                else
     398                    COUT(2) << "Warning: Can't use \"" << this->mainStateName_ << "\" as MainState because it needs a second argument." << std::endl;
     399            }
     400            else
     401                COUT(2) << "Warning: \"" << this->mainStateName_ << "\" is not a valid MainState." << std::endl;
     402        }
     403    }
     404   
     405    /**
     406        @brief Calls XMLEventPort with an empty XML-element to register the event states if necessary.
     407    */
     408    void BaseObject::registerEventStates()
     409    {
     410        if (!this->bRegisteredEventStates_)
     411        {
     412            Element xmlelement;
     413            this->XMLEventPort(xmlelement, XMLPort::NOP);
     414        }
     415    }
     416   
     417    /**
     418        @brief Manually loads all event states, even if the class doesn't officially support them. This is needed by some classes like @ref EventDispatcher or @ref EventTarget.
     419    */
     420    void BaseObject::loadAllEventStates(Element& xmlelement, XMLPort::Mode mode, BaseObject* object, Identifier* identifier)
     421    {
     422        Element* events = xmlelement.FirstChildElement("events", false);
     423        if (events)
     424        {
     425            // get the list of all states present
     426            std::list<std::string> eventnames;
     427            if (mode == XMLPort::LoadObject || mode == XMLPort::ExpandObject)
     428            {
     429                for (ticpp::Iterator<ticpp::Element> child = events->FirstChildElement(false); child != child.end(); child++)
     430                    eventnames.push_back(child->Value());
     431            }
     432            else if (mode == XMLPort::SaveObject)
     433            {
     434            }
     435
     436            // iterate through all states and get the event sources
     437            for (std::list<std::string>::iterator it = eventnames.begin(); it != eventnames.end(); ++it)
     438            {
     439                std::string statename = (*it);
     440
     441                // if the event state is already known, continue with the next state
     442                orxonox::EventState* eventstate = object->getEventState(statename);
     443                if (eventstate)
     444                    continue;
     445
     446                XMLPortClassObjectContainer<BaseObject, BaseObject>* container = (XMLPortClassObjectContainer<BaseObject, BaseObject>*)(identifier->getXMLPortObjectContainer(statename));
     447                if (!container)
     448                {
     449                    ExecutorMember<BaseObject>* setfunctor = createExecutor(createFunctor(&BaseObject::addEventSource), std::string( "BaseObject" ) + "::" + "addEventSource" + "(" + statename + ")");
     450                    ExecutorMember<BaseObject>* getfunctor = createExecutor(createFunctor(&BaseObject::getEventSource), std::string( "BaseObject" ) + "::" + "getEventSource" + "(" + statename + ")");
     451                    setfunctor->setDefaultValue(1, statename);
     452                    getfunctor->setDefaultValue(1, statename);
     453
     454                    container = new XMLPortClassObjectContainer<BaseObject, BaseObject>(statename, identifier, setfunctor, getfunctor, false, true);
     455                    identifier->addXMLPortObjectContainer(statename, container);
     456                }
     457                container->port(object, *events, mode);
     458            }
     459        }
    341460    }
    342461}
Note: See TracChangeset for help on using the changeset viewer.