Skip to content

Instantly share code, notes, and snippets.

Created Sep 8, 2012
Embed
What would you like to do?
SDL 2 gesture detection
#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