/******************************************************************** 文件: 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 bool IsActive { get; set; } = false; public UIElement UIElement { get; private set; } public FrameData frameData; public FrameBase() { UIElement = new UIElement(); UIElementAttribute elementAttribute = GetType().GetCustomAttribute(); UIElement.prefabPath = (elementAttribute != null && !string.IsNullOrEmpty(elementAttribute.framePrefabPath)) ? elementAttribute.framePrefabPath : PrefabPath; UIElement.tier = elementAttribute == null ? FrameTier.Middle : elementAttribute.tier; UIElement.frameType = elementAttribute == null ? FrameType.Frame : elementAttribute.frameType; UIElement.frameName = GetType().Name; } protected virtual void OnInit() { } protected virtual void OnOpenAnim() { UIElement.Root?.SetActive(true); } public virtual void OnOpenFrame() { } public virtual void OnCloseFrame() { } public virtual void OnSubscribe() { } public virtual void OnUnSubscribe() { } public virtual void OnFocus(PointerEventData pointerEventData) { } public virtual void OnUpdate(float deltaTime) { } public void SetVisible(bool isShow, Action callback = null, FrameData openFrameData = null) { IsActive = isShow; if (isShow) { frameData = openFrameData; OnShow(callback); UIElement.Root.transform.SetAsLastSibling(); } else { OnHide(callback); } } private void OnShow(Action callback) { Debug.Log($"界面{UIElement.frameName}打开"); BindRoot(); OnOpenAnim(); OnInit(); OnSubscribe(); OnOpenFrame(); callback?.Invoke(); } private void OnHide(Action callback) { Debug.Log($"界面{UIElement.frameName}关闭"); OnUnSubscribe(); OnCloseFrame(); UIElement.Root.SetVisible(false, () => { callback?.Invoke(); GameObject.Destroy(UIElement.Root); UIElement.Root = null; childFindCache.Clear(); }); } /// /// 绑定UIRoot /// public void BindRoot() { UIElement.Root = UIManager.Inst.GetFrameRes(this); Debug.Log($"Frame:{UIElement.frameName} Root初始化成功。。。。{UIElement.Root.name}"); OnClick(UIElement.Root, OnFocus); } /// /// 返回上个界面 /// public virtual void Back() { UIManager.Inst.BackFrame(UIElement.frameName, UIElement.frameType); } public void Close() { SwitchHideFrame(UIElement.frameName); } //========================================= 工具 ============================================ #region 切换面板 /// /// 切换到另个界面 /// protected void SwitchFrame() where T : FrameBase { string targetViewName = typeof(T).Name; UIManager.Inst.CloseFrame(UIElement.frameName, () => { UIManager.Inst.OpenFrame(targetViewName); }); //UIMgr.Ins.SwitchPanel(SwitchPanelType.SwitchShowAndHide, targetViewName, frameName); } /// /// 切换到另个界面 /// protected void SwitchFrame(string targetViewName) { UIManager.Inst.CloseFrame(UIElement.frameName, () => { UIManager.Inst.OpenFrame(targetViewName); }); //UIMgr.Ins.SwitchPanel(SwitchPanelType.SwitchShowAndHide, targetViewName, frameName); } /// /// 打开另个界面,不隐藏自己 /// protected void SwitchOnlyFrame() where T : FrameBase { string targetViewName = typeof(T).Name; UIManager.Inst.OpenFrame(targetViewName); //UIMgr.Ins.SwitchPanel(SwitchPanelType.SwitchOnlyShow, targetViewName); } /// /// 打开另个界面,不隐藏自己 /// protected void SwitchOnlyFrame(string targetViewName) { UIManager.Inst.OpenFrame(targetViewName); //UIMgr.Ins.SwitchPanel(SwitchPanelType.SwitchOnlyShow, targetViewName); } /// /// 隐藏界面某个界面 /// protected void SwitchHideFrame(string targetViewName) { UIManager.Inst.CloseFrame(targetViewName); //UIMgr.Ins.SwitchPanel(SwitchPanelType.SwitchOnlyHide, targetViewName); } #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 = UIElement.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, UIElement.Root.transform.Find(path)); } /// /// 查找当前界面的某个物体的组件 /// protected T GetComponent(string path) where T : Component { //Debug.Log("GetComponent:" + typeof(T) + " : " + path); return GetChild(path).GetComponent(); } #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 } }