using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; namespace Ximmerse.XR.InputSystems.GazeAndGestureInteraction { /// /// Interface : interaction with objects /// public interface I_InteractionState { bool IsEnabled { get; } void OnEnable(); void OnDisable(); void OnReticleEnter(); void Tick(); void OnReticleExit(); } class LockedGameObjectInfo { public Object lockedReference; public enum LockType { None = 0, /// /// Lock interaction target for slider UI /// SliderUI, /// /// Lock interaction target for 3d GameObject /// GameObject, } public LockType lockType = LockType.None; public float lockTime = 0; } /// /// Gaze and hand interaction system manages how XR user interacts world objects withe eye reticle and hand gesture. /// public partial class GazeAndHandInteractionSystem { /// /// UI objects interaction state. /// internal class UIObjectsInteractionState : I_InteractionState { public bool IsEnabled { get; private set; } Transform mainCam; LockedGameObjectInfo lockInfo = new LockedGameObjectInfo(); public void OnEnable() { } public void OnDisable() { } public void OnReticleEnter() { } public void Tick() { if (!mainCam) { mainCam = Camera.main.transform; } if (HandTracking.HandTrackingInfo.IsTracking == false) { //Clear lock info: if (lockInfo.lockType != LockedGameObjectInfo.LockType.None && (Time.realtimeSinceStartup - lockInfo.lockTime) >= 0.333f) { lockInfo.lockType = LockedGameObjectInfo.LockType.None; lockInfo.lockedReference = null; Debug.Log("Slider UI : Clear 1 : " + HandTracking.HandTrackingInfo.IsTracking); } return; } var isInteractingUI = GazeAndHandInteractionSystem.instance.eyeReticle.CurrentInteractingTarget.isUI; bool isclosepinch = HandTracking.HandTrackingInfo.NativeGestureType == (int)TouchlessA3D.GestureType.CLOSED_PINCH; bool isclosehand = HandTracking.HandTrackingInfo.gestureFistOpenHand == GestureType_Fist_OpenHand.Fist; bool isPinchGesture = false; if (isclosepinch || isclosehand) { isPinchGesture = true; } else { isPinchGesture = false; } //var isPinchGesture = HandTracking.HandTrackingInfo.NativeGestureType == (byte)(TouchlessA3D.GestureType.CLOSED_PINCH); //设置 lock target : slider UI: if (isInteractingUI && GazeAndHandInteractionSystem.instance.eyeReticle.CurrentInteractingTarget.target) { Debug.Log("miao0:" + GazeAndHandInteractionSystem.instance.eyeReticle.CurrentInteractingTarget.target.name+ GazeAndHandInteractionSystem.instance.eyeReticle.CurrentHoveringTarget.target.GetComponentInParent()); Slider sliderUI = GazeAndHandInteractionSystem.instance.eyeReticle.CurrentInteractingTarget.target.GetComponentInParent(); if (sliderUI && isPinchGesture) { lockInfo.lockType = LockedGameObjectInfo.LockType.SliderUI; lockInfo.lockedReference = sliderUI; lockInfo.lockTime = Time.realtimeSinceStartup;//记录lock time Debug.Log("Slider UI : Set"); } } //在 lock slider UI的情况下, 拖动进度条: if (this.lockInfo.lockType == LockedGameObjectInfo.LockType.SliderUI) { //放手或者丢失引用的时候, 解锁: if ((!lockInfo.lockedReference || !isPinchGesture) && (Time.realtimeSinceStartup - lockInfo.lockTime) >= 0.1f) { lockInfo.lockType = LockedGameObjectInfo.LockType.None; lockInfo.lockedReference = default(Object); Debug.Log("Slider UI : Clear 2"); } else { //捏合姿态下,移动slider: if (isPinchGesture) { MoveSliderUI(lockInfo.lockedReference as Slider); lockInfo.lockTime = Time.realtimeSinceStartup;//更新 lock time Debug.Log("Slider UI : Move !"); } } } } private void MoveSliderUI(Slider sliderUI) { //Debug.LogFormat("On UI state hover: {0}, {1}", sliderUI, isPinchGesture); { var delta = HandTracking.HandTrackingInfo.PalmDeltaPosition; var deltaVectorToHead = mainCam.InverseTransformVector(delta); float velocityX = Mathf.Abs(delta.x / Time.deltaTime); float velocityY = Mathf.Abs(delta.y / Time.deltaTime); if (sliderUI.direction== Slider.Direction.LeftToRight|| sliderUI.direction == Slider.Direction.RightToLeft) { if (velocityX >= 0.5f) { bool isRight = deltaVectorToHead.x > 0; float progressDelta = Mathf.Abs(delta.x) * (isRight ? 1 : -1) * 8;//加速8倍 sliderUI.normalizedValue = Mathf.Clamp01(sliderUI.normalizedValue + progressDelta); Debug.LogFormat("Change slider UI with delta: {0}, velX : {1}", progressDelta, velocityX); } } if (sliderUI.direction == Slider.Direction.BottomToTop || sliderUI.direction == Slider.Direction.TopToBottom) { if (velocityY >= 0.5f) { bool istop = deltaVectorToHead.y > 0; float progressDelta = Mathf.Abs(delta.y) * (istop ? 1 : -1) * 8;//加速8倍 sliderUI.normalizedValue = Mathf.Clamp01(sliderUI.normalizedValue + progressDelta); Debug.LogFormat("Change slider UI with delta: {0}, velX : {1}", progressDelta, velocityY); } } } } public void OnReticleExit() { } } } }