InteractorButton.cs 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. using System.Collections.Generic;
  2. using UnityEngine;
  3. using UnityEngine.Events;
  4. using UnityEngine.EventSystems;
  5. namespace Rokid.UXR.Interaction
  6. {
  7. public class InteractorButton : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler, IPointerDownHandler, IPointerUpHandler, IPointerClickHandler
  8. {
  9. public enum TouchState
  10. {
  11. Normal = 1,//正常状态
  12. Hover = 2,//手指到达开始按钮浮起的位置
  13. Touch = 4,//手指触碰到浮起的
  14. PressDown = 8,//按下,触碰到按钮地板
  15. }
  16. public TouchState touchState
  17. {
  18. get;
  19. private set;
  20. } = TouchState.Normal;
  21. /// <summary>
  22. /// 默认抬起的高度,米
  23. /// </summary>
  24. public float normalOffsetAlongNormal = 0.00f;
  25. /// <summary>
  26. /// 被hover时自动抬起的高度,米
  27. /// </summary>
  28. public float hoverOffsetAlongNormal = 0.006f;
  29. /// <summary>
  30. /// 开始抬起时手指高度,米
  31. /// </summary>
  32. public float beginHoverOffsetAlongNormal = 0.08f;
  33. /// <summary>
  34. /// 抬起的UI图片
  35. /// </summary>
  36. public Transform buttonUp;
  37. public UnityEvent<TouchState> onStateChanged;
  38. public UnityEvent<PointerEventData> onPointerDown = new UnityEvent<PointerEventData>();
  39. public UnityEvent<PointerEventData> onPointerUp = new UnityEvent<PointerEventData>();
  40. public UnityEvent<PointerEventData> onPointerClick = new UnityEvent<PointerEventData>();
  41. public UnityEvent<PointerEventData> onPointerEnter = new UnityEvent<PointerEventData>();
  42. public UnityEvent<PointerEventData> onPointerExit = new UnityEvent<PointerEventData>();
  43. public HashSet<PokeInteractor> _pokeInteractors = new HashSet<PokeInteractor>();
  44. private PokeInteractable _pokeInteractable;
  45. private bool hoverEnter = false;
  46. private bool pointerDown = false;
  47. private PokeInteractable pokeInteractable
  48. {
  49. get
  50. {
  51. if (_pokeInteractable == null)
  52. {
  53. _pokeInteractable = transform.GetComponentInParent<PokeInteractable>();
  54. if (_pokeInteractable == null)
  55. {
  56. enabled = false;
  57. }
  58. }
  59. return _pokeInteractable;
  60. }
  61. }
  62. void Awake()
  63. {
  64. if (!buttonUp)
  65. {
  66. enabled = false;
  67. }
  68. buttonUp.position = transform.position - transform.forward * normalOffsetAlongNormal;
  69. }
  70. private void OnEnable()
  71. {
  72. hoverEnter = false;
  73. _pokeInteractors.Clear();
  74. _pokeInteractors.UnionWith(pokeInteractable.Interactors);
  75. pokeInteractable.WhenInteractorAdded.Action += HandleInteractorAdded;
  76. pokeInteractable.WhenInteractorRemoved.Action += HandleInteractorRemoved;
  77. }
  78. private void OnDisable()
  79. {
  80. OnPointerExit(null);
  81. pokeInteractable.WhenInteractorAdded.Action -= HandleInteractorAdded;
  82. pokeInteractable.WhenInteractorRemoved.Action -= HandleInteractorRemoved;
  83. _pokeInteractors.Clear();
  84. }
  85. private void HandleInteractorAdded(PokeInteractor pokeInteractor)
  86. {
  87. _pokeInteractors.Add(pokeInteractor);
  88. }
  89. private void HandleInteractorRemoved(PokeInteractor pokeInteractor)
  90. {
  91. pokeInteractor.InteractorButtonUpPosition = Vector3.zero;
  92. _pokeInteractors.Remove(pokeInteractor);
  93. }
  94. private void Update()
  95. {
  96. if (hoverEnter)
  97. {
  98. if (_pokeInteractors.Count > 0)
  99. {
  100. float closestDistance = int.MaxValue;
  101. foreach (var v in _pokeInteractors)
  102. {
  103. float dis = Vector3.Dot(transform.position - v.transform.position, transform.forward);
  104. closestDistance = closestDistance < dis ? closestDistance : dis;
  105. }
  106. closestDistance = closestDistance < 0 ? 0 : closestDistance;
  107. if (closestDistance > beginHoverOffsetAlongNormal)
  108. {
  109. buttonUp.position = Vector3.Lerp(buttonUp.position, transform.position - transform.forward * normalOffsetAlongNormal, 20 * Time.deltaTime);
  110. }
  111. else if (closestDistance > hoverOffsetAlongNormal)
  112. {
  113. buttonUp.position = Vector3.Lerp(buttonUp.position, transform.position - transform.forward * hoverOffsetAlongNormal, 30 * Time.deltaTime);
  114. }
  115. else
  116. {
  117. buttonUp.position = transform.position -
  118. transform.forward * closestDistance;
  119. }
  120. foreach (var item in _pokeInteractors)
  121. {
  122. item.InteractorButtonUpPosition = buttonUp.position;
  123. }
  124. ChangeState(closestDistance);
  125. }
  126. }
  127. }
  128. void ChangeState(float closestDistance)
  129. {
  130. TouchState curState;
  131. if (closestDistance > beginHoverOffsetAlongNormal)
  132. {
  133. curState = TouchState.Normal;
  134. }
  135. else if (closestDistance > hoverOffsetAlongNormal)
  136. {
  137. curState = TouchState.Hover;
  138. }
  139. else if (closestDistance > 0.001)
  140. {
  141. curState = TouchState.Touch;
  142. }
  143. else
  144. {
  145. curState = TouchState.PressDown;
  146. }
  147. if (curState != touchState)
  148. {
  149. touchState = curState;
  150. onStateChanged?.Invoke(curState);
  151. }
  152. }
  153. public void OnPointerDown(PointerEventData eventData)
  154. {
  155. RKLog.Info($"====InteractorButton==== P {eventData?.currentInputModule?.GetType().Name} pointerDown");
  156. if (_pokeInteractors.Count == 0)
  157. {
  158. buttonUp.position = transform.position;
  159. }
  160. onPointerDown?.Invoke(eventData);
  161. pointerDown = true;
  162. }
  163. public void OnPointerUp(PointerEventData eventData)
  164. {
  165. RKLog.Info($"====InteractorButton==== P {eventData?.currentInputModule?.GetType().Name} pointerUp");
  166. if (_pokeInteractors.Count == 0)
  167. {
  168. buttonUp.position = transform.position -
  169. transform.forward * normalOffsetAlongNormal;
  170. }
  171. onPointerUp?.Invoke(eventData);
  172. pointerDown = false;
  173. }
  174. public void OnPointerEnter(PointerEventData eventData)
  175. {
  176. RKLog.Info($"====InteractorButton==== E {eventData?.currentInputModule?.GetType().Name} pointerEnter");
  177. hoverEnter = true;
  178. onPointerEnter?.Invoke(eventData);
  179. }
  180. public void OnPointerExit(PointerEventData eventData)
  181. {
  182. RKLog.Info($"====InteractorButton==== E {eventData?.currentInputModule?.GetType().Name} pointerExit");
  183. hoverEnter = false;
  184. buttonUp.position = transform.position -
  185. transform.forward * normalOffsetAlongNormal;
  186. if (touchState != TouchState.Normal)
  187. {
  188. touchState = TouchState.Normal;
  189. onStateChanged?.Invoke(touchState);
  190. }
  191. foreach (var item in _pokeInteractors)
  192. {
  193. item.InteractorButtonUpPosition = Vector3.zero;
  194. }
  195. onPointerExit?.Invoke(eventData);
  196. pointerDown = false;
  197. }
  198. public void OnPointerClick(PointerEventData eventData)
  199. {
  200. onPointerClick?.Invoke(eventData);
  201. }
  202. }
  203. }