The All-New, All-Singing, All-Dancing CrystalSpace Event System

The CrystalSpace event core suffers from two serious architectural problems:

  • There can only be 32 event names.
    • This means event names must be divorced from event source identities, i.e., it is possible to subscribe to "joystick button events" but not "button events only from the first joystick".
    • More generally, this limits the granularity with which event handlers can limit the set of events they receive.
    • This forces the creation of artificial aggregate event types (e.g., the "Command" event type).
  • The only way to make sure one handler receives an event before another handler is for it to subscribe first. Furthermore, there is only one order - it is not possible to say "give me event A before handler X, but give me event B after handler X".

Hierarchical Event Naming System (BETA)

Events are now named using lexical dot-separated strings, e.g., crystalspace.input.joystick.2.button.down.

Event handlers can subscribe to a full event name or to an event name prefix (e.g., crystalspace.input.joystick.2); in the latter case, the subscriber receives all events whose names have that prefix.

Roadmap to the new event namespace...

Internally, event names are converted into csEventIDs (which are just csStringIDs) by the static csEventNameRegistry::GetID() method, which can be converted back into strings by csEventNameRegistry::GetString(). Event name relationships can be managed using the csEventNameRegistry::GetParentID(), csEventNameRegistry::IsKindOf(), and csEventNameRegistry::IsImmediateChildOf() methods.

Event Subscription and Scheduling (BETA)

An event handler is mapped to a csHandlerID (just a csStringID) by the static csHandlerRegistry::GetID() method. (It does this using the event handler's ::GenericName() method, combined with an "instance counter" that is used to distinguish between multiple distinct instances of a single event handler.)

These csHandlerIDs are used, in conjunction with the handler's implementations of the iEventHandler::GenericPrec(), ::GenericSucc(), ::InstancePrec(), and ::InstanceSucc() methods, to establish the order in which handlers receive events.

The arrays returned by the ::InstancePrec() and ::InstanceSucc() methods are comprised of generic and instance IDs of other event handlers which should, for the event given as the method's argument, handle the given event before or after this handler. csHandlerIDs are acquired for handlers which have not yet been instantiated by calling csHandlerRegistry::GetID(HandlerClass::StaticID(), and for those which have been instantiated by calling csHandlerRegistry::GetID(h) for the iEventHandler pointer h. See csHandlerRegistry for all of the related helper functions and their interfaces.

Patches