naev 0.11.5
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/* keybinding structure */
41typedef struct Keybind_ {
43 const char *name;
44 KeybindType type;
45 SDL_Keycode key;
46 SDL_Keymod mod;
47} Keybind;
48
49/* name of each keybinding */
50const char *keybind_info[][3] = {
51 /* Movement */
52 { "accel", N_("Accelerate"), N_("Makes your ship accelerate forward.") },
53 { "left", N_("Turn Left"), N_("Makes your ship turn left.") },
54 { "right", N_("Turn Right"), N_("Makes your ship turn right.") },
55 { "reverse", N_("Reverse"), N_("Makes your ship face the direction you're moving from. Useful for braking.") },
56 { "stealth", N_("Stealth"), N_("Tries to enter stealth mode.") },
57 /* Targeting */
58 { "target_next", N_("Target Next"), N_("Cycles through ship targets.") },
59 { "target_prev", N_("Target Previous"), N_("Cycles backwards through ship targets.") },
60 { "target_nearest", N_("Target Nearest"), N_("Targets the nearest non-disabled ship.") },
61 { "target_nextHostile", N_("Target Next Hostile"), N_("Cycles through hostile ship targets.") },
62 { "target_prevHostile", N_("Target Previous Hostile"), N_("Cycles backwards through hostile ship targets.") },
63 { "target_hostile", N_("Target Nearest Hostile"), N_("Targets the nearest hostile ship.") },
64 { "target_clear", N_("Clear Target"), N_("Clears the currently-targeted ship, space object, or jump point.") },
65 /* Fighting */
66 { "primary", N_("Fire Primary Weapon"), N_("Fires primary weapons.") },
67 { "face", N_("Face Target"), N_("Faces the targeted ship if one is targeted, otherwise faces targeted space object, or jump point.") },
68 /* Secondary Weapons */
69 { "secondary", N_("Fire Secondary Weapon"), N_("Fires secondary weapons.") },
70 { "weapset1", N_("Weapon Set 1"), N_("Activates weapon set 1.") },
71 { "weapset2", N_("Weapon Set 2"), N_("Activates weapon set 2.") },
72 { "weapset3", N_("Weapon Set 3"), N_("Activates weapon set 3.") },
73 { "weapset4", N_("Weapon Set 4"), N_("Activates weapon set 4.") },
74 { "weapset5", N_("Weapon Set 5"), N_("Activates weapon set 5.") },
75 { "weapset6", N_("Weapon Set 6"), N_("Activates weapon set 6.") },
76 { "weapset7", N_("Weapon Set 7"), N_("Activates weapon set 7.") },
77 { "weapset8", N_("Weapon Set 8"), N_("Activates weapon set 8.") },
78 { "weapset9", N_("Weapon Set 9"), N_("Activates weapon set 9.") },
79 { "weapset0", N_("Weapon Set 0"), N_("Activates weapon set 0.") },
80 /* Escorts */
81 { "e_targetNext", N_("Target Next Escort"), N_("Cycles through your escorts.") },
82 { "e_targetPrev", N_("Target Previous Escort"), N_("Cycles backwards through your escorts.") },
83 { "e_attack", N_("Escort Attack Command"), N_("Orders escorts to attack your target.") },
84 { "e_hold", N_("Escort Hold Command"), N_("Orders escorts to hold their formation.") },
85 { "e_return", N_("Escort Return Command"), N_("Orders escorts to return to your ship hangars.") },
86 { "e_clear", N_("Escort Clear Commands"), N_("Clears your escorts of commands.") },
87 /* Space Navigation */
88 { "autonav", N_("Autonavigation On"), N_("Initializes the autonavigation system.") },
89 { "target_spob", N_("Target Space object"), N_("Cycles through space object targets.") },
90 { "approach", N_("Approach"), N_("Attempts to approach the targeted ship or space object, or targets the nearest landable space object. Requests landing permission if necessary. Prioritizes ships over space objects.") },
91 { "thyperspace", N_("Target Jump Point"), N_("Cycles through jump points.") },
92 { "starmap", N_("Star Map"), N_("Opens the star map.") },
93 { "jump", N_("Initiate Jump"), N_("Attempts to jump via a jump point.") },
94 { "overlay", N_("Overlay Map"), N_("Opens the in-system overlay map.") },
95 { "mousefly", N_("Mouse Flight"), N_("Toggles mouse flying.") },
96 { "cooldown", N_("Active Cooldown"), N_("Begins active cooldown.") },
97 /* Communication */
98 { "log_up", N_("Log Scroll Up"), N_("Scrolls the log upwards.") },
99 { "log_down", N_("Log Scroll Down"), N_("Scrolls the log downwards.") },
100 { "hail", N_("Hail Target"), N_("Attempts to initialize communication with the targeted ship.") },
101 { "autohail", N_("Autohail"), N_("Automatically initialize communication with a ship that is hailing you.") },
102 /* Misc. */
103 { "mapzoomin", N_("Radar Zoom In"), N_("Zooms in on the radar.") },
104 { "mapzoomout", N_("Radar Zoom Out"), N_("Zooms out on the radar.") },
105 { "screenshot", N_("Screenshot"), N_("Takes a screenshot.") },
106 { "togglefullscreen", N_("Toggle Fullscreen"), N_("Toggles between windowed and fullscreen mode.") },
107 { "pause", N_("Pause"), N_("Pauses the game.") },
108 { "speed", N_("Toggle Speed"), N_("Toggles speed modifier.") },
109 { "menu", N_("Small Menu"), N_("Opens the small in-game menu.") },
110 { "info", N_("Information Menu"), N_("Opens the information menu.") },
111 { "console", N_("Lua Console"), N_("Opens the Lua console.") },
112 { "switchtab1", N_("Switch Tab 1"), N_("Switches to tab 1.") },
113 { "switchtab2", N_("Switch Tab 2"), N_("Switches to tab 2.") },
114 { "switchtab3", N_("Switch Tab 3"), N_("Switches to tab 3.") },
115 { "switchtab4", N_("Switch Tab 4"), N_("Switches to tab 4.") },
116 { "switchtab5", N_("Switch Tab 5"), N_("Switches to tab 5.") },
117 { "switchtab6", N_("Switch Tab 6"), N_("Switches to tab 6.") },
118 { "switchtab7", N_("Switch Tab 7"), N_("Switches to tab 7.") },
119 { "switchtab8", N_("Switch Tab 8"), N_("Switches to tab 8.") },
120 { "switchtab9", N_("Switch Tab 9"), N_("Switches to tab 9.") },
121 { "switchtab0", N_("Switch Tab 0"), N_("Switches to tab 0.") },
122 /* Console-main. */
123 { "paste", N_("Paste"), N_("Paste from the operating system's clipboard.") },
124 /* Must terminate in NULL. */
125 { NULL, NULL, NULL }
126};
129const int input_numbinds = ( sizeof( keybind_info ) / sizeof( keybind_info[ 0 ] ) ) - 1;
130static Keybind *input_paste;
131
132/*
133 * accel hacks
134 */
135static int doubletap_key = -1;
136static unsigned int doubletap_t = 0;
138/*
139 * Key repeat hack.
140 */
141static int repeat_key = -1;
142static unsigned int repeat_keyTimer = 0;
143static unsigned int repeat_keyCounter = 0;
145/*
146 * Mouse.
147 */
148static double input_mouseTimer = 1.;
149static int input_mouseCounter = 1;
150static unsigned int input_mouseClickLast = 0;
151static void *input_lastClicked = NULL;
153/*
154 * from player.c
155 */
156extern double player_left;
157extern double player_right;
159/*
160 * Prototypes.
161 */
162static void input_key( int keynum, double value, double kabs, int repeat );
163static void input_clickZoom( double modifier );
164static void input_clickevent( SDL_Event* event );
165static void input_mouseMove( SDL_Event* event );
166
172void input_setDefault ( int wasd )
173{
174 /* Movement */
175 if (wasd) {
176 input_setKeybind( "accel", KEYBIND_KEYBOARD, SDLK_w, NMOD_ANY );
177 input_setKeybind( "left", KEYBIND_KEYBOARD, SDLK_a, NMOD_ANY );
178 input_setKeybind( "right", KEYBIND_KEYBOARD, SDLK_d, NMOD_ANY );
179 input_setKeybind( "reverse", KEYBIND_KEYBOARD, SDLK_s, NMOD_ANY );
180 }
181 else {
182 input_setKeybind( "accel", KEYBIND_KEYBOARD, SDLK_UP, NMOD_ANY );
183 input_setKeybind( "left", KEYBIND_KEYBOARD, SDLK_LEFT, NMOD_ANY );
184 input_setKeybind( "right", KEYBIND_KEYBOARD, SDLK_RIGHT, NMOD_ANY );
185 input_setKeybind( "reverse", KEYBIND_KEYBOARD, SDLK_DOWN, NMOD_ANY );
186 }
187 input_setKeybind( "stealth", KEYBIND_KEYBOARD, SDLK_f, NMOD_NONE );
188
189 /* Targeting */
190 if (wasd) {
191 input_setKeybind( "target_next", KEYBIND_KEYBOARD, SDLK_e, NMOD_CTRL );
192 input_setKeybind( "target_prev", KEYBIND_KEYBOARD, SDLK_q, NMOD_CTRL );
193 input_setKeybind( "target_nearest", KEYBIND_KEYBOARD, SDLK_t, NMOD_ANY );
194 input_setKeybind( "target_nextHostile", KEYBIND_NULL, SDLK_UNKNOWN, NMOD_NONE );
195 input_setKeybind( "target_prevHostile", KEYBIND_NULL, SDLK_UNKNOWN, NMOD_NONE );
196 input_setKeybind( "target_hostile", KEYBIND_KEYBOARD, SDLK_r, NMOD_ANY );
197 input_setKeybind( "target_clear", KEYBIND_KEYBOARD, SDLK_c, NMOD_ANY );
198 }
199 else {
200 input_setKeybind( "target_next", KEYBIND_KEYBOARD, SDLK_t, NMOD_NONE );
201 input_setKeybind( "target_prev", KEYBIND_KEYBOARD, SDLK_t, NMOD_CTRL );
202 input_setKeybind( "target_nearest", KEYBIND_KEYBOARD, SDLK_n, NMOD_NONE );
203 input_setKeybind( "target_nextHostile", KEYBIND_KEYBOARD, SDLK_r, NMOD_CTRL );
204 input_setKeybind( "target_prevHostile", KEYBIND_NULL, SDLK_UNKNOWN, NMOD_NONE );
205 input_setKeybind( "target_hostile", KEYBIND_KEYBOARD, SDLK_r, NMOD_NONE );
206 input_setKeybind( "target_clear", KEYBIND_KEYBOARD, SDLK_BACKSPACE, NMOD_ANY );
207 }
208
209 /* Combat */
210 input_setKeybind( "primary", KEYBIND_KEYBOARD, SDLK_SPACE, NMOD_ANY );
211
212 if (wasd)
213 input_setKeybind( "face", KEYBIND_KEYBOARD, SDLK_q, NMOD_NONE );
214 else
215 input_setKeybind( "face", KEYBIND_KEYBOARD, SDLK_a, NMOD_ANY );
216
217 /* Secondary Weapons */
218 input_setKeybind( "secondary", KEYBIND_KEYBOARD, SDLK_LSHIFT, NMOD_ANY );
219 input_setKeybind( "weapset1", KEYBIND_KEYBOARD, SDLK_1, NMOD_ANY );
220 input_setKeybind( "weapset2", KEYBIND_KEYBOARD, SDLK_2, NMOD_ANY );
221 input_setKeybind( "weapset3", KEYBIND_KEYBOARD, SDLK_3, NMOD_ANY );
222 input_setKeybind( "weapset4", KEYBIND_KEYBOARD, SDLK_4, NMOD_ANY );
223 input_setKeybind( "weapset5", KEYBIND_KEYBOARD, SDLK_5, NMOD_ANY );
224 input_setKeybind( "weapset6", KEYBIND_KEYBOARD, SDLK_6, NMOD_ANY );
225 input_setKeybind( "weapset7", KEYBIND_KEYBOARD, SDLK_7, NMOD_ANY );
226 input_setKeybind( "weapset8", KEYBIND_KEYBOARD, SDLK_8, NMOD_ANY );
227 input_setKeybind( "weapset9", KEYBIND_KEYBOARD, SDLK_9, NMOD_ANY );
228 input_setKeybind( "weapset0", KEYBIND_KEYBOARD, SDLK_0, NMOD_ANY );
229 /* Escorts */
230 input_setKeybind( "e_targetNext", KEYBIND_NULL, SDLK_UNKNOWN, NMOD_NONE );
231 input_setKeybind( "e_targetPrev", KEYBIND_NULL, SDLK_UNKNOWN, NMOD_NONE );
232 input_setKeybind( "e_attack", KEYBIND_KEYBOARD, SDLK_END, NMOD_ANY );
233 input_setKeybind( "e_hold", KEYBIND_KEYBOARD, SDLK_INSERT, NMOD_ANY );
234 input_setKeybind( "e_return", KEYBIND_KEYBOARD, SDLK_DELETE, NMOD_ANY );
235 input_setKeybind( "e_clear", KEYBIND_KEYBOARD, SDLK_HOME, NMOD_ANY );
236 /* Space Navigation */
237 input_setKeybind( "autonav", KEYBIND_KEYBOARD, SDLK_j, NMOD_CTRL );
238 input_setKeybind( "target_spob", KEYBIND_KEYBOARD, SDLK_p, NMOD_NONE );
239 input_setKeybind( "approach", KEYBIND_KEYBOARD, SDLK_l, NMOD_NONE );
240 input_setKeybind( "thyperspace", KEYBIND_KEYBOARD, SDLK_h, NMOD_NONE );
241 input_setKeybind( "starmap", KEYBIND_KEYBOARD, SDLK_m, NMOD_NONE );
242 input_setKeybind( "jump", KEYBIND_KEYBOARD, SDLK_j, NMOD_NONE );
243 input_setKeybind( "overlay", KEYBIND_KEYBOARD, SDLK_TAB, NMOD_ANY );
244 input_setKeybind( "mousefly", KEYBIND_KEYBOARD, SDLK_x, NMOD_CTRL );
245 input_setKeybind( "cooldown", KEYBIND_KEYBOARD, SDLK_s, NMOD_CTRL );
246 /* Communication */
247 input_setKeybind( "log_up", KEYBIND_KEYBOARD, SDLK_PAGEUP, NMOD_ANY );
248 input_setKeybind( "log_down", KEYBIND_KEYBOARD, SDLK_PAGEDOWN, NMOD_ANY );
249 input_setKeybind( "hail", KEYBIND_KEYBOARD, SDLK_y, NMOD_NONE );
250 input_setKeybind( "autohail", KEYBIND_KEYBOARD, SDLK_y, NMOD_CTRL );
251 /* Misc. */
252 input_setKeybind( "mapzoomin", KEYBIND_KEYBOARD, SDLK_KP_PLUS, NMOD_ANY );
253 input_setKeybind( "mapzoomout", KEYBIND_KEYBOARD, SDLK_KP_MINUS, NMOD_ANY );
254 input_setKeybind( "screenshot", KEYBIND_KEYBOARD, SDLK_KP_MULTIPLY, NMOD_ANY );
255 input_setKeybind( "togglefullscreen", KEYBIND_KEYBOARD, SDLK_F11, NMOD_ANY );
256 input_setKeybind( "pause", KEYBIND_KEYBOARD, SDLK_PAUSE, NMOD_ANY );
257
258 input_setKeybind( "speed", KEYBIND_KEYBOARD, SDLK_BACKQUOTE, NMOD_ANY );
259 input_setKeybind( "menu", KEYBIND_KEYBOARD, SDLK_ESCAPE, NMOD_ANY );
260 input_setKeybind( "info", KEYBIND_KEYBOARD, SDLK_i, NMOD_NONE );
261 input_setKeybind( "console", KEYBIND_KEYBOARD, SDLK_F2, NMOD_ANY );
262 input_setKeybind( "switchtab1", KEYBIND_KEYBOARD, SDLK_1, NMOD_ALT );
263 input_setKeybind( "switchtab2", KEYBIND_KEYBOARD, SDLK_2, NMOD_ALT );
264 input_setKeybind( "switchtab3", KEYBIND_KEYBOARD, SDLK_3, NMOD_ALT );
265 input_setKeybind( "switchtab4", KEYBIND_KEYBOARD, SDLK_4, NMOD_ALT );
266 input_setKeybind( "switchtab5", KEYBIND_KEYBOARD, SDLK_5, NMOD_ALT );
267 input_setKeybind( "switchtab6", KEYBIND_KEYBOARD, SDLK_6, NMOD_ALT );
268 input_setKeybind( "switchtab7", KEYBIND_KEYBOARD, SDLK_7, NMOD_ALT );
269 input_setKeybind( "switchtab8", KEYBIND_KEYBOARD, SDLK_8, NMOD_ALT );
270 input_setKeybind( "switchtab9", KEYBIND_KEYBOARD, SDLK_9, NMOD_ALT );
271 input_setKeybind( "switchtab0", KEYBIND_KEYBOARD, SDLK_0, NMOD_ALT );
272 input_setKeybind( "paste", KEYBIND_KEYBOARD, SDLK_v, NMOD_CTRL );
273}
274
278void input_init (void)
279{
280 /* Window. */
281 SDL_EventState( SDL_SYSWMEVENT, SDL_DISABLE );
282
283 /* Keyboard. */
284 SDL_EventState( SDL_KEYDOWN, SDL_ENABLE );
285 SDL_EventState( SDL_KEYUP, SDL_ENABLE );
286
287 /* Mice. */
288 SDL_EventState( SDL_MOUSEMOTION, SDL_ENABLE );
289 SDL_EventState( SDL_MOUSEBUTTONDOWN, SDL_ENABLE );
290 SDL_EventState( SDL_MOUSEBUTTONUP, SDL_ENABLE );
291
292 /* Joystick, enabled in joystick.c if needed. */
293 SDL_EventState( SDL_JOYAXISMOTION, SDL_DISABLE );
294 SDL_EventState( SDL_JOYHATMOTION, SDL_DISABLE );
295 SDL_EventState( SDL_JOYBUTTONDOWN, SDL_DISABLE );
296 SDL_EventState( SDL_JOYBUTTONUP, SDL_DISABLE );
297
298 /* Quit. */
299 SDL_EventState( SDL_QUIT, SDL_ENABLE );
300
301 /* Window. */
302 SDL_EventState( SDL_WINDOWEVENT, SDL_ENABLE );
303
304 /* Keyboard. */
305 SDL_EventState( SDL_TEXTINPUT, SDL_DISABLE); /* Enabled on a per-widget basis. */
306
307 /* Mouse. */
308 SDL_EventState( SDL_MOUSEWHEEL, SDL_ENABLE );
309
310 input_keybinds = malloc( input_numbinds * sizeof(Keybind) );
311
312 /* Create safe null keybinding for each. */
313 for (int i=0; i<input_numbinds; i++) {
314 Keybind *temp = &input_keybinds[i];
315 memset( temp, 0, sizeof(Keybind) );
316 temp->name = keybind_info[i][0];
317 temp->type = KEYBIND_NULL;
318 temp->key = SDLK_UNKNOWN;
319 temp->mod = NMOD_NONE;
320
321 if (strcmp(temp->name,"paste")==0)
322 input_paste = temp;
323 }
324}
325
329void input_exit (void)
330{
331 free(input_keybinds);
332}
333
338{
339 for (int i=0; keybind_info[i][0] != NULL; i++)
340 input_keybinds[i].disabled = 0;
341}
342
347{
348 for (int i=0; keybind_info[i][0] != NULL; i++)
349 input_keybinds[i].disabled = 1;
350}
351
355void input_toggleEnable( const char *key, int enable )
356{
357 for (int i=0; i<input_numbinds; i++) {
358 if (strcmp(key, input_keybinds[i].name)==0) {
359 input_keybinds[i].disabled = !enable;
360 break;
361 }
362 }
363}
364
369{
370 SDL_ShowCursor( SDL_ENABLE );
372}
373
378{
380 if (input_mouseCounter <= 0) {
383 }
384}
385
392SDL_Keycode input_keyConv( const char *name )
393{
394 SDL_Keycode k = SDL_GetKeyFromName( name );
395 if (k == SDLK_UNKNOWN)
396 WARN(_("Keyname '%s' doesn't match any key."), name);
397
398 return k;
399}
400
409void input_setKeybind( const char *keybind, KeybindType type, SDL_Keycode key, SDL_Keymod mod )
410{
411 for (int i=0; i<input_numbinds; i++) {
412 if (strcmp(keybind, input_keybinds[i].name)==0) {
413 input_keybinds[i].type = type;
414 input_keybinds[i].key = key;
415 /* Non-keyboards get mod NMOD_ANY to always match. */
416 input_keybinds[i].mod = (type==KEYBIND_KEYBOARD) ? mod : NMOD_ANY;
417 return;
418 }
419 }
420 WARN(_("Unable to set keybinding '%s', that command doesn't exist"), keybind);
421}
422
431SDL_Keycode input_getKeybind( const char *keybind, KeybindType *type, SDL_Keymod *mod )
432{
433 for (int i=0; i<input_numbinds; i++) {
434 if (strcmp(keybind, input_keybinds[i].name)==0) {
435 if (type != NULL)
436 (*type) = input_keybinds[i].type;
437 if (mod != NULL)
438 (*mod) = input_keybinds[i].mod;
439 return input_keybinds[i].key;
440 }
441 }
442 WARN(_("Unable to get keybinding '%s', that command doesn't exist"), keybind);
443 return (SDL_Keycode)-1;
444}
445
453void input_getKeybindDisplay( const char *keybind, char *buf, int len )
454{
455 /* Get the keybinding. */
456 KeybindType type = KEYBIND_NULL;
457 SDL_Keymod mod = NMOD_NONE;
458 SDL_Keycode key = input_getKeybind( keybind, &type, &mod );
459
460 /* Handle type. */
461 switch (type) {
462 case KEYBIND_NULL:
463 strncpy( buf, _("Not bound"), len );
464 break;
465
466 case KEYBIND_KEYBOARD:
467 {
468 int p = 0;
469 /* Handle mod. */
470 if ((mod != NMOD_NONE) && (mod != NMOD_ANY))
471 p += scnprintf( &buf[p], len-p, "%s + ", input_modToText(mod) );
472 /* Print key. Special-case ASCII letters (use uppercase, unlike SDL_GetKeyName.). */
473 if (key < 0x100 && isalpha(key))
474 p += scnprintf( &buf[p], len-p, "%c", toupper(key) );
475 else
476 p += scnprintf( &buf[p], len-p, "%s", pgettext_var("keyname", SDL_GetKeyName(key)) );
477 break;
478 }
479
480 case KEYBIND_JBUTTON:
481 snprintf( buf, len, _("joy button %d"), key );
482 break;
483
484 case KEYBIND_JHAT_UP:
485 snprintf( buf, len, _("joy hat %d up"), key );
486 break;
487
488 case KEYBIND_JHAT_DOWN:
489 snprintf( buf, len, _("joy hat %d down"), key );
490 break;
491
492 case KEYBIND_JHAT_LEFT:
493 snprintf( buf, len, _("joy hat %d left"), key );
494 break;
495
496 case KEYBIND_JHAT_RIGHT:
497 snprintf( buf, len, _("joy hat %d right"), key );
498 break;
499
500 case KEYBIND_JAXISPOS:
501 snprintf( buf, len, _("joy axis %d-"), key );
502 break;
503
504 case KEYBIND_JAXISNEG:
505 snprintf( buf, len, _("joy axis %d+"), key );
506 break;
507 }
508}
509
516const char* input_modToText( SDL_Keymod mod )
517{
518 switch ((int)mod) {
519 case NMOD_NONE: return _("None");
520 case NMOD_CTRL: return _("Ctrl");
521 case NMOD_SHIFT: return _("Shift");
522 case NMOD_ALT: return _("Alt");
523 case NMOD_META: return _("Meta");
524 case NMOD_ANY: return _("Any");
525 default: return _("unknown");
526 }
527}
528
537const char *input_keyAlreadyBound( KeybindType type, SDL_Keycode key, SDL_Keymod mod )
538{
539 for (int i=0; i<input_numbinds; i++) {
540 Keybind *k = &input_keybinds[i];
541
542 /* Type must match. */
543 if (k->type != type)
544 continue;
545
546 /* Must match key. */
547 if (key != k->key)
548 continue;
549
550 /* Handle per case. */
551 switch (type) {
552 case KEYBIND_KEYBOARD:
553 if ((k->mod == NMOD_ANY) || (mod == NMOD_ANY) ||
554 (k->mod == mod))
555 return keybind_info[i][0];
556 break;
557
558 case KEYBIND_JAXISPOS:
559 case KEYBIND_JAXISNEG:
560 case KEYBIND_JBUTTON:
561 case KEYBIND_JHAT_UP:
562 case KEYBIND_JHAT_DOWN:
563 case KEYBIND_JHAT_LEFT:
564 case KEYBIND_JHAT_RIGHT:
565 return keybind_info[i][0];
566
567 default:
568 break;
569 }
570 }
571
572 /* Not found. */
573 return NULL;
574}
575
582const char* input_getKeybindDescription( const char *keybind )
583{
584 for (int i=0; keybind_info[i][0] != NULL; i++)
585 if (strcmp(keybind, input_keybinds[i].name)==0)
586 return _(keybind_info[i][2]);
587 WARN(_("Unable to get keybinding description '%s', that command doesn't exist"), keybind);
588 return NULL;
589}
590
597SDL_Keymod input_translateMod( SDL_Keymod mod )
598{
599 SDL_Keymod mod_filtered = 0;
600 if (mod & (KMOD_LSHIFT | KMOD_RSHIFT))
601 mod_filtered |= NMOD_SHIFT;
602 if (mod & (KMOD_LCTRL | KMOD_RCTRL))
603 mod_filtered |= NMOD_CTRL;
604 if (mod & (KMOD_LALT | KMOD_RALT))
605 mod_filtered |= NMOD_ALT;
606 if (mod & (KMOD_LGUI | KMOD_RGUI))
607 mod_filtered |= NMOD_META;
608 return mod_filtered;
609}
610
614void input_update( double dt )
615{
616 if (input_mouseTimer > 0.) {
617 input_mouseTimer -= dt;
618
619 /* Hide if necessary. */
620 if ((input_mouseTimer < 0.) && (input_mouseCounter <= 0))
621 SDL_ShowCursor( SDL_DISABLE );
622 }
623
624 /* Key repeat if applicable. */
625 if (conf.repeat_delay != 0) {
626 unsigned int t;
627
628 /* Key must be repeating. */
629 if (repeat_key == -1)
630 return;
631
632 /* Get time. */
633 t = SDL_GetTicks();
634
635 /* Should be repeating. */
637 return;
638
639 /* Key repeat. */
641 input_key( repeat_key, KEY_PRESS, 0., 1 );
642 }
643}
644
645#define KEY(s) (strcmp(input_keybinds[keynum].name,s)==0)
646#define INGAME() (!toolkit_isOpen() && ((value==KEY_RELEASE) || !player_isFlag(PLAYER_CINEMATICS)))
647#define NOHYP() \
648 ((player.p != NULL) && !pilot_isFlag(player.p,PILOT_HYP_PREP) &&\
649 !pilot_isFlag(player.p,PILOT_HYP_BEGIN) &&\
650 !pilot_isFlag(player.p,PILOT_HYPERSPACE))
651#define NODEAD() ((player.p != NULL) && !pilot_isFlag(player.p,PILOT_DEAD))
652#define NOLAND() ((player.p != NULL) && (!landed && !pilot_isFlag(player.p,PILOT_LANDING)))
661static void input_key( int keynum, double value, double kabs, int repeat )
662{
663 HookParam hparam[3];
664 int isdoubletap = 0;
665
666 /* Repetition stuff. */
667 if (conf.repeat_delay != 0) {
668 if ((value==KEY_PRESS) && !repeat) {
669 repeat_key = keynum;
670 repeat_keyTimer = SDL_GetTicks();
672 }
673 else if (value==KEY_RELEASE) {
674 repeat_key = -1;
675 repeat_keyTimer = 0;
677 }
678 }
679
680 /* Detect if double tap. */
681 if (value==KEY_PRESS) {
682 unsigned int t = SDL_GetTicks();
683 if ((keynum == doubletap_key) && (t-doubletap_t <= conf.doubletap_sens))
684 isdoubletap = 1;
685 else {
686 doubletap_key = keynum;
687 doubletap_t = t;
688 }
689 }
690
691 /*
692 * movement
693 */
694 /* accelerating */
695 if (KEY("accel") && !repeat) {
696 if (kabs >= 0.) {
697 player_restoreControl( PINPUT_MOVEMENT, NULL );
698 player_accel(kabs);
699 }
700 else { /* prevent it from getting stuck */
701 if (isdoubletap) {
702 if (NODEAD()) {
703 pilot_outfitLOnkeydoubletap( player.p, OUTFIT_KEY_ACCEL );
705 }
706 }
707 else if (value==KEY_RELEASE) {
708 if (NODEAD()) {
709 pilot_outfitLOnkeyrelease( player.p, OUTFIT_KEY_ACCEL );
711 }
712 }
713
714 if (value==KEY_PRESS) {
715 player_restoreControl( PINPUT_MOVEMENT, NULL );
716 player_setFlag(PLAYER_ACCEL);
717 player_accel(1.);
718 }
719 else if (value==KEY_RELEASE) {
720 player_rmFlag(PLAYER_ACCEL);
721 if (!player_isFlag(PLAYER_REVERSE))
723 }
724 }
725
726 /* turning left */
727 } else if (KEY("left") && !repeat) {
728 if (isdoubletap) {
729 if (NODEAD())
730 pilot_outfitLOnkeydoubletap( player.p, OUTFIT_KEY_LEFT );
731 }
732 else if (value==KEY_RELEASE) {
733 if (NODEAD())
734 pilot_outfitLOnkeyrelease( player.p, OUTFIT_KEY_LEFT );
735 }
736
737 if (kabs >= 0.) {
738 player_restoreControl( PINPUT_MOVEMENT, NULL );
739 player_setFlag(PLAYER_TURN_LEFT);
740 player_left = kabs;
741 }
742 else {
743 /* set flags for facing correction */
744 if (value==KEY_PRESS) {
745 player_restoreControl( PINPUT_MOVEMENT, NULL );
746 player_setFlag(PLAYER_TURN_LEFT);
747 player_left = 1.;
748 }
749 else if (value==KEY_RELEASE) {
750 player_rmFlag(PLAYER_TURN_LEFT);
751 player_left = 0.;
752 }
753 }
754
755 /* turning right */
756 } else if (KEY("right") && !repeat) {
757 if (isdoubletap) {
758 if (NODEAD())
759 pilot_outfitLOnkeydoubletap( player.p, OUTFIT_KEY_RIGHT );
760 }
761 else if (value==KEY_RELEASE) {
762 if (NODEAD())
763 pilot_outfitLOnkeyrelease( player.p, OUTFIT_KEY_RIGHT );
764 }
765
766 if (kabs >= 0.) {
767 player_restoreControl( PINPUT_MOVEMENT, NULL );
768 player_setFlag(PLAYER_TURN_RIGHT);
769 player_right = kabs;
770 }
771 else {
772 /* set flags for facing correction */
773 if (value==KEY_PRESS) {
774 player_restoreControl( PINPUT_MOVEMENT, NULL );
775 player_setFlag(PLAYER_TURN_RIGHT);
776 player_right = 1.;
777 }
778 else if (value==KEY_RELEASE) {
779 player_rmFlag(PLAYER_TURN_RIGHT);
780 player_right = 0.;
781 }
782 }
783
784 /* turn around to face vel */
785 } else if (KEY("reverse") && !repeat) {
786 if (value==KEY_PRESS) {
787 player_restoreControl( PINPUT_MOVEMENT, NULL );
788 player_setFlag(PLAYER_REVERSE);
789 }
790 else if ((value==KEY_RELEASE) && player_isFlag(PLAYER_REVERSE)) {
791 player_rmFlag(PLAYER_REVERSE);
792
793 if (!player_isFlag(PLAYER_ACCEL))
795 }
796
797 /* Double tap reverse = cooldown! */
798 if (isdoubletap)
800
801 /* try to enter stealth mode. */
802 } else if (KEY("stealth") && !repeat && NOHYP() && NODEAD() && INGAME()) {
803 if (value==KEY_PRESS)
805
806 /* face the target */
807 } else if (KEY("face") && !repeat) {
808 if (value==KEY_PRESS) {
809 player_restoreControl( PINPUT_MOVEMENT, NULL );
810 player_setFlag(PLAYER_FACE);
811 }
812 else if ((value==KEY_RELEASE) && player_isFlag(PLAYER_FACE))
813 player_rmFlag(PLAYER_FACE);
814
815 /*
816 * Combat
817 */
818 /* shooting primary weapon */
819 } else if (KEY("primary") && !repeat) {
820 if (value==KEY_PRESS) {
821 player_setFlag(PLAYER_PRIMARY);
822 }
823 else if (value==KEY_RELEASE)
824 player_rmFlag(PLAYER_PRIMARY);
825 /* targeting */
826 } else if ((INGAME() || map_isOpen()) && NODEAD() && KEY("target_next")) {
827 if (value==KEY_PRESS) {
828 if (map_isOpen())
829 map_cycleMissions(1);
830 else
832 }
833 } else if ((INGAME() || map_isOpen()) && NODEAD() && KEY("target_prev")) {
834 if (value==KEY_PRESS) {
835 if (map_isOpen())
836 map_cycleMissions(-1);
837 else
839 }
840 } else if ((INGAME() || map_isOpen()) && NODEAD() && KEY("target_nearest")) {
841 if (value==KEY_PRESS) {
842 if (map_isOpen())
843 map_cycleMissions(1);
844 else
846 }
847 } else if (INGAME() && NODEAD() && KEY("target_nextHostile")) {
848 if (value==KEY_PRESS) player_targetNext(1);
849 } else if (INGAME() && NODEAD() && KEY("target_prevHostile")) {
850 if (value==KEY_PRESS) player_targetPrev(1);
851 } else if (INGAME() && NODEAD() && KEY("target_hostile")) {
852 if (value==KEY_PRESS) player_targetHostile();
853 } else if (INGAME() && NODEAD() && KEY("target_clear")) {
854 if (value==KEY_PRESS) player_targetClear();
855
856 /*
857 * Escorts.
858 */
859 } else if (INGAME() && NODEAD() && KEY("e_targetNext") && !repeat) {
860 if (value==KEY_PRESS) player_targetEscort(0);
861 } else if (INGAME() && NODEAD() && KEY("e_targetPrev") && !repeat) {
862 if (value==KEY_PRESS) player_targetEscort(1);
863 } else if (INGAME() && NODEAD() && KEY("e_attack") && !repeat) {
864 if (value==KEY_PRESS) escorts_attack(player.p);
865 } else if (INGAME() && NODEAD() && KEY("e_hold") && !repeat) {
866 if (value==KEY_PRESS) escorts_hold(player.p);
867 } else if (INGAME() && NODEAD() && KEY("e_return") && !repeat) {
868 if (value==KEY_PRESS) escorts_return(player.p);
869 } else if (INGAME() && NODEAD() && KEY("e_clear") && !repeat) {
870 if (value==KEY_PRESS) escorts_clear(player.p);
871
872 /*
873 * secondary weapons
874 */
875 /* shooting secondary weapon */
876 } else if (KEY("secondary") && !repeat) {
877 if (value==KEY_PRESS) {
878 player_setFlag(PLAYER_SECONDARY);
879 }
880 else if (value==KEY_RELEASE)
881 player_rmFlag(PLAYER_SECONDARY);
882
883 /* Weapon sets. */
884 } else if (NODEAD() && KEY("weapset1")) {
885 player_weapSetPress( 0, value, repeat );
886 } else if (NODEAD() && KEY("weapset2")) {
887 player_weapSetPress( 1, value, repeat );
888 } else if (NODEAD() && KEY("weapset3")) {
889 player_weapSetPress( 2, value, repeat );
890 } else if (NODEAD() && KEY("weapset4")) {
891 player_weapSetPress( 3, value, repeat );
892 } else if (NODEAD() && KEY("weapset5")) {
893 player_weapSetPress( 4, value, repeat );
894 } else if (NODEAD() && KEY("weapset6")) {
895 player_weapSetPress( 5, value, repeat );
896 } else if (NODEAD() && KEY("weapset7")) {
897 player_weapSetPress( 6, value, repeat );
898 } else if (NODEAD() && KEY("weapset8")) {
899 player_weapSetPress( 7, value, repeat );
900 } else if (NODEAD() && KEY("weapset9")) {
901 player_weapSetPress( 8, value, repeat );
902 } else if (NODEAD() && KEY("weapset0")) {
903 player_weapSetPress( 9, value, repeat );
904
905 /*
906 * Space
907 */
908 } else if (KEY("autonav") && NOHYP() && NODEAD()) {
909 if (value==KEY_PRESS) {
910 if (map_isOpen()) {
911 unsigned int wid = window_get( MAP_WDWNAME );
912 player_autonavStartWindow( wid, NULL );
913 }
914 else if INGAME() {
916 }
917 }
918 /* target spob (cycles like target) */
919 } else if (KEY("target_spob") && INGAME() && NOHYP() && NOLAND() && NODEAD()) {
920 if (value==KEY_PRESS) player_targetSpob();
921 /* target nearest spob or attempt to land */
922 } else if (KEY("approach") && INGAME() && NOHYP() && NOLAND() && NODEAD() && !repeat) {
923 if (value==KEY_PRESS) {
924 player_restoreControl( 0, NULL );
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 );
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)
1154 cam_setZoomTarget( cam_getZoomTarget() * modifier, conf.zoom_speed );
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;
1237 Pilot *p;
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 player_autonavPos( x, y );
1309 return 1;
1310 }
1311
1312 return 0;
1313}
1314
1322int input_clickedJump( int jump, int autonav )
1323{
1324 JumpPoint *jp = &cur_system->jumps[ jump ];
1325
1326 if (!jp_isUsable(jp))
1327 return 0;
1328
1329 if (autonav)
1330 return 0;
1331
1332 if (player.p->nav_hyperspace != jump)
1333 map_select( jp->target, 0 );
1334
1335 if ((jump == player.p->nav_hyperspace) && input_isDoubleClick( (void*)jp )) {
1336 player_targetHyperspaceSet( jump, 0 );
1338 player_jump();
1339 else
1341 return 1;
1342 }
1343 else
1344 player_targetHyperspaceSet( jump, 0 );
1345
1346 input_clicked( (void*)jp );
1347 return 0;
1348}
1349
1357int input_clickedSpob( int spob, int autonav )
1358{
1359 Spob *pnt = cur_system->spobs[ spob ];
1360
1361 if (!spob_isKnown(pnt))
1362 return 0;
1363
1364 if (autonav) {
1366 player_autonavSpob(pnt->name, 0);
1367 return 1;
1368 }
1369
1370 if (spob == player.p->nav_spob && input_isDoubleClick((void*)pnt)) {
1372 spob_updateLand( pnt );
1373 if (!spob_isFlag(pnt, SPOB_SERVICE_INHABITED) || pnt->can_land ||
1374 (pnt->land_override > 0)) {
1375 int ret = player_land(0);
1376 if (ret == PLAYER_LAND_AGAIN) {
1377 player_autonavSpob(pnt->name, 1);
1378 }
1379 else if (ret == PLAYER_LAND_DENIED) {
1380 player_autonavSpob(pnt->name, 0);
1381 }
1382 }
1383 else
1385 }
1386 else
1387 player_targetSpobSet( spob );
1388
1389 input_clicked( (void*)pnt );
1390 return 1;
1391}
1392
1400int input_clickedAsteroid( int field, int asteroid )
1401{
1402 AsteroidAnchor *anchor = &cur_system->asteroids[ field ];
1403 Asteroid *ast = &anchor->asteroids[ asteroid ];
1404 player_targetAsteroidSet( field, asteroid );
1405 input_clicked( (void*)ast );
1406 return 1;
1407}
1408
1416int input_clickedPilot( unsigned int pilot, int autonav )
1417{
1418 Pilot *p;
1419
1420 if (pilot == PLAYER_ID)
1421 return 0;
1422
1423 if (autonav) {
1424 player_targetSet( pilot );
1425 player_autonavPil( pilot );
1426 return 1;
1427 }
1428
1429 p = pilot_get(pilot);
1430 if (pilot == player.p->target && input_isDoubleClick( (void*)p )) {
1431 if (pilot_isDisabled(p) || pilot_isFlag(p, PILOT_BOARDABLE)) {
1432 if (player_tryBoard(0)==PLAYER_BOARD_RETRY)
1434 }
1435 else
1436 player_hail();
1437 }
1438 else
1439 player_targetSet( pilot );
1440
1441 input_clicked( (void*)p );
1442 return 1;
1443}
1444
1449void input_clicked( void *clicked )
1450{
1451 if (conf.mouse_doubleclick <= 0.)
1452 return;
1453
1454 input_lastClicked = clicked;
1455 input_mouseClickLast = SDL_GetTicks();
1456}
1457
1462int input_isDoubleClick( void *clicked )
1463{
1464 unsigned int threshold;
1465
1466 if (conf.mouse_doubleclick <= 0.)
1467 return 1;
1468
1469 /* Most recent time that constitutes a valid double-click. */
1470 threshold = input_mouseClickLast + (int)(conf.mouse_doubleclick * 1000);
1471
1472 if ((SDL_GetTicks() <= threshold) && (clicked == input_lastClicked))
1473 return 1;
1474
1475 return 0;
1476}
1477
1485void input_handle( SDL_Event* event )
1486{
1487 int ismouse;
1488
1489 /* Special case mouse stuff. */
1490 if ((event->type == SDL_MOUSEMOTION) ||
1491 (event->type == SDL_MOUSEBUTTONDOWN) ||
1492 (event->type == SDL_MOUSEBUTTONUP)) {
1494 SDL_ShowCursor( SDL_ENABLE );
1495 ismouse = 1;
1496 }
1497 else
1498 ismouse = 0;
1499
1500 /* Special case paste. */
1501 if (event->type == SDL_KEYDOWN && SDL_HasClipboardText() &&
1502 SDL_EventState( SDL_TEXTINPUT, SDL_QUERY )==SDL_ENABLE) {
1503 SDL_Keymod mod = input_translateMod( event->key.keysym.mod );
1504 if ((input_paste->key == event->key.keysym.sym) &&
1505 (input_paste->mod & mod)) {
1506 SDL_Event evt;
1507 char *txt = SDL_GetClipboardText();
1508 evt.type = SDL_TEXTINPUT;
1509 size_t i = 0;
1510 uint32_t ch;
1511 while ((ch = u8_nextchar( txt, &i ))) {
1512 size_t e = u8_wc_toutf8( evt.text.text, ch );
1513 evt.text.text[e] = '\0';
1514 SDL_PushEvent( &evt );
1515 }
1516 return;
1517 }
1518 }
1519
1520 if (toolkit_isOpen()) { /* toolkit handled completely separately */
1521 if (toolkit_input(event))
1522 return; /* we don't process it if toolkit grabs it */
1523 if (ismouse)
1524 return; /* Toolkit absorbs everything mousy. */
1525 }
1526
1527 if (ovr_isOpen())
1528 if (ovr_input(event))
1529 return; /* Don't process if the map overlay wants it. */
1530
1531 /* GUI gets event. */
1532 if (gui_handleEvent(event))
1533 return;
1534
1535 switch (event->type) {
1536
1537 /*
1538 * game itself
1539 */
1540 case SDL_JOYAXISMOTION:
1541 input_joyaxis(event->jaxis.axis, event->jaxis.value);
1542 break;
1543
1544 case SDL_JOYBUTTONDOWN:
1545 input_joyevent(KEY_PRESS, event->jbutton.button);
1546 break;
1547
1548 case SDL_JOYBUTTONUP:
1549 input_joyevent(KEY_RELEASE, event->jbutton.button);
1550 break;
1551
1552 case SDL_JOYHATMOTION:
1553 input_joyhatevent(event->jhat.value, event->jhat.hat);
1554 break;
1555
1556 case SDL_KEYDOWN:
1557 if (event->key.repeat != 0)
1558 return;
1559 input_keyevent(KEY_PRESS, event->key.keysym.sym, event->key.keysym.mod, 0);
1560 break;
1561
1562 case SDL_KEYUP:
1563 if (event->key.repeat != 0)
1564 return;
1565 input_keyevent(KEY_RELEASE, event->key.keysym.sym, event->key.keysym.mod, 0);
1566 break;
1567
1568 /* Mouse stuff. */
1569 case SDL_MOUSEBUTTONDOWN:
1570 input_clickevent( event );
1571 break;
1572
1573 case SDL_MOUSEWHEEL:
1574 if (event->wheel.y > 0)
1575 input_clickZoom( 1.1 );
1576 else if (event->wheel.y < 0)
1577 input_clickZoom( 0.9 );
1578 break;
1579
1580 case SDL_MOUSEMOTION:
1581 input_mouseMove( event );
1582 break;
1583
1584 default:
1585 break;
1586 }
1587}
Provides macros to work with dynamic arrays.
int player_tryBoard(int noisy)
Attempt to board the player's target.
Definition board.c:152
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_hold(const Pilot *parent)
Have a pilot order its escorts to hold position.
Definition escort.c:322
int escorts_return(const Pilot *parent)
Have a pilot order its escorts to dock.
Definition escort.c:335
int escorts_attack(Pilot *parent)
Have a pilot order its escorts to attack its target.
Definition escort.c:283
int escorts_clear(const Pilot *parent)
Have a pilot order its escorts to clear orders.
Definition escort.c:348
const char * pgettext_var(const char *msgctxt, const char *msgid)
Definition gettext.c:318
int gui_radarClickEvent(SDL_Event *event)
Handles a click at a position in the current system.
Definition gui.c:2108
int gui_handleEvent(SDL_Event *evt)
Handles GUI events.
Definition gui.c:2192
void gui_messageScrollDown(int lines)
Scrolls up the message box.
Definition gui.c:258
int gui_borderClickEvent(SDL_Event *event)
Handles clicks on the GUI border icons.
Definition gui.c:2137
void gui_setRadarRel(int mod)
Modifies the radar resolution.
Definition gui.c:2049
void gui_messageScrollUp(int lines)
Scrolls up the message box.
Definition gui.c:229
int hooks_runParam(const char *stack, const HookParam *param)
Runs all the hooks of stack.
Definition hook.c:979
Handles the info menu.
#define INFO_DEFAULT
Definition info.h:16
void input_init(void)
Initializes the input subsystem (does not set keys).
Definition input.c:278
static void input_mouseMove(SDL_Event *event)
Provides mouse X and Y coordinates for mouse flying.
Definition input.c:1160
static void input_joyhatevent(const Uint8 value, const Uint8 hat)
Filters a joystick hat event.
Definition input.c:1094
SDL_Keycode input_getKeybind(const char *keybind, KeybindType *type, SDL_Keymod *mod)
Gets the value of a keybind.
Definition input.c:431
void input_disableAll(void)
Disables all the keybinds.
Definition input.c:346
static int doubletap_key
Definition input.c:135
int input_clickedPilot(unsigned int pilot, int autonav)
Performs an appropriate action when a pilot is clicked.
Definition input.c:1416
static void input_clickZoom(double modifier)
Handles zoom.
Definition input.c:1151
static unsigned int repeat_keyCounter
Definition input.c:143
const char * keybind_info[][3]
Definition input.c:50
void input_clicked(void *clicked)
Sets the last-clicked item, for double-click detection.
Definition input.c:1449
double player_right
Definition player.c:122
static void input_joyevent(const int event, const SDL_Keycode button)
Filters a joystick button event.
Definition input.c:1078
static void input_clickevent(SDL_Event *event)
Handles a click event.
Definition input.c:1171
static unsigned int input_mouseClickLast
Definition input.c:150
SDL_Keycode input_keyConv(const char *name)
Gets the key id from its name.
Definition input.c:392
void input_toggleEnable(const char *key, int enable)
Enables or disables a keybind.
Definition input.c:355
static void input_joyaxis(const SDL_Keycode axis, const int value)
Filters a joystick axis event.
Definition input.c:1049
void input_handle(SDL_Event *event)
Handles global input.
Definition input.c:1485
void input_mouseShow(void)
Shows the mouse.
Definition input.c:368
static void * input_lastClicked
Definition input.c:151
static int input_mouseCounter
Definition input.c:149
int input_isDoubleClick(void *clicked)
Checks whether a clicked item is the same as the last-clicked.
Definition input.c:1462
#define NOLAND()
Definition input.c:652
const char * input_keyAlreadyBound(KeybindType type, SDL_Keycode key, SDL_Keymod mod)
Checks to see if a key is already bound.
Definition input.c:537
void input_setDefault(int wasd)
Sets the default input keys.
Definition input.c:172
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:1234
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:1130
int input_clickedAsteroid(int field, int asteroid)
Performs an appropriate action when an asteroid is clicked.
Definition input.c:1400
int input_clickedSpob(int spob, int autonav)
Performs an appropriate action when a spob is clicked.
Definition input.c:1357
#define INGAME()
Definition input.c:646
static Keybind * input_keybinds
Definition input.c:128
static unsigned int doubletap_t
Definition input.c:136
static unsigned int repeat_keyTimer
Definition input.c:142
static double input_mouseTimer
Definition input.c:148
static int repeat_key
Definition input.c:141
void input_update(double dt)
Handles key repeating.
Definition input.c:614
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:409
void input_exit(void)
exits the input subsystem.
Definition input.c:329
const char * input_getKeybindDescription(const char *keybind)
Gets the description of the keybinding.
Definition input.c:582
double player_left
Definition player.c:121
#define KEY(s)
Definition input.c:645
#define NODEAD()
Definition input.c:651
SDL_Keymod input_translateMod(SDL_Keymod mod)
Translates SDL modifier to Naev modifier.
Definition input.c:597
const int input_numbinds
Definition input.c:129
void input_enableAll(void)
Enables all the keybinds.
Definition input.c:337
#define NOHYP()
Definition input.c:647
int input_clickedJump(int jump, int autonav)
Performs an appropriate action when a jump point is clicked.
Definition input.c:1322
const char * input_modToText(SDL_Keymod mod)
Gets the human readable version of mod.
Definition input.c:516
void input_getKeybindDisplay(const char *keybind, char *buf, int len)
Gets the display name (translated and human-readable) of a keybind.
Definition input.c:453
void input_mouseHide(void)
Hides the mouse.
Definition input.c:377
Handles the important game menus.
Header file with generic functions and naev-specifics.
#define MIN(x, y)
Definition naev.h:40
#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:99
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:547
Pilot * pilot_get(unsigned int id)
Pulls a pilot out of the pilot_stack based on ID.
Definition pilot.c:620
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:4615
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:1422
void player_autohail(void)
Automatically tries to hail a pilot that hailed the player.
Definition player.c:2425
void player_cooldownBrake(void)
Starts braking or active cooldown.
Definition player.c:2481
void player_accel(double acc)
Start accelerating.
Definition player.c:2113
void player_targetEscort(int prev)
Targets the pilot.
Definition player.c:2254
void player_targetAsteroidSet(int field, int id)
Sets the player's target asteroid.
Definition player.c:1522
void player_targetSet(unsigned int id)
Sets the player's target.
Definition player.c:2137
void player_hailSpob(void)
Opens communication with the player's spob target.
Definition player.c:2406
void player_resetSpeed(void)
Resets the player speed stuff.
Definition player.c:1448
void player_targetHyperspaceSet(int id, int nomsg)
Sets the player's hyperspace target.
Definition player.c:1821
void player_targetHyperspace(void)
Gets a hyperspace target.
Definition player.c:1855
void player_hyperspacePreempt(int preempt)
Enables or disables jump points preempting spobs in autoface and target clearing.
Definition player.c:1893
void player_toggleMouseFly(void)
Toggles mouse flying.
Definition player.c:2458
void player_targetNearest(void)
Player targets nearest pilot.
Definition player.c:2297
void player_restoreControl(int reason, const char *str)
Aborts autonav and other states that take control of the ship.
Definition player.c:1461
int player_jump(void)
Actually attempts to jump in hyperspace.
Definition player.c:1941
void player_targetSpobSet(int id)
Sets the player's target spob.
Definition player.c:1485
void player_accelOver(void)
Done accelerating.
Definition player.c:2127
int player_land(int loud)
Try to land or target closest spob if no land target.
Definition player.c:1579
Player_t player
Definition player.c:74
void player_targetPrev(int mode)
Cycles to previous target.
Definition player.c:2212
void player_targetClear(void)
Clears the player's ship, spob or hyperspace target, in that order.
Definition player.c:2220
void player_targetHostile(void)
Targets the nearest hostile enemy to the player.
Definition player.c:2163
void player_screenshot(void)
Takes a screenshot.
Definition player.c:2319
void player_approach(void)
Logic to make the player approach a target pilot to board or spob to land on.
Definition player.c:1757
void player_targetSpob(void)
Cycle through spob targets.
Definition player.c:1546
void player_targetNext(int mode)
Cycles to next target.
Definition player.c:2202
void player_hail(void)
Opens communication with the player's target.
Definition player.c:2378
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_autonavBoard(unsigned int p)
Starts autonav with a pilot to board.
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:687
int space_canHyperspace(const Pilot *p)
Checks to make sure if pilot is far enough away to hyperspace.
Definition space.c:469
StarSystem * cur_system
Definition space.c:106
void spob_updateLand(Spob *p)
Updates the land possibilities of a spob.
Definition space.c:1943
Represents an asteroid field anchor.
Definition asteroid.h:100
Asteroid * asteroids
Definition asteroid.h:105
Represents a single asteroid.
Definition asteroid.h:77
const glTexture * gfx
Definition asteroid.h:83
The actual hook parameter.
Definition hook.h:38
const char * str
Definition hook.h:42
HookParamType type
Definition hook.h:39
union HookParam::@25 u
double num
Definition hook.h:41
int b
Definition hook.h:43
Naev Keybinding.
Definition input.c:41
int disabled
Definition input.c:42
SDL_Keycode key
Definition input.c:45
const char * name
Definition input.c:43
KeybindType type
Definition input.c:44
SDL_Keymod mod
Definition input.c:46
The representation of an in-game pilot.
Definition pilot.h:217
int nav_hyperspace
Definition pilot.h:345
Solid solid
Definition pilot.h:227
unsigned int target
Definition pilot.h:342
int nav_spob
Definition pilot.h:344
double zoom_speed
Definition conf.h:136
double mouse_hide
Definition conf.h:151
unsigned int repeat_freq
Definition conf.h:130
double mouse_doubleclick
Definition conf.h:154
unsigned int repeat_delay
Definition conf.h:129
unsigned int doubletap_sens
Definition conf.h:150
Pilot * p
Definition player.h:101
double mousex
Definition player.h:108
double speed
Definition player.h:110
double mousey
Definition player.h:109
vec2 pos
Definition physics.h:49
Represents a Space Object (SPOB), including and not limited to planets, stations, wormholes,...
Definition space.h:89
int can_land
Definition space.h:108
int land_override
Definition space.h:109
double radius
Definition space.h:95
char * name
Definition space.h:91
double sw
Definition opengl_tex.h:46
double sh
Definition opengl_tex.h:47
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:94
static SDL_Keycode input_key
Definition toolkit.c:43
unsigned int window_get(const char *wdwname)
Gets the ID of a window.
Definition toolkit.c:666
int toolkit_input(SDL_Event *event)
Toolkit input handled here.
Definition toolkit.c:1672