/******************************************************************** 文件: 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 subFrames = new DictionaryEx(); protected FrameBase() { FrameData = new FrameData(); OpenFrameData = new OpenFrameData(); UIElementAttribute elementAttribute = GetType().GetCustomAttribute(); 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 界面生命周期 /// /// 绑定UIRoot /// 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 /// /// 打开界面 /// 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(); } /// /// 关闭界面 /// 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(); }); } /// /// 返回上个界面 /// 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(OpenFrameData openFrameData, Action callback = null) where T : FrameBase { if (openFrameData == null || openFrameData.ParentFrameData == null) { Debug.LogError("打开子界面需要FrameData,并给FrameData中的ParentData赋值"); return; } UIManager.Inst.OpenFrame(openFrameData, callback); T frame = UIManager.Inst.GetFrame(); subFrames.TryAdd(typeof(T).Name, frame); } public void CloseSubFrame(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 查找物体 /// /// 子物体缓存 /// Dictionary childFindCache = new Dictionary(); /// /// 检查缓存中内容 /// /// /// private Transform CheckChildCache(string path) { if (childFindCache.ContainsKey(path)) { return childFindCache[path]; } return null; } /// /// 添加子物体到缓存 /// /// /// /// private Transform AddChildCache(string path, Transform trans) { if (childFindCache.ContainsKey(path)) { childFindCache[path] = trans; } else { childFindCache.Add(path, trans); } return trans; } /// /// 通过名称查找物体 /// protected Transform GetChildForName(string name) { var tempTrans = CheckChildCache(name); if (tempTrans != null) { return tempTrans; } Transform[] trans = FrameData.Root.GetComponentsInChildren(true); foreach (Transform tran in trans) { if (tran.name == name) { return AddChildCache(name, tran); } } return null; } /// /// 通过名称查找物体组件 /// protected T GetComponentForName(string name) { return GetChildForName(name).GetComponent(); } /// /// 查找当前界面的某个物体 /// 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)); } /// /// 查找当前界面的某个物体的组件 /// protected T GetComponent(string path) where T : Component { //Debug.Log("GetComponent:" + typeof(T) + " : " + path); return GetChild(path).GetComponent(); } #endregion #region 事件 Dictionary eventCache = new Dictionary(); protected void AddEventListener(string eventName, Delegate callback) { //EventCenter.AddListener(eventName, callback); } #endregion //========================================= 事件工具 ============================================ #region 按钮事件 protected void OnBtnLeftClick(string path, Action action) { ButtonEx btn = GetComponent(path); OnBtnLeftClick(btn, action); } protected void OnBtnLeftClick(GameObject obj, Action action) { ButtonEx btn = obj.GetComponent(); 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(path); OnBtnRightClick(btn, action); } protected void OnBtnRightClick(GameObject obj, Action action) { ButtonEx btn = obj.GetComponent(); 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(path); SetText(label, text); } protected void SetText(GameObject obj, string text) { Text label = obj.GetComponent(); 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(path); SetSprite(img, spritePath); } protected void SetSprite(GameObject obj, string spritePath) { Image img = obj.GetComponent(); SetSprite(img, spritePath); } protected void SetSprite(Image img, string spritePath) { img.sprite = LoaderTools.LoadAsset(spritePath); } #endregion #region 输入框 protected void SetInputFieldValue(string path, string text) { GetComponent(path).text = text; } protected void SetInputFieldValue(GameObject obj, string text) { obj.GetComponent().text = text; } protected void SetInputFieldValue(InputField input, string text) { input.text = text; } protected void OnInputFieldValueChanged(string path, Action action) { InputField input = GetComponent(path); OnInputFieldValueChanged(input, action); } protected void OnInputFieldValueChanged(GameObject obj, Action action) { InputField input = obj.GetComponent(); OnInputFieldValueChanged(input, action); } protected void OnInputFieldValueChanged(InputField input, Action action) { input.onValueChanged.RemoveAllListeners(); input.onValueChanged.AddListener((str) => { action?.Invoke(str); }); } protected void OnInputFieldEnd(string path, Action action) { InputField input = GetComponent(path); OnInputFieldEnd(input, action); } protected void OnInputFieldEnd(GameObject obj, Action action) { InputField input = obj.GetComponent(); OnInputFieldEnd(input, action); } protected void OnInputFieldEnd(InputField input, Action action) { input.onEndEdit.AddListener((str) => { action?.Invoke(str); }); } #endregion #region 复选框 protected void OnToggleChange(string path, Action action) { Toggle toggle = GetComponent(path); OnToggleChange(toggle, action); } protected void OnToggleChange(GameObject obj, Action action) { Toggle toggle = obj.GetComponent(); OnToggleChange(toggle, action); } protected void OnToggleChange(Toggle toggle, Action action) { toggle.onValueChanged.AddListener((isChange) => { action?.Invoke(isChange); }); } #endregion #region 滑动条 protected void OnSliderChange(string path, Action action) { Slider slider = GetComponent(path); OnSliderChange(slider, action); } protected void OnSliderChange(GameObject obj, Action action) { Slider slider = obj.GetComponent(); OnSliderChange(slider, action); } protected void OnSliderChange(Slider slider, Action action) { slider.onValueChanged.AddListener((value) => { action?.Invoke(value); }); } #endregion #region EventTrigger事件 /// /// EventTrigger监听 /// public void AddTriggersListener(GameObject obj, EventTriggerType eventID, Action unityAction) { EventTrigger trigger = obj.GetComponent(); if (trigger == null) { trigger = obj.AddComponent(); } if (trigger.triggers.Count == 0) { trigger.triggers = new List(); } UnityAction callback = new UnityAction(unityAction); EventTrigger.Entry entry = new EventTrigger.Entry(); entry.eventID = eventID; entry.callback.AddListener(callback); trigger.triggers.Add(entry); } protected void OnClick(GameObject obj, Action clickEvent) { AddTriggersListener(obj, EventTriggerType.PointerClick, (baseEventData) => { PointerEventData eventData = (PointerEventData)baseEventData; clickEvent?.Invoke(eventData); }); } protected void OnClick(string path, Action clickEvent) { GameObject obj = GetChild(path).gameObject; OnClick(obj, clickEvent); } protected void OnClickDown(GameObject obj, Action clickDownEvent) { AddTriggersListener(obj, EventTriggerType.PointerDown, (baseEventData) => { PointerEventData eventData = (PointerEventData)baseEventData; clickDownEvent?.Invoke(eventData); }); } protected void OnClickDown(string path, Action clickDownEvent) { GameObject obj = GetChild(path).gameObject; OnClickDown(obj, clickDownEvent); } protected void OnClickUp(GameObject obj, Action clickUpEvent) { AddTriggersListener(obj, EventTriggerType.PointerUp, (baseEventData) => { PointerEventData eventData = (PointerEventData)baseEventData; clickUpEvent?.Invoke(eventData); }); } protected void OnClickUp(string path, Action clickUpEvent) { GameObject obj = GetChild(path).gameObject; OnClickUp(obj, clickUpEvent); } protected void OnDrag(GameObject obj, Action dragEvent) { AddTriggersListener(obj, EventTriggerType.Drag, (baseEventData) => { PointerEventData eventData = (PointerEventData)baseEventData; dragEvent?.Invoke(eventData); }); } protected void OnDrag(string path, Action dragEvent) { GameObject obj = GetChild(path).gameObject; OnDrag(obj, dragEvent); } /// /// UI物体拖拽 /// /// 拖拽的物体 /// 拖拽结束回调 internal void OnDragMove(GameObject obj, Action dragEndcallback = null) { RectTransform canvas = UIManager.Inst.MainCanvas.GetComponent(); ; //得到canvas的ugui坐标 RectTransform objRect = obj.GetComponent(); //得到图片的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 action = null) { GameObject obj = GetChild(path).gameObject; OnDragMove(obj, action); } #endregion } }