Пример #1
0
Файл: input.c Проект: Ttech/naev
/**
 * @brief Handles a click event.
 */
static void input_clickevent( SDL_Event* event )
{
   unsigned int pid;
   Pilot *p;
   int mx, my, mxr, myr, pntid, jpid;
   int rx, ry, rh, rw, res;
   double x, y, m, r, rp, d, dp, px, py;
   double ang, angp, mouseang;
   Planet *pnt;
   JumpPoint *jp;
   HookParam hparam[2];

   /* Generate hook. */
   hparam[0].type    = HOOK_PARAM_NUMBER;
   hparam[0].u.num   = event->button.button;
   hparam[1].type    = HOOK_PARAM_SENTINAL;
   hooks_runParam( "mouse", hparam );

   /* Handle zoom. */
   if (event->button.button == SDL_BUTTON_WHEELUP) {
      input_clickZoom( 1.1 );
      return;
   }
   else if (event->button.button == SDL_BUTTON_WHEELDOWN) {
      input_clickZoom( 0.9 );
      return;
   }

   /* Middle mouse enables mouse flying. */
   if (event->button.button == SDL_BUTTON_MIDDLE) {
      player_toggleMouseFly();
      return;
   }

   /* Mouse targetting is left only. */
   if (event->button.button != SDL_BUTTON_LEFT)
      return;

   /* Player must not be NULL. */
   if (player_isFlag(PLAYER_DESTROYED) || (player.p == NULL))
      return;

   px = player.p->solid->pos.x;
   py = player.p->solid->pos.y;
   gl_windowToScreenPos( &mx, &my, event->button.x, event->button.y );
   gl_screenToGameCoords( &x, &y, (double)mx, (double)my );
   if ((mx <= 15 || my <= 15 ) || (my >= gl_screen.h - 15 || mx >= gl_screen.w - 15)) { /* Border */
      x = (mx - (gl_screen.w / 2.)) + px;
      y = (my - (gl_screen.h / 2.)) + py;
      mouseang = atan2(py - y, px -  x);
      angp = pilot_getNearestAng( player.p, &pid, mouseang, 1 );
      ang  = system_getClosestAng( cur_system, &pntid, &jpid, x, y, mouseang );

      if  ((ABS(angle_diff(mouseang, angp)) > M_PI / 64) ||
            ABS(angle_diff(mouseang, ang)) < ABS(angle_diff(mouseang, angp)))
         pid = PLAYER_ID; /* Pilot angle is too great, or planet/jump is closer. */
      if  (ABS(angle_diff(mouseang, ang)) > M_PI / 64 )
         jpid = pntid = -1; /* Asset angle difference is too great. */
   }
   else { /* Radar targeting requires raw coordinates. */
      mxr = event->button.x;
      myr  = gl_screen.rh - event->button.y;
      gui_radarGetPos( &rx, &ry );
      gui_radarGetDim( &rw, &rh );
      if ((mxr > rx && mxr <= rx + rw ) && (myr > ry && myr <= ry + rh )) { /* Radar */
         m = 1;
         gui_radarGetRes( &res );
         x = (mxr - (rx + rw / 2.)) * res + px;
         y = (myr - (ry + rh / 2.)) * res + py;
      }
      else /* Visual (on-screen) */
         m = res = 1. / cam_getZoom();
      dp = pilot_getNearestPos( player.p, &pid, x, y, 1 );
      d  = system_getClosest( cur_system, &pntid, &jpid, x, y );
      rp = MAX( 1.5 * PILOT_SIZE_APROX * pilot_get(pid)->ship->gfx_space->sw / 2 * m,  10. * res);

      if (pntid >=0) { /* Planet is closer. */
         pnt = cur_system->planets[ pntid ];
         r  = MAX( 1.5 * pnt->radius, 100. );
      }
      else if (jpid >= 0) {
         jp = &cur_system->jumps[ jpid ];
         r  = MAX( 1.5 * jp->radius, 100. );
      }
      else {
         r  = 0.;
      }
      /* Reject pilot if it's too far or a valid asset is closer. */
      if (dp > pow2(rp) || (d < pow2(r) && dp < pow2(rp) && dp >  d))
         pid = PLAYER_ID;
      if (d > pow2(r)) /* Planet or jump point is too far. */
         jpid = pntid = -1;
   }

   if (pid != PLAYER_ID) {
      /* Apply an action if already selected. */
      if (!pilot_isFlag(player.p, PILOT_DEAD) && (pid == player.p->target)) {
         p = pilot_get(pid);
         if (pilot_isDisabled(p) || pilot_isFlag(p, PILOT_BOARDABLE))
            player_board();
         else
            player_hail();
      }
      else
         player_targetSet( pid );
   }
   else if (pntid >= 0) { /* Planet is closest. */
      if (pntid == player.p->nav_planet) {
         pnt = cur_system->planets[ pntid ];
         if (planet_hasService(pnt, PLANET_SERVICE_LAND) &&
               (!areEnemies( player.p->faction, pnt->faction ) || pnt->bribed ))
            player_land();
         else
            player_hailPlanet();
      }
      else
         player_targetPlanetSet( pntid );
   }
   else if (jpid >= 0) { /* Jump point is closest. */
      jp = &cur_system->jumps[ jpid ];
      if (jpid == player.p->nav_hyperspace) {
         if (space_canHyperspace(player.p)) {
            if (!paused) player_autonavAbort(NULL);
            player_jump();
         }
         else
            player_autonavStart();
      }
      else
         player_targetHyperspaceSet( jpid );
   }
}
Пример #2
0
/**
 * @brief Handles a click at a position in the current system
 *
 *    @brief event The click event itself, used for button information.
 *    @brief x X coordinate within the system.
 *    @brief y Y coordinate within the system.
 *    @brief zoom Camera zoom (mostly for on-screen targeting).
 *    @brief minpr Minimum radius to assign to pilots.
 *    @brief minr Minimum radius to assign to planets and jumps.
 *    @return Whether the click was used to trigger an action.
 */
int input_clickPos( SDL_Event *event, double x, double y, double zoom, double minpr, double minr )
{
   unsigned int pid;
   Pilot *p;
   double r, rp;
   double d, dp;
   Planet *pnt;
   JumpPoint *jp;
   int pntid, jpid;

   dp = pilot_getNearestPos( player.p, &pid, x, y, 1 );
   p  = pilot_get(pid);

   d  = system_getClosest( cur_system, &pntid, &jpid, x, y );
   rp = MAX( 1.5 * PILOT_SIZE_APROX * p->ship->gfx_space->sw / 2 * zoom,  minpr);

   if (pntid >=0) { /* Planet is closer. */
      pnt = cur_system->planets[ pntid ];
      r  = MAX( 1.5 * pnt->radius * zoom, minr );
   }
   else if (jpid >= 0) {
      jp = &cur_system->jumps[ jpid ];
      r  = MAX( 1.5 * jp->radius * zoom, minr );
   }
   else
      r  = 0.;

   /* Reject pilot if it's too far or a valid asset is closer. */
   if (dp > pow2(rp) || ((d < pow2(r)) && (dp >  d)))
      pid = PLAYER_ID;

   if (d > pow2(r)) /* Planet or jump point is too far. */
      jpid = pntid = -1;

   /* Target a pilot, planet or jump, and/or perform an appropriate action. */
   if (event->button.button == SDL_BUTTON_LEFT) {
      if (pid != PLAYER_ID) {
         return input_clickedPilot(pid);
      }
      else if (pntid >= 0) { /* Planet is closest. */
         return input_clickedPlanet(pntid, 0);
      }
      else if (jpid >= 0) { /* Jump point is closest. */
         return input_clickedJump(jpid, 0);
      }
   }
   /* Right click only controls autonav. */
   else if (event->button.button == SDL_BUTTON_RIGHT) {
      if ((pntid >= 0) && input_clickedPlanet(pntid, 1))
         return 1;
      else if ((jpid >= 0) && input_clickedJump(jpid, 1))
         return 1;

      /* Go to position, if the position is >= 1500 px away. */
      if ((pow2(x - player.p->solid->pos.x) + pow2(y - player.p->solid->pos.y))
            >= pow2(1500))

      player_autonavPos( x, y );
      return 1;
   }

   return 0;
}
Пример #3
0
/**
 * @brief Handles input to the map overlay.
 */
int ovr_input( SDL_Event *event )
{
   unsigned int pid;
   Pilot *p;
   int mx, my;
   double x, y, r, rp;
   double d, dp;
   Planet *pnt;
   JumpPoint *jp;
   int pntid, jpid;

   /* We only want mouse events. */
   if (event->type != SDL_MOUSEBUTTONDOWN)
      return 0;

   /* Player must not be NULL. */
   if (player_isFlag(PLAYER_DESTROYED) || (player.p == NULL))
      return 0;

   /* Selection. */
   if (event->button.button == SDL_BUTTON_LEFT) {
      /* Translate from window to screen. */
      mx = event->button.x;
      my = event->button.y;
      gl_windowToScreenPos( &mx, &my, mx, my );

      /* Translate to space coords. */
      x  = ((double)mx - SCREEN_W/2.) * ovr_res;
      y  = ((double)my - SCREEN_H/2.) * ovr_res;

      /* Get nearest pilot and jump point/planet. */
      dp    = pilot_getNearestPos( player.p, &pid, x, y, 1 );
      d     = system_getClosest( cur_system, &pntid, &jpid, x, y );
      p     = pilot_get(pid);
      rp    = MAX( 1.5 * PILOT_SIZE_APROX * p->ship->gfx_space->sw / 2, 20.*ovr_res );

      if (pntid >=0) { /* Planet is closer. */
         pnt = cur_system->planets[ pntid ];
         r  = MAX( 1.5 * pnt->radius, 20. * ovr_res );
      }
      else if (jpid >= 0) {
         jp = &cur_system->jumps[ jpid ];
         r  = MAX( 1.5 * jp->radius, 20. * ovr_res );
      }
      else
         r  = 0.;

      /* Pilot is closest, or new jump point/planet is the same as the old. */
      if ((dp < pow2(rp) && player.p->target != pid) && (dp < d ||
            ((pntid >=0 && player.p->nav_planet == pntid) ||
            (jpid >=0 && player.p->nav_planet == jpid))))
         player_targetSet( pid );
      else if ((pntid >= 0) && (d < pow2(r))) /* Planet is closest. */
         player_targetPlanetSet( pntid );
      else if ((jpid >= 0) && (d < pow2(r))) /* Jump point is closest. */
         player_targetHyperspaceSet( jpid );
      else
         return 0;
      return 1;
   }
   /* Autogo. */
   else if (event->button.button == SDL_BUTTON_RIGHT) {
      if ((player.p == NULL) || pilot_isFlag( player.p, PILOT_MANUAL_CONTROL ) ||
            pilot_isFlag( player.p, PILOT_HYP_PREP ) ||
            pilot_isFlag( player.p, PILOT_HYP_BEGIN ) ||
            pilot_isFlag( player.p, PILOT_HYPERSPACE ))
         return 1;

      /* Translate from window to screen. */
      mx = event->button.x;
      my = event->button.y;
      gl_windowToScreenPos( &mx, &my, mx, my );

      /* Translate to space coords. */
      x  = ((double)mx - SCREEN_W/2.) * ovr_res;
      y  = ((double)my - SCREEN_H/2.) * ovr_res;

      /* Go to position. */
      player_autonavPos( x, y );

      return 1;
   }

   return 0;
}