public void OnFingerTouchStart(bool isLeft, GameObject obj)
        {
            InteractionPointer pointer = isLeft ? pointers[(int)InputDeviceIDs.LeftHand] : pointers[(int)InputDeviceIDs.RightHand];

            pointer.focusObject = obj;
            pointer.data.delta  = Vector3.zero;
            pointer.ProcessTouch();
        }
        private void ProcessPointer(InteractionPointer pointer, InputDeviceIDs inputDeviceID)
        {
            CastRayFromPointer(pointer, inputDeviceID);

            pointer.ProcessFocus();
            if (pointer.focusObject != null && pointer.focusTimeToTouch != 0 && Time.time - pointer.focusStart > pointer.focusTimeToTouch)   // we are clicking
            {
                pointer.ProcessClick();
            }

            if (pointer.type == PointerType.Gaze)
            {
                if (pointer.controllerInputSide.GetButton(pointer.controllerButton))   // we are touching
                {
                    pointer.ProcessTouch();
                }
                else
                {
                    pointer.ProcessNoTouch();
                }
            }

            if (pointer.data.pointerCurrentRaycast.gameObject == null)   // no focus
            {
                return;
            }

            //Trigger Enter or Exit Events on the UI Element (like highlighting)
            base.HandlePointerExitAndEnter(pointer.data, pointer.data.pointerCurrentRaycast.gameObject);

            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)
            {
                float distance = DistanceTipToTransform(pointer.pointerTransform, pointer.data.pointerCurrentRaycast.gameObject.transform);
                if (distance < 0)   // we are touching
                {
                    pointer.ProcessTouch();
                }
                else
                {
                    pointer.ProcessNoTouch();
                }
            }

            if (pointer.controllerInputSide.GetButton(pointer.controllerButton))   // we are clicking
            {
                pointer.ProcessTouch();
            }
            else
            {
                pointer.ProcessNoTouch();
            }
        }
        public void EnableFingerPointing(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
            }
        }
        private void CastRayFromPointer(InteractionPointer pointer, InputDeviceIDs inputDeviceID)
        {
            pointer.data.Reset();
            pointer.data.inputDevice = inputDeviceID;

            Vector3 pointingDirection = pointer.pointerTransform.rotation * pointer.localPointingDirection;

            if (pointer.focusingEnabled)
            {
                RaycastHit hit;
                bool       raycastHit = Physics.Raycast(pointer.pointerTransform.position, pointingDirection, out hit);
                if (raycastHit)
                {
                    pointer.focusPosition = hit.point;
                    pointer.focusObject   = hit.transform.gameObject;
                }
                else
                {
                    pointer.focusPosition = pointer.pointerTransform.position + pointingDirection * 10;
                    pointer.focusObject   = null;
                }

                pointer.data.position = Camera.main.WorldToScreenPoint(pointer.focusPosition);
            }
            else
            {
                pointer.focusPosition = pointer.pointerTransform.position;
                pointer.focusObject   = null;

                pointer.data.position = Camera.main.WorldToScreenPoint(pointer.pointerTransform.position);
            }

            pointer.data.scrollDelta = Vector2.zero;
            pointer.data.delta       = pointer.data.position - pointer.previousPosition;
            pointer.previousPosition = pointer.data.position;

            eventSystem.RaycastAll(pointer.data, m_RaycastResultCache);

            pointer.data.pointerCurrentRaycast = FindFirstRaycast(m_RaycastResultCache);
            m_RaycastResultCache.Clear();

            if (pointer.data.pointerCurrentRaycast.gameObject != null)   // we are focusing on a UI element
            {
                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)
                // The result does not look right in scene view, but does look OK in game view
                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.touchPosition = pointer.data.pointerCurrentRaycast.worldPosition;
        }
        public void EnableFingerInputModule(IVR_HandMovements handMovements, bool isLeft, bool touch, float autoActivation)
        {
            if (pointers == null)
            {
                pointers = new InteractionPointer[3]; // 0 = left index, 1 = right index, 2 = head
            }
            ControllerInput controllerInput = Controllers.GetController(0);

            Transform          indexFingerDistal = null;
            InteractionPointer pointer           = null;

            if (isLeft)
            {
                indexFingerDistal = handMovements.animator.GetBoneTransform(HumanBodyBones.LeftIndexDistal);
                if (indexFingerDistal != null)
                {
                    pointer = new InteractionPointer(touch ? PointerType.Touch : PointerType.Gaze, indexFingerDistal.GetChild(0), eventSystem);
                    pointers[(int)InputDeviceIDs.LeftHand] = pointer;
                }

                if (controllerInput != null)
                {
                    pointer.controllerInputSide = controllerInput.left;
                }
            }
            else
            {
                indexFingerDistal = handMovements.animator.GetBoneTransform(HumanBodyBones.RightIndexDistal);
                if (indexFingerDistal != null)
                {
                    pointer = new InteractionPointer(touch ? PointerType.Touch : PointerType.Gaze, indexFingerDistal.GetChild(0), eventSystem);
                    pointers[(int)InputDeviceIDs.RightHand] = pointer;
                }

                if (controllerInput != null)
                {
                    pointer.controllerInputSide = controllerInput.right;
                }
            }

            if (indexFingerDistal != null)
            {
                Transform indexFingerTip = indexFingerDistal.GetChild(0);
                pointer.localPointingDirection = indexFingerTip.InverseTransformDirection(indexFingerTip.position - indexFingerDistal.position).normalized;
            }
            pointer.focusTimeToTouch = autoActivation;
        }
        public static new InteractionPointer Add(Transform parentTransform, PointerType pointerType = PointerType.Ray)
        {
            GameObject pointerObj = new GameObject("Interaction Pointer");

            pointerObj.transform.SetParent(parentTransform);
            pointerObj.transform.localPosition = Vector3.zero;
            pointerObj.transform.localRotation = Quaternion.identity;

            GameObject focusPointObj = new GameObject("FocusPoint");

            focusPointObj.transform.SetParent(pointerObj.transform);
            focusPointObj.transform.localPosition = Vector3.zero;
            focusPointObj.transform.localRotation = Quaternion.identity;

            if (pointerType == PointerType.FocusPoint)
            {
                GameObject focusPointSphere = GameObject.CreatePrimitive(PrimitiveType.Sphere);
                focusPointSphere.transform.SetParent(focusPointObj.transform);
                focusPointSphere.transform.localPosition = Vector3.zero;
                focusPointSphere.transform.localRotation = Quaternion.identity;
                focusPointSphere.transform.localScale    = Vector3.one * 0.1F;
                Collider collider = focusPointSphere.GetComponent <Collider>();
                DestroyImmediate(collider, true);
            }
            else
            {
                LineRenderer pointerRay = focusPointObj.AddComponent <LineRenderer>();
                pointerRay.startWidth        = 0.01F;
                pointerRay.endWidth          = 0.01F;
                pointerRay.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off;
                pointerRay.receiveShadows    = false;
                pointerRay.useWorldSpace     = false;
            }

            InteractionPointer pointer = pointerObj.AddComponent <HumanoidInteractionPointer>();

            pointer.focusPointObj = focusPointObj;
            pointer.rayType       = RayType.Straight;
            return(pointer);
        }
        public void EnableGazeInputModule(Transform cameraTransform, ControllerInput.Side inputSide, ControllerInput.Button activationButton, float autoActivation)
        {
            if (pointers == null)
            {
                pointers = new InteractionPointer[3]; // 0 = left index, 1 = right index, 2 = head
            }
            InteractionPointer pointer = new InteractionPointer(PointerType.Gaze, cameraTransform, eventSystem);

            pointer.focusingEnabled        = true; // gaze is always focusing
            pointer.localPointingDirection = Vector3.forward;
            pointer.focusTimeToTouch       = autoActivation;

            ControllerInput controllerInput = Controllers.GetController(0);

            if (controllerInput != null)
            {
                pointer.controllerInputSide = (inputSide == ControllerInput.Side.Left) ? controllerInput.left : controllerInput.right;
            }
            pointer.controllerButton = activationButton;

            pointers[(int)InputDeviceIDs.Head] = pointer;
        }
        public void OnFingerTouchEnd(bool isLeft)
        {
            InteractionPointer pointer = isLeft ? pointers[(int)InputDeviceIDs.LeftHand] : pointers[(int)InputDeviceIDs.RightHand];

            pointer.ProcessNoTouch();
        }