Skip to content

Instantly share code, notes, and snippets.

@nicloay
Last active February 6, 2019 11:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nicloay/d13f5c8fa8e1b81eddac92057643308f to your computer and use it in GitHub Desktop.
Save nicloay/d13f5c8fa8e1b81eddac92057643308f to your computer and use it in GitHub Desktop.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using DigitalRubyShared;
using UnityEngine;
using UnityEngine.EventSystems;
using TouchPhase = DigitalRubyShared.TouchPhase;
public class VectorPair
{
public Vector2 Current;
public Vector2 Previous;
public Vector2 Delta
{
get { return Current - Previous; }
}
}
public class StickerGesturesCtrl : MonoBehaviour
{
public Action<GameObject, VectorPair> OnStickerPan;
public Action<GameObject, VectorPair, VectorPair> OnStickerPinch;//<figer1, finger2> (each has current and rprevious)
public Action OnAllGesturesDone;
private int _stickerLayer;
private PanGestureRecognizer _panGesture;
private Camera _camera;
void Awake ()
{
_camera = Camera.main;
_stickerLayer = 1 << this.gameObject.layer;
_panGesture = new PanGestureRecognizer { MinimumNumberOfTouchesToTrack = 1, MaximumNumberOfTouchesToTrack = 5, ThresholdUnits = 0.0f };
}
private void OnEnable()
{
FingersScript.Instance.AddGesture(_panGesture);
_panGesture.StateUpdated += OnPanStateUpdated;
}
private void OnDisable()
{
_panGesture.StateUpdated -= OnPanStateUpdated;
FingersScript.Instance.RemoveGesture(_panGesture);
}
private void OnPanStateUpdated(GestureRecognizer gesture)
{
switch (gesture.State)
{
case GestureRecognizerState.Began:
case GestureRecognizerState.Executing:
case GestureRecognizerState.Ended:
UpdateDragStates();
break;
}
}
Dictionary<int, StickerInfo> _stickerInfoByTouchId= new Dictionary<int, StickerInfo>();
Dictionary<GameObject, StickerInfo> _stickerInfoByGO = new Dictionary<GameObject, StickerInfo>();
private void UpdateDragStates()
{
// collect objects by finger id
foreach (GestureTouch touch in _panGesture.CurrentTrackedTouches)
{
if (_stickerInfoByTouchId.ContainsKey(touch.Id))
{
// already have one - do nothing?
}
else
{
// find gameobject
GameObject stickerGO = GetGOForTouch(touch);
if (stickerGO != null)
{
StickerInfo stickerInfo;
if (_stickerInfoByGO.ContainsKey(stickerGO))
{
stickerInfo = _stickerInfoByGO[stickerGO];
if (!stickerInfo.TouchID.Contains(touch.Id))
{
stickerInfo.TouchID.Add(touch.Id);
}
}
else
{
stickerInfo = new StickerInfo()
{
Sticker = stickerGO,
TouchID = new List<int>() {touch.Id}
};
_stickerInfoByGO.Add(stickerGO, stickerInfo);
}
_stickerInfoByTouchId.Add(touch.Id, stickerInfo);
}
else
{
// didn't WheelHit any sticker here
}
}
}
//iterate over all fingers and report movement
foreach (StickerInfo stickerInfo in _stickerInfoByGO.Values)
{
GestureTouch gt = GetTouchById(stickerInfo.TouchID[0]);
if (stickerInfo.TouchID.Count == 1)
{
if (gt.TouchPhase == TouchPhase.Moved)
{
OnStickerPan.Invoke(stickerInfo.Sticker,
new VectorPair()
{
Current = _camera.ScreenToWorldPoint(gt.ScreenPosition),
Previous = _camera.ScreenToWorldPoint(gt.PreviousPosition)
});
}
}
else
{
GestureTouch gt2 = GetTouchById(stickerInfo.TouchID[1]);
if (gt.TouchPhase == TouchPhase.Moved || gt2.TouchPhase == TouchPhase.Moved)
{
OnStickerPinch.Invoke(stickerInfo.Sticker,
new VectorPair()
{
Current = _camera.ScreenToWorldPoint(gt.ScreenPosition),
Previous = _camera.ScreenToWorldPoint(gt.PreviousPosition)
},
new VectorPair()
{
Current = _camera.ScreenToWorldPoint(gt2.ScreenPosition),
Previous = _camera.ScreenToWorldPoint(gt2.PreviousPosition)
});
}
}
}
if (_panGesture.State == GestureRecognizerState.Ended)
{
_stickerInfoByGO.Clear();
_stickerInfoByTouchId.Clear();
OnAllGesturesDone.Invoke();
}
}
GestureTouch GetTouchById(int id)
{
return _panGesture.CurrentTrackedTouches.First(touch => touch.Id == id);
}
GameObject GetGOForTouch(GestureTouch touch)
{
int nativeTouchId = touch.Id;
// if (EventSystem.current.IsPointerOverGameObject(nativeTouchId))
// {
// return null;
// }
var inputModule = EventSystem.current.currentInputModule;
MethodInfo methodInfo = inputModule.GetType().GetMethod("GetLastPointerEventData", BindingFlags.Instance | BindingFlags.NonPublic);
PointerEventData pointerEventData =
(PointerEventData) methodInfo.Invoke(inputModule, new object[] {nativeTouchId});
if (pointerEventData != null && pointerEventData.pointerDrag != null && pointerEventData.pointerDrag.layer != this.gameObject.layer)
{
return null;
}
var ray = _camera.ScreenPointToRay(touch.ScreenPosition);
var intersection = Physics2D.GetRayIntersection(ray, 1000, _stickerLayer);
return intersection != null && intersection.collider != null ? intersection.transform.gameObject : null;
}
private class StickerInfo
{
public GameObject Sticker;
public List<int> TouchID;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment