Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

Ignore:
Timestamp:
Oct 5, 2009, 5:02:25 PM (15 years ago)
Author:
landauf
Message:

More changes in the event-system: processEvent() is now locally executed in BaseObject. The event states (like activity, visibility, …) are now defined in XMLEventPort, a function which closely resembles XMLPort. This function is used to define event states and to parse event sources from XML.

Connected the main-state directly with the event-system. After a state was declared as the "main state", the Functor from the corresponding EventState-object is used to call the function. This reduces the redundancy of declaring event-states and main-states separately. Of course only boolean event-states (like activity or visibility) can be used as main-state, while memoryless states (like spawn in ParticleSpawner) and individual states which need the triggering object (like execute in QuestEffectBeacon) won't work.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • code/branches/core5/src/libraries/core/BaseObject.cc

    r5866 r5879  
    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);
     
    100100                (*(it++))->removeEventSource(this);
    101101
    102             for (std::map<std::string, EventContainer*>::const_iterator it = this->eventContainers_.begin(); it != this->eventContainers_.end(); ++it)
     102            for (std::map<std::string, EventState*>::const_iterator it = this->eventStates_.begin(); it != this->eventStates_.end(); ++it)
    103103                delete it->second;
    104 
    105             if (this->functorSetMainState_)
    106                 delete this->functorSetMainState_;
    107             if (this->functorGetMainState_)
    108                 delete this->functorGetMainState_;
    109104        }
    110105    }
     
    114109        @param xmlelement The XML-element
    115110        @param loading Loading (true) or saving (false)
    116         @return The XML-element
    117111    */
    118112    void BaseObject::XMLPort(Element& xmlelement, XMLPort::Mode mode)
     
    124118
    125119        XMLPortObjectTemplate(BaseObject, Template, "templates", addTemplate, getTemplate, xmlelement, mode, Template*);
    126 
    127         Element* events = xmlelement.FirstChildElement("events", false);
    128 
     120       
     121        Element* events = 0;
     122        if (mode == XMLPort::LoadObject || mode == XMLPort::ExpandObject)
     123            events = xmlelement.FirstChildElement("events", false);
     124        else if (mode == XMLPort::SaveObject)
     125            ;
    129126        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         }
     127            this->XMLEventPort(*events, mode);
     128    }
     129
     130    /**
     131        @brief Defines the possible event states of this object and parses eventsources from an XML file.
     132        @param xmlelement The XML-element
     133        @param loading Loading (true) or saving (false)
     134    */
     135    void BaseObject::XMLEventPort(Element& xmlelement, XMLPort::Mode mode)
     136    {
     137        XMLPortEventState(BaseObject, BaseObject, "activity", setActive, xmlelement, mode);
     138        XMLPortEventState(BaseObject, BaseObject, "visibility", setVisible, xmlelement, mode);
     139       
     140        this->bRegisteredEventStates_ = true;
    162141    }
    163142
     
    263242    }
    264243
    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;
     244    void BaseObject::addEventState(const std::string& name, EventState* state)
     245    {
     246        std::map<std::string, EventState*>::const_iterator it = this->eventStates_.find(name);
     247        if (it != this->eventStates_.end())
     248        {
     249            COUT(2) << "Warning: Overwriting EventState in class " << this->getIdentifier()->getName() << "." << std::endl;
    271250            delete (it->second);
    272251        }
    273252
    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())
     253        this->eventStates_[name] = state;
     254    }
     255
     256    EventState* BaseObject::getEventState(const std::string& name) const
     257    {
     258        std::map<std::string, EventState*>::const_iterator it = this->eventStates_.find(name);
     259        if (it != this->eventStates_.end())
    281260            return ((*it).second);
    282261        else
     
    302281
    303282    /**
    304         @brief Fires an event which activates or deactivates a state with agiven originator (the object which sends the event).
     283        @brief Fires an event which activates or deactivates a state with agiven originator (the object which triggered the event).
    305284    */
    306285    void BaseObject::fireEvent(bool activate, BaseObject* originator)
     
    310289        for (std::set<BaseObject*>::iterator it = this->eventListeners_.begin(); it != this->eventListeners_.end(); ++it)
    311290        {
    312             event.sectionname_ = (*it)->eventSources_[this];
     291            event.statename_ = (*it)->eventSources_[this];
    313292            (*it)->processEvent(event);
    314293        }
     
    324303    }
    325304
     305    /**
     306        @brief Processing an event by calling the right main state.
     307        @param event The event struct which contains the information about the event
     308    */
    326309    void BaseObject::processEvent(Event& event)
    327310    {
    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 
     311        this->registerEventStates();
     312       
     313        std::map<std::string, EventState*>::const_iterator it = this->eventStates_.find(event.statename_);
     314        if (it != this->eventStates_.end())
     315            it->second->process(event, this);
     316        else if (event.statename_ != "")
     317            COUT(2) << "Warning: \"" << event.statename_ << "\" is not a valid state in object \"" << this->getName() << "\" of class " << this->getIdentifier()->getName() << "." << std::endl;
     318        else
     319            COUT(2) << "Warning: Event with invalid source sent to object \"" << this->getName() << "\" of class " << this->getIdentifier()->getName() << "." << std::endl;
     320    }
     321
     322    /**
     323        @brief Sets the main state of the object to a given boolean value.
     324       
     325        Note: The main state of an object can be set with the @ref setMainStateName function.
     326        It's part of the eventsystem and used for event forwarding (when the target object can't specify a specific state,
     327        the main state is used by default).
     328    */
    347329    void BaseObject::setMainState(bool state)
    348330    {
    349         if (this->functorSetMainState_)
    350             (*this->functorSetMainState_)(state);
     331        if (this->mainStateFunctor_)
     332            (*this->mainStateFunctor_)(state);
    351333        else
    352334            COUT(2) << "Warning: No MainState defined in object \"" << this->getName() << "\" (" << this->getIdentifier()->getName() << ")" << std::endl;
    353335    }
    354336
    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);
     337    /**
     338        @brief This function gets called if the main state name of the object changes.
     339    */
     340    void BaseObject::changedMainStateName()
     341    {
     342        this->registerEventStates();
     343       
     344        this->mainStateFunctor_ = 0;
     345       
     346        std::map<std::string, EventState*>::const_iterator it = this->eventStates_.find(this->mainStateName_);
     347        if (it != this->eventStates_.end() && it->second->getFunctor() && it->second->getFunctor()->getParamCount() == 1)
     348            this->mainStateFunctor_ = it->second->getFunctor();
     349        else
     350            COUT(2) << "Warning: \"" << this->mainStateName_ << "\" is not a valid MainState." << std::endl;
     351    }
     352   
     353    /**
     354        @brief Calls XMLEventPort with an empty XML-element to register the event states if necessary.
     355    */
     356    void BaseObject::registerEventStates()
     357    {
     358        if (!this->bRegisteredEventStates_)
     359        {
     360            Element xmlelement;
     361            this->XMLEventPort(xmlelement, XMLPort::NOP);
     362        }
    373363    }
    374364}
Note: See TracChangeset for help on using the changeset viewer.