|
|
|
The Event-based ApproachAbstract class CcEditorShell demonstrates how an application containing a CcOpenglPresenter can respond to keyboard input using Dolphin Smalltalks event system. CcEditorShell makes use of two ST3D classes that simplify the process of mapping keystrokes to actions: CcKeyActionMap and CcKeyActionMapChain. A CcKeyActionMap allows keystrokes to be mapped to code blocks; e.g., it allows the developer to say "whenever the up arrow is pressed, evaluate this block". In CcEditorShell>>initKeyActionMaps, a CcKeyActionMap is instantiated and then initialized using CcKeyActionMap>>on:do:. The first argument to #on:do: is a symbol corresponding to a key on the keyboard (e.g., #A, #Up, #Down). These symbols can be prefixed with #shift, #ctrl, and #alt to respond to keystroke combinations like CTRL+A (#ctrlA). The second argument is a niladicBlock. This is the block that is to be evaluated when the keystroke occurs. CcKeyActionMapChain allows multiple CcKeyActionMaps to be associated with a single view and routes keyboard events generated in the user interface through this chain. Routing of a given event stops when its handled by one of the CcKeyActionMaps. Individual CcKeyActionMaps can also be disabled if necessary. This scheme allows multiple keyboard mappings to be defined and activated or deactivated based on the applications current mode. For example, the CoolPool sample application initializes its CcKeyActionMapChain with two CcKeyActionMaps. One is used to control the camera and the other is used to control the cue stick (see PgPoolGameShell>>initKeyActionMapChain). The cue mapping is always active. The camera mapping is active only when the application is in "normal view" mode. It is disabled when the application is in "overhead view" mode where no camera manipulation is required. In order to receive input events from the keyboard, the CcOpenglPresenter from which the events originate must be set into the CcKeyActionMapChain. By default, a keyboard event is processed immediately by the CcKeyActionMapChain as the event is received from the user interface. However, the CcKeyActionMapChain can be configured so that received input events are queued and processed as a batch when requested by the application (see CcKeyActionMapChain>>useInputQueue:). It is also possible to disable a CcKeyActionMapChain for situations where user input is not allowed. When using the event mechanism to obtain user input within a process executing a "tight" animation loop, it may be necessary to insert the line "Processor sleep: numberOfMilliseconds" (numberOfMilliseconds being 1 to 5) within the loop to avoid excessive latency between key presses and the execution of associated actions. In general, though, it is best to use DirectInput to read keyboard data in such situations (See CcAnimationExample and LmSimulatorShell).
The DirectInput-based ApproachThe second method of obtaining data from the keyboard or joystick is to use ST3Ds DirectInput support. DirectXs DirectInput subsystem provides services for instantiating keyboard and joystick objects and reading their state. Unlike the event-based approach where the application is notified when a key is pressed on the keyboard, the DirectInput approach makes the application responsible for polling the keyboard (or joystick) to obtain its current state (e.g., left arrow key is depressed). In CcAnimationExample1, the logic that reads the keyboard and joystick state is embedded within the animation loop so devices are polled once per frame. The key classes in the DirectInput subsystem are CcIDirectInput, CcDxiKeyboard and CcDxiJoystick. CcIDirectInput is a wrapper for the COM interface of a DirectInput subsystem. It provides services for creating instances of CcDxiKeyboard and CcDxiJoystick. Once created, a keyboard or joystick object can be interrogated to determine the current state of the device. For a keyboard, this amounts to asking whether or not a specific key is currently pressed. For a joystick, the state includes a number of variables such as the current x, y and z axis position of the joystick and what, if any, joystick buttons are currently pressed. Examples of DirectInput device initialization and polling can be found in CcAnimationExample>>onViewOpened and CcAnimationExample>>advanceStateBy:. |