using System.Collections; using UnityEngine; using UnityEngine.UI; using UnityEngine.Events; using TMPro; using UnityEngine.EventSystems; #if ENABLE_INPUT_SYSTEM using UnityEngine.InputSystem; #endif namespace Michsky.MUIP { [ExecuteInEditMode] public class ButtonManager : MonoBehaviour, IPointerClickHandler, IPointerDownHandler, IPointerUpHandler, IPointerEnterHandler, IPointerExitHandler, ISelectHandler, IDeselectHandler, ISubmitHandler { // Content public Sprite buttonIcon; public string buttonText = "Button"; [Range(0.1f, 10)] public float iconScale = 1; [Range(10, 200)] public float textSize = 24; // Auto Size public bool autoFitContent = true; public Padding padding; [Range(0, 100)] public int spacing = 15; public HorizontalLayoutGroup disabledLayout; public HorizontalLayoutGroup normalLayout; public HorizontalLayoutGroup highlightedLayout; [SerializeField] private HorizontalLayoutGroup mainLayout; [SerializeField] private ContentSizeFitter mainFitter; [SerializeField] private ContentSizeFitter targetFitter; [SerializeField] private RectTransform targetRect; // Resources public CanvasGroup normalCG; public CanvasGroup highlightCG; public CanvasGroup disabledCG; public TextMeshProUGUI normalText; public TextMeshProUGUI highlightedText; public TextMeshProUGUI disabledText; public Image normalImage; public Image highlightImage; public Image disabledImage; public AudioSource soundSource; [SerializeField] private GameObject rippleParent; // Settings public bool isInteractable = true; public bool enableIcon = false; public bool enableText = true; public bool useCustomContent = false; [SerializeField] private bool useCustomTextSize = false; public bool checkForDoubleClick = true; public bool enableButtonSounds = false; public bool useHoverSound = true; public bool useClickSound = true; public AudioClip hoverSound; public AudioClip clickSound; public bool useUINavigation = false; public Navigation.Mode navigationMode = Navigation.Mode.Automatic; public GameObject selectOnUp; public GameObject selectOnDown; public GameObject selectOnLeft; public GameObject selectOnRight; public bool wrapAround = false; public bool useRipple = true; [Range(0.1f, 1)] public float doubleClickPeriod = 0.25f; [Range(0.25f, 15)] public float fadingMultiplier = 8; [SerializeField] private AnimationSolution animationSolution = AnimationSolution.ScriptBased; // Events public UnityEvent onClick = new UnityEvent(); public UnityEvent onDoubleClick = new UnityEvent(); public UnityEvent onHover = new UnityEvent(); public UnityEvent onLeave = new UnityEvent(); // Ripple [SerializeField] private RippleUpdateMode rippleUpdateMode = RippleUpdateMode.UnscaledTime; [SerializeField] private Canvas targetCanvas; public Sprite rippleShape; [Range(0.1f, 5)] public float speed = 1f; [Range(0.5f, 25)] public float maxSize = 4f; public Color startColor = new Color(1f, 1f, 1f, 0.2f); public Color transitionColor = new Color(1f, 1f, 1f, 0f); [SerializeField] private bool renderOnTop = false; [SerializeField] private bool centered = false; // Helpers bool isInitialized = false; Button targetButton; bool isPointerOn; bool waitingForDoubleClickInput; #if UNITY_EDITOR public bool isPreset; public int latestTabIndex = 0; #endif public enum AnimationSolution { Custom, ScriptBased } public enum RippleUpdateMode { Normal, UnscaledTime } [System.Serializable] public class Padding { public int left = 20; public int right = 20; public int top = 5; public int bottom = 5; } void OnEnable() { if (isInitialized == false) { Initialize(); } UpdateUI(); } void OnDisable() { if (isInteractable == false) return; if (disabledCG != null) { disabledCG.alpha = 0; } if (normalCG != null) { normalCG.alpha = 1; } if (highlightCG != null) { highlightCG.alpha = 0; } } void Initialize() { #if UNITY_EDITOR if (!Application.isPlaying) { return; } #endif if (animationSolution == AnimationSolution.ScriptBased) { Animator tempAnimator = GetComponent(); if (tempAnimator != null) { Destroy(tempAnimator); } } if (gameObject.GetComponent() == null) { Image raycastImg = gameObject.AddComponent(); raycastImg.color = new Color(0, 0, 0, 0); raycastImg.raycastTarget = true; } if (targetCanvas == null) { targetCanvas = GetComponentInParent(); } if (normalCG == null) { normalCG = new GameObject().AddComponent(); normalCG.gameObject.AddComponent(); normalCG.transform.SetParent(transform); normalCG.gameObject.name = "Normal"; } if (highlightCG == null) { highlightCG = new GameObject().AddComponent(); highlightCG.gameObject.AddComponent(); highlightCG.transform.SetParent(transform); highlightCG.gameObject.name = "Highlight"; } if (disabledCG == null) { disabledCG = new GameObject().AddComponent(); disabledCG.gameObject.AddComponent(); disabledCG.transform.SetParent(transform); disabledCG.gameObject.name = "Disabled"; } if (useRipple == true && rippleParent != null) { rippleParent.SetActive(false); } else if (useRipple == false && rippleParent != null) { Destroy(rippleParent); } if (gameObject.activeInHierarchy) { StartCoroutine("LayoutFix"); } if (targetButton == null) { if (gameObject.GetComponent