Commits

ric...@richard-lap.telecom.wifi  committed bd0d534

- Added multigesture page. This just displays the value of SDL mgesture events.
- Added coregesture page. This currently just allows drawing, the stroke and
other core gesture detection is in the process of being written.
- Upped version number for last release.
- Fixed bug where gestures with one coord were not drawn, only gestures with
more than one coord were.
- Formalised pages, particularly non-gesture ones, with defined constants.

  • Participants
  • Parent commits 92eb8ae

Comments (0)

Files changed (2)

File AndroidManifest.xml

 <?xml version="1.0" encoding="utf-8"?>
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
       package="org.disinterest.gestures"
-      android:versionCode="3"
-      android:versionName="1.02">
+      android:versionCode="4"
+      android:versionName="1.03">
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
 <uses-sdk android:minSdkVersion="8"/>
     <application android:label="@string/app_name" android:icon="@drawable/icon" android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen">

File jni/src/main.c

+/*
+ * Android SDL 2.0 gesture testing application.
+ *
+ * TODO: Finger down event should be consistently processed as a touch move event.
+ *
+ */
+
 #include "libtcod.h"
 #define _SDL_main_h
 #include <SDL.h>
 #define MAX_GESTURE_COORDS 200
 #define MAX_GESTURES 20
 #define MAX_FINGERS 3
+
 #define MAX_EVENTS_POLLED_PER_FRAME 20
+#define NORMAL_TOUCH_CLOCKS CLOCKS_PER_SEC
+
+/* The main menu page defines. */
+#define EXTRA_MAIN_PAGES 3
+/* These should be in range from EXTRA_MAIN_PAGES to -1 */
+#define COREGESTURES_MAIN_PAGE	-EXTRA_MAIN_PAGES+2
+#define MULTIGESTURE_MAIN_PAGE	-EXTRA_MAIN_PAGES+1
+#define ADD_MAIN_PAGE 			-EXTRA_MAIN_PAGES+0
 
 #define Y_LOWER_GAP 1
 
 static SDL_TouchID touch_id;
 static int app_flags;
 static int console_width, console_height;
-static int gesture_index = -1, gesture_count;
+static int gesture_index = ADD_MAIN_PAGE, gesture_count;
 static struct _gesture *gestures[MAX_GESTURES];
 
 int get_gesture_finger_index(struct _gesture *gesture, SDL_FingerID finger_id) {
 		while (coord_index < gesture->coord_count && running_finger_coord_count < used_finger_coord_count) {
 			/* Only pay attention to the coords for the given finger. */
 			if (gesture->coords[coord_index].finger_index == finger_index) {
+				/* Only one coord for the finger, just plot it. */
+				if (used_finger_coord_count == 1) {
+					int cx = gesture->coords[coord_index].cx, cy = gesture->coords[coord_index].cy;
+					TCOD_console_set_char_background(NULL, cx, cy, color, TCOD_BKGND_SET);
+					TCOD_console_set_char(NULL, cx, cy, '0'+finger_index);
+					break;
+				}
+				/* Otherwise from the second coord on, draw lines to connect to the preceding one. */
 				if (last_finger_coord_index != -1) {
 					int cx = gesture->coords[last_finger_coord_index].cx, cy = gesture->coords[last_finger_coord_index].cy;
 					TCOD_line_init(cx, cy, gesture->coords[coord_index].cx, gesture->coords[coord_index].cy);
 			}
 		}
 
+		TCOD_console_set_default_foreground(NULL, TCOD_white);
 		TCOD_console_set_default_background(NULL, TCOD_black);
 		TCOD_console_clear(NULL);
 
 		}
 	}
 
+	TCOD_console_set_default_foreground(NULL, TCOD_white);
 	TCOD_console_set_default_background(NULL, TCOD_black);
 	TCOD_console_clear(NULL);
 
 			}
 		}
 
+		TCOD_console_set_default_foreground(NULL, TCOD_white);
 		TCOD_console_set_default_background(NULL, TCOD_black);
 		TCOD_console_clear(NULL);
 
 	return;
 }
 
+/*
+ * This should display what the user draws, then show any reported multigesture
+ * event fields over the top of it.
+ *
+ * TODO: Drawing the gesture in the standard way, collects events and hits the
+ * too many event error.  Better to not draw..
+ */
+void show_multigesture_test_menu() {
+	SDL_Event event;
+	int frame_cx = 0,
+		frame_cy = 0,
+		frame_cw = console_width,
+		frame_ch = console_height - Y_LOWER_GAP,
+		have_match = 0;
+	static int cy = 2;
+	int skip_count = 0, last_was_skip = 0, do_clear = 1;
+
+	do {
+		int num_events_polled = 0;
+
+		/* Do an initial console clear as we will not be doing one once per frame. */
+		if (do_clear) {
+			do_clear = 0;
+
+			TCOD_console_set_default_foreground(NULL, TCOD_white);
+			TCOD_console_set_default_background(NULL, TCOD_black);
+			TCOD_console_clear(NULL);
+			TCOD_console_print_frame(NULL, frame_cx, frame_cy, frame_cw, frame_ch, 1, TCOD_BKGND_NONE, "MULTIGESTURE TEST PAGE");
+		}
+
+		while (num_events_polled++ < MAX_EVENTS_POLLED_PER_FRAME && SDL_PollEvent(&event)) {
+			switch (event.type) {
+			case SDL_MULTIGESTURE:
+				if (event.mgesture.touchId == touch_id) {
+					if (fabs(event.mgesture.dDist) + 0.0001f <= 0.002) {
+						skip_count += 1;
+						if (last_was_skip)
+							cy -= 1;
+						TCOD_console_print_ex(NULL, 1, cy++, TCOD_BKGND_NONE, TCOD_LEFT, "Skipped %d events                                            ", skip_count);
+						last_was_skip = 1;
+					} else {
+						TCOD_console_print_ex(NULL, 1, cy++, TCOD_BKGND_NONE, TCOD_LEFT, \
+								"dTheta: %0.3f dDist: %0.3f X: %0.3f Y: %0.3f numFingers: %d        ",
+								event.mgesture.dTheta,event.mgesture.dDist, event.mgesture.x, event.mgesture.y, event.mgesture.numFingers);
+						skip_count = 0;
+						last_was_skip = 0;
+					}
+					/* Wrap around. */
+					if (cy == frame_cy+frame_ch-2) {
+						do_clear = 1;
+						cy = frame_cy+2;
+					}
+				}
+				break;
+			case SDL_KEYDOWN:
+				switch (event.key.keysym.scancode) {
+				case SDL_SCANCODE_ESCAPE:
+				case SDL_SCANCODE_AC_BACK:
+					return;
+				}
+				break;
+			case SDL_WINDOWEVENT :
+				switch (event.window.event) {
+				case SDL_WINDOWEVENT_RESTORED:
+					TCOD_sys_set_clear_screen();
+					break;
+				}
+				break;
+			}
+		}
+
+		TCOD_console_flush();
+	} while (!TCOD_console_is_window_closed());
+
+	return;
+}
+
+/*
+ * TODO: Combine detection of simple "core" gestures with detection of dollar gestures.
+ *
+ * Core gestures:
+ * - Swipe.
+ * 	 - Finger down and movement away from the initial point within a set time in a relatively fixed direction.
+ * - Normal touch.
+ * 	 - Finger down and finger up within a set time without significant movement.
+ * - Long touch.
+ * 	 - Finger down and finger up outside of a set time.  Movement may occur after the time.
+ * - Pinching.
+ * 	 - Two fingers down move towards or away from each other in relatively fixed direction.
+ *
+ * The dollar gesture match should only be used if no core gesture was recognised.
+ *
+ * Is it possible to narrow it down with flags (all imply only one finger)?
+ *
+ * a) time passed
+ * b) touch moved, not just shifting at same approximate spot
+ * c) movement goes in a relatively fixed direction
+ *
+ * .. swipe: b+c, normal touch: !a+!b, long touch: a+!b
+ *
+ * Swipe information:
+ * - swipe distance = point N - point 0.
+ * - max drift angle
+ * - all points should be same or further distance from point 0.
+ *
+ * What if it is naively determined?
+ * Any movement that only proceeds in one general direction where the short axis is determinably
+ * negligible compared to the long axis. Just need to get a simple implementation working that
+ * handles any direction.
+ *
+ * First point.
+ * Last point.
+ * Current point.
+ * Average direction.
+ * Average direction = normalize(average direction + (current point - last point))
+ */
+void show_coregestures_test_menu() {
+	SDL_Event event;
+	struct _gesture *temp_gesture = alloca(SIZEOF_GESTURE(MAX_GESTURE_COORDS));
+	int frame_cx = 0,
+		frame_cy = 0,
+		frame_cw = console_width,
+		frame_ch = console_height - Y_LOWER_GAP;
+	int fingers_in_use, long_press;
+	double direct_distance, path_distance;
+	float dx_sum, dy_sum;
+	int clocks_start, clocks_end;
+	unsigned short cx0, cy0, cxN, cyN;
+	Sint16 x0, y0, xN, yN;
+	float dx_average, dy_average;
+
+	INIT_GESTURE(temp_gesture);
+
+	fingers_in_use = long_press = 0;
+	dx_sum = dy_sum = 0.0f;
+	clocks_start = clocks_end = 0;
+	do {
+		int cx = 0, cy = 0;
+		int num_events_polled = 0;
+
+		while (num_events_polled++ < MAX_EVENTS_POLLED_PER_FRAME && SDL_PollEvent(&event)) {
+			switch (event.type) {
+			case SDL_FINGERDOWN:
+				if (event.tfinger.touchId == touch_id) {
+					if (fingers_in_use == 0) {
+						SDL_Touch *touch = SDL_GetTouch(event.tfinger.touchId);
+						cx0 = cxN = (event.tfinger.x * console_width) / touch->xres;
+						cy0 = cxN = (event.tfinger.y * console_height) / touch->yres;
+
+						long_press = 0;
+						direct_distance = path_distance = 0.0;
+						dx_sum = dy_sum = 0.0f;
+						clocks_start = clock();
+						INIT_GESTURE(temp_gesture);
+						process_fingermotion_event(&event, temp_gesture);
+					}
+					fingers_in_use += 1;
+				}
+				break;
+			case SDL_FINGERUP:
+				if (event.tfinger.touchId == touch_id) {
+					fingers_in_use -= 1;
+				}
+				if (fingers_in_use == 0) {
+					int cxN_last = cxN, cyN_last = cyN;
+					SDL_Touch *touch = SDL_GetTouch(event.tfinger.touchId);
+					cxN = (event.tfinger.x * console_width) / touch->xres;
+					cyN = (event.tfinger.y * console_height) / touch->yres;
+					clocks_end = clock();
+
+					long_press = (clocks_end - clocks_start) > NORMAL_TOUCH_CLOCKS;
+					direct_distance = sqrt(pow(cxN-cx0,2)+pow(cyN-cy0,2));
+					path_distance += sqrt(pow(cxN-cxN_last,2)+pow(cyN-cyN_last,2));
+				}
+				break;
+			case SDL_FINGERMOTION:
+				if (event.tfinger.touchId == touch_id && fingers_in_use > 0) {
+					int cxN_last = cxN, cyN_last = cyN;
+					SDL_Touch *touch = SDL_GetTouch(event.tfinger.touchId);
+					cxN = (event.tfinger.x * console_width) / touch->xres;
+					cyN = (event.tfinger.y * console_height) / touch->yres;
+					direct_distance = sqrt(pow(cxN-cx0,2)+pow(cyN-cy0,2));
+					path_distance += sqrt(pow(cxN-cxN_last,2)+pow(cyN-cyN_last,2));
+
+					process_fingermotion_event(&event, temp_gesture);
+					dx_sum += (float)event.tfinger.dx/touch->xres;
+					dy_sum += (float)event.tfinger.dy/touch->yres;
+				}
+				break;
+			case SDL_KEYDOWN:
+				switch (event.key.keysym.scancode) {
+				case SDL_SCANCODE_ESCAPE:
+				case SDL_SCANCODE_AC_BACK:
+					return;
+				}
+				break;
+			case SDL_WINDOWEVENT :
+				switch (event.window.event) {
+				case SDL_WINDOWEVENT_RESTORED:
+					TCOD_sys_set_clear_screen();
+					break;
+				}
+				break;
+			}
+		}
+
+		TCOD_console_set_default_foreground(NULL, TCOD_white);
+		TCOD_console_set_default_background(NULL, TCOD_black);
+		TCOD_console_clear(NULL);
+
+		if (fingers_in_use) {
+			draw_gesture_coords(temp_gesture, TCOD_white, 1.0);
+			clocks_end = clock();
+		} else {
+			draw_gesture_coords(temp_gesture, TCOD_grey, 1.0);
+		}
+
+		TCOD_console_set_default_foreground(NULL, TCOD_white);
+		TCOD_console_print_frame(NULL, frame_cx, frame_cy, frame_cw, frame_ch, 1, TCOD_BKGND_NONE, "TESTING \"CORE\" GESTURES", gesture_index+1);
+		if (temp_gesture->coord_count) {
+			struct _gesture_coord *temp_coord = &(temp_gesture->coords[temp_gesture->coord_count-1]);
+			cx = temp_coord->cx;
+			cy = temp_coord->cy;
+		}
+		TCOD_console_print_ex(NULL, frame_cx+2, frame_cy+2, TCOD_BKGND_NONE, TCOD_LEFT, "MOVE: %0.2f,%0.2f\nTIME: %0.1fs\nPOS: %d,%d\nDISTANCE: %d\nPATH LEN: %d", dx_sum, dy_sum, (float)(clocks_end-clocks_start)/CLOCKS_PER_SEC, cx, cy, (int)direct_distance, (int)path_distance);
+		TCOD_console_print_ex(NULL, console_width-1, frame_cy+frame_ch, TCOD_BKGND_NONE, TCOD_RIGHT, "% 3d recorded events", temp_gesture->coord_count);
+
+		TCOD_console_flush();
+	} while (!TCOD_console_is_window_closed());
+
+	return;
+}
+
 void show_gesture_test_menu() {
 	SDL_Event event;
 	struct _gesture *temp_gesture = alloca(SIZEOF_GESTURE(MAX_GESTURE_COORDS));
 			}
 		}
 
+		TCOD_console_set_default_foreground(NULL, TCOD_white);
 		TCOD_console_set_default_background(NULL, TCOD_black);
 		TCOD_console_clear(NULL);
 
 					if (gesture_index < gesture_count-1)
 						gesture_index += 1;
 					else
-						gesture_index = -1;
+						gesture_index = -EXTRA_MAIN_PAGES;
 				} else if (cx > tx) { /* Center - select */
 #ifndef NDEBUG
 					__android_log_print(ANDROID_LOG_INFO, "gestures", "SELECT GESTURE: %d, %d", cx, cy);
 #endif
-					if (gesture_index == -1)
+					if (gesture_index == ADD_MAIN_PAGE)
 						show_gesture_addition_menu();
+					else if (gesture_index == COREGESTURES_MAIN_PAGE)
+						show_coregestures_test_menu();
+					else if (gesture_index == MULTIGESTURE_MAIN_PAGE)
+						show_multigesture_test_menu();
 					else
 						show_gesture_test_menu();
 				} else { /* LHS - previous */
-					if (gesture_index > -1)
+					if (gesture_index > -EXTRA_MAIN_PAGES)
 						gesture_index -= 1;
 					else
 						gesture_index = gesture_count-1;
 		}
 	}
 
-	//__android_log_print(ANDROID_LOG_INFO, "gestures", "text %d", 1);
+	TCOD_console_set_default_foreground(NULL, TCOD_white);
 	TCOD_console_set_default_background(NULL, TCOD_black);
-	//__android_log_print(ANDROID_LOG_INFO, "gestures", "text %d", 2);
 	TCOD_console_clear(NULL);
 
-	if (gesture_index == -1) {
+	if (gesture_index == ADD_MAIN_PAGE) {
 		TCOD_console_print_frame(NULL, frame_cx, frame_cy, frame_cw, frame_ch, 1, TCOD_BKGND_NONE, "ADD A NEW GESTURE");
-		if (gesture_count)
-			TCOD_console_print_rect_ex(NULL, frame_cx+frame_cw/2, frame_cy+frame_ch/2-2, frame_cw-2, frame_ch-2, TCOD_BKGND_NONE, TCOD_CENTER, "<-- GESTURE %d          GESTURE %d -->", gesture_count, 1);
-		TCOD_console_print_rect_ex(NULL, frame_cx+frame_cw/2, frame_cy+frame_ch/2, frame_cw-2, frame_ch-2, TCOD_BKGND_NONE, TCOD_CENTER, "Touch left-hand side to go back one gesture.\nTouch center to select current page.\nTouch right-hand side to go forward one gesture.");
-		TCOD_console_print_rect_ex(NULL, frame_cx+frame_cw/2, frame_cy+frame_ch, frame_cw-2, 1, TCOD_BKGND_NONE, TCOD_CENTER, "Select this page to enter a new gesture");
-	} else {
+		TCOD_console_print_rect_ex(NULL, frame_cx+frame_cw/2, frame_cy+frame_ch, frame_cw-2, 1, TCOD_BKGND_NONE, TCOD_CENTER, "Select to enter a new gesture");
+	} else if (gesture_index == MULTIGESTURE_MAIN_PAGE) {
+		TCOD_console_print_frame(NULL, frame_cx, frame_cy, frame_cw, frame_ch, 1, TCOD_BKGND_NONE, "MULTIGESTURE TESTING");
+		TCOD_console_print_rect_ex(NULL, frame_cx+frame_cw/2, frame_cy+frame_ch, frame_cw-2, 1, TCOD_BKGND_NONE, TCOD_CENTER, "Select to test multigesture events");
+	} else if (gesture_index == COREGESTURES_MAIN_PAGE) {
+		TCOD_console_print_frame(NULL, frame_cx, frame_cy, frame_cw, frame_ch, 1, TCOD_BKGND_NONE, "\"CORE\" GESTURE TESTING");
+		TCOD_console_print_rect_ex(NULL, frame_cx+frame_cw/2, frame_cy+frame_ch, frame_cw-2, 1, TCOD_BKGND_NONE, TCOD_CENTER, "Select to test the \"core\" gesture events");
+	} else if (gesture_index >= 0 && gesture_index < gesture_count) {
 		double PERIOD_S = 3.0f;
 		int clock_diff = clock() - last_clock;
 		double clock_diff_seconds = (double)clock_diff / CLOCKS_PER_SEC;
 		double draw_fraction = (clock_diff_seconds - floor(clock_diff_seconds / PERIOD_S) * PERIOD_S) / PERIOD_S;
 
-	//__android_log_print(ANDROID_LOG_INFO, "gestures", "t0=%d, tn=%0.3f, f=%0.3f", last_clock, clock_diff_seconds, draw_fraction);
-	//__android_log_print(ANDROID_LOG_INFO, "gestures", "text %d", 3);
 		TCOD_console_print_frame(NULL, frame_cx, frame_cy, frame_cw, frame_ch, 1, TCOD_BKGND_NONE, "GESTURE %d", gesture_index+1);
 		/* Draw full gesture as grey backdrop. */
-	//__android_log_print(ANDROID_LOG_INFO, "gestures", "text %d", 4);
 		draw_gesture_coords(gestures[gesture_index], TCOD_grey, 1.0);
 		/* Gradually re-overlay gesture in green to show as drawn. */
-	//__android_log_print(ANDROID_LOG_INFO, "gestures", "text %d", 5);
 		draw_gesture_coords(gestures[gesture_index], TCOD_green, draw_fraction);
-	//__android_log_print(ANDROID_LOG_INFO, "gestures", "text %d", 6);
+		/* Restore default background colour. */
+		TCOD_console_set_default_background(NULL, TCOD_black);
 		TCOD_console_print_rect_ex(NULL, frame_cx+frame_cw/2, frame_cy+frame_ch, frame_cw-2, 1, TCOD_BKGND_NONE, TCOD_CENTER, "Select this page to test this gesture");
+	} else {
+		TCOD_console_print_rect_ex(NULL, frame_cx+frame_cw/2, frame_cy+frame_ch, frame_cw-2, 1, TCOD_BKGND_NONE, TCOD_CENTER, "Error displaying gesture index %d", gesture_index);
 	}
+	TCOD_console_print_rect_ex(NULL, frame_cx+frame_cw/2, frame_cy+frame_ch/2, frame_cw-2, frame_ch-2, TCOD_BKGND_SET, TCOD_CENTER, "Touch left-hand side to go back one gesture.\nTouch center to select current page.\nTouch right-hand side to go forward one gesture.");
+	TCOD_console_set_default_foreground(NULL, TCOD_grey);
+	TCOD_console_print_ex(NULL, 0, frame_cy+frame_ch, TCOD_BKGND_NONE, TCOD_LEFT, "Page %d/%d", gesture_index+1+EXTRA_MAIN_PAGES, (gesture_count+EXTRA_MAIN_PAGES));
 
 #ifndef NDEBUG
 	__android_log_print(ANDROID_LOG_INFO, "gestures", "text %d", 7);