using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.UI; public class BottomBarButtonHover : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler, IPointerDownHandler, IPointerUpHandler, IPointerMoveHandler { public float hoverScale = 1.06f; public float pressScale = 0.92f; public float hoverWidthScale = 1.08f; public float scaleLerp = 12f; public float gyroAngle = 6f; public float gyroLerp = 12f; private RectTransform rect; private LayoutElement layout; private float basePreferredWidth; private Vector3 baseScale; private bool hovering; private bool pressed; private Vector3 targetScale; private Quaternion targetRotation = Quaternion.identity; private Camera eventCamera; private RectTransform layoutRoot; private void Awake() { rect = GetComponent(); baseScale = transform.localScale; targetScale = baseScale; layout = GetComponent(); if (layout == null) layout = gameObject.AddComponent(); basePreferredWidth = layout.preferredWidth; if (basePreferredWidth <= 0f && rect != null) basePreferredWidth = rect.rect.width; if (basePreferredWidth <= 0f) basePreferredWidth = 100f; layout.preferredWidth = basePreferredWidth; var group = GetComponentInParent(); if (group != null) layoutRoot = group.GetComponent(); } private void Update() { float dt = Time.unscaledDeltaTime; transform.localScale = Vector3.Lerp(transform.localScale, targetScale, 1f - Mathf.Exp(-scaleLerp * dt)); if (hovering) { Vector2 localPoint; if (rect != null && RectTransformUtility.ScreenPointToLocalPointInRectangle(rect, Input.mousePosition, eventCamera, out localPoint)) { Vector2 size = rect.rect.size; float nx = size.x > 0f ? localPoint.x / size.x : 0f; float ny = size.y > 0f ? localPoint.y / size.y : 0f; float rotX = -ny * gyroAngle * 2f; float rotY = nx * gyroAngle * 2f; targetRotation = Quaternion.Euler(rotX, rotY, 0f); } } else { targetRotation = Quaternion.identity; } transform.localRotation = Quaternion.Slerp(transform.localRotation, targetRotation, 1f - Mathf.Exp(-gyroLerp * dt)); } public void OnPointerEnter(PointerEventData eventData) { hovering = true; eventCamera = eventData.pressEventCamera; layout.preferredWidth = basePreferredWidth * hoverWidthScale; RebuildLayout(); if (!pressed) targetScale = baseScale * hoverScale; } public void OnPointerExit(PointerEventData eventData) { hovering = false; layout.preferredWidth = basePreferredWidth; RebuildLayout(); if (!pressed) targetScale = baseScale; } public void OnPointerDown(PointerEventData eventData) { pressed = true; targetScale = baseScale * pressScale; } public void OnPointerUp(PointerEventData eventData) { pressed = false; targetScale = baseScale * (hovering ? hoverScale : 1f); } public void OnPointerMove(PointerEventData eventData) { eventCamera = eventData.pressEventCamera; } private void RebuildLayout() { if (layoutRoot != null) LayoutRebuilder.ForceRebuildLayoutImmediate(layoutRoot); } }