Created
September 8, 2012 05:36
-
-
Save anonymous/3672150 to your computer and use it in GitHub Desktop.
SDL 2 gesture detection
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifdef TCOD_ANDROID | |
#include <android/log.h> | |
#define MAX_GESTURE_COORDS 4000 | |
#define MAX_GESTURES 3 | |
#ifndef PRIs32 | |
#define PRIs32 "d" | |
#endif | |
#ifndef PRIs64 | |
#ifdef __WIN32__ | |
#define PRIs64 "I64" | |
#else | |
#define PRIs64 "lld" | |
#endif | |
#endif | |
#define GESTURE_ERROR_RECORDING_OVERFLOW (1 << 0) | |
#define GESTURE_ERROR_RECORDING_DENIED (1 << 1) | |
void render_gesture_chars(unsigned short *coords, int min_coord, int max_coord) { | |
int i, lcx, lcy; | |
for (i=min_coord; i<max_coord; i++) { | |
lcx = (int)coords[i*2+0]; | |
lcy = (int)coords[i*2+1]; | |
TCOD_console_set_char_background(NULL,lcx,lcy,TCOD_green,TCOD_BKGND_SET); | |
TCOD_console_set_char(NULL,lcx,lcy,TCOD_CHAR_BLOCK3); | |
} | |
} | |
void render_gestures(bool first, TCOD_key_t*key, TCOD_mouse_t *mouse) { | |
SDL_Event event; | |
SDL_Touch *touch; | |
int i, cx=0, cy=1; | |
TCOD_console_clear(sample_console); | |
TCOD_console_set_default_foreground(sample_console,TCOD_white); | |
if (SDL_GetNumTouch() == 1) { | |
if (key->c == 'r') { | |
if (SDL_RecordGesture(-1)) { | |
int font_width, font_height; | |
int fullscreen_offsetx, fullscreen_offsety; | |
int scale_width, scale_height, actual_width, actual_height; | |
int rows, cols, num_detections = 0, error_flags = 0, exit_keypress = 0, num_moves = 0; | |
unsigned short num_coords = 0, num_gestures = 0; | |
unsigned short coords[MAX_GESTURE_COORDS]; | |
unsigned short gestures[MAX_GESTURES]; | |
SDL_Event events[MAX_GESTURES]; | |
SDL_Event last_detect_event; | |
TCOD_sys_get_char_size(&font_width, &font_height); | |
TCOD_sys_get_fullscreen_offsets(&fullscreen_offsetx, &fullscreen_offsety); | |
TCOD_sys_get_fullscreen_scale_size(&scale_width, &scale_height); | |
TCOD_sys_get_fullscreen_size(&actual_width, &actual_height); | |
cols = TCOD_console_get_width(NULL); | |
rows = TCOD_console_get_height(NULL); | |
/* Mark the start of the coords for the first gesture. */ | |
gestures[num_gestures] = num_coords; | |
while (num_gestures < MAX_GESTURES || exit_keypress == 0) { | |
int lcx, lcy; | |
cx = SAMPLE_SCREEN_X+1; | |
cy = SAMPLE_SCREEN_Y+1; | |
/* Poor man's console clear. */ | |
TCOD_console_blit(sample_console,0,0,SAMPLE_SCREEN_WIDTH,SAMPLE_SCREEN_HEIGHT, /* the source console & zone to blit */ | |
NULL,SAMPLE_SCREEN_X,SAMPLE_SCREEN_Y, /* the destination console & position */ | |
1.0f,1.0f /* alpha coefs */ | |
); | |
TCOD_console_set_default_foreground(NULL,TCOD_white); | |
TCOD_console_set_default_background(NULL,TCOD_black); | |
if (error_flags & GESTURE_ERROR_RECORDING_DENIED) { | |
TCOD_console_print(NULL,cx,cy++,"Failed recording a gesture:"); | |
TCOD_console_print(NULL,cx,cy++,"SDL wouldn't let you."); | |
} else if (error_flags & GESTURE_ERROR_RECORDING_OVERFLOW) { | |
TCOD_console_print(NULL,cx,cy++,"Failed recording a gesture:"); | |
TCOD_console_print(NULL,cx,cy++,"Too many motion events, no end detected."); | |
} else { | |
if (num_gestures < MAX_GESTURES) { | |
render_gesture_chars(coords, gestures[num_gestures], num_coords); | |
TCOD_console_print(NULL,cx,cy++,"Recording gesture %d/%d: ",num_gestures+1,MAX_GESTURES); | |
TCOD_console_print(NULL,cx,cy++,"Press finger, move it, lift it. "); | |
} else { | |
TCOD_console_print(NULL,cx,cy++,"Gesture detection test (%d known gestures).",MAX_GESTURES); | |
TCOD_console_print(NULL,cx,cy++,"Press back key to exit at any time. "); | |
} | |
cy+=5; | |
for (i=0; i<num_gestures; i++) { | |
TCOD_console_print(NULL,cx,cy++,"Recorded gesture %d: gestureId %"PRIs64" ",i+1,events[i].dgesture.gestureId); | |
} | |
cy+=2; | |
if (num_detections > 0) { | |
if (num_moves == 0) { | |
int j; | |
for (j=0; j<num_gestures; j++) { | |
if (last_detect_event.dgesture.gestureId == events[j].dgesture.gestureId) { | |
TCOD_console_print(NULL,cx,cy++,"Detected gesture #%d (%d gesture detections).", j+1, num_detections); | |
TCOD_console_print(NULL,cx,cy++,"Error: %f", events[j].dgesture.error); | |
if (j == MAX_GESTURES-1) | |
render_gesture_chars(coords, gestures[j], num_coords); | |
else | |
render_gesture_chars(coords, gestures[j], gestures[j+1]); | |
break; | |
} | |
} | |
} else { | |
TCOD_console_print(NULL,cx,cy++,"Detecting gesture, %d moves counted.", num_moves); | |
} | |
} | |
} | |
if (SDL_PollEvent(&event)) { | |
SDL_TouchFingerEvent *event_finger; | |
SDL_Touch *event_touch; | |
int x, y; | |
switch (event.type) { | |
case SDL_FINGERMOTION: | |
/* While a gesture is recording, display some visual indication. */ | |
if (num_gestures < MAX_GESTURES && error_flags == 0) { | |
event_finger=&event.tfinger; | |
event_touch=SDL_GetTouch(event_finger->touchId); | |
x = (event_finger->x * actual_width)/event_touch->xres; | |
y = (event_finger->y * actual_height)/event_touch->yres; | |
if (scale_width != 0) { | |
lcx = ((x - fullscreen_offsetx) * cols) / scale_width; | |
lcy = ((y - fullscreen_offsety) * rows) / scale_height; | |
} else { | |
lcx = (x - fullscreen_offsetx) / font_width; | |
lcy = (y - fullscreen_offsety) / font_height; | |
} | |
TCOD_console_set_char_background(NULL,lcx,lcy,TCOD_green,TCOD_BKGND_SET); | |
TCOD_console_set_char(NULL,lcx,lcy,TCOD_CHAR_BLOCK3); | |
if (num_coords*2 >= MAX_GESTURE_COORDS) { | |
error_flags = GESTURE_ERROR_RECORDING_OVERFLOW; | |
} else { | |
coords[num_coords*2+0] = (unsigned short)lcx; | |
coords[num_coords*2+1] = (unsigned short)lcy; | |
num_coords += 1; | |
} | |
} else if (error_flags == 0) { | |
num_moves += 1; | |
} | |
break; | |
case SDL_KEYDOWN: | |
/* A gesture was recorded, now wait for the user to acknowledge it. */ | |
if (num_gestures == MAX_GESTURES) { | |
switch(event.key.keysym.scancode) { | |
case SDL_SCANCODE_AC_BACK: | |
exit_keypress = 1; | |
break; | |
} | |
} | |
break; | |
case SDL_DOLLARRECORD: | |
/* A gesture was being recorded, and SDL acknowledged it finished. */ | |
events[num_gestures] = event; | |
num_gestures += 1; | |
/* If there are further gestures to record, mark the start of their coords. */ | |
if (num_gestures < MAX_GESTURES) { | |
gestures[num_gestures] = num_coords; | |
/* Start SDL recording the next gesture. */ | |
if (!SDL_RecordGesture(-1)) | |
error_flags = GESTURE_ERROR_RECORDING_DENIED; | |
} | |
break; | |
case SDL_DOLLARGESTURE: | |
num_detections += 1; | |
num_moves = 0; | |
last_detect_event = event; | |
break; | |
} | |
} | |
TCOD_console_flush(); | |
} | |
} | |
} else { | |
TCOD_console_print(sample_console,1,cy++,"Detected touch pads:"); | |
for (i=0; i<SDL_GetNumTouch();i++) { | |
touch = (SDL_Touch*)SDL_GetTouchIndex(i); | |
TCOD_console_print(sample_console,1,cy++,"#%d: %li %lx",i,touch->id,touch->id); | |
} | |
TCOD_console_print(sample_console,1,cy++,"Press 'r' to start recording."); | |
} | |
} else if (SDL_GetNumTouch() > 1) { | |
TCOD_console_print(sample_console,1,cy++,"Too many touch pads."); | |
TCOD_console_print(sample_console,1,cy++,"Programmer hasn't handled this."); | |
} else { | |
TCOD_console_print(sample_console,1,cy++,"No known touch pad."); | |
TCOD_console_print(sample_console,1,cy++,"Please touch it, so SDL can see it."); | |
} | |
} | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment