private bool canFireClickEvent( TouchRaycast info, TouchRaycast touch ) { #region Should not fire click event if control has been moved var p2u = control.PixelsToUnits(); var startPosition = controlStartPosition / p2u; var currentPosition = control.transform.position / p2u; if( Vector3.Distance( startPosition, currentPosition ) > 1f ) return false; #endregion return true; }
internal void Process( Transform transform, Camera renderCamera, IDFTouchInputSource input, bool retainFocusSetting ) { controlUnderMouse = null; var touches = input.Touches; for( int i = 0; i < touches.Count; i++ ) { // Dereference Touch information var touch = touches[ i ]; // Keep track of the last control under the "mouse" var touchedControl = dfGUIManager.HitTestAll( touch.position ); if( touchedControl != null && touchedControl.transform.IsChildOf( manager.transform ) ) { controlUnderMouse = touchedControl; } #region Don't track touches on empty space if( controlUnderMouse == null ) { if( touch.phase == TouchPhase.Began ) { if( !retainFocusSetting && untracked.Count == 0 ) { var focusControl = dfGUIManager.ActiveControl; if( focusControl != null && focusControl.transform.IsChildOf( manager.transform ) ) { focusControl.Unfocus(); } } untracked.Add( touch.fingerId ); continue; } } if( untracked.Contains( touch.fingerId ) ) { if( touch.phase == TouchPhase.Ended ) untracked.Remove( touch.fingerId ); continue; } #endregion var ray = renderCamera.ScreenPointToRay( touch.position ); var info = new TouchRaycast( controlUnderMouse, touch, ray ); var captured = tracked.FirstOrDefault( x => x.IsTrackingFinger( info.FingerID ) ); if( captured != null ) { captured.Process( info ); continue; } var processed = false; for( int x = 0; x < tracked.Count; x++ ) { if( tracked[ x ].Process( info ) ) { processed = true; break; } } if( !processed && controlUnderMouse != null ) { if( !tracked.Any( x => x.control == controlUnderMouse ) ) { var newTracker = new ControlTouchTracker( manager, controlUnderMouse ); tracked.Add( newTracker ); newTracker.Process( info ); } } } }
/// <summary> /// Processes touch information for a single control /// </summary> /// <param name="info">The touch/raycast data to be processed</param> /// <returns>Returns TRUE if the touch information was processed</returns> public bool Process( TouchRaycast info ) { #region Drag / Drop if( IsDragging ) { // Not interested in any fingers other than the one that // started the drag operation if( !capture.Contains( info.FingerID ) ) return false; // Nothing to do if there's no user action if( info.Phase == TouchPhase.Stationary ) return true; // If the touch was cancelled, raise OnDragEnd event if( info.Phase == TouchPhase.Canceled ) { control.OnDragEnd( new dfDragEventArgs( control, dfDragDropState.Cancelled, dragData, info.ray, info.position ) ); dragState = dfDragDropState.None; touches.Clear(); capture.Clear(); return true; } // If the finger was lifted, attempt drop if( info.Phase == TouchPhase.Ended ) { // Dropped on nothing if( info.control == null || info.control == control ) { control.OnDragEnd( new dfDragEventArgs( control, dfDragDropState.CancelledNoTarget, dragData, info.ray, info.position ) ); dragState = dfDragDropState.None; touches.Clear(); capture.Clear(); return true; } // Dropped on another control var dropArgs = new dfDragEventArgs( info.control, dfDragDropState.Dragging, dragData, info.ray, info.position ); info.control.OnDragDrop( dropArgs ); // If there was no event consumer, or if the event consumer did not // change the state from Dragging (which is not a valid state for // a drop event) then just cancel the operation if( !dropArgs.Used || dropArgs.State != dfDragDropState.Dropped ) { dropArgs.State = dfDragDropState.Cancelled; } // Let the control know that it is no longer being dragged var endArgs = new dfDragEventArgs( control, dropArgs.State, dragData, info.ray, info.position ); endArgs.Target = info.control; control.OnDragEnd( endArgs ); // Clear state dragState = dfDragDropState.None; touches.Clear(); capture.Clear(); return true; } return true; } #endregion #region New touch for this control if( !touches.ContainsKey( info.FingerID ) ) { // Touch is not over control, and is not "captured" by control if( info.control != control ) return false; // Start tracking this finger touches[ info.FingerID ] = info; // See if this is the first touch to be tracked for this control if( touches.Count == 1 ) { // This is the first Touch to be associated with the control control.OnMouseEnter( info ); // If the touch was also started while over the control, // then raise the OnMouseDown event if( info.Phase == TouchPhase.Began ) { capture.Add( info.FingerID ); controlStartPosition = control.transform.position; control.OnMouseDown( info ); // Prevent "click-through" if( Event.current != null ) Event.current.Use(); } return true; } // Switch control to "multi-touch" mode if touch began on control, // otherwise ignore the new touch info if( info.Phase == TouchPhase.Began ) { // Send multi-touch event var activeTouches = getActiveTouches(); var multiTouchArgs = new dfTouchEventArgs( control, activeTouches, info.ray ); control.OnMultiTouch( multiTouchArgs ); } return true; } #endregion #region Previously tracked touch has now ended if( info.Phase == TouchPhase.Canceled || info.Phase == TouchPhase.Ended ) { var phase = info.Phase; var touch = touches[ info.FingerID ]; // Remove the finger from the list of touches touches.Remove( info.FingerID ); if( touches.Count == 0 && phase != TouchPhase.Canceled ) { if( capture.Contains( info.FingerID ) ) { if( canFireClickEvent( info, touch ) ) { if( info.control == this.control ) { if( info.touch.tapCount > 1 ) control.OnDoubleClick( info ); else control.OnClick( info ); } } info.control = this.control; this.control.OnMouseUp( info ); } capture.Remove( info.FingerID ); return true; } else { capture.Remove( info.FingerID ); } if( touches.Count == 1 ) { // Explicitly notify control that multi-touch state has ended control.OnMultiTouchEnd(); return true; } } #endregion #region Multi-touch events // If there is more than one touch active for this control, // then raise the OnMultiTouch event instead of converting // the touch info to mouse events if( touches.Count > 1 ) { var activeTouches = getActiveTouches(); var multiTouchArgs = new dfTouchEventArgs( control, activeTouches, info.ray ); control.OnMultiTouch( multiTouchArgs ); return true; } #endregion // If the touch has not moved, send hover message if( !IsDragging && info.Phase == TouchPhase.Stationary ) { if( info.control == this.control ) { control.OnMouseHover( info ); return true; } return false; } #region See if the control supports (and allows) drag-and-drop var canStartDrag = capture.Contains( info.FingerID ) && dragState == dfDragDropState.None && info.Phase == TouchPhase.Moved; if( canStartDrag ) { // Query the control to see if drag-and-drop is allowed var dragStartArgs = (dfDragEventArgs)info; control.OnDragStart( dragStartArgs ); // If control set State and Used properties to the correct values, // enter drag-and-drop mode if( dragStartArgs.State == dfDragDropState.Dragging && dragStartArgs.Used ) { this.dragState = dfDragDropState.Dragging; this.dragData = dragStartArgs.Data; return true; } // Flag that we've already tried drag and drop this.dragState = dfDragDropState.Denied; } #endregion // Check for mouse leave if( info.control != this.control ) { // If "capture" is not active, fire the OnMouseLeave event if( !capture.Contains( info.FingerID ) ) { info.control = this.control; this.control.OnMouseLeave( info ); this.touches.Remove( info.FingerID ); return true; } } // At this point, the only remaining option is to send OnMouseMove event info.control = this.control; this.control.OnMouseMove( info ); return true; }
internal void Process( Transform transform, Camera renderCamera, dfList<Touch> touches, bool retainFocus ) { for( int i = 0; i < touches.Count; i++ ) { // Dereference Touch information var touch = touches[ i ]; // Raycast from touch position to find the top-most control under the touch var ray = renderCamera.ScreenPointToRay( touch.position ); var maxDistance = renderCamera.farClipPlane - renderCamera.nearClipPlane; var hits = Physics.RaycastAll( ray, maxDistance, renderCamera.cullingMask ); // Keep track of the last control under the "mouse" controlUnderMouse = clipCast( transform, hits ); #region Don't track touches on empty space if( controlUnderMouse == null ) { if( touch.phase == TouchPhase.Began ) { untracked.Add( touch.fingerId ); continue; } } if( untracked.Contains( touch.fingerId ) ) { if( touch.phase == TouchPhase.Ended ) untracked.Remove( touch.fingerId ); continue; } #endregion var info = new TouchRaycast( controlUnderMouse, touch, ray ); var captured = tracked.FirstOrDefault( x => x.IsTrackingFinger( info.FingerID ) ); if( captured != null ) { captured.Process( info ); continue; } var processed = false; for( int x = 0; x < tracked.Count; x++ ) { if( tracked[ x ].Process( info ) ) { processed = true; break; } } if( !processed && controlUnderMouse != null ) { if( !tracked.Any( x => x.control == controlUnderMouse ) ) { if( controlUnderMouse == null ) Debug.Log( "Tracking touch with no control: " + touch.fingerId ); var newTracker = new ControlTouchTracker( manager, controlUnderMouse ); tracked.Add( newTracker ); newTracker.Process( info ); } } } }
private bool canFireClickEvent( TouchRaycast info, TouchRaycast touch ) { if( manager.TouchClickRadius <= 0 ) return true; var distanceFromStart = Vector2.Distance( info.position, touch.position ); return distanceFromStart < manager.TouchClickRadius; }
private bool canFireClickEvent( TouchRaycast info, TouchRaycast touch ) { #region Should not fire click event if control has been moved var p2u = control.PixelsToUnits(); var startPosition = controlStartPosition / p2u; var currentPosition = control.transform.position / p2u; if( Vector3.Distance( startPosition, currentPosition ) > 1f ) return false; #endregion if( manager.TouchClickRadius <= 0 ) return true; var distanceFromStart = Vector2.Distance( info.position, touch.position ); return distanceFromStart <= manager.TouchClickRadius; }
private bool canFireClickEvent( TouchRaycast info, TouchRaycast touch ) { // It is possible that a control could have been deleted during event processing. if( this.control == null ) return false; #region Should not fire click event if control has been moved var p2u = control.PixelsToUnits(); var startPosition = controlStartPosition / p2u; var currentPosition = control.transform.position / p2u; if( Vector3.Distance( startPosition, currentPosition ) > 1f ) return false; #endregion return true; }