/// <summary>
 /// Whether the given data is valid.
 /// </summary>
 /// <param name="data">The data to check.</param>
 /// <param name="checkIfHovered">Whether to check if the hover state is active.</param>
 /// <returns>Whether the data is valid.</returns>
 protected virtual bool IsValidData(SurfaceData data, bool checkIfHovered = false)
 {
     return(data.Transform != null &&
            data.Transform.gameObject != null &&
            SourceValidity.Accepts(data.Transform.gameObject) &&
            (!checkIfHovered || HoveringElements.Any(element => element.Transform.Equals(data.Transform))));
 }
        public virtual bool Enter(SurfaceData data)
        {
            if (!IsValidData(data))
            {
                return(false);
            }

            SurfaceData hoverPayload = CreateHoverPayload(data);

            IsHovered = true;

            if (!HoveringElements.Any(element => element.Transform.Equals(data.Transform)))
            {
                HoveringElements.Add(data);

                if (HoveringElements.Count == 1)
                {
                    FirstEntered?.Invoke(hoverPayload);
                }
            }

            Entered?.Invoke(hoverPayload);

            return(true);
        }
        public virtual bool Select(SurfaceData data)
        {
            if (!IsSelectable || !IsValidData(data, true))
            {
                return(false);
            }

            if (IsActivated)
            {
                return(Deselect());
            }

            IsActivated = true;
            Activated?.Invoke(CreateSelectedPayload(data));

            if (ExitAllHoveringOnActivated)
            {
                for (int index = HoveringElements.Count - 1; index >= 0; index--)
                {
                    Exit(HoveringElements[index]);
                }

                HoveringElements.Clear();
            }

            if (DeactivateSelfOnActivated)
            {
                if (DeactivateDelay.ApproxEquals(0f))
                {
                    return(Deselect());
                }
                else
                {
                    Invoke("DoDeselect", DeactivateDelay);
                    return(true);
                }
            }

            return(true);
        }
        public virtual bool Exit(SurfaceData data)
        {
            if (!IsValidData(data, true))
            {
                return(false);
            }

            if (HoveringElements.RemoveAll(element => element.Transform.Equals(data.Transform)) > 0)
            {
                SurfaceData hoverPayload = CreateHoverPayload(data);

                Exited?.Invoke(hoverPayload);

                if (HoveringElements.Count == 0)
                {
                    IsHovered = false;
                    LastExited?.Invoke(hoverPayload);
                }

                return(true);
            }

            return(false);
        }