IndieGame/client/Assets/Ether/Scripts/Module/UI/FrameBase.cs
2024-10-28 18:20:21 +08:00

591 lines
19 KiB
C#

/********************************************************************
文件: FrameBase.cs
作者: 梦语
邮箱: 1982614048@qq.com
创建时间: 2024/03/29 17:28:19
最后修改: 梦语
最后修改时间: 2024/04/04 16:58:56
功能: 界面基类
*********************************************************************/
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;
using UnityEngine.UI;
namespace Ether
{
public abstract class FrameBase
{
public virtual string PrefabPath { get; }
public FrameData FrameData { get; private set; }
public OpenFrameData OpenFrameData;
public DictionaryEx<string, FrameBase> subFrames = new DictionaryEx<string, FrameBase>();
protected FrameBase()
{
FrameData = new FrameData();
OpenFrameData = new OpenFrameData();
UIElementAttribute elementAttribute = GetType().GetCustomAttribute<UIElementAttribute>();
FrameData.PrefabPath = (elementAttribute != null && !string.IsNullOrEmpty(elementAttribute.framePrefabPath)) ? elementAttribute.framePrefabPath : PrefabPath;
FrameData.Tier = elementAttribute == null ? FrameTier.Middle : elementAttribute.tier;
FrameData.FrameType = elementAttribute == null ? FrameType.Frame : elementAttribute.frameType;
FrameData.FrameName = GetType().Name;
}
#region
/// <summary>
/// 绑定UIRoot
/// </summary>
private void BindRoot()
{
FrameData.Root = UIManager.Inst.GetFrameRes(this);
Debug.Log($"Frame:{FrameData.FrameName} Root初始化成功。。。。{FrameData.Root.name}");
OnClick(FrameData.Root, OnFocus);
}
protected virtual void OnInit() { }
protected virtual void OnOpenAnim() { FrameData.Root?.SetActive(true); }
protected virtual void OnShow() { }
protected virtual void OnClose() { }
protected virtual void OnSubscribe() { }
protected virtual void OnUnSubscribe() { }
protected virtual void OnFocus(PointerEventData pointerEventData) { }
public virtual void OnUpdate(float deltaTime) { }
#endregion
/// <summary>
/// 打开界面
/// </summary>
public void ShowFrame(OpenFrameData openFrameData, Action callback = null)
{
if (openFrameData != null)
{
OpenFrameData = openFrameData ;
}
BindRoot();
FrameData.Root.transform.SetAsLastSibling();
Debug.Log($"界面{FrameData.FrameName}打开");
OnOpenAnim();
OnInit();
OnSubscribe();
OnShow();
OnFocus(null);
callback?.Invoke();
}
/// <summary>
/// 关闭界面
/// </summary>
public void CloseFrame(Action callback = null)
{
Debug.Log($"界面{FrameData.FrameName}关闭");
OnUnSubscribe();
OnClose();
FrameData.Root.SetVisible(false, () =>
{
GameObject.Destroy(FrameData.Root);
FrameData.Root = null;
childFindCache.Clear();
callback?.Invoke();
});
}
/// <summary>
/// 返回上个界面
/// </summary>
public virtual void Back()
{
UIManager.Inst.BackFrame(FrameData.FrameName, FrameData.FrameType);
}
public void Close()
{
//如果是子界面的话使用父界面的关闭
if (OpenFrameData.ParentFrameData != null)
{
FrameBase parentFrameBase = UIManager.Inst.GetFrame(OpenFrameData.ParentFrameData.parentFrameName);
parentFrameBase.CloseSubFrame(FrameData.FrameName);
return;
}
foreach (var framePair in subFrames)
{
UIManager.Inst.CloseFrame(framePair.Key);
}
subFrames.Clear();
UIManager.Inst.CloseFrame(FrameData.FrameName);
}
#region
protected void OpenSubFrame<T>(OpenFrameData openFrameData, Action callback = null) where T : FrameBase
{
if (openFrameData == null || openFrameData.ParentFrameData == null)
{
Debug.LogError("打开子界面需要FrameData,并给FrameData中的ParentData赋值");
return;
}
UIManager.Inst.OpenFrame<T>(openFrameData, callback);
T frame = UIManager.Inst.GetFrame<T>();
subFrames.TryAdd(typeof(T).Name, frame);
}
public void CloseSubFrame<T>(Action callback = null) where T : FrameBase
{
CloseSubFrame(typeof(T).Name, callback);
}
public void CloseSubFrame(string subFrameName, Action callback = null)
{
subFrames.Remove(subFrameName);
UIManager.Inst.CloseFrame(subFrameName, callback);
}
#endregion
#region
/// <summary>
/// 子物体缓存
/// </summary>
Dictionary<string, Transform> childFindCache = new Dictionary<string, Transform>();
/// <summary>
/// 检查缓存中内容
/// </summary>
/// <param name="path"></param>
/// <returns></returns>
private Transform CheckChildCache(string path)
{
if (childFindCache.ContainsKey(path))
{
return childFindCache[path];
}
return null;
}
/// <summary>
/// 添加子物体到缓存
/// </summary>
/// <param name="path"></param>
/// <param name="trans"></param>
/// <returns></returns>
private Transform AddChildCache(string path, Transform trans)
{
if (childFindCache.ContainsKey(path))
{
childFindCache[path] = trans;
}
else
{
childFindCache.Add(path, trans);
}
return trans;
}
/// <summary>
/// 通过名称查找物体
/// </summary>
protected Transform GetChildForName(string name)
{
var tempTrans = CheckChildCache(name);
if (tempTrans != null)
{
return tempTrans;
}
Transform[] trans = FrameData.Root.GetComponentsInChildren<Transform>(true);
foreach (Transform tran in trans)
{
if (tran.name == name)
{
return AddChildCache(name, tran);
}
}
return null;
}
/// <summary>
/// 通过名称查找物体组件
/// </summary>
protected T GetComponentForName<T>(string name)
{
return GetChildForName(name).GetComponent<T>();
}
/// <summary>
/// 查找当前界面的某个物体
/// </summary>
protected Transform GetChild(string path)
{
var tempTrans = CheckChildCache(path);
if (tempTrans != null)
{
return tempTrans;
}
//Debug.Log("FindChild:" + path + " Root:" + Root);
return AddChildCache(path, FrameData.Root.transform.Find(path));
}
/// <summary>
/// 查找当前界面的某个物体的组件
/// </summary>
protected T GetComponent<T>(string path) where T : Component
{
//Debug.Log("GetComponent:" + typeof(T) + " : " + path);
return GetChild(path).GetComponent<T>();
}
#endregion
#region
Dictionary<string, Delegate> eventCache = new Dictionary<string, Delegate>();
protected void AddEventListener(string eventName, Delegate callback)
{
//EventCenter.AddListener(eventName, callback);
}
#endregion
//========================================= 事件工具 ============================================
#region
protected void OnBtnLeftClick(string path, Action action)
{
ButtonEx btn = GetComponent<ButtonEx>(path);
OnBtnLeftClick(btn, action);
}
protected void OnBtnLeftClick(GameObject obj, Action action)
{
ButtonEx btn = obj.GetComponent<ButtonEx>();
OnBtnLeftClick(btn, action);
}
protected void OnBtnLeftClick(ButtonEx btn, Action action)
{
btn.OnLeftClick.RemoveAllListeners();
btn.OnLeftClick.AddListener(() =>
{
action?.Invoke();
});
}
protected void OnBtnRightClick(string path, Action action)
{
ButtonEx btn = GetComponent<ButtonEx>(path);
OnBtnRightClick(btn, action);
}
protected void OnBtnRightClick(GameObject obj, Action action)
{
ButtonEx btn = obj.GetComponent<ButtonEx>();
OnBtnRightClick(btn, action);
}
protected void OnBtnRightClick(ButtonEx btn, Action action)
{
btn.OnRightClick.RemoveAllListeners();
btn.OnRightClick.AddListener(() =>
{
action?.Invoke();
});
}
#endregion
#region
protected void SetText(string path, string text)
{
Text label = GetComponent<Text>(path);
SetText(label, text);
}
protected void SetText(GameObject obj, string text)
{
Text label = obj.GetComponent<Text>();
SetText(label, text);
}
protected void SetText(Text label, string text)
{
label.text = text;
}
#endregion
#region
protected void SetSprite(string path, string spritePath)
{
Image img = GetComponent<Image>(path);
SetSprite(img, spritePath);
}
protected void SetSprite(GameObject obj, string spritePath)
{
Image img = obj.GetComponent<Image>();
SetSprite(img, spritePath);
}
protected void SetSprite(Image img, string spritePath)
{
img.sprite = LoaderTools.LoadAsset<Sprite>(spritePath);
}
#endregion
#region
protected void SetInputFieldValue(string path, string text)
{
GetComponent<InputField>(path).text = text;
}
protected void SetInputFieldValue(GameObject obj, string text)
{
obj.GetComponent<InputField>().text = text;
}
protected void SetInputFieldValue(InputField input, string text)
{
input.text = text;
}
protected void OnInputFieldValueChanged(string path, Action<string> action)
{
InputField input = GetComponent<InputField>(path);
OnInputFieldValueChanged(input, action);
}
protected void OnInputFieldValueChanged(GameObject obj, Action<string> action)
{
InputField input = obj.GetComponent<InputField>();
OnInputFieldValueChanged(input, action);
}
protected void OnInputFieldValueChanged(InputField input, Action<string> action)
{
input.onValueChanged.RemoveAllListeners();
input.onValueChanged.AddListener((str) =>
{
action?.Invoke(str);
});
}
protected void OnInputFieldEnd(string path, Action<string> action)
{
InputField input = GetComponent<InputField>(path);
OnInputFieldEnd(input, action);
}
protected void OnInputFieldEnd(GameObject obj, Action<string> action)
{
InputField input = obj.GetComponent<InputField>();
OnInputFieldEnd(input, action);
}
protected void OnInputFieldEnd(InputField input, Action<string> action)
{
input.onEndEdit.AddListener((str) =>
{
action?.Invoke(str);
});
}
#endregion
#region
protected void OnToggleChange(string path, Action<bool> action)
{
Toggle toggle = GetComponent<Toggle>(path);
OnToggleChange(toggle, action);
}
protected void OnToggleChange(GameObject obj, Action<bool> action)
{
Toggle toggle = obj.GetComponent<Toggle>();
OnToggleChange(toggle, action);
}
protected void OnToggleChange(Toggle toggle, Action<bool> action)
{
toggle.onValueChanged.AddListener((isChange) =>
{
action?.Invoke(isChange);
});
}
#endregion
#region
protected void OnSliderChange(string path, Action<float> action)
{
Slider slider = GetComponent<Slider>(path);
OnSliderChange(slider, action);
}
protected void OnSliderChange(GameObject obj, Action<float> action)
{
Slider slider = obj.GetComponent<Slider>();
OnSliderChange(slider, action);
}
protected void OnSliderChange(Slider slider, Action<float> action)
{
slider.onValueChanged.AddListener((value) =>
{
action?.Invoke(value);
});
}
#endregion
#region EventTrigger事件
/// <summary>
/// EventTrigger监听
/// </summary>
public void AddTriggersListener(GameObject obj, EventTriggerType eventID, Action<BaseEventData> unityAction)
{
EventTrigger trigger = obj.GetComponent<EventTrigger>();
if (trigger == null)
{
trigger = obj.AddComponent<EventTrigger>();
}
if (trigger.triggers.Count == 0)
{
trigger.triggers = new List<EventTrigger.Entry>();
}
UnityAction<BaseEventData> callback = new UnityAction<BaseEventData>(unityAction);
EventTrigger.Entry entry = new EventTrigger.Entry();
entry.eventID = eventID;
entry.callback.AddListener(callback);
trigger.triggers.Add(entry);
}
protected void OnClick(GameObject obj, Action<PointerEventData> clickEvent)
{
AddTriggersListener(obj, EventTriggerType.PointerClick, (baseEventData) =>
{
PointerEventData eventData = (PointerEventData)baseEventData;
clickEvent?.Invoke(eventData);
});
}
protected void OnClick(string path, Action<PointerEventData> clickEvent)
{
GameObject obj = GetChild(path).gameObject;
OnClick(obj, clickEvent);
}
protected void OnClickDown(GameObject obj, Action<PointerEventData> clickDownEvent)
{
AddTriggersListener(obj, EventTriggerType.PointerDown, (baseEventData) =>
{
PointerEventData eventData = (PointerEventData)baseEventData;
clickDownEvent?.Invoke(eventData);
});
}
protected void OnClickDown(string path, Action<PointerEventData> clickDownEvent)
{
GameObject obj = GetChild(path).gameObject;
OnClickDown(obj, clickDownEvent);
}
protected void OnClickUp(GameObject obj, Action<PointerEventData> clickUpEvent)
{
AddTriggersListener(obj, EventTriggerType.PointerUp, (baseEventData) =>
{
PointerEventData eventData = (PointerEventData)baseEventData;
clickUpEvent?.Invoke(eventData);
});
}
protected void OnClickUp(string path, Action<PointerEventData> clickUpEvent)
{
GameObject obj = GetChild(path).gameObject;
OnClickUp(obj, clickUpEvent);
}
protected void OnDrag(GameObject obj, Action<PointerEventData> dragEvent)
{
AddTriggersListener(obj, EventTriggerType.Drag, (baseEventData) =>
{
PointerEventData eventData = (PointerEventData)baseEventData;
dragEvent?.Invoke(eventData);
});
}
protected void OnDrag(string path, Action<PointerEventData> dragEvent)
{
GameObject obj = GetChild(path).gameObject;
OnDrag(obj, dragEvent);
}
/// <summary>
/// UI物体拖拽
/// </summary>
/// <param name="obj">拖拽的物体</param>
/// <param name="dragEndcallback">拖拽结束回调</param>
internal void OnDragMove(GameObject obj, Action<PointerEventData> dragEndcallback = null)
{
RectTransform canvas = UIManager.Inst.MainCanvas.GetComponent<RectTransform>(); ; //得到canvas的ugui坐标
RectTransform objRect = obj.GetComponent<RectTransform>(); //得到图片的ugui坐标
Vector2 offset = new Vector3(); //用来得到鼠标和图片的差值
Vector3 imgReduceScale = new Vector3(0.8f, 0.8f, 1); //设置图片缩放
Vector3 imgNormalScale = new Vector3(1, 1, 1); //正常大小
AddTriggersListener(obj, EventTriggerType.BeginDrag, (BaseEventData) =>
{
PointerEventData eventData = (PointerEventData)BaseEventData;
Vector2 mouseDown = eventData.position; //记录鼠标按下时的屏幕坐标
Vector2 mouseUguiPos = new Vector2(); //定义一个接收返回的ugui坐标
bool isRect = RectTransformUtility.ScreenPointToLocalPointInRectangle(canvas, mouseDown, eventData.enterEventCamera, out mouseUguiPos);
if (isRect) //如果在
{
//计算图片中心和鼠标点的差值
offset = objRect.anchoredPosition - mouseUguiPos;
}
});
AddTriggersListener(obj, EventTriggerType.Drag, (BaseEventData) =>
{
PointerEventData eventData = (PointerEventData)BaseEventData;
Vector2 mouseDrag = eventData.position; //当鼠标拖动时的屏幕坐标
Vector2 uguiPos = new Vector2(); //用来接收转换后的拖动坐标
//和上面类似
bool isRect = RectTransformUtility.ScreenPointToLocalPointInRectangle(canvas, mouseDrag, eventData.enterEventCamera, out uguiPos);
if (isRect)
{
//设置图片的ugui坐标与鼠标的ugui坐标保持不变
objRect.anchoredPosition = offset + uguiPos;
}
});
AddTriggersListener(obj, EventTriggerType.EndDrag, (BaseEventData) =>
{
dragEndcallback?.Invoke((PointerEventData)BaseEventData);
});
}
internal void OnDragMove(string path, Action<PointerEventData> action = null)
{
GameObject obj = GetChild(path).gameObject;
OnDragMove(obj, action);
}
#endregion
}
}