Mouse support, and fix calibration to outer edges.
authorRusty Russell <rusty@rustcorp.com.au>
Thu, 24 Jan 2008 08:06:48 +0000 (19:06 +1100)
committerRusty Russell <rusty@rustcorp.com.au>
Thu, 24 Jan 2008 08:06:48 +0000 (19:06 +1100)
prpong.c

index b814c436516e2472e3c422a472f92b6168edcc0b..7799f63fdccf90d068ab2f90d34f858163cfdc26 100644 (file)
--- a/prpong.c
+++ b/prpong.c
@@ -17,8 +17,6 @@
 #define MAX_X CWIID_IR_X_MAX
 #define MAX_Y CWIID_IR_Y_MAX
 
-#define CALIB_OFF 50
-
 struct coord
 {
        double x;
@@ -651,41 +649,42 @@ static void clear_ignore(struct list_head *lines)
                i->ignore = false;
 }
 
-static void make_cross(unsigned x, unsigned y,
-                      struct line_segment *seg1,
-                      struct line_segment *seg2)
+static uint16_t *find_valid_point(struct cwiid_state *state)
 {
-       seg1->start.x = x-5;
-       seg1->start.y = y-5;
-       seg1->end.x = x+5;
-       seg1->end.y = y+5;
-       seg2->start.x = x-5;
-       seg2->start.y = y+5;
-       seg2->end.x = x+5;
-       seg2->end.y = y-5;
+       unsigned int i;
+
+       for (i = 0; i < CWIID_IR_SRC_COUNT; i++) {
+               if (state->ir_src[i].valid)
+                       return state->ir_src[i].pos;
+       }
+       return NULL;
 }
 
 static void calibrate(SDL_Surface *screen,
                      cwiid_wiimote_t *wiimote,
                      struct coord *calib, unsigned x, unsigned y)
 {
-       struct line_segment seg1, seg2;
+       uint16_t *pos;
        struct cwiid_state state;
-       unsigned int i;
-
-       make_cross(x, y, &seg1, &seg2);
-       thick_line(screen, &seg1, 0);
-       thick_line(screen, &seg2, 0);
+       unsigned int last_x = MAX_X, last_y = MAX_Y, count = 0;
 
-       do {
+       /* Must see it for a full half second. */
+       while (count < 20) {
                SDL_Event event;
+
                if (cwiid_get_state(wiimote, &state))
                        errx(1, "No wii state");
 
-               for (i = 0; i < CWIID_IR_SRC_COUNT; i++) {
-                       if (state.ir_src[i].valid)
-                               break;
+               pos = find_valid_point(&state);
+               if (!pos || pos[0] != last_x || pos[1] != last_y)
+                       count = 0;
+
+               if (pos) {
+                       last_x = pos[0];
+                       last_y = pos[1];
+                       count++;
                }
+
                SDL_Delay(25);
                if (SDL_PollEvent(&event)
                    && (event.type == SDL_QUIT
@@ -694,20 +693,11 @@ static void calibrate(SDL_Surface *screen,
                        SDL_Quit();
                        exit(0);
                }
-       } while (i == CWIID_IR_SRC_COUNT);
-
-       thick_line(screen, &seg1, 0xFFFFFFFF);
-       thick_line(screen, &seg2, 0xFFFFFFFF);
-
-       calib->x = state.ir_src[i].pos[0];
-       calib->y = state.ir_src[i].pos[1];
-       printf("Calibration point: %u,%u\n",
-              state.ir_src[i].pos[0],
-              state.ir_src[i].pos[1]);
-       make_cross(calib->x, calib->y, &seg1, &seg2);
+       }
 
-       thick_line(screen, &seg1, 0xFFFF0000);
-       thick_line(screen, &seg2, 0xFFFF0000);
+       calib->x = last_x;
+       calib->y = last_y;
+       printf("Calibration point: %u,%u\n", last_x, last_y);
 }
 
 static bool map_coord(unsigned int x, unsigned int y,
@@ -740,7 +730,7 @@ static bool map_coord(unsigned int x, unsigned int y,
                             &intersect))
                return false;
        d2 = dist(&pos, &intersect);
-       res->x = d1 / (d1 + d2) * (MAX_X - 2*CALIB_OFF) + CALIB_OFF;
+       res->x = d1 / (d1 + d2) * MAX_X;
 
        line_start.y = 0;
        line_end.y = MAX_Y-1;
@@ -788,9 +778,10 @@ int main(int argc, char *argv[])
        struct cwiid_state state;
        struct coord calib[4];
        bdaddr_t addr = *BDADDR_ANY;
-       bool needs_calibration = true;
+       bool mouse = false, needs_calibration = true, drawing = false;
        LIST_HEAD(lines);
        struct cwiid_ir_src *ir, last_ir = { .valid = 0 };
+       struct line_segment *n;
 
        videoflags = SDL_SWSURFACE;
 
@@ -812,8 +803,22 @@ int main(int argc, char *argv[])
                argv++;
        }
 
+       if (argv[1] && streq(argv[1], "--mouse")) {
+               mouse = true;
+               needs_calibration = false;
+               calib[0].x = calib[0].y = 0;
+               calib[1].x = MAX_X - 1;
+               calib[1].y = 0;
+               calib[2].x = MAX_X - 1;
+               calib[2].y = MAX_Y - 1;
+               calib[3].x = 0;
+               calib[3].y = MAX_Y - 1;
+               argc--;
+               argv++;
+       }
+
        if (argc != 5)
-               errx(1, "Usage: %s [--fullscreen] [--calib=x,y,x,y,x,y,x,y] ballx bally ballangle ballspeed\n"
+               errx(1, "Usage: %s [--fullscreen] [--calib=x,y,x,y,x,y,x,y] [--mouse] ballx bally ballangle ballspeed\n"
                     "   Where ballangle is 0 for north, 90 for east, etc\n",
                        argv[0]);
 
@@ -824,20 +829,22 @@ int main(int argc, char *argv[])
        printf("ball move = %f,%f\n", ball.move.x, ball.move.y);
 
        /* Initialize SDL */
-       if ( SDL_Init(SDL_INIT_VIDEO) < 0 ) {
+       if (SDL_Init(SDL_INIT_VIDEO) < 0) {
                fprintf(stderr, "Couldn't initialize SDL: %s\n",SDL_GetError());
                return(1);
        }
 
        video_bpp = 0;
 
-       printf("Put Wiimote in discoverable mode (press 1+2)\n");
-       wiimote = cwiid_open(&addr, 0);
-       if (!wiimote)
-               errx(1, "Can't find the Wiimote");
+       if (!mouse) {
+               printf("Put Wiimote in discoverable mode (press 1+2)\n");
+               wiimote = cwiid_open(&addr, 0);
+               if (!wiimote)
+                       errx(1, "Can't find the Wiimote");
 
-       if (cwiid_set_rpt_mode(wiimote, CWIID_RPT_IR))
-               errx(1, "Can't set IR repeat mode");
+               if (cwiid_set_rpt_mode(wiimote, CWIID_RPT_IR))
+                       errx(1, "Can't set IR repeat mode");
+       }
 
        if ( (screen=SDL_SetVideoMode(MAX_X,MAX_Y,video_bpp,videoflags)) == NULL ) {
                errx(1, "Couldn't set %dx%dx%d video mode: %s",
@@ -857,16 +864,10 @@ int main(int argc, char *argv[])
 
        if (needs_calibration) {
                /* Calibration */
-               calibrate(screen, wiimote, &calib[0], CALIB_OFF, 6);
-               sleep(1);
-               calibrate(screen, wiimote, &calib[1],
-                         MAX_X - 1 - CALIB_OFF, 6);
-               sleep(1);
-               calibrate(screen, wiimote, &calib[2],
-                         MAX_X - 1 - CALIB_OFF, MAX_Y - 7);
-               sleep(1);
-               calibrate(screen, wiimote, &calib[3],
-                         CALIB_OFF, MAX_Y - 7);
+               calibrate(screen, wiimote, &calib[0], 0, 0);
+               calibrate(screen, wiimote, &calib[1], MAX_X - 1, 0);
+               calibrate(screen, wiimote, &calib[2], MAX_X - 1, MAX_Y - 1);
+               calibrate(screen, wiimote, &calib[3], 0, MAX_Y - 1);
        }
 
        /* Draw borders, put them in list. */
@@ -966,14 +967,46 @@ int main(int argc, char *argv[])
                ball.pos = new;
                SDL_Delay(25);
 
-               if (SDL_PollEvent(&event)
-                   && (event.type == SDL_QUIT
-                       || (event.type == SDL_KEYDOWN
-                           && event.key.keysym.sym == SDLK_ESCAPE))) {
-                       SDL_Quit();
-                       return 0;
+               while (SDL_PollEvent(&event)) {
+                       if (event.type == SDL_QUIT
+                           || (event.type == SDL_KEYDOWN
+                               && event.key.keysym.sym == SDLK_ESCAPE)) {
+                               SDL_Quit();
+                               return 0;
+                       }
+                       if (mouse) {
+                               switch (event.type) {
+                               case SDL_MOUSEBUTTONDOWN:
+                                       drawing = true;
+                                       break;
+                               case SDL_MOUSEBUTTONUP:
+                                       drawing = false;
+                                       break;
+                               case SDL_MOUSEMOTION:
+                                       if (!drawing)
+                                               break;
+
+                                       n = new_line(event.motion.x,
+                                                    event.motion.y,
+                                                    event.motion.x
+                                                    + event.motion.xrel,
+                                                    event.motion.y
+                                                    + event.motion.yrel,
+                                                    calib);
+
+                                       if (n) {
+                                               timeradd(&now, &line_life,
+                                                        &n->expires);
+                                               list_add_tail(&lines, &n->list);
+                                               thick_line(screen, n, 0);
+                                       }
+                               }
+                       }
                }
 
+               if (mouse)
+                       continue;
+
                if (cwiid_get_state(wiimote, &state))
                        errx(1, "No wii state");
 
@@ -989,8 +1022,6 @@ int main(int argc, char *argv[])
                if (ir->valid) {
                        /* Give it some slack for missing one or two... */
                        if (time_since_last_ir <= 5) {
-                               struct line_segment *n;
-
                                n = new_line(last_ir.pos[0],
                                             last_ir.pos[1],
                                             ir->pos[0],