void loop() { // Make sure we don't update the map tile on screen when we don't need to! uint8_t update_display_window = 0; if ( first_time ) { first_time = 0; update_display_window = 1; } // Joystick displacement. int16_t dx = 0; int16_t dy = 0; uint8_t select_button_event = 0; // If the map has been zoomed in or out we need to do a redraw, // and will center the display window about the cursor. // So a zoom in-out will re-center over a mis-positioned cursor! // if the map changed as a result of a zoom button press if (shared_new_map_num != current_map_num) { #ifdef DEBUG_SCROLLING Serial.print("Zoom from "); Serial.print(current_map_num); Serial.print(" x "); Serial.print(cursor_map_x); Serial.print(" y "); Serial.print(cursor_map_y); #endif // change the map and figure out the position of the cursor on // the new map. set_zoom(); // center the display window around the cursor move_window_to( cursor_map_x - display_window_width/2, cursor_map_y - display_window_height/2); #ifdef DEBUG_SCROLLING Serial.print(" to "); Serial.print(current_map_num); Serial.print(" x "); Serial.print(cursor_map_x); Serial.print(" y "); Serial.print(cursor_map_y); Serial.println(); #endif // Changed the zoom level, so we want to redraw the window update_display_window = 1; } // Now, see if the joystick has moved, in which case we want to // also want to move the visible cursor on the screen. // Process joystick input. select_button_event = process_joystick(&dx, &dy); // the joystick routine filters out small changes, so anything non-0 // is a real movement if ( abs(dx) > 0 || abs(dy) > 0 ) { // redraw the path if the cursor moves: (brute force yay) // comment out if you find it runs too slowly, and live with the // cursor erasing the path if ( path_length > 0 ) { draw_path(path_length, path, current_map_num); } // Is the cursor getting near the edge of the screen? If so // then scroll the map over by re-centering the window. uint16_t new_screen_map_x = screen_map_x; uint16_t new_screen_map_y = screen_map_y; uint8_t need_to_move = 0; uint16_t cursor_screen_x; uint16_t cursor_screen_y; if ( get_cursor_screen_x_y(&cursor_screen_x, &cursor_screen_y) ) { // if the cursor is visible, then adjust the display to // to scroll if near the edge. if ( cursor_screen_x < screen_left_margin ) { new_screen_map_x = screen_map_x - screen_scroll_delta; move_cursor_by(3, 0); need_to_move = 1; } else if ( cursor_screen_x > screen_right_margin ) { new_screen_map_x = screen_map_x + screen_scroll_delta; move_cursor_by(-3, 0); need_to_move = 1; } if ( cursor_screen_y < screen_top_margin ) { new_screen_map_y = screen_map_y - screen_scroll_delta; move_cursor_by(0, 3); need_to_move = 1; } else if ( cursor_screen_y > screen_bottom_margin ) { new_screen_map_y = screen_map_y + screen_scroll_delta; move_cursor_by(0, -3); need_to_move = 1; } if ( need_to_move ) { // move the display window, leaving cursor at same lat-lon move_window_to(new_screen_map_x, new_screen_map_y); update_display_window = 1; } else { // erase old cursor, move, and draw new one, no need to // redraw the underlying map tile erase_cursor(); move_cursor_by(dx, dy); draw_cursor(); } } } // at this point the screen is updated, with a new tile window and // cursor position if necessary // will only be down once, then waits for a min time before allowing // pres again. if (select_button_event) { // Button was pressed, we are selecting a point! #ifdef DEBUG_PATH Serial.print("x "); Serial.print(cursor_map_x); Serial.print(" y "); Serial.print(cursor_map_y); Serial.println(); #endif // which press is this, the start or the stop selection? // If we are making a request to find a shortest path, we will send out // the request on the serial port and then wait for a response from the // server. While this is happening, the client user interface is // suspended. // if the stop point, then we send out the server request and wait. if ( request_state == 0 ) { // collect the start point start_lat = cursor_lat; start_lon = cursor_lon; request_state = 1; } else if ( request_state == 1) { // collect the stop point stop_lat = cursor_lat; stop_lon = cursor_lon; request_state = 0; // send out the start and stop coordinates to the server Serial.print(start_lat); Serial.print(" "); Serial.print(start_lon); Serial.print(" "); Serial.print(stop_lat); Serial.print(" "); Serial.print(stop_lon); Serial.println(); // free any existing path if ( path_length > 0 ) { free(path); } // read the path from the serial port status_msg("WAITING"); if ( read_path(&path_length, &path) ) { #ifdef DEBUG_PATH uint8_t is_visible; for (uint16_t i=0; i < path_length; i++) { is_visible = is_coord_visible(path[i]); Serial.print(i); Serial.print(": "); Serial.print(path[i].lat); Serial.print(","); Serial.print(path[i].lon); Serial.print(is_visible ? "V": ""); Serial.println(); } #endif update_display_window = 1; } else { // should display this error on the screen Serial.print("Path read error, code "); Serial.println(path_errno); if ( path_errno == 1 ) { status_msg("Path too long"); delay(5000); } } } } // end of select_button_event processing // do we have to redraw the map tile? if (update_display_window) { #ifdef DEBUG_SCROLLING Serial.println("Screen update"); Serial.print(current_map_num); Serial.print(" "); Serial.print(cursor_lon); Serial.print(" "); Serial.print(cursor_lat); Serial.println(); #endif draw_map_screen(); draw_cursor(); // Need to redraw any other things that are on the screen if ( path_length > 0 ) { draw_path(path_length, path, current_map_num); } // force a redisplay of status message clear_status_msg(); } // always update the status message area if message changes // Indicate which point we are waiting for if ( request_state == 0 ) { status_msg("FROM?"); } else { status_msg("TO?"); } }
/****** Handle Input From Keyboard ******/ void DMG_GamePad::handle_input(SDL_Event &event) { //Key Presses if(event.type == SDL_KEYDOWN) { pad = event.key.keysym.sym; process_keyboard(pad, true); } //Key Releases else if(event.type == SDL_KEYUP) { pad = event.key.keysym.sym; process_keyboard(pad, false); } //Joystick Button Presses else if(event.type == SDL_JOYBUTTONDOWN) { pad = 100 + event.jbutton.button; process_joystick(pad, true); } //Joystick Button Releases else if(event.type == SDL_JOYBUTTONUP) { pad = 100 + event.jbutton.button; process_joystick(pad, false); } //Joystick axes else if(event.type == SDL_JOYAXISMOTION) { pad = 200 + (event.jaxis.axis * 2); int axis_pos = event.jaxis.value; if(axis_pos > 0) { pad++; } else { axis_pos *= -1; } if(axis_pos > config::dead_zone) { process_joystick(pad, true); } else { process_joystick(pad, false); } } //Joystick hats else if(event.type == SDL_JOYHATMOTION) { pad = 300; pad += event.jhat.hat * 4; switch(event.jhat.value) { case SDL_HAT_LEFT: process_joystick(pad, true); process_joystick(pad+2, false); break; case SDL_HAT_LEFTUP: process_joystick(pad, true); process_joystick(pad+2, true); break; case SDL_HAT_LEFTDOWN: process_joystick(pad, true); process_joystick(pad+3, true); break; case SDL_HAT_RIGHT: process_joystick(pad+1, true); process_joystick(pad+2, false); break; case SDL_HAT_RIGHTUP: process_joystick(pad+1, true); process_joystick(pad+2, true); break; case SDL_HAT_RIGHTDOWN: process_joystick(pad+1, true); process_joystick(pad+3, true); break; case SDL_HAT_UP: process_joystick(pad+2, true); process_joystick(pad, false); break; case SDL_HAT_DOWN: process_joystick(pad+3, true); process_joystick(pad, false); break; case SDL_HAT_CENTERED: process_joystick(pad, false); process_joystick(pad+2, false); break; } } }