292 lines
8.6 KiB
C#
292 lines
8.6 KiB
C#
![]() |
using System;
|
||
|
using UnityEngine;
|
||
|
using UnityEngine.Events;
|
||
|
using UnityEngine.UI;
|
||
|
using UnityEngine.EventSystems;
|
||
|
using UnityEngine.InputSystem;
|
||
|
|
||
|
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;
|
||
|
[SerializeField] private bool _isEnabled = true;
|
||
|
[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");
|
||
|
private readonly int _isEnabledHash = Animator.StringToHash("Enabled");
|
||
|
|
||
|
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)
|
||
|
{
|
||
|
_animator.SetBool(_isEnabledHash, _isEnabled);
|
||
|
_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();
|
||
|
|
||
|
public bool IsEnabled => _isEnabled;
|
||
|
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();
|
||
|
}
|
||
|
}
|
||
|
}
|