]> git.mxchange.org Git - flightgear.git/blob - src/Input/input.hxx
new FSF address
[flightgear.git] / src / Input / input.hxx
1 // input.hxx -- handle user input from various sources.
2 //
3 // Written by David Megginson, started May 2001.
4 //
5 // Copyright (C) 2001 David Megginson, david@megginson.com
6 //
7 // This program is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU General Public License as
9 // published by the Free Software Foundation; either version 2 of the
10 // License, or (at your option) any later version.
11 //
12 // This program is distributed in the hope that it will be useful, but
13 // WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 // General Public License for more details.
16 //
17 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, write to the Free Software
19 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
20 //
21 // $Id$
22
23
24 #ifndef _INPUT_HXX
25 #define _INPUT_HXX
26
27 #ifndef __cplusplus                                                          
28 # error This library requires C++
29 #endif
30
31 #include <plib/js.h>
32 #include <plib/ul.h>
33
34 #include <simgear/compiler.h>
35
36 #include <simgear/misc/sg_path.hxx>
37 #include <simgear/structure/subsystem_mgr.hxx>
38 #include <simgear/structure/commands.hxx>
39 #include <simgear/props/condition.hxx>
40 #include <simgear/props/props.hxx>
41
42 #include <Main/fg_os.hxx>
43 #include <Main/fg_props.hxx>
44 #include <Main/globals.hxx>
45
46 #include <map>
47 #include <vector>
48
49 SG_USING_STD(map);
50 SG_USING_STD(vector);
51
52
53 \f
54
55 #if defined( UL_WIN32 )
56 #define TGT_PLATFORM    "windows"
57 #elif defined ( UL_MAC_OSX )
58 #define TGT_PLATFORM    "mac"
59 #else
60 #define TGT_PLATFORM    "unix"
61 #endif
62
63
64 \f
65 ////////////////////////////////////////////////////////////////////////
66 // General binding support.
67 ////////////////////////////////////////////////////////////////////////
68
69
70 /**
71  * An input binding of some sort.
72  *
73  * <p>This class represents a binding that can be assigned to a
74  * keyboard key, a joystick button or axis, or even a panel
75  * instrument.</p>
76  */
77 class FGBinding : public SGConditional
78 {
79 public:
80
81   /**
82    * Default constructor.
83    */
84   FGBinding ();
85
86
87   /**
88    * Convenience constructor.
89    *
90    * @param node The binding will be built from this node.
91    */
92   FGBinding (const SGPropertyNode * node);
93
94
95   /**
96    * Destructor.
97    */
98   virtual ~FGBinding ();
99
100
101   /**
102    * Get the command name.
103    *
104    * @return The string name of the command for this binding.
105    */
106   virtual const string &getCommandName () const { return _command_name; }
107
108
109   /**
110    * Get the command itself.
111    *
112    * @return The command associated with this binding, or 0 if none
113    * is present.
114    */
115   virtual SGCommandMgr::command_t getCommand () const { return _command; }
116
117
118   /**
119    * Get the argument that will be passed to the command.
120    *
121    * @return A property node that will be passed to the command as its
122    * argument, or 0 if none was supplied.
123    */
124   virtual const SGPropertyNode * getArg () { return _arg; }
125   
126
127   /**
128    * Read a binding from a property node.
129    *
130    * @param node The property node containing the binding.
131    */
132   virtual void read (const SGPropertyNode * node);
133
134
135   /**
136    * Fire a binding.
137    */
138   virtual void fire () const;
139
140
141   /**
142    * Fire a binding with a scaled movement (rather than absolute position).
143    */
144   virtual void fire (double offset, double max) const;
145
146
147   /**
148    * Fire a binding with a setting (i.e. joystick axis).
149    *
150    * A double 'setting' property will be added to the arguments.
151    *
152    * @param setting The input setting, usually between -1.0 and 1.0.
153    */
154   virtual void fire (double setting) const;
155
156
157 private:
158                                 // just to be safe.
159   FGBinding (const FGBinding &binding);
160
161   string _command_name;
162   mutable SGCommandMgr::command_t _command;
163   mutable SGPropertyNode_ptr _arg;
164   mutable SGPropertyNode_ptr _setting;
165 };
166
167
168 \f
169 ////////////////////////////////////////////////////////////////////////
170 // General input mapping support.
171 ////////////////////////////////////////////////////////////////////////
172
173
174 /**
175  * Generic input module.
176  *
177  * <p>This module is designed to handle input from multiple sources --
178  * keyboard, joystick, mouse, or even panel switches -- in a consistent
179  * way, and to allow users to rebind any of the actions at runtime.</p>
180  */
181 class FGInput : public SGSubsystem
182 {
183 public:
184   /**
185    * Default constructor.
186    */
187   FGInput ();
188
189   /**
190    * Destructor.
191    */
192   virtual ~FGInput();
193
194   //
195   // Implementation of SGSubsystem.
196   //
197   virtual void init ();
198   virtual void reinit ();
199   virtual void postinit ();
200   virtual void update (double dt);
201   virtual void suspend ();
202   virtual void resume ();
203   virtual bool is_suspended () const;
204
205
206   /**
207    * Control whether this is the default module to receive events.
208    *
209    * The first input module created will set itself as the default
210    * automatically.
211    *
212    * @param status true if this should be the default module for
213    * events, false otherwise.
214    */
215   virtual void makeDefault (bool status = true);
216
217
218   /**
219    * Handle a single keystroke.
220    *
221    * @param k The integer key code, see Main/fg_os.hxx
222    * @param modifiers Modifier keys pressed (bitfield).
223    * @param x The mouse x position at the time of keypress.
224    * @param y The mouse y position at the time of keypress.
225    */
226   virtual void doKey (int k, int modifiers, int x, int y);
227
228
229   /**
230    * Handle a mouse click event.
231    *
232    * @param button The mouse button selected.
233    * @param updown Button status.
234    * @param x The X position of the mouse event, in screen coordinates.
235    * @param y The Y position of the mouse event, in screen coordinates.
236    */
237   virtual void doMouseClick (int button, int updown, int x, int y);
238
239
240   /**
241    * Handle mouse motion.
242    *
243    * @param x The new mouse x position, in screen coordinates.
244    * @param y The new mouse y position, in screen coordinates.
245    */
246   virtual void doMouseMotion (int x, int y);
247
248
249 private:
250                                 // Constants
251   enum 
252   {
253     MAX_KEYS = 1024,
254
255   #ifdef WIN32
256     MAX_JOYSTICKS = 2,
257   #else
258     MAX_JOYSTICKS = 10,
259   #endif
260     MAX_JOYSTICK_AXES = _JS_MAX_AXES,
261     MAX_JOYSTICK_BUTTONS = 32,
262
263     MAX_MICE = 1,
264     MAX_MOUSE_BUTTONS = 8
265   };
266   struct mouse;
267   friend struct mouse;
268
269   typedef vector<FGBinding *> binding_list_t;
270
271   /**
272    * Settings for a key or button.
273    */
274   struct button {
275     button ();
276     virtual ~button ();
277     bool is_repeatable;
278     float interval_sec;
279     float last_dt;
280     int last_state;
281     binding_list_t bindings[KEYMOD_MAX];
282   };
283
284
285   /**
286    * Settings for a single joystick axis.
287    */
288   struct axis {
289     axis ();
290     virtual ~axis ();
291     float last_value;
292     float tolerance;
293     binding_list_t bindings[KEYMOD_MAX];
294     float low_threshold;
295     float high_threshold;
296     struct button low;
297     struct button high;
298     float interval_sec;
299     double last_dt;
300   };
301
302
303   /**
304    * Settings for a joystick.
305    */
306   struct joystick {
307     joystick ();
308     virtual ~joystick ();
309     int jsnum;
310     jsJoystick * js;
311     int naxes;
312     int nbuttons;
313     axis * axes;
314     button * buttons;
315   };
316
317
318   /**
319    * Settings for a mouse mode.
320    */
321   struct mouse_mode {
322     mouse_mode ();
323     virtual ~mouse_mode ();
324     int cursor;
325     bool constrained;
326     bool pass_through;
327     button * buttons;
328     binding_list_t x_bindings[KEYMOD_MAX];
329     binding_list_t y_bindings[KEYMOD_MAX];
330   };
331
332
333   /**
334    * Settings for a mouse.
335    */
336   struct mouse {
337     mouse ();
338     virtual ~mouse ();
339     int x;
340     int y;
341     SGPropertyNode * mode_node;
342     SGPropertyNode * mouse_button_nodes[MAX_MOUSE_BUTTONS];
343     int nModes;
344     int current_mode;
345     double timeout;
346     int save_x;
347     int save_y;
348     mouse_mode * modes;
349   };
350
351
352   /**
353    * Initialize key bindings.
354    */
355   void _init_keyboard ();
356
357
358   /**
359    * Initialize joystick bindings.
360    */
361   void _init_joystick ();
362
363
364   /**
365    * Scan directory recursively for "named joystick" configuration files,
366    * and read them into /input/joysticks/js-named[index]++.
367    */
368   void _scan_joystick_dir (SGPath *path, SGPropertyNode* node, int *index);
369
370
371   /**
372    * Initialize mouse bindings.
373    */
374   void _init_mouse ();
375
376
377   /**
378    * Initialize a single button.
379    */
380   inline void _init_button (const SGPropertyNode * node,
381                             button &b,
382                             const string name);
383
384   /**
385    * Initialize nasal parts that had to wait for the nasal to get
386    * functional.
387    */
388   void _postinit_joystick ();
389
390   /**
391    * Update the keyboard.
392    */
393   void _update_keyboard ();
394
395
396   /**
397    * Update the joystick.
398    */
399   void _update_joystick (double dt);
400
401
402   /**
403    * Update the mouse.
404    */
405   void _update_mouse (double dt);
406
407
408   /**
409    * Update a single button.
410    */
411   inline void _update_button (button &b, int modifiers, bool pressed,
412                               int x, int y);
413
414
415   /**
416    * Read bindings and modifiers.
417    */
418   void _read_bindings (const SGPropertyNode * node,
419                        binding_list_t * binding_list,
420                        int modifiers);
421
422   /**
423    * Look up the bindings for a key code.
424    */
425   const vector<FGBinding *> &_find_key_bindings (unsigned int k,
426                                                  int modifiers);
427
428   button _key_bindings[MAX_KEYS];
429   joystick _joystick_bindings[MAX_JOYSTICKS];
430   mouse _mouse_bindings[MAX_MICE];
431
432   /**
433    * Nasal module name/namespace.
434    */
435   char _module[32];
436 };
437
438 #endif // _INPUT_HXX