|  | using System; | 
        
          |  | using UnityEngine.Events; | 
        
          |  | using UnityEngine.EventSystems; | 
        
          |  |  | 
        
          |  | namespace UnityEngine.UI | 
        
          |  | { | 
        
          |  | public class RepeatButton : Selectable, IPointerDownHandler, IPointerUpHandler, IPointerExitHandler, IPointerClickHandler | 
        
          |  | { | 
        
          |  | [SerializeField] private float interval = 0.1f; | 
        
          |  | [SerializeField] private float delay = 1.0f; | 
        
          |  | [SerializeField] private UnityEvent onInvoke = new UnityEvent(); | 
        
          |  |  | 
        
          |  | private bool isPointDown = false; | 
        
          |  | private float lastInvokeTime; | 
        
          |  |  | 
        
          |  | private float delayTime = 0f; | 
        
          |  |  | 
        
          |  | public UnityEvent OnInvoke => onInvoke; | 
        
          |  |  | 
        
          |  | // Use this for initialization | 
        
          |  | protected override void Start() | 
        
          |  | { | 
        
          |  | base.Start(); | 
        
          |  | delayTime = delay; | 
        
          |  | } | 
        
          |  |  | 
        
          |  | protected override void OnDisable() | 
        
          |  | { | 
        
          |  | base.OnDisable(); | 
        
          |  |  | 
        
          |  | isPointDown = false; | 
        
          |  | delayTime = delay; | 
        
          |  | } | 
        
          |  |  | 
        
          |  | void Update() | 
        
          |  | { | 
        
          |  | if (!IsInteractable() && isPointDown) | 
        
          |  | { | 
        
          |  | isPointDown = false; | 
        
          |  | delayTime = delay; | 
        
          |  |  | 
        
          |  | return; | 
        
          |  | } | 
        
          |  |  | 
        
          |  | if (isPointDown) | 
        
          |  | { | 
        
          |  | if ((delayTime -= Time.deltaTime) > 0f) | 
        
          |  | { | 
        
          |  | return; | 
        
          |  | } | 
        
          |  |  | 
        
          |  | if (Time.time - lastInvokeTime > interval) | 
        
          |  | { | 
        
          |  | Invoke(); | 
        
          |  | lastInvokeTime = Time.time; | 
        
          |  | } | 
        
          |  | } | 
        
          |  | } | 
        
          |  |  | 
        
          |  | private void Invoke() | 
        
          |  | { | 
        
          |  | if (!IsActive() || !IsInteractable()) | 
        
          |  | return; | 
        
          |  |  | 
        
          |  | onInvoke.Invoke(); | 
        
          |  | } | 
        
          |  |  | 
        
          |  | public virtual void OnPointerClick(PointerEventData eventData) | 
        
          |  | { | 
        
          |  | if (eventData.button != PointerEventData.InputButton.Left) | 
        
          |  | return; | 
        
          |  |  | 
        
          |  | Invoke(); | 
        
          |  | } | 
        
          |  |  | 
        
          |  | public override void OnPointerDown(PointerEventData eventData) | 
        
          |  | { | 
        
          |  | base.OnPointerExit(eventData); | 
        
          |  |  | 
        
          |  | isPointDown = true; | 
        
          |  | delayTime = delay; | 
        
          |  |  | 
        
          |  | if (IsInteractable()) | 
        
          |  | { | 
        
          |  | DoStateTransition(SelectionState.Pressed, false); | 
        
          |  | } | 
        
          |  | } | 
        
          |  |  | 
        
          |  | public override void OnPointerUp(PointerEventData eventData) | 
        
          |  | { | 
        
          |  | base.OnPointerExit(eventData); | 
        
          |  |  | 
        
          |  | isPointDown = false; | 
        
          |  | delayTime = delay; | 
        
          |  |  | 
        
          |  | DoStateTransition(currentSelectionState, false); | 
        
          |  | } | 
        
          |  |  | 
        
          |  | public override void OnPointerExit(PointerEventData eventData) | 
        
          |  | { | 
        
          |  | base.OnPointerExit(eventData); | 
        
          |  |  | 
        
          |  | isPointDown = false; | 
        
          |  | delayTime = delay; | 
        
          |  |  | 
        
          |  | DoStateTransition(currentSelectionState, false); | 
        
          |  | } | 
        
          |  |  | 
        
          |  | [Serializable] | 
        
          |  | public class ButtonRepeatEvent : UnityEvent { } | 
        
          |  | } | 
        
          |  | } |