Update, read below

The gestures are basicly (on first version) done with this mechanic:

1) Gesture your gesture
2) Press enter, the program will tell you that it has saved the gesture by which id and how many parts it consisted
3) Press d, a new file will be created where all the gesture coords are dumped
4) Copy the coordinates from newly created file to gests.txt

That wasn't really sayed in the engine, that why this new update (I just add the code to here, no reason to DL this). This version gives you a realtime output of coordinates and gives you more information about what should be done. So you shouldn't (hopefully) anymore feel lost. Note tho that the gesture is regodnised only in a play mode.


Here's demo.c
Code:
#include <acknex.h>
#include <default.c>
#include "GestIT.c"

var demo_mode = -1;
TEXT* information =
{
	pos_x = 0;
	pos_y = 0;
	font = "Arial#16";
	string("This is GestIT demo\n","","");
	flags  = VISIBLE;
}
TEXT* gesture_output=
{
	strings = 11;//Should be MAX_GESTPART+1
	pos_x = 0;
	pos_y = 200;
	flags = VISIBLE;
}
void main()
{
	TEXT* printer = 
	{
		pos_x = 200;
		pos_y = 300;
		strings = 1;
		alpha = 100;
		flags = VISIBLE | TRANSLUCENT;
	}
	mouse_mode  = 4;
	read_gestures(MGST_STR_GEST_FILE);
	wait_for(read_gestures);
	gesture(280,281);
	str_cat((information.pstring)[0],"Currect gesture input file:");
	str_cat((information.pstring)[0],MGST_STR_GEST_FILE);
	str_cat((information.pstring)[0],"\nCurrect gesture output file:");
	str_cat((information.pstring)[0],MGST_STR_GEST_FILE);
	str_cat((information.pstring)[0],"_copy.txt\n");
	str_cpy((information.pstring)[1],"To enter play mode press F1\nTo enter gesture creation mode press F2");
	var i = 0;
	var a = 0;
	var line = 0;
	var time_delay;
	var temp_x = 0;
	var temp_y = 0;
	MGST* temp_gest = NULL;
	MGSTPART* temp_part = NULL;
	var fhandle = 0;
	var key_d_clear = 1;
	var key_enter_clear = 1;
	STRING* str_temp = NULL;
	var loc_temp_x = 0;
	var loc_temp_y = 0;
	var reset_gest = 0;
	for(i=0;i<11;i++)
	{
		str_cpy((gesture_output.pstring)[i],"");
	}
	i = 0;
	while(1)
	{
		
		if(key_f1)
		{
			gesture_output.flags = NULL;
			str_cpy((information.pstring)[1],"Now using: Play mode(Try to gesture the gestures)\nNote: If you just did a new gesture usgin this demo.c, you have to copy the gestures to gest.txt file");
			str_cpy((information.pstring)[2],"Press your defined gesture button to gest ( note,gests come in order they appear in gest file\nAfter this make a gesture in order\nGesture in order:");
			str_cat_num((information.pstring)[2],"%.f",(double)i+1);
			demo_mode = 1;
			reset_gest = 0;
		}
		if(key_f2)
		{
			gesture_output.flags = VISIBLE;
			str_cpy((information.pstring)[1],"Now using: New gesture creation");
			str_cpy((information.pstring)[2],"To create new gesture, gest it first and after press enter this will save the gesture to the database
			\nTo reset your gesture or last output, press R.Note: Pressing R will reset both if valid!\nTo save the database(dump), Press D. This will create a new file on local directory
			To exit press Esc\n\nCurrect gesture coordinates:");
			demo_mode = 2;
			reset_gest = 0;
		}
		if(!key_enter)key_enter_clear = 1;
		if(demo_mode == 1 || demo_mode == 2)
		{
			printer.pos_x = mouse_pos.x + 40;
			printer.pos_y = mouse_pos.y;
			if(time_delay >= 5)
			{
				printer.alpha -=1*time_step;
				if(printer.alpha <= 5)
				{
					str_cpy((printer.pstring)[0],"");
					time_delay = 0;
					line = 0;
					for(i=0;i<10;i++)
					{
						str_cpy((gesture_output.pstring)[i],"");
					}
				}
			}
			else
			{
				if(time_delay >= 0)
				{
					time_delay +=1*time_step;
				}
			}
		}
		if(demo_mode == 1)
		{
			if(gest[i])
			{
				/*
				THIS IS IMPORTANT PART 
				
				If the found gest is valid we need to reset it to NULL before we can continue
				with check operations
				*/
				if(found_gest)//IMPORTANT
				{
					if(found_gest == gest[i])
					{
						printer.alpha = 100;
						str_cpy((printer.pstring)[0],"");
						str_cpy((printer.pstring)[0],"Found gest, try the next one");
						beep();
						i++;
						time_delay = 0;
						found_gest = NULL;//IMPORTANT
					}
					else
					{
						printer.alpha = 100;
						str_cpy((printer.pstring)[0],"");
						time_delay = 0;
						str_cpy((printer.pstring)[0],"Did not do the right gest, try again! (resetting found gesture)");
						found_gest = NULL;//IMPORTANT
					}
				}
				/*
				END OF IMPORTANT PART
				*/
			}
			else
			{
				if(printer.alpha <=55 && time_delay >= 0)
				{
					time_delay = -1;
					printer.alpha = 100;
					str_cat((printer.pstring)[0],"\nNo more gestures, press T to reset gestures and start over\n Or press Q to exist");
				}
				if(key_t)
				{
					str_cpy((printer.pstring)[0],"Reseted");
					found_gest = NULL;
					i = 0;
				}
				if(key_q)
				{
					sys_exit("");
				}
			}
		}
		if(demo_mode == 2)
		{
			time_delay = -1;
			if(key_d && key_d_clear == 1)
			{
				str_temp = str_create(_chr(MGST_STR_GEST_FILE));
				str_cat(str_temp,"_copy.txt");
				fhandle = file_open_write(str_temp);
				if(fhandle != NULL)
				{
					for(i=0;i<MGST_MAX_GEST;i++)
					{
						if(gest[i])
						{
							for(a=0;a<MGST_MAX_GESTPART;a++)
							{
								if(gest[i]->part[a])
								{
									file_var_write(fhandle,gest[i]->part[a]->x);
									file_var_write(fhandle,gest[i]->part[a]->y);
								}
							}
							file_var_write(fhandle,-2);
						}
					}
					file_var_write(fhandle,-3);
					reset_gest = 1;
					file_close(fhandle);
					printf("File saved: %s",_chr(str_temp));
				}
				key_d_clear = 0;
			}
			if(!key_d)
			{
				key_d_clear = 1;
			}
			str_cpy((printer.pstring)[0],"");
			str_cat_num((printer.pstring)[0],"X_MOVEMENT:%.f",MGST_X_MOVEMENT);
			str_cat_num((printer.pstring)[0],"\nY_MOVEMENT:%.f",MGST_Y_MOVEMENT);
			if(mouse_moving == 1 && vec_dist(MGST_VEC_MOUSE_OLD,mouse_pos.x) >= MGST_MOVEMENT_CHECK && MGST_CHECK_VALID)
			{
				if(!temp_gest)
				{
					temp_gest = create_gesture();
					for(i=0;i<10;i++)
					{
						str_cpy((gesture_output.pstring)[i],"");
					}
					line = 0;
				}
				else
				{
					if(MGST_X_MOVEMENT != 0 || MGST_Y_MOVEMENT != 0)
					{
						if(MGST_X_MOVEMENT != loc_temp_x || MGST_Y_MOVEMENT != loc_temp_y)
						{
							loc_temp_x = MGST_X_MOVEMENT;
							loc_temp_y = MGST_Y_MOVEMENT;
							if(temp_gest->max_part < MGST_MAX_GESTPART)
							{
								create_gesture_part(temp_gest,MGST_X_MOVEMENT,MGST_Y_MOVEMENT);
								if((gesture_output.pstring)[line])
								{
									str_cpy((gesture_output.pstring)[line],"(X,Y):");
									str_cat_num((gesture_output.pstring)[line],"(%.f,",MGST_X_MOVEMENT);
									str_cat_num((gesture_output.pstring)[line],"%.f)",MGST_Y_MOVEMENT);
									line++;
								}
								str_cpy((gesture_output.pstring)[10],"There's still room for gesture parts");
							}
							else
							{
								str_cpy((gesture_output.pstring)[10],"No room for gesture parts");
							}
						}
					}
				}
			}
			if(mouse_moving == 0)
			{
				if(key_r)
				{
					if(temp_gest)
					{
						for(i=0;i<MGST_MAX_GESTPART;i++)
						{
							if(temp_gest->part[i])
							free(temp_gest->part[i]);
						}
						free(temp_gest);
					}
					for(i=0;i<10;i++)
					{
						str_cpy((gesture_output.pstring)[i],"");
					}
					line = 0;
					reset_gest = 0;
					temp_gest = NULL;
				}
			}
			if(key_enter && temp_gest != NULL && key_enter_clear == 1)
			{
				if(temp_gest->max_part >= 1)
				{
					for(i=0;i<MGST_MAX_GEST;i++)
					{
						if(!gest[i])
						{
							gest[i] = temp_gest;
							printf("Gesture saved succesfully (information to follow)\nGesture parts: %.f\nGesture saved ID (order of appearence in the file): %.f",(double)temp_gest->max_part,(double)i);
							wait(2);
							vec_set(MGST_VEC_MOUSE_OLD,mouse_pos.x);
							temp_gest = NULL;
							break;
						}
					}
				}
				key_enter_clear = 0;
			}
		}
		wait(1);
	}
}



Here's the GestIT.c
Code:
#ifndef acknex.h
	#include <acknex.h>
#endif

#define MGST_MOVEMENT_CHECK 20//The distance the mouse has to move before a new check is called
#define MGST_MOVEMENT_ACCURACY 5//How much we give space for an error
#define MGST_END_LINE -2//Which number we have to meet before we create a new gesture struct
#define MGST_END_FILE -3//When this number is meat we've reached the end of the file
#define MGST_TIME_DELAY 2//The time that mouse is required to be stopped before we check for gesture
#define MGST_ENABLE_TRAIL//If this is enabled a trail is drawn based on mouse movement on the screen
#define MGST_MAX_GEST 200//Maxium amount of gestures(terminates the array size)
#define MGST_MAX_GESTPART 10//Maxium amount of parts in gestures

STRING* MGST_STR_ERROR_LOAD1 = "Could not open a valid gesture file. Please check the file/path given to the function\nThis function returns 0";
STRING* MGST_STR_GEST_FILE = "gests.txt";

VECTOR MGST_VEC_MOUSE_OLD;

var MGST_FOUND = -1;//Global variable used by the gesture function
var MGST_KILL_LINES = 1;//Used to kill lines made by gesture (function draw_line_coord(x1,x2,y1,y2))
var MGST_GEST_COUNT = 1;//Used for faster array checks, counts the total amount of gestures loaded
var MGST_X_MOVEMENT = 0;//Global variable of which direction mouse is moving on X axis
var MGST_Y_MOVEMENT = 0;//Global variable of mouse movement on Y axis
var MGST_RESET_CHECK = 0;//Used to reset gesture checking
var MGST_CHECK_VALID = 0;//Used to check if the chek loop is valid
var temp_x = 0;//Temporary X axis movement var
var temp_y = 0;//Temporary Y axis movement var

typedef struct
{
	var x,y,z;//Coordinates, Z is free for user
}MGSTPART;//Gesture part struct

typedef struct
{
	var id;//Gesture's ID
	var part_check;//Variable that tells gesture function which part it should check next
	var max_part;//Tells how many parts we have
	MGSTPART* part[MGST_MAX_GESTPART];//Array of gesture parts, size of defined maxium gest part
}MGST;

MGST* gest[MGST_MAX_GEST];//Array for REAL gestures
MGST* gest_check[MGST_MAX_GEST];//Array for GESTURES THAT ARE CHECKED (these point to REAL gestures)
MGST* found_gest;//Pointer to the found variabel in gesture function

function draw_line_coord(x1,x2,y1,y2)
{
	var time_delay = 0;//Counter variableu
	while(1)
	{
		if(time_delay >= 10)//if this line has existed for over 10 seconds
		{
			if(MGST_KILL_LINES == 1 || MGST_KILL_LINES == 2)
			{
				break;
			}
		}
		else
		{
			time_delay +=1*time_step;//If the time isn't meat, increase the counter
		}
		draw_line(vector(x1,x2,0), vector(0,0,250), 0);//Draw line from x1,x2
		draw_line(vector(y1,y2,0), vector(0,0,250), 100);//Draw line to y1,y2
		draw_quad(NULL, vector(x1,x2,0), NULL, vector(5,5,0), NULL, vector(0,250,0), 100, 0);//Add square to start position
		wait(1);
	}
	
}
function gesture(var key_press,var ignore_press)
{
	/*---------------------------------------------------------------------------
	Gesture main function, this function is RELEVANT for your projects.
	
	This function holds the spine of the wholse system, it calculates the gestures
	and their coordinates to the ones that are loaded to the memory. 
	
	funtion comments start here
	---------------------------------------------------------------------------*/
	/*---------------------------------------------------------------------------
	---------------------------------------------------------------------------*/
	var i,a;//Counter variables
	var time_delay  = 0;//Counter how long it takes to check the gesture after the mouse is stopped
	var found_check = 0;//Counter of how many gestures fit (faster searching through the array), THIS IS MODIFIED
	var found_start_check = 0;//same as above but this variable holds the amount of fitting gestures until the gesture loop breaks
	vec_set(MGST_VEC_MOUSE_OLD,vector(mouse_pos.x,mouse_pos.y,0));//Set mouse old to mouse position
	MGST* temp_found_gest = NULL;//Temporary gesture canditate pointer
	MGST_RESET_CHECK = 1;
	while(1)
	{
		proc_mode = PROC_LATE;
		/*---------------------------------------------------------------------------
		Preset certain parts before checking if we're pressing the key
		---------------------------------------------------------------------------*/
		// 	if(!key_pressed(key_press))//Comment out this line if you don't want reseting the gestures before user lets off the gesture button
		if(MGST_RESET_CHECK == 1)
		{
			for(i=0;i<MGST_GEST_COUNT;i++)//Count for defined maxium gest amourn
			{
				if(gest[i])//If there's a gesture with this I
				{
					gest[i]->part_check = 0;//Reset its gesture part counter
				}
				gest_check[i] = NULL;//Reset gest_check by this I
			}
			temp_found_gest = NULL;
			found_gest = NULL;
			MGST_X_MOVEMENT = 0;//Reset x mouse movement variable
			MGST_Y_MOVEMENT = 0;//Reset y movement variable
			temp_x = -10;//Reset last x movement
			temp_y = -10;//Rest last y movement
			found_start_check = 0;
			found_check = 0;
			time_delay = 0;
			MGST_FOUND = 0;//Set this variable to we want to sync mouse position to mouse old
			MGST_RESET_CHECK = 0;//Reset the reseting variable
		}
		if(key_pressed(key_press))
		{
			vec_set(MGST_VEC_MOUSE_OLD,vector(mouse_pos.x,mouse_pos.y,0));
		}
		MGST_CHECK_VALID = 0;
		while(key_pressed(key_press) && MGST_RESET_CHECK == 0)//If wanted key is pressed continue wit htis (And we aren't reseting check)
		{
			proc_mode = PROC_LATE;
			if(MGST_RESET_CHECK != 0)//If reset variable is not NULL, break the check
			{
				break;
			}
			if(ignore_press > 0 && key_pressed(ignore_press))//If we've defined ignore press and we're pressing the button
			{
				break;//Break from this loop
			}
			MGST_CHECK_VALID = 1;//Set checking valid, check loop is valid in other words
			if(mouse_moving == 0)//If  mouse doesn't move
			{
				time_delay +=1*time_step;//Increase time delay
				if(time_delay >= MGST_TIME_DELAY)//If time delay variable is higher thand defined time delay
				{
					if(temp_found_gest)//If we have mouse gest canditate
					{
						found_gest = temp_found_gest;//Set found gest to mouse gest canditate
						temp_found_gest = NULL;
					}
					else
					{
						found_gest = NULL;//If we didn't have gest caditate set found_gest pointer to NULL
					}
					MGST_RESET_CHECK = 1;
				}
			}
			else
			{
				#ifdef MGST_ENABLE_TRAIL
					draw_line_coord(MGST_VEC_MOUSE_OLD.x,MGST_VEC_MOUSE_OLD.y,mouse_pos.x,mouse_pos.y);//If enabled lines are drawn based on mouse movement
				#endif
				time_delay = 0;//If mouse is moving set time delay to 0
			}
			if(vec_dist(MGST_VEC_MOUSE_OLD,vector(mouse_pos.x,mouse_pos.y,0)) >= MGST_MOVEMENT_CHECK && MGST_RESET_CHECK == 0)//If mouse has moved more than defined movement check
			{
				if((sign(mouse_pos.x-MGST_VEC_MOUSE_OLD.x)*(mouse_pos.x-MGST_VEC_MOUSE_OLD.x)) >= MGST_MOVEMENT_ACCURACY)//If mouse has moved more thant defined accuracy to this direction continue
				{
					MGST_X_MOVEMENT = sign((mouse_pos.x - MGST_VEC_MOUSE_OLD.x));//Set x movement to the 1,0 or -1
				}
				else
				{
					MGST_X_MOVEMENT = 0;//If mouse didn't move to this direction enough we set x movmeent to 0
				}
				if((sign(mouse_pos.y-MGST_VEC_MOUSE_OLD.y)*(mouse_pos.y-MGST_VEC_MOUSE_OLD.y)) >= MGST_MOVEMENT_ACCURACY)//Same as with X check
				{
					MGST_Y_MOVEMENT = sign((mouse_pos.y - MGST_VEC_MOUSE_OLD.y));
				}
				else
				{
					MGST_Y_MOVEMENT = 0;
				}
				vec_set(MGST_VEC_MOUSE_OLD,vector(mouse_pos.x,mouse_pos.y,0));//Set the new position for MGST_VEC_MOUSE_OLD vector
				if(MGST_X_MOVEMENT != temp_x || MGST_Y_MOVEMENT != temp_y)//If x and/or y movement were different than the last x and/or y movement
				{
					temp_x = MGST_X_MOVEMENT;//Set last variables to x movement
					temp_y = MGST_Y_MOVEMENT;//Set last variable to y movement
					if(MGST_FOUND == 1)//If function has triggered global variable to 1 we can continue with this ( we have populated gest_check array)
					{
						for(i=0;i<found_start_check;i++)//Count for defined maxium gest number
						{
							if(gest_check[i] != NULL)//If cheked gest does exist in this I
							{
								if(gest_check[i]->part[gest_check[i]->part_check] != NULL)//If the gesture part exists in the gest_check with the amount part_check gives
								{
									if(gest_check[i]->part[gest_check[i]->part_check]->x == MGST_X_MOVEMENT && 
									gest_check[i]->part[gest_check[i]->part_check]->y == MGST_Y_MOVEMENT)//If both x and y movement matched with the gesture part
									{
										gest_check[i]->part_check++;//Increase the part check so the function can check the new part in the gest
										if(gest_check[i]->part_check >= (gest_check[i]->max_part))//If we've got more in the part check variable than there are parts we have a canditate
										{
											temp_found_gest = gest_check[i];//Set canditate to this gest_check
										}
									}
									else
									{
										gest_check[i] = NULL;//If the x and/or y movement didn't match with the gest check we can erase this gest_check
										found_check--;//Decrease the amount of gestures that fit
									}
								}
								else
								{
									gest_check[i] = NULL;//If there was no part with the variable gest_check pointed in part check variable
									found_check--;//Decrease the amount of gestures that fit
								}
							}
						}
						if(found_check <= MGST_GEST_COUNT)
						{
							if(found_check == 1)
							{
								for(i=0;i<MGST_GEST_COUNT;i++)//Count for defined maxium gest
								{
									if(gest_check[i] != NULL)//If gest_check with this I exists
									{
										temp_found_gest = gest_check[i];
										break;//Break the loop
									}
								}
							}
							if(found_check <= 0)
							{
								MGST_RESET_CHECK = 1;
							}
						}
						else
						{
							MGST_FOUND = 1;
						}
					}
					else//If we've not found any gestures yet (or the user has failed in gesting)
					{
						for(i=0;i<MGST_GEST_COUNT;i++)//Count for defined maxium GEST
						{
							if(gest[i])//If gest exists with this I
							if(gest[i]->part[0])//If the first part does exists in this I
							if(gest[i]->part[0]->x == MGST_X_MOVEMENT && gest[i]->part[0]->y == MGST_Y_MOVEMENT)//If coord movement match with the part
							{
								MGST_FOUND = 1;ยด//Set this variable ("We've found a gesture!")
								for(a=0;a<MGST_GEST_COUNT;a++)//Count for defined maxium gest
								{
									if(gest_check[a] == NULL)//if gest check in this A pointer does not exist we can continue
									{
										gest_check[a] = gest[i];//Set gest_check to point to gest
										gest_check[a]->part_check = 1;//We've allready found the first coord and it matched so we can move to next coord
										found_check++;//Increase the amoung of gestures that fit ( THIS VARIABLE IS MODIFIED THROUGH THE FUNCTION)
										found_start_check++;//Same as above, but the amount is kept the same as long as this loop is valid, THIS VARIABLE IS NOT MODIFIED
										break;
									}
								}
							}
						}
					}
				}
			}
			
			wait(1);	
		}
		wait(2);
	}
}

function create_gesture()
{
	var i;
	MGST* gest  = malloc(sizeof(MGST));
	gest->id = 0;
	gest->part_check = 0;
	gest->max_part = 0;
	for(i=0;i<MGST_MAX_GESTPART;i++)
	{
		gest->part[i] = NULL;
	}
	return gest;
}

function create_gesture_part(MGST*gest,var x, var y)
{
	if(!gest)
	{
		return 0;
	}
	var i;
	MGSTPART* part = malloc(sizeof(MGSTPART));
	part->x = x;
	part->y = y;
	for(i=0;i<MGST_MAX_GESTPART;i++)
	{
		if(gest->part[i] == NULL)
		{
			gest->part[i] = part;
			gest->max_part++;
			break;
		}
	}
	return part;
}
function read_gestures(STRING* path)
{
	/*---------------------------------------------------------------------------
	This function reads the gesture coordinates from the file defined in th
	STRING* path
	
	This is relevant peace to the gesture system, this function is also required
	before we can use gesture function.
	---------------------------------------------------------------------------*/
	var fhandle = file_open_read(path);//Our pointer to the file
	var new_line = 1;//Trigger to start a new line
	var x_read = 0;//First variable that's read
	var y_read = 0;//Second variable that's read
	var i;//Counter
	if(fhandle == NULL)//If we couldn't open the file 
	{
		error(MGST_STR_ERROR_LOAD1);//Print an error
		return 0;//Return this function
	}
	MGST* temp = NULL;//Temporary mouse gesture pointer
	for(i=0;i<MGST_MAX_GEST;i++)//Count for the defined maxium gest amount
	{
		gest[i] = NULL;//Initialize gesture array
	}
	while(1)//Loop for reading
	{
		if(x_read == MGST_END_FILE)//If x variable has this as its value we are at the end of the file
		{
			free(temp);//Free the created mouse gest(this function creates one empty gesture before this part is checked!)
			gest[i] = NULL;//Set gesture in I as empty
			break;//Break from read loop
		}
		MGST* mgst = create_gesture();
		temp = mgst;//Set temporary gest pointer to newly allocated mouse gesture
		while(1)//Coordinate populate loop
		{
			x_read = file_var_read(fhandle);//Read the first number
			if(x_read == MGST_END_LINE || x_read == MGST_END_FILE)//If these numbers are meat
			{
				new_line = 1;//Trigger new line
				break;
			}
			y_read = file_var_read(fhandle);//Read the second number
			create_gesture_part(temp,x_read, y_read);
		}
		if(temp)//If we've got temp gesture
		{
			for(i=0;i<MGST_MAX_GEST;i++)//Count for maxium gestures
			{
				if(gest[i] == NULL)//If there's a space for gestures
				{
					temp->id = i;//Give an id for the gesture based to I
					gest[i] = temp;//Set temp to gest array in I
					MGST_GEST_COUNT++;
					temp = NULL;
					break;//Break this loop
				}
			}
		}
	}
	return 1;//Return the function
}



Last edited by Walori; 01/05/11 10:03.