Post removed.
Post removed.
Post removed.
Last edited by TheRLG on Fri Dec 28, 2007 7:29 am, edited 2 times in total.
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...
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;
};
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:
Then i use a map to store the functions (but other structures would also be no problem):
and certainly some access functions:
And in the event-receiver i call them:
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:
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).
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;
};
Code: Select all
typedef std::map<int, IEventFunctor*> EventObjectMap;
EventObjectMap mGuiEventFunctors;
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);
}
}
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;
}
Code: Select all
AddGuiEventFunctor(0, new EventFunctor<TestDialog>(this, &TestDialog::EventCallback));
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?
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/
IrrLua - a Lua binding for Irrlicht
http://irrlua.sourceforge.net/
There is nothing _wrong_ with that, but there are cases when it's not so useful.zenaku wrote:What's wrong with deriving a class and overriding OnEvent() ?
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.
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!
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!