using System;
using UnityEngine;
using UnityEngine.EventSystems;
namespace OmiLAXR
{
///
/// Handles pointer interaction events for UI elements, supporting both mouse and XR interaction.
/// Implements Unity's pointer interface to track hover, press, and release events.
///
public class InteractionEventHandler : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler,
IPointerDownHandler, IPointerUpHandler
{
///
/// Contains data about the pointer interaction events.
///
public struct InteractionEventArgs
{
///
/// Total number of presses recorded since this component was initialized.
///
public int TotalPresses { get; set; }
///
/// Number of presses recorded during the current hover.
///
public int PressesInHover { get; set; }
///
/// Duration in seconds that the pointer has been hovering over this element.
///
public float HoverDuration { get; set; }
///
/// Duration in seconds that the pointer has been pressing this element.
///
public float PressDuration { get; set; }
}
// Timestamp when the pointer starts hovering over this element
private float _hoverStartTime;
// Timestamp when the pointer starts pressing this element
private float _pressStartTime;
// Flags to track the current interaction state
private bool _isHovering = false;
private bool _isPressing = false;
// Sum of how often the button was pressed inside a hover
private int _pressHoverSum = 0;
private int _pressTotalSum = 0;
///
/// Event triggered when the pointer starts hovering over this element.
///
public event Action OnHoverStarted;
///
/// Event triggered when the pointer stops hovering over this element.
///
public event Action OnHoverEnded;
///
/// Event triggered when the pointer begins pressing this element.
///
public event Action OnPressStarted;
///
/// Event triggered when the pointer releases this element after pressing.
///
public event Action OnPressEnded;
///
/// Event triggered when a complete click action occurs (press and release while hovering).
/// Only fires when the element is released while the pointer is still hovering over it.
///
public event Action OnClicked;
///
/// Whether the pointer is currently hovering over this element.
///
public bool IsHovering => _isHovering;
///
/// Whether the pointer is currently pressing this element.
///
public bool IsPressing => _isPressing;
///
/// Called when the pointer enters this UI element.
/// Records the start time and logs the event.
///
public void OnPointerEnter(PointerEventData eventData)
{
_hoverStartTime = Time.time;
_isHovering = true;
_pressHoverSum = 0;
OnHoverStarted?.Invoke(new InteractionEventArgs()
{
TotalPresses = _pressTotalSum,
PressesInHover = _pressHoverSum,
HoverDuration = 0,
PressDuration = 0
});
}
///
/// Called when the pointer exits this UI element.
/// Calculates the hover duration, logs the event, and triggers the OnHoverEnded event.
///
public void OnPointerExit(PointerEventData eventData)
{
if (!_isHovering)
return;
_isHovering = false;
OnHoverEnded?.Invoke(new InteractionEventArgs()
{
TotalPresses = _pressTotalSum,
PressesInHover = _pressHoverSum,
HoverDuration = Time.time - _hoverStartTime,
PressDuration = _isPressing ? Time.time - _pressStartTime : 0
});
}
///
/// Called when the pointer is pressed down on this UI element.
/// Records the start time and triggers the OnPressStarted event.
///
public void OnPointerDown(PointerEventData eventData)
{
_pressStartTime = Time.time;
_isPressing = true;
OnPressStarted?.Invoke(new InteractionEventArgs()
{
TotalPresses = _pressTotalSum,
PressesInHover = _pressHoverSum,
HoverDuration = Time.time - _hoverStartTime,
PressDuration = 0
});
}
///
/// Called when the pointer is released on this UI element.
/// Calculates the press duration, increments press counters, and triggers the OnPressEnded event.
/// Also triggers OnClicked if the release happens while still hovering over the element.
///
public void OnPointerUp(PointerEventData eventData)
{
if (!_isPressing)
return;
var pressDuration = Time.time - _pressStartTime;
_isPressing = false;
_pressHoverSum++;
_pressTotalSum++;
var eventArgs = new InteractionEventArgs()
{
TotalPresses = _pressTotalSum,
PressesInHover = _pressHoverSum,
HoverDuration = Time.time - _hoverStartTime,
PressDuration = pressDuration
};
OnPressEnded?.Invoke(eventArgs);
// If we're still hovering when the press ends, this is considered a "click"
if (_isHovering)
{
OnClicked?.Invoke(eventArgs);
}
}
}
}