IndieGame/client/Assets/Ether/Scripts/Module/Extension/UGUI/Button/ButtonEx.cs

496 lines
14 KiB
C#
Raw Normal View History

2024-10-11 10:12:15 +08:00
/********************************************************************
: ButtonEx.cs
:
: 1982614048@qq.com
: 2024/03/29 17:28:19
:
: 2024/04/22 20:20:24
:
*********************************************************************/
using Sirenix.OdinInspector;
using System;
using System.Collections;
using System.Collections.Generic;
#if UNITY_EDITOR
using UnityEditor;
#endif
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;
using UnityEngine.UI;
using UnityTimer;
namespace Ether
{
public class ButtonExPointerData : Selectable
{
public GameObject PointerItem; //点击的Item
public Vector3 lastPosition; //上次的位置
/// <summary>
/// 是否在拖拽
/// </summary>
public bool IsDrag
{
get
{
Vector3 curPos = PointerItem.transform.position;
Vector3 offset = curPos - lastPosition;
if (Mathf.Abs(offset.x) <= 10 && Mathf.Abs(offset.y) <= 10 && Mathf.Abs(offset.z) <= 10)
{
return false;
}
return true;
}
}
}
[Serializable]
public class ButtonEx : SerializedMonoBehaviour,
IPointerDownHandler, IPointerUpHandler,
IPointerEnterHandler, IPointerExitHandler
{
#region
[Header("音效")]
[Space]
[LabelText("点击音效")]
[ValueDropdown("@ConstName.AudioNameList")]
public string clickSound;
[LabelText("移入音效")]
[ValueDropdown("@ConstName.AudioNameList")]
public string enterSound;
[Space]
[Space]
[LabelText("是否点击缩放")]
public bool isScale = true;
[LabelText("点击缩放大小"), Range(0, 2)]
[ShowIf("isScale", true)]
public float clickScale = 0.95f;
[Space]
[LabelText("是否允许长按")]
public bool allowLongPress = true;
[ShowIf("allowLongPress", true), LabelText("触发长按时间")]
public float longPressDuration = 1f;
[ShowIf("allowLongPress", true), LabelText("是否允许长按循环触发")]
public bool allowLongPressWhile = true;
[Space]
[LabelText("是否允许双击")]
public bool allowDoubleClick = false;
[ShowIf("allowDoubleClick", true), Tooltip("第二次点击与第一次点击的间隔"), LabelText("点击间隔"), Range(0.2f, 1.5f)]
public float doubleClickDuration = 0.5f;
[Space]
[SerializeField, LabelText("使用不规则点击"), SetProperty("UseAnomalousClick")]
private bool useAnomalousClick = false;
public bool UseAnomalousClick
{
get
{
return useAnomalousClick;
}
set
{
useAnomalousClick = value;
Debug.Log("UseAnomalousClick");
}
}
[LabelText("是否打印Log")]
public bool isShowLog = false;
#endregion
#region
/// <summary>
/// 按钮点击事件
/// </summary>
private ActionEvent m_OnClick = new ActionEvent();
public ActionEvent OnClick
{
get { return m_OnClick; }
}
/// <summary>
/// 按钮左键点击事件
/// </summary>
private ActionEvent m_OnLeftClick = new ActionEvent();
public ActionEvent OnLeftClick
{
get { return m_OnLeftClick; }
}
/// <summary>
/// 按钮右键点击事件
/// </summary>
private ActionEvent m_OnRightClick = new ActionEvent();
public ActionEvent OnRightClick
{
get { return m_OnRightClick; }
}
/// <summary>
/// 按钮点击事件
/// </summary>
private ActionEvent m_OnDoubleClick = new ActionEvent();
public ActionEvent OnDoubleClick
{
get { return m_OnDoubleClick; }
}
/// <summary>
/// 按钮长按点击事件
/// </summary>
private ActionEvent m_OnLongClick = new ActionEvent();
public ActionEvent OnLongClick
{
get { return m_OnLongClick; }
}
/// <summary>
/// 按钮进入事件
/// </summary>
private ActionEvent m_OnEnter = new ActionEvent();
public ActionEvent OnEnter
{
get { return m_OnEnter; }
}
/// <summary>
/// 按钮移出事件
/// </summary>
private ActionEvent m_OnExit = new ActionEvent();
public ActionEvent OnExit
{
get { return m_OnExit; }
}
public void Awake()
{
BaseScale = transform.localScale;
pointerData = new ButtonExPointerData()
{
PointerItem = gameObject,
};
}
ButtonExPointerData pointerData; //按钮数据
public Vector3 BaseScale { get; private set; }
private Vector3 normalScale = Vector3.zero; //基础缩放
private bool isOnClickDown = false; //是否点击按下
private bool isOnClickTrigger = false; //是否触发点击
private bool isDoubleClicking = false; //是否正在双击状态
private bool isLongPressing = false; //是否长按状态
private Timer longPressTimer; //长按定时器
private Timer doubleTimer; //双击定时器
#region
public void OnPointerDown(PointerEventData eventData)
{
normalScale = transform.localScale;
//if (eventData.button != PointerEventData.InputButton.Left)
// return;
pointerData.lastPosition = transform.position;
OnPointerDownEvent();
}
private void OnPointerDownEvent()
{
if (isShowLog)
{
Debug.Log("按钮按下");
}
isOnClickDown = true;
isOnClickTrigger = true;
isLongPressing = false;
if (isScale)
{
transform.localScale = new Vector2(normalScale.x * clickScale, normalScale.y * clickScale);
}
StartLongPress();
}
#endregion
#region
public void OnPointerUp(PointerEventData eventData)
{
if (!isActiveAndEnabled)
return;
//if (eventData.button != PointerEventData.InputButton.Left)
// return;
if (isOnClickTrigger && !isLongPressing)
{
if (isDoubleClicking)
{
return;
}
if (allowDoubleClick)
{
isDoubleClicking = true;
doubleTimer = Timer.Register(doubleClickDuration, () =>
{
isDoubleClicking = false;
if (isOnClickTrigger)
{
OnPointerDoubleClick(eventData);
OnPointerUpEvent(eventData); //因为上面return掉了所以第二次的up没有执行得手动调用
}
else
{
OnPointerClick(eventData);
}
});
}
else
{
OnPointerClick(eventData);
}
}
OnPointerUpEvent(eventData);
}
private void OnPointerUpEvent(PointerEventData eventData)
{
isOnClickDown = false;
isOnClickTrigger = false;
isLongPressing = false;
if (isScale)
{
transform.localScale = normalScale;
}
StopLongPress();
if (eventData.dragging)
{
return;
}
if (isShowLog)
{
Debug.Log("按钮抬起");
}
}
#endregion
#region
public void OnPointerClick(PointerEventData eventData)
{
if (eventData.dragging)
{
return;
}
if (isShowLog)
{
Debug.Log($"{transform.name}按钮点击");
}
if (m_OnClick.Count == 0)
{
if (eventData.button == PointerEventData.InputButton.Left)
{
m_OnLeftClick.Invoke();
}
else if (eventData.button == PointerEventData.InputButton.Right)
{
m_OnRightClick.Invoke();
}
}
else
{
m_OnClick.Invoke();
}
if (!string.IsNullOrEmpty(clickSound))
{
AudioManager.Inst.PlayEffectAudio(clickSound);
}
}
public void OnPointerDoubleClick(PointerEventData eventData)
{
if (eventData.dragging)
{
return;
}
if (isShowLog)
{
Debug.Log($"{transform.name}按钮双击");
}
m_OnDoubleClick.Invoke();
if (!string.IsNullOrEmpty(clickSound))
{
AudioManager.Inst.PlayEffectAudio(clickSound);
}
}
#endregion
#region
public void OnPointerEnter(PointerEventData eventData)
{
//Debug.Log("移入按钮");
m_OnEnter?.Invoke();
if (!string.IsNullOrEmpty(enterSound))
{
AudioManager.Inst.PlayEffectAudio(enterSound);
}
if (isOnClickDown)
{
isOnClickTrigger = true;
if (isScale)
{
transform.localScale = new Vector2(normalScale.x * clickScale, normalScale.y * clickScale);
}
StartLongPress();
}
}
#endregion
#region
public void OnPointerExit(PointerEventData eventData)
{
isOnClickTrigger = false;
isLongPressing = false;
// if (isOnClickDown && isScale)
// {
// transform.localScale = normalScale;
// }
StopLongPress();
m_OnExit?.Invoke();
}
#endregion
#region
/// <summary>
/// 开始长按
/// </summary>
private void StartLongPress()
{
if (allowLongPress)
{
longPressTimer = Timer.Register(longPressDuration, () =>
{
if (pointerData.IsDrag)
{
isOnClickDown = false;
isOnClickTrigger = false;
isLongPressing = false;
StopLongPress();
return;
}
isLongPressing = true;
OnPointerLongClick();
}, isLooped: allowLongPressWhile);
}
}
/// <summary>
/// 长按触发
/// </summary>
private void OnPointerLongClick()
{
if (isShowLog)
{
Debug.Log("按钮长按!");
}
m_OnLongClick.Invoke();
}
/// <summary>
/// 停止长按
/// </summary>
private void StopLongPress()
{
longPressTimer?.Cancel();
}
#endregion
#endregion
#if UNITY_EDITOR
[MenuItem("GameObject/UIEx/ButtonEx", priority = 0)]
private static void CreateButtonEx(MenuCommand menuCmd)
{
GameObject selection = Selection.activeGameObject;
GameObject gameObject;
if (selection != null)
{
Debug.Log($"选择物体:{selection.name}");
// 获取物体的根 Canvas
Canvas rootCanvas = selection.GetComponentInParent<Canvas>();
Transform parentTransform;
if (rootCanvas != null)
{
parentTransform = selection.transform;
}
else
{
var canvas = ObjectFactory.CreateGameObject("Canvas", typeof(Canvas), typeof(CanvasScaler), typeof(GraphicRaycaster));
var eventSystem = ObjectFactory.CreateGameObject("EventSystem", typeof(UnityEngine.EventSystems.EventSystem), typeof(UnityEngine.EventSystems.StandaloneInputModule));
parentTransform = canvas.transform;
}
gameObject = ObjectFactory.CreateGameObject("New ButtonEx", typeof(Image), typeof(ButtonEx));
gameObject.transform.SetParent(parentTransform, false);
}
else
{
var canvas = ObjectFactory.CreateGameObject("Canvas", typeof(Canvas), typeof(CanvasScaler), typeof(GraphicRaycaster));
var eventSystem = ObjectFactory.CreateGameObject("EventSystem", typeof(UnityEngine.EventSystems.EventSystem), typeof(UnityEngine.EventSystems.StandaloneInputModule));
canvas.GetComponent<Canvas>().renderMode = RenderMode.ScreenSpaceOverlay;
Transform parentTransform = canvas.transform;
gameObject = ObjectFactory.CreateGameObject("New ButtonEx", typeof(Image), typeof(ButtonEx));
gameObject.transform.SetParent(parentTransform, false);
}
gameObject.transform.localPosition = Vector3.zero;
gameObject.transform.localScale = new Vector3(1, 1, 1);
EditorUtility.FocusProjectWindow();
Selection.activeObject = gameObject;
EditorGUIUtility.PingObject(Selection.activeObject);
}
#endif
}
}