naev 0.10.4
input.c
Go to the documentation of this file.
1/*
2 * See Licensing and Copyright notice in naev.h
3 */
10#include "naev.h"
13#include "input.h"
14
15#include "array.h"
16#include "board.h"
17#include "camera.h"
18#include "conf.h"
19#include "console.h"
20#include "escort.h"
21#include "gui.h"
22#include "hook.h"
23#include "info.h"
24#include "land.h"
25#include "log.h"
26#include "map.h"
27#include "map_overlay.h"
28#include "menu.h"
29#include "nstring.h"
30#include "pause.h"
31#include "pilot.h"
32#include "player.h"
33#include "toolkit.h"
34#include "weapon.h"
35#include "utf8.h"
36
37#define MOUSE_HIDE (3.)
39/* keybinding structure */
43typedef struct Keybind_ {
45 const char *name;
46 KeybindType type;
47 SDL_Keycode key;
48 SDL_Keymod mod;
49} Keybind;
50
51/* name of each keybinding */
52const char *keybind_info[][3] = {
53 /* Movement */
54 { "accel", N_("Accelerate"), N_("Makes your ship accelerate forward.") },
55 { "left", N_("Turn Left"), N_("Makes your ship turn left.") },
56 { "right", N_("Turn Right"), N_("Makes your ship turn right.") },
57 { "reverse", N_("Reverse"), N_("Makes your ship face the direction you're moving from. Useful for braking.") },
58 { "stealth", N_("Stealth"), N_("Tries to enter stealth mode.") },
59 /* Targeting */
60 { "target_next", N_("Target Next"), N_("Cycles through ship targets.") },
61 { "target_prev", N_("Target Previous"), N_("Cycles backwards through ship targets.") },
62 { "target_nearest", N_("Target Nearest"), N_("Targets the nearest non-disabled ship.") },
63 { "target_nextHostile", N_("Target Next Hostile"), N_("Cycles through hostile ship targets.") },
64 { "target_prevHostile", N_("Target Previous Hostile"), N_("Cycles backwards through hostile ship targets.") },
65 { "target_hostile", N_("Target Nearest Hostile"), N_("Targets the nearest hostile ship.") },
66 { "target_clear", N_("Clear Target"), N_("Clears the currently-targeted ship, spob or jump point.") },
67 /* Fighting */
68 { "primary", N_("Fire Primary Weapon"), N_("Fires primary weapons.") },
69 { "face", N_("Face Target"), N_("Faces the targeted ship if one is targeted, otherwise faces targeted spob or jump point.") },
70 { "board", N_("Board Target"), N_("Attempts to board the targeted ship.") },
71 /* Secondary Weapons */
72 { "secondary", N_("Fire Secondary Weapon"), N_("Fires secondary weapons.") },
73 { "weapset1", N_("Weapon Set 1"), N_("Activates weapon set 1.") },
74 { "weapset2", N_("Weapon Set 2"), N_("Activates weapon set 2.") },
75 { "weapset3", N_("Weapon Set 3"), N_("Activates weapon set 3.") },
76 { "weapset4", N_("Weapon Set 4"), N_("Activates weapon set 4.") },
77 { "weapset5", N_("Weapon Set 5"), N_("Activates weapon set 5.") },
78 { "weapset6", N_("Weapon Set 6"), N_("Activates weapon set 6.") },
79 { "weapset7", N_("Weapon Set 7"), N_("Activates weapon set 7.") },
80 { "weapset8", N_("Weapon Set 8"), N_("Activates weapon set 8.") },
81 { "weapset9", N_("Weapon Set 9"), N_("Activates weapon set 9.") },
82 { "weapset0", N_("Weapon Set 0"), N_("Activates weapon set 0.") },
83 /* Escorts */
84 { "e_targetNext", N_("Target Next Escort"), N_("Cycles through your escorts.") },
85 { "e_targetPrev", N_("Target Previous Escort"), N_("Cycles backwards through your escorts.") },
86 { "e_attack", N_("Escort Attack Command"), N_("Orders escorts to attack your target.") },
87 { "e_hold", N_("Escort Hold Command"), N_("Orders escorts to hold their formation.") },
88 { "e_return", N_("Escort Return Command"), N_("Orders escorts to return to your ship hangars.") },
89 { "e_clear", N_("Escort Clear Commands"), N_("Clears your escorts of commands.") },
90 /* Space Navigation */
91 { "autonav", N_("Autonavigation On"), N_("Initializes the autonavigation system.") },
92 { "target_spob", N_("Target Spob"), N_("Cycles through spob targets.") },
93 { "land", N_("Land"), N_("Attempts to land on the targeted spob or targets the nearest landable spob. Requests permission if necessary.") },
94 { "thyperspace", N_("Target Jumpgate"), N_("Cycles through jump points.") },
95 { "starmap", N_("Star Map"), N_("Opens the star map.") },
96 { "jump", N_("Initiate Jump"), N_("Attempts to jump via a jump point.") },
97 { "overlay", N_("Overlay Map"), N_("Opens the in-system overlay map.") },
98 { "mousefly", N_("Mouse Flight"), N_("Toggles mouse flying.") },
99 { "cooldown", N_("Active Cooldown"), N_("Begins active cooldown.") },
100 /* Communication */
101 { "log_up", N_("Log Scroll Up"), N_("Scrolls the log upwards.") },
102 { "log_down", N_("Log Scroll Down"), N_("Scrolls the log downwards.") },
103 { "hail", N_("Hail Target"), N_("Attempts to initialize communication with the targeted ship.") },
104 { "autohail", N_("Autohail"), N_("Automatically initialize communication with a ship that is hailing you.") },
105 /* Misc. */
106 { "mapzoomin", N_("Radar Zoom In"), N_("Zooms in on the radar.") },
107 { "mapzoomout", N_("Radar Zoom Out"), N_("Zooms out on the radar.") },
108 { "screenshot", N_("Screenshot"), N_("Takes a screenshot.") },
109 { "togglefullscreen", N_("Toggle Fullscreen"), N_("Toggles between windowed and fullscreen mode.") },
110 { "pause", N_("Pause"), N_("Pauses the game.") },
111 { "speed", N_("Toggle Speed"), N_("Toggles speed modifier.") },
112 { "menu", N_("Small Menu"), N_("Opens the small in-game menu.") },
113 { "info", N_("Information Menu"), N_("Opens the information menu.") },
114 { "console", N_("Lua Console"), N_("Opens the Lua console.") },
115 { "switchtab1", N_("Switch Tab 1"), N_("Switches to tab 1.") },
116 { "switchtab2", N_("Switch Tab 2"), N_("Switches to tab 2.") },
117 { "switchtab3", N_("Switch Tab 3"), N_("Switches to tab 3.") },
118 { "switchtab4", N_("Switch Tab 4"), N_("Switches to tab 4.") },
119 { "switchtab5", N_("Switch Tab 5"), N_("Switches to tab 5.") },
120 { "switchtab6", N_("Switch Tab 6"), N_("Switches to tab 6.") },
121 { "switchtab7", N_("Switch Tab 7"), N_("Switches to tab 7.") },
122 { "switchtab8", N_("Switch Tab 8"), N_("Switches to tab 8.") },
123 { "switchtab9", N_("Switch Tab 9"), N_("Switches to tab 9.") },
124 { "switchtab0", N_("Switch Tab 0"), N_("Switches to tab 0.") },
125 /* Console-main. */
126 { "paste", N_("Paste"), N_("Paste from the operating system's clipboard.") },
127 /* Must terminate in NULL. */
128 { NULL, NULL, NULL }
129};
132const int input_numbinds = ( sizeof( keybind_info ) / sizeof( keybind_info[ 0 ] ) ) - 1;
133static Keybind *input_paste;
134
135/*
136 * accel hacks
137 */
138static unsigned int input_accelLast = 0;
139static unsigned int input_revLast = 0;
140static int input_accelButton = 0;
142/*
143 * Key repeat hack.
144 */
145static int repeat_key = -1;
146static unsigned int repeat_keyTimer = 0;
147static unsigned int repeat_keyCounter = 0;
149/*
150 * Mouse.
151 */
152static double input_mouseTimer = -1.;
153static int input_mouseCounter = 1;
154static unsigned int input_mouseClickLast = 0;
155static void *input_lastClicked = NULL;
157/*
158 * from player.c
159 */
160extern double player_left;
161extern double player_right;
163/*
164 * Prototypes.
165 */
166static void input_key( int keynum, double value, double kabs, int repeat );
167static void input_clickZoom( double modifier );
168static void input_clickevent( SDL_Event* event );
169static void input_mouseMove( SDL_Event* event );
170
176void input_setDefault ( int wasd )
177{
178 /* Movement */
179 if (wasd) {
180 input_setKeybind( "accel", KEYBIND_KEYBOARD, SDLK_w, NMOD_ANY );
181 input_setKeybind( "left", KEYBIND_KEYBOARD, SDLK_a, NMOD_ANY );
182 input_setKeybind( "right", KEYBIND_KEYBOARD, SDLK_d, NMOD_ANY );
183 input_setKeybind( "reverse", KEYBIND_KEYBOARD, SDLK_s, NMOD_ANY );
184 }
185 else {
186 input_setKeybind( "accel", KEYBIND_KEYBOARD, SDLK_UP, NMOD_ANY );
187 input_setKeybind( "left", KEYBIND_KEYBOARD, SDLK_LEFT, NMOD_ANY );
188 input_setKeybind( "right", KEYBIND_KEYBOARD, SDLK_RIGHT, NMOD_ANY );
189 input_setKeybind( "reverse", KEYBIND_KEYBOARD, SDLK_DOWN, NMOD_ANY );
190 }
191 input_setKeybind( "stealth", KEYBIND_KEYBOARD, SDLK_f, NMOD_NONE );
192
193 /* Targeting */
194 if (wasd) {
195 input_setKeybind( "target_next", KEYBIND_KEYBOARD, SDLK_e, NMOD_CTRL );
196 input_setKeybind( "target_prev", KEYBIND_KEYBOARD, SDLK_q, NMOD_CTRL );
197 input_setKeybind( "target_nearest", KEYBIND_KEYBOARD, SDLK_t, NMOD_ANY );
198 input_setKeybind( "target_nextHostile", KEYBIND_NULL, SDLK_UNKNOWN, NMOD_NONE );
199 input_setKeybind( "target_prevHostile", KEYBIND_NULL, SDLK_UNKNOWN, NMOD_NONE );
200 input_setKeybind( "target_hostile", KEYBIND_KEYBOARD, SDLK_r, NMOD_ANY );
201 input_setKeybind( "target_clear", KEYBIND_KEYBOARD, SDLK_c, NMOD_ANY );
202 }
203 else {
204 input_setKeybind( "target_next", KEYBIND_KEYBOARD, SDLK_t, NMOD_NONE );
205 input_setKeybind( "target_prev", KEYBIND_KEYBOARD, SDLK_t, NMOD_CTRL );
206 input_setKeybind( "target_nearest", KEYBIND_KEYBOARD, SDLK_n, NMOD_NONE );
207 input_setKeybind( "target_nextHostile", KEYBIND_KEYBOARD, SDLK_r, NMOD_CTRL );
208 input_setKeybind( "target_prevHostile", KEYBIND_NULL, SDLK_UNKNOWN, NMOD_NONE );
209 input_setKeybind( "target_hostile", KEYBIND_KEYBOARD, SDLK_r, NMOD_NONE );
210 input_setKeybind( "target_clear", KEYBIND_KEYBOARD, SDLK_BACKSPACE, NMOD_ANY );
211 }
212
213 /* Combat */
214 input_setKeybind( "primary", KEYBIND_KEYBOARD, SDLK_SPACE, NMOD_ANY );
215
216 if (wasd)
217 input_setKeybind( "face", KEYBIND_KEYBOARD, SDLK_q, NMOD_NONE );
218 else
219 input_setKeybind( "face", KEYBIND_KEYBOARD, SDLK_a, NMOD_ANY );
220
221 input_setKeybind( "board", KEYBIND_KEYBOARD, SDLK_b, NMOD_NONE );
222 /* Secondary Weapons */
223 input_setKeybind( "secondary", KEYBIND_KEYBOARD, SDLK_LSHIFT, NMOD_ANY );
224 input_setKeybind( "weapset1", KEYBIND_KEYBOARD, SDLK_1, NMOD_ANY );
225 input_setKeybind( "weapset2", KEYBIND_KEYBOARD, SDLK_2, NMOD_ANY );
226 input_setKeybind( "weapset3", KEYBIND_KEYBOARD, SDLK_3, NMOD_ANY );
227 input_setKeybind( "weapset4", KEYBIND_KEYBOARD, SDLK_4, NMOD_ANY );
228 input_setKeybind( "weapset5", KEYBIND_KEYBOARD, SDLK_5, NMOD_ANY );
229 input_setKeybind( "weapset6", KEYBIND_KEYBOARD, SDLK_6, NMOD_ANY );
230 input_setKeybind( "weapset7", KEYBIND_KEYBOARD, SDLK_7, NMOD_ANY );
231 input_setKeybind( "weapset8", KEYBIND_KEYBOARD, SDLK_8, NMOD_ANY );
232 input_setKeybind( "weapset9", KEYBIND_KEYBOARD, SDLK_9, NMOD_ANY );
233 input_setKeybind( "weapset0", KEYBIND_KEYBOARD, SDLK_0, NMOD_ANY );
234 /* Escorts */
235 input_setKeybind( "e_targetNext", KEYBIND_NULL, SDLK_UNKNOWN, NMOD_NONE );
236 input_setKeybind( "e_targetPrev", KEYBIND_NULL, SDLK_UNKNOWN, NMOD_NONE );
237 input_setKeybind( "e_attack", KEYBIND_KEYBOARD, SDLK_END, NMOD_ANY );
238 input_setKeybind( "e_hold", KEYBIND_KEYBOARD, SDLK_INSERT, NMOD_ANY );
239 input_setKeybind( "e_return", KEYBIND_KEYBOARD, SDLK_DELETE, NMOD_ANY );
240 input_setKeybind( "e_clear", KEYBIND_KEYBOARD, SDLK_HOME, NMOD_ANY );
241 /* Space Navigation */
242 input_setKeybind( "autonav", KEYBIND_KEYBOARD, SDLK_j, NMOD_CTRL );
243 input_setKeybind( "target_spob", KEYBIND_KEYBOARD, SDLK_p, NMOD_NONE );
244 input_setKeybind( "land", KEYBIND_KEYBOARD, SDLK_l, NMOD_NONE );
245 input_setKeybind( "thyperspace", KEYBIND_KEYBOARD, SDLK_h, NMOD_NONE );
246 input_setKeybind( "starmap", KEYBIND_KEYBOARD, SDLK_m, NMOD_NONE );
247 input_setKeybind( "jump", KEYBIND_KEYBOARD, SDLK_j, NMOD_NONE );
248 input_setKeybind( "overlay", KEYBIND_KEYBOARD, SDLK_TAB, NMOD_ANY );
249 input_setKeybind( "mousefly", KEYBIND_KEYBOARD, SDLK_x, NMOD_CTRL );
250 input_setKeybind( "cooldown", KEYBIND_KEYBOARD, SDLK_s, NMOD_CTRL );
251 /* Communication */
252 input_setKeybind( "log_up", KEYBIND_KEYBOARD, SDLK_PAGEUP, NMOD_ANY );
253 input_setKeybind( "log_down", KEYBIND_KEYBOARD, SDLK_PAGEDOWN, NMOD_ANY );
254 input_setKeybind( "hail", KEYBIND_KEYBOARD, SDLK_y, NMOD_NONE );
255 input_setKeybind( "autohail", KEYBIND_KEYBOARD, SDLK_y, NMOD_CTRL );
256 /* Misc. */
257 input_setKeybind( "mapzoomin", KEYBIND_KEYBOARD, SDLK_KP_PLUS, NMOD_ANY );
258 input_setKeybind( "mapzoomout", KEYBIND_KEYBOARD, SDLK_KP_MINUS, NMOD_ANY );
259 input_setKeybind( "screenshot", KEYBIND_KEYBOARD, SDLK_KP_MULTIPLY, NMOD_ANY );
260 input_setKeybind( "togglefullscreen", KEYBIND_KEYBOARD, SDLK_F11, NMOD_ANY );
261 input_setKeybind( "pause", KEYBIND_KEYBOARD, SDLK_PAUSE, NMOD_ANY );
262
263 input_setKeybind( "speed", KEYBIND_KEYBOARD, SDLK_BACKQUOTE, NMOD_ANY );
264 input_setKeybind( "menu", KEYBIND_KEYBOARD, SDLK_ESCAPE, NMOD_ANY );
265 input_setKeybind( "info", KEYBIND_KEYBOARD, SDLK_i, NMOD_NONE );
266 input_setKeybind( "console", KEYBIND_KEYBOARD, SDLK_F2, NMOD_ANY );
267 input_setKeybind( "switchtab1", KEYBIND_KEYBOARD, SDLK_1, NMOD_ALT );
268 input_setKeybind( "switchtab2", KEYBIND_KEYBOARD, SDLK_2, NMOD_ALT );
269 input_setKeybind( "switchtab3", KEYBIND_KEYBOARD, SDLK_3, NMOD_ALT );
270 input_setKeybind( "switchtab4", KEYBIND_KEYBOARD, SDLK_4, NMOD_ALT );
271 input_setKeybind( "switchtab5", KEYBIND_KEYBOARD, SDLK_5, NMOD_ALT );
272 input_setKeybind( "switchtab6", KEYBIND_KEYBOARD, SDLK_6, NMOD_ALT );
273 input_setKeybind( "switchtab7", KEYBIND_KEYBOARD, SDLK_7, NMOD_ALT );
274 input_setKeybind( "switchtab8", KEYBIND_KEYBOARD, SDLK_8, NMOD_ALT );
275 input_setKeybind( "switchtab9", KEYBIND_KEYBOARD, SDLK_9, NMOD_ALT );
276 input_setKeybind( "switchtab0", KEYBIND_KEYBOARD, SDLK_0, NMOD_ALT );
277 input_setKeybind( "paste", KEYBIND_KEYBOARD, SDLK_v, NMOD_CTRL );
278}
279
283void input_init (void)
284{
285 /* Window. */
286 SDL_EventState( SDL_SYSWMEVENT, SDL_DISABLE );
287
288 /* Keyboard. */
289 SDL_EventState( SDL_KEYDOWN, SDL_ENABLE );
290 SDL_EventState( SDL_KEYUP, SDL_ENABLE );
291
292 /* Mice. */
293 SDL_EventState( SDL_MOUSEMOTION, SDL_ENABLE );
294 SDL_EventState( SDL_MOUSEBUTTONDOWN, SDL_ENABLE );
295 SDL_EventState( SDL_MOUSEBUTTONUP, SDL_ENABLE );
296
297 /* Joystick, enabled in joystick.c if needed. */
298 SDL_EventState( SDL_JOYAXISMOTION, SDL_DISABLE );
299 SDL_EventState( SDL_JOYHATMOTION, SDL_DISABLE );
300 SDL_EventState( SDL_JOYBUTTONDOWN, SDL_DISABLE );
301 SDL_EventState( SDL_JOYBUTTONUP, SDL_DISABLE );
302
303 /* Quit. */
304 SDL_EventState( SDL_QUIT, SDL_ENABLE );
305
306 /* Window. */
307 SDL_EventState( SDL_WINDOWEVENT, SDL_ENABLE );
308
309 /* Keyboard. */
310 SDL_EventState( SDL_TEXTINPUT, SDL_DISABLE); /* Enabled on a per-widget basis. */
311
312 /* Mouse. */
313 SDL_EventState( SDL_MOUSEWHEEL, SDL_ENABLE );
314
315 input_keybinds = malloc( input_numbinds * sizeof(Keybind) );
316
317 /* Create safe null keybinding for each. */
318 for (int i=0; i<input_numbinds; i++) {
319 Keybind *temp = &input_keybinds[i];
320 memset( temp, 0, sizeof(Keybind) );
321 temp->name = keybind_info[i][0];
322 temp->type = KEYBIND_NULL;
323 temp->key = SDLK_UNKNOWN;
324 temp->mod = NMOD_NONE;
325
326 if (strcmp(temp->name,"paste")==0)
327 input_paste = temp;
328 }
329}
330
334void input_exit (void)
335{
336 free(input_keybinds);
337}
338
343{
344 for (int i=0; keybind_info[i][0] != NULL; i++)
345 input_keybinds[i].disabled = 0;
346}
347
352{
353 for (int i=0; keybind_info[i][0] != NULL; i++)
354 input_keybinds[i].disabled = 1;
355}
356
360void input_toggleEnable( const char *key, int enable )
361{
362 for (int i=0; i<input_numbinds; i++) {
363 if (strcmp(key, input_keybinds[i].name)==0) {
364 input_keybinds[i].disabled = !enable;
365 break;
366 }
367 }
368}
369
374{
375 SDL_ShowCursor( SDL_ENABLE );
377}
378
383{
385 if (input_mouseCounter <= 0) {
388 }
389}
390
397SDL_Keycode input_keyConv( const char *name )
398{
399 SDL_Keycode k = SDL_GetKeyFromName( name );
400 if (k == SDLK_UNKNOWN)
401 WARN(_("Keyname '%s' doesn't match any key."), name);
402
403 return k;
404}
405
414void input_setKeybind( const char *keybind, KeybindType type, SDL_Keycode key, SDL_Keymod mod )
415{
416 for (int i=0; i<input_numbinds; i++) {
417 if (strcmp(keybind, input_keybinds[i].name)==0) {
418 input_keybinds[i].type = type;
419 input_keybinds[i].key = key;
420 /* Non-keyboards get mod NMOD_ANY to always match. */
421 input_keybinds[i].mod = (type==KEYBIND_KEYBOARD) ? mod : NMOD_ANY;
422 return;
423 }
424 }
425 WARN(_("Unable to set keybinding '%s', that command doesn't exist"), keybind);
426}
427
436SDL_Keycode input_getKeybind( const char *keybind, KeybindType *type, SDL_Keymod *mod )
437{
438 for (int i=0; i<input_numbinds; i++) {
439 if (strcmp(keybind, input_keybinds[i].name)==0) {
440 if (type != NULL)
441 (*type) = input_keybinds[i].type;
442 if (mod != NULL)
443 (*mod) = input_keybinds[i].mod;
444 return input_keybinds[i].key;
445 }
446 }
447 WARN(_("Unable to get keybinding '%s', that command doesn't exist"), keybind);
448 return (SDL_Keycode)-1;
449}
450
458void input_getKeybindDisplay( const char *keybind, char *buf, int len )
459{
460 /* Get the keybinding. */
461 KeybindType type = KEYBIND_NULL;
462 SDL_Keymod mod = NMOD_NONE;
463 SDL_Keycode key = input_getKeybind( keybind, &type, &mod );
464
465 /* Handle type. */
466 switch (type) {
467 case KEYBIND_NULL:
468 strncpy( buf, _("Not bound"), len );
469 break;
470
471 case KEYBIND_KEYBOARD:
472 {
473 int p = 0;
474 /* Handle mod. */
475 if ((mod != NMOD_NONE) && (mod != NMOD_ANY))
476 p += scnprintf( &buf[p], len-p, "%s + ", input_modToText(mod) );
477 /* Print key. Special-case ASCII letters (use uppercase, unlike SDL_GetKeyName.). */
478 if (key < 0x100 && isalpha(key))
479 p += scnprintf( &buf[p], len-p, "%c", toupper(key) );
480 else
481 p += scnprintf( &buf[p], len-p, "%s", pgettext_var("keyname", SDL_GetKeyName(key)) );
482 break;
483 }
484
485 case KEYBIND_JBUTTON:
486 snprintf( buf, len, _("joy button %d"), key );
487 break;
488
489 case KEYBIND_JHAT_UP:
490 snprintf( buf, len, _("joy hat %d up"), key );
491 break;
492
493 case KEYBIND_JHAT_DOWN:
494 snprintf( buf, len, _("joy hat %d down"), key );
495 break;
496
497 case KEYBIND_JHAT_LEFT:
498 snprintf( buf, len, _("joy hat %d left"), key );
499 break;
500
501 case KEYBIND_JHAT_RIGHT:
502 snprintf( buf, len, _("joy hat %d right"), key );
503 break;
504
505 case KEYBIND_JAXISPOS:
506 snprintf( buf, len, _("joy axis %d-"), key );
507 break;
508
509 case KEYBIND_JAXISNEG:
510 snprintf( buf, len, _("joy axis %d+"), key );
511 break;
512 }
513}
514
521const char* input_modToText( SDL_Keymod mod )
522{
523 switch ((int)mod) {
524 case NMOD_NONE: return _("None");
525 case NMOD_CTRL: return _("Ctrl");
526 case NMOD_SHIFT: return _("Shift");
527 case NMOD_ALT: return _("Alt");
528 case NMOD_META: return _("Meta");
529 case NMOD_ANY: return _("Any");
530 default: return _("unknown");
531 }
532}
533
542const char *input_keyAlreadyBound( KeybindType type, SDL_Keycode key, SDL_Keymod mod )
543{
544 for (int i=0; i<input_numbinds; i++) {
545 Keybind *k = &input_keybinds[i];
546
547 /* Type must match. */
548 if (k->type != type)
549 continue;
550
551 /* Must match key. */
552 if (key != k->key)
553 continue;
554
555 /* Handle per case. */
556 switch (type) {
557 case KEYBIND_KEYBOARD:
558 if ((k->mod == NMOD_ANY) || (mod == NMOD_ANY) ||
559 (k->mod == mod))
560 return keybind_info[i][0];
561 break;
562
563 case KEYBIND_JAXISPOS:
564 case KEYBIND_JAXISNEG:
565 case KEYBIND_JBUTTON:
566 case KEYBIND_JHAT_UP:
567 case KEYBIND_JHAT_DOWN:
568 case KEYBIND_JHAT_LEFT:
569 case KEYBIND_JHAT_RIGHT:
570 return keybind_info[i][0];
571
572 default:
573 break;
574 }
575 }
576
577 /* Not found. */
578 return NULL;
579}
580
587const char* input_getKeybindDescription( const char *keybind )
588{
589 for (int i=0; keybind_info[i][0] != NULL; i++)
590 if (strcmp(keybind, input_keybinds[i].name)==0)
591 return _(keybind_info[i][2]);
592 WARN(_("Unable to get keybinding description '%s', that command doesn't exist"), keybind);
593 return NULL;
594}
595
602SDL_Keymod input_translateMod( SDL_Keymod mod )
603{
604 SDL_Keymod mod_filtered = 0;
605 if (mod & (KMOD_LSHIFT | KMOD_RSHIFT))
606 mod_filtered |= NMOD_SHIFT;
607 if (mod & (KMOD_LCTRL | KMOD_RCTRL))
608 mod_filtered |= NMOD_CTRL;
609 if (mod & (KMOD_LALT | KMOD_RALT))
610 mod_filtered |= NMOD_ALT;
611 if (mod & (KMOD_LGUI | KMOD_RGUI))
612 mod_filtered |= NMOD_META;
613 return mod_filtered;
614}
615
619void input_update( double dt )
620{
621 if (input_mouseTimer > 0.) {
622 input_mouseTimer -= dt;
623
624 /* Hide if necessary. */
625 if ((input_mouseTimer < 0.) && (input_mouseCounter <= 0))
626 SDL_ShowCursor( SDL_DISABLE );
627 }
628
629 /* Key repeat if applicable. */
630 if (conf.repeat_delay != 0) {
631 unsigned int t;
632
633 /* Key must be repeating. */
634 if (repeat_key == -1)
635 return;
636
637 /* Get time. */
638 t = SDL_GetTicks();
639
640 /* Should be repeating. */
642 return;
643
644 /* Key repeat. */
646 input_key( repeat_key, KEY_PRESS, 0., 1 );
647 }
648}
649
650#define KEY(s) (strcmp(input_keybinds[keynum].name,s)==0)
651#define INGAME() (!toolkit_isOpen() && ((value==KEY_RELEASE) || !player_isFlag(PLAYER_CINEMATICS)))
652#define NOHYP() \
653 ((player.p != NULL) && !pilot_isFlag(player.p,PILOT_HYP_PREP) &&\
654 !pilot_isFlag(player.p,PILOT_HYP_BEGIN) &&\
655 !pilot_isFlag(player.p,PILOT_HYPERSPACE))
656#define NODEAD() ((player.p != NULL) && !pilot_isFlag(player.p,PILOT_DEAD))
657#define NOLAND() ((player.p != NULL) && (!landed && !pilot_isFlag(player.p,PILOT_LANDING)))
666static void input_key( int keynum, double value, double kabs, int repeat )
667{
668 HookParam hparam[3];
670 /* Repetition stuff. */
671 if (conf.repeat_delay != 0) {
672 if ((value == KEY_PRESS) && !repeat) {
673 repeat_key = keynum;
674 repeat_keyTimer = SDL_GetTicks();
676 }
677 else if (value == KEY_RELEASE) {
678 repeat_key = -1;
679 repeat_keyTimer = 0;
681 }
682 }
683
684 /*
685 * movement
686 */
687 /* accelerating */
688 if (KEY("accel") && !repeat) {
689 if (kabs >= 0.) {
690 player_restoreControl( PINPUT_MOVEMENT, NULL );
691 player_accel(kabs);
693 }
694 else { /* prevent it from getting stuck */
695 unsigned int t;
696
697 if (value==KEY_PRESS) {
698 player_restoreControl( PINPUT_MOVEMENT, NULL );
699 player_setFlag(PLAYER_ACCEL);
700 player_accel(1.);
702 }
703
704 else if (value==KEY_RELEASE) {
705 player_rmFlag(PLAYER_ACCEL);
707 if (!player_isFlag(PLAYER_REVERSE))
709 }
710
711 /* double tap accel = afterburn! */
712 t = SDL_GetTicks();
713 if ((conf.doubletap_sens != 0) &&
714 (value==KEY_PRESS) && INGAME() && NOHYP() && NODEAD() &&
717 else if (value==KEY_RELEASE)
719
720 if (value==KEY_PRESS)
721 input_accelLast = t;
722 }
723
724 /* turning left */
725 } else if (KEY("left") && !repeat) {
726 if (kabs >= 0.) {
727 player_restoreControl( PINPUT_MOVEMENT, NULL );
728 player_setFlag(PLAYER_TURN_LEFT);
729 player_left = kabs;
730 }
731 else {
732 /* set flags for facing correction */
733 if (value==KEY_PRESS) {
734 player_restoreControl( PINPUT_MOVEMENT, NULL );
735 player_setFlag(PLAYER_TURN_LEFT);
736 player_left = 1.;
737 }
738 else if (value==KEY_RELEASE) {
739 player_rmFlag(PLAYER_TURN_LEFT);
740 player_left = 0.;
741 }
742 }
743
744 /* turning right */
745 } else if (KEY("right") && !repeat) {
746 if (kabs >= 0.) {
747 player_restoreControl( PINPUT_MOVEMENT, NULL );
748 player_setFlag(PLAYER_TURN_RIGHT);
749 player_right = kabs;
750 }
751 else {
752 /* set flags for facing correction */
753 if (value==KEY_PRESS) {
754 player_restoreControl( PINPUT_MOVEMENT, NULL );
755 player_setFlag(PLAYER_TURN_RIGHT);
756 player_right = 1.;
757 }
758 else if (value==KEY_RELEASE) {
759 player_rmFlag(PLAYER_TURN_RIGHT);
760 player_right = 0.;
761 }
762 }
763
764 /* turn around to face vel */
765 } else if (KEY("reverse") && !repeat) {
766 unsigned int t;
767
768 if (value==KEY_PRESS) {
769 player_restoreControl( PINPUT_MOVEMENT, NULL );
770 player_setFlag(PLAYER_REVERSE);
771 }
772 else if ((value==KEY_RELEASE) && player_isFlag(PLAYER_REVERSE)) {
773 player_rmFlag(PLAYER_REVERSE);
774
775 if (!player_isFlag(PLAYER_ACCEL))
777 }
778
779 /* double tap reverse = cooldown! */
780 t = SDL_GetTicks();
781 if ((conf.doubletap_sens != 0) &&
782 (value==KEY_PRESS) && INGAME() && NOHYP() && NODEAD() &&
783 (t-input_revLast <= conf.doubletap_sens))
784 player_brake();
785
786 if (value==KEY_PRESS)
787 input_revLast = t;
788
789 /* try to enter stealth mode. */
790 } else if (KEY("stealth") && !repeat && NOHYP() && NODEAD() && INGAME()) {
791 if (value==KEY_PRESS)
793
794 /* face the target */
795 } else if (KEY("face") && !repeat) {
796 if (value==KEY_PRESS) {
797 player_restoreControl( PINPUT_MOVEMENT, NULL );
798 player_setFlag(PLAYER_FACE);
799 }
800 else if ((value==KEY_RELEASE) && player_isFlag(PLAYER_FACE))
801 player_rmFlag(PLAYER_FACE);
802
803 /*
804 * Combat
805 */
806 /* shooting primary weapon */
807 } else if (KEY("primary") && !repeat) {
808 if (value==KEY_PRESS) {
809 player_setFlag(PLAYER_PRIMARY);
810 }
811 else if (value==KEY_RELEASE)
812 player_rmFlag(PLAYER_PRIMARY);
813 /* targeting */
814 } else if ((INGAME() || map_isOpen()) && NODEAD() && KEY("target_next")) {
815 if (value==KEY_PRESS) {
816 if (map_isOpen())
817 map_cycleMissions(1);
818 else
820 }
821 } else if ((INGAME() || map_isOpen()) && NODEAD() && KEY("target_prev")) {
822 if (value==KEY_PRESS) {
823 if (map_isOpen())
824 map_cycleMissions(-1);
825 else
827 }
828 } else if ((INGAME() || map_isOpen()) && NODEAD() && KEY("target_nearest")) {
829 if (value==KEY_PRESS) {
830 if (map_isOpen())
831 map_cycleMissions(1);
832 else
834 }
835 } else if (INGAME() && NODEAD() && KEY("target_nextHostile")) {
836 if (value==KEY_PRESS) player_targetNext(1);
837 } else if (INGAME() && NODEAD() && KEY("target_prevHostile")) {
838 if (value==KEY_PRESS) player_targetPrev(1);
839 } else if (INGAME() && NODEAD() && KEY("target_hostile")) {
840 if (value==KEY_PRESS) player_targetHostile();
841 } else if (INGAME() && NODEAD() && KEY("target_clear")) {
842 if (value==KEY_PRESS) player_targetClear();
843
844 /* board them ships */
845 } else if (KEY("board") && INGAME() && NOHYP() && NODEAD() && !repeat) {
846 if (value==KEY_PRESS) {
847 player_restoreControl( 0, NULL );
848 if (player_tryBoard(0) == PLAYER_BOARD_RETRY)
849 player_board();
850 }
851
852 /*
853 * Escorts.
854 */
855 } else if (INGAME() && NODEAD() && KEY("e_targetNext") && !repeat) {
856 if (value==KEY_PRESS) player_targetEscort(0);
857 } else if (INGAME() && NODEAD() && KEY("e_targetPrev") && !repeat) {
858 if (value==KEY_PRESS) player_targetEscort(1);
859 } else if (INGAME() && NODEAD() && KEY("e_attack") && !repeat) {
860 if (value==KEY_PRESS) escorts_attack(player.p);
861 } else if (INGAME() && NODEAD() && KEY("e_hold") && !repeat) {
862 if (value==KEY_PRESS) escorts_hold(player.p);
863 } else if (INGAME() && NODEAD() && KEY("e_return") && !repeat) {
864 if (value==KEY_PRESS) escorts_return(player.p);
865 } else if (INGAME() && NODEAD() && KEY("e_clear") && !repeat) {
866 if (value==KEY_PRESS) escorts_clear(player.p);
867
868 /*
869 * secondary weapons
870 */
871 /* shooting secondary weapon */
872 } else if (KEY("secondary") && !repeat) {
873 if (value==KEY_PRESS) {
874 player_setFlag(PLAYER_SECONDARY);
875 }
876 else if (value==KEY_RELEASE)
877 player_rmFlag(PLAYER_SECONDARY);
878
879 /* Weapon sets. */
880 } else if (NODEAD() && KEY("weapset1")) {
881 player_weapSetPress( 0, value, repeat );
882 } else if (NODEAD() && KEY("weapset2")) {
883 player_weapSetPress( 1, value, repeat );
884 } else if (NODEAD() && KEY("weapset3")) {
885 player_weapSetPress( 2, value, repeat );
886 } else if (NODEAD() && KEY("weapset4")) {
887 player_weapSetPress( 3, value, repeat );
888 } else if (NODEAD() && KEY("weapset5")) {
889 player_weapSetPress( 4, value, repeat );
890 } else if (NODEAD() && KEY("weapset6")) {
891 player_weapSetPress( 5, value, repeat );
892 } else if (NODEAD() && KEY("weapset7")) {
893 player_weapSetPress( 6, value, repeat );
894 } else if (NODEAD() && KEY("weapset8")) {
895 player_weapSetPress( 7, value, repeat );
896 } else if (NODEAD() && KEY("weapset9")) {
897 player_weapSetPress( 8, value, repeat );
898 } else if (NODEAD() && KEY("weapset0")) {
899 player_weapSetPress( 9, value, repeat );
900
901 /*
902 * Space
903 */
904 } else if (KEY("autonav") && NOHYP() && NODEAD()) {
905 if (value==KEY_PRESS) {
906 if (map_isOpen()) {
907 unsigned int wid = window_get( MAP_WDWNAME );
908 player_autonavStartWindow( wid, NULL );
909 }
910 else if INGAME() {
912 }
913 }
914 /* target spob (cycles like target) */
915 } else if (KEY("target_spob") && INGAME() && NOHYP() && NOLAND() && NODEAD()) {
916 if (value==KEY_PRESS) player_targetSpob();
917 /* target nearest spob or attempt to land */
918 } else if (KEY("land") && INGAME() && NOHYP() && NOLAND() && NODEAD()) {
919 if (value==KEY_PRESS) {
920 if (player.p->nav_spob != -1) {
921 if (player_land(0) == PLAYER_LAND_AGAIN) {
922 player_autonavSpob( cur_system->spobs[player.p->nav_spob]->name, 1 );
923 }
924 } else
925 player_land(1);
926 }
927 } else if (KEY("thyperspace") && NOHYP() && NOLAND() && NODEAD()) {
928 if (value==KEY_PRESS) player_targetHyperspace();
929 } else if (KEY("starmap") && NOHYP() && NODEAD() && !repeat) {
930 if (value==KEY_PRESS) map_open();
931 } else if (KEY("jump") && INGAME() && !repeat) {
932 if (value==KEY_PRESS) {
933 player_restoreControl( 0, NULL );
934 player_jump();
935 }
936 } else if (KEY("overlay") && NODEAD() && (INGAME() || map_isOpen()) && !repeat) {
937 if (map_isOpen())
938 map_toggleNotes();
939 else
940 ovr_key( value );
941 } else if (KEY("mousefly") && NODEAD() && !repeat) {
942 if (value==KEY_PRESS)
944 } else if (KEY("cooldown") && NOHYP() && NOLAND() && NODEAD() && !repeat) {
945 if (value==KEY_PRESS) {
946 player_restoreControl( PINPUT_BRAKING, NULL );
947 player_brake();
948 }
949
950 /*
951 * Communication.
952 */
953 } else if (KEY("log_up") && INGAME() && NODEAD()) {
954 if (value==KEY_PRESS) {
956 }
957 } else if (KEY("log_down") && INGAME() && NODEAD()) {
958 if (value==KEY_PRESS) {
960 }
961 } else if (KEY("hail") && INGAME() && NOHYP() && NODEAD() && !repeat) {
962 if (value==KEY_PRESS) {
963 player_hail();
964 }
965 } else if (KEY("autohail") && INGAME() && NOHYP() && NODEAD() && !repeat) {
966 if (value==KEY_PRESS) {
968 }
969
970 /*
971 * misc
972 */
973 /* zooming in */
974 } else if (KEY("mapzoomin") && INGAME() && NODEAD()) {
975 if (value==KEY_PRESS) gui_setRadarRel(-1);
976 /* zooming out */
977 } else if (KEY("mapzoomout") && INGAME() && NODEAD()) {
978 if (value==KEY_PRESS) gui_setRadarRel(1);
979 /* take a screenshot */
980 } else if (KEY("screenshot")) {
981 if (value==KEY_PRESS) player_screenshot();
982 /* toggle fullscreen */
983 } else if (KEY("togglefullscreen") && !repeat) {
984 if (value==KEY_PRESS) naev_toggleFullscreen();
985 /* pause the games */
986 } else if (KEY("pause") && !repeat) {
987 if (value==KEY_PRESS) {
988 if (!toolkit_isOpen()) {
989 if (paused)
990 unpause_game();
991 else
992 pause_player();
993 }
994 }
995 /* toggle speed mode */
996 } else if (KEY("speed") && !repeat) {
997 if ((value==KEY_PRESS) && (!player_isFlag( PLAYER_CINEMATICS_2X ))) {
998 if (player.speed < 4.) {
999 player.speed *= 2.;
1000 } else {
1001 player.speed = 1.;
1002 }
1004 }
1005 /* opens a small menu */
1006 } else if (KEY("menu") && NODEAD() && !repeat) {
1007 if (value==KEY_PRESS) menu_small( 1, 1, 1, 1 );
1008
1009 /* shows pilot information */
1010 } else if (KEY("info") && NOHYP() && NODEAD() && !repeat) {
1011 if (value==KEY_PRESS) menu_info( INFO_DEFAULT );
1012
1013 /* Opens the Lua console. */
1014 } else if (KEY("console") && NODEAD() && !repeat) {
1015 if (value==KEY_PRESS) cli_open();
1016 }
1017
1018 /* Key press not used. */
1019 else {
1020 return;
1021 }
1022
1023 /* Run the hook. */
1024 hparam[0].type = HOOK_PARAM_STRING;
1025 hparam[0].u.str = input_keybinds[keynum].name;
1026 hparam[1].type = HOOK_PARAM_BOOL;
1027 hparam[1].u.b = (value > 0.);
1028 hparam[2].type = HOOK_PARAM_SENTINEL;
1029 hooks_runParam( "input", hparam );
1030}
1031#undef KEY
1032
1033/*
1034 * events
1035 */
1036/* prototypes */
1037static void input_joyaxis( const SDL_Keycode axis, const int value );
1038static void input_joyevent( const int event, const SDL_Keycode button );
1039static void input_keyevent( const int event, const SDL_Keycode key, const SDL_Keymod mod, const int repeat );
1040
1041/*
1042 * joystick
1043 */
1049static void input_joyaxis( const SDL_Keycode axis, const int value )
1050{
1051 for (int i=0; i<input_numbinds; i++) {
1052 if (input_keybinds[i].key == axis) {
1053 /* Positive axis keybinding. */
1054 if ((input_keybinds[i].type == KEYBIND_JAXISPOS)
1055 && (value >= 0)) {
1056 int k = (value > 0) ? KEY_PRESS : KEY_RELEASE;
1057 if ((k == KEY_PRESS) && input_keybinds[i].disabled)
1058 continue;
1059 input_key( i, k, FABS(((double)value)/32767.), 0 );
1060 }
1061
1062 /* Negative axis keybinding. */
1063 if ((input_keybinds[i].type == KEYBIND_JAXISNEG)
1064 && (value <= 0)) {
1065 int k = (value < 0) ? KEY_PRESS : KEY_RELEASE;
1066 if ((k == KEY_PRESS) && input_keybinds[i].disabled)
1067 continue;
1068 input_key( i, k, FABS(((double)value)/32767.), 0 );
1069 }
1070 }
1071 }
1072}
1078static void input_joyevent( const int event, const SDL_Keycode button )
1079{
1080 for (int i=0; i<input_numbinds; i++) {
1081 if ((event == KEY_PRESS) && input_keybinds[i].disabled)
1082 continue;
1083 if ((input_keybinds[i].type == KEYBIND_JBUTTON) &&
1084 (input_keybinds[i].key == button))
1085 input_key(i, event, -1., 0);
1086 }
1087}
1088
1094static void input_joyhatevent( const Uint8 value, const Uint8 hat )
1095{
1096 for (int i=0; i<input_numbinds; i++) {
1097 if (input_keybinds[i].key != hat)
1098 continue;
1099
1100 if (input_keybinds[i].type == KEYBIND_JHAT_UP) {
1101 int event = (value & SDL_HAT_UP) ? KEY_PRESS : KEY_RELEASE;
1102 if (!((event == KEY_PRESS) && input_keybinds[i].disabled))
1103 input_key(i, event, -1., 0);
1104 } else if (input_keybinds[i].type == KEYBIND_JHAT_DOWN) {
1105 int event = (value & SDL_HAT_DOWN) ? KEY_PRESS : KEY_RELEASE;
1106 if (!((event == KEY_PRESS) && input_keybinds[i].disabled))
1107 input_key(i, event, -1., 0);
1108 } else if (input_keybinds[i].type == KEYBIND_JHAT_LEFT) {
1109 int event = (value & SDL_HAT_LEFT) ? KEY_PRESS : KEY_RELEASE;
1110 if (!((event == KEY_PRESS) && input_keybinds[i].disabled))
1111 input_key(i, event, -1., 0);
1112 } else if (input_keybinds[i].type == KEYBIND_JHAT_RIGHT) {
1113 int event = (value & SDL_HAT_RIGHT) ? KEY_PRESS : KEY_RELEASE;
1114 if (!((event == KEY_PRESS) && input_keybinds[i].disabled))
1115 input_key(i, event, -1., 0);
1116 }
1117 }
1118}
1119
1120/*
1121 * keyboard
1122 */
1130static void input_keyevent( const int event, SDL_Keycode key, const SDL_Keymod mod, const int repeat )
1131{
1132 /* Filter to "Naev" modifiers. */
1133 SDL_Keymod mod_filtered = input_translateMod(mod);
1134 for (int i=0; i<input_numbinds; i++) {
1135 if ((event == KEY_PRESS) && input_keybinds[i].disabled)
1136 continue;
1137 if ((input_keybinds[i].type == KEYBIND_KEYBOARD) &&
1138 (input_keybinds[i].key == key)) {
1139 if ((input_keybinds[i].mod == mod_filtered) ||
1140 (input_keybinds[i].mod == NMOD_ANY) ||
1141 (event == KEY_RELEASE))
1142 input_key(i, event, -1., repeat);
1143 /* No break so all keys get pressed if needed. */
1144 }
1145 }
1146}
1147
1151static void input_clickZoom( double modifier )
1152{
1153 if (player.p != NULL)
1155}
1156
1160static void input_mouseMove( SDL_Event* event )
1161{
1162 int mx, my;
1163 gl_windowToScreenPos( &mx, &my, event->button.x, event->button.y );
1164 player.mousex = mx;
1165 player.mousey = my;
1166}
1167
1171static void input_clickevent( SDL_Event* event )
1172{
1173 int mx, my;
1174 int res;
1175 double x, y, zoom;
1176 HookParam hparam[3];
1177
1178 /* Generate hook. */
1179 hparam[0].type = HOOK_PARAM_NUMBER;
1180 hparam[0].u.num = event->button.button;
1181 hparam[1].type = HOOK_PARAM_BOOL;
1182 hparam[1].u.b = (event->type == SDL_MOUSEBUTTONDOWN);
1183 hparam[2].type = HOOK_PARAM_SENTINEL;
1184 hooks_runParam( "mouse", hparam );
1185
1186 /* Disable in cinematics. */
1187 if (player_isFlag(PLAYER_CINEMATICS))
1188 return;
1189
1190 /* Player must not be NULL. */
1191 if ((player.p == NULL) || player_isFlag(PLAYER_DESTROYED))
1192 return;
1193
1194 /* Player must not be dead. */
1195 if (pilot_isFlag(player.p, PILOT_DEAD))
1196 return;
1197
1198 /* Middle mouse enables mouse flying. */
1199 if (event->button.button == SDL_BUTTON_MIDDLE) {
1201 return;
1202 }
1203
1204 /* Mouse targeting only uses left and right buttons. */
1205 if (event->button.button != SDL_BUTTON_LEFT &&
1206 event->button.button != SDL_BUTTON_RIGHT)
1207 return;
1208
1209 if (gui_borderClickEvent( event ))
1210 return;
1211
1212 if (gui_radarClickEvent( event ))
1213 return;
1214
1215 /* Visual (on-screen) */
1216 gl_windowToScreenPos( &mx, &my, event->button.x, event->button.y );
1217 gl_screenToGameCoords( &x, &y, (double)mx, (double)my );
1218 zoom = res = 1. / cam_getZoom();
1219 input_clickPos( event, x, y, zoom, 10. * res, 15. * res );
1220 return;
1221}
1222
1234int input_clickPos( SDL_Event *event, double x, double y, double zoom, double minpr, double minr )
1235{
1236 unsigned int pid;
1238 double r, rp;
1239 double d, dp;
1240 int pntid, jpid, astid, fieid;
1241
1242 /* Don't allow selecting a new target with the right mouse button
1243 * (prevents pilots from getting in the way of autonav). */
1244 if (event->button.button == SDL_BUTTON_RIGHT) {
1245 pid = player.p->target;
1246 p = pilot_get(pid);
1247 dp = pow2(x - p->solid->pos.x) + pow2(y - p->solid->pos.y);
1248 } else {
1249 dp = pilot_getNearestPos( player.p, &pid, x, y, 1 );
1250 p = pilot_get(pid);
1251 }
1252
1253 d = system_getClosest( cur_system, &pntid, &jpid, &astid, &fieid, x, y );
1254 rp = MAX( 1.5 * PILOT_SIZE_APPROX * p->ship->gfx_space->sw / 2 * zoom, minpr);
1255
1256 if (pntid >=0) { /* Spob is closer. */
1257 Spob *pnt = cur_system->spobs[ pntid ];
1258 r = MAX( 1.5 * pnt->radius * zoom, minr );
1259 }
1260 else if (jpid >= 0) {
1261 JumpPoint *jp = &cur_system->jumps[ jpid ];
1262 r = MAX( 1.5 * jp->radius * zoom, minr );
1263 }
1264 else if (astid >= 0) {
1265 AsteroidAnchor *field = &cur_system->asteroids[fieid];
1266 Asteroid *ast = &field->asteroids[astid];
1267
1268 /* Recover the right gfx */
1269 r = MAX( MAX( ast->gfx->sw * zoom, minr ), ast->gfx->sh * zoom );
1270 }
1271 else
1272 r = 0.;
1273
1274 /* Reject pilot if it's too far or a valid spob is closer. */
1275 if ((dp > pow2(rp)) || ((d < pow2(r)) && (dp > d)))
1276 pid = PLAYER_ID;
1277
1278 if (d > pow2(r)) /* Spob or jump point is too far. */
1279 jpid = pntid = astid = fieid = -1;
1280
1281 /* Target a pilot, spob or jump, and/or perform an appropriate action. */
1282 if (event->button.button == SDL_BUTTON_LEFT) {
1283 if (pid != PLAYER_ID) {
1284 return input_clickedPilot(pid, 0);
1285 }
1286 else if (pntid >= 0) { /* Spob is closest. */
1287 return input_clickedSpob(pntid, 0);
1288 }
1289 else if (jpid >= 0) { /* Jump point is closest. */
1290 return input_clickedJump(jpid, 0);
1291 }
1292 else if (astid >= 0) { /* Asteroid is closest. */
1293 return input_clickedAsteroid(fieid, astid);
1294 }
1295 }
1296 /* Right click only controls autonav. */
1297 else if (event->button.button == SDL_BUTTON_RIGHT) {
1298 if ((pid != PLAYER_ID) && input_clickedPilot(pid, 1))
1299 return 1;
1300 else if ((pntid >= 0) && input_clickedSpob(pntid, 1))
1301 return 1;
1302 else if ((jpid >= 0) && input_clickedJump(jpid, 1))
1303 return 1;
1304
1305 /* Go to position, if the position is >= 1500 px away. */
1306 if ((pow2(x - player.p->solid->pos.x) + pow2(y - player.p->solid->pos.y))
1307 >= pow2(1500))
1308
1309 player_autonavPos( x, y );
1310 return 1;
1311 }
1312
1313 return 0;
1314}
1315
1323int input_clickedJump( int jump, int autonav )
1324{
1325 JumpPoint *jp = &cur_system->jumps[ jump ];
1327 if (!jp_isUsable(jp))
1328 return 0;
1329
1330 if (autonav)
1331 return 0;
1332
1333 if (player.p->nav_hyperspace != jump)
1334 map_select( jp->target, 0 );
1335
1336 if ((jump == player.p->nav_hyperspace) && input_isDoubleClick( (void*)jp )) {
1337 player_targetHyperspaceSet( jump, 0 );
1339 player_jump();
1340 else
1342 return 1;
1343 }
1344 else
1345 player_targetHyperspaceSet( jump, 0 );
1346
1347 input_clicked( (void*)jp );
1348 return 0;
1349}
1350
1358int input_clickedSpob( int spob, int autonav )
1359{
1360 Spob *pnt = cur_system->spobs[ spob ];
1362 if (!spob_isKnown(pnt))
1363 return 0;
1364
1365 if (autonav) {
1367 player_autonavSpob(pnt->name, 0);
1368 return 1;
1369 }
1370
1371 if (spob == player.p->nav_spob && input_isDoubleClick((void*)pnt)) {
1373 spob_updateLand( pnt );
1374 if (!spob_isFlag(pnt, SPOB_SERVICE_INHABITED) || pnt->can_land ||
1375 (pnt->land_override > 0)) {
1376 int ret = player_land(0);
1377 if (ret == PLAYER_LAND_AGAIN) {
1378 player_autonavSpob(pnt->name, 1);
1379 }
1380 else if (ret == PLAYER_LAND_DENIED) {
1381 player_autonavSpob(pnt->name, 0);
1382 }
1383 }
1384 else
1386 }
1387 else
1388 player_targetSpobSet( spob );
1389
1390 input_clicked( (void*)pnt );
1391 return 1;
1392}
1393
1401int input_clickedAsteroid( int field, int asteroid )
1402{
1403 AsteroidAnchor *anchor = &cur_system->asteroids[ field ];
1404 Asteroid *ast = &anchor->asteroids[ asteroid ];
1405 player_targetAsteroidSet( field, asteroid );
1406 input_clicked( (void*)ast );
1407 return 1;
1408}
1409
1417int input_clickedPilot( unsigned int pilot, int autonav )
1418{
1419 Pilot *p;
1421 if (pilot == PLAYER_ID)
1422 return 0;
1423
1424 if (autonav) {
1425 player_targetSet( pilot );
1426 player_autonavPil( pilot );
1427 return 1;
1428 }
1429
1430 p = pilot_get(pilot);
1431 if (pilot == player.p->target && input_isDoubleClick( (void*)p )) {
1432 if (pilot_isDisabled(p) || pilot_isFlag(p, PILOT_BOARDABLE)) {
1433 if (player_tryBoard(0)==PLAYER_BOARD_RETRY)
1434 player_board();
1435 }
1436 else
1437 player_hail();
1438 }
1439 else
1440 player_targetSet( pilot );
1441
1442 input_clicked( (void*)p );
1443 return 1;
1444}
1445
1450void input_clicked( void *clicked )
1451{
1452 if (conf.mouse_doubleclick <= 0.)
1453 return;
1454
1455 input_lastClicked = clicked;
1456 input_mouseClickLast = SDL_GetTicks();
1457}
1458
1463int input_isDoubleClick( void *clicked )
1464{
1465 unsigned int threshold;
1467 if (conf.mouse_doubleclick <= 0.)
1468 return 1;
1469
1470 /* Most recent time that constitutes a valid double-click. */
1471 threshold = input_mouseClickLast + (int)(conf.mouse_doubleclick * 1000);
1472
1473 if ((SDL_GetTicks() <= threshold) && (clicked == input_lastClicked))
1474 return 1;
1475
1476 return 0;
1477}
1478
1486void input_handle( SDL_Event* event )
1487{
1488 int ismouse;
1490 /* Special case mouse stuff. */
1491 if ((event->type == SDL_MOUSEMOTION) ||
1492 (event->type == SDL_MOUSEBUTTONDOWN) ||
1493 (event->type == SDL_MOUSEBUTTONUP)) {
1495 SDL_ShowCursor( SDL_ENABLE );
1496 ismouse = 1;
1497 }
1498 else
1499 ismouse = 0;
1500
1501 /* Special case paste. */
1502 if (event->type == SDL_KEYDOWN && SDL_HasClipboardText() &&
1503 SDL_EventState( SDL_TEXTINPUT, SDL_QUERY )==SDL_ENABLE) {
1504 SDL_Keymod mod = input_translateMod( event->key.keysym.mod );
1505 if ((input_paste->key == event->key.keysym.sym) &&
1506 (input_paste->mod & mod)) {
1507 SDL_Event evt;
1508 char *txt = SDL_GetClipboardText();
1509 evt.type = SDL_TEXTINPUT;
1510 size_t i = 0;
1511 uint32_t ch;
1512 while ((ch = u8_nextchar( txt, &i ))) {
1513 size_t e = u8_wc_toutf8( evt.text.text, ch );
1514 evt.text.text[e] = '\0';
1515 SDL_PushEvent( &evt );
1516 }
1517 return;
1518 }
1519 }
1520
1521 if (toolkit_isOpen()) { /* toolkit handled completely separately */
1522 if (toolkit_input(event))
1523 return; /* we don't process it if toolkit grabs it */
1524 if (ismouse)
1525 return; /* Toolkit absorbs everything mousy. */
1526 }
1527
1528 if (ovr_isOpen())
1529 if (ovr_input(event))
1530 return; /* Don't process if the map overlay wants it. */
1531
1532 /* GUI gets event. */
1533 if (gui_handleEvent(event))
1534 return;
1535
1536 switch (event->type) {
1537
1538 /*
1539 * game itself
1540 */
1541 case SDL_JOYAXISMOTION:
1542 input_joyaxis(event->jaxis.axis, event->jaxis.value);
1543 break;
1544
1545 case SDL_JOYBUTTONDOWN:
1546 input_joyevent(KEY_PRESS, event->jbutton.button);
1547 break;
1548
1549 case SDL_JOYBUTTONUP:
1550 input_joyevent(KEY_RELEASE, event->jbutton.button);
1551 break;
1552
1553 case SDL_JOYHATMOTION:
1554 input_joyhatevent(event->jhat.value, event->jhat.hat);
1555 break;
1556
1557 case SDL_KEYDOWN:
1558 if (event->key.repeat != 0)
1559 return;
1560 input_keyevent(KEY_PRESS, event->key.keysym.sym, event->key.keysym.mod, 0);
1561 break;
1562
1563 case SDL_KEYUP:
1564 if (event->key.repeat !=0)
1565 return;
1566 input_keyevent(KEY_RELEASE, event->key.keysym.sym, event->key.keysym.mod, 0);
1567 break;
1568
1569 /* Mouse stuff. */
1570 case SDL_MOUSEBUTTONDOWN:
1571 input_clickevent( event );
1572 break;
1573
1574 case SDL_MOUSEWHEEL:
1575 if (event->wheel.y > 0)
1576 input_clickZoom( 1.1 );
1577 else if (event->wheel.y < 0)
1578 input_clickZoom( 0.9 );
1579 break;
1580
1581 case SDL_MOUSEMOTION:
1582 input_mouseMove( event );
1583 break;
1584
1585 default:
1586 break;
1587 }
1588}
Provides macros to work with dynamic arrays.
int player_tryBoard(int noisy)
Attempt to board the player's target.
Definition: board.c:113
double cam_getZoomTarget(void)
Gets the camera zoom.
Definition: camera.c:107
double cam_getZoom(void)
Gets the camera zoom.
Definition: camera.c:97
void cam_setZoomTarget(double zoom, double speed)
Sets the camera zoom target.
Definition: camera.c:86
void cli_open(void)
Opens the console.
Definition: console.c:654
int escorts_return(Pilot *parent)
Have a pilot order its escorts to dock.
Definition: escort.c:330
int escorts_attack(Pilot *parent)
Have a pilot order its escorts to attack its target.
Definition: escort.c:284
int escorts_hold(Pilot *parent)
Have a pilot order its escorts to hold position.
Definition: escort.c:317
int escorts_clear(Pilot *parent)
Have a pilot order its escorts to clear orders.
Definition: escort.c:343
const char * pgettext_var(const char *msgctxt, const char *msgid)
Definition: gettext.c:303
int gui_radarClickEvent(SDL_Event *event)
Handles a click at a position in the current system.
Definition: gui.c:2067
int gui_handleEvent(SDL_Event *evt)
Handles GUI events.
Definition: gui.c:2151
void gui_messageScrollDown(int lines)
Scrolls up the message box.
Definition: gui.c:253
int gui_borderClickEvent(SDL_Event *event)
Handles clicks on the GUI border icons.
Definition: gui.c:2096
void gui_setRadarRel(int mod)
Modifies the radar resolution.
Definition: gui.c:2008
void gui_messageScrollUp(int lines)
Scrolls up the message box.
Definition: gui.c:224
int hooks_runParam(const char *stack, const HookParam *param)
Runs all the hooks of stack.
Definition: hook.c:967
Handles the info menu.
#define INFO_DEFAULT
Definition: info.h:16
void menu_info(int window)
Opens the information menu.
Definition: info.c:278
void input_init(void)
Initializes the input subsystem (does not set keys).
Definition: input.c:283
static void input_mouseMove(SDL_Event *event)
Provides mouse X and Y coordinates for mouse flying.
Definition: input.c:1163
static void input_joyhatevent(const Uint8 value, const Uint8 hat)
Filters a joystick hat event.
Definition: input.c:1097
SDL_Keycode input_getKeybind(const char *keybind, KeybindType *type, SDL_Keymod *mod)
Gets the value of a keybind.
Definition: input.c:436
void input_disableAll(void)
Disables all the keybinds.
Definition: input.c:351
static void input_key(int keynum, double value, double kabs, int repeat)
Runs the input command.
Definition: input.c:669
int input_clickedPilot(unsigned int pilot, int autonav)
Performs an appropriate action when a pilot is clicked.
Definition: input.c:1420
static void input_clickZoom(double modifier)
Handles zoom.
Definition: input.c:1154
static unsigned int repeat_keyCounter
Definition: input.c:147
const char * keybind_info[][3]
Definition: input.c:52
void input_clicked(void *clicked)
Sets the last-clicked item, for double-click detection.
Definition: input.c:1453
double player_right
Definition: player.c:121
static void input_joyevent(const int event, const SDL_Keycode button)
Filters a joystick button event.
Definition: input.c:1081
#define MOUSE_HIDE
Definition: input.c:37
static void input_clickevent(SDL_Event *event)
Handles a click event.
Definition: input.c:1174
static unsigned int input_mouseClickLast
Definition: input.c:154
SDL_Keycode input_keyConv(const char *name)
Gets the key id from its name.
Definition: input.c:397
void input_toggleEnable(const char *key, int enable)
Enables or disables a keybind.
Definition: input.c:360
static void input_joyaxis(const SDL_Keycode axis, const int value)
Filters a joystick axis event.
Definition: input.c:1052
static int input_accelButton
Definition: input.c:140
void input_handle(SDL_Event *event)
Handles global input.
Definition: input.c:1489
void input_mouseShow(void)
Shows the mouse.
Definition: input.c:373
static void * input_lastClicked
Definition: input.c:155
static int input_mouseCounter
Definition: input.c:153
int input_isDoubleClick(void *clicked)
Checks whether a clicked item is the same as the last-clicked.
Definition: input.c:1466
#define NOLAND()
Definition: input.c:660
const char * input_keyAlreadyBound(KeybindType type, SDL_Keycode key, SDL_Keymod mod)
Checks to see if a key is already bound.
Definition: input.c:542
void input_setDefault(int wasd)
Sets the default input keys.
Definition: input.c:176
int input_clickPos(SDL_Event *event, double x, double y, double zoom, double minpr, double minr)
Handles a click at a position in the current system.
Definition: input.c:1237
static void input_keyevent(const int event, const SDL_Keycode key, const SDL_Keymod mod, const int repeat)
Filters a keyboard event.
Definition: input.c:1133
int input_clickedAsteroid(int field, int asteroid)
Performs an appropriate action when an asteroid is clicked.
Definition: input.c:1404
int input_clickedSpob(int spob, int autonav)
Performs an appropriate action when a spob is clicked.
Definition: input.c:1361
#define INGAME()
Definition: input.c:651
static Keybind * input_keybinds
Definition: input.c:131
static unsigned int input_accelLast
Definition: input.c:138
static unsigned int repeat_keyTimer
Definition: input.c:146
static double input_mouseTimer
Definition: input.c:152
static int repeat_key
Definition: input.c:145
void input_update(double dt)
Handles key repeating.
Definition: input.c:619
void input_setKeybind(const char *keybind, KeybindType type, SDL_Keycode key, SDL_Keymod mod)
Binds key of type type to action keybind.
Definition: input.c:414
void input_exit(void)
exits the input subsystem.
Definition: input.c:334
const char * input_getKeybindDescription(const char *keybind)
Gets the description of the keybinding.
Definition: input.c:587
double player_left
Definition: player.c:120
#define KEY(s)
Definition: input.c:650
#define NODEAD()
Definition: input.c:659
SDL_Keymod input_translateMod(SDL_Keymod mod)
Translates SDL modifier to Naev modifier.
Definition: input.c:602
const int input_numbinds
Definition: input.c:132
void input_enableAll(void)
Enables all the keybinds.
Definition: input.c:342
#define NOHYP()
Definition: input.c:652
int input_clickedJump(int jump, int autonav)
Performs an appropriate action when a jump point is clicked.
Definition: input.c:1326
const char * input_modToText(SDL_Keymod mod)
Gets the human readable version of mod.
Definition: input.c:521
void input_getKeybindDisplay(const char *keybind, char *buf, int len)
Gets the display name (translated and human-readable) of a keybind.
Definition: input.c:458
static unsigned int input_revLast
Definition: input.c:139
void input_mouseHide(void)
Hides the mouse.
Definition: input.c:382
Handles the important game menus.
void menu_small(int docheck, int info, int options, int allowsave)
Opens the small in-game menu.
Definition: menu.c:416
Header file with generic functions and naev-specifics.
#define pow2(x)
Definition: naev.h:46
#define FABS(x)
Definition: naev.h:37
#define MAX(x, y)
Definition: naev.h:39
int scnprintf(char *text, size_t maxlen, const char *fmt,...)
Like snprintf(), but returns the number of characters ACTUALLY "printed" into the buffer....
Definition: nstring.c:178
void gl_windowToScreenPos(int *sx, int *sy, int wx, int wy)
Translates the window position to screen position.
Definition: opengl.c:616
void gl_screenToGameCoords(double *nx, double *ny, int bx, int by)
Converts screen coordinates to in-game coordinates.
void pause_player(void)
Pauses the game and marks the pause as player-initiated.
Definition: pause.c:72
int paused
Definition: pause.c:21
void unpause_game(void)
Unpauses the game.
Definition: pause.c:46
double pilot_getNearestPos(const Pilot *p, unsigned int *tp, double x, double y, int disabled)
Get the nearest pilot to a pilot from a certain position.
Definition: pilot.c:492
Pilot * pilot_get(unsigned int id)
Pulls a pilot out of the pilot_stack based on ID.
Definition: pilot.c:589
void pilot_afterburnOver(Pilot *p)
Deactivates the afterburner.
void pilot_afterburn(Pilot *p)
Activate the afterburner.
void player_stealth(void)
Input binding for toggling stealth for the player.
Definition: player.c:4565
void player_weapSetPress(int id, double value, int repeat)
Handles keyboard events involving the player's weapon-set keys. It's valid to call this while gamepla...
Definition: player.c:1392
void player_autohail(void)
Automatically tries to hail a pilot that hailed the player.
Definition: player.c:2405
void player_accel(double acc)
Start accelerating.
Definition: player.c:2088
void player_targetEscort(int prev)
Targets the pilot.
Definition: player.c:2232
void player_targetAsteroidSet(int field, int id)
Sets the player's target asteroid.
Definition: player.c:1492
void player_targetSet(unsigned int id)
Sets the player's target.
Definition: player.c:2112
void player_hailSpob(void)
Opens communication with the player's spob target.
Definition: player.c:2386
void player_resetSpeed(void)
Resets the player speed stuff.
Definition: player.c:1416
void player_targetHyperspaceSet(int id, int nomsg)
Sets the player's hyperspace target.
Definition: player.c:1778
void player_targetHyperspace(void)
Gets a hyperspace target.
Definition: player.c:1813
void player_hyperspacePreempt(int preempt)
Enables or disables jump points preempting spobs in autoface and target clearing.
Definition: player.c:1851
void player_toggleMouseFly(void)
Toggles mouse flying.
Definition: player.c:2438
void player_targetNearest(void)
Player targets nearest pilot.
Definition: player.c:2275
void player_restoreControl(int reason, const char *str)
Aborts autonav and other states that take control of the ship.
Definition: player.c:1429
int player_jump(void)
Actually attempts to jump in hyperspace.
Definition: player.c:1900
void player_targetSpobSet(int id)
Sets the player's target spob.
Definition: player.c:1453
void player_accelOver(void)
Done accelerating.
Definition: player.c:2102
int player_land(int loud)
Try to land or target closest spob if no land target.
Definition: player.c:1549
Player_t player
Definition: player.c:73
void player_brake(void)
Starts braking or active cooldown.
Definition: player.c:2461
void player_targetPrev(int mode)
Cycles to previous target.
Definition: player.c:2190
void player_targetClear(void)
Clears the player's ship, spob or hyperspace target, in that order.
Definition: player.c:2198
void player_targetHostile(void)
Targets the nearest hostile enemy to the player.
Definition: player.c:2141
void player_screenshot(void)
Takes a screenshot.
Definition: player.c:2299
void player_targetSpob(void)
Cycle through spob targets.
Definition: player.c:1516
void player_targetNext(int mode)
Cycles to next target.
Definition: player.c:2180
void player_hail(void)
Opens communication with the player's target.
Definition: player.c:2358
void player_autonavStartWindow(unsigned int wid, const char *str)
Starts autonav and closes the window.
void player_autonavPos(double x, double y)
Starts autonav with a local position destination.
void player_autonavStart(void)
Starts autonav.
void player_autonavPil(unsigned int p)
Starts autonav with a pilot to follow.
void player_autonavSpob(const char *name, int tryland)
Starts autonav with a spob destination.
static const double d[]
Definition: rng.c:273
double system_getClosest(const StarSystem *sys, int *pnt, int *jp, int *ast, int *fie, double x, double y)
Gets the closest feature to a position in the system.
Definition: space.c:655
int space_canHyperspace(const Pilot *p)
Checks to make sure if pilot is far enough away to hyperspace.
Definition: space.c:437
StarSystem * cur_system
Definition: space.c:105
void spob_updateLand(Spob *p)
Updates the land possibilities of a spob.
Definition: space.c:1896
Represents an asteroid field anchor.
Definition: asteroid.h:100
Asteroid * asteroids
Definition: asteroid.h:105
Represents a single asteroid.
Definition: asteroid.h:76
const glTexture * gfx
Definition: asteroid.h:82
The actual hook parameter.
Definition: hook.h:35
const char * str
Definition: hook.h:39
union HookParam::@4 u
HookParamType type
Definition: hook.h:36
double num
Definition: hook.h:38
int b
Definition: hook.h:40
Naev Keybinding.
Definition: input.c:43
int disabled
Definition: input.c:44
SDL_Keycode key
Definition: input.c:47
const char * name
Definition: input.c:45
KeybindType type
Definition: input.c:46
SDL_Keymod mod
Definition: input.c:48
The representation of an in-game pilot.
Definition: pilot.h:210
Solid * solid
Definition: pilot.h:220
int nav_hyperspace
Definition: pilot.h:337
unsigned int target
Definition: pilot.h:334
int nav_spob
Definition: pilot.h:336
double zoom_speed
Definition: conf.h:137
unsigned int repeat_freq
Definition: conf.h:131
double mouse_doubleclick
Definition: conf.h:155
unsigned int repeat_delay
Definition: conf.h:130
unsigned int doubletap_sens
Definition: conf.h:152
Pilot * p
Definition: player.h:101
double mousex
Definition: player.h:113
double speed
Definition: player.h:115
double mousey
Definition: player.h:114
vec2 pos
Definition: physics.h:22
Represents a Space Object (SPOB), including and not limited to planets, stations, wormholes,...
Definition: space.h:88
double radius
Definition: space.h:94
char * name
Definition: space.h:90
double sw
Definition: opengl_tex.h:44
double sh
Definition: opengl_tex.h:45
double y
Definition: vec2.h:34
double x
Definition: vec2.h:33
int toolkit_isOpen(void)
Checks to see if the toolkit is open.
Definition: toolkit.c:95
unsigned int window_get(const char *wdwname)
Gets the ID of a window.
Definition: toolkit.c:671
int toolkit_input(SDL_Event *event)
Toolkit input handled here.
Definition: toolkit.c:1674