ProjectDDD/Assets/_DDD/_Scripts/GameUi/CommonButton.cs
2025-08-25 10:54:25 +09:00

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();
}
}
}