初始化

This commit is contained in:
come
2025-07-26 16:56:42 +08:00
parent 8291dbb91c
commit fa81439a8c
2574 changed files with 328492 additions and 2170 deletions

View File

@@ -0,0 +1,45 @@
using UnityEngine;
namespace YIUIFramework
{
/// <summary>
/// 面板信息
/// </summary>
public class PanelInfo
{
public BasePanel UIBasePanel { get; private set; }
public bool ActiveSelf => UIBasePanel?.ActiveSelf ?? false;
/// <summary>
/// 包名
/// </summary>
public string PkgName { get; internal set; }
/// <summary>
/// 资源名称 因为每个包分开 这个资源名称是有可能重复的 虽然设计上不允许
/// </summary>
public string ResName { get; internal set; }
/// <summary>
/// C#文件名 因为有可能存在Res名称与文件名不一致的问题
/// </summary>
public string Name { get; internal set; }
internal void Reset(UIBase uiBase)
{
switch (uiBase)
{
case null:
UIBasePanel = null;
break;
case BasePanel basePanel:
UIBasePanel = basePanel;
break;
default:
Debug.LogError($"当前UI 不是Panel 请检查 {PkgName} {ResName}");
break;
}
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 6cd37b35cb984ee480cbca8c59547621
timeCreated: 1681898498

View File

@@ -0,0 +1,34 @@
using System.Collections.Generic;
using Cysharp.Threading.Tasks;
using UnityEngine;
namespace YIUIFramework
{
/// <summary>
/// YIUI 面板管理器
/// </summary>
public partial class PanelMgr : MgrSingleton<PanelMgr>
{
//低品质 将会影响动画等逻辑 也可以根据这个参数自定义一些区别
public static bool IsLowQuality = false;
//绑定初始化情况
public static bool BindInit { private set; get; }
protected override async UniTask<bool> MgrAsyncInit()
{
BindInit = UIBindHelper.InitAllBind();
if (!await InitRoot()) return false;
InitSafeArea();
return true;
}
protected override void OnDispose()
{
ResetRoot();
OnBlockDispose();
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: b786e4b603514a25963ba5537c7416ea
timeCreated: 1681898783

View File

@@ -0,0 +1,69 @@
namespace YIUIFramework
{
public partial class PanelMgr
{
#region Panel是否存在且显示
public bool ActiveSelf(string panelName)
{
var info = GetPanelInfo(panelName);
return info?.ActiveSelf ?? false;
}
public bool ActiveSelf<T>() where T : BasePanel
{
var info = GetPanelInfo<T>();
return info?.ActiveSelf ?? false;
}
#endregion
#region Panel的指定View是否存在且显示
public bool ActiveSelfView(string panelName, string viewName)
{
var info = GetPanelInfo(panelName);
if (info == null) return false;
if (info.UIBasePanel == null) return false;
var (exist, entity) = info.UIBasePanel.ExistView(viewName);
if (!exist) return false;
return entity.ActiveSelf;
}
public bool ActiveSelfView<TPanel, TView>()
where TPanel : BasePanel
where TView : BaseView
{
var info = GetPanelInfo<TPanel>();
if (info == null) return false;
if (info.UIBasePanel == null) return false;
var (exist, entity) = info.UIBasePanel.ExistView<TView>();
if (!exist) return false;
return entity.ActiveSelf;
}
public bool ActiveSelfViewByViewName<TPanel>(string viewName)
where TPanel : BasePanel
{
var info = GetPanelInfo<TPanel>();
if (info == null) return false;
if (info.UIBasePanel == null) return false;
var (exist, entity) = info.UIBasePanel.ExistView(viewName);
if (!exist) return false;
return entity.ActiveSelf;
}
public bool ActiveSelfViewByPanelName<TView>(string panelName)
where TView : BaseView
{
var info = GetPanelInfo(panelName);
if (info == null) return false;
if (info.UIBasePanel == null) return false;
var (exist, entity) = info.UIBasePanel.ExistView<TView>();
if (!exist) return false;
return entity.ActiveSelf;
}
#endregion
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: c95d90afbff74d2ebffe4411639427ea
timeCreated: 1684120713

View File

@@ -0,0 +1,128 @@
using System;
using UnityEngine;
namespace YIUIFramework
{
/// <summary>
/// 加入 移除
/// </summary>
public partial class PanelMgr
{
/// <summary>
/// 加入UI到对应层级 设置顺序 大小
/// </summary>
private void AddUI(PanelInfo panelInfo)
{
var uiBasePanel = panelInfo.UIBasePanel;
var panelLayer = uiBasePanel.Layer;
var priority = uiBasePanel.Priority;
var uiRect = uiBasePanel.OwnerRectTransform;
var layerRect = GetLayerRect(panelLayer);
if (layerRect == null)
{
panelLayer = EPanelLayer.Bottom;
layerRect = GetLayerRect(panelLayer);
Debug.LogError($"没有找到这个UILayer {panelLayer} 强制修改为使用最低层 请检查");
}
var addLast = true; //放到最后 也就是最前面
var infoList = GetLayerPanelInfoList(panelLayer);
var removeResult = infoList.Remove(panelInfo);
if (removeResult)
uiRect.SetParent(UILayerRoot);
/*
* 使用Unity的层级作为前后显示
* 大的在前 小的在后
* 所以根据优先级 从小到大排序
* 当前优先级 >= 目标优先级时 插入
*/
for (var i = infoList.Count - 1; i >= 0; i--)
{
var info = infoList[i];
var infoPriority = info.UIBasePanel?.Priority ?? 0;
if (i == infoList.Count - 1 && priority >= infoPriority) break;
if (priority >= infoPriority)
{
infoList.Insert(i + 1, panelInfo);
uiRect.SetParent(layerRect);
uiRect.SetSiblingIndex(i + 1);
addLast = false;
break;
}
if (i <= 0)
{
infoList.Insert(0, panelInfo);
uiRect.SetParent(layerRect);
uiRect.SetSiblingIndex(0);
addLast = false;
break;
}
}
if (addLast)
{
infoList.Add(panelInfo);
uiRect.SetParent(layerRect);
uiRect.SetAsLastSibling();
}
uiRect.ResetToFullScreen();
uiRect.ResetLocalPosAndRot();
panelInfo.UIBasePanel.StopCountDownDestroyPanel();
}
/// <summary>
/// 移除一个UI
/// </summary>
private void RemoveUI(PanelInfo panelInfo)
{
if (panelInfo.UIBasePanel == null)
{
Debug.LogError($"无法移除一个null panelInfo 数据 {panelInfo.ResName}");
return;
}
var uiBasePanel = panelInfo.UIBasePanel;
var foreverCache = uiBasePanel.PanelForeverCache;
var timeCache = uiBasePanel.PanelTimeCache;
var panelLayer = uiBasePanel.Layer;
RemoveLayerPanelInfo(panelLayer, panelInfo);
if (foreverCache || timeCache)
{
//缓存界面只是单纯的吧界面隐藏
//再次被打开 如何重构界面需要自行设置
var layerRect = GetLayerRect(EPanelLayer.Cache);
var uiRect = uiBasePanel.OwnerRectTransform;
uiRect.SetParent(layerRect, false);
uiBasePanel.SetActive(false);
if (timeCache && !foreverCache)
{
//根据配置时间X秒后自动摧毁
//如果X秒内又被打开则可复用
uiBasePanel.CacheTimeCountDownDestroyPanel();
}
}
else
{
var uiObj = uiBasePanel.OwnerGameObject;
UnityEngine.Object.Destroy(uiObj);
panelInfo.Reset(null);
}
}
internal void RemoveUIReset(string panelName)
{
var panelInfo = GetPanelInfo(panelName);
panelInfo?.Reset(null);
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: aaf85dfb0e364f7f924673f7e2e2f8c3
timeCreated: 1682582456

View File

@@ -0,0 +1,181 @@
using System;
using Cysharp.Threading.Tasks;
using UnityEngine;
namespace YIUIFramework
{
/// <summary>
/// 界面回退功能 关闭 / 恢复 / Home
/// </summary>
public partial class PanelMgr
{
/// <summary>
/// 打开一个同级UI时关闭其他UI
/// 只有Panel层才有这个逻辑
/// </summary>
private async UniTask AddUICloseElse(PanelInfo info)
{
if (!(info.UIBasePanel is { Layer: EPanelLayer.Panel }))
{
return;
}
if (info.UIBasePanel.PanelIgnoreBack)
{
return;
}
var layerList = GetLayerPanelInfoList(EPanelLayer.Panel);
var skipTween = info.UIBasePanel.WindowSkipOtherCloseTween;
for (var i = layerList.Count - 1; i >= 0; i--)
{
var child = layerList[i];
if (child == info)
{
continue;
}
if (child.UIBasePanel is IYIUIBack back)
{
back.DoBackClose(info);
}
switch (child.UIBasePanel.StackOption)
{
case EPanelStackOption.Omit:
if (skipTween)
child.UIBasePanel.Close(true, true);
else
await child.UIBasePanel.CloseAsync(true, true);
break;
case EPanelStackOption.None:
break;
case EPanelStackOption.Visible:
child.UIBasePanel.SetActive(false);
break;
case EPanelStackOption.VisibleTween:
if (!skipTween)
await child.UIBasePanel.InternalOnWindowCloseTween();
child.UIBasePanel.SetActive(false);
break;
default:
Debug.LogError($"新增类型未实现 {child.UIBasePanel.StackOption}");
child.UIBasePanel.SetActive(false);
break;
}
}
}
private async UniTask RemoveUIAddElse(PanelInfo info)
{
if (!(info.UIBasePanel is { Layer: EPanelLayer.Panel }))
{
return;
}
if (info.UIBasePanel.PanelIgnoreBack)
{
return;
}
var layerList = GetLayerPanelInfoList(EPanelLayer.Panel);
var skipTween = info.UIBasePanel.WindowSkipOtherOpenTween;
for (var i = layerList.Count - 1; i >= 0; i--)
{
var child = layerList[i];
if (child == info)
{
continue;
}
if (child.UIBasePanel is IYIUIBack back)
{
back.DoBackAdd(info);
}
var isBreak = true;
switch (child.UIBasePanel.StackOption)
{
case EPanelStackOption.Omit: //不可能进入这里因为他已经被关闭了 如果进入则跳过这个界面
isBreak = false;
break;
case EPanelStackOption.None:
break;
case EPanelStackOption.Visible:
child.UIBasePanel.SetActive(true);
break;
case EPanelStackOption.VisibleTween:
child.UIBasePanel.SetActive(true);
if (!skipTween)
await child.UIBasePanel.InternalOnWindowOpenTween();
break;
default:
Debug.LogError($"新增类型未实现 {child.UIBasePanel.StackOption}");
child.UIBasePanel.SetActive(true);
break;
}
if (isBreak)
break;
}
}
private async UniTask RemoveUIToHome(PanelInfo home, bool tween = true)
{
if (!(home.UIBasePanel is { Layer: EPanelLayer.Panel }))
{
return;
}
var layerList = GetLayerPanelInfoList(EPanelLayer.Panel);
var skipOtherCloseTween = home.UIBasePanel.WindowSkipOtherCloseTween;
var skipHomeOpenTween = home.UIBasePanel.WindowSkipHomeOpenTween;
for (var i = layerList.Count - 1; i >= 0; i--)
{
var child = layerList[i];
if (child != home)
{
if (child.UIBasePanel is IYIUIBack back)
{
back.DoBackHome(home);
}
if (skipOtherCloseTween)
{
ClosePanel(child.Name, false, true);
}
else
{
await ClosePanelAsync(child.Name, tween, true);
}
continue;
}
switch (child.UIBasePanel.StackOption)
{
case EPanelStackOption.Omit:
case EPanelStackOption.None:
case EPanelStackOption.Visible:
child.UIBasePanel.SetActive(true);
break;
case EPanelStackOption.VisibleTween:
child.UIBasePanel.SetActive(true);
if (tween && !skipHomeOpenTween)
await child.UIBasePanel.InternalOnWindowOpenTween();
break;
default:
Debug.LogError($"新增类型未实现 {child.UIBasePanel.StackOption}");
child.UIBasePanel.SetActive(true);
break;
}
}
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 9b2d898dda434adb8f8aed0c58061a60
timeCreated: 1682582419

View File

@@ -0,0 +1,154 @@
using System;
using System.Collections.Generic;
using UnityEngine;
namespace YIUIFramework
{
//UI最高层级之上的 屏蔽所有操作的模块
//屏蔽层显示时所有UI操作会被屏蔽 默认隐藏
//可通过API 快捷屏蔽操作
//适用于 统一动画播放时 某些操作需要等待时 都可以调节
public partial class PanelMgr
{
private GameObject m_LayerBlock; //内部屏蔽对象 显示时之下的所有UI将不可操作
private int m_LastCountDownGuid; //倒计时的唯一ID
private float m_LastRecoverOptionTime; //下一次恢复操作时间
private void OnBlockDispose()
{
RemoveLastCountDown();
}
private void RemoveLastCountDown()
{
CountDownMgr.Inst?.Remove(ref m_LastCountDownGuid);
}
//初始化添加屏蔽模块
private void InitAddUIBlock()
{
m_LayerBlock = new GameObject("LayerBlock");
var rect = m_LayerBlock.AddComponent<RectTransform>();
m_LayerBlock.AddComponent<CanvasRenderer>();
m_LayerBlock.AddComponent<UIBlock>();
rect.SetParent(UILayerRoot);
rect.SetAsLastSibling();
rect.ResetToFullScreen();
SetLayerBlockOption(true);
}
/// <summary>
/// 设置UI是否可以操作
/// 不能提供此API对外操作
/// 因为有人设置过后就会忘记恢复
/// 如果你确实需要你可以设置 禁止无限时间
/// 之后调用恢复操作也可以做到
/// </summary>
/// <param name="value">true = 可以操作 = 屏蔽层会被隐藏</param>
private void SetLayerBlockOption(bool value)
{
m_LayerBlock.SetActive(!value);
}
/// <summary>
/// 强制恢复层级到可操作状态
/// 此方法会强制打断倒计时 根据需求调用
/// </summary>
private void RecoverLayerOptionAll()
{
SetLayerBlockOption(true);
m_LastRecoverOptionTime = 0;
m_AllForeverBlockCode.Clear();
RemoveLastCountDown();
}
#region
/// <summary>
/// 禁止层级操作
/// 适合于知道想屏蔽多久 且可托管的操作
/// </summary>
/// <param name="time">需要禁止的时间</param>
private void BanLayerOptionCountDown(float time)
{
SetLayerBlockOption(false);
var currentTime = Time.realtimeSinceStartup; //当前的时间不受暂停影响
var currentRecoverOptionTime = currentTime + time;
//假设A 先禁止100秒
//B 又想禁止10秒 显然 B这个就会被屏蔽最少需要等到A禁止的时间结束
if (currentRecoverOptionTime > m_LastRecoverOptionTime)
{
m_LastRecoverOptionTime = currentRecoverOptionTime;
RemoveLastCountDown();
CountDownMgr.Inst?.Add(ref m_LastCountDownGuid, time, OnCountDownLayerOption);
}
}
private void OnCountDownLayerOption(double residuetime, double elapsetime, double totaltime)
{
if (residuetime <= 0)
{
m_LastCountDownGuid = 0;
if (IsForeverBlock)
{
//如果当前被其他永久屏蔽 则等待永久屏蔽执行恢复
return;
}
SetLayerBlockOption(true);
}
}
#endregion
#region forever
//当前是否正在被永久屏蔽
public bool IsForeverBlock => m_AllForeverBlockCode.Count >= 1;
//永久屏蔽引用计数 一定要成对使用且保证
//否则将会出现永久屏蔽的情况只能通过RecoverLayerOptionCountDown 强制恢复
private HashSet<int> m_AllForeverBlockCode = new HashSet<int>();
//永久屏蔽
//适用于 不知道要屏蔽多久 但是能保证可以成对调用的
//这个没有放到API类中
//因为如果你不能保证请不要用
//至少过程中要try起来finally 保证不会出错 否则请不要使用这个功能
public int BanLayerOptionForever()
{
SetLayerBlockOption(false);
var foreverBlockCode = IDHelper.GetGuid();
m_AllForeverBlockCode.Add(foreverBlockCode);
return foreverBlockCode;
}
//恢复永久屏蔽
public void RecoverLayerOptionForever(int code)
{
if (!m_AllForeverBlockCode.Contains(code))
{
return;
}
m_AllForeverBlockCode.Remove(code);
if (!IsForeverBlock)
{
//如果当前有其他倒计时 就等待倒计时恢复
//否则可直接恢复
if (m_LastCountDownGuid == 0)
{
SetLayerBlockOption(true);
}
}
}
#endregion
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 547433b7d178427a88077378ddb05216
timeCreated: 1688974258

View File

@@ -0,0 +1,50 @@
using UnityEngine;
namespace YIUIFramework
{
public partial class PanelMgr
{
//当前层级屏蔽操作状态 true = 显示 = 无法操作 不要与可操作搞混
public bool LayerBlockActiveSelf => m_LayerBlock.activeSelf;
//当前UI是否可以操作 true = 可以操作
public bool CanLayerBlockOption => !LayerBlockActiveSelf;
//如果当前被屏蔽了操作 下一次可以操作的时间是什么时候基于 Time.unscaledTime;
//=0 不表示可以操作 也有可能被永久屏蔽了
//可单独判断是否永久屏蔽
//也可以使用上面的方法 CanLayerBlockOption 也可以得到是否被屏蔽
public float LastRecoverOptionTime => m_LastRecoverOptionTime;
//如果当前被屏蔽了操作 可以拿到还有多久操作会恢复
public float GetLastRecoverOptionResidueTime()
{
if (CanLayerBlockOption)
{
return 0;
}
return LastRecoverOptionTime - Time.unscaledTime;
}
/// <summary>
/// 禁止层级操作
/// </summary>
/// <param name="time">需要禁止的时间</param>
public void BanLayerOption(float time = 1f)
{
BanLayerOptionCountDown(time);
}
/// <summary>
/// 强制恢复层级到可操作状态
/// 此方法会强制打断倒计时
/// 清除所有永久屏蔽
/// 根据需求调用
/// </summary>
public void RecoverLayerOption()
{
RecoverLayerOptionAll();
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: a963a8b0d20e4028ac577e66e9bcd045
timeCreated: 1689150136

View File

@@ -0,0 +1,200 @@
using Cysharp.Threading.Tasks;
using UnityEngine;
namespace YIUIFramework
{
public partial class PanelMgr
{
/// <summary>
/// 得到最顶层的面板
/// 默认将返回所有面板的第一个
/// 可能没有
/// </summary>
public PanelInfo GetTopPanel(EPanelLayer layer = EPanelLayer.Any,
EPanelOption ignoreOption = EPanelOption.Container)
{
var layerCount = (int)EPanelLayer.Count;
for (var i = 0; i < layerCount; i++)
{
var currentLayer = (EPanelLayer)i;
//如果是任意层级则 从上到下找
//否则只会在目标层级上找
if (layer != EPanelLayer.Any && currentLayer != layer)
{
continue;
}
var list = GetLayerPanelInfoList(currentLayer);
foreach (var info in list)
{
//禁止关闭的界面无法获取到
if (info.UIBasePanel.PanelDisClose)
{
continue;
}
//有忽略操作 且满足调节 则这个界面无法获取到
if (ignoreOption != EPanelOption.None &&
(info.UIBasePanel.PanelOption & ignoreOption) != 0)
{
continue;
}
if (layer == EPanelLayer.Any || info.UIBasePanel.Layer == layer)
{
return info;
}
}
}
return null;
}
/// <summary>
/// 关闭这个层级上的最前面的一个UI 异步
/// </summary>
/// <param name="layer">层级</param>
/// <param name="ignoreOption">忽略操作</param>
public async UniTask<bool> CloseLayerTopPanelAsync(EPanelLayer layer,
EPanelOption ignoreOption = EPanelOption.Container)
{
var topPanel = GetTopPanel(layer, ignoreOption);
if (topPanel == null)
{
return false;
}
await ClosePanelAsync(topPanel.Name);
return true;
}
/// <summary>
/// 关闭指定层级上的 最上层UI 同步
/// </summary>
/// <param name="layer">层级</param>
/// <param name="ignoreOption">忽略操作</param>
public void CloseLayerTopPanel(EPanelLayer layer, EPanelOption ignoreOption = EPanelOption.Container)
{
CloseLayerTopPanelAsync(layer, ignoreOption).Forget();
}
/// <summary>
/// 关闭Panel层级上的最上层UI 异步
/// </summary>
public async UniTask<bool> CloseTopPanelAsync()
{
return await CloseLayerTopPanelAsync(EPanelLayer.Panel);
}
/// <summary>
/// 关闭Panel层级上的最上层UI 同步
/// </summary>
public void CloseTopPanel()
{
CloseTopPanelAsync().Forget();
}
/// <summary>
/// 关闭一个窗口
/// </summary>
/// <param name="panelName">名称</param>
/// <param name="tween">是否调用关闭动画</param>
/// <param name="ignoreElse">忽略堆栈操作 -- 不要轻易忽略除非你明白 </param>
public async UniTask ClosePanelAsync(string panelName, bool tween = true, bool ignoreElse = false)
{
#if YIUIMACRO_PANEL_OPENCLOSE
Debug.Log($"<color=yellow> 关闭UI: {panelName} </color>");
#endif
using var asyncLock = await AsyncLockMgr.Inst.Wait(panelName.GetHashCode());
m_PanelCfgMap.TryGetValue(panelName, out var info);
if (info?.UIBasePanel == null) return;
if (info.UIBasePanel.PanelOption.HasFlag(EPanelOption.DisClose))
{
bool allowClose = false; //是否允许关闭
//如果继承禁止关闭接口 可返回是否允许关闭自行处理
if (info.UIBasePanel is IYIUIBanClose disClose)
{
allowClose = disClose.DoBanClose();
}
if (!allowClose)
{
Debug.LogError($"{panelName} 这个界面禁止被关闭 请检查");
return;
}
}
if (info.UIBasePanel is { WindowLastClose: false })
{
await info.UIBasePanel.InternalOnWindowCloseTween(tween);
info.UIBasePanel?.OnWindowClose();
}
if (!ignoreElse)
await RemoveUIAddElse(info);
if (info.UIBasePanel is { WindowLastClose: true })
{
await info.UIBasePanel.InternalOnWindowCloseTween(tween);
info.UIBasePanel?.OnWindowClose();
}
RemoveUI(info);
}
public void ClosePanel(string panelName, bool tween = true, bool ignoreElse = false)
{
ClosePanelAsync(panelName, tween, ignoreElse).Forget();
}
/// <summary>
/// 关闭一个窗口
/// 异步等待关闭动画
/// </summary>
public async UniTask ClosePanelAsync<T>(bool tween = true, bool ignoreElse = false) where T : BasePanel
{
await ClosePanelAsync(GetPanelName<T>(), tween, ignoreElse);
}
/// <summary>
/// 同步关闭窗口
/// 无法等待关闭动画
/// </summary>
public void ClosePanel<T>(bool tween = true, bool ignoreElse = false) where T : BasePanel
{
ClosePanelAsync(GetPanelName<T>(), tween, ignoreElse).Forget();
}
/// <summary>
/// 回到指定的界面 其他界面全部关闭
/// </summary>
/// <param name="homeName">需要被打开的界面 且这个UI是存在的 否则无法打开</param>
/// <param name="tween">动画</param>
public async UniTask HomePanel(string homeName, bool tween = true)
{
#if YIUIMACRO_PANEL_OPENCLOSE
Debug.Log($"<color=yellow> Home关闭其他所有Panel UI: {homeName} </color>");
#endif
m_PanelCfgMap.TryGetValue(homeName, out var homeInfo);
if (homeInfo?.UIBasePanel != null)
{
await RemoveUIToHome(homeInfo, tween);
}
}
public async UniTask HomePanel<T>(bool tween = true)
{
await HomePanel(typeof(T).Name, tween);
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 167bceffde2c4b8a8ab12ec63fb86567
timeCreated: 1682567774

View File

@@ -0,0 +1,95 @@
namespace YIUIFramework
{
public partial class PanelMgr
{
#region Panel
//字符串类型获取 需要自己转换 建议不要使用
public BasePanel GetPanel(string panelName)
{
var info = GetPanelInfo(panelName);
return info?.UIBasePanel;
}
/// <summary>
/// 获取一个panel
/// 必须是存在的 但不一定是打开的有可能是隐藏
/// 这个只能表示对象存在
/// 不应该滥用 UI与UI之间还是应该使用消息通信 这个是为了解决部分问题
/// </summary>
public T GetPanel<T>() where T : BasePanel
{
var info = GetPanelInfo<T>();
if (info is { UIBasePanel: { } })
{
return (T)info.UIBasePanel;
}
return null;
}
#endregion
#region Panel的指定View
//字符串类型获取 需要自己转换 建议不要使用
public BaseView GetPanelView(string panelName, string viewName)
{
var info = GetPanelInfo(panelName);
if (info == null) return null;
if (info.UIBasePanel == null) return null;
var (exist, view) = info.UIBasePanel.ExistView(viewName);
if (exist == false) return null;
return view;
}
/// <summary>
/// 获取指定Panel的指定View
/// 必须是存在的 但不一定是打开的有可能是隐藏
/// 这个只能表示对象存在
/// 不应该滥用 UI与UI之间还是应该使用消息通信 这个是为了解决部分问题
/// </summary>
public TView GetPanelView<TPanel, TView>()
where TPanel : BasePanel
where TView : BaseView
{
var info = GetPanelInfo<TPanel>();
if (info == null) return null;
if (info.UIBasePanel == null) return null;
var (exist, view) = info.UIBasePanel.ExistView<TView>();
if (exist == false) return null;
return (TView)view;
}
//字符串类型获取 需要自己转换 建议不要使用
public BaseView GetPanelViewByViewName<TPanel>(string viewName)
where TPanel : BasePanel
{
var info = GetPanelInfo<TPanel>();
if (info == null) return null;
if (info.UIBasePanel == null) return null;
var (exist, view) = info.UIBasePanel.ExistView(viewName);
if (!exist) return null;
return view;
}
/// <summary>
/// 获取指定Panel的指定View
/// 必须是存在的 但不一定是打开的有可能是隐藏
/// 这个只能表示对象存在
/// 不应该滥用 UI与UI之间还是应该使用消息通信 这个是为了解决部分问题
/// </summary>
public TView GetPanelViewByPanelName<TView>(string panelName)
where TView : BaseView
{
var info = GetPanelInfo(panelName);
if (info == null) return null;
if (info.UIBasePanel == null) return null;
var (exist, view) = info.UIBasePanel.ExistView<TView>();
if (exist == false) return null;
return (TView)view;
}
#endregion
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 7d2722d786bf42dc9e83345dda9c1fd4
timeCreated: 1705238019

View File

@@ -0,0 +1,6 @@
namespace YIUIFramework
{
public partial class PanelMgr
{
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: c7a8218e43994df9831b67c0e5fc8f25
timeCreated: 1682501141

View File

@@ -0,0 +1,94 @@
using System.Collections.Generic;
using Cysharp.Threading.Tasks;
namespace YIUIFramework
{
/// <summary>
/// 打开相关
/// </summary>
public partial class PanelMgr
{
/// <summary>
/// 所有已经打开过的UI
/// K = C#文件名
/// 主要是作为缓存PanelInfo
/// </summary>
private Dictionary<string, PanelInfo> m_PanelCfgMap = new Dictionary<string, PanelInfo>();
/// <summary>
/// 获取PanelInfo
/// 没有则创建 相当于一个打开过了 UI基础配置档
/// 这个根据BindVo创建 为什么没有直接用VO 因为里面有Panel 实例对象
/// 这个k 根据resName
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
private PanelInfo GetPanelInfo<T>() where T : BasePanel
{
var type = typeof(T);
var data = UIBindHelper.GetBindVoByType(type);
if (data == null) return null;
var vo = data.Value;
var name = type.Name;
if (!m_PanelCfgMap.ContainsKey(name))
{
var info = new PanelInfo()
{
Name = name,
PkgName = vo.PkgName,
ResName = vo.ResName,
};
m_PanelCfgMap.Add(name, info);
}
return m_PanelCfgMap[name];
}
/// <summary>
/// 获取UI名称 用字符串开界面 不用类型 减少GC
/// 另外也方便之后有可能需要的扩展 字符串会更好使用
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
private string GetPanelName<T>() where T : BasePanel
{
var panelInfo = GetPanelInfo<T>();
return panelInfo?.Name;
}
/// <summary>
/// 打开之前
/// </summary>
private async UniTask OpenPanelBefore(PanelInfo info)
{
if (!info.UIBasePanel.WindowFirstOpen)
{
await AddUICloseElse(info);
}
}
/// <summary>
/// 打开之后
/// </summary>
private async UniTask<BasePanel> OpenPanelAfter(PanelInfo info, bool success)
{
if (success)
{
if (info.UIBasePanel.WindowFirstOpen)
{
await AddUICloseElse(info);
}
}
else
{
//如果打开失败直接屏蔽
info?.UIBasePanel?.SetActive(false);
info?.UIBasePanel?.Close();
}
return info.UIBasePanel;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 288d1e95dea444ab80be6d5c611faaa0
timeCreated: 1682496758

View File

@@ -0,0 +1,181 @@
using System;
using UnityEngine;
using Cysharp.Threading.Tasks;
namespace YIUIFramework
{
/// <summary>
/// 异步打开
/// </summary>
public partial class PanelMgr
{
private async UniTask<PanelInfo> OpenPanelStartAsync(string panelName)
{
if (string.IsNullOrEmpty(panelName))
{
Debug.LogError($"<color=red> 无法打开 这是一个空名称 </color>");
return null;
}
using var asyncLock = await AsyncLockMgr.Inst.Wait(panelName.GetHashCode());
#if YIUIMACRO_PANEL_OPENCLOSE
Debug.Log($"<color=yellow> 打开UI: {panelName} </color>");
#endif
if (!m_PanelCfgMap.TryGetValue(panelName, out var info))
{
Debug.LogError($"请检查 {panelName} 没有获取到PanelInfo 1. 必须继承IPanel 的才可行 2. 检查是否没有注册上");
return null;
}
if (info.UIBasePanel == null)
{
var uiBase = await YIUIFactory.CreatePanelAsync(info);
if (uiBase == null)
{
Debug.LogError($"面板[{panelName}]没有创建成功packName={info.PkgName}, resName={info.ResName}");
return null;
}
uiBase.SetActive(false);
info.Reset(uiBase);
}
AddUI(info);
return info;
}
public async UniTask<T> OpenPanelAsync<T>()
where T : BasePanel, new()
{
var info = await OpenPanelStartAsync(GetPanelName<T>());
if (info == null) return default;
var success = false;
await OpenPanelBefore(info);
try
{
success = await info.UIBasePanel.Open();
}
catch (Exception e)
{
Debug.LogError($"panel={info.ResName}, err={e.Message}{e.StackTrace}");
}
return (T)await OpenPanelAfter(info, success);
}
public async UniTask<T> OpenPanelAsync<T, P1>(P1 p1)
where T : BasePanel, IYIUIOpen<P1>, new()
{
var info = await OpenPanelStartAsync(GetPanelName<T>());
if (info == null) return default;
var success = false;
await OpenPanelBefore(info);
try
{
success = await info.UIBasePanel.Open(p1);
}
catch (Exception e)
{
Debug.LogError($"panel={info.ResName}, err={e.Message}{e.StackTrace}");
}
return (T)await OpenPanelAfter(info, success);
}
public async UniTask<T> OpenPanelAsync<T, P1, P2>(P1 p1, P2 p2)
where T : BasePanel, IYIUIOpen<P1, P2>, new()
{
var info = await OpenPanelStartAsync(GetPanelName<T>());
if (info == null) return default;
var success = false;
await OpenPanelBefore(info);
try
{
success = await info.UIBasePanel.Open(p1, p2);
}
catch (Exception e)
{
Debug.LogError($"panel={info.ResName}, err={e.Message}{e.StackTrace}");
}
return (T)await OpenPanelAfter(info, success);
}
public async UniTask<T> OpenPanelAsync<T, P1, P2, P3>(P1 p1, P2 p2, P3 p3)
where T : BasePanel, IYIUIOpen<P1, P2, P3>, new()
{
var info = await OpenPanelStartAsync(GetPanelName<T>());
if (info == null) return default;
var success = false;
await OpenPanelBefore(info);
try
{
success = await info.UIBasePanel.Open(p1, p2, p3);
}
catch (Exception e)
{
Debug.LogError($"panel={info.ResName}, err={e.Message}{e.StackTrace}");
}
return (T)await OpenPanelAfter(info, success);
}
public async UniTask<T> OpenPanelAsync<T, P1, P2, P3, P4>(P1 p1, P2 p2, P3 p3, P4 p4)
where T : BasePanel, IYIUIOpen<P1, P2, P3, P4>, new()
{
var info = await OpenPanelStartAsync(GetPanelName<T>());
if (info == null) return default;
var success = false;
await OpenPanelBefore(info);
try
{
success = await info.UIBasePanel.Open(p1, p2, p3, p4);
}
catch (Exception e)
{
Debug.LogError($"panel={info.ResName}, err={e.Message}{e.StackTrace}");
}
return (T)await OpenPanelAfter(info, success);
}
public async UniTask<T> OpenPanelAsync<T, P1, P2, P3, P4, P5>(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5)
where T : BasePanel, IYIUIOpen<P1, P2, P3, P4, P5>, new()
{
var info = await OpenPanelStartAsync(GetPanelName<T>());
if (info == null) return default;
var success = false;
await OpenPanelBefore(info);
try
{
success = await info.UIBasePanel.Open(p1, p2, p3, p4, p5);
}
catch (Exception e)
{
Debug.LogError($"panel={info.ResName}, err={e.Message}{e.StackTrace}");
}
return (T)await OpenPanelAfter(info, success);
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: dc47078c71a84f5ca2e3ebe2e7d3c531
timeCreated: 1683624447

View File

@@ -0,0 +1,121 @@
using System;
using UnityEngine;
using Cysharp.Threading.Tasks;
namespace YIUIFramework
{
/// <summary>
/// 字符串异步打开
/// </summary>
public partial class PanelMgr
{
/// <summary>
/// 获取PanelInfo
/// 没有则创建 相当于一个打开过了 UI基础配置档
/// 这个根据BindVo创建 为什么没有直接用VO 因为里面有Panel 实例对象
/// 这个k 根据resName
/// </summary>
private PanelInfo GetPanelInfo(string panelName)
{
var data = UIBindHelper.GetBindVoByPanelName(panelName);
if (data == null) return null;
var vo = data.Value;
if (!m_PanelCfgMap.ContainsKey(panelName))
{
var info = new PanelInfo()
{
Name = panelName,
PkgName = vo.PkgName,
ResName = vo.ResName,
};
m_PanelCfgMap.Add(panelName, info);
}
return m_PanelCfgMap[panelName];
}
/// <summary>
/// 用字符串开启 必须保证类名与资源名一致否则无法找到
/// 首选使用<T>泛型方法打开UI 字符串只适合于特定场合使用
/// </summary>
public async UniTask<BasePanel> OpenPanelAsync(string panelName, object param = null)
{
var info = GetPanelInfo(panelName);
if (info == null) return default;
var panel = await OpenPanelStartAsync(panelName);
if (panel == null) return default;
var success = false;
await OpenPanelBefore(info);
try
{
var p = ParamVo.Get(param);
success = await info.UIBasePanel.Open(p);
ParamVo.Put(p);
}
catch (Exception e)
{
Debug.LogError($"panel={info.ResName}, err={e.Message}{e.StackTrace}");
}
return await OpenPanelAfter(info, success);
}
public async UniTask<BasePanel> OpenPanelAsync(string panelName, object param1, object param2)
{
var paramList = ListPool<object>.Get();
paramList.Add(param1);
paramList.Add(param2);
var panel = await OpenPanelAsync(panelName, paramList);
ListPool<object>.Put(paramList);
return panel;
}
public async UniTask<BasePanel> OpenPanelAsync(string panelName, object param1, object param2, object param3)
{
var paramList = ListPool<object>.Get();
paramList.Add(param1);
paramList.Add(param2);
paramList.Add(param3);
var panel = await OpenPanelAsync(panelName, paramList);
ListPool<object>.Put(paramList);
return panel;
}
public async UniTask<BasePanel> OpenPanelAsync(string panelName, object param1, object param2, object param3,
object param4)
{
var paramList = ListPool<object>.Get();
paramList.Add(param1);
paramList.Add(param2);
paramList.Add(param3);
paramList.Add(param4);
var panel = await OpenPanelAsync(panelName, paramList);
ListPool<object>.Put(paramList);
return panel;
}
public async UniTask<BasePanel> OpenPanelAsync(string panelName, object param1, object param2, object param3,
object param4, params object[] paramMore)
{
var paramList = ListPool<object>.Get();
paramList.Add(param1);
paramList.Add(param2);
paramList.Add(param3);
paramList.Add(param4);
if (paramMore.Length > 0)
{
paramList.AddRange(paramMore);
}
var panel = await OpenPanelAsync(panelName, paramList);
ListPool<object>.Put(paramList);
return panel;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: a6dd836e26064f07b54d03aded870a65
timeCreated: 1683626146

View File

@@ -0,0 +1,47 @@
using Cysharp.Threading.Tasks;
namespace YIUIFramework
{
/// <summary>
/// 打开泛型 同步方法 内部还是异步打开
/// 不想提供快捷操作可以删除此类
/// </summary>
public partial class PanelMgr
{
public void OpenPanel<T>()
where T : BasePanel, new()
{
OpenPanelAsync<T>().Forget();
}
public void OpenPanel<T, P1>(P1 p1)
where T : BasePanel, IYIUIOpen<P1>, new()
{
OpenPanelAsync<T, P1>(p1).Forget();
}
public void OpenPanel<T, P1, P2>(P1 p1, P2 p2)
where T : BasePanel, IYIUIOpen<P1, P2>, new()
{
OpenPanelAsync<T, P1, P2>(p1, p2).Forget();
}
public void OpenPanel<T, P1, P2, P3>(P1 p1, P2 p2, P3 p3)
where T : BasePanel, IYIUIOpen<P1, P2, P3>, new()
{
OpenPanelAsync<T, P1, P2, P3>(p1, p2, p3).Forget();
}
public void OpenPanel<T, P1, P2, P3, P4>(P1 p1, P2 p2, P3 p3, P4 p4)
where T : BasePanel, IYIUIOpen<P1, P2, P3, P4>, new()
{
OpenPanelAsync<T, P1, P2, P3, P4>(p1, p2, p3, p4).Forget();
}
public void OpenPanel<T, P1, P2, P3, P4, P5>(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5)
where T : BasePanel, IYIUIOpen<P1, P2, P3, P4, P5>, new()
{
OpenPanelAsync<T, P1, P2, P3, P4, P5>(p1, p2, p3, p4, p5).Forget();
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 474b6909bd0148c187aa0e2c79891441
timeCreated: 1685587583

View File

@@ -0,0 +1,35 @@
using Cysharp.Threading.Tasks;
namespace YIUIFramework
{
public partial class PanelMgr
{
//非特殊需求 应该尽量使用异步操作
//同步 无法获得返回值
public void OpenPanel(string panelName, object param = null)
{
OpenPanelAsync(panelName, param).Forget();
}
public void OpenPanel(string panelName, object param1, object param2)
{
OpenPanelAsync(panelName, param1, param2).Forget();
}
public void OpenPanel(string panelName, object param1, object param2, object param3)
{
OpenPanelAsync(panelName, param1, param2, param3).Forget();
}
public void OpenPanel(string panelName, object param1, object param2, object param3, object param4)
{
OpenPanelAsync(panelName, param1, param2, param3, param4).Forget();
}
public void OpenPanel(string panelName, object param1, object param2, object param3, object param4,
params object[] paramMore)
{
OpenPanelAsync(panelName, param1, param2, param3, param4, paramMore).Forget();
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 22df9686773749298918198b242e26cd
timeCreated: 1683011560

View File

@@ -0,0 +1,222 @@
using System.Collections.Generic;
using Cysharp.Threading.Tasks;
using YIUIBind;
using UnityEngine;
using UnityEngine.UI;
using Object = UnityEngine.Object;
namespace YIUIFramework
{
/// <summary>
/// UIRoot
/// </summary>
public partial class PanelMgr
{
public GameObject UIRoot;
public GameObject UICanvasRoot;
public RectTransform UILayerRoot;
public Camera UICamera;
public Canvas UICanvas;
public const int DesignScreenWidth = 1920;
public const int DesignScreenHeight = 1080;
public const float DesignScreenWidth_F = 1920f;
public const float DesignScreenHeight_F = 1080f;
private const int RootPosOffset = 1000;
private const int LayerDistance = 1000;
#region
public const string UIRootName = "YIUIRoot";
public const string UILayerRootName = "YIUILayerRoot";
public const string UIRootPkgName = "Common";
#endregion
//K1 = 层级枚举 V1 = 层级对应的rect
//List = 当前层级中的当前所有UI 前面的代表这个UI在前面以此类推
private Dictionary<EPanelLayer, Dictionary<RectTransform, List<PanelInfo>>> m_AllPanelLayer =
new Dictionary<EPanelLayer, Dictionary<RectTransform, List<PanelInfo>>>();
private async UniTask<bool> InitRoot()
{
#region UICanvasRoot
UIRoot = GameObject.Find(UIRootName);
if (UIRoot == null)
{
UIRoot = await YIUILoadHelper.LoadAssetAsyncInstantiate(UIRootPkgName, UIRootName);
}
if (UIRoot == null)
{
Debug.LogError($"初始化错误 没有找到UIRoot");
return false;
}
UIRoot.name = UIRoot.name.Replace("(Clone)", "");
Object.DontDestroyOnLoad(UIRoot);
UIRoot.transform.position = new Vector3(RootPosOffset, RootPosOffset, 0); //root可修改位置防止与世界3D场景重叠导致不好编辑
UICanvas = UIRoot.GetComponentInChildren<Canvas>();
if (UICanvas == null)
{
Debug.LogError($"初始化错误 没有找到Canvas");
return false;
}
UICanvasRoot = UICanvas.gameObject;
UILayerRoot = UICanvasRoot.transform.FindChildByName(UILayerRootName)?.GetComponent<RectTransform>();
if (UILayerRoot == null)
{
Debug.LogError($"初始化错误 没有找到UILayerRoot");
return false;
}
UICamera = UICanvasRoot.GetComponentInChildren<Camera>();
if (UICamera == null)
{
Debug.LogError($"初始化错误 没有找到UICamera");
return false;
}
var canvas = UICanvasRoot.GetComponent<Canvas>();
if (canvas == null)
{
Debug.LogError($"初始化错误 没有找到UICanvasRoot - Canvas");
return false;
}
canvas.renderMode = RenderMode.ScreenSpaceCamera;
canvas.worldCamera = UICamera;
var canvasScaler = UICanvasRoot.GetComponent<CanvasScaler>();
if (canvasScaler == null)
{
Debug.LogError($"初始化错误 没有找到UICanvasRoot - CanvasScaler");
return false;
}
canvasScaler.uiScaleMode = CanvasScaler.ScaleMode.ScaleWithScreenSize;
canvasScaler.referenceResolution = new Vector2(DesignScreenWidth, DesignScreenHeight);
#endregion
//分层
const int len = (int)EPanelLayer.Count;
m_AllPanelLayer.Clear();
for (var i = len - 1; i >= 0; i--)
{
var layer = new GameObject($"Layer{i}-{(EPanelLayer)i}");
var rect = layer.AddComponent<RectTransform>();
rect.SetParent(UILayerRoot);
rect.localScale = Vector3.one;
rect.pivot = new Vector2(0.5f, 0.5f);
rect.anchorMax = Vector2.one;
rect.anchorMin = Vector2.zero;
rect.sizeDelta = Vector2.zero;
rect.localRotation = Quaternion.identity;
rect.localPosition = new Vector3(0, 0, i * LayerDistance); //这个是为了3D模型时穿插的问题
var rectDic = new Dictionary<RectTransform, List<PanelInfo>> { { rect, new List<PanelInfo>() } };
m_AllPanelLayer.Add((EPanelLayer)i, rectDic);
}
InitAddUIBlock(); //所有层级初始化后添加一个终极屏蔽层 可根据API 定时屏蔽UI操作
UICamera.transform.localPosition =
new Vector3(UILayerRoot.localPosition.x, UILayerRoot.localPosition.y, -LayerDistance);
UICamera.clearFlags = CameraClearFlags.Depth;
UICamera.orthographic = true;
//根据需求可以修改摄像机的远剪裁平面大小 没必要设置的很大
//UICamera.farClipPlane = ((len + 1) * LayerDistance) * UICanvasRoot.transform.localScale.x;
return true;
}
private void ResetRoot()
{
for (int i = UILayerRoot.transform.childCount - 1; i >= 0; i--)
{
UnityEngine.Object.Destroy(UILayerRoot.transform.GetChild(i).gameObject);
}
}
#region
private RectTransform m_UICache;
public RectTransform UICache
{
get
{
if (m_UICache == null)
{
m_UICache = GetLayerRect(EPanelLayer.Cache);
}
return m_UICache;
}
}
private RectTransform m_UIPanel;
public RectTransform UIPanel
{
get
{
if (m_UIPanel == null)
{
m_UIPanel = GetLayerRect(EPanelLayer.Panel);
}
return m_UIPanel;
}
}
#endregion
public RectTransform GetLayerRect(EPanelLayer panelLayer)
{
m_AllPanelLayer.TryGetValue(panelLayer, out var rectDic);
if (rectDic == null)
{
Debug.LogError($"没有这个层级 请检查 {panelLayer}");
return null;
}
//只能有一个所以返回第一个
foreach (var rect in rectDic.Keys)
{
return rect;
}
return null;
}
private List<PanelInfo> GetLayerPanelInfoList(EPanelLayer panelLayer)
{
m_AllPanelLayer.TryGetValue(panelLayer, out var rectDic);
if (rectDic == null)
{
Debug.LogError($"没有这个层级 请检查 {panelLayer}");
return null;
}
//只能有一个所以返回第一个
foreach (var infoList in rectDic.Values)
{
return infoList;
}
return null;
}
private bool RemoveLayerPanelInfo(EPanelLayer panelLayer, PanelInfo panelInfo)
{
var list = GetLayerPanelInfoList(panelLayer);
return list != null && list.Remove(panelInfo);
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 9ecb408c3ce249da88137f17b4a71966
timeCreated: 1682501162

View File

@@ -0,0 +1,77 @@
using System;
using UnityEngine;
namespace YIUIFramework
{
/// <summary>
/// 安全区 刘海屏
/// </summary>
public partial class PanelMgr
{
/// <summary>
/// 在刘海屏机子时,是否打开黑边
/// </summary>
public const bool OpenBlackBorder = false;
//启用2倍安全 则左右2边都会裁剪
public const bool DoubleSafe = false;
//安全区
private static Rect g_SafeArea;
/// <summary>
/// 安全区
/// </summary>
public static Rect SafeArea => g_SafeArea;
/// <summary>
/// 横屏设置时,界面左边离屏幕的距离
/// </summary>
public static float SafeAreaLeft => Screen.orientation == ScreenOrientation.LandscapeRight
? Screen.width - g_SafeArea.xMax
: g_SafeArea.x;
private ScreenOrientation ScreenOrientation = Screen.orientation;
private void InitSafeArea()
{
var safeAreaX = Math.Max(Screen.safeArea.x, Screen.width - Screen.safeArea.xMax);
var safeAreaY = Math.Max(Screen.safeArea.y, Screen.height - Screen.safeArea.yMax);
#if UNITY_EDITOR
//safeAreaX = 100;
//safeAreaY = 100;
#endif
g_SafeArea = new Rect(
safeAreaX,
safeAreaY,
DesignScreenWidth_F - GetSafeValue(safeAreaX),
DesignScreenHeight_F - GetSafeValue(safeAreaY));
InitUISafeArea();
}
private float GetSafeValue(float safeValue)
{
return DoubleSafe ? safeValue * 2 : safeValue;
}
private void InitUISafeArea()
{
UILayerRoot.anchoredPosition = new Vector2(SafeArea.x, -SafeArea.y);
if (DoubleSafe)
{
UILayerRoot.offsetMax = new Vector2(-SafeArea.x, UILayerRoot.offsetMax.y);
UILayerRoot.offsetMin = new Vector2(UILayerRoot.offsetMin.x, SafeArea.y);
}
else
{
//TODO 单边时需要考虑手机是左还是右
UILayerRoot.offsetMax = new Vector2(0, UILayerRoot.offsetMax.y);
UILayerRoot.offsetMin = new Vector2(UILayerRoot.offsetMin.x, 0);
}
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 6d3db2f7d94640ab99edaf0f6527f8c9
timeCreated: 1682500371