Mercurial > projects > mde
comparison mde/input/Input.d @ 34:6b4116e6355c
Work on the Gui: some of the framework for drag & drop. Also made Window an IWidget.
Implemented getWidget(x,y) to find the widget under this location for IWidgets (but not Gui).
Made Window an IWidget and made it work a little more similarly to widgets.
Implemented callbacks on the Gui for mouse events (enabling drag & drop, etc.).
committer: Diggory Hardy <diggory.hardy@gmail.com>
author | Diggory Hardy <diggory.hardy@gmail.com> |
---|---|
date | Fri, 02 May 2008 16:03:52 +0100 |
parents | 316b0230a849 |
children | 052df9b2fe07 |
comparison
equal
deleted
inserted
replaced
33:6886402c1545 | 34:6b4116e6355c |
---|---|
28 import derelict.sdl.types; // only SDL_PRESSED | 28 import derelict.sdl.types; // only SDL_PRESSED |
29 import derelict.sdl.joystick; // SDL_HAT_* | 29 import derelict.sdl.joystick; // SDL_HAT_* |
30 | 30 |
31 import tango.util.log.Log : Log, Logger; | 31 import tango.util.log.Log : Log, Logger; |
32 | 32 |
33 /// Class encapsulating all input functionality. | 33 /** Class encapsulating all input functionality. |
34 * | |
35 * The following methods are provided for Gui mouse input: | |
36 * --- | |
37 * void getMouseScreenPos (out uint x, out uint y); | |
38 * void addMouseClickCallback (MouseClickCallback dg); | |
39 * void addMouseMotionCallback (MouseMotionCallback dg); | |
40 * --- | |
41 * | |
42 * The following methods are provided for mouse (and joystick ball) relative motion input: | |
43 * --- | |
44 * void getRelMotion (inputID id, out real x = 0.0, out real y = 0.0); | |
45 * void addRelMotionCallback (inputID id, RelMotionCallback dg); | |
46 * --- | |
47 * | |
48 * The following methods are provided for joystick axis input: | |
49 * --- | |
50 * short getAxis (inputID id); | |
51 * real getAxis1 (inputID id); | |
52 * void addAxisCallback (inputID id, AxisCallback dg); | |
53 * --- | |
54 * | |
55 * The following methods are provided for keyboard, joystick and mouse button input: | |
56 * --- | |
57 * bool getButton (inputID id); | |
58 * void addButtonCallback (inputID id, ButtonCallback dg) | |
59 * --- | |
60 * | |
61 * The following methods are provided for setup & posting events: | |
62 * --- | |
63 * bool opCall (ref SDL_Event event); | |
64 * void frameReset (); | |
65 * void loadConfig (char[] profile = "Default"); | |
66 * --- | |
67 ***************************************************/ | |
68 // FIXME: remove getMouseScreenPos (no use)? | |
69 // FIXME: add an Axis1Callback similar to getAxis1? Or remove getAxis1 and provide a conversion | |
70 // function? | |
34 class Input | 71 class Input |
35 { | 72 { |
36 /// Typedef for all indexes (type is uint). | 73 /// Typedef for all indexes (type is uint). |
37 typedef uint inputID; | 74 typedef uint inputID; |
38 alias void delegate(inputID, bool) ButtonCallback; | 75 alias void delegate(inputID, bool) ButtonCallback; |
39 alias void delegate(inputID, short) AxisCallback; | 76 alias void delegate(inputID, short) AxisCallback; |
40 alias void delegate(inputID, real,real) RelMotionCallback; | 77 alias void delegate(inputID, real,real) RelMotionCallback; |
41 alias void delegate(ushort, ushort, ubyte, bool) MouseClickCallback; | 78 alias void delegate(ushort, ushort, ubyte, bool) MouseClickCallback; |
79 alias void delegate(ushort, ushort) MouseMotionCallback; | |
42 | 80 |
43 /** Get key status at this ID. | 81 /** Get key status at this ID. |
44 * | 82 * |
45 * Returns: value (true = down, false = up) or false if no value at this ID. */ | 83 * Returns: value (true = down, false = up) or false if no value at this ID. */ |
46 bool getButton (inputID id) { | 84 bool getButton (inputID id) { |
71 * Future: Converts to a real via sensitivity settings (defaults may be set and overriden per item). | 109 * Future: Converts to a real via sensitivity settings (defaults may be set and overriden per item). |
72 * | 110 * |
73 * To avoid confusion over the ID here, the idea is for the input-layer upward to support | 111 * To avoid confusion over the ID here, the idea is for the input-layer upward to support |
74 * multiple mice, in case future platforms do. | 112 * multiple mice, in case future platforms do. |
75 * Also joystick balls (supported by SDL) can be used in the same way as a mouse for relative | 113 * Also joystick balls (supported by SDL) can be used in the same way as a mouse for relative |
76 * positions. | 114 * positions. */ |
77 */ | |
78 void getRelMotion (inputID id, out real x = 0.0, out real y = 0.0) { | 115 void getRelMotion (inputID id, out real x = 0.0, out real y = 0.0) { |
79 RelPair* rp = id in relMotion; | 116 RelPair* rp = id in relMotion; |
80 if (rp) { | 117 if (rp) { |
81 x = rp.x; y = rp.y; | 118 x = rp.x; y = rp.y; |
82 } | 119 } |
83 } | 120 } |
84 /** Get mouse pointer position in screen coordinates. | 121 /** Get mouse pointer position in screen coordinates. |
85 * | 122 * |
86 * Window managers only support one mouse, so there will only be one screen coordinate. | 123 * Window managers only support one mouse, so there will only be one screen coordinate. |
87 * Unlike nearly everything else, this is not configurable. | 124 * Unlike nearly everything else, this is not configurable. |
88 */ | 125 * |
126 * Also see addMouseMotionCallback. */ | |
89 void getMouseScreenPos (out uint x, out uint y) { | 127 void getMouseScreenPos (out uint x, out uint y) { |
90 x = mouse_x; y = mouse_y; | 128 x = mouse_x; y = mouse_y; |
91 } | 129 } |
92 // /// Is this modifier on? | 130 // /// Is this modifier on? |
93 //bool modifierStatus (inputID id); | 131 //bool modifierStatus (inputID id); |
94 | 132 |
95 /** Adds a callback delegate for key events (both DOWN and UP) with this ID. | 133 /** Adds a callback delegate for key events (both DOWN and UP) with this ID. |
96 * | 134 * |
97 * Delegate receives event status. | 135 * Delegate receives event status. */ |
98 */ | |
99 void addButtonCallback (inputID id, ButtonCallback dg) { | 136 void addButtonCallback (inputID id, ButtonCallback dg) { |
100 buttonCallbacks[id] ~= dg; | 137 buttonCallbacks[id] ~= dg; |
101 } | 138 } |
102 | 139 |
103 /** Adds a callback delegate for axis events with this ID. | 140 /** Adds a callback delegate for axis events with this ID. |
104 * | 141 * |
105 * Delegate receives event status (as per what getAxis returns). | 142 * Delegate receives event status (as per what getAxis returns). */ |
106 */ | |
107 void addAxisCallback (inputID id, AxisCallback dg) { | 143 void addAxisCallback (inputID id, AxisCallback dg) { |
108 axisCallbacks[id] ~= dg; | 144 axisCallbacks[id] ~= dg; |
109 } | 145 } |
110 | 146 |
111 /** Adds a callback delegate for mouse motion/joystick ball events with this ID. | 147 /** Adds a callback delegate for mouse motion/joystick ball events with this ID. |
113 * Delegate receives event status. As the name suggests, this is relative motion not screen | 149 * Delegate receives event status. As the name suggests, this is relative motion not screen |
114 * position, with sensitivity adjustments applied. | 150 * position, with sensitivity adjustments applied. |
115 * | 151 * |
116 * (A separate callback for mouse screen position changes is not | 152 * (A separate callback for mouse screen position changes is not |
117 * necessary since this will be triggered by the same event - use mouseScreenPos from within the | 153 * necessary since this will be triggered by the same event - use mouseScreenPos from within the |
118 * function to get new screen coordinates.) | 154 * function to get new screen coordinates.) */ |
119 */ | |
120 void addRelMotionCallback (inputID id, RelMotionCallback dg) { | 155 void addRelMotionCallback (inputID id, RelMotionCallback dg) { |
121 relMotionCallbacks[id] ~= dg; | 156 relMotionCallbacks[id] ~= dg; |
122 } | 157 } |
123 | 158 |
124 /** Adds a callback delegate for all mouse clicks & releases. | 159 /** Adds a callback delegate for all mouse clicks & releases. |
127 * 2 for middle, 3 for right, 4/5 for wheel, etc.), and whether the button was pressed or | 162 * 2 for middle, 3 for right, 4/5 for wheel, etc.), and whether the button was pressed or |
128 * released (true if pressed). | 163 * released (true if pressed). |
129 * | 164 * |
130 * The point of this over a standard button callback is firstly to avoid mouse configuration for | 165 * The point of this over a standard button callback is firstly to avoid mouse configuration for |
131 * the GUI, and secondly to give the pointer position at the time of the event, not the time the | 166 * the GUI, and secondly to give the pointer position at the time of the event, not the time the |
132 * callback gets called. | 167 * callback gets called. */ |
133 */ | |
134 void addMouseClickCallback (MouseClickCallback dg) { | 168 void addMouseClickCallback (MouseClickCallback dg) { |
135 mouseClickCallbacks ~= dg; | 169 mouseClickCallbacks ~= dg; |
136 } | 170 } |
171 | |
172 /** Adds a callback delegate for all mouse motion events. | |
173 * | |
174 * Really just for graphical user interfaces. Use addRelMotionCallback for relative motion (for | |
175 * manipulating 3D views, etc.). */ | |
176 void addMouseMotionCallback (MouseMotionCallback dg) { | |
177 mouseMotionCallbacks ~= dg; | |
178 } | |
137 | 179 |
138 /** Feed an SDL_Event struct (only uses if it's a key, mouse or joystick event). | 180 /** Feed an SDL_Event struct (only uses if it's a key, mouse or joystick event). |
139 * | 181 * |
140 * Other types of event functions may be added. Returns true if the event was used, false if not | 182 * Other types of event functions may be added. Returns true if the event was used, false if not |
141 * or no config was available. Hmm... doesn't seem very useful, but has practically no cost. | 183 * or no config was available. Hmm... doesn't seem very useful, but has practically no cost. |
142 * | 184 * |
143 * May throw InputClassExceptions (on configuration errors). Catching the exception and continuing should | 185 * May throw InputClassExceptions (on configuration errors). Catching the exception and continuing should |
144 * be fine. | 186 * be fine. */ |
145 */ | |
146 bool opCall (ref SDL_Event event) { | 187 bool opCall (ref SDL_Event event) { |
147 /* Non-config events. | 188 /* Non-config events. |
148 * | 189 * |
149 * Mouse events don't need config for the GUI. Handle them first so that if no config exists | 190 * Mouse events don't need config for the GUI. Handle them first so that if no config exists |
150 * some functionality at least is retained. | 191 * some functionality at least is retained. |
161 break; | 202 break; |
162 | 203 |
163 case SDL_MOUSEMOTION: | 204 case SDL_MOUSEMOTION: |
164 mouse_x = event.motion.x - 1; | 205 mouse_x = event.motion.x - 1; |
165 mouse_y = event.motion.y - 1; | 206 mouse_y = event.motion.y - 1; |
207 | |
208 foreach (dg; mouseMotionCallbacks) | |
209 dg (event.motion.x - 1, event.motion.y - 1); | |
166 break; | 210 break; |
167 | 211 |
168 default: | 212 default: |
169 } | 213 } |
170 | 214 |
171 /* No config available, so don't try to access it and segfault. | 215 /* No config available, so don't try to access it and segfault. |
172 * Don't log a message because this function is called per-event (i.e. frequently). | 216 * Don't log a message because this function is called per-event (i.e. frequently). |
173 * A message should already have been logged by loadConfig anyway. | 217 * A message should already have been logged by loadConfig anyway. */ |
174 */ | |
175 if (!config) return false; | 218 if (!config) return false; |
176 | 219 |
177 switch (event.type) { | 220 switch (event.type) { |
178 // Keyboard events: | 221 // Keyboard events: |
179 case SDL_KEYDOWN: | 222 case SDL_KEYDOWN: |
284 } | 327 } |
285 | 328 |
286 /** Resets relative movement of mice / joystick balls to zero. | 329 /** Resets relative movement of mice / joystick balls to zero. |
287 * | 330 * |
288 * Should be called once-per-frame if these are used, but must be called after their state has | 331 * Should be called once-per-frame if these are used, but must be called after their state has |
289 * been read (e.g. just before updating the input). | 332 * been read (e.g. just before updating the input). */ |
290 */ | |
291 void frameReset () { | 333 void frameReset () { |
292 foreach (rp; relMotion) { | 334 foreach (rp; relMotion) { |
293 rp.x = rp.y = 0.0; | 335 rp.x = rp.y = 0.0; |
294 } | 336 } |
295 } | 337 } |
296 | 338 |
297 /** Loads all configs, activating the requested id. | 339 /** Loads all configs, activating the requested id. |
298 * | 340 * |
299 * Throws: ConfigLoadException if unable to load any configs or the requested config id wasn't | 341 * Throws: ConfigLoadException if unable to load any configs or the requested config id wasn't |
300 * found. | 342 * found. */ |
301 */ | |
302 void loadConfig (char[] profile = "Default") { | 343 void loadConfig (char[] profile = "Default") { |
303 Config.load("input"); // FIXME: filename | 344 Config.load("input"); // FIXME: filename |
304 Config* c_p = profile in Config.configs; | 345 Config* c_p = profile in Config.configs; |
305 if (c_p) config = *c_p; | 346 if (c_p) config = *c_p; |
306 else { | 347 else { |
340 // FIXME: currently no means of removal | 381 // FIXME: currently no means of removal |
341 ButtonCallback[][inputID] buttonCallbacks; | 382 ButtonCallback[][inputID] buttonCallbacks; |
342 AxisCallback[][inputID] axisCallbacks; | 383 AxisCallback[][inputID] axisCallbacks; |
343 RelMotionCallback[][inputID] relMotionCallbacks; | 384 RelMotionCallback[][inputID] relMotionCallbacks; |
344 MouseClickCallback[] mouseClickCallbacks; | 385 MouseClickCallback[] mouseClickCallbacks; |
386 MouseMotionCallback[] mouseMotionCallbacks; | |
345 | 387 |
346 //BEGIN Event stream functionality | 388 //BEGIN Event stream functionality |
347 /* This section contains functions called on an event, which may modify the event (adjuster | 389 /* This section contains functions called on an event, which may modify the event (adjuster |
348 * functions), and finally output to one (or more) of the state tables (the event stream). | 390 * functions), and finally output to one (or more) of the state tables (the event stream). |
349 * | 391 * |
350 * Adjuster and other event functions should have a format to fit the ES_X_Func types, for X is B | 392 * Adjuster and other event functions should have a format to fit the ES_X_Func types, for X is |
351 * (button event), A (axis event) or M (mouse relative motion event or joystick ball event). | 393 * B (button event), A (axis event) or M (mouse relative motion event or joystick ball event). |
352 * Adjusters should call one of the xEvent() functions with their output and the remainder of | 394 * Adjusters should call one of the xEvent() functions with their output and the remainder of |
353 * the readOutQueue. | 395 * the readOutQueue. |
354 * | 396 * |
355 * To control which adjusters get called and pass parameters, a stack of sorts is used: outQueue. | 397 * To control which adjusters get called and pass parameters, a stack of sorts is used: |
356 */ | 398 * outQueue. */ |
357 //BEGIN ES Definitions | 399 //BEGIN ES Definitions |
358 /* Note: We really want an array, not a stack. We cannot edit the lists, so we can either | 400 /* Note: We really want an array, not a stack. We cannot edit the lists, so we can either |
359 * copy to a stack or just iterate through it as an array. | 401 * copy to a stack or just iterate through it as an array. */ |
360 */ | |
361 alias Config.outQueue outQueue; | 402 alias Config.outQueue outQueue; |
362 struct readOutQueue { // A convenient structure for reading an outQueue item by item. | 403 struct readOutQueue { // A convenient structure for reading an outQueue item by item. |
363 private Config.outQueue _q; // the queue, stored by reference to the original | 404 private Config.outQueue _q; // the queue, stored by reference to the original |
364 private uint p = 0; // current read position (start at beginning) | 405 private uint p = 0; // current read position (start at beginning) |
365 | 406 |
387 alias void function (Input, short, readOutQueue) ES_A_Func; | 428 alias void function (Input, short, readOutQueue) ES_A_Func; |
388 alias void function (Input, short, short, readOutQueue) ES_M_Func; | 429 alias void function (Input, short, short, readOutQueue) ES_M_Func; |
389 | 430 |
390 /* These are the codes allowing the config to specify event functions. | 431 /* These are the codes allowing the config to specify event functions. |
391 * | 432 * |
392 * They are organised as defined in doc/input_ID_assignments. | 433 * They are organised as defined in doc/input_ID_assignments. */ |
393 */ | |
394 enum ES_B : uint { | 434 enum ES_B : uint { |
395 OUT = 0x1000u, | 435 OUT = 0x1000u, |
396 } | 436 } |
397 enum ES_A : uint { | 437 enum ES_A : uint { |
398 OUT = 0x1000u, | 438 OUT = 0x1000u, |
486 * Events of all types. | 526 * Events of all types. |
487 * Callbacks of all types. | 527 * Callbacks of all types. |
488 * Status set from events for all types (button,axis,relMotion). | 528 * Status set from events for all types (button,axis,relMotion). |
489 * | 529 * |
490 * It relies on config loaded from a file (dependant on where input bindings are loaded from; | 530 * It relies on config loaded from a file (dependant on where input bindings are loaded from; |
491 * currently conf/input.mtt). | 531 * currently conf/input.mtt). */ |
492 */ | |
493 debug (mdeUnitTest) unittest { | 532 debug (mdeUnitTest) unittest { |
494 Input ut = new Input(); | 533 Input ut = new Input(); |
495 ut.loadConfig ("UnitTest"); | 534 ut.loadConfig ("UnitTest"); |
496 | 535 |
497 int[6] counters; // counters for callbacks | 536 int[6] counters; // counters for callbacks |