front_idill/src/mosaic/js/mosaic.js
changeset 45 0e29ae4568a0
parent 44 8393d3473b98
child 46 9d7a2aa112fb
--- a/front_idill/src/mosaic/js/mosaic.js	Fri Jun 29 16:16:24 2012 +0200
+++ b/front_idill/src/mosaic/js/mosaic.js	Thu Jul 05 16:04:33 2012 +0200
@@ -25,11 +25,11 @@
 function mosaic(config, default_conf)
 {
 	//Interactions souris/kinect.
-	this.mouseInteractions = false;
+	this.mouseInteractions = true;
 	//Interactions avec/sans préphase.
 	this.prephaseEnabled = true;
 	
-	this.gestures = ["fall", "jump", "circle", "screw", "bend", "arc", "pendulum", "knee-up", "right-angle", "wave", "slow", "hello", "no-motion", "wheel", "contact", "run"];
+	this.gestures = ["fall", "jump", "circle", "screw", "bend", "arc", "pendulum", "knee-up", "right-angle", "wave", "slow", "hello", "no-motion", "wheel", "contact", "run", "up-down", "grand-jete"];
 
 	//Chemin du fichier de configuration.
 	this.config_path = config;
@@ -47,6 +47,9 @@
 	this.fillingIds = [];
 	this.currentRandomVideoIdx = 0;
 	
+	//Dictionnaire pour les courbes de recherche.
+	this.dictionary = [];
+	
 	//Dernières positions des pointeurs.
 	this.mainPointerLastX;
 	this.mainPointerLastY;
@@ -58,6 +61,15 @@
 	this.secondPointerIdleStartX;
 	this.secondPointerIdleStartY;
 	
+	//Coordonnées de la souris dans le mode d'interaction souris.
+	this.mousePosX;
+	this.mousePosY;
+	//Coordonnées précédentes de la souris dans le mode d'interaction souris.
+	this.mousePosLastX;
+	this.mousePosLastY;
+	//Valeur du déplacement entre un mouse up et un mouse down.
+	this.mouseUpDownDelta = 0;
+	
 	//Dimensions de la mosaïque en pixels.
 	this.width;
 	this.height;
@@ -68,95 +80,103 @@
 	this.marginWidth;
 	
 	//Booléens permettant ou non certaines intéractions selon le contexte.
-	this.zoomed;
-	this.fullscreen;
-	this.canMoveToNeighbour;
-	this.mainPointerExitBorder;
-	this.secondPointerExitBorder;
-	this.isMainPointerDisplayed;
-	this.isSecondPointerDisplayed;
-	this.helpDisplayed;
+	this.zoomed = false;
+	this.fullscreen = false;
+	this.canMoveToNeighbour = false;
+	this.mainPointerExitBorder = false;
+	this.secondPointerExitBorder = false;
+	this.isMainPointerDisplayed = false;
+	this.isSecondPointerDisplayed = false;
+	this.helpDisplayed = false;
 	//Indique si l'utilisateur a manuellement pausé la vidéo.
-	this.userPaused;
+	this.userPaused = false;
 	//Indique si on est en train de se déplacer vers un voisin.
-	this.currentlyMoving;
+	this.currentlyMoving = false;
 	//Indique si on est en train de dézoomer vers la mosaïque.
-	this.currentlyUnzooming;
+	this.currentlyUnzooming = false;
 	//Indique si on peut s'approcher de kinect.
-	this.canStart;
+	this.canStart = false;
 	//Indique si on est actuellement sur un snapshot.
-	this.isOnASnapshot;
+	this.isOnASnapshot = false;
 	//Indique si l'idle des pointeurs est disponible (deux mains détectées).
-	this.pointersIdleAvailable;
+	this.pointersIdleAvailable = false;
 	//Indique si le timeout pour l'idle des pointeurs à besoin d'être lancé.
-	this.pointersIdleNeedLaunch;
+	this.pointersIdleNeedLaunch = false;
 	//Indique si les deux mains sont là.
-	this.areBothPointersHere;
+	this.areBothPointersHere = false;
 	//Indique si le timeout pour la détection de deux pointeurs a été lancé.
-	this.areBothPointersTimeoutLaunched;
+	this.areBothPointersTimeoutLaunched = false;
 	//Indique si la mosaïque a été filtrée.
-	this.isMosaicFiltered;
+	this.isMosaicFiltered = false;
 	//Indique si on est actuellement dans une recherche par gesture.
-	this.isCurrentlyInASearchByGesture;
+	this.isCurrentlyInASearchByGesture = false;
 	//Indique si un pointeur est déjà sur une notification de recherche par gesture.
-	this.alreadyOnNotification;
+	this.alreadyOnNotification = false;
 	//Si on a fait un swipe.
-	this.isSwipe;
+	this.isSwipe = false;
 	//On peut swiper.
-	this.canSwipe;
+	this.canSwipe = false;
 	//On passe vers une autre video automatiquement à la fin d'une lecture.
-	this.autoMove;
+	this.autoMove = false;
 	//Si l'utilisateur a demandé à sélectionner la TL.
-	this.isTLRequested;
+	this.isTLRequested = false;
 	//Le pointeur gauche a sélectionné la TL.
-	this.isTLSelectedBySecondPointer;
+	this.isTLSelectedBySecondPointer = false;
 	//Le pointeur droit a sélectionné la TL.
-	this.isTLSelectedByMainPointer;
+	this.isTLSelectedByMainPointer = false;
 	//On peut afficher l'aide.
-	this.canNotifyHelp;
+	this.canNotifyHelp = false;
 	//Indique si la mosaique est en train d'être filtrée.
-	this.isMosaicFiltering;
+	this.isMosaicFiltering = false;
 	this.arrowLeftLoading = false;
 	this.arrowRightLoading = false;
 	this.arrowUpLoading = false;
 	this.arrowDownLoading = false;
 	//On est dans une recherche par courbes.
-	this.isSearchByCurvesOn;
+	this.isSearchByCurvesOn = false;
 	this.canDrawNextCurve = false;
+	//Dans le mode d'interaction souris, indique si on se situe actuellement sur un snapshot entièrement prézoomé.
+	this.isOnAPrezoomSN = false;
+	//Indique si une courbe de recherche donne au moins un résultat.
+	this.curvesGesturesFound = false;
+	//Indique si on souhaite supprimer la recherche en cours.
+	this.gestureDelRequested = false;
+	//Code de gesture actuellement calculé par les détecteurs de courbes.
+	this.actualCode = '';
 	
 	//Timeout (attente) pour le zoom après un préZoom.
-	this.zoomTimeout;
+	this.zoomTimeout = null;
 	//Timeout (attente) pour le passage vers un voisin.
-	this.moveToNeighbourTimeout;
-	this.mainPointerExitBorderTimeout;
-	this.secondPointerExitBorderTimeout;
+	this.moveToNeighbourTimeout = null;
+	this.mainPointerExitBorderTimeout = null;
+	this.secondPointerExitBorderTimeout = null;
 	//Idle time pour les pointeurs afin d'informer le front qu'on souhaite faire une recherche.
-	this.pointersSearchIdleTimeout;
+	this.pointersSearchIdleTimeout = null;
 	//Vérifie toutes les N ms que les deux pointeurs sont détectés.
-	this.areBothPointersHereTimeout;
+	this.areBothPointersHereTimeout = null;
 	//Délai de suppression d'une notification de recherche par gesture.
-	this.removeNotificationByGestureTimeout;
+	this.removeNotificationByGestureTimeout = null;
 	//Délai de suppression d'une notification de recherche par gesture infructueuse.
-	this.removeFailedNotificationByGestureTimeout;
+	this.removeFailedNotificationByGestureTimeout = null;
 	//Délai avant la suppression de notification swipe.
-	this.notifySwipeTimeout;
+	this.notifySwipeTimeout = null;
 	//Délai pour la sélection de la TL.
-	this.selectTLTimeout;
+	this.selectTLTimeout = null;
 	//Délai pour slider sur la TL.
-	this.canSlideInTLTimeout;
+	this.canSlideInTLTimeout = null;
 	//Délai pour afficher l'aide.
-	this.canNotifyHelpTimeout;
-	this.arrowLeftTimeout;
-	this.arrowRightTimeout;
-	this.arrowUpTimeout;
-	this.arrowDownTimeout;
+	this.canNotifyHelpTimeout = null;
+	this.arrowLeftTimeout = null;
+	this.arrowRightTimeout = null;
+	this.arrowUpTimeout = null;
+	this.arrowDownTimeout = null;
 	
-	this.arrowSpinnerTimeout;
-	this.nouserTimeout;
-	this.nextDrawCurveTimeout;
+	this.arrowSpinnerTimeout = null;
+	this.nouserTimeout = null;
+	this.nextDrawCurveTimeout = null;
 	
 	//Dernier message INCOMING (pour éviter d'effectuer n fois la même action.
-	this.lastIncomingMessage;
+	this.lastIncomingMessage = '';
 	
 	//Type de marqueur recherché dans la mosaïque (en mode filter).
 	this.filterSearchedType = "";
@@ -165,8 +185,10 @@
 	this.currentMode = "NO-USER";
 	//Snapshot sur lequel on a zoomé.
 	this.previousZoomedSN = null;
+	//Snapshot sur lequel on a prezoomé.
+	this.previousPrezoomDiv = null;
 	//Son ID.
-	this.previousId;
+	this.previousId = null;
 	//Dernier snapshot prézoomé non null.
 	this.lastNonNullSN = null;
 	//Largeur de la marge pour le centrage vertical de la mosaïque.
@@ -174,8 +196,8 @@
 	this.top_margin;
 	
 	//Gesture actuellement cherchée.
-	this.currentSearchGesture;
-
+	this.currentSearchGesture = '';
+	
 	//Mosaïque locale.
 	this.localMos;
 	//Position des voisins lors d'un zoom.
@@ -191,9 +213,9 @@
 	this.snapshotsToShow = 1;
 	
 	//Lecteur.
-	this.player;
+	this.player = null;
 	//Si le lecteur est prêt.
-	this.playerIsReady;
+	this.playerIsReady = false;
 	
 	//Annotations (pour les marqueurs los d'un filtrage).
 	this.annotations = [];
@@ -240,34 +262,6 @@
 	//S'il s'agit d'un rectangle.
     if(imgs % len == 0)
     {
-		this.previousZoomedSN = null;
-		this.previousPrezoomDiv = null;
-		this.fullscreen = false;
-		this.canMoveToNeighbour = false;
-		this.currentlyZooming = false;
-		this.currentlyUnzooming = false;
-		this.helpDisplayed = false;
-		this.canStart = false;
-		this.isOnASnapshot = false;
-		this.isMosaicFiltered = false;
-		this.areBothPointersHere = false;
-		this.areBothPointersTimeoutLaunched = false;
-		this.isCurrentlyInASearchByGesture = false;
-		this.alreadyOnNotification = false;
-		this.playerIsReady = false;
-		this.currentSearchGesture = '';
-		this.isMainPointerDisplayed = false;
-		this.isSecondPointerDisplayed = false;
-		this.isSwipe = false;
-		this.canSwipe = false;
-		this.autoMove = false;
-		this.isTLRequested = false;
-		this.isTLSelectedByMainPointer = false;
-		this.isTLSelectedBySecondPointer = false;
-		this.canNotifyHelp = false;
-		this.isMosaicFiltering = false;
-		this.isSearchByCurvesOn = false;
-		
 		this.lastIncomingMessage = 'INCOMING-0';
 		
 		var str = '';
@@ -281,7 +275,7 @@
 			}
 		}
 		
-		return str;
+		return str + '<div id="ghostPanel"></div>';
 	}
 	else
 	{
@@ -307,6 +301,7 @@
     //On affecte les chemins vers les images à la mosaïque.
     this.previousZoomedSN;
     //this.width = 
+	// console.log(createMosaic);
     //On met à jour la mosaïque.
     $('#mainPanel').html(createMosaic);
     //On récupère la taille des bordures.
@@ -326,7 +321,6 @@
 	
 	//On fait coincider le background du body avec celui de la mosaïque.
 	$('body').css('background-position', '0px ' + this.MPTop_margin + 'px');
-	console.log(this.MPTop_margin);
 	
 	/*$('.snapshotDivs').mouseover(function ()
 	{
@@ -374,12 +368,15 @@
 				//Si on gère les interactions à la souris.
 				if(_this.mouseInteractions)
 				{
-					$('body').mousemove(function(e){_this.refreshMainPointer(e.pageX, e.pageY, _this)});
+					$('body').mousemove(function(e)
+					{
+						_this.refreshMainPointer(e.pageX, e.pageY, _this);
+						_this.mousePosX = e.pageX;
+						_this.mousePosY = e.pageY;
+					});
 				}
 				
-				// if(false)
-				// {
-				if(_this.prephaseEnabled)
+				if(_this.prephaseEnabled && !_this.mouseInteractions)
 				{
 					_this.init();
 					_this.showNImages(0);
@@ -390,7 +387,6 @@
 					_this.showNImages(20);
 					_this.currentMode = "MOSAIC";
 				}
-				// }
 				
 				// /!\ //
 				// _this.currentMode = "FILTER";
@@ -408,6 +404,197 @@
 			}
 		});
 	}
+	
+	if(this.mouseInteractions)
+	{
+		//On bind le clic pour supprimer une recherche.
+		$('body').click(function(e)
+		{
+			_this.removeSearchNotificationIfOnIt(e.pageX, e.pageY);
+		});
+		
+		//Si on fait un mouse down sur le body, on vérifie enregistre le déplacement de la souris jusqu'au prochain mouse up.
+		$(window).mousedown(function ()
+		{
+			if(_this.isSearchByCurvesOn)
+			{
+				_this.searchCanvas.onPointerIn(_this.mousePosX, _this.mousePosY, null, null);
+			}
+			
+			console.log('mdown');
+			//On écoute le déplacement de la souris.
+			$(window).mousemove(function(e)
+			{
+				if(_this.isSearchByCurvesOn)
+				{
+					_this.searchCanvas.onPointerMove(_this.mousePosX, _this.mousePosY - _this.MPTop_margin, null, null);
+				}
+				
+				//On met à jour l'ancienne position de la souris si elle est nulle.
+				if(!_this.mousePosLastX && _this.mousePosLastX != 0)
+				{
+					_this.mousePosLastX = _this.mousePosX;
+				}
+				if(!_this.mousePosLastY && _this.mousePosLastY != 0)
+				{
+					_this.mousePosLastY = _this.mousePosY;
+				}
+				
+				//Le delta s'accroît si la souris bouge.
+				_this.mouseUpDownDelta += Math.floor(Math.sqrt((_this.mousePosLastX - e.pageX) * (_this.mousePosLastX - e.pageX) + (_this.mousePosLastY - e.pageY) * (_this.mousePosLastY - e.pageY)));
+				
+				// console.log(_this.mouseUpDownDelta, _this.mousePosLastX, e.pageX);
+				
+				if(_this.mousePosLastX != _this.mousePosX)
+				{
+					_this.mousePosLastX = _this.mousePosX;
+				}
+				if(_this.mousePosLastY != _this.mousePosY)
+				{
+					_this.mousePosLastY = _this.mousePosY;
+				}
+				
+				//Si la souris a parcouru une trop grande distance, on entre en recherche.
+				if(_this.mouseUpDownDelta > _this.config['mouseUpDownDeltaTreshold'])
+				{
+					//Si on est en mosaique, on entre en filtrage.
+					if(_this.currentMode == "MOSAIC")
+					{
+						_this.preUnzoom();
+						_this.currentMode = "FILTER";
+						_this.isMosaicFiltered = true;
+						
+						console.log(_this.date() + ' - ENTRE EN MODE FILTRAGE');
+						
+						_this.isSearchByCurvesOn = true;
+						_this.startSearch();
+						
+						if(!_this.curvesGesturesFound)
+						{
+							$('.notifications').remove();
+							_this.filterSearch();
+						}
+						
+						_this.searchCanvas.onPointerIn(_this.mousePosX, _this.mousePosY - _this.MPTop_margin, null, null);
+					}
+					else if(_this.currentMode == "FILTER" && !_this.isSearchByCurvesOn)
+					{
+						console.log('after search');
+						_this.preUnzoom();
+						_this.isSearchByCurvesOn = true;
+						_this.startSearch();
+						_this.searchCanvas.onPointerIn(_this.mousePosX, _this.mousePosY - _this.MPTop_margin, null, null);
+					}
+					//Si on est dans une vidéo, on entre en recherche.
+					else if(_this.currentMode == "VIDEO" || _this.currentMode == "TIMELINE")
+					{
+						_this.currentMode = "SEARCH";
+						
+						console.log(_this.date() + ' - ENTRE EN MODE RECHERCHE');
+						
+						_this.isSearchByCurvesOn = true;
+						_this.startSearch();
+						
+						if(!_this.curvesGesturesFound)
+						{
+							$('.notifications').remove();
+							_this.searchSearch();
+						}
+						
+						_this.searchCanvas.onPointerIn(_this.mousePosX, _this.mousePosY - _this.MPTop_margin, null, null);
+					}
+					else if(_this.currentMode == "SEARCH" && !_this.isSearchByCurvesOn)
+					{
+						_this.isSearchByCurvesOn = true;
+						_this.startSearch();
+						_this.searchCanvas.onPointerIn(_this.mousePosX, _this.mousePosY - _this.MPTop_margin, null, null);
+					}
+					
+					//Il est possible d'afficher l'aide.
+					if(!_this.canNotifyHelp)
+					{
+						_this.canNotifyHelpTimeout = setTimeout(function()
+						{
+							_this.canNotifyHelp = true;
+						}, _this.config['timeoutCanNotifyHelp']);
+					}
+				}
+			});
+			
+			//Si on fait un mouse up après ce mouse down.
+			$(window).mouseup(function()
+			{
+				console.log('mup');
+				
+				if(_this.isSearchByCurvesOn)
+				{
+					var gesture_match = _this.gestureWithSameCode(_this.actualCode);
+					_this.actualCode = '';
+					
+					if(gesture_match.length > 0)
+					{
+						if(_this.currentMode == "SEARCH" && _this.playerIsReady)
+						{
+							_this.player.widgets[0].searchByGesture(gesture_match);
+							_this.isCurrentlyInASearchByGesture = _this.player.widgets[0].isCurrentlyInASearchByGesture;
+							
+							$('.notifications').remove();
+							_this.searchGesture(gesture_match, 'valid');
+							_this.curvesGesturesFound = false;
+						}
+						else if(_this.currentMode == "FILTER")
+						{
+							if(_this.isMosaicFiltered)
+							{
+								$('.notifications').remove();
+								_this.filterSearchedType = gesture_match;
+								_this.filterGesture(gesture_match, 'valid');
+								_this.searchFilter(gesture_match);
+								_this.curvesGesturesFound = false;
+							}
+						}
+					}
+					
+					_this.searchCanvas.onPointerOut();
+				}
+				
+				//On unbind ce qui a été bindé après le mouse up.
+				$(window).unbind('mousemove');
+				$(window).unbind('mouseup');
+				//On rebind le mousemove principal du body, car ils ont tous été unbindés.
+				$('body').mousemove(function(e)
+				{
+					_this.refreshMainPointer(e.pageX, e.pageY, _this);
+					_this.mousePosX = e.pageX;
+					_this.mousePosY = e.pageY;
+				});
+				
+				_this.mousePosLastX = null;
+				_this.mousePosLastY = null;
+				
+				//Si la distance parcourue par la souris entre le mouse down et le mouse up est inférieure ou égale au seuil.
+				if(_this.mouseUpDownDelta <= _this.config['mouseUpDownDeltaTreshold'])
+				{
+					//Si on est sur un snapshot prézoomé.
+					if(_this.isOnAPrezoomSN && _this.previousZoomedSN != '' && (_this.currentMode == 'MOSAIC' || _this.currentMode == 'FILTER'))
+					{
+						_this.zoom();
+					}
+				}
+				
+				_this.mouseUpDownDelta = 0;
+				_this.isSearchByCurvesOn = false;
+				_this.leaveSearch();
+				
+				if(_this.currentMode == 'FILTER' && _this.filterSearchedType != '')//if(_this.currentSearchGesture != '')
+				{
+					$('.notifications').remove();
+					_this.filterGesture(_this.currentSearchGesture, 'valid');
+				}
+				
+			});
+		});
+	}
 }
 
 /*
@@ -417,7 +604,7 @@
 {
 	var _this = this;
 	
-	var supposedToBeInt = ['length', 'imagesToShow', 'totalImages', 'timePrezoom', 'timePreUnzoom', 'timeZoom', 'zoomTime', 'timeUnzoom', 'timeNeighbourGlowing', 'timeNeighbourUnglowing', 'timeMovingToNeighbour', 'timeSearchFade', 'timeNotifyFade', 'timeFilterFade', 'timeANFade', 'timeFilling', 'zoomedMargin', 'timeoutZoom', 'timeoutUnzoom', 'timeoutMoveToNeighbour', 'timeoutPointersIdle', 'timeoutAreBothPointersHere', 'timeoutRemoveNotificationByGesture', 'timeoutRemoveFailedNotificationByGesture', 'timeoutNotifySwipe', 'timeoutSelectTL', 'timeoutSlideTL', 'timeoutCanNotifyHelp', 'timeoutRemoveSpinner', 'timeoutNouser', 'timeoutNextDrawCurve'];
+	var supposedToBeInt = ['length', 'imagesToShow', 'totalImages', 'timePrezoom', 'timePreUnzoom', 'timeZoom', 'zoomTime', 'timeUnzoom', 'timeNeighbourGlowing', 'timeNeighbourUnglowing', 'timeMovingToNeighbour', 'timeSearchFade', 'timeNotifyFade', 'timeFilterFade', 'timeANFade', 'timeFilling', 'zoomedMargin', 'timeoutZoom', 'timeoutUnzoom', 'timeoutMoveToNeighbour', 'timeoutPointersIdle', 'timeoutAreBothPointersHere', 'timeoutRemoveNotificationByGesture', 'timeoutRemoveFailedNotificationByGesture', 'timeoutNotifySwipe', 'timeoutSelectTL', 'timeoutSlideTL', 'timeoutCanNotifyHelp', 'timeoutRemoveSpinner', 'timeoutNouser', 'timeoutNextDrawCurve', 'mouseUpDownDeltaTreshold'];
 	var supposedToBeFloat = ['zoomPercentage', 'prezoomPercentage'];
 	
 	$.getJSON(file_path, function(data)
@@ -489,7 +676,12 @@
 		}
 		
 		//On initialise le client.
-		_this.client = new client(_this.config['host'], _this.config['port'], _this);
+		if(!_this.mouseInteractions)
+		{
+			_this.client = new client(_this.config['host'], _this.config['port'], _this);
+		}
+		
+		_this.getDictionary();
 	});
 }
 
@@ -554,8 +746,12 @@
 		// this.unzoom();
 		if(this.currentMode == "NO-USER" || this.currentMode.indexOf("INCOMING-") > -1)
 		{
-			this.currentMode = "INCOMING-20";
-			this.unzoom();
+			if(!this.mouseInteractions)
+			{
+				this.currentMode = "INCOMING-20";
+				this.unzoom();
+			}
+			
 			this.currentMode = "MOSAIC";
 			$('.notifications').remove();
 			this.mosaicSelectionAndSearch();
@@ -565,8 +761,8 @@
 		//On affiche les notifications.
 		// this.notifySelectionSearchMosaicFull();
 	
-		// $('#mainPointer').fadeTo(this.config['timePrezoom'], 1);
-		// $('#secondPointer').fadeTo(this.config['timePrezoom'], 1);
+		//$('#mainPointer').fadeTo(this.config['timePrezoom'], 1);
+		//$('#secondPointer').fadeTo(this.config['timePrezoom'], 1);
 	}
 	
 	//Pour les snapshots à afficher.
@@ -939,6 +1135,7 @@
 			// console.log(_this.player);
 			// console.log(_this.player.popcorn);
 		}
+		
 		//Lorsque le player est en pause (par exemple lorsque le curseur arrive à la fin de la timeline).
 		if(_this.player.popcorn)
 		{
@@ -987,6 +1184,11 @@
 			{
 				_this.playerIsReady = true;
 				
+				if(_this.player.widgets[0])
+				{
+					_this.player.widgets[0].setMouseInteractions(_this.mouseInteractions);
+				}
+				
 				if(_this.currentMode == 'VIDEO' || _this.currentMode == 'SEARCH' || _this.currentMode == 'TIMELINE')
 				{
 					_this.canSwipe = true;