//========= Copyright 2016-2023, HTC Corporation. All rights reserved. =========== using HTC.UnityPlugin.Utility; using HTC.UnityPlugin.Vive; using System.Collections.Generic; using UnityEngine; public class ControllerManagerSample : MonoBehaviour { public enum CustomModelActiveModeEnum { None, ActiveOnGripped, ToggleByDoubleGrip } public enum LaserPointerActiveModeEnum { None, ToggleByMenuClick, ActiveOnPadPressed, ToggleByTriggerClick } public enum CurvePointerActiveModeEnum { None, ActiveOnPadPressed, ToggleByPadDoubleClick } // after changing following public fields in playing mode, call UpdateStatus() to apply changes [Header("Mode Settings")] public bool hideRenderModelOnGrab = true; public CustomModelActiveModeEnum customModelActiveMode; public LaserPointerActiveModeEnum laserPointerActiveMode; public CurvePointerActiveModeEnum curvePointerActiveMode; [Header("Right controller")] public GameObject rightRenderModel; public GameObject rightCustomModel; public GameObject rightGrabber; public GameObject rightLaserPointer; public GameObject rightCurvePointer; [Header("Left controller")] public GameObject leftRenderModel; public GameObject leftCustomModel; public GameObject leftGrabber; public GameObject leftLaserPointer; public GameObject leftCurvePointer; private bool m_rightCustomModelActive; private bool m_rightLaserPointerActive; private bool m_rightCurvePointerActive; private bool m_leftCustomModelActive; private bool m_leftLaserPointerActive; private bool m_leftCurvePointerActive; private bool isLeftStickyGrab = false; private bool isRightStickyGrab = false; private HashSet rightGrabbingSet = new HashSet(); private HashSet leftGrabbingSet = new HashSet(); //properties public bool rightGrabberActive { get { return !m_rightLaserPointerActive && !m_rightCurvePointerActive && !m_rightCustomModelActive; } } public bool rightLaserPointerActive { get { return m_rightLaserPointerActive; } set { SetRightLaserPointerActive(value); } } public bool rightCurvePointerActive { get { return m_rightCurvePointerActive; } set { SetRightCurvePointerActive(value); } } public bool rightCustomModelActive { get { return m_rightCustomModelActive; } set { SetRightCustomModelActive(value); } } public bool leftGrabberActive { get { return !m_leftLaserPointerActive && !m_leftCurvePointerActive && !m_leftCustomModelActive; } } public bool leftLaserPointerActive { get { return m_leftLaserPointerActive; } set { SetLeftLaserPointerActive(value); } } public bool leftCurvePointerActive { get { return m_leftCurvePointerActive; } set { SetLeftCurvePointerActive(value); } } public bool leftCustomModelActive { get { return m_leftCustomModelActive; } set { SetLeftCustomModelActive(value); } } public bool SetRightLaserPointerActive(bool value) { if (ChangeProp.Set(ref m_rightLaserPointerActive, value)) { if (value) { m_rightCurvePointerActive = false; m_rightCustomModelActive = false; } return true; } return false; } public bool SetRightCurvePointerActive(bool value) { if (ChangeProp.Set(ref m_rightCurvePointerActive, value)) { if (value) { m_rightLaserPointerActive = false; m_rightCustomModelActive = false; } return true; } return false; } public bool SetRightCustomModelActive(bool value) { if (ChangeProp.Set(ref m_rightCustomModelActive, value)) { if (value) { m_rightLaserPointerActive = false; m_rightCurvePointerActive = false; } return true; } return false; } public bool SetLeftLaserPointerActive(bool value) { if (ChangeProp.Set(ref m_leftLaserPointerActive, value)) { if (value) { m_leftCurvePointerActive = false; m_leftCustomModelActive = false; } return true; } return false; } public bool SetLeftCurvePointerActive(bool value) { if (ChangeProp.Set(ref m_leftCurvePointerActive, value)) { if (value) { m_leftLaserPointerActive = false; m_leftCustomModelActive = false; } return true; } return false; } public bool SetLeftCustomModelActive(bool value) { if (ChangeProp.Set(ref m_leftCustomModelActive, value)) { if (value) { m_leftLaserPointerActive = false; m_leftCurvePointerActive = false; } return true; } return false; } public void ToggleRightLaserPointer() { rightLaserPointerActive = !rightLaserPointerActive; } public void ToggleRightCurvePointer() { rightCurvePointerActive = !rightCurvePointerActive; } public void ToggleRightCustomModel() { rightCustomModelActive = !rightCustomModelActive; } public void ToggleLeftLaserPointer() { leftLaserPointerActive = !leftLaserPointerActive; } public void ToggleLeftCurvePointer() { leftCurvePointerActive = !leftCurvePointerActive; } public void ToggleLeftCustomModel() { leftCustomModelActive = !leftCustomModelActive; } #if UNITY_EDITOR protected virtual void OnValidate() { if (Application.isPlaying) { UpdateActivity(); } } #endif protected virtual void Start() { m_rightLaserPointerActive = false; m_rightCustomModelActive = false; m_rightCurvePointerActive = false; m_leftLaserPointerActive = false; m_leftCustomModelActive = false; m_leftCurvePointerActive = false; UpdateActivity(); } protected virtual void LateUpdate() { var needUpdate = false; switch (laserPointerActiveMode) { case LaserPointerActiveModeEnum.None: needUpdate |= SetRightLaserPointerActive(false); needUpdate |= SetLeftLaserPointerActive(false); break; case LaserPointerActiveModeEnum.ToggleByMenuClick: if (ViveInput.GetPressUpEx(HandRole.RightHand, ControllerButton.Menu)) { ToggleRightLaserPointer(); needUpdate = true; } if (ViveInput.GetPressUpEx(HandRole.LeftHand, ControllerButton.Menu)) { ToggleLeftLaserPointer(); needUpdate = true; } break; case LaserPointerActiveModeEnum.ToggleByTriggerClick: if (ViveInput.GetPressUpEx(HandRole.RightHand, ControllerButton.Trigger)) { ToggleRightLaserPointer(); needUpdate = true; } if (ViveInput.GetPressUpEx(HandRole.LeftHand, ControllerButton.Trigger)) { ToggleLeftLaserPointer(); needUpdate = true; } break; case LaserPointerActiveModeEnum.ActiveOnPadPressed: needUpdate |= SetRightLaserPointerActive(ViveInput.GetPressEx(HandRole.RightHand, ControllerButton.Pad)); needUpdate |= SetLeftLaserPointerActive(ViveInput.GetPressEx(HandRole.LeftHand, ControllerButton.Pad)); break; } switch (curvePointerActiveMode) { case CurvePointerActiveModeEnum.None: needUpdate |= SetRightCurvePointerActive(false); needUpdate |= SetLeftCurvePointerActive(false); break; case CurvePointerActiveModeEnum.ActiveOnPadPressed: needUpdate |= SetRightCurvePointerActive(ViveInput.GetPressEx(HandRole.RightHand, ControllerButton.Pad)); needUpdate |= SetLeftCurvePointerActive(ViveInput.GetPressEx(HandRole.LeftHand, ControllerButton.Pad)); break; case CurvePointerActiveModeEnum.ToggleByPadDoubleClick: if (ViveInput.GetPressDownEx(HandRole.RightHand, ControllerButton.Pad) && ViveInput.ClickCountEx(HandRole.RightHand, ControllerButton.Pad) == 2) { ToggleRightCurvePointer(); needUpdate = true; } if (ViveInput.GetPressDownEx(HandRole.LeftHand, ControllerButton.Pad) && ViveInput.ClickCountEx(HandRole.LeftHand, ControllerButton.Pad) == 2) { ToggleLeftCurvePointer(); needUpdate = true; } break; } switch (customModelActiveMode) { case CustomModelActiveModeEnum.None: needUpdate |= ChangeProp.Set(ref m_rightCustomModelActive, false); needUpdate |= ChangeProp.Set(ref m_leftCustomModelActive, false); break; case CustomModelActiveModeEnum.ActiveOnGripped: needUpdate |= SetRightCustomModelActive(ViveInput.GetPressEx(HandRole.RightHand, ControllerButton.Grip)); needUpdate |= SetLeftCustomModelActive(ViveInput.GetPressEx(HandRole.LeftHand, ControllerButton.Grip)); break; case CustomModelActiveModeEnum.ToggleByDoubleGrip: if (ViveInput.GetPressDownEx(HandRole.RightHand, ControllerButton.Grip) && ViveInput.ClickCountEx(HandRole.RightHand, ControllerButton.Grip) == 2) { ToggleRightCustomModel(); needUpdate = true; } if (ViveInput.GetPressDownEx(HandRole.LeftHand, ControllerButton.Grip) && ViveInput.ClickCountEx(HandRole.LeftHand, ControllerButton.Grip) == 2) { ToggleLeftCustomModel(); needUpdate = true; } break; } if (needUpdate) { UpdateActivity(); } } public void OnGrabbed(BasicGrabbable grabbedObj) { ViveColliderButtonEventData viveEventData; if (!grabbedObj.grabbedEvent.TryGetViveButtonEventData(out viveEventData)) { return; } switch (viveEventData.viveRole.ToRole()) { case HandRole.RightHand: if (rightGrabbingSet.Add(grabbedObj.gameObject) && rightGrabbingSet.Count == 1) { UpdateActivity(); } break; case HandRole.LeftHand: if (leftGrabbingSet.Add(grabbedObj.gameObject) && leftGrabbingSet.Count == 1) { UpdateActivity(); } break; } } public void OnStickyGrabbed(StickyGrabbable grabbedObj) { ViveColliderButtonEventData viveEventData; if (!grabbedObj.grabbedEvent.TryGetViveButtonEventData(out viveEventData)) { return; } UpdateActivity(); switch (viveEventData.viveRole.ToRole()) { case HandRole.RightHand: if (rightGrabbingSet.Count > 0 || isRightStickyGrab) { return; } if (rightGrabbingSet.Add(grabbedObj.gameObject) && rightGrabbingSet.Count == 1) { UpdateActivity(); } break; case HandRole.LeftHand: if (leftGrabbingSet.Count > 0 || isLeftStickyGrab) { return; } if (leftGrabbingSet.Add(grabbedObj.gameObject) && leftGrabbingSet.Count == 1) { UpdateActivity(); } break; } } public void OnRelease(BasicGrabbable releasedObj) { ViveColliderButtonEventData viveEventData; if (!releasedObj.grabbedEvent.TryGetViveButtonEventData(out viveEventData)) { return; } UpdateActivity(); switch (viveEventData.viveRole.ToRole()) { case HandRole.RightHand: if (rightGrabbingSet.Remove(releasedObj.gameObject) && rightGrabbingSet.Count == 0) { UpdateActivity(); } break; case HandRole.LeftHand: if (leftGrabbingSet.Remove(releasedObj.gameObject) && leftGrabbingSet.Count == 0) { UpdateActivity(); } break; } } public void OnLetGo(BasicGrabbable releaseObj) { leftGrabbingSet.Clear(); rightGrabbingSet.Clear(); UpdateActivity(); } public void OnStickyLetGo(StickyGrabbable releaseObj) { leftGrabbingSet.Clear(); rightGrabbingSet.Clear(); UpdateActivity(); } public void OnStickyRelease(StickyGrabbable releasedObj) { UpdateActivity(); ViveColliderButtonEventData viveEventData; if (!releasedObj.grabbedEvent.TryGetViveButtonEventData(out viveEventData)) { return; } switch (viveEventData.viveRole.ToRole()) { case HandRole.RightHand: if (rightGrabbingSet.Remove(releasedObj.gameObject) && rightGrabbingSet.Count == 0) { isRightStickyGrab = false; UpdateActivity(); } break; case HandRole.LeftHand: if (leftGrabbingSet.Remove(releasedObj.gameObject) && leftGrabbingSet.Count == 0) { isLeftStickyGrab = false; UpdateActivity(); } break; } } public void OnDropped(BasicGrabbable grabbedObj) { OnRelease(grabbedObj); } public void OnDropped(StickyGrabbable grabbedObj) { OnStickyRelease(grabbedObj); } public void UpdateActivity() { //var rightRenderModelShouldActive = !m_rightCustomModelActive && (!hideRenderModelOnGrab || rightGrabbingSet.Count == 0); var rightRenderModelShouldActive = !hideRenderModelOnGrab || rightGrabbingSet.Count == 0; var rightCustomModelShouldActive = m_rightCustomModelActive; var rightLaserPointerShouldActive = m_rightLaserPointerActive; var rightCurvePointerShouldActive = m_rightCurvePointerActive; var rightGrabberShouldActive = !m_rightLaserPointerActive && !m_rightCustomModelActive && !m_rightCurvePointerActive; if (rightRenderModel != null && rightRenderModel.activeSelf != rightRenderModelShouldActive) { rightRenderModel.SetActive(rightRenderModelShouldActive); } if (rightCustomModel != null && rightCustomModel.activeSelf != rightCustomModelShouldActive) { rightCustomModel.SetActive(rightCustomModelShouldActive); } if (rightLaserPointer != null && rightLaserPointer.activeSelf != rightLaserPointerShouldActive) { rightLaserPointer.SetActive(rightLaserPointerShouldActive); } if (rightCurvePointer != null && rightCurvePointer.activeSelf != rightCurvePointerShouldActive) { rightCurvePointer.SetActive(rightCurvePointerShouldActive); } if (rightGrabber != null && rightGrabber.activeSelf != rightGrabberShouldActive) { rightGrabber.SetActive(rightGrabberShouldActive); } // var leftRenderModelShouldActive = !m_leftCustomModelActive && (!hideRenderModelOnGrab || leftGrabbingSet.Count == 0); var leftRenderModelShouldActive = !hideRenderModelOnGrab || leftGrabbingSet.Count == 0; var leftCustomModelShouldActive = m_leftCustomModelActive; var leftLaserPointerShouldActive = m_leftLaserPointerActive; var leftCurvePointerShouldActive = m_leftCurvePointerActive; var leftGrabberShouldActive = !m_leftLaserPointerActive && !m_leftCustomModelActive && !m_leftCurvePointerActive; if (leftRenderModel != null && leftRenderModel.activeSelf != leftRenderModelShouldActive) { leftRenderModel.SetActive(leftRenderModelShouldActive); } if (leftCustomModel != null && leftCustomModel.activeSelf != leftCustomModelShouldActive) { leftCustomModel.SetActive(leftCustomModelShouldActive); } if (leftLaserPointer != null && leftLaserPointer.activeSelf != leftLaserPointerShouldActive) { leftLaserPointer.SetActive(leftLaserPointerShouldActive); } if (leftCurvePointer != null && leftCurvePointer.activeSelf != leftCurvePointerShouldActive) { leftCurvePointer.SetActive(leftCurvePointerShouldActive); } if (leftGrabber != null && leftGrabber.activeSelf != leftGrabberShouldActive) { leftGrabber.SetActive(leftGrabberShouldActive); } } }