ButtonMouseCursorVisual.cs 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. using UnityEngine;
  2. using Rokid.UXR.Utility;
  3. using UnityEngine.EventSystems;
  4. namespace Rokid.UXR.Interaction
  5. {
  6. public class ButtonMouseCursorVisual : MonoBehaviour
  7. {
  8. [SerializeField]
  9. private RayInteractor rayInteractor;
  10. [SerializeField]
  11. private ButtonMouseSelector buttonMouseSelector;
  12. [Tooltip("光标Size")]
  13. [SerializeField]
  14. private float cursorAngularSize = 100;
  15. [SerializeField]
  16. private Transform focusCursor;
  17. [SerializeField]
  18. private Transform pressCursor;
  19. private Material CursorMat;
  20. private bool IsPlayAnim;
  21. private float CurrentAnimTime;
  22. private float CurrentScale = 1.0f;
  23. private float AnimMinScale = 1f;
  24. private float AnimMaxScale = 2.2f;
  25. private float AnimMiddleTime = 0.2f;
  26. private float AnimTotalTime = 0.4f;
  27. private void Start()
  28. {
  29. rayInteractor.WhenPostprocessed += UpdateVisual;
  30. rayInteractor.WhenStateChanged += UpdateVisualState;
  31. ButtonMouseEventInput.OnEnterLongPressState += EnterLongPressState;
  32. ButtonMouseEventInput.OnExitLongPressState += ExitLongPressState;
  33. ButtonMouseEventInput.OnReHoverState += OnReHoverState;
  34. CursorMat = GetComponentInChildren<SpriteRenderer>().material;
  35. IsPlayAnim = false;
  36. }
  37. private void OnDestroy()
  38. {
  39. rayInteractor.WhenPostprocessed -= UpdateVisual;
  40. rayInteractor.WhenStateChanged -= UpdateVisualState;
  41. ButtonMouseEventInput.OnEnterLongPressState -= EnterLongPressState;
  42. ButtonMouseEventInput.OnExitLongPressState -= ExitLongPressState;
  43. ButtonMouseEventInput.OnReHoverState -= OnReHoverState;
  44. }
  45. private void OnEnable()
  46. {
  47. RKPointerLisener.OnGraphicPointerEnter += OnPointerEnter;
  48. RKPointerLisener.OnGraphicPointerExit += OnPointerExit;
  49. RKPointerLisener.OnGraphicPointerHover += OnPointerHover;
  50. IsPlayAnim = true;
  51. }
  52. private void OnDisable()
  53. {
  54. RKPointerLisener.OnGraphicPointerEnter -= OnPointerEnter;
  55. RKPointerLisener.OnGraphicPointerExit -= OnPointerExit;
  56. RKPointerLisener.OnGraphicPointerHover -= OnPointerHover;
  57. IsPlayAnim = false;
  58. IsInHover = false;
  59. }
  60. private void Update()
  61. {
  62. if (IsPlayAnim)
  63. {
  64. if (CurrentAnimTime <= AnimMiddleTime)
  65. {
  66. CurrentScale = AnimMinScale + (CurrentAnimTime / AnimMiddleTime) * (AnimMaxScale - AnimMinScale);
  67. CurrentScale = Mathf.Clamp(CurrentScale, AnimMinScale, AnimMaxScale);
  68. CurrentAnimTime += Time.deltaTime;
  69. CursorMat?.SetFloat("_BlurSize", CurrentScale * 1.5f);
  70. }
  71. else if (CurrentAnimTime <= AnimTotalTime)
  72. {
  73. CurrentScale = AnimMaxScale - ((CurrentAnimTime - AnimMiddleTime) / AnimMiddleTime) * (AnimMaxScale - AnimMinScale);
  74. CurrentScale = Mathf.Clamp(CurrentScale, AnimMinScale, AnimMaxScale);
  75. CurrentAnimTime += Time.deltaTime;
  76. CursorMat?.SetFloat("_BlurSize", CurrentScale * 1.5f);
  77. }
  78. else
  79. {
  80. IsPlayAnim = false;
  81. CurrentScale = 1.0f;
  82. CurrentAnimTime = 0.0f;
  83. CursorMat?.SetFloat("_BlurSize", 0);
  84. }
  85. transform.localScale = ComputeScaleWithAngularScale(rayInteractor.End) * CurrentScale;
  86. }
  87. }
  88. private Vector3 ComputeScaleWithAngularScale(Vector3 targetPoint)
  89. {
  90. float cursorDistance = Vector3.Distance(MainCameraCache.mainCamera.transform.position, targetPoint);
  91. float desiredScale = Utils.ScaleFromAngularSizeAndDistance(cursorAngularSize, cursorDistance);
  92. return Vector3.one * desiredScale;
  93. }
  94. private void EnterLongPressState()
  95. {
  96. focusCursor.gameObject.SetActive(false);
  97. pressCursor.gameObject.SetActive(false);
  98. buttonMouseSelector.setClickEnable(false);
  99. // 进入锁定状态,取消选中状态
  100. rayInteractor.CancelWhenEnterLock();
  101. }
  102. private void OnReHoverState()
  103. {
  104. // 取消选择状态后,按键重新获取焦点
  105. rayInteractor.ReHoverWhenLock();
  106. }
  107. private void ExitLongPressState()
  108. {
  109. buttonMouseSelector.setClickEnable(true);
  110. }
  111. private void UpdateVisual()
  112. {
  113. if (rayInteractor.State == InteractorState.Disabled)
  114. {
  115. gameObject.SetActive(false);
  116. return;
  117. }
  118. if (ButtonMouseEventInput.Instance.IsInLockState())
  119. {
  120. return;
  121. }
  122. gameObject.SetActive(true);
  123. Vector3 EndPosition;
  124. Vector3 EndNormal;
  125. if (IsInHover && HoverNormal != Vector3.zero && HoverPosition != Vector3.zero)
  126. {
  127. EndPosition = HoverPosition;
  128. EndNormal = HoverNormal;
  129. }
  130. else
  131. {
  132. EndPosition = rayInteractor.End;
  133. EndNormal = rayInteractor.Forward;
  134. }
  135. this.transform.position = EndPosition - EndNormal * 0.001f;
  136. if (rayInteractor.State == InteractorState.Select || rayInteractor.State == InteractorState.Hover)
  137. {
  138. if (rayInteractor.CollisionInfo != null)
  139. {
  140. Quaternion rotation = Quaternion.FromToRotation(Vector3.forward, -EndNormal);
  141. this.transform.eulerAngles = new Vector3(rotation.eulerAngles.x, rotation.eulerAngles.y, 0);
  142. }
  143. else
  144. {
  145. this.transform.rotation = Quaternion.LookRotation(EndPosition - MainCameraCache.mainCamera.transform.position, Vector3.up);
  146. }
  147. if (!IsPlayAnim)
  148. {
  149. this.transform.localScale = ComputeScaleWithAngularScale(EndPosition);
  150. }
  151. }
  152. else if (rayInteractor.State == InteractorState.Normal && MainCameraCache.mainCamera != null)
  153. {
  154. this.transform.rotation = Quaternion.LookRotation(EndPosition - MainCameraCache.mainCamera.transform.position, Vector3.up);
  155. if (!IsPlayAnim)
  156. {
  157. this.transform.localScale = ComputeScaleWithAngularScale(EndPosition);
  158. }
  159. }
  160. bool press = rayInteractor.State == InteractorState.Select;
  161. focusCursor.gameObject.SetActive(!press);
  162. pressCursor.gameObject.SetActive(press);
  163. }
  164. private void UpdateVisualState(InteractorStateChangeArgs args) => UpdateVisual();
  165. #region ForCursorHoverPose
  166. private bool IsInHover;
  167. private Vector3 HoverPosition;
  168. private Vector3 HoverNormal;
  169. private void OnPointerEnter(PointerEventData eventData)
  170. {
  171. if (eventData.pointerCurrentRaycast.gameObject != null)
  172. {
  173. IsInHover = true;
  174. HoverPosition = Vector3.zero;
  175. HoverNormal = Vector3.zero;
  176. }
  177. }
  178. private void OnPointerExit(PointerEventData eventData)
  179. {
  180. IsInHover = false;
  181. HoverPosition = Vector3.zero;
  182. HoverNormal = Vector3.zero;
  183. }
  184. private void OnPointerHover(PointerEventData eventData)
  185. {
  186. HoverPosition = eventData.pointerCurrentRaycast.worldPosition;
  187. HoverNormal = eventData.pointerCurrentRaycast.worldNormal;
  188. }
  189. #endregion
  190. }
  191. }