using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;
namespace Rokid.UXR.Interaction
{
public class InteractorButton : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler, IPointerDownHandler, IPointerUpHandler, IPointerClickHandler
{
public enum TouchState
{
Normal = 1,//正常状态
Hover = 2,//手指到达开始按钮浮起的位置
Touch = 4,//手指触碰到浮起的
PressDown = 8,//按下,触碰到按钮地板
}
public TouchState touchState
{
get;
private set;
} = TouchState.Normal;
///
/// 默认抬起的高度,米
///
public float normalOffsetAlongNormal = 0.00f;
///
/// 被hover时自动抬起的高度,米
///
public float hoverOffsetAlongNormal = 0.006f;
///
/// 开始抬起时手指高度,米
///
public float beginHoverOffsetAlongNormal = 0.08f;
///
/// 抬起的UI图片
///
public Transform buttonUp;
public UnityEvent onStateChanged;
public UnityEvent onPointerDown = new UnityEvent();
public UnityEvent onPointerUp = new UnityEvent();
public UnityEvent onPointerClick = new UnityEvent();
public UnityEvent onPointerEnter = new UnityEvent();
public UnityEvent onPointerExit = new UnityEvent();
public HashSet _pokeInteractors = new HashSet();
private PokeInteractable _pokeInteractable;
private bool hoverEnter = false;
private bool pointerDown = false;
private PokeInteractable pokeInteractable
{
get
{
if (_pokeInteractable == null)
{
_pokeInteractable = transform.GetComponentInParent();
if (_pokeInteractable == null)
{
enabled = false;
}
}
return _pokeInteractable;
}
}
void Awake()
{
if (!buttonUp)
{
enabled = false;
}
buttonUp.position = transform.position - transform.forward * normalOffsetAlongNormal;
}
private void OnEnable()
{
hoverEnter = false;
_pokeInteractors.Clear();
_pokeInteractors.UnionWith(pokeInteractable.Interactors);
pokeInteractable.WhenInteractorAdded.Action += HandleInteractorAdded;
pokeInteractable.WhenInteractorRemoved.Action += HandleInteractorRemoved;
}
private void OnDisable()
{
OnPointerExit(null);
pokeInteractable.WhenInteractorAdded.Action -= HandleInteractorAdded;
pokeInteractable.WhenInteractorRemoved.Action -= HandleInteractorRemoved;
_pokeInteractors.Clear();
}
private void HandleInteractorAdded(PokeInteractor pokeInteractor)
{
_pokeInteractors.Add(pokeInteractor);
}
private void HandleInteractorRemoved(PokeInteractor pokeInteractor)
{
pokeInteractor.InteractorButtonUpPosition = Vector3.zero;
_pokeInteractors.Remove(pokeInteractor);
}
private void Update()
{
if (hoverEnter)
{
if (_pokeInteractors.Count > 0)
{
float closestDistance = int.MaxValue;
foreach (var v in _pokeInteractors)
{
float dis = Vector3.Dot(transform.position - v.transform.position, transform.forward);
closestDistance = closestDistance < dis ? closestDistance : dis;
}
closestDistance = closestDistance < 0 ? 0 : closestDistance;
if (closestDistance > beginHoverOffsetAlongNormal)
{
buttonUp.position = Vector3.Lerp(buttonUp.position, transform.position - transform.forward * normalOffsetAlongNormal, 20 * Time.deltaTime);
}
else if (closestDistance > hoverOffsetAlongNormal)
{
buttonUp.position = Vector3.Lerp(buttonUp.position, transform.position - transform.forward * hoverOffsetAlongNormal, 30 * Time.deltaTime);
}
else
{
buttonUp.position = transform.position -
transform.forward * closestDistance;
}
foreach (var item in _pokeInteractors)
{
item.InteractorButtonUpPosition = buttonUp.position;
}
ChangeState(closestDistance);
}
}
}
void ChangeState(float closestDistance)
{
TouchState curState;
if (closestDistance > beginHoverOffsetAlongNormal)
{
curState = TouchState.Normal;
}
else if (closestDistance > hoverOffsetAlongNormal)
{
curState = TouchState.Hover;
}
else if (closestDistance > 0.001)
{
curState = TouchState.Touch;
}
else
{
curState = TouchState.PressDown;
}
if (curState != touchState)
{
touchState = curState;
onStateChanged?.Invoke(curState);
}
}
public void OnPointerDown(PointerEventData eventData)
{
RKLog.Info($"====InteractorButton==== P {eventData?.currentInputModule?.GetType().Name} pointerDown");
if (_pokeInteractors.Count == 0)
{
buttonUp.position = transform.position;
}
onPointerDown?.Invoke(eventData);
pointerDown = true;
}
public void OnPointerUp(PointerEventData eventData)
{
RKLog.Info($"====InteractorButton==== P {eventData?.currentInputModule?.GetType().Name} pointerUp");
if (_pokeInteractors.Count == 0)
{
buttonUp.position = transform.position -
transform.forward * normalOffsetAlongNormal;
}
onPointerUp?.Invoke(eventData);
pointerDown = false;
}
public void OnPointerEnter(PointerEventData eventData)
{
RKLog.Info($"====InteractorButton==== E {eventData?.currentInputModule?.GetType().Name} pointerEnter");
hoverEnter = true;
onPointerEnter?.Invoke(eventData);
}
public void OnPointerExit(PointerEventData eventData)
{
RKLog.Info($"====InteractorButton==== E {eventData?.currentInputModule?.GetType().Name} pointerExit");
hoverEnter = false;
buttonUp.position = transform.position -
transform.forward * normalOffsetAlongNormal;
if (touchState != TouchState.Normal)
{
touchState = TouchState.Normal;
onStateChanged?.Invoke(touchState);
}
foreach (var item in _pokeInteractors)
{
item.InteractorButtonUpPosition = Vector3.zero;
}
onPointerExit?.Invoke(eventData);
pointerDown = false;
}
public void OnPointerClick(PointerEventData eventData)
{
onPointerClick?.Invoke(eventData);
}
}
}