using System.Collections.Generic; using System.Diagnostics; using Debug = UnityEngine.Debug; namespace YIUIFramework { public static class RedDotStackHelper { #region 操作 static readonly string m_OsCountFormat = "自己改变数量 {0} >> {1}"; static readonly string m_OsTipsFormat = "自己改变提示 {0} >> {1} >> {2}"; static readonly string m_OsChildCountFormat = "有子类改变数量 {0} >> {1}"; static readonly string m_OsChildTipsFormat = "有子类改变提示 {0} >> {1} >> {2}"; /// /// 获取操作拼接 /// public static string GetOS(this RedDotStack self, RedDotData currentData) { var sb = SbPool.Get(); switch (self.RedDotOSType) { case ERedDotOSType.Count: sb.AppendFormat(self.FirstData.ChangeData.Key == currentData.Key ? m_OsCountFormat : m_OsChildCountFormat, self.OriginalCount, self.ChangeCount); break; case ERedDotOSType.Tips: sb.AppendFormat(self.FirstData.ChangeData.Key == currentData.Key ? m_OsTipsFormat : m_OsChildTipsFormat, self.ChangeTips, self.OriginalCount, self.ChangeCount); break; default: Debug.LogError("此枚举没有实现 " + self.RedDotOSType); break; } return SbPool.PutAndToStr(sb); } #endregion #region 时间 static readonly string m_TimeFormat = "{0:D2}/{1:D2}/{2:D2} - {3:D2}:{4:D2}:{5:D2}"; /// /// 获取操作时间 /// public static string GetTime(this RedDotStack self) { var time = self.DataTime; var sb = SbPool.Get(); sb.AppendFormat(m_TimeFormat, time.Year, time.Month, time.Day, time.Hour, time.Minute, time.Second); return SbPool.PutAndToStr(sb); } #endregion #region 来源 static readonly string m_SourceFormat = "改变的红点ID: {0} 名称: {1}"; static readonly string m_SourceCountFormat = " 当前提示: {0} >> {1} >> {2}"; /// /// 来源 /// public static string GetSource(this RedDotStack self) { var data = self.FirstData; var sb = SbPool.Get(); sb.AppendFormat(m_SourceFormat, data.ChangeData.Config.Key, RedDotMgr.Inst.GetKeyDes(data.ChangeData.Config.Key)); sb.AppendFormat(m_SourceCountFormat, data.ChangeTips, data.OriginalCount, data.ChangeCount); return SbPool.PutAndToStr(sb); } #endregion #region 详细堆栈 带缓存 /// /// 缓存堆栈解析数据 /// private static Dictionary m_StackContentDic = new Dictionary(); private static void ClearStackContentDic() { m_StackContentDic.Clear(); } #region 存储的值 private static BoolPrefs g_StackHideUnityEngineBoolPrefs = new BoolPrefs("RedDot_StackHideUnityEngine", null, true); public static bool StackHideUnityEngine { get => g_StackHideUnityEngineBoolPrefs.Value; set { g_StackHideUnityEngineBoolPrefs.Value = value; ClearStackContentDic(); } } private static BoolPrefs g_StackHideYIUIBindBoolPrefs = new BoolPrefs("RedDot_StackHideYIUIBind", null, true); public static bool StackHideYIUIBind { get => g_StackHideYIUIBindBoolPrefs.Value; set { g_StackHideYIUIBindBoolPrefs.Value = value; ClearStackContentDic(); } } private static BoolPrefs g_StackHideYIUIFrameworkBoolPrefs = new BoolPrefs("RedDot_StackHideYIUIFramework", null, true); public static bool StackHideYIUIFramework { get => g_StackHideYIUIFrameworkBoolPrefs.Value; set { g_StackHideYIUIFrameworkBoolPrefs.Value = value; ClearStackContentDic(); } } private static BoolPrefs g_ShowStackIndexBoolPrefs = new BoolPrefs("RedDot_ShowStackIndex", null, false); public static bool ShowStackIndex { get => g_ShowStackIndexBoolPrefs.Value; set { g_ShowStackIndexBoolPrefs.Value = value; ClearStackContentDic(); } } private static BoolPrefs g_ShowFileNameStackBoolPrefs = new BoolPrefs("RedDot_ShowFileNameStack", null, true); public static bool ShowFileNameStack { get => g_ShowFileNameStackBoolPrefs.Value; set { g_ShowFileNameStackBoolPrefs.Value = value; ClearStackContentDic(); } } private static BoolPrefs g_ShowFilePathBoolPrefs = new BoolPrefs("RedDot_ShowFilePath", null, false); public static bool ShowFilePath { get => g_ShowFilePathBoolPrefs.Value; set { g_ShowFilePathBoolPrefs.Value = value; ClearStackContentDic(); } } #endregion /// /// 根据堆栈 获取到已经解析后的详细信息 /// public static string GetStackContent(this RedDotStack self) { var stackTrace = self.StackTrace; m_StackContentDic.TryGetValue(stackTrace, out var content); if (content != null) { return content; } content = AnalysisStack(stackTrace); if (string.IsNullOrEmpty(content)) { content = "无堆栈显示 可能都被屏蔽了"; } m_StackContentDic.Add(stackTrace, content); return content; } static readonly string m_FrameFormat = "{0} {1}.{2} : {3} : {4}"; static readonly string m_FileFormat = "\tFile: {0}"; static readonly string m_StackContinueUnityEngine = "UnityEngine"; static readonly string m_StackContinueUnityEngineTMP = "TMP"; static readonly string m_StackContinueYIUIBind = "YIUIBind"; static readonly string m_StackContinueYIUIFramework = "YIUIFramework"; /// /// 解析堆栈 /// 会隐藏 某些堆栈 /// private static string AnalysisStack(StackTrace stackTrace) { var sb = SbPool.Get(); var stackFrames = stackTrace.GetFrames(); if (stackFrames != null) { for (int i = 0; i < stackFrames.Length; i++) { var stackFrame = stackFrames[i]; var method = stackFrame.GetMethod(); var declaring = method.DeclaringType; if (declaring == null) { continue; } var stackNamespace = declaring.Namespace ?? ""; //命名空间 var className = declaring.Name; //类名 if (StackHideUnityEngine) { if (stackNamespace.Contains(m_StackContinueUnityEngine)) { continue; } if (stackNamespace.Contains(m_StackContinueUnityEngineTMP)) { continue; } } if (StackHideYIUIBind) { if (stackNamespace.Contains(m_StackContinueYIUIBind)) { continue; } } if (StackHideYIUIFramework) { if (stackNamespace.Contains(m_StackContinueYIUIFramework)) { continue; } } sb.Append(string.Format(m_FrameFormat, ShowStackIndex ? i.ToString() : "", //堆栈索引 stackNamespace, //命名空间 className, //类名 method.Name, //方法名 stackFrame.GetFileLineNumber().ToString())); //所在行数 //所在的文件路径 if (ShowFileNameStack) { var fileName = stackFrame.GetFileName(); if (string.IsNullOrEmpty(fileName)) { continue; } sb.AppendLine(); if (ShowFilePath) { sb.Append(string.Format(m_FileFormat, fileName)); } else { var filePathArray = fileName.Split('\\'); sb.Append(string.Format(m_FileFormat, filePathArray[filePathArray.Length - 1])); } } sb.AppendLine(); sb.AppendLine(); } } return SbPool.PutAndToStr(sb); } #endregion } }