using System.Collections.Generic; using System.Linq; using UnityEngine; namespace VIVE.OpenXR.Toolkits.RealisticHandInteraction { /// /// This class is designed to manage all Grabbers and Grabbables. /// public static class GrabManager { private static List m_GrabberRegistry = new List(); public static IReadOnlyList handGrabbers => m_GrabberRegistry.OfType().ToList().AsReadOnly(); private static List m_GrabbableRegistry = new List(); public static IReadOnlyList handGrabbables => m_GrabbableRegistry.OfType().ToList().AsReadOnly(); #region IGrabber /// /// Register the grabber in the grabber registry. /// /// The grabber to register. /// True if the grabber is successfully registered; otherwise, false. public static bool RegisterGrabber(IGrabber grabber) { if (!m_GrabberRegistry.Contains(grabber)) { m_GrabberRegistry.Add(grabber); } return m_GrabberRegistry.Contains(grabber); } /// /// Remove the grabber from the grabber registry. /// /// The grabber to remove. /// True if the grabber is successfully removed; otherwise, false. public static bool UnregisterGrabber(IGrabber grabber) { if (m_GrabberRegistry.Contains(grabber)) { m_GrabberRegistry.Remove(grabber); } return !m_GrabberRegistry.Contains(grabber); } /// /// Get the first hand grabber component found in the child hierarchy of the GameObject. /// /// The target whose child hierarchy to search. /// The output parameter to store the first hand grabber component found. /// True if a hand grabber component is found; otherwise, false. public static bool GetFirstHandGrabberFromChild(GameObject target, out HandGrabInteractor grabber) { grabber = TopDownFind(target.transform); return grabber != null; } /// /// Get the first hand grabber component found in the parent hierarchy of the GameObject. /// /// The target whose parent hierarchy to search. /// The output parameter to store the first hand grabber component found. /// True if a hand grabber component is found; otherwise, false. public static bool GetFirstHandGrabberFromParent(GameObject target, out HandGrabInteractor grabber) { grabber = BottomUpFind(target.transform); return grabber != null; } #endregion #region GrabInteractable /// /// Register the grabbable in the grabbable registry. /// /// The grabbable to register. /// True if the grabbable is successfully registered; otherwise, false. public static bool RegisterGrabbable(IGrabbable grabbable) { if (!m_GrabbableRegistry.Contains(grabbable)) { m_GrabbableRegistry.Add(grabbable); } return m_GrabbableRegistry.Contains(grabbable); } /// /// Remove the grabbable from the grabbable registry. /// /// The grabbable to remove. /// True if the grabbable is successfully removed; otherwise, false. public static bool UnregisterGrabbable(IGrabbable grabbable) { if (m_GrabbableRegistry.Contains(grabbable)) { m_GrabbableRegistry.Remove(grabbable); } return !m_GrabbableRegistry.Contains(grabbable); } /// /// Get the first hand grabbable component found in the child hierarchy of the GameObject. /// /// The target whose child hierarchy to search. /// The output parameter to store the first hand grabbable component found. /// True if a hand grabbable component is found; otherwise, false. public static bool GetFirstHandGrabbableFromChild(GameObject target, out HandGrabInteractable grabbable) { grabbable = TopDownFind(target.transform); return grabbable != null; } /// /// Get the first hand grabbable component found in the parent hierarchy of the GameObject. /// /// The target whose parent hierarchy to search. /// The output parameter to store the first hand grabbable component found. /// True if a hand grabbable component is found; otherwise, false. public static bool GetFirstHandGrabbableFromParent(GameObject target, out HandGrabInteractable grabbable) { grabbable = BottomUpFind(target.transform); return grabbable != null; } #endregion /// /// Find available components from self to children nodes. /// /// The transform of the gameobject. /// Value for available component. private static T TopDownFind(Transform transform) where T : Component { T component = transform.GetComponent(); if (component != null) { return component; } if (transform.childCount > 0) { for (int i = 0; i < transform.childCount; i++) { T childComponent = TopDownFind(transform.GetChild(i)); if (childComponent != null) { return childComponent; } } } return null; } /// /// Find available components from self to parent node. /// /// The transform of the gameobject. /// Value for available component. private static T BottomUpFind(Transform transform) where T : Component { T component = transform.GetComponent(); if (component != null) { return component; } if (transform.parent != null) { return BottomUpFind(transform.parent); } return null; } } }