IndieGame/client/Assets/Ether/Scripts/Module/Extension/UGUI/Button/ButtonEx.cs
DOBEST\zhaoyingjie f242607587 初始化工程
2024-10-11 10:12:15 +08:00

496 lines
14 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/********************************************************************
文件: 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
}
}