2025-08-25 01:54:25 +00:00
|
|
|
using UnityEngine;
|
|
|
|
using UnityEngine.Events;
|
|
|
|
using UnityEngine.UI;
|
|
|
|
using UnityEngine.EventSystems;
|
2025-08-25 05:00:03 +00:00
|
|
|
using UnityEngine.Serialization;
|
2025-08-25 01:54:25 +00:00
|
|
|
|
|
|
|
namespace DDD
|
|
|
|
{
|
|
|
|
public enum ButtonState
|
|
|
|
{
|
|
|
|
Normal,
|
|
|
|
Highlighted,
|
|
|
|
Pressed,
|
|
|
|
Selected,
|
|
|
|
Disabled
|
|
|
|
}
|
|
|
|
|
|
|
|
public enum ButtonType
|
|
|
|
{
|
|
|
|
Normal = 0,
|
|
|
|
Toggle
|
|
|
|
}
|
|
|
|
|
|
|
|
[RequireComponent(typeof(Button))]
|
|
|
|
public class CommonButton : MonoBehaviour, IInteractableUi, IPointerClickHandler, IPointerEnterHandler, IPointerExitHandler,
|
|
|
|
IPointerDownHandler, IPointerUpHandler, ISelectHandler, IDeselectHandler, ISubmitHandler
|
|
|
|
{
|
|
|
|
[SerializeField] private Button _button;
|
|
|
|
[SerializeField] private Animator _animator;
|
2025-08-25 05:00:03 +00:00
|
|
|
[SerializeField] private bool _canDisabledAnimation = true;
|
2025-08-25 01:54:25 +00:00
|
|
|
[SerializeField] private bool _synchronizeStates = true;
|
|
|
|
[SerializeField] private ButtonType _buttonType;
|
|
|
|
|
|
|
|
private bool _isPressed;
|
|
|
|
private bool _isHighlighted;
|
|
|
|
private bool _isSelected;
|
|
|
|
private bool _isToggled;
|
|
|
|
|
|
|
|
private readonly int _normalHash = Animator.StringToHash("Normal");
|
|
|
|
private readonly int _highlightedHash = Animator.StringToHash("Highlighted");
|
|
|
|
private readonly int _pressedHash = Animator.StringToHash("Pressed");
|
|
|
|
private readonly int _selectedHash = Animator.StringToHash("Selected");
|
|
|
|
private readonly int _toggleHash = Animator.StringToHash("Toggled");
|
|
|
|
private readonly int _disabledHash = Animator.StringToHash("Disabled");
|
2025-08-25 05:00:03 +00:00
|
|
|
private readonly int _canDisabled = Animator.StringToHash("CanDisabled");
|
2025-08-25 01:54:25 +00:00
|
|
|
|
|
|
|
private void OnEnable()
|
|
|
|
{
|
|
|
|
_isPressed = false;
|
|
|
|
_isHighlighted = false;
|
|
|
|
_isSelected = false;
|
|
|
|
_isToggled = false;
|
|
|
|
|
|
|
|
UpdateVisualState();
|
|
|
|
}
|
|
|
|
|
|
|
|
private void OnDestroy()
|
|
|
|
{
|
|
|
|
if (_button)
|
|
|
|
{
|
|
|
|
_button.onClick.RemoveAllListeners();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private void UpdateVisualState()
|
|
|
|
{
|
|
|
|
if (gameObject.activeInHierarchy == false || _synchronizeStates == false) return;
|
|
|
|
|
|
|
|
var currentState = GetCurrentState();
|
|
|
|
ApplyVisualState(currentState);
|
|
|
|
}
|
|
|
|
|
|
|
|
private ButtonState GetCurrentState()
|
|
|
|
{
|
|
|
|
if (_buttonType == ButtonType.Normal)
|
|
|
|
{
|
|
|
|
if (_button.interactable == false)
|
|
|
|
{
|
|
|
|
return ButtonState.Disabled;
|
|
|
|
}
|
|
|
|
if (_isPressed)
|
|
|
|
{
|
|
|
|
return ButtonState.Pressed;
|
|
|
|
}
|
|
|
|
if (_isSelected)
|
|
|
|
{
|
|
|
|
return ButtonState.Selected;
|
|
|
|
}
|
|
|
|
return ButtonState.Normal;
|
|
|
|
}
|
|
|
|
if (_buttonType == ButtonType.Toggle)
|
|
|
|
{
|
|
|
|
if (_isToggled)
|
|
|
|
{
|
|
|
|
return ButtonState.Selected;
|
|
|
|
}
|
|
|
|
if (_isPressed)
|
|
|
|
{
|
|
|
|
return ButtonState.Pressed;
|
|
|
|
}
|
|
|
|
if (_isSelected || _isHighlighted)
|
|
|
|
{
|
|
|
|
return ButtonState.Highlighted;
|
|
|
|
}
|
|
|
|
if (_button.interactable == false)
|
|
|
|
{
|
|
|
|
return ButtonState.Disabled;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return ButtonState.Normal;
|
|
|
|
}
|
|
|
|
|
|
|
|
private void ApplyVisualState(ButtonState state)
|
|
|
|
{
|
|
|
|
if (_animator && _animator.runtimeAnimatorController)
|
|
|
|
{
|
|
|
|
ApplyAnimatorState(state);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private void ApplyAnimatorState(ButtonState state)
|
|
|
|
{
|
2025-08-25 05:00:03 +00:00
|
|
|
_animator.SetBool(_canDisabled, _canDisabledAnimation);
|
2025-08-25 01:54:25 +00:00
|
|
|
_animator.SetBool(_highlightedHash, _isHighlighted);
|
|
|
|
_animator.SetBool(_pressedHash, _isPressed);
|
|
|
|
_animator.SetBool(_selectedHash, _isSelected);
|
|
|
|
_animator.SetBool(_toggleHash, _isToggled);
|
|
|
|
_animator.SetBool(_disabledHash, !_button.interactable);
|
|
|
|
}
|
|
|
|
|
|
|
|
public void OnInteract()
|
|
|
|
{
|
|
|
|
_button.onClick.Invoke();
|
|
|
|
}
|
|
|
|
|
|
|
|
public void OnPointerClick(PointerEventData eventData)
|
|
|
|
{
|
|
|
|
UpdateVisualState();
|
|
|
|
}
|
|
|
|
|
|
|
|
public void OnPointerEnter(PointerEventData eventData)
|
|
|
|
{
|
|
|
|
if (_button.interactable == false) return;
|
|
|
|
|
|
|
|
if (_buttonType == ButtonType.Normal)
|
|
|
|
{
|
|
|
|
_isSelected = true;
|
|
|
|
EventSystem.current.SetSelectedGameObject(gameObject);
|
|
|
|
}
|
|
|
|
else if (_buttonType == ButtonType.Toggle)
|
|
|
|
{
|
|
|
|
_isHighlighted = true;
|
|
|
|
}
|
|
|
|
UpdateVisualState();
|
|
|
|
}
|
|
|
|
|
|
|
|
public void OnPointerExit(PointerEventData eventData)
|
|
|
|
{
|
|
|
|
if (_button.interactable == false) return;
|
|
|
|
|
|
|
|
if (_buttonType == ButtonType.Normal)
|
|
|
|
{
|
|
|
|
_isSelected = false;
|
|
|
|
}
|
|
|
|
else if (_buttonType == ButtonType.Toggle)
|
|
|
|
{
|
|
|
|
_isHighlighted = false;
|
|
|
|
}
|
|
|
|
UpdateVisualState();
|
|
|
|
}
|
|
|
|
|
|
|
|
public void OnPointerDown(PointerEventData eventData)
|
|
|
|
{
|
|
|
|
if (_button.interactable == false) return;
|
|
|
|
|
|
|
|
if (eventData.button == PointerEventData.InputButton.Left)
|
|
|
|
{
|
|
|
|
_isPressed = true;
|
|
|
|
UpdateVisualState();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public void OnPointerUp(PointerEventData eventData)
|
|
|
|
{
|
|
|
|
if (_button.interactable == false) return;
|
|
|
|
|
|
|
|
if (eventData.button == PointerEventData.InputButton.Left)
|
|
|
|
{
|
|
|
|
_isPressed = false;
|
|
|
|
if (_buttonType == ButtonType.Normal)
|
|
|
|
{
|
|
|
|
_isSelected = false;
|
|
|
|
}
|
|
|
|
else if (_buttonType == ButtonType.Toggle)
|
|
|
|
{
|
|
|
|
_isHighlighted = false;
|
|
|
|
_isToggled = true;
|
|
|
|
}
|
|
|
|
UpdateVisualState();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public void OnSelect(BaseEventData eventData)
|
|
|
|
{
|
|
|
|
if (_button.interactable == false) return;
|
|
|
|
|
|
|
|
if (_buttonType == ButtonType.Normal)
|
|
|
|
{
|
|
|
|
_isSelected = true;
|
|
|
|
}
|
|
|
|
else if (_buttonType == ButtonType.Toggle)
|
|
|
|
{
|
|
|
|
_isHighlighted = true;
|
|
|
|
}
|
|
|
|
UpdateVisualState();
|
|
|
|
}
|
|
|
|
|
|
|
|
public void OnDeselect(BaseEventData eventData)
|
|
|
|
{
|
|
|
|
if (_button.interactable == false) return;
|
|
|
|
|
|
|
|
if (_buttonType == ButtonType.Normal)
|
|
|
|
{
|
|
|
|
_isSelected = false;
|
|
|
|
}
|
|
|
|
else if (_buttonType == ButtonType.Toggle)
|
|
|
|
{
|
|
|
|
_isHighlighted = false;
|
|
|
|
}
|
|
|
|
UpdateVisualState();
|
|
|
|
}
|
|
|
|
|
|
|
|
public void OnSubmit(BaseEventData eventData)
|
|
|
|
{
|
|
|
|
_button.onClick.Invoke();
|
|
|
|
}
|
|
|
|
|
|
|
|
public void AddListener(UnityAction action) => _button.onClick.AddListener(action);
|
|
|
|
public void RemoveListener(UnityAction action) => _button?.onClick.RemoveListener(action);
|
|
|
|
public void RemoveAllListeners() => _button.onClick.RemoveAllListeners();
|
|
|
|
|
2025-08-25 05:00:03 +00:00
|
|
|
public bool CanDisabledAnimation => _canDisabledAnimation;
|
2025-08-25 01:54:25 +00:00
|
|
|
public bool IsInteractable => _button.interactable;
|
|
|
|
|
|
|
|
public void SetInteractable(bool interactable)
|
|
|
|
{
|
|
|
|
_button.interactable = interactable;
|
|
|
|
UpdateVisualState();
|
|
|
|
}
|
|
|
|
|
|
|
|
public void SetToggle(bool isSelected)
|
|
|
|
{
|
|
|
|
if (_buttonType == ButtonType.Toggle)
|
|
|
|
{
|
|
|
|
_isToggled = isSelected;
|
|
|
|
_isHighlighted = false;
|
|
|
|
_button.interactable = !isSelected;
|
|
|
|
}
|
|
|
|
|
|
|
|
UpdateVisualState();
|
|
|
|
}
|
|
|
|
|
|
|
|
public void ForceUpdateState()
|
|
|
|
{
|
|
|
|
UpdateVisualState();
|
|
|
|
}
|
|
|
|
|
|
|
|
public bool UseToggle
|
|
|
|
{
|
|
|
|
get => _buttonType == ButtonType.Toggle;
|
|
|
|
set => _buttonType = value ? ButtonType.Toggle : ButtonType.Normal;
|
|
|
|
}
|
|
|
|
|
|
|
|
public bool IsToggled => _isToggled;
|
|
|
|
|
|
|
|
public void SetToggleState(bool toggled)
|
|
|
|
{
|
|
|
|
if (_buttonType != ButtonType.Toggle) return;
|
|
|
|
|
|
|
|
_isToggled = toggled;
|
|
|
|
_isPressed = false;
|
|
|
|
if (!toggled)
|
|
|
|
{
|
|
|
|
_isSelected = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
UpdateVisualState();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|