Post removed.

Discuss about anything related to the Irrlicht Engine, or read announcements about any significant features or usage changes.
Post Reply

Good idea?

No, you fool.
1
13%
Yes.
7
88%
 
Total votes: 8

TheRLG
Posts: 372
Joined: Thu Oct 07, 2004 11:20 pm

Post removed.

Post by TheRLG »

Post removed.
Last edited by TheRLG on Fri Dec 28, 2007 7:29 am, edited 2 times in total.
vitek
Bug Slayer
Posts: 3919
Joined: Mon Jan 16, 2006 10:52 am
Location: Corvallis, OR

Post by vitek »

The current system kinda does that. It sends the messages back through the system as events. The current system is kinda weird to use though. All events are filtered down through the the entire application just so they end up somewhere the user can access them.

Another common way to handle things like this is...

Code: Select all

class IButtonHandler
{
public:
  virtual ~IButtonHandler()
  {
  }

  virtual void OnRightClick(IButton* button) = 0;
  virtual void OnLeftClick(IButton* button) = 0;
  virtual void OnMouseIn(IButton* button) = 0;
  virtual void OnMouseOut(IButton* button) = 0;
  virtual void OnMouseMoved(IButton* button) = 0;
};

class MyButton : public IButton
{
public:
  void setButtonHandler(IButtonHandler* handler)
  {
    Handler = handler;
  }

  // methods notify button handler
private:
  IButtonHandler* Handler;
};
CuteAlien
Admin
Posts: 9930
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Post by CuteAlien »

I'm currently using functors, which have the advantage over callbacks that you don't lose the class object.If we were to use callbacks they should at least have an additional pointer for custom data (usually void *) so you can still access custom objects by casting.

My current solution works for my game, but has still some disadvantages.
1.So far it works only for gui-events
2. Only one callback per gui-id is currently possible (one for each event would be better)
3. The necessary syntax looks complicated (i guess it could be made nicer with some clever defines)

Code for a typical functor:

Code: Select all

class IEventFunctor
{
public:
    virtual ~IEventFunctor() {}
    virtual bool CallEvent(const irr::SEvent &event_) = 0;
};

template <class T>
class EventFunctor : public IEventFunctor
{
public:
    EventFunctor(T* obj_, bool (T::* fpt_)(const irr::SEvent &event_))
    {
        mObj = obj_;
        mFunctionPtr = fpt_;
    }
    virtual ~EventFunctor() {}
    virtual bool CallEvent(const irr::SEvent &event_)
    {
        return (*mObj.*mFunctionPtr)(event_);
    }

private:
    bool (T::*  mFunctionPtr)(const irr::SEvent &event_);
    T*          mObj;
};
Then i use a map to store the functions (but other structures would also be no problem):

Code: Select all

    typedef std::map<int, IEventFunctor*> EventObjectMap;
    EventObjectMap   mGuiEventFunctors;
and certainly some access functions:

Code: Select all

void AddGuiEventFunctor(int elementId_, IEventFunctor * functor_ )
{
    mGuiEventFunctors[elementId_] = functor_;
}

void RemoveGuiEventFunctor(int elementId_)
{
    EventObjectMap::iterator it = mGuiEventFunctors.find(elementId_);
    if ( it != mGuiEventFunctors.end() )
    {
        mGuiEventFunctors.erase(it);
    }
}
And in the event-receiver i call them:

Code: Select all

bool OnEvent( SEvent &event)
{
    if ( event.EventType == EET_GUI_EVENT && event.GUIEvent.Caller )
    {
        EventObjectMap::iterator it = mGuiEventFunctors.find(event.GUIEvent.Caller->getID());
        if ( it != mGuiEventFunctors.end() )
        {
            if ( it->second->CallEvent(event) )
                return true;
        }
    }
    return false;
}
With this mechanism i can now add member-functions, which look like the eventreceiver, within any class (in this case for TestDialog, so this points to an instance of TestDialog) as callbacks for gui-elements like that:

Code: Select all

AddGuiEventFunctor(0, new EventFunctor<TestDialog>(this, &TestDialog::EventCallback));
Well, it's just another way to do it and it still can be improved (i'll try to do so when i find some time for it).
zenaku
Posts: 212
Joined: Tue Jun 07, 2005 11:23 pm

Post by zenaku »

What's wrong with deriving a class and overriding OnEvent() ? Overridden functions ARE function pointers. Since they are class members you also get a 'this' pointer, so no need for the 'void *context' either. The map you use to store functions, well in C++ that's called a vtable.

C++ already deals with this and it's built in to the language. Why redo it the old C way?
-------------------------------------
IrrLua - a Lua binding for Irrlicht
http://irrlua.sourceforge.net/
CuteAlien
Admin
Posts: 9930
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Post by CuteAlien »

zenaku wrote:What's wrong with deriving a class and overriding OnEvent() ?
There is nothing _wrong_ with that, but there are cases when it's not so useful.
In my game inheritance wouldn't be so nice for example, as the behaviour of my GUI-Dialogs is a lot different than that of IGUIWindow so i use composition there. It wouldn't be much of a problem still deriving IGUIWindows additionally, but with my solutions there's no need for that.

The old way still works, as i didn't change anything within the engine, but i have new possibilities now. The OnEvent functions have for example the disadvantages that they need long constructions of switch - case statements and ususally at the end of those there's nothing but another functioncall to handle the event. I started that way, but with several big Dialogs this got very complex and since i added my own solution this switch-case stuff could be completly removed. It's just about doing the same stuff with a lot less code and i think this is also the reason why most advanced gui-system do offer a callback mechanism.
TheRLG
Posts: 372
Joined: Thu Oct 07, 2004 11:20 pm

Post by TheRLG »

Post removed.
Last edited by TheRLG on Fri Dec 28, 2007 7:29 am, edited 1 time in total.
kornerr
Posts: 245
Joined: Thu Jul 06, 2006 9:57 am
Location: Russia, Siberia, Kemerovo
Contact:

Post by kornerr »

current event systems looks good to me. you just need to create your own event system suitable for your project and filter irr events to yours. this is easily done atm, so all's good)
Open Source all the way, baby ;)
OSRPG
bitplane
Admin
Posts: 3204
Joined: Mon Mar 28, 2005 3:45 am
Location: England
Contact:

Post by bitplane »

hmm I'm opposed to c-style callbacks. I like CuteAlien's functor approach, but I think it unnecessarily complicates things.
Vitek's suggestion has to be my favourite so far, it's simple, could work for any GUI elements, and more importantly it fits Irrlicht's style.
There's still lots of other GUI things I need to fix at the moment, so no promises yet!
Submit bugs/patches to the tracker!
Need help right now? Visit the chat room
TheRLG
Posts: 372
Joined: Thu Oct 07, 2004 11:20 pm

Post by TheRLG »

Post removed.
Last edited by TheRLG on Fri Dec 28, 2007 7:29 am, edited 1 time in total.
vitek
Bug Slayer
Posts: 3919
Joined: Mon Jan 16, 2006 10:52 am
Location: Corvallis, OR

Post by vitek »

I think adding callback support is fine and dandy, but if you are going to add callback support then the GUI event stuff should be deprecated. Having two ways to do the same thing is not a good idea IMO.

Travis
Post Reply