Support for hand tracking
This commit is contained in:
@@ -0,0 +1,372 @@
|
||||
/************************************************************************************
|
||||
|
||||
Copyright (c) Facebook Technologies, LLC and its affiliates. All rights reserved.
|
||||
|
||||
See SampleFramework license.txt for license terms. Unless required by applicable law
|
||||
or agreed to in writing, the sample code is provided “AS IS” WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied. See the license for specific
|
||||
language governing permissions and limitations under the license.
|
||||
|
||||
************************************************************************************/
|
||||
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Assertions;
|
||||
|
||||
namespace ControllerSelection
|
||||
{
|
||||
public class HandsManager : MonoBehaviour
|
||||
{
|
||||
private const string SKELETON_VISUALIZER_NAME = "SkeletonRenderer";
|
||||
|
||||
[SerializeField] GameObject _leftHand = null;
|
||||
[SerializeField] GameObject _rightHand = null;
|
||||
|
||||
public HandsVisualMode VisualMode = HandsVisualMode.Mesh;
|
||||
private OVRHand[] _hand = new OVRHand[(int)OVRHand.Hand.HandRight + 1];
|
||||
private OVRSkeleton[] _handSkeleton = new OVRSkeleton[(int)OVRHand.Hand.HandRight + 1];
|
||||
private OVRSkeletonRenderer[] _handSkeletonRenderer = new OVRSkeletonRenderer[(int)OVRHand.Hand.HandRight + 1];
|
||||
private OVRMesh[] _handMesh = new OVRMesh[(int)OVRHand.Hand.HandRight + 1];
|
||||
private OVRMeshRenderer[] _handMeshRenderer = new OVRMeshRenderer[(int)OVRHand.Hand.HandRight + 1];
|
||||
private SkinnedMeshRenderer _leftMeshRenderer = null;
|
||||
private SkinnedMeshRenderer _rightMeshRenderer = null;
|
||||
private GameObject _leftSkeletonVisual = null;
|
||||
private GameObject _rightSkeletonVisual = null;
|
||||
private float _currentHandAlpha = 1.0f;
|
||||
private int HandAlphaId = Shader.PropertyToID("_HandAlpha");
|
||||
private PinchMode[] _pinchModeLeft = new PinchMode[(int)OVRHand.HandFinger.Max];
|
||||
private PinchMode[] _pinchModeRight = new PinchMode[(int)OVRHand.HandFinger.Max];
|
||||
private PinchMode[] _lastPinchModeLeft = new PinchMode[(int)OVRHand.HandFinger.Max];
|
||||
private PinchMode[] _lastPinchModeRight = new PinchMode[(int)OVRHand.HandFinger.Max];
|
||||
|
||||
// Pinch strength to be considered a pinch
|
||||
static readonly float PinchMaxStrength = 0.9f;
|
||||
|
||||
public enum HandsVisualMode
|
||||
{
|
||||
Mesh = 0, Skeleton = 1, Both = 2
|
||||
}
|
||||
|
||||
public enum PinchMode
|
||||
{
|
||||
Pinched = 0, NotPinched = 1
|
||||
}
|
||||
|
||||
public OVRHand RightHand
|
||||
{
|
||||
get
|
||||
{
|
||||
return _hand[(int)OVRHand.Hand.HandRight];
|
||||
}
|
||||
private set
|
||||
{
|
||||
_hand[(int)OVRHand.Hand.HandRight] = value;
|
||||
}
|
||||
}
|
||||
|
||||
public OVRSkeleton RightHandSkeleton
|
||||
{
|
||||
get
|
||||
{
|
||||
return _handSkeleton[(int)OVRHand.Hand.HandRight];
|
||||
}
|
||||
private set
|
||||
{
|
||||
_handSkeleton[(int)OVRHand.Hand.HandRight] = value;
|
||||
}
|
||||
}
|
||||
|
||||
public OVRSkeletonRenderer RightHandSkeletonRenderer
|
||||
{
|
||||
get
|
||||
{
|
||||
return _handSkeletonRenderer[(int)OVRHand.Hand.HandRight];
|
||||
}
|
||||
private set
|
||||
{
|
||||
_handSkeletonRenderer[(int)OVRHand.Hand.HandRight] = value;
|
||||
}
|
||||
}
|
||||
|
||||
public OVRMesh RightHandMesh
|
||||
{
|
||||
get
|
||||
{
|
||||
return _handMesh[(int)OVRHand.Hand.HandRight];
|
||||
}
|
||||
private set
|
||||
{
|
||||
_handMesh[(int)OVRHand.Hand.HandRight] = value;
|
||||
}
|
||||
}
|
||||
|
||||
public OVRMeshRenderer RightHandMeshRenderer
|
||||
{
|
||||
get
|
||||
{
|
||||
return _handMeshRenderer[(int)OVRHand.Hand.HandRight];
|
||||
}
|
||||
private set
|
||||
{
|
||||
_handMeshRenderer[(int)OVRHand.Hand.HandRight] = value;
|
||||
}
|
||||
}
|
||||
|
||||
public OVRHand LeftHand
|
||||
{
|
||||
get
|
||||
{
|
||||
return _hand[(int)OVRHand.Hand.HandLeft];
|
||||
}
|
||||
private set
|
||||
{
|
||||
_hand[(int)OVRHand.Hand.HandLeft] = value;
|
||||
}
|
||||
}
|
||||
|
||||
public OVRSkeleton LeftHandSkeleton
|
||||
{
|
||||
get
|
||||
{
|
||||
return _handSkeleton[(int)OVRHand.Hand.HandLeft];
|
||||
}
|
||||
private set
|
||||
{
|
||||
_handSkeleton[(int)OVRHand.Hand.HandLeft] = value;
|
||||
}
|
||||
}
|
||||
|
||||
public OVRSkeletonRenderer LeftHandSkeletonRenderer
|
||||
{
|
||||
get
|
||||
{
|
||||
return _handSkeletonRenderer[(int)OVRHand.Hand.HandLeft];
|
||||
}
|
||||
private set
|
||||
{
|
||||
_handSkeletonRenderer[(int)OVRHand.Hand.HandLeft] = value;
|
||||
}
|
||||
}
|
||||
|
||||
public OVRMesh LeftHandMesh
|
||||
{
|
||||
get
|
||||
{
|
||||
return _handMesh[(int)OVRHand.Hand.HandLeft];
|
||||
}
|
||||
private set
|
||||
{
|
||||
_handMesh[(int)OVRHand.Hand.HandLeft] = value;
|
||||
}
|
||||
}
|
||||
|
||||
public OVRMeshRenderer LeftHandMeshRenderer
|
||||
{
|
||||
get
|
||||
{
|
||||
return _handMeshRenderer[(int)OVRHand.Hand.HandLeft];
|
||||
}
|
||||
private set
|
||||
{
|
||||
_handMeshRenderer[(int)OVRHand.Hand.HandLeft] = value;
|
||||
}
|
||||
}
|
||||
|
||||
public static HandsManager Instance { get; private set; }
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
if (Instance && Instance != this)
|
||||
{
|
||||
Destroy(this);
|
||||
return;
|
||||
}
|
||||
Instance = this;
|
||||
|
||||
Assert.IsNotNull(_leftHand);
|
||||
Assert.IsNotNull(_rightHand);
|
||||
|
||||
LeftHand = _leftHand.GetComponent<OVRHand>();
|
||||
LeftHandSkeleton = _leftHand.GetComponent<OVRSkeleton>();
|
||||
LeftHandSkeletonRenderer = _leftHand.GetComponent<OVRSkeletonRenderer>();
|
||||
LeftHandMesh = _leftHand.GetComponent<OVRMesh>();
|
||||
LeftHandMeshRenderer = _leftHand.GetComponent<OVRMeshRenderer>();
|
||||
|
||||
RightHand = _rightHand.GetComponent<OVRHand>();
|
||||
RightHandSkeleton = _rightHand.GetComponent<OVRSkeleton>();
|
||||
RightHandSkeletonRenderer = _rightHand.GetComponent<OVRSkeletonRenderer>();
|
||||
RightHandMesh = _rightHand.GetComponent<OVRMesh>();
|
||||
RightHandMeshRenderer = _rightHand.GetComponent<OVRMeshRenderer>();
|
||||
_leftMeshRenderer = LeftHand.GetComponent<SkinnedMeshRenderer>();
|
||||
_rightMeshRenderer = RightHand.GetComponent<SkinnedMeshRenderer>();
|
||||
StartCoroutine(FindSkeletonVisualGameObjects());
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
switch (VisualMode)
|
||||
{
|
||||
case HandsVisualMode.Mesh:
|
||||
case HandsVisualMode.Skeleton:
|
||||
_currentHandAlpha = 1.0f;
|
||||
break;
|
||||
case HandsVisualMode.Both:
|
||||
_currentHandAlpha = 0.6f;
|
||||
break;
|
||||
default:
|
||||
_currentHandAlpha = 1.0f;
|
||||
break;
|
||||
}
|
||||
_rightMeshRenderer.sharedMaterial.SetFloat(HandAlphaId, _currentHandAlpha);
|
||||
_leftMeshRenderer.sharedMaterial.SetFloat(HandAlphaId, _currentHandAlpha);
|
||||
|
||||
UpdateFingerPinching(LeftHand, _pinchModeLeft, _lastPinchModeLeft);
|
||||
UpdateFingerPinching(RightHand, _pinchModeRight, _lastPinchModeRight);
|
||||
}
|
||||
|
||||
private IEnumerator FindSkeletonVisualGameObjects()
|
||||
{
|
||||
while (!_leftSkeletonVisual || !_rightSkeletonVisual)
|
||||
{
|
||||
if (!_leftSkeletonVisual)
|
||||
{
|
||||
Transform leftSkeletonVisualTransform = LeftHand.transform.Find(SKELETON_VISUALIZER_NAME);
|
||||
if (leftSkeletonVisualTransform)
|
||||
{
|
||||
_leftSkeletonVisual = leftSkeletonVisualTransform.gameObject;
|
||||
}
|
||||
}
|
||||
|
||||
if (!_rightSkeletonVisual)
|
||||
{
|
||||
Transform rightSkeletonVisualTransform = RightHand.transform.Find(SKELETON_VISUALIZER_NAME);
|
||||
if (rightSkeletonVisualTransform)
|
||||
{
|
||||
_rightSkeletonVisual = rightSkeletonVisualTransform.gameObject;
|
||||
}
|
||||
}
|
||||
yield return null;
|
||||
}
|
||||
SetToCurrentVisualMode();
|
||||
}
|
||||
|
||||
public void SwitchVisualization()
|
||||
{
|
||||
if (!_leftSkeletonVisual || !_rightSkeletonVisual)
|
||||
{
|
||||
return;
|
||||
}
|
||||
VisualMode = (HandsVisualMode)(((int)VisualMode + 1) % ((int)HandsVisualMode.Both + 1));
|
||||
SetToCurrentVisualMode();
|
||||
}
|
||||
|
||||
private void SetToCurrentVisualMode()
|
||||
{
|
||||
switch (VisualMode)
|
||||
{
|
||||
case HandsVisualMode.Mesh:
|
||||
RightHandMeshRenderer.enabled = true;
|
||||
_rightMeshRenderer.enabled = true;
|
||||
_rightSkeletonVisual.gameObject.SetActive(false);
|
||||
LeftHandMeshRenderer.enabled = true;
|
||||
_leftMeshRenderer.enabled = true;
|
||||
_leftSkeletonVisual.gameObject.SetActive(false);
|
||||
break;
|
||||
case HandsVisualMode.Skeleton:
|
||||
RightHandMeshRenderer.enabled = false;
|
||||
_rightMeshRenderer.enabled = false;
|
||||
_rightSkeletonVisual.gameObject.SetActive(true);
|
||||
LeftHandMeshRenderer.enabled = false;
|
||||
_leftMeshRenderer.enabled = false;
|
||||
_leftSkeletonVisual.gameObject.SetActive(true);
|
||||
break;
|
||||
case HandsVisualMode.Both:
|
||||
RightHandMeshRenderer.enabled = true;
|
||||
_rightMeshRenderer.enabled = true;
|
||||
_rightSkeletonVisual.gameObject.SetActive(true);
|
||||
LeftHandMeshRenderer.enabled = true;
|
||||
_leftMeshRenderer.enabled = true;
|
||||
_leftSkeletonVisual.gameObject.SetActive(true);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public static List<OVRBoneCapsule> GetCapsulesPerBone(OVRSkeleton skeleton, OVRSkeleton.BoneId boneId)
|
||||
{
|
||||
List<OVRBoneCapsule> boneCapsules = new List<OVRBoneCapsule>();
|
||||
var capsules = skeleton.Capsules;
|
||||
for (int i = 0; i < capsules.Count; ++i)
|
||||
{
|
||||
if (capsules[i].BoneIndex == (short)boneId)
|
||||
{
|
||||
boneCapsules.Add(capsules[i]);
|
||||
}
|
||||
}
|
||||
return boneCapsules;
|
||||
}
|
||||
|
||||
public PinchMode GetLeftPinchMode(OVRHand.HandFinger finger)
|
||||
{
|
||||
return _pinchModeLeft[(int)finger];
|
||||
}
|
||||
|
||||
public PinchMode GetRightPinchMode(OVRHand.HandFinger finger)
|
||||
{
|
||||
return _pinchModeRight[(int)finger];
|
||||
}
|
||||
|
||||
public PinchMode GetLastLeftPinchMode(OVRHand.HandFinger finger)
|
||||
{
|
||||
return _lastPinchModeLeft[(int)finger];
|
||||
}
|
||||
|
||||
public PinchMode GetLastRightPinchMode(OVRHand.HandFinger finger)
|
||||
{
|
||||
return _lastPinchModeRight[(int)finger];
|
||||
}
|
||||
|
||||
public bool IsInitialized()
|
||||
{
|
||||
return LeftHandSkeleton && LeftHandSkeleton.IsInitialized &&
|
||||
RightHandSkeleton && RightHandSkeleton.IsInitialized &&
|
||||
LeftHandMesh && LeftHandMesh.IsInitialized &&
|
||||
RightHandMesh && RightHandMesh.IsInitialized;
|
||||
}
|
||||
|
||||
static private bool IsFingerPinched(OVRHand hand, OVRHand.HandFinger finger)
|
||||
{
|
||||
return hand.GetFingerConfidence(finger) == OVRHand.TrackingConfidence.High && hand.GetFingerIsPinching(finger) && hand.GetFingerPinchStrength(finger) >= PinchMaxStrength;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enumerates all fingers and updates pinching status. Also tracks last pinch status.
|
||||
/// </summary>
|
||||
/// <param name="hand"></param>
|
||||
/// <param name="pinchModes"></param>
|
||||
/// <param name="lastPinchModes"></param>
|
||||
private void UpdateFingerPinching(OVRHand hand, PinchMode[] pinchModes, PinchMode[] lastPinchModes)
|
||||
{
|
||||
for (int i = 0; i < pinchModes.Length; i++)
|
||||
{
|
||||
lastPinchModes[i] = pinchModes[i];
|
||||
pinchModes[i] = PinchMode.NotPinched;
|
||||
}
|
||||
|
||||
var isReliable = hand.IsTracked && hand.HandConfidence == OVRHand.TrackingConfidence.High;
|
||||
if (!isReliable)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
pinchModes[(int)OVRHand.HandFinger.Thumb] = IsFingerPinched(hand, OVRHand.HandFinger.Thumb) ? PinchMode.Pinched : PinchMode.NotPinched;
|
||||
pinchModes[(int)OVRHand.HandFinger.Index] = IsFingerPinched(hand, OVRHand.HandFinger.Index) ? PinchMode.Pinched : PinchMode.NotPinched;
|
||||
pinchModes[(int)OVRHand.HandFinger.Middle] = IsFingerPinched(hand, OVRHand.HandFinger.Middle) ? PinchMode.Pinched : PinchMode.NotPinched;
|
||||
pinchModes[(int)OVRHand.HandFinger.Ring] = IsFingerPinched(hand, OVRHand.HandFinger.Ring) ? PinchMode.Pinched : PinchMode.NotPinched;
|
||||
pinchModes[(int)OVRHand.HandFinger.Pinky] = IsFingerPinched(hand, OVRHand.HandFinger.Pinky) ? PinchMode.Pinched : PinchMode.NotPinched;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 355b24382fa1a9c4f8b72fd2095581f7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -19,37 +19,137 @@ limitations under the License.
|
||||
|
||||
************************************************************************************/
|
||||
|
||||
using System.Collections.Specialized;
|
||||
using System.Runtime.InteropServices;
|
||||
using UnityEngine;
|
||||
|
||||
namespace ControllerSelection {
|
||||
public class OVRInputHelpers {
|
||||
// Given a controller and tracking spcae, return the ray that controller uses.
|
||||
namespace ControllerSelection
|
||||
{
|
||||
public class OVRInputHelpers
|
||||
{
|
||||
public enum HandFilter
|
||||
{
|
||||
None = 0,
|
||||
Left = 1,
|
||||
Right = 2,
|
||||
Both = Left | Right
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indicates whether hand started pinching in this frame
|
||||
/// </summary>
|
||||
/// <param name="activeController"></param>
|
||||
/// <param name="finger"></param>
|
||||
/// <returns></returns>
|
||||
public static bool IsFingerStartPinching(OVRInput.Controller activeController, OVRHand.HandFinger finger)
|
||||
{
|
||||
bool isLeftHand = (activeController & OVRInput.Controller.LHand) == OVRInput.Controller.LHand;
|
||||
var curPinch = isLeftHand ? HandsManager.Instance.GetLeftPinchMode(finger) : HandsManager.Instance.GetRightPinchMode(finger);
|
||||
var lastPinch = isLeftHand ? HandsManager.Instance.GetLastLeftPinchMode(finger) : HandsManager.Instance.GetLastRightPinchMode(finger);
|
||||
|
||||
return (lastPinch == HandsManager.PinchMode.NotPinched && curPinch == HandsManager.PinchMode.Pinched);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indicates whether hand stopped pinching in this frame
|
||||
/// </summary>
|
||||
/// <param name="activeController"></param>
|
||||
/// <param name="finger"></param>
|
||||
/// <returns></returns>
|
||||
public static bool IsFingerStopPinching(OVRInput.Controller activeController, OVRHand.HandFinger finger)
|
||||
{
|
||||
bool isLeftHand = (activeController & OVRInput.Controller.LHand) == OVRInput.Controller.LHand;
|
||||
var curPinch = isLeftHand ? HandsManager.Instance.GetLeftPinchMode(finger) : HandsManager.Instance.GetRightPinchMode(finger);
|
||||
var lastPinch = isLeftHand ? HandsManager.Instance.GetLastLeftPinchMode(finger) : HandsManager.Instance.GetLastRightPinchMode(finger);
|
||||
|
||||
return (lastPinch == HandsManager.PinchMode.Pinched && curPinch == HandsManager.PinchMode.NotPinched);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indicates whether hand is pinching
|
||||
/// </summary>
|
||||
/// <param name="activeController"></param>
|
||||
/// <param name="finger"></param>
|
||||
/// <returns></returns>
|
||||
public static bool IsFingerPinching(OVRInput.Controller activeController, OVRHand.HandFinger finger)
|
||||
{
|
||||
bool isLeftHand = (activeController & OVRInput.Controller.LHand) == OVRInput.Controller.LHand;
|
||||
var curPinch = isLeftHand ? HandsManager.Instance.GetLeftPinchMode(finger) : HandsManager.Instance.GetRightPinchMode(finger);
|
||||
return (curPinch == HandsManager.PinchMode.Pinched);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns hand orientation
|
||||
/// </summary>
|
||||
/// <param name="factiveController"></param>
|
||||
/// <param name="orientation"></param>
|
||||
/// <param name="position"></param>
|
||||
/// <returns></returns>
|
||||
public static bool GetHandOrientation(OVRInput.Controller activeController, out Quaternion orientation, out Vector3 position)
|
||||
{
|
||||
orientation = default(Quaternion);
|
||||
position = default(Vector3);
|
||||
|
||||
if ((activeController & OVRInput.Controller.Hands) == OVRInput.Controller.None)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!HandsManager.Instance || !HandsManager.Instance.IsInitialized())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var hand = (activeController & OVRInput.Controller.RHand) == OVRInput.Controller.RHand ? HandsManager.Instance.RightHand : HandsManager.Instance.LeftHand;
|
||||
var isReliable = hand.IsTracked && hand.HandConfidence == OVRHand.TrackingConfidence.High;
|
||||
if (!isReliable || !hand.IsPointerPoseValid)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var pointer = hand.PointerPose;
|
||||
|
||||
orientation = pointer.rotation;
|
||||
position = pointer.position;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Given a controller and tracking space, return the ray that controller uses.
|
||||
// Will fall back to center eye or camera on Gear if no controller is present.
|
||||
public static Ray GetSelectionRay(OVRInput.Controller activeController, Transform trackingSpace) {
|
||||
if (trackingSpace != null && activeController != OVRInput.Controller.None) {
|
||||
Quaternion orientation = OVRInput.GetLocalControllerRotation(activeController);
|
||||
Vector3 localStartPoint = OVRInput.GetLocalControllerPosition(activeController);
|
||||
public static bool GetSelectionRay(OVRInput.Controller activeController, Transform trackingSpace, out Ray ray)
|
||||
{
|
||||
ray = default(Ray);
|
||||
if (trackingSpace != null && activeController != OVRInput.Controller.None)
|
||||
{
|
||||
Quaternion orientation = default(Quaternion);
|
||||
Vector3 localStartPoint = default(Vector3);
|
||||
|
||||
if ((activeController & OVRInput.Controller.Hands) != OVRInput.Controller.None)
|
||||
{
|
||||
if (!GetHandOrientation(activeController, out orientation, out localStartPoint))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
orientation = OVRInput.GetLocalControllerRotation(activeController);
|
||||
localStartPoint = OVRInput.GetLocalControllerPosition(activeController);
|
||||
}
|
||||
|
||||
Matrix4x4 localToWorld = trackingSpace.localToWorldMatrix;
|
||||
Vector3 worldStartPoint = localToWorld.MultiplyPoint(localStartPoint);
|
||||
Vector3 worldOrientation = localToWorld.MultiplyVector(orientation * Vector3.forward);
|
||||
|
||||
return new Ray(worldStartPoint, worldOrientation);
|
||||
ray = new Ray(worldStartPoint, worldOrientation);
|
||||
return true;
|
||||
}
|
||||
|
||||
Transform cameraTransform = Camera.main.transform;
|
||||
|
||||
if (OVRManager.instance != null) {
|
||||
OVRCameraRig cameraRig = OVRManager.instance.GetComponent<OVRCameraRig>();
|
||||
if (cameraRig != null) {
|
||||
cameraTransform = cameraRig.centerEyeAnchor;
|
||||
}
|
||||
}
|
||||
|
||||
return new Ray(cameraTransform.position, cameraTransform.forward);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Search the scene to find a tracking spce. This method can be expensive! Try to avoid it if possible.
|
||||
// Search the scene to find a tracking space. This method can be expensive! Try to avoid it if possible.
|
||||
public static Transform FindTrackingSpace() {
|
||||
// There should be an OVRManager in the scene
|
||||
if (OVRManager.instance != null) {
|
||||
@@ -82,39 +182,53 @@ namespace ControllerSelection {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Find the current active controller, based on last time a certain button was hit. Needs to know the previous active controller.
|
||||
public static OVRInput.Controller GetControllerForButton(OVRInput.Button joyPadClickButton, OVRInput.Controller oldController) {
|
||||
/// <summary>
|
||||
/// Returns connected controllers
|
||||
/// </summary>
|
||||
/// <param name="filter"></param>
|
||||
/// <returns></returns>
|
||||
public static OVRInput.Controller GetConnectedControllers(HandFilter filter = HandFilter.Both)
|
||||
{
|
||||
OVRInput.Controller controller = OVRInput.GetConnectedControllers();
|
||||
|
||||
if ((controller & OVRInput.Controller.RTouch) == OVRInput.Controller.RTouch) {
|
||||
if (OVRInput.Get(joyPadClickButton, OVRInput.Controller.RTouch) || oldController == OVRInput.Controller.None) {
|
||||
return OVRInput.Controller.RTouch;
|
||||
if (((filter & HandFilter.Right) == HandFilter.Right) && (controller & OVRInput.Controller.RTouch) == OVRInput.Controller.RTouch)
|
||||
{
|
||||
return OVRInput.Controller.RTouch;
|
||||
}
|
||||
|
||||
if (((filter & HandFilter.Left) == HandFilter.Left) && (controller & OVRInput.Controller.LTouch) == OVRInput.Controller.LTouch)
|
||||
{
|
||||
return OVRInput.Controller.LTouch;
|
||||
}
|
||||
|
||||
if (((filter & HandFilter.Right) == HandFilter.Right) && (controller & OVRInput.Controller.RTrackedRemote) == OVRInput.Controller.RTrackedRemote)
|
||||
{
|
||||
return OVRInput.Controller.RTrackedRemote;
|
||||
}
|
||||
|
||||
if (((filter & HandFilter.Left) == HandFilter.Left) && (controller & OVRInput.Controller.LTrackedRemote) == OVRInput.Controller.LTrackedRemote)
|
||||
{
|
||||
return OVRInput.Controller.LTrackedRemote;
|
||||
}
|
||||
|
||||
controller = OVRInput.Controller.None;
|
||||
if (OVRPlugin.GetHandTrackingEnabled())
|
||||
{
|
||||
if ((filter & HandFilter.Both) == HandFilter.Both)
|
||||
{
|
||||
return OVRInput.Controller.Hands;
|
||||
}
|
||||
else if ((filter & HandFilter.Right) == HandFilter.Right)
|
||||
{
|
||||
return OVRInput.Controller.RHand;
|
||||
}
|
||||
else
|
||||
{
|
||||
return OVRInput.Controller.LHand;
|
||||
}
|
||||
}
|
||||
|
||||
if ((controller & OVRInput.Controller.LTouch) == OVRInput.Controller.LTouch) {
|
||||
if (OVRInput.Get(joyPadClickButton, OVRInput.Controller.LTouch) || oldController == OVRInput.Controller.None) {
|
||||
return OVRInput.Controller.LTouch;
|
||||
}
|
||||
}
|
||||
|
||||
if ((controller & OVRInput.Controller.RTrackedRemote) == OVRInput.Controller.RTrackedRemote) {
|
||||
if (OVRInput.Get(joyPadClickButton, OVRInput.Controller.RTrackedRemote) || oldController == OVRInput.Controller.None) {
|
||||
return OVRInput.Controller.RTrackedRemote;
|
||||
}
|
||||
}
|
||||
|
||||
if ((controller & OVRInput.Controller.LTrackedRemote) == OVRInput.Controller.LTrackedRemote) {
|
||||
if (OVRInput.Get(joyPadClickButton, OVRInput.Controller.LTrackedRemote) || oldController == OVRInput.Controller.None) {
|
||||
return OVRInput.Controller.LTrackedRemote;
|
||||
}
|
||||
}
|
||||
|
||||
if ((controller & oldController) != oldController) {
|
||||
return OVRInput.Controller.None;
|
||||
}
|
||||
|
||||
return oldController;
|
||||
return OVRInput.Controller.None;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -28,7 +28,14 @@ namespace ControllerSelection
|
||||
{
|
||||
public class OVRInputModule : UnityEngine.EventSystems.PointerInputModule
|
||||
{
|
||||
protected override void Awake() {
|
||||
public enum Hand
|
||||
{
|
||||
None,
|
||||
Left = OVRInputHelpers.HandFilter.Left,
|
||||
Right = OVRInputHelpers.HandFilter.Right
|
||||
}
|
||||
|
||||
protected override void Awake() {
|
||||
base.Awake();
|
||||
if (trackingSpace == null) {
|
||||
Debug.LogWarning ("OVRInputModule did not have a tracking space set. Looking for one");
|
||||
@@ -65,6 +72,9 @@ namespace ControllerSelection
|
||||
[Tooltip("Primary selection button")]
|
||||
public OVRInput.Button joyPadClickButton = OVRInput.Button.PrimaryIndexTrigger;
|
||||
|
||||
[Tooltip("Primary hand pinch finger")]
|
||||
public OVRHand.HandFinger pinchFinger = OVRHand.HandFinger.Index;
|
||||
|
||||
[Header("Physics")]
|
||||
[Tooltip("Perform an sphere cast to determine correct depth for gaze pointer")]
|
||||
public bool performSphereCastForGazepointer;
|
||||
@@ -87,8 +97,7 @@ namespace ControllerSelection
|
||||
[Tooltip("Distance scrolled when swipe scroll occurs")]
|
||||
public float swipeScrollScale = 4f;
|
||||
|
||||
|
||||
[HideInInspector]
|
||||
[HideInInspector]
|
||||
public OVRInput.Controller activeController = OVRInput.Controller.None;
|
||||
|
||||
public delegate void RayHitDelegate(Vector3 hitPosition, Vector3 hitNormal);
|
||||
@@ -101,13 +110,15 @@ namespace ControllerSelection
|
||||
#endregion
|
||||
|
||||
// The raycaster that gets to do pointer interaction (e.g. with a mouse), gaze interaction always works
|
||||
// private OVRRaycaster _activeGraphicRaycaster;
|
||||
[NonSerialized]
|
||||
public OVRRaycaster activeGraphicRaycaster;
|
||||
[Header("Dragging")]
|
||||
[Tooltip("Minimum pointer movement in degrees to start dragging")]
|
||||
public float angleDragThreshold = 1;
|
||||
|
||||
[Tooltip("Suppress click while dragging")]
|
||||
public bool suppressClickOnDrag = true;
|
||||
|
||||
// The following region contains code exactly the same as the implementation
|
||||
// of StandaloneInputModule. It is copied here rather than inheriting from StandaloneInputModule
|
||||
// because most of StandaloneInputModule is private so it isn't possible to easily derive from.
|
||||
@@ -120,8 +131,8 @@ namespace ControllerSelection
|
||||
// ProcessMouseEvent
|
||||
// UseMouse
|
||||
#region StandaloneInputModule code
|
||||
|
||||
private float m_NextAction;
|
||||
|
||||
private float m_NextAction;
|
||||
|
||||
private Vector2 m_LastMousePosition;
|
||||
private Vector2 m_MousePosition;
|
||||
@@ -218,8 +229,6 @@ namespace ControllerSelection
|
||||
|
||||
public override void UpdateModule()
|
||||
{
|
||||
activeController = OVRInputHelpers.GetControllerForButton (OVRInput.Button.PrimaryIndexTrigger, activeController);
|
||||
|
||||
m_LastMousePosition = m_MousePosition;
|
||||
m_MousePosition = Input.mousePosition;
|
||||
}
|
||||
@@ -243,6 +252,7 @@ namespace ControllerSelection
|
||||
shouldActivate |= !Mathf.Approximately(Input.GetAxisRaw(m_VerticalAxis), 0.0f);
|
||||
shouldActivate |= (m_MousePosition - m_LastMousePosition).sqrMagnitude > 0.0f;
|
||||
shouldActivate |= Input.GetMouseButtonDown(0);
|
||||
|
||||
return shouldActivate;
|
||||
}
|
||||
|
||||
@@ -265,8 +275,6 @@ namespace ControllerSelection
|
||||
ClearSelection();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Process submit keys.
|
||||
/// </summary>
|
||||
@@ -337,10 +345,6 @@ namespace ControllerSelection
|
||||
return axisEventData.used;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
private bool SendUpdateEventToSelectedObject()
|
||||
{
|
||||
if (eventSystem.currentSelectedGameObject == null)
|
||||
@@ -380,8 +384,6 @@ namespace ControllerSelection
|
||||
if (newPressed == null)
|
||||
newPressed = UnityEngine.EventSystems.ExecuteEvents.GetEventHandler<UnityEngine.EventSystems.IPointerClickHandler>(currentOverGo);
|
||||
|
||||
// Debug.Log("Pressed: " + newPressed);
|
||||
|
||||
float time = Time.unscaledTime;
|
||||
|
||||
if (newPressed == pointerEvent.lastPress)
|
||||
@@ -408,22 +410,25 @@ namespace ControllerSelection
|
||||
pointerEvent.pointerDrag = UnityEngine.EventSystems.ExecuteEvents.GetEventHandler<UnityEngine.EventSystems.IDragHandler>(currentOverGo);
|
||||
|
||||
if (pointerEvent.pointerDrag != null)
|
||||
{
|
||||
UnityEngine.EventSystems.ExecuteEvents.Execute(pointerEvent.pointerDrag, pointerEvent, UnityEngine.EventSystems.ExecuteEvents.initializePotentialDrag);
|
||||
}
|
||||
}
|
||||
|
||||
// PointerUp notification
|
||||
if (data.ReleasedThisFrame())
|
||||
{
|
||||
// Debug.Log("Executing pressup on: " + pointer.pointerPress);
|
||||
UnityEngine.EventSystems.ExecuteEvents.Execute(pointerEvent.pointerPress, pointerEvent, UnityEngine.EventSystems.ExecuteEvents.pointerUpHandler);
|
||||
|
||||
// Debug.Log("KeyCode: " + pointer.eventData.keyCode);
|
||||
|
||||
// see if we mouse up on the same element that we clicked on...
|
||||
var pointerUpHandler = UnityEngine.EventSystems.ExecuteEvents.GetEventHandler<UnityEngine.EventSystems.IPointerClickHandler>(currentOverGo);
|
||||
|
||||
// Determine if we're dragging and if we want to suppress click while dragging
|
||||
var isDragging = pointerEvent.pointerDrag != null && pointerEvent.dragging;
|
||||
var suppressClick = suppressClickOnDrag && isDragging;
|
||||
|
||||
// PointerClick and Drop events
|
||||
if (pointerEvent.pointerPress == pointerUpHandler && pointerEvent.eligibleForClick)
|
||||
if (!suppressClick && pointerEvent.pointerPress == pointerUpHandler && pointerEvent.eligibleForClick)
|
||||
{
|
||||
UnityEngine.EventSystems.ExecuteEvents.Execute(pointerEvent.pointerPress, pointerEvent, UnityEngine.EventSystems.ExecuteEvents.pointerClickHandler);
|
||||
}
|
||||
@@ -436,8 +441,10 @@ namespace ControllerSelection
|
||||
pointerEvent.pointerPress = null;
|
||||
pointerEvent.rawPointerPress = null;
|
||||
|
||||
if (pointerEvent.pointerDrag != null && pointerEvent.dragging)
|
||||
if (isDragging)
|
||||
{
|
||||
UnityEngine.EventSystems.ExecuteEvents.Execute(pointerEvent.pointerDrag, pointerEvent, UnityEngine.EventSystems.ExecuteEvents.endDragHandler);
|
||||
}
|
||||
|
||||
pointerEvent.dragging = false;
|
||||
pointerEvent.pointerDrag = null;
|
||||
@@ -506,10 +513,8 @@ namespace ControllerSelection
|
||||
SendSubmitEventToSelectedObject();
|
||||
}
|
||||
|
||||
ProcessMouseEvent(GetGazePointerData());
|
||||
#if !UNITY_ANDROID
|
||||
ProcessMouseEvent(GetCanvasPointerData());
|
||||
#endif
|
||||
ProcessMouseEvent(GetGazePointerData(true));
|
||||
ProcessMouseEvent(GetGazePointerData(false));
|
||||
}
|
||||
/// <summary>
|
||||
/// Decide if mouse events need to be processed this frame. Same as StandloneInputModule except
|
||||
@@ -560,19 +565,20 @@ namespace ControllerSelection
|
||||
#region PointerEventData pool
|
||||
|
||||
// Pool for OVRRayPointerEventData for ray based pointers
|
||||
protected Dictionary<int, OVRRayPointerEventData> m_VRRayPointerData = new Dictionary<int, OVRRayPointerEventData>();
|
||||
protected Dictionary<int, OVRRayPointerEventData> m_VRRayPointerDataLeft = new Dictionary<int, OVRRayPointerEventData>();
|
||||
protected Dictionary<int, OVRRayPointerEventData> m_VRRayPointerDataRight = new Dictionary<int, OVRRayPointerEventData>();
|
||||
|
||||
|
||||
protected bool GetPointerData(int id, out OVRRayPointerEventData data, bool create)
|
||||
protected bool GetPointerData(int id, out OVRRayPointerEventData data, bool create, bool isLeft)
|
||||
{
|
||||
if (!m_VRRayPointerData.TryGetValue(id, out data) && create)
|
||||
var rayPointerData = isLeft ? m_VRRayPointerDataLeft : m_VRRayPointerDataRight;
|
||||
if (!rayPointerData.TryGetValue(id, out data) && create)
|
||||
{
|
||||
data = new OVRRayPointerEventData(eventSystem)
|
||||
{
|
||||
pointerId = id,
|
||||
};
|
||||
|
||||
m_VRRayPointerData.Add(id, data);
|
||||
rayPointerData.Add(id, data);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -590,7 +596,12 @@ namespace ControllerSelection
|
||||
// clear all selection
|
||||
HandlePointerExitAndEnter(pointer, null);
|
||||
}
|
||||
foreach (var pointer in m_VRRayPointerData.Values)
|
||||
foreach (var pointer in m_VRRayPointerDataLeft.Values)
|
||||
{
|
||||
// clear all selection
|
||||
HandlePointerExitAndEnter(pointer, null);
|
||||
}
|
||||
foreach (var pointer in m_VRRayPointerDataRight.Values)
|
||||
{
|
||||
// clear all selection
|
||||
HandlePointerExitAndEnter(pointer, null);
|
||||
@@ -614,26 +625,28 @@ namespace ControllerSelection
|
||||
return Vector3.Cross(LeftEdge, BottomEdge).normalized;
|
||||
}
|
||||
|
||||
private readonly MouseState m_MouseState = new MouseState();
|
||||
// Overridden so that we can process the two types of pointer separately
|
||||
private readonly MouseState m_MouseStateLeft = new MouseState();
|
||||
private readonly MouseState m_MouseStateRight = new MouseState();
|
||||
|
||||
// Overridden so that we can process the two types of pointer separately
|
||||
|
||||
// The following 2 functions are equivalent to PointerInputModule.GetMousePointerEventData but are customized to
|
||||
// get data for ray pointers and canvas mouse pointers.
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// State for a pointer controlled by a world space ray. E.g. gaze pointer
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
protected MouseState GetGazePointerData()
|
||||
protected MouseState GetGazePointerData(bool isLeft)
|
||||
{
|
||||
// Get the OVRRayPointerEventData reference
|
||||
OVRRayPointerEventData leftData;
|
||||
GetPointerData(kMouseLeftId, out leftData, true );
|
||||
GetPointerData(kMouseLeftId, out leftData, true, isLeft);
|
||||
leftData.Reset();
|
||||
|
||||
|
||||
leftData.worldSpaceRay = OVRInputHelpers.GetSelectionRay(activeController, trackingSpace);
|
||||
leftData.worldSpaceRay = default(Ray);
|
||||
var activeController = OVRInputHelpers.GetConnectedControllers(isLeft ? OVRInputHelpers.HandFilter.Left : OVRInputHelpers.HandFilter.Right);
|
||||
bool gotRay = OVRInputHelpers.GetSelectionRay(activeController, trackingSpace, out leftData.worldSpaceRay);
|
||||
leftData.scrollDelta = GetExtraScrollDelta();
|
||||
|
||||
//Populate some default values
|
||||
@@ -654,7 +667,6 @@ namespace ControllerSelection
|
||||
// space position for the camera attached to this raycaster for compatability
|
||||
leftData.position = ovrRaycaster.GetScreenPosition(raycast);
|
||||
|
||||
|
||||
// Find the world position and normal the Graphic the ray intersected
|
||||
RectTransform graphicRect = raycast.gameObject.GetComponent<RectTransform>();
|
||||
if (graphicRect != null)
|
||||
@@ -682,75 +694,21 @@ namespace ControllerSelection
|
||||
|
||||
// copy the apropriate data into right and middle slots
|
||||
OVRRayPointerEventData rightData;
|
||||
GetPointerData(kMouseRightId, out rightData, true );
|
||||
GetPointerData(kMouseRightId, out rightData, true, isLeft);
|
||||
CopyFromTo(leftData, rightData);
|
||||
rightData.button = UnityEngine.EventSystems.PointerEventData.InputButton.Right;
|
||||
|
||||
OVRRayPointerEventData middleData;
|
||||
GetPointerData(kMouseMiddleId, out middleData, true );
|
||||
GetPointerData(kMouseMiddleId, out middleData, true, isLeft);
|
||||
CopyFromTo(leftData, middleData);
|
||||
middleData.button = UnityEngine.EventSystems.PointerEventData.InputButton.Middle;
|
||||
|
||||
var mouseState = isLeft ? m_MouseStateLeft : m_MouseStateRight;
|
||||
|
||||
m_MouseState.SetButtonState(UnityEngine.EventSystems.PointerEventData.InputButton.Left, GetGazeButtonState(), leftData);
|
||||
m_MouseState.SetButtonState(UnityEngine.EventSystems.PointerEventData.InputButton.Right, UnityEngine.EventSystems.PointerEventData.FramePressState.NotChanged, rightData);
|
||||
m_MouseState.SetButtonState(UnityEngine.EventSystems.PointerEventData.InputButton.Middle, UnityEngine.EventSystems.PointerEventData.FramePressState.NotChanged, middleData);
|
||||
return m_MouseState;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get state for pointer which is a pointer moving in world space across the surface of a world space canvas.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
protected MouseState GetCanvasPointerData()
|
||||
{
|
||||
// Get the OVRRayPointerEventData reference
|
||||
UnityEngine.EventSystems.PointerEventData leftData;
|
||||
GetPointerData(kMouseLeftId, out leftData, true );
|
||||
leftData.Reset();
|
||||
|
||||
// Setup default values here. Set position to zero because we don't actually know the pointer
|
||||
// positions. Each canvas knows the position of its canvas pointer.
|
||||
leftData.position = Vector2.zero;
|
||||
leftData.scrollDelta = Input.mouseScrollDelta;
|
||||
leftData.button = UnityEngine.EventSystems.PointerEventData.InputButton.Left;
|
||||
|
||||
if (activeGraphicRaycaster)
|
||||
{
|
||||
// Let the active raycaster find intersections on its canvas
|
||||
activeGraphicRaycaster.RaycastPointer(leftData, m_RaycastResultCache);
|
||||
var raycast = FindFirstRaycast(m_RaycastResultCache);
|
||||
leftData.pointerCurrentRaycast = raycast;
|
||||
m_RaycastResultCache.Clear();
|
||||
|
||||
OVRRaycaster ovrRaycaster = raycast.module as OVRRaycaster;
|
||||
if (ovrRaycaster) // raycast may not actually contain a result
|
||||
{
|
||||
// The Unity UI system expects event data to have a screen position
|
||||
// so even though this raycast came from a world space ray we must get a screen
|
||||
// space position for the camera attached to this raycaster for compatability
|
||||
Vector2 position = ovrRaycaster.GetScreenPosition(raycast);
|
||||
|
||||
leftData.delta = position - leftData.position;
|
||||
leftData.position = position;
|
||||
}
|
||||
}
|
||||
|
||||
// copy the apropriate data into right and middle slots
|
||||
UnityEngine.EventSystems.PointerEventData rightData;
|
||||
GetPointerData(kMouseRightId, out rightData, true );
|
||||
CopyFromTo(leftData, rightData);
|
||||
rightData.button = UnityEngine.EventSystems.PointerEventData.InputButton.Right;
|
||||
|
||||
UnityEngine.EventSystems.PointerEventData middleData;
|
||||
GetPointerData(kMouseMiddleId, out middleData, true );
|
||||
CopyFromTo(leftData, middleData);
|
||||
middleData.button = UnityEngine.EventSystems.PointerEventData.InputButton.Middle;
|
||||
|
||||
m_MouseState.SetButtonState(UnityEngine.EventSystems.PointerEventData.InputButton.Left, StateForMouseButton(0), leftData);
|
||||
m_MouseState.SetButtonState(UnityEngine.EventSystems.PointerEventData.InputButton.Right, StateForMouseButton(1), rightData);
|
||||
m_MouseState.SetButtonState(UnityEngine.EventSystems.PointerEventData.InputButton.Middle, StateForMouseButton(2), middleData);
|
||||
return m_MouseState;
|
||||
mouseState.SetButtonState(UnityEngine.EventSystems.PointerEventData.InputButton.Left, GetGazeButtonState(activeController), leftData);
|
||||
mouseState.SetButtonState(UnityEngine.EventSystems.PointerEventData.InputButton.Right, UnityEngine.EventSystems.PointerEventData.FramePressState.NotChanged, rightData);
|
||||
mouseState.SetButtonState(UnityEngine.EventSystems.PointerEventData.InputButton.Middle, UnityEngine.EventSystems.PointerEventData.FramePressState.NotChanged, middleData);
|
||||
return mouseState;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -840,16 +798,27 @@ namespace ControllerSelection
|
||||
/// Get state of button corresponding to gaze pointer
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
protected UnityEngine.EventSystems.PointerEventData.FramePressState GetGazeButtonState()
|
||||
protected UnityEngine.EventSystems.PointerEventData.FramePressState GetGazeButtonState(OVRInput.Controller activeController)
|
||||
{
|
||||
var pressed = false;
|
||||
var released = false;
|
||||
|
||||
if (activeController != OVRInput.Controller.None) {
|
||||
pressed = OVRInput.GetDown(joyPadClickButton, activeController);
|
||||
released = OVRInput.GetUp(joyPadClickButton, activeController);
|
||||
if ((activeController & OVRInput.Controller.Touch) != OVRInput.Controller.None)
|
||||
{
|
||||
// Handle touch controllers
|
||||
pressed = OVRInput.GetDown(joyPadClickButton, activeController);
|
||||
released = OVRInput.GetUp(joyPadClickButton, activeController);
|
||||
}
|
||||
else if ((activeController & OVRInput.Controller.Hands) != OVRInput.Controller.None &&
|
||||
OVRPlugin.GetHandTrackingEnabled() && null != HandsManager.Instance && HandsManager.Instance.IsInitialized())
|
||||
{
|
||||
pressed = OVRInputHelpers.IsFingerStartPinching(activeController, pinchFinger);
|
||||
released = OVRInputHelpers.IsFingerStopPinching(activeController, pinchFinger);
|
||||
}
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
pressed = OVRInput.GetDown(joyPadClickButton);
|
||||
released = OVRInput.GetUp(joyPadClickButton);
|
||||
}
|
||||
@@ -860,16 +829,13 @@ namespace ControllerSelection
|
||||
#endif
|
||||
|
||||
if (pressed && released) {
|
||||
//Debug.Log ("pressed & released");
|
||||
return UnityEngine.EventSystems.PointerEventData.FramePressState.PressedAndReleased;
|
||||
}
|
||||
if (pressed) {
|
||||
//Debug.Log ("pressed");
|
||||
return UnityEngine.EventSystems.PointerEventData.FramePressState.Pressed;
|
||||
return UnityEngine.EventSystems.PointerEventData.FramePressState.Pressed;
|
||||
}
|
||||
if (released) {
|
||||
//Debug.Log ("released");
|
||||
return UnityEngine.EventSystems.PointerEventData.FramePressState.Released;
|
||||
return UnityEngine.EventSystems.PointerEventData.FramePressState.Released;
|
||||
}
|
||||
|
||||
return UnityEngine.EventSystems.PointerEventData.FramePressState.NotChanged;
|
||||
|
||||
@@ -23,7 +23,15 @@ using UnityEngine.SceneManagement;
|
||||
|
||||
namespace ControllerSelection {
|
||||
|
||||
public class OVRPointerVisualizer : MonoBehaviour {
|
||||
public class OVRPointerVisualizer : MonoBehaviour
|
||||
{
|
||||
public enum Hand
|
||||
{
|
||||
None,
|
||||
Left = OVRInputHelpers.HandFilter.Left,
|
||||
Right = OVRInputHelpers.HandFilter.Right
|
||||
}
|
||||
|
||||
[Header("(Optional) Tracking space")]
|
||||
[Tooltip("Tracking space of the OVRCameraRig.\nIf tracking space is not set, the scene will be searched.\nThis search is expensive.")]
|
||||
public Transform trackingSpace = null;
|
||||
@@ -38,36 +46,42 @@ namespace ControllerSelection {
|
||||
public float gazeDrawDistance = 3;
|
||||
[Tooltip("Show gaze pointer as ray pointer.")]
|
||||
public bool showRayPointer = true;
|
||||
[Tooltip("Left or Right hand / controller")]
|
||||
public Hand handType = Hand.None;
|
||||
|
||||
// Start ray draw distance
|
||||
private const float StartRayDrawDistance = 0.032f;
|
||||
|
||||
[HideInInspector]
|
||||
public OVRInput.Controller activeController = OVRInput.Controller.None;
|
||||
|
||||
void Awake() {
|
||||
if (trackingSpace == null) {
|
||||
void Awake()
|
||||
{
|
||||
if (trackingSpace == null)
|
||||
{
|
||||
Debug.LogWarning("OVRPointerVisualizer did not have a tracking space set. Looking for one");
|
||||
trackingSpace = OVRInputHelpers.FindTrackingSpace();
|
||||
}
|
||||
}
|
||||
|
||||
void OnEnable() {
|
||||
void OnEnable()
|
||||
{
|
||||
SceneManager.sceneLoaded += OnSceneLoaded;
|
||||
}
|
||||
|
||||
void OnDisable() {
|
||||
void OnDisable()
|
||||
{
|
||||
SceneManager.sceneLoaded -= OnSceneLoaded;
|
||||
}
|
||||
|
||||
void OnSceneLoaded(Scene scene, LoadSceneMode mode) {
|
||||
if (trackingSpace == null) {
|
||||
void OnSceneLoaded(Scene scene, LoadSceneMode mode)
|
||||
{
|
||||
if (trackingSpace == null)
|
||||
{
|
||||
Debug.LogWarning("OVRPointerVisualizer did not have a tracking space set. Looking for one");
|
||||
trackingSpace = OVRInputHelpers.FindTrackingSpace();
|
||||
}
|
||||
}
|
||||
|
||||
public void SetPointer(Ray ray) {
|
||||
void SetPointer(Ray ray)
|
||||
{
|
||||
float hitRayDrawDistance = rayDrawDistance;
|
||||
RaycastHit hit;
|
||||
if (Physics.Raycast(ray, out hit))
|
||||
@@ -75,40 +89,54 @@ namespace ControllerSelection {
|
||||
hitRayDrawDistance = hit.distance;
|
||||
}
|
||||
|
||||
if (linePointer != null) {
|
||||
if (linePointer != null)
|
||||
{
|
||||
linePointer.SetPosition(0, ray.origin + ray.direction * StartRayDrawDistance);
|
||||
linePointer.SetPosition(1, ray.origin + ray.direction * hitRayDrawDistance);
|
||||
}
|
||||
|
||||
if (gazePointer != null) {
|
||||
if (gazePointer != null)
|
||||
{
|
||||
gazePointer.position = ray.origin + ray.direction * (showRayPointer ? hitRayDrawDistance : gazeDrawDistance);
|
||||
}
|
||||
}
|
||||
|
||||
public void SetPointerVisibility() {
|
||||
if (trackingSpace != null && activeController != OVRInput.Controller.None) {
|
||||
if (linePointer != null) {
|
||||
void SetPointerVisibility(bool show)
|
||||
{
|
||||
if (show) {
|
||||
if (linePointer != null)
|
||||
{
|
||||
linePointer.enabled = true;
|
||||
}
|
||||
if (gazePointer != null) {
|
||||
if (gazePointer != null)
|
||||
{
|
||||
gazePointer.gameObject.SetActive(showRayPointer ? true : false);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (linePointer != null) {
|
||||
if (linePointer != null)
|
||||
{
|
||||
linePointer.enabled = false;
|
||||
}
|
||||
if (gazePointer != null) {
|
||||
if (gazePointer != null)
|
||||
{
|
||||
gazePointer.gameObject.SetActive(showRayPointer ? false : true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Update() {
|
||||
activeController = OVRInputHelpers.GetControllerForButton(OVRInput.Button.PrimaryIndexTrigger, activeController);
|
||||
Ray selectionRay = OVRInputHelpers.GetSelectionRay(activeController, trackingSpace);
|
||||
SetPointerVisibility();
|
||||
SetPointer(selectionRay);
|
||||
void Update()
|
||||
{
|
||||
var activeController = OVRInputHelpers.GetConnectedControllers((OVRInputHelpers.HandFilter)handType);
|
||||
|
||||
Ray selectionRay;
|
||||
bool gotRay = OVRInputHelpers.GetSelectionRay(activeController, trackingSpace, out selectionRay);
|
||||
SetPointerVisibility(gotRay && trackingSpace != null && activeController != OVRInput.Controller.None);
|
||||
|
||||
if (gotRay)
|
||||
{
|
||||
SetPointer(selectionRay);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -19,12 +19,25 @@ limitations under the License.
|
||||
|
||||
************************************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Security.Permissions;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
using UnityEngine.EventSystems;
|
||||
using UnityEngine.SceneManagement;
|
||||
|
||||
namespace ControllerSelection {
|
||||
public class OVRRawRaycaster : MonoBehaviour {
|
||||
namespace ControllerSelection
|
||||
{
|
||||
public class OVRRawRaycaster : MonoBehaviour, IBeginDragHandler, IEndDragHandler
|
||||
{
|
||||
public enum Hand
|
||||
{
|
||||
None,
|
||||
Left = OVRInputHelpers.HandFilter.Left,
|
||||
Right = OVRInputHelpers.HandFilter.Right
|
||||
}
|
||||
|
||||
[System.Serializable]
|
||||
public class HoverCallback : UnityEvent<Transform> { }
|
||||
[System.Serializable]
|
||||
@@ -34,7 +47,6 @@ namespace ControllerSelection {
|
||||
[Tooltip("Tracking space of the OVRCameraRig.\nIf tracking space is not set, the scene will be searched.\nThis search is expensive.")]
|
||||
public Transform trackingSpace = null;
|
||||
|
||||
|
||||
[Header("Selection")]
|
||||
[Tooltip("Primary selection button")]
|
||||
public OVRInput.Button primaryButton = OVRInput.Button.PrimaryIndexTrigger;
|
||||
@@ -42,6 +54,12 @@ namespace ControllerSelection {
|
||||
public OVRInput.Button secondaryButton = OVRInput.Button.PrimaryTouchpad;
|
||||
[Tooltip("Tertiary selection button")]
|
||||
public OVRInput.Button tertiaryButton = OVRInput.Button.One;
|
||||
[Tooltip("Primary pinch finger")]
|
||||
public OVRHand.HandFinger primaryPinchFinger = OVRHand.HandFinger.Index;
|
||||
[Tooltip("Secondary pinch finger")]
|
||||
public OVRHand.HandFinger secondaryPinchFinger = OVRHand.HandFinger.Middle;
|
||||
[Tooltip("Tertiary pinch finger")]
|
||||
public OVRHand.HandFinger tertiaryPinchFinger = OVRHand.HandFinger.Ring;
|
||||
[Tooltip("Layers to exclude from raycast")]
|
||||
public LayerMask excludeLayers;
|
||||
[Tooltip("Maximum raycast distance")]
|
||||
@@ -58,137 +76,338 @@ namespace ControllerSelection {
|
||||
public OVRRawRaycaster.SelectionCallback onTertiarySelect;
|
||||
|
||||
//protected Ray pointer;
|
||||
protected Transform lastHit = null;
|
||||
protected Transform triggerDown = null;
|
||||
protected Transform padDown = null;
|
||||
protected Transform tertiaryDown = null;
|
||||
protected Transform lastHitLeft = null;
|
||||
protected Transform lastHitRight = null;
|
||||
protected Transform lastButtonHitLeft = null;
|
||||
protected Transform lastButtonHitRight = null;
|
||||
protected Transform triggerButtonDownLeft = null;
|
||||
protected Transform triggerButtonDownRight = null;
|
||||
protected Transform padButtonDownLeft = null;
|
||||
protected Transform padButtonDownRight = null;
|
||||
protected Transform tertiaryButtonDownLeft = null;
|
||||
protected Transform tertiaryButtonDownRight = null;
|
||||
protected Transform triggerFingerDownLeft = null;
|
||||
protected Transform triggerFingerDownRight = null;
|
||||
protected Transform padFingerDownLeft = null;
|
||||
protected Transform padFingerDownRight = null;
|
||||
protected Transform tertiaryFingerDownLeft = null;
|
||||
protected Transform tertiaryFingerDownRight = null;
|
||||
|
||||
[HideInInspector]
|
||||
public OVRInput.Controller activeController = OVRInput.Controller.None;
|
||||
// Hover actions
|
||||
[Flags]
|
||||
enum HoverAction
|
||||
{
|
||||
None = 0,
|
||||
Exit = 1,
|
||||
Enter = 2,
|
||||
Stay = 4,
|
||||
Hover = 8
|
||||
}
|
||||
|
||||
void Awake() {
|
||||
if (trackingSpace == null) {
|
||||
// Map of transform to hover actions. We allocate this once & reuse to avoid memory allocations in Update().
|
||||
Dictionary<Transform, HoverAction> _actions = new Dictionary<Transform, HoverAction>(4);
|
||||
|
||||
// Whether we're dragging
|
||||
bool _isDragging = false;
|
||||
|
||||
void Awake()
|
||||
{
|
||||
if (trackingSpace == null)
|
||||
{
|
||||
Debug.LogWarning("OVRRawRaycaster did not have a tracking space set. Looking for one");
|
||||
trackingSpace = OVRInputHelpers.FindTrackingSpace();
|
||||
}
|
||||
}
|
||||
|
||||
void OnEnable() {
|
||||
void OnEnable()
|
||||
{
|
||||
SceneManager.sceneLoaded += OnSceneLoaded;
|
||||
}
|
||||
|
||||
void OnDisable() {
|
||||
void OnDisable()
|
||||
{
|
||||
SceneManager.sceneLoaded -= OnSceneLoaded;
|
||||
}
|
||||
|
||||
void OnSceneLoaded(Scene scene, LoadSceneMode mode) {
|
||||
if (trackingSpace == null) {
|
||||
void OnSceneLoaded(Scene scene, LoadSceneMode mode)
|
||||
{
|
||||
if (trackingSpace == null)
|
||||
{
|
||||
Debug.LogWarning("OVRRawRaycaster did not have a tracking space set. Looking for one");
|
||||
trackingSpace = OVRInputHelpers.FindTrackingSpace();
|
||||
}
|
||||
}
|
||||
|
||||
void Update() {
|
||||
activeController = OVRInputHelpers.GetControllerForButton(OVRInput.Button.PrimaryIndexTrigger, activeController);
|
||||
Ray pointer = OVRInputHelpers.GetSelectionRay(activeController, trackingSpace);
|
||||
public void OnBeginDrag(PointerEventData eventData)
|
||||
{
|
||||
_isDragging = true;
|
||||
}
|
||||
|
||||
RaycastHit hit; // Was anything hit?
|
||||
if (Physics.Raycast(pointer, out hit, raycastDistance, ~excludeLayers)) {
|
||||
if (lastHit != null && lastHit != hit.transform) {
|
||||
if (onHoverExit != null) {
|
||||
onHoverExit.Invoke(lastHit);
|
||||
}
|
||||
lastHit = null;
|
||||
}
|
||||
public void OnEndDrag(PointerEventData eventData)
|
||||
{
|
||||
_isDragging = false;
|
||||
}
|
||||
|
||||
if (lastHit == null) {
|
||||
if (onHoverEnter != null) {
|
||||
onHoverEnter.Invoke(hit.transform);
|
||||
}
|
||||
}
|
||||
|
||||
if (onHover != null) {
|
||||
onHover.Invoke(hit.transform);
|
||||
}
|
||||
|
||||
lastHit = hit.transform;
|
||||
|
||||
// Handle selection callbacks. An object is selected if the button selecting it was
|
||||
// pressed AND released while hovering over the object.
|
||||
if (activeController != OVRInput.Controller.None) {
|
||||
if (OVRInput.GetDown(tertiaryButton, activeController))
|
||||
static void ProcessHit(Dictionary<Transform, HoverAction> actions, bool isHit, Transform hit, ref Transform lastHit)
|
||||
{
|
||||
if (isHit)
|
||||
{
|
||||
if (lastHit != null)
|
||||
{
|
||||
if (lastHit != hit)
|
||||
{
|
||||
tertiaryDown = lastHit;
|
||||
// We move out of the last hit, so action is Exit
|
||||
actions[lastHit] |= HoverAction.Exit;
|
||||
lastHit = null;
|
||||
}
|
||||
else if (OVRInput.GetUp(tertiaryButton, activeController))
|
||||
else
|
||||
{
|
||||
if (tertiaryDown != null && tertiaryDown == lastHit)
|
||||
{
|
||||
if (onTertiarySelect != null)
|
||||
{
|
||||
onTertiarySelect.Invoke(tertiaryDown);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!OVRInput.Get(tertiaryButton, activeController))
|
||||
{
|
||||
tertiaryDown = null;
|
||||
// We have not moved from last hit, so action is Stay
|
||||
actions[lastHit] |= HoverAction.Stay;
|
||||
}
|
||||
}
|
||||
|
||||
if (OVRInput.GetDown(secondaryButton, activeController)) {
|
||||
padDown = lastHit;
|
||||
}
|
||||
else if (OVRInput.GetUp(secondaryButton, activeController)) {
|
||||
if (padDown != null && padDown == lastHit) {
|
||||
if (onSecondarySelect != null) {
|
||||
onSecondarySelect.Invoke(padDown);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!OVRInput.Get(secondaryButton, activeController)) {
|
||||
padDown = null;
|
||||
}
|
||||
if (lastHit == null)
|
||||
{
|
||||
// We moved into a new hit, so action is Enter
|
||||
actions[hit] |= HoverAction.Enter;
|
||||
}
|
||||
|
||||
if (OVRInput.GetDown(primaryButton, activeController)) {
|
||||
triggerDown = lastHit;
|
||||
}
|
||||
else if (OVRInput.GetUp(primaryButton, activeController)) {
|
||||
if (triggerDown != null && triggerDown == lastHit) {
|
||||
if (onPrimarySelect != null) {
|
||||
onPrimarySelect.Invoke(triggerDown);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!OVRInput.Get(primaryButton, activeController)) {
|
||||
triggerDown = null;
|
||||
}
|
||||
}
|
||||
#if UNITY_ANDROID && !UNITY_EDITOR
|
||||
// Gaze pointer fallback
|
||||
else {
|
||||
if (Input.GetMouseButtonDown(0) ) {
|
||||
triggerDown = lastHit;
|
||||
}
|
||||
else if (Input.GetMouseButtonUp(0) ) {
|
||||
if (triggerDown != null && triggerDown == lastHit) {
|
||||
if (onPrimarySelect != null) {
|
||||
onPrimarySelect.Invoke(triggerDown);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!Input.GetMouseButton(0)) {
|
||||
triggerDown = null;
|
||||
}
|
||||
// We hit something, so action is hover
|
||||
actions[hit] |= HoverAction.Hover;
|
||||
lastHit = hit;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
// Nothing was hit, handle exit callback
|
||||
else if (lastHit != null) {
|
||||
if (onHoverExit != null) {
|
||||
onHoverExit.Invoke(lastHit);
|
||||
}
|
||||
else if (lastHit != null)
|
||||
{
|
||||
// Nothing was hit, handle exit callback
|
||||
actions[lastHit] |= HoverAction.Exit;
|
||||
lastHit = null;
|
||||
}
|
||||
}
|
||||
|
||||
void ProcessButtonPresses(OVRInput.Controller activeController, bool isLeft, Transform lastHit,
|
||||
ref Transform triggerDown, ref Transform padDown, ref Transform tertiaryDown)
|
||||
{
|
||||
// Handle selection callbacks. An object is selected if the button selecting it was
|
||||
// pressed AND released while hovering over the object.
|
||||
if (isLeft && (activeController & OVRInput.Controller.LTouch) != OVRInput.Controller.LTouch ||
|
||||
!isLeft && (activeController & OVRInput.Controller.RTouch) != OVRInput.Controller.RTouch)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (OVRInput.GetDown(tertiaryButton, activeController))
|
||||
{
|
||||
tertiaryDown = lastHit;
|
||||
}
|
||||
else if (OVRInput.GetUp(tertiaryButton, activeController))
|
||||
{
|
||||
if (tertiaryDown != null && tertiaryDown == lastHit)
|
||||
{
|
||||
if (onTertiarySelect != null)
|
||||
{
|
||||
onTertiarySelect.Invoke(tertiaryDown);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!OVRInput.Get(tertiaryButton, activeController))
|
||||
{
|
||||
tertiaryDown = null;
|
||||
}
|
||||
|
||||
if (OVRInput.GetDown(secondaryButton, activeController))
|
||||
{
|
||||
padDown = lastHit;
|
||||
}
|
||||
else if (OVRInput.GetUp(secondaryButton, activeController))
|
||||
{
|
||||
if (padDown != null && padDown == lastHit)
|
||||
{
|
||||
if (onSecondarySelect != null)
|
||||
{
|
||||
onSecondarySelect.Invoke(padDown);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!OVRInput.Get(secondaryButton, activeController))
|
||||
{
|
||||
padDown = null;
|
||||
}
|
||||
|
||||
if (OVRInput.GetDown(primaryButton, activeController))
|
||||
{
|
||||
triggerDown = lastHit;
|
||||
}
|
||||
else if (OVRInput.GetUp(primaryButton, activeController))
|
||||
{
|
||||
if (triggerDown != null && triggerDown == lastHit)
|
||||
{
|
||||
if (onPrimarySelect != null)
|
||||
{
|
||||
onPrimarySelect.Invoke(triggerDown);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!OVRInput.Get(primaryButton, activeController))
|
||||
{
|
||||
triggerDown = null;
|
||||
}
|
||||
}
|
||||
|
||||
void ProcessHandPinch(OVRInput.Controller activeController, Transform lastHit,
|
||||
ref Transform triggerDown, ref Transform padDown, ref Transform tertiaryDown)
|
||||
{
|
||||
// Handle selection callbacks. An object is selected if the button selecting it was
|
||||
// pressed AND released while hovering over the object.
|
||||
if ((activeController & OVRInput.Controller.Hands) == OVRInput.Controller.None)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!OVRPlugin.GetHandTrackingEnabled() || !HandsManager.Instance || !HandsManager.Instance.IsInitialized())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (OVRInputHelpers.IsFingerStartPinching(activeController, tertiaryPinchFinger))
|
||||
{
|
||||
tertiaryDown = lastHit;
|
||||
}
|
||||
else if (OVRInputHelpers.IsFingerStopPinching(activeController, tertiaryPinchFinger))
|
||||
{
|
||||
if (tertiaryDown != null && tertiaryDown == lastHit)
|
||||
{
|
||||
if (onTertiarySelect != null)
|
||||
{
|
||||
onTertiarySelect.Invoke(tertiaryDown);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!OVRInputHelpers.IsFingerPinching(activeController, tertiaryPinchFinger))
|
||||
{
|
||||
tertiaryDown = null;
|
||||
}
|
||||
|
||||
if (OVRInputHelpers.IsFingerStartPinching(activeController, secondaryPinchFinger))
|
||||
{
|
||||
padDown = lastHit;
|
||||
}
|
||||
else if (OVRInputHelpers.IsFingerStopPinching(activeController, secondaryPinchFinger))
|
||||
{
|
||||
if (padDown != null && padDown == lastHit)
|
||||
{
|
||||
if (onSecondarySelect != null)
|
||||
{
|
||||
onSecondarySelect.Invoke(padDown);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!OVRInputHelpers.IsFingerPinching(activeController, secondaryPinchFinger))
|
||||
{
|
||||
padDown = null;
|
||||
}
|
||||
|
||||
if (OVRInputHelpers.IsFingerStartPinching(activeController, primaryPinchFinger))
|
||||
{
|
||||
triggerDown = lastHit;
|
||||
}
|
||||
else if (OVRInputHelpers.IsFingerStopPinching(activeController, primaryPinchFinger))
|
||||
{
|
||||
if (triggerDown != null && triggerDown == lastHit)
|
||||
{
|
||||
if (onPrimarySelect != null)
|
||||
{
|
||||
onPrimarySelect.Invoke(triggerDown);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!OVRInputHelpers.IsFingerPinching(activeController, primaryPinchFinger))
|
||||
{
|
||||
triggerDown = null;
|
||||
}
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
Ray pointerLeft;
|
||||
Ray pointerRight;
|
||||
|
||||
// Get left & right rays
|
||||
var activeControllerLeft = OVRInputHelpers.GetConnectedControllers(OVRInputHelpers.HandFilter.Left);
|
||||
var activeControllerRight = OVRInputHelpers.GetConnectedControllers(OVRInputHelpers.HandFilter.Right);
|
||||
|
||||
bool gotRayLeft = OVRInputHelpers.GetSelectionRay(activeControllerLeft, trackingSpace, out pointerLeft);
|
||||
bool gotRayRight = OVRInputHelpers.GetSelectionRay(activeControllerRight, trackingSpace, out pointerRight);
|
||||
|
||||
// Cast the rays
|
||||
RaycastHit hitLeft = default(RaycastHit);
|
||||
RaycastHit hitRight = default(RaycastHit);
|
||||
bool isHitLeft = gotRayLeft && Physics.Raycast(pointerLeft, out hitLeft, raycastDistance, ~excludeLayers);
|
||||
bool isHitRight = gotRayRight && Physics.Raycast(pointerRight, out hitRight, raycastDistance, ~excludeLayers);
|
||||
|
||||
// Process the hits
|
||||
_actions.Clear();
|
||||
|
||||
if (lastHitLeft != null)
|
||||
{
|
||||
_actions[lastHitLeft] = HoverAction.None;
|
||||
}
|
||||
|
||||
if (lastHitRight != null)
|
||||
{
|
||||
_actions[lastHitRight] = HoverAction.None;
|
||||
}
|
||||
|
||||
if (isHitLeft)
|
||||
{
|
||||
_actions[hitLeft.transform] = HoverAction.None;
|
||||
}
|
||||
|
||||
if (isHitRight)
|
||||
{
|
||||
_actions[hitRight.transform] = HoverAction.None;
|
||||
}
|
||||
|
||||
ProcessHit(_actions, isHitLeft, hitLeft.transform, ref lastHitLeft);
|
||||
ProcessHit(_actions, isHitRight, hitRight.transform, ref lastHitRight);
|
||||
|
||||
// Perform the actions
|
||||
foreach (KeyValuePair<Transform, HoverAction> kvp in _actions)
|
||||
{
|
||||
// Only perform enter / exit actions if we are not staying on existing transform
|
||||
// and if we're not both entering & exiting
|
||||
if ((kvp.Value & HoverAction.Stay) == HoverAction.None &&
|
||||
(kvp.Value & (HoverAction.Enter | HoverAction.Exit)) != (HoverAction.Enter | HoverAction.Exit))
|
||||
{
|
||||
if ((kvp.Value & HoverAction.Enter) != HoverAction.None && onHoverEnter != null)
|
||||
{
|
||||
onHoverEnter.Invoke(kvp.Key);
|
||||
}
|
||||
|
||||
if ((kvp.Value & HoverAction.Exit) != HoverAction.None && onHoverExit != null)
|
||||
{
|
||||
onHoverExit.Invoke(kvp.Key);
|
||||
}
|
||||
}
|
||||
|
||||
if ((kvp.Value & HoverAction.Hover) != HoverAction.None && onHover != null)
|
||||
{
|
||||
// Hovering over transform
|
||||
onHover.Invoke(kvp.Key);
|
||||
}
|
||||
}
|
||||
|
||||
if (isHitLeft && !_isDragging)
|
||||
{
|
||||
ProcessButtonPresses(activeControllerLeft, true, lastHitLeft, ref triggerButtonDownLeft, ref padButtonDownLeft, ref tertiaryButtonDownLeft);
|
||||
ProcessHandPinch(activeControllerLeft, lastHitLeft, ref triggerFingerDownLeft, ref padFingerDownLeft, ref tertiaryFingerDownLeft);
|
||||
}
|
||||
|
||||
if (isHitRight && !_isDragging)
|
||||
{
|
||||
ProcessButtonPresses(activeControllerRight, false, lastHitRight, ref triggerButtonDownRight, ref padButtonDownRight, ref tertiaryButtonDownRight);
|
||||
ProcessHandPinch(activeControllerRight, lastHitRight, ref triggerFingerDownRight, ref padFingerDownRight, ref tertiaryFingerDownRight);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user