[vtk-developers] Some Event handling ideas

David Gobbi david.gobbi at gmail.com
Mon Jul 10 14:59:07 EDT 2017


Hi Ken,

Why not use polymorphism here?  I use an event hierarchy like so:

  Event <- InputEvent <- PointEvent, KeyEvent

I've never used a union; the code that generates the event knows what type
of event object to instantiate, and the observer methods just get a pointer
to the event object.  Qt does things similarly.

 - David


On Mon, Jul 10, 2017 at 9:15 AM, Ken Martin <ken.martin at kitware.com> wrote:

>
> Lucas and I have been working on VTK's VR support and one issue we bumped
> into was event handing. VTK's event handling tends to be data light where
> most events follow this approach
>
> 1) event happens
>
> 2) we set properties on the interactor such as alt/shift/control key
> state, mouse position, etc
>
> 3) fire the event (with little or no calldata)
>
> 4) event handlers query needed properties from the interactor
>
> The challenge here is that as more event types are supported, the
> interactor's state and structure is required to grow to match them.  For
> example with multitouch events, the interactor now has to support multiple
> mouse positions and pointer indexes. Now add in multi controller VR and we
> have to also store arrays of world coordinate positions and orientations
> and what controller the current event corresponds to.
>
> Many systems use a different approach where they define an event data
> structure or class that get passed with the event (or associated with the
> event). Then whatever is handling the event receives that data structure
> which contains most of the key properties of the event.  Such an event
> structure can also be used for filtering. For example currently in VTK you
> can map keyboard events on a widget using the vtkWidgetCallbackMapper method
>
> void SetCallbackMethod(unsigned long VTKEvent, int modifiers, char keyCode,
>                          int repeatCount, const char* keySym,
>                          unsigned long widgetEvent,
>                          vtkAbstractWidget *w, CallbackType f);
>
> Note that this signature is designed for keyboard events as it contains
> keyboard event specific parameters. To add a mapping for multitouch, or VR
> controller events would require more event specific signatures. In contrast
> if we had a formal vtkEventData structure then the method could use a
> vtkEventData as a filter and handle many different event types as long as
> the EventData has an equality operator on it (or maybe a filtering specific
> equality).
>
> Lucas and I have tried this out for VR and it has made event handling
> reasonable and fairly clean and I would like to get some feedback on the
> idea/approach/etc.  Right now our vtkEventData is included below. It uses
> the approach of a union of event type structs and what has been fleshed out
> is targeted at VR but it should be easy to see how keyboard or mouse
> devices/events could get added as well.
>
> Thanks!
> Ken
>
>
>
> enum class vtkEventDataDevice {
>   Unknown = -1,
>   HeadMountedDisplay,
>   RightController,
>   LeftController,
>   NumberOfDevices
> };
>
> const int vtkEventDataNumberOfDevices =
>   static_cast<int>(vtkEventDataDevice::NumberOfDevices);
>
> enum class vtkEventDataDeviceInput {
>   Unknown = -1,
>   Trigger,
>   TrackPad,
>   Grip,
>   ApplicationMenu,
>   NumberOfInputs
> };
>
> const int vtkEventDataNumberOfInputs =
>   static_cast<int>(vtkEventDataDeviceInput::NumberOfInputs);
>
> enum class vtkEventDataAction {
>   Unknown = -1,
>   Press,
>   Release,
>   NumberOfActions
> };
>
> struct vtkEventDataButton3D
> {
>   vtkEventDataDevice Device;
>   vtkEventDataDeviceInput Input;
>   vtkEventDataAction Action;
>   double WorldPosition[3];
>   double WorldOrientation[4];
>
>   bool operator==(const vtkEventDataButton3D& rh)
>   {
>     return (Device == rh.Device && Input == rh.Input && Action ==
> rh.Action);
>   }
>   void SetWorldPosition(const double p[3])
>   {
>     WorldPosition[0] = p[0];
>     WorldPosition[1] = p[1];
>     WorldPosition[2] = p[2];
>   }
>   void SetWorldOrientation(const double p[4])
>   {
>     WorldOrientation[0] = p[0];
>     WorldOrientation[1] = p[1];
>     WorldOrientation[2] = p[2];
>     WorldOrientation[3] = p[3];
>   }
> };
>
> struct vtkEventDataMove3D
> {
>   vtkEventDataDevice Device;
>   double WorldPosition[3];
>   double WorldOrientation[4];
>
>   bool operator==(const vtkEventDataMove3D& rh)
>   {
>     return (Device == rh.Device);
>   }
>   void SetWorldPosition(const double p[3])
>   {
>     WorldPosition[0] = p[0];
>     WorldPosition[1] = p[1];
>     WorldPosition[2] = p[2];
>   }
>   void SetWorldOrientation(const double p[4])
>   {
>     WorldOrientation[0] = p[0];
>     WorldOrientation[1] = p[1];
>     WorldOrientation[2] = p[2];
>     WorldOrientation[3] = p[3];
>   }
> };
>
> typedef union
> {
>   vtkEventDataButton3D Button;
>   vtkEventDataMove3D Move;
> } vtkEventDataUnion;
>
> struct vtkEventData
> {
>   int Type; // see vtkCommand.h
>   vtkEventDataUnion Data;
>
>   bool operator==(const vtkEventData& rh)
>   {
>     if (Type != rh.Type)
>     {
>       return false;
>     }
>     switch (Type)
>     {
>       case vtkCommand::ButtonEvent3D:
>         return Data.Button == rh.Data.Button;
>       case vtkCommand::MoveEvent3D:
>         return Data.Move == rh.Data.Move;
>     }
>     return false;
>   }
>
>   bool GetDevice(vtkEventDataDevice &val)
>   {
>     switch (Type)
>     {
>       case vtkCommand::ButtonEvent3D:
>         val = Data.Button.Device;
>         return true;
>       case vtkCommand::MoveEvent3D:
>         val = Data.Move.Device;
>         return true;
>     }
>     return false;
>   }
>
>   bool GetWorldPosition(double *&pos)
>   {
>     switch (Type)
>     {
>       case vtkCommand::ButtonEvent3D:
>         pos = Data.Button.WorldPosition;
>         return true;
>       case vtkCommand::MoveEvent3D:
>         pos = Data.Move.WorldPosition;
>         return true;
>     }
>     return false;
>   }
>
>   bool GetWorldOrientation(double *&val)
>   {
>     switch (Type)
>     {
>       case vtkCommand::ButtonEvent3D:
>         val = Data.Button.WorldOrientation;
>         return true;
>       case vtkCommand::MoveEvent3D:
>         val = Data.Move.WorldOrientation;
>         return true;
>     }
>     return false;
>   }
> };
>
>
>
> --
> Ken Martin PhD
> Distinguished Engineer
> Kitware Inc.
> 28 Corporate Drive
> Clifton Park NY 12065
>
> This communication, including all attachments, contains confidential and
> legally privileged information, and it is intended only for the use of the
> addressee.  Access to this email by anyone else is unauthorized. If you are
> not the intended recipient, any disclosure, copying, distribution or any
> action taken in reliance on it is prohibited and may be unlawful. If you
> received this communication in error please notify us immediately and
> destroy the original message.  Thank you.
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://public.kitware.com/pipermail/vtk-developers/attachments/20170710/034a5919/attachment.html>


More information about the vtk-developers mailing list