]> icculus.org git repositories - taylor/freespace2.git/blob - src/io/mouse.cpp
use SDL_arraysize() instead of sizeof() where appropriate
[taylor/freespace2.git] / src / io / mouse.cpp
1 /*
2  * Copyright (C) Volition, Inc. 1999.  All rights reserved.
3  *
4  * All source code herein is the property of Volition, Inc. You may not sell 
5  * or otherwise commercially exploit the source or things you created based on
6  * the source.
7  */
8
9 /*
10  * $Logfile: /Freespace2/code/Io/Mouse.cpp $
11  * $Revision$
12  * $Date$
13  * $Author$
14  *
15  * Routines to read the mouse.
16  *
17  * $Log$
18  * Revision 1.7  2003/05/25 02:30:42  taylor
19  * Freespace 1 support
20  *
21  * Revision 1.6  2002/07/13 06:46:48  theoddone33
22  * Warning cleanups
23  *
24  * Revision 1.5  2002/06/09 04:41:22  relnev
25  * added copyright header
26  *
27  * Revision 1.4  2002/06/02 04:26:34  relnev
28  * warning cleanup
29  *
30  * Revision 1.3  2002/05/29 06:25:13  theoddone33
31  * Keyboard input, mouse tracking now work
32  *
33  * Revision 1.2  2002/05/07 03:16:46  theoddone33
34  * The Great Newline Fix
35  *
36  * Revision 1.1.1.1  2002/05/03 03:28:09  root
37  * Initial import.
38  *
39  * 
40  * 4     7/15/99 9:20a Andsager
41  * FS2_DEMO initial checkin
42  * 
43  * 3     6/02/99 6:18p Dave
44  * Fixed TNT lockup problems! Wheeeee!
45  * 
46  * 2     10/07/98 10:53a Dave
47  * Initial checkin.
48  * 
49  * 1     10/07/98 10:49a Dave
50  * 
51  * 29    6/10/98 2:52p Hoffoss
52  * Made mouse code use DI by default, but fall back on normal code if that
53  * fails.
54  * 
55  * 28    5/24/98 1:35p Hoffoss
56  * Fixed bug where  mouse cursor is always recentering with a
57  * mouse_flush() call in debug version.
58  * 
59  * 27    5/22/98 4:50p Hoffoss
60  * Trying to fix mouse acceleration problem..
61  * 
62  * 26    5/21/98 12:26p Lawrance
63  * Fixed mouse jerk at mission start while in debug build only.
64  * 
65  * 25    5/15/98 2:41p Hoffoss
66  * Made mouse default to off (for flying ship) and fixed some new pilot
67  * init bugs.
68  * 
69  * 24    5/08/98 4:13p Hoffoss
70  * Fixed problem with mouse pointer centering causing lost keypresses.
71  * 
72  * 23    5/07/98 6:58p Hoffoss
73  * Made changes to mouse code to fix a number of problems.
74  * 
75  * 22    5/05/98 8:38p Hoffoss
76  * Added sensitivity adjustment to options menu and made it save to pilot
77  * file.
78  * 
79  * 21    5/05/98 1:03p Hoffoss
80  * Fixed initialization bug.
81  * 
82  * 20    5/01/98 5:45p Hoffoss
83  * Made further improvements to the mouse code.
84  * 
85  * 19    5/01/98 3:35p Hoffoss
86  * Made changes to release version of mouse code.
87  * 
88  * 18    5/01/98 1:14p Hoffoss
89  * Changed mouse usage so directInput is only used for release version.
90  * 
91  * 17    4/30/98 5:40p Hoffoss
92  * Added mouse as a supported control to fly the ship.
93  * 
94  * 16    4/29/98 12:13a Lawrance
95  * Add function to check down count of mouse button without reseting the
96  * internal count.  Added hook to reset demo trailer timer when a button
97  * is pressed.
98  * 
99  * 15    4/02/98 5:26p John
100  * 
101  * 14    1/19/98 6:15p John
102  * Fixed all my Optimized Build compiler warnings
103  * 
104  * 13    12/04/97 3:47p John
105  * Made joystick move mouse cursor
106  * 
107  * 12    11/20/97 5:36p Dave
108  * Hooked in a bunch of main hall changes (including sound). Made it
109  * possible to reposition (rewind/ffwd) 
110  * sound buffer pointers. Fixed animation direction change framerate
111  * problem.
112  * 
113  * 11    5/12/97 11:41a John
114  * Added range checking to mouse position
115  * 
116  * 10    4/22/97 5:55p Lawrance
117  * let mouse.cpp decide if mouse has moved
118  * 
119  * 9     4/22/97 12:29p John
120  * Changed mouse code so that you have to call mouse_init for the mouse
121  * stuff to work.
122  * 
123  * 8     4/22/97 10:56a John
124  * fixed some resource leaks.
125  * 
126  * 7     3/26/97 10:52a Lawrance
127  * mouse always on in menus, disappears in gameplay after 1 second
128  * 
129  * 6     3/11/97 1:37p Lawrance
130  * added mouse_up_count(), changed mouse_mark() to mouse_mark_button() &
131  * mouse_mark_move()
132  * 
133  * 5     12/09/96 1:29p Lawrance
134  * adding 3 button support
135  * 
136  * 4     12/03/96 4:19p John
137  * Added some code so that holding down the mouse buttons between menus
138  * doesn't select the next menu.
139  *
140  * $NoKeywords: $
141  */
142
143
144 #include "mouse.h"
145 #include "2d.h"
146 #include "osapi.h"
147
148
149 static int mouse_inited = 0;
150
151 static int mouse_flags;
152 static int mouse_left_pressed = 0;
153 static int mouse_right_pressed = 0;
154 static int mouse_middle_pressed = 0;
155 static int mouse_left_up = 0;
156 static int mouse_right_up = 0;
157 static int mouse_middle_up = 0;
158
159 static int Mouse_x;
160 static int Mouse_y;
161 // total mouse delta motion each game frame
162 static int Mouse_dx = 0;
163 static int Mouse_dy = 0;
164 static int Mouse_dz = 0;
165 // accumulation of mouse delta motion during each game frame
166 static int Mouse_dx_inc = 0;
167 static int Mouse_dy_inc = 0;
168
169 int Mouse_sensitivity = 4;
170 int Use_mouse_to_fly = 0;
171 int Mouse_hidden = 0;
172 int Keep_mouse_centered = 0;;
173
174 void mouse_force_pos(int x, int y);
175
176
177 int mouse_is_visible()
178 {
179         return !Mouse_hidden;
180 }
181
182 void mouse_close()
183 {
184         if (!mouse_inited)
185                 return;
186
187         mouse_inited = 0;
188 }
189
190 void mouse_init()
191 {
192         // Initialize queue
193         if (mouse_inited)
194                 return;
195
196         mouse_inited = 1;
197
198         mouse_flags = 0;
199         Mouse_x = gr_screen.max_w / 2;
200         Mouse_y = gr_screen.max_h / 2;
201
202         atexit( mouse_close );
203 }
204
205
206 // ----------------------------------------------------------------------------
207 // mouse_mark_button() is called asynchronously by the OS when a mouse button
208 // goes up or down.  The mouse button that is affected is passed via the 
209 // flags parameter.  
210 //
211 // parameters:   flags ==> mouse button pressed/released
212 //               set   ==> 1 - button is pressed
213 //                         0 - button is released
214
215 void mouse_mark_button( uint btn, int set)
216 {
217         uint flags = 0;
218
219         if ( !mouse_inited )
220                 return;
221
222         switch (btn) {
223                 case SDL_BUTTON_LEFT:
224                         flags |= MOUSE_LEFT_BUTTON;
225                         break;
226
227                 case SDL_BUTTON_RIGHT:
228                         flags |= MOUSE_RIGHT_BUTTON;
229                         break;
230
231                 case SDL_BUTTON_MIDDLE:
232                         flags |= MOUSE_MIDDLE_BUTTON;
233                         break;
234
235                 default:
236                         return;
237         }
238
239         if ( !(mouse_flags & MOUSE_LEFT_BUTTON) )       {
240
241                 if ( (flags & MOUSE_LEFT_BUTTON) && (set == 1) ) {
242                         mouse_left_pressed++;
243                 }
244         }
245         else {
246                 if ( (flags & MOUSE_LEFT_BUTTON) && (set == 0) ){
247                         mouse_left_up++;
248                 }
249         }
250
251         if ( !(mouse_flags & MOUSE_RIGHT_BUTTON) )      {
252
253                 if ( (flags & MOUSE_RIGHT_BUTTON) && (set == 1) ){
254                         mouse_right_pressed++;
255                 }
256         }
257         else {
258                 if ( (flags & MOUSE_RIGHT_BUTTON) && (set == 0) ){
259                         mouse_right_up++;
260                 }
261         }
262
263         if ( !(mouse_flags & MOUSE_MIDDLE_BUTTON) )     {
264
265                 if ( (flags & MOUSE_MIDDLE_BUTTON) && (set == 1) ){
266                         mouse_middle_pressed++;
267                 }
268         }
269         else {
270                 if ( (flags & MOUSE_MIDDLE_BUTTON) && (set == 0) ){
271                         mouse_middle_up++;
272                 }
273         }
274
275         if ( set ){
276                 mouse_flags |= flags;
277         } else {
278                 mouse_flags &= ~flags;
279         }
280 }
281
282 void mouse_flush()
283 {
284         if (!mouse_inited)
285                 return;
286
287         mouse_eval_deltas();
288         Mouse_dx = Mouse_dy = Mouse_dz = 0;
289         Mouse_dx_inc = Mouse_dy_inc = 0;
290         mouse_left_pressed = 0;
291         mouse_right_pressed = 0;
292         mouse_middle_pressed = 0;
293         mouse_flags = 0;
294 }
295
296 int mouse_down_count(int n, int reset_count)
297 {
298         int tmp = 0;
299
300         if ( !mouse_inited )
301                 return 0;
302
303         if ( (n < LOWEST_MOUSE_BUTTON) || (n > HIGHEST_MOUSE_BUTTON) )
304                 return 0;
305
306         switch (n) {
307                 case MOUSE_LEFT_BUTTON:
308                         tmp = mouse_left_pressed;
309                         if ( reset_count ) {
310                                 mouse_left_pressed = 0;
311                         }
312                         break;
313
314                 case MOUSE_RIGHT_BUTTON:
315                         tmp = mouse_right_pressed;
316                         if ( reset_count ) {
317                                 mouse_right_pressed = 0;
318                         }
319                         break;
320
321                 case MOUSE_MIDDLE_BUTTON:
322                         tmp = mouse_middle_pressed;
323                         if ( reset_count ) {
324                                 mouse_middle_pressed = 0;
325                         }
326                         break;
327         } // end switch
328
329         return tmp;
330 }
331
332 // mouse_up_count() returns the number of times button n has gone from down to up
333 // since the last call
334 //
335 // parameters:  n - button of mouse (see #define's in mouse.h)
336 //
337 int mouse_up_count(int n)
338 {
339         int tmp = 0;
340
341         if ( !mouse_inited )
342                 return 0;
343
344         if ( (n < LOWEST_MOUSE_BUTTON) || (n > HIGHEST_MOUSE_BUTTON) )
345                 return 0;
346
347         switch (n) {
348                 case MOUSE_LEFT_BUTTON:
349                         tmp = mouse_left_up;
350                         mouse_left_up = 0;
351                         break;
352
353                 case MOUSE_RIGHT_BUTTON:
354                         tmp = mouse_right_up;
355                         mouse_right_up = 0;
356                         break;
357
358                 case MOUSE_MIDDLE_BUTTON:
359                         tmp = mouse_middle_up;
360                         mouse_middle_up = 0;
361                         break;
362
363                 default:
364                         SDL_assert(0);  // can't happen
365                         break;
366         } // end switch
367
368         return tmp;
369 }
370
371 // returns 1 if mouse button btn is down, 0 otherwise
372
373 int mouse_down(int btn)
374 {
375         int tmp;
376
377         if ( !mouse_inited )
378                 return 0;
379
380         if ( (btn < LOWEST_MOUSE_BUTTON) || (btn > HIGHEST_MOUSE_BUTTON) )
381                 return 0;
382
383         if ( mouse_flags & btn )
384                 tmp = 1;
385         else
386                 tmp = 0;
387
388         return tmp;
389 }
390
391 // returns the fraction of time btn has been down since last call 
392 // (currently returns 1 if buttons is down, 0 otherwise)
393 //
394 float mouse_down_time(int btn)
395 {
396         float tmp;
397
398         if ( !mouse_inited )
399                 return 0.0f;
400
401         if ( (btn < LOWEST_MOUSE_BUTTON) || (btn > HIGHEST_MOUSE_BUTTON) )
402                 return 0.0f;
403
404         if ( mouse_flags & btn )
405                 tmp = 1.0f;
406         else
407                 tmp = 0.0f;
408
409         return tmp;
410 }
411
412 void mouse_get_delta(int *dx, int *dy, int *dz)
413 {
414         if (dx)
415                 *dx = Mouse_dx;
416         if (dy)
417                 *dy = Mouse_dy;
418         if (dz)
419                 *dz = Mouse_dz;
420 }
421
422 // Forces the actual windows cursor to be at (x,y).  This may be independent of our tracked (x,y) mouse pos.
423 void mouse_force_pos(int x, int y)
424 {
425         if (os_foreground()) {  // only mess with windows's mouse if we are in control of it
426                 SDL_WarpMouseInWindow(os_get_window(), x, y);
427         }
428 }
429
430 static bool Mouse_grabbed = false;
431 void mouse_eval_deltas()
432 {
433         Mouse_dx = Mouse_dx_inc;
434         Mouse_dy = Mouse_dy_inc;
435
436         Mouse_dx_inc = Mouse_dy_inc = 0;
437
438         // make sure mouse is bound to window if we're flying with it
439         if (Keep_mouse_centered && Mouse_hidden) {
440                 if ( !Mouse_grabbed ) {
441                         SDL_SetRelativeMouseMode(SDL_TRUE);
442                         SDL_SetWindowGrab(os_get_window(), SDL_TRUE);
443                         Mouse_grabbed = true;
444                 }
445         } else {
446                 if (Mouse_grabbed) {
447                         SDL_SetRelativeMouseMode(SDL_FALSE);
448                         SDL_SetWindowGrab(os_get_window(), SDL_FALSE);
449                         Mouse_grabbed = false;
450                 }
451         }
452 }
453
454 int mouse_get_pos(int *xpos, int *ypos)
455 {
456         if ( !mouse_inited ) {
457                 if (xpos) {
458                         *xpos = 0;
459                 }
460
461                 if (ypos) {
462                         *ypos = 0;
463                 }
464
465                 return 0;
466         }
467
468         if (xpos){
469                 *xpos = Mouse_x;
470         }
471
472         if (ypos){
473                 *ypos = Mouse_y;
474         }
475
476         return mouse_flags;
477 }
478
479 void mouse_get_real_pos(int *mx, int *my)
480 {
481         if (mx) {
482                 *mx = Mouse_x;
483         }
484
485         if (my) {
486                 *my = Mouse_y;
487         }
488 }
489
490 void mouse_set_pos(int xpos, int ypos)
491 {
492         if ((xpos != Mouse_x) || (ypos != Mouse_y)){
493                 mouse_force_pos(xpos, ypos);
494         }
495 }
496
497 void mouse_update_pos(int x, int y, int dx, int dy)
498 {
499         Mouse_x = x;
500         Mouse_y = y;
501
502         Mouse_dx_inc += dx;
503         Mouse_dy_inc += dy;
504 }