This document describes the mechanisms within OpenGLContext which allow for providing interactivity, both at the context and the scenegraph levels. This includes keyboard and mouse events, as well as timers and routes.
There are a number of user-level features which are implemented by
the "event model" within OpenGLContext:
each of these features will be discussed below.
The PyDispatcher package is the primary mechanism
used for event propagation within OpenGLContext 2.0. This module
allows you to register functions to be notified when "senders" send
particular signals. Each field of each node can generate signals
when setting and/or deleting field values for the node.
Similarly, each event manager registers functions with the dispatcher
which are to be called when a particular event is received, then sends
those events when the event is actually received.
Fields generate signals by default on set or delete.
Nothing generated during parser-mediated instantiation save for prototyped nodes
Normally not something you want to use directly, but it is what much of the rest of the interaction is built upon.
Built upon field watching, nodes register dependencies on node,
field pairs. If the node sends an update signal for that field,
then the cache object is invalidated, and the node regenerates its
cache data during the next rendering pass.
Two major variants:
The ROUTE is a simple unidirectional channel through which updates
to a particular field of a particular node are propagated along the arc
of the route to the destination node, field pair. This allows you
to create routing tables which tie together elements within a
scenegraph so that code does not need to explicitly chase down
dependent fields, it can simply allow route propagation to update the
The PROTO's IS mapping, which maps from a prototype node's fields to
fields on nodes within the prototype's internal scenegraph. This
is a bidirectional linkage, where changing the prototype's fields
updates the internal nodes, and updating the internal node updates the
prototype's corresponding field.
Most contexts derive from the EventHandlerMixIn class, which
provides a method addEventHandler, which allows for registering event
handlers for given event types (specified as strings). Individual
EventHandler objects are responsible for each event type, and are
responsible for processing events of their own type. Most
(currently all) EventHandler objects use the PyDispatcher module to
maintain the internal structures required to provide the registration
tables for the handler callbacks.
self.addEventHandler( "mousein", function = self.OnMouseIn )
self.addEventHandler( "mouseout", function = self.OnMouseOut )
self.addEventHandler( 'keyboard', name='<up>', state=1, modifiers=(0,0,0), function=self.forward )
self.addEventHandler( 'keypress', name='-', modifiers=(0,0,0), function=self.straighten)
self.addEventHandler( 'mousebutton', button=1, state = 1, modifiers=(0,0,0), function=self.startExamineMode)
self.addEventHandler( 'mousemove', buttons=(), modifiers=(0,0,0), function=self.RefreshTooltip)
Timer objects are also based on the same mechanism (with some
significant extra machinery).