/** * @brief Creates a secondary loop until loop_done is set to 1 or the toolkit closes. * * Almost identical to the main loop in naev.c. * * @TODO Fix this, we need proper threading as the music Lua and dialogue running Lua * may be run in parallel and this will make everyone cry. So basically we have * a race condition due to the "threading" effect this creates. Solved most of * it by removing globals in the Lua event/mission code, but this doesn't mean * it's solved. It just means it's extremely unlikely. * * @return 0 on success. */ static int toolkit_loop( int *loop_done ) { SDL_Event event; /* Delay a toolkit iteration. */ toolkit_delay(); *loop_done = 0; while (!(*loop_done) && toolkit_isOpen()) { /* Loop first so exit condition is checked before next iteration. */ main_loop( 0 ); while (SDL_PollEvent(&event)) { /* event loop */ if (event.type == SDL_QUIT) { /* pass quit event to main engine */ if (menu_askQuit()) { naev_quit(); *loop_done = 1; SDL_PushEvent(&event); return -1; } } input_handle(&event); /* handles all the events and player keybinds */ } } return 0; }
/** * @brief Creates a secondary loop until loop_done is set to 1 or the toolkit closes. * * Almost identical to the main loop in naev.c. * * @TODO Fix this, we need proper threading as the music Lua and dialogue running Lua * may be run in parallel and this will make everyone cry. So basically we have * a race condition due to the "threading" effect this creates. Solved most of * it by removing globals in the Lua event/mission code, but this doesn't mean * it's solved. It just means it's extremely unlikely. * * @return 0 on success. */ static int toolkit_loop( int *loop_done ) { SDL_Event event; /* Delay a toolkit iteration. */ toolkit_delay(); *loop_done = 0; while (!(*loop_done) && toolkit_isOpen()) { /* Loop first so exit condition is checked before next iteration. */ main_loop( 0 ); while (SDL_PollEvent(&event)) { /* event loop */ if (event.type == SDL_QUIT) { /* pass quit event to main engine */ if (menu_askQuit()) { naev_quit(); *loop_done = 1; SDL_PushEvent(&event); return -1; } } #if SDL_VERSION_ATLEAST(2,0,0) else if (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_RESIZED) { naev_resize( event.window.data1, event.window.data2 ); continue; } #endif /* SDL_VERSION_ATLEAST(2,0,0) */ input_handle(&event); /* handles all the events and player keybinds */ } } return 0; }
/** * @brief Split main loop from main() for secondary loop hack in toolkit.c. */ void main_loop (void) { int tk; /* Check to see if toolkit is open. */ tk = toolkit_isOpen(); /* Clear buffer. */ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); fps_control(); /* everyone loves fps control */ sound_update( real_dt ); /* Update sounds. */ if (tk) toolkit_update(); /* to simulate key repetition */ if (!menu_isOpen(MENU_MAIN)) { if (!paused) update_all(); /* update game */ render_all(); } /* Toolkit is rendered on top. */ if (tk) toolkit_render(); gl_checkErr(); /* check error every loop */ /* Draw buffer. */ SDL_GL_SwapBuffers(); }
/** * @brief Runs the input command. * * @param keynum The index of the keybind. * @param value The value of the keypress (defined above). * @param kabs The absolute value. */ static void input_key( int keynum, double value, double kabs, int repeat ) { unsigned int t; HookParam hparam[3]; /* Repetition stuff. */ if (conf.repeat_delay != 0) { if ((value == KEY_PRESS) && !repeat) { repeat_key = keynum; repeat_keyTimer = SDL_GetTicks(); repeat_keyCounter = 0; } else if (value == KEY_RELEASE) { repeat_key = -1; repeat_keyTimer = 0; repeat_keyCounter = 0; } } /* * movement */ /* accelerating */ if (KEY("accel") && !repeat) { if (kabs >= 0.) { player_restoreControl( PINPUT_MOVEMENT, NULL ); player_accel(kabs); input_accelButton = 1; } else { /* prevent it from getting stuck */ if (value==KEY_PRESS) { player_restoreControl( PINPUT_MOVEMENT, NULL ); player_setFlag(PLAYER_ACCEL); player_accel(1.); input_accelButton = 1; } else if (value==KEY_RELEASE) { player_accelOver(); player_rmFlag(PLAYER_ACCEL); input_accelButton = 0; } /* double tap accel = afterburn! */ t = SDL_GetTicks(); if ((conf.afterburn_sens != 0) && (value==KEY_PRESS) && INGAME() && NOHYP() && NODEAD() && (t-input_accelLast <= conf.afterburn_sens)) pilot_afterburn( player.p ); else if (value==KEY_RELEASE) pilot_afterburnOver( player.p ); if (value==KEY_PRESS) input_accelLast = t; } /* turning left */ } else if (KEY("left") && !repeat) { if (kabs >= 0.) { player_restoreControl( PINPUT_MOVEMENT, NULL ); player_setFlag(PLAYER_TURN_LEFT); player_left = kabs; } else { /* set flags for facing correction */ if (value==KEY_PRESS) { player_restoreControl( PINPUT_MOVEMENT, NULL ); player_setFlag(PLAYER_TURN_LEFT); player_left = 1.; } else if (value==KEY_RELEASE) { player_rmFlag(PLAYER_TURN_LEFT); player_left = 0.; } } /* turning right */ } else if (KEY("right") && !repeat) { if (kabs >= 0.) { player_restoreControl( PINPUT_MOVEMENT, NULL ); player_setFlag(PLAYER_TURN_RIGHT); player_right = kabs; } else { /* set flags for facing correction */ if (value==KEY_PRESS) { player_restoreControl( PINPUT_MOVEMENT, NULL ); player_setFlag(PLAYER_TURN_RIGHT); player_right = 1.; } else if (value==KEY_RELEASE) { player_rmFlag(PLAYER_TURN_RIGHT); player_right = 0.; } } /* turn around to face vel */ } else if (KEY("reverse") && !repeat) { if (value==KEY_PRESS) { player_restoreControl( PINPUT_MOVEMENT, NULL ); player_setFlag(PLAYER_REVERSE); } else if ((value==KEY_RELEASE) && player_isFlag(PLAYER_REVERSE)) { player_rmFlag(PLAYER_REVERSE); if (!player_isFlag(PLAYER_ACCEL)) player_accelOver(); } /* * combat */ /* shooting primary weapon */ } else if (KEY("primary") && NODEAD() && !repeat) { if (value==KEY_PRESS) { player_setFlag(PLAYER_PRIMARY); } else if (value==KEY_RELEASE) player_rmFlag(PLAYER_PRIMARY); /* targeting */ } else if (INGAME() && NODEAD() && KEY("target_next")) { if (value==KEY_PRESS) player_targetNext(0); } else if (INGAME() && NODEAD() && KEY("target_prev")) { if (value==KEY_PRESS) player_targetPrev(0); } else if (INGAME() && NODEAD() && KEY("target_nearest")) { if (value==KEY_PRESS) player_targetNearest(); } else if (INGAME() && NODEAD() && KEY("target_nextHostile")) { if (value==KEY_PRESS) player_targetNext(1); } else if (INGAME() && NODEAD() && KEY("target_prevHostile")) { if (value==KEY_PRESS) player_targetPrev(1); } else if (INGAME() && NODEAD() && KEY("target_hostile")) { if (value==KEY_PRESS) player_targetHostile(); } else if (INGAME() && NODEAD() && KEY("target_clear")) { if (value==KEY_PRESS) player_targetClear(); /* face the target */ } else if (INGAME() && NODEAD() && KEY("face") && !repeat) { if (value==KEY_PRESS) { player_restoreControl( PINPUT_MOVEMENT, NULL ); player_setFlag(PLAYER_FACE); } else if ((value==KEY_RELEASE) && player_isFlag(PLAYER_FACE)) player_rmFlag(PLAYER_FACE); /* board them ships */ } else if (KEY("board") && INGAME() && NOHYP() && NODEAD() && !repeat) { if (value==KEY_PRESS) { player_restoreControl( 0, NULL ); player_board(); } /* * Escorts. */ } else if (INGAME() && NODEAD() && KEY("e_targetNext") && !repeat) { if (value==KEY_PRESS) player_targetEscort(0); } else if (INGAME() && NODEAD() && KEY("e_targetPrev") && !repeat) { if (value==KEY_PRESS) player_targetEscort(1); } else if (INGAME() && NODEAD() && KEY("e_attack") && !repeat) { if (value==KEY_PRESS) escorts_attack(player.p); } else if (INGAME() && NODEAD() && KEY("e_hold") && !repeat) { if (value==KEY_PRESS) escorts_hold(player.p); } else if (INGAME() && NODEAD() && KEY("e_return") && !repeat) { if (value==KEY_PRESS) escorts_return(player.p); } else if (INGAME() && NODEAD() && KEY("e_clear") && !repeat) { if (value==KEY_PRESS) escorts_clear(player.p); /* * secondary weapons */ /* shooting secondary weapon */ } else if (KEY("secondary") && NOHYP() && NODEAD() && !repeat) { if (value==KEY_PRESS) { player_setFlag(PLAYER_SECONDARY); } else if (value==KEY_RELEASE) player_rmFlag(PLAYER_SECONDARY); /* Weapon sets. */ } else if (KEY("weapset1")) { player_weapSetPress( 0, value, repeat ); } else if (KEY("weapset2")) { player_weapSetPress( 1, value, repeat ); } else if (KEY("weapset3")) { player_weapSetPress( 2, value, repeat ); } else if (KEY("weapset4")) { player_weapSetPress( 3, value, repeat ); } else if (KEY("weapset5")) { player_weapSetPress( 4, value, repeat ); } else if (KEY("weapset6")) { player_weapSetPress( 5, value, repeat ); } else if (KEY("weapset7")) { player_weapSetPress( 6, value, repeat ); } else if (KEY("weapset8")) { player_weapSetPress( 7, value, repeat ); } else if (KEY("weapset9")) { player_weapSetPress( 8, value, repeat ); } else if (KEY("weapset0")) { player_weapSetPress( 9, value, repeat ); /* * space */ } else if (KEY("autonav") && INGAME() && NOHYP() && NODEAD()) { if (value==KEY_PRESS) player_autonavStart(); /* target planet (cycles like target) */ } else if (KEY("target_planet") && INGAME() && NOHYP() && NOLAND() && NODEAD()) { if (value==KEY_PRESS) player_targetPlanet(); /* target nearest planet or attempt to land */ } else if (KEY("land") && INGAME() && NOHYP() && NOLAND() && NODEAD()) { if (value==KEY_PRESS) player_land(); } else if (KEY("thyperspace") && NOHYP() && NOLAND() && NODEAD()) { if (value==KEY_PRESS) player_targetHyperspace(); } else if (KEY("starmap") && NOHYP() && NODEAD() && !repeat) { if (value==KEY_PRESS) map_open(); } else if (KEY("jump") && INGAME() && !repeat) { if (value==KEY_PRESS) { player_restoreControl( 0, NULL ); player_jump(); } } else if (KEY("overlay") && NODEAD() && INGAME() && !repeat) { ovr_key( value ); } else if (KEY("mousefly") && NODEAD() && !repeat) { if (value==KEY_PRESS) player_toggleMouseFly(); } else if (KEY("autobrake") && NOHYP() && NOLAND() && NODEAD() && !repeat) { if (value==KEY_PRESS) { player_restoreControl( PINPUT_BRAKING, NULL ); player_brake(); } /* * Communication. */ } else if (KEY("log_up") && INGAME() && NODEAD()) { if (value==KEY_PRESS) { gui_messageScrollUp(5); } } else if (KEY("log_down") && INGAME() && NODEAD()) { if (value==KEY_PRESS) { gui_messageScrollDown(5); } } else if (KEY("hail") && INGAME() && NOHYP() && NODEAD() && !repeat) { if (value==KEY_PRESS) { player_hail(); } } else if (KEY("autohail") && INGAME() && NOHYP() && NODEAD() && !repeat) { if (value==KEY_PRESS) { player_autohail(); } /* * misc */ /* zooming in */ } else if (KEY("mapzoomin") && INGAME() && NODEAD()) { if (value==KEY_PRESS) gui_setRadarRel(-1); /* zooming out */ } else if (KEY("mapzoomout") && INGAME() && NODEAD()) { if (value==KEY_PRESS) gui_setRadarRel(1); /* take a screenshot */ } else if (KEY("screenshot")) { if (value==KEY_PRESS) player_screenshot(); #if SDL_VERSION_ATLEAST(2,0,0) /* toggle fullscreen */ } else if (KEY("togglefullscreen") && !repeat) { if (value==KEY_PRESS) naev_toggleFullscreen(); #endif /* SDL_VERSION_ATLEAST(2,0,0) */ /* pause the games */ } else if (KEY("pause") && !repeat) { if (value==KEY_PRESS) { if (!toolkit_isOpen()) { if (paused) unpause_game(); else pause_player(); } } /* toggle speed mode */ } else if (KEY("speed") && !repeat) { if ((value==KEY_PRESS) && (!player_isFlag( PLAYER_CINEMATICS_2X ))) { if (player_isFlag(PLAYER_DOUBLESPEED)) { if (!player_isFlag(PLAYER_AUTONAV)) pause_setSpeed(1.); player_rmFlag(PLAYER_DOUBLESPEED); } else { if (!player_isFlag(PLAYER_AUTONAV)) pause_setSpeed(2.); player_setFlag(PLAYER_DOUBLESPEED); } } /* opens a small menu */ } else if (KEY("menu") && NODEAD() && !repeat) { if (value==KEY_PRESS) menu_small(); /* shows pilot information */ } else if (KEY("info") && NOHYP() && NODEAD() && !repeat) { if (value==KEY_PRESS) menu_info( INFO_MAIN ); /* Opens the Lua console. */ } else if (KEY("console") && NODEAD() && !repeat) { if (value==KEY_PRESS) cli_open(); } /* Key press not used. */ else { return; } /* Run the hook. */ hparam[0].type = HOOK_PARAM_STRING; hparam[0].u.str = input_keybinds[keynum].name; hparam[1].type = HOOK_PARAM_BOOL; hparam[1].u.b = (value > 0.); hparam[2].type = HOOK_PARAM_SENTINEL; hooks_runParam( "input", hparam ); }
/** * @brief Handles global input. * * Basically separates the event types * * @param event Incoming SDL_Event. */ void input_handle( SDL_Event* event ) { int ismouse = 0; /* Special case mouse stuff. */ if ((event->type == SDL_MOUSEMOTION) || (event->type == SDL_MOUSEBUTTONDOWN) || (event->type == SDL_MOUSEBUTTONUP)) { input_mouseTimer = MOUSE_HIDE; SDL_ShowCursor( SDL_ENABLE ); ismouse = 1; } if (toolkit_isOpen()) { /* toolkit handled completely separately */ if (toolkit_input(event)) return; /* we don't process it if toolkit grabs it */ if (ismouse) return; /* Toolkit absorbs everything mousy. */ } if (ovr_isOpen()) if (ovr_input(event)) return; /* Don't process if the map overlay wants it. */ /* GUI gets event. */ if (gui_handleEvent(event)) return; switch (event->type) { /* * game itself */ case SDL_JOYAXISMOTION: input_joyaxis(event->jaxis.axis, event->jaxis.value); break; case SDL_JOYBUTTONDOWN: input_joyevent(KEY_PRESS, event->jbutton.button); break; case SDL_JOYBUTTONUP: input_joyevent(KEY_RELEASE, event->jbutton.button); break; case SDL_KEYDOWN: #if SDL_VERSION_ATLEAST(2,0,0) if (event->key.repeat != 0) return; #endif /* SDL_VERSION_ATLEAST(2,0,0) */ input_keyevent(KEY_PRESS, event->key.keysym.sym, event->key.keysym.mod, 0); break; case SDL_KEYUP: #if SDL_VERSION_ATLEAST(2,0,0) if (event->key.repeat !=0) return; #endif /* SDL_VERSION_ATLEAST(2,0,0) */ input_keyevent(KEY_RELEASE, event->key.keysym.sym, event->key.keysym.mod, 0); break; /* Mouse stuff. */ case SDL_MOUSEBUTTONDOWN: input_clickevent( event ); break; #if SDL_VERSION_ATLEAST(2,0,0) case SDL_MOUSEWHEEL: if (event->wheel.y > 0) input_clickZoom( 1.1 ); else input_clickZoom( 0.9 ); break; #endif /* SDL_VERSION_ATLEAST(2,0,0) */ case SDL_MOUSEMOTION: input_mouseMove( event ); break; default: break; } }
/** * @brief Handles global input. * * Basically seperates the event types * * @param event Incoming SDL_Event. */ void input_handle( SDL_Event* event ) { /* Special case mouse stuff. */ if ((event->type == SDL_MOUSEMOTION) || (event->type == SDL_MOUSEBUTTONDOWN) || (event->type == SDL_MOUSEBUTTONUP)) { input_mouseTimer = MOUSE_HIDE; SDL_ShowCursor( SDL_ENABLE ); } if (toolkit_isOpen()) /* toolkit handled seperately completely */ if (toolkit_input(event)) return; /* we don't process it if toolkit grabs it */ if (ovr_isOpen()) if (ovr_input(event)) return; /* Don't process if the map overlay wants it. */ /* GUI gets event. */ if (gui_handleEvent(event)) return; switch (event->type) { /* * game itself */ case SDL_JOYAXISMOTION: input_joyaxis(event->jaxis.axis, event->jaxis.value); break; case SDL_JOYBUTTONDOWN: input_joyevent(KEY_PRESS, event->jbutton.button); break; case SDL_JOYBUTTONUP: input_joyevent(KEY_RELEASE, event->jbutton.button); break; case SDL_KEYDOWN: input_keyevent(KEY_PRESS, event->key.keysym.sym, event->key.keysym.mod, 0); break; case SDL_KEYUP: input_keyevent(KEY_RELEASE, event->key.keysym.sym, event->key.keysym.mod, 0); break; /* Mouse stuff. */ case SDL_MOUSEBUTTONDOWN: input_clickevent( event ); break; case SDL_MOUSEMOTION: input_mouseMove( event ); break; default: break; } }