/* * Copyright (c) Meta Platforms, Inc. and affiliates. * All rights reserved. * * Licensed under the Oculus SDK License Agreement (the "License"); * you may not use the Oculus SDK except in compliance with the License, * which is provided at the time of installation or download, or which * otherwise accompanies this software in either electronic or hard copy form. * * You may obtain a copy of the License at * * https://developer.oculus.com/licenses/oculussdk/ * * Unless required by applicable law or agreed to in writing, the Oculus SDK * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using Oculus.Interaction.Input; using UnityEngine; using UnityEngine.Assertions; namespace Oculus.Interaction.PoseDetection { /// /// Test if hand joint is inside generic collider and updates its active state /// based on that test. We could trigger-based testing, but if the hand disappears /// during one frame, we will not get a trigger exit event (which means we require /// manual testing in Update anyway to accomodate that edge case). /// public class ColliderContainsHandJointActiveState : MonoBehaviour, IActiveState { [SerializeField, Interface(typeof(IHand))] private UnityEngine.Object _hand; private IHand Hand; [SerializeField] private Collider[] _entryColliders; [SerializeField] private Collider[] _exitColliders; [SerializeField] private HandJointId _jointToTest = HandJointId.HandWristRoot; public bool Active { get; private set; } private bool _active = false; protected virtual void Awake() { Hand = _hand as IHand; Active = false; } protected virtual void Start() { this.AssertField(Hand, nameof(Hand)); this.AssertCollectionField(_entryColliders, nameof(_entryColliders)); this.AssertCollectionField(_exitColliders, nameof(_exitColliders)); } protected virtual void Update() { if (Hand.GetJointPose(_jointToTest, out Pose jointPose)) { Active = JointPassesTests(jointPose); } else { Active = false; } } private bool JointPassesTests(Pose jointPose) { bool passesCollisionTest; if (_active) { passesCollisionTest = IsPointWithinColliders(jointPose.position, _exitColliders); } else { passesCollisionTest = IsPointWithinColliders(jointPose.position, _entryColliders); } _active = passesCollisionTest; return passesCollisionTest; } private bool IsPointWithinColliders(Vector3 point, Collider[] colliders) { foreach (var collider in colliders) { if (!Collisions.IsPointWithinCollider(point, collider)) { return false; } } return true; } #region Inject public void InjectAllColliderContainsHandJointActiveState(IHand hand, Collider[] entryColliders, Collider[] exitColliders, HandJointId jointToTest) { InjectHand(hand); InjectEntryColliders(entryColliders); InjectExitColliders(exitColliders); InjectJointToTest(jointToTest); } public void InjectHand(IHand hand) { _hand = hand as UnityEngine.Object; Hand = hand; } public void InjectEntryColliders(Collider[] entryColliders) { _entryColliders = entryColliders; } public void InjectExitColliders(Collider[] exitColliders) { _exitColliders = exitColliders; } public void InjectJointToTest(HandJointId jointToTest) { _jointToTest = jointToTest; } #endregion } }