588 lines
25 KiB
C#
588 lines
25 KiB
C#
using UnityEngine;
|
|
using UnityEngine.EventSystems;
|
|
|
|
namespace Passer {
|
|
|
|
public enum InputDeviceIDs {
|
|
Head,
|
|
LeftHand,
|
|
RightHand,
|
|
Controller
|
|
}
|
|
|
|
public class InteractionEventData : PointerEventData {
|
|
public InteractionEventData(EventSystem eventSystem) : base(eventSystem) { }
|
|
|
|
public InputDeviceIDs inputDevice;
|
|
public Transform transform;
|
|
}
|
|
|
|
public class InteractionModule : BaseInputModule {
|
|
protected static void DebugLog(string s) {
|
|
#if UNITY_EDITOR
|
|
//Debug.Log(s);
|
|
#endif
|
|
}
|
|
|
|
private const int maxInteractions = 8;
|
|
private int nInteractions = 3;
|
|
|
|
public enum PointerType {
|
|
Point,
|
|
Touch
|
|
}
|
|
|
|
public class InteractionPointer {
|
|
public Transform pointerTransform;
|
|
public Vector3 localPointingDirection;
|
|
public InteractionEventData data;
|
|
|
|
public bool focusingEnabled = false;
|
|
public bool focusing;
|
|
|
|
public GameObject focusObject;
|
|
public GameObject previousFocusObject;
|
|
|
|
public Vector3 focusPosition;
|
|
public Quaternion focusRotation;
|
|
|
|
public Vector2 previousScreenPosition;
|
|
public Vector3 previousFocusPosition;
|
|
public Vector3 focusPositionDelta;
|
|
|
|
public float focusStart;
|
|
public float focusTimeToTouch = 2;
|
|
|
|
public bool externalRayCast = false;
|
|
|
|
public bool clicking = false;
|
|
public GameObject touchedObject;
|
|
public Vector3 touchPosition;
|
|
|
|
public ControllerSide controllerInputSide;
|
|
public Controller.Button controllerButton = Controller.Button.None;
|
|
|
|
public bool hasClicked;
|
|
|
|
public PointerType type;
|
|
|
|
public InteractionPointer(PointerType type, Transform pointerTransform, EventSystem eventSystem) {
|
|
this.type = type;
|
|
this.pointerTransform = pointerTransform;
|
|
this.data = new InteractionEventData(eventSystem);
|
|
}
|
|
|
|
public void ProcessFocus() {
|
|
if (!focusingEnabled)
|
|
return;
|
|
|
|
if (focusObject != previousFocusObject) {
|
|
DebugLog("Focus Change " + focusObject);
|
|
|
|
if (previousFocusObject != null) {
|
|
ExecuteEvents.ExecuteHierarchy(previousFocusObject, data, ExecuteEvents.pointerExitHandler);
|
|
ExecuteEvents.ExecuteHierarchy(previousFocusObject, data, ExecuteEvents.deselectHandler);
|
|
}
|
|
if (focusObject != null) {
|
|
ExecuteEvents.ExecuteHierarchy(focusObject, data, ExecuteEvents.pointerEnterHandler);
|
|
ExecuteEvents.ExecuteHierarchy(focusObject, data, ExecuteEvents.selectHandler);
|
|
focusStart = Time.time;
|
|
hasClicked = false;
|
|
focusing = true;
|
|
}
|
|
previousFocusObject = focusObject;
|
|
}
|
|
}
|
|
|
|
public void ProcessNoFocus() {
|
|
if (previousFocusObject != null) {
|
|
DebugLog("No Focus ");
|
|
|
|
ExecuteEvents.ExecuteHierarchy(previousFocusObject, data, ExecuteEvents.pointerExitHandler);
|
|
ExecuteEvents.ExecuteHierarchy(previousFocusObject, data, ExecuteEvents.deselectHandler);
|
|
focusing = false;
|
|
// no focus = no clicking
|
|
clicking = false;
|
|
previousFocusObject = null;
|
|
}
|
|
}
|
|
|
|
public void ProcessTouch() {
|
|
if (!focusing) {
|
|
// This is not working, because Unity may set this to the wrong object autonomously
|
|
//touchedObject = data.pointerCurrentRaycast.gameObject;
|
|
//if (touchedObject == null) {// object is a 3D object, as we do not use Physicsraycaster, use the focusObject
|
|
touchedObject = focusObject;
|
|
//}
|
|
DebugLog("Touch " + touchedObject);
|
|
|
|
ExecuteEvents.ExecuteHierarchy(touchedObject, data, ExecuteEvents.pointerEnterHandler);
|
|
ExecuteEvents.ExecuteHierarchy(touchedObject, data, ExecuteEvents.selectHandler);
|
|
|
|
focusing = true;
|
|
return;
|
|
}
|
|
else
|
|
ProcessFocus();
|
|
|
|
if (!clicking) { // first activation
|
|
touchedObject = data.pointerCurrentRaycast.gameObject;
|
|
if (touchedObject == null) // object is a 3D object, as we do not use Physicsraycaster, use the focusObject
|
|
touchedObject = focusObject;
|
|
else
|
|
focusObject = touchedObject;
|
|
|
|
ExecuteEvents.ExecuteHierarchy(touchedObject, data, ExecuteEvents.pointerDownHandler);
|
|
|
|
clicking = true;
|
|
}
|
|
else { // we were already touching
|
|
if (focusPositionDelta.sqrMagnitude > 0) { // moved finger during touch
|
|
GameObject pointerDrag = ExecuteEvents.GetEventHandler<IDragHandler>(touchedObject);
|
|
if (!data.dragging) { // we were not dragging yet
|
|
if (pointerDrag != null) { // start dragging only where there is something to drag
|
|
data.pointerDrag = pointerDrag;
|
|
data.dragging = ExecuteEvents.ExecuteHierarchy(data.pointerDrag, data, ExecuteEvents.beginDragHandler);
|
|
}
|
|
}
|
|
else { // still dragging
|
|
ExecuteEvents.ExecuteHierarchy(data.pointerDrag, data, ExecuteEvents.dragHandler);
|
|
}
|
|
|
|
}
|
|
else { // finger did not move
|
|
if (data.dragging) { // we were dragging
|
|
ExecuteEvents.ExecuteHierarchy(data.pointerDrag, data, ExecuteEvents.endDragHandler);
|
|
data.dragging = false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public void ProcessNoTouch() {
|
|
if (clicking) { // We were touching
|
|
if (data.dragging) {
|
|
ExecuteEvents.ExecuteHierarchy(data.pointerDrag, data, ExecuteEvents.endDragHandler);
|
|
data.dragging = false;
|
|
}
|
|
ExecuteEvents.ExecuteHierarchy(touchedObject, data, ExecuteEvents.pointerUpHandler);
|
|
ExecuteEvents.ExecuteHierarchy(touchedObject, data, ExecuteEvents.pointerClickHandler);
|
|
clicking = false;
|
|
touchedObject = null;
|
|
}
|
|
ProcessNoFocus();
|
|
}
|
|
|
|
public void ProcessClick() {
|
|
if (hasClicked)
|
|
return;
|
|
|
|
if (touchedObject != null) {
|
|
ExecuteEvents.ExecuteHierarchy(touchedObject, data, ExecuteEvents.pointerUpHandler);
|
|
}
|
|
else {
|
|
ExecuteEvents.ExecuteHierarchy(focusObject, data, ExecuteEvents.pointerUpHandler);
|
|
}
|
|
hasClicked = true;
|
|
}
|
|
}
|
|
|
|
public InteractionPointer[] pointers = new InteractionPointer[maxInteractions];
|
|
|
|
public int CreateNewInteraction(Transform transform, float timedClick) {
|
|
InteractionPointer pointer = new InteractionPointer(PointerType.Point, transform, eventSystem);
|
|
pointers[nInteractions++] = pointer;
|
|
|
|
pointer.focusingEnabled = false;
|
|
pointer.localPointingDirection = Vector3.forward;
|
|
|
|
pointer.focusTimeToTouch = timedClick;
|
|
|
|
return nInteractions - 1;
|
|
}
|
|
|
|
public int CreateNewInteraction(Transform transform, float timedClick, EventSystem eventSystem) {
|
|
InteractionPointer pointer = new InteractionPointer(PointerType.Point, transform, eventSystem);
|
|
pointers[nInteractions++] = pointer;
|
|
|
|
pointer.focusingEnabled = false;
|
|
pointer.localPointingDirection = Vector3.forward;
|
|
|
|
pointer.focusTimeToTouch = timedClick;
|
|
|
|
return nInteractions - 1;
|
|
}
|
|
|
|
|
|
public void ActivatePointing(int inputDevice, bool active) {
|
|
if (!pointers[inputDevice].focusingEnabled && active)
|
|
pointers[inputDevice].focusStart = 0;
|
|
pointers[inputDevice].focusingEnabled = active;
|
|
}
|
|
|
|
public bool IsPointing(int inputDevice) {
|
|
return pointers[inputDevice].focusingEnabled;
|
|
}
|
|
|
|
public void SetPointingDirection(int inputDevice, Vector3 direction) {
|
|
InteractionPointer pointer = pointers[inputDevice];
|
|
pointer.localPointingDirection = pointer.pointerTransform.InverseTransformDirection(direction);
|
|
}
|
|
|
|
public bool IsTimedClick(int inputDevice) {
|
|
InteractionPointer pointer = pointers[inputDevice];
|
|
|
|
return
|
|
!pointer.hasClicked &&
|
|
pointer.focusTimeToTouch != 0 &&
|
|
pointer.focusStart > 0 &&
|
|
Time.time - pointer.focusStart > pointer.focusTimeToTouch;
|
|
}
|
|
|
|
public void ClickDown(int inputDevice) {
|
|
pointers[inputDevice].ProcessTouch();
|
|
}
|
|
|
|
public void ClickUp(int inputDevice) {
|
|
pointers[inputDevice].ProcessNoTouch();
|
|
}
|
|
|
|
#region FingerInput
|
|
|
|
public void EnableTouchInput(Humanoid.HumanoidControl humanoid, bool isLeft, float autoActivation) {
|
|
if (humanoid.avatarRig == null)
|
|
return;
|
|
|
|
if (pointers == null)
|
|
pointers = new InteractionPointer[maxInteractions]; // 0 = left index, 1 = right index, 2 = head, 3 = controller
|
|
|
|
EventSystem eventSystem = GameObject.FindObjectOfType<EventSystem>();
|
|
if (eventSystem == null)
|
|
eventSystem = humanoid.gameObject.AddComponent<EventSystem>();
|
|
|
|
Controller controllerInput = Controllers.GetController(0);
|
|
|
|
Transform indexFingerDistal = null;
|
|
Transform indexFingerTip = null;
|
|
|
|
InteractionPointer pointer = null;
|
|
if (isLeft) {
|
|
indexFingerDistal = humanoid.leftHandTarget.fingers.index.distal.bone.transform;
|
|
if (indexFingerDistal != null) {
|
|
if (indexFingerDistal.childCount == 1)
|
|
indexFingerTip = indexFingerDistal.GetChild(0);
|
|
else
|
|
indexFingerTip = indexFingerDistal;
|
|
pointer = new InteractionPointer(PointerType.Touch, indexFingerTip, eventSystem);
|
|
pointers[(int)InputDeviceIDs.LeftHand] = pointer;
|
|
|
|
if (controllerInput != null)
|
|
pointer.controllerInputSide = controllerInput.left;
|
|
}
|
|
}
|
|
else {
|
|
indexFingerDistal = humanoid.rightHandTarget.fingers.index.distal.bone.transform;
|
|
if (indexFingerDistal != null) {
|
|
if (indexFingerDistal.childCount == 1)
|
|
indexFingerTip = indexFingerDistal.GetChild(0);
|
|
else
|
|
indexFingerTip = indexFingerDistal;
|
|
pointer = new InteractionPointer(PointerType.Touch, indexFingerTip, eventSystem);
|
|
pointers[(int)InputDeviceIDs.RightHand] = pointer;
|
|
|
|
if (controllerInput != null)
|
|
pointer.controllerInputSide = controllerInput.right;
|
|
}
|
|
}
|
|
|
|
if (indexFingerDistal != null) {
|
|
if (indexFingerDistal.childCount > 0) {
|
|
indexFingerTip = indexFingerDistal.GetChild(0);
|
|
pointer.localPointingDirection = indexFingerTip.InverseTransformDirection(indexFingerTip.position - indexFingerDistal.position).normalized;
|
|
}
|
|
else {
|
|
pointer.localPointingDirection = indexFingerDistal.InverseTransformDirection(indexFingerDistal.position - indexFingerDistal.parent.position).normalized;
|
|
}
|
|
}
|
|
|
|
if (pointer != null) {
|
|
pointer.focusTimeToTouch = autoActivation;
|
|
|
|
// To support hovering
|
|
pointer.focusingEnabled = true;
|
|
}
|
|
}
|
|
|
|
public void ActivateFingerPointing(bool isPointing, bool isLeft) {
|
|
InteractionPointer pointer = isLeft ? pointers[(int)InputDeviceIDs.LeftHand] : pointers[(int)InputDeviceIDs.RightHand];
|
|
|
|
if (pointer != null) {
|
|
pointer.focusingEnabled = isPointing; // only focusing when we are pointing
|
|
}
|
|
}
|
|
|
|
public void OnFingerTouchStart(bool isLeft, GameObject obj) {
|
|
InteractionPointer pointer = isLeft ? pointers[(int)InputDeviceIDs.LeftHand] : pointers[(int)InputDeviceIDs.RightHand];
|
|
if (pointer == null)
|
|
return;
|
|
|
|
pointer.focusObject = obj;
|
|
pointer.data.delta = Vector3.zero;
|
|
pointer.ProcessTouch();
|
|
}
|
|
|
|
public void OnFingerTouchEnd(bool isLeft) {
|
|
InteractionPointer pointer = isLeft ? pointers[(int)InputDeviceIDs.LeftHand] : pointers[(int)InputDeviceIDs.RightHand];
|
|
if (pointer == null)
|
|
return;
|
|
|
|
pointer.ProcessNoTouch();
|
|
}
|
|
|
|
public void HandInteractionActivation(bool isLeft) {
|
|
InteractionPointer pointer = isLeft ? pointers[(int)InputDeviceIDs.LeftHand] : pointers[(int)InputDeviceIDs.RightHand];
|
|
if (pointer == null)
|
|
return;
|
|
|
|
pointer.ProcessTouch();
|
|
}
|
|
#endregion
|
|
|
|
public Vector3 GetFocusPoint(int inputDeviceID) {
|
|
return pointers[inputDeviceID].focusPosition;
|
|
}
|
|
public Quaternion GetFocusRotation(int inputDeviceID) {
|
|
return pointers[inputDeviceID].focusRotation;
|
|
}
|
|
|
|
public GameObject GetFocusObject(int inputDeviceID) {
|
|
if (pointers[(int)inputDeviceID].focusObject != null)
|
|
return pointers[(int)inputDeviceID].focusObject;
|
|
else
|
|
return null;
|
|
}
|
|
|
|
public GameObject GetTouchObject(InputDeviceIDs inputDeviceID) {
|
|
InteractionPointer pointer = pointers[(int)inputDeviceID];
|
|
if (pointer == null)
|
|
return null;
|
|
|
|
if (pointer.touchedObject != null) {
|
|
return pointer.touchedObject;
|
|
}
|
|
else
|
|
return null;
|
|
}
|
|
|
|
public float GetGazeDuration(InputDeviceIDs inputDeviceID) {
|
|
return Time.time - pointers[(int)inputDeviceID].focusStart;
|
|
}
|
|
|
|
public void SetExternalRayCast(int inputDeviceID, Vector3 focusPosition, Quaternion focusRotation, GameObject focusObject) {
|
|
InteractionPointer pointer = pointers[inputDeviceID];
|
|
pointer.focusPosition = focusPosition;
|
|
pointer.focusRotation = focusRotation;
|
|
pointer.focusObject = focusObject;
|
|
pointer.externalRayCast = true;
|
|
}
|
|
|
|
protected virtual void Update() {
|
|
for (int i = 0; i < pointers.Length; i++) {
|
|
if (pointers[i] != null) {
|
|
ProcessPointer(pointers[i], (InputDeviceIDs)i);
|
|
}
|
|
}
|
|
}
|
|
|
|
// This is disabled because it only works when the game window is selected
|
|
public override void Process() {
|
|
}
|
|
|
|
private void ProcessPointer(InteractionPointer pointer, InputDeviceIDs inputDeviceID) {
|
|
CastRayFromPointer(pointer, inputDeviceID);
|
|
|
|
if (pointer.focusingEnabled && pointer.type == PointerType.Point)
|
|
pointer.ProcessFocus();
|
|
if (pointer.focusObject != null && pointer.focusTimeToTouch != 0 && Time.time - pointer.focusStart > pointer.focusTimeToTouch) { // we are clicking
|
|
pointer.ProcessTouch();
|
|
pointer.ProcessNoTouch();
|
|
}
|
|
else if (pointer.clicking) {
|
|
pointer.ProcessTouch();
|
|
}
|
|
|
|
if (pointer.data.pointerCurrentRaycast.gameObject == null) { // no focus
|
|
return;
|
|
}
|
|
|
|
pointer.data.pressPosition = pointer.data.position;
|
|
pointer.data.pointerPressRaycast = pointer.data.pointerCurrentRaycast;
|
|
pointer.data.pointerPress = null; //Clear this for setting later
|
|
pointer.data.useDragThreshold = true;
|
|
|
|
if (pointer.type == PointerType.Touch) {
|
|
// UI touch without colliders works on the finger tip
|
|
float distance = DistanceTipToTransform(pointer.pointerTransform, pointer.data.pointerCurrentRaycast.gameObject.transform);
|
|
if (distance < 0) // we are touching
|
|
pointer.ProcessTouch();
|
|
else if (distance > 0.05F)
|
|
pointer.ProcessNoTouch();
|
|
else
|
|
pointer.ProcessFocus();
|
|
|
|
}
|
|
}
|
|
|
|
private void CastRayFromPointer(InteractionPointer pointer, InputDeviceIDs inputDeviceID) {
|
|
pointer.data.Reset();
|
|
pointer.data.inputDevice = inputDeviceID;
|
|
pointer.data.transform = pointer.pointerTransform;
|
|
if (pointer.pointerTransform == null)
|
|
return;
|
|
|
|
//CastPhysicsRayFromPointer(pointer);
|
|
CastUIRayFromPointer(pointer);
|
|
|
|
pointer.data.scrollDelta = Vector2.zero;
|
|
if (pointer.focusObject != null || pointer.touchedObject != null) {
|
|
if (pointer.previousFocusPosition.sqrMagnitude == 0) {
|
|
pointer.data.delta = Vector2.zero;
|
|
pointer.focusPositionDelta = Vector3.zero;
|
|
}
|
|
else {
|
|
pointer.data.delta = pointer.data.position - pointer.previousScreenPosition;
|
|
pointer.focusPositionDelta = pointer.focusPosition - pointer.previousFocusPosition;
|
|
}
|
|
pointer.previousScreenPosition = pointer.data.position;
|
|
pointer.previousFocusPosition = pointer.focusPosition;
|
|
|
|
pointer.touchPosition = pointer.data.pointerCurrentRaycast.worldPosition;
|
|
}
|
|
}
|
|
|
|
private void CastPhysicsRayFromPointer(InteractionPointer pointer) {
|
|
RaycastResult raycastResult = new RaycastResult();
|
|
|
|
if (pointer.focusingEnabled && pointer.type == PointerType.Point) {
|
|
if (pointer.externalRayCast) {
|
|
raycastResult.worldPosition = pointer.focusPosition;
|
|
raycastResult.worldNormal = pointer.focusRotation * Vector3.forward;
|
|
raycastResult.distance = (raycastResult.worldPosition - pointer.pointerTransform.position).magnitude;
|
|
raycastResult.gameObject = pointer.focusObject;
|
|
Debug.Log("raycasthit 1: " + pointer.focusObject);
|
|
}
|
|
else {
|
|
Vector3 pointingDirection = pointer.pointerTransform.rotation * pointer.localPointingDirection;
|
|
|
|
RaycastHit hit;
|
|
bool raycastHit = Physics.Raycast(pointer.pointerTransform.position, pointingDirection * 10, out hit);
|
|
if (raycastHit) {
|
|
pointer.focusPosition = hit.point;
|
|
pointer.focusRotation = Quaternion.LookRotation(hit.normal);
|
|
pointer.focusObject = hit.transform.gameObject;
|
|
|
|
raycastResult.worldPosition = hit.point;
|
|
raycastResult.worldNormal = hit.normal;
|
|
raycastResult.distance = hit.distance;
|
|
raycastResult.gameObject = hit.transform.gameObject;
|
|
Debug.Log("raycasthit 2: " + hit.transform.gameObject);
|
|
|
|
}
|
|
else {
|
|
pointer.focusPosition = pointer.pointerTransform.position + pointingDirection * 10;
|
|
pointer.focusRotation = Quaternion.LookRotation(-pointingDirection);
|
|
pointer.focusObject = null;
|
|
|
|
raycastResult.worldPosition = pointer.pointerTransform.position + pointingDirection * 10;
|
|
raycastResult.worldNormal = -pointingDirection;
|
|
raycastResult.distance = 0;
|
|
raycastResult.gameObject = null;
|
|
}
|
|
|
|
if (Camera.main != null) {
|
|
pointer.data.position = Camera.main.WorldToScreenPoint(pointer.focusPosition);
|
|
raycastResult.screenPosition = Camera.main.WorldToScreenPoint(pointer.focusPosition);
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
pointer.focusPosition = pointer.pointerTransform.position;
|
|
pointer.focusRotation = Quaternion.identity;
|
|
pointer.focusObject = null;
|
|
|
|
raycastResult.worldPosition = pointer.pointerTransform.position;
|
|
raycastResult.worldNormal = Vector3.up;
|
|
raycastResult.distance = 0;
|
|
raycastResult.gameObject = null;
|
|
|
|
if (Camera.main != null) {
|
|
pointer.data.position = Camera.main.WorldToScreenPoint(pointer.pointerTransform.position);
|
|
raycastResult.screenPosition = Camera.main.WorldToScreenPoint(pointer.focusPosition);
|
|
}
|
|
}
|
|
|
|
pointer.data.pointerCurrentRaycast = raycastResult;
|
|
}
|
|
|
|
//private EventSystem eventSystem;
|
|
private void CastUIRayFromPointer(InteractionPointer pointer) {
|
|
// We only support touch UI interaction without colliders
|
|
if (Camera.main == null || pointer.type != PointerType.Touch)
|
|
return;
|
|
|
|
pointer.data.position = Camera.main.WorldToScreenPoint(pointer.pointerTransform.position);
|
|
float distanceToPointer = Vector3.Distance(Camera.main.transform.position, pointer.pointerTransform.position);
|
|
|
|
System.Collections.Generic.List<RaycastResult> m_RaycastResultCache = new System.Collections.Generic.List<RaycastResult>();
|
|
eventSystem.RaycastAll(pointer.data, m_RaycastResultCache);
|
|
RaycastResult raycastResult = FindFirstRaycast(m_RaycastResultCache, distanceToPointer);
|
|
m_RaycastResultCache.Clear();
|
|
|
|
|
|
if (raycastResult.gameObject != null) {
|
|
if (pointer.type == PointerType.Touch) {
|
|
float distance = DistanceTipToTransform(pointer.pointerTransform, raycastResult.gameObject.transform);
|
|
// Focus only when hovering
|
|
if (distance > 0.05F)
|
|
return;
|
|
}
|
|
|
|
pointer.data.pointerCurrentRaycast = raycastResult;
|
|
pointer.focusObject = pointer.data.pointerCurrentRaycast.gameObject;
|
|
// EventSystem.RaycastAll always casts from main.camera. This is why we need a trick to look like it is casting from the pointerlocation (e.g. finger)
|
|
Vector3 focusDirection = (pointer.focusPosition - Camera.main.transform.position).normalized;
|
|
pointer.focusPosition = Camera.main.transform.position + focusDirection * pointer.data.pointerCurrentRaycast.distance; // pointer.data.pointerCurrentRaycast.worldPosition == Vector.zero unfortunately
|
|
//pointer.data.position = pointer.focusPosition;
|
|
pointer.data.position = Camera.main.WorldToScreenPoint(pointer.focusPosition);
|
|
|
|
}
|
|
}
|
|
|
|
private RaycastResult FindFirstRaycast(System.Collections.Generic.List<RaycastResult> raycastResults, float pointerDistance) {
|
|
foreach (RaycastResult result in raycastResults) {
|
|
float resultDistance = Vector3.Distance(Camera.main.transform.position, result.worldPosition);
|
|
if (result.isValid &&
|
|
result.worldPosition != Vector3.zero &&
|
|
Mathf.Abs(resultDistance - pointerDistance) < 0.02F) {
|
|
return result;
|
|
}
|
|
}
|
|
return new RaycastResult();
|
|
}
|
|
|
|
private Vector2 NormalizedCartesianToSpherical(Vector3 cartCoords) {
|
|
cartCoords.Normalize();
|
|
if (cartCoords.x == 0)
|
|
cartCoords.x = Mathf.Epsilon;
|
|
float outPolar = Mathf.Atan(cartCoords.z / cartCoords.x);
|
|
if (cartCoords.x < 0)
|
|
outPolar += Mathf.PI;
|
|
float outElevation = Mathf.Asin(cartCoords.y);
|
|
return new Vector2(outPolar, outElevation);
|
|
}
|
|
|
|
private float DistanceTipToTransform(Transform fingerTip, Transform transform) {
|
|
return (-transform.InverseTransformPoint(fingerTip.position).z * transform.lossyScale.z) - 0.01F;
|
|
}
|
|
}
|
|
} |