初始化

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,3 @@
fileFormatVersion: 2
guid: e3594b483cf74321833ca582d8c0fce0
timeCreated: 1687140416

View File

@@ -0,0 +1,56 @@
using Sirenix.OdinInspector;
using TMPro;
using UnityEngine;
namespace YIUIFramework
{
public class RedDotBind : MonoBehaviour
{
[SerializeField]
[LabelText("文本")]
private TextMeshProUGUI m_Text;
[SerializeField]
[LabelText("红点枚举")]
[EnableIf("@UIOperationHelper.CommonShowIf()")]
private ERedDotKeyType m_Key;
public ERedDotKeyType Key => m_Key;
[ShowInInspector]
[ReadOnly]
[LabelText("显影")]
public bool Show { get; private set; }
[ShowInInspector]
[ReadOnly]
[LabelText("数量")]
public int Count { get; private set; }
private void Awake()
{
RedDotMgr.Inst?.AddChanged(Key, OnRedDotChangeHandler);
}
private void OnDestroy()
{
if (SingletonMgr.Disposing)
return;
RedDotMgr.Inst?.RemoveChanged(Key, OnRedDotChangeHandler);
}
private void OnRedDotChangeHandler(int count)
{
Show = count >= 1;
Count = count;
Refresh();
}
private void Refresh()
{
gameObject.SetActive(Show);
if (m_Text != null)
m_Text.text = Count.ToString();
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 3d70f63b11f84bb6b4b14aa53c80ddb9
timeCreated: 1687141098

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 90a72f32bc1444b98e68a283c07cad0e
timeCreated: 1686713959

View File

@@ -0,0 +1,25 @@
using System.Collections.Generic;
using Sirenix.OdinInspector;
using Sirenix.Serialization;
namespace YIUIFramework
{
//[CreateAssetMenu(fileName = "RedDotConfigAsset", menuName = "YIUI/RedDot/RedDotConfigAsset", order = 2)]
[LabelText("红点关系配置资源")]
public class RedDotConfigAsset : SerializedScriptableObject
{
[OdinSerialize]
[ReadOnly]
[ShowInInspector]
internal Dictionary<ERedDotKeyType, RedDotConfigData> m_AllRedDotConfigDic =
new Dictionary<ERedDotKeyType, RedDotConfigData>();
public IReadOnlyDictionary<ERedDotKeyType, RedDotConfigData> AllRedDotConfigDic => m_AllRedDotConfigDic;
public RedDotConfigData GetConfigData(ERedDotKeyType key)
{
m_AllRedDotConfigDic.TryGetValue(key, out var value);
return value;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 45535728f0f947f9a2e9c2262eaec459
timeCreated: 1686714322

View File

@@ -0,0 +1,32 @@
using System;
using System.Collections.Generic;
using Sirenix.OdinInspector;
using Sirenix.Serialization;
namespace YIUIFramework
{
[HideLabel]
[HideReferenceObjectPicker]
[Serializable]
public class RedDotConfigData
{
[LabelText("Key")]
[ShowInInspector]
[OdinSerialize]
public ERedDotKeyType Key { get; internal set; } = ERedDotKeyType.None;
[LabelText("所有父级列表")]
[ShowInInspector]
[OdinSerialize]
public List<ERedDotKeyType> ParentList { get; internal set; } = new List<ERedDotKeyType>();
[LabelText("是否允许开关提示")]
[ShowInInspector]
[OdinSerialize]
public bool SwitchTips { get; internal set; } = true; //true = 玩家可开关 false = 不可开关 (永久提示)
internal RedDotConfigData()
{
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: e97bf195316a469d952769645a25ac7a
timeCreated: 1686714172

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 46b62d94079b4a80ab67a85cfb702adc
timeCreated: 1686829112

View File

@@ -0,0 +1,16 @@
using Sirenix.OdinInspector;
namespace YIUIFramework
{
/// <summary>
/// 操作类型
/// </summary>
public enum ERedDotOSType
{
[LabelText("改变数量")]
Count = 0,
[LabelText("改变提示")]
Tips = 1,
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: a9fb33275fae48c38deba2338386caae
timeCreated: 1686829505

View File

@@ -0,0 +1,45 @@
namespace YIUIFramework
{
/// <summary>
/// 第一个改变的数据
/// 在整个修改堆栈中 一个红点数据因为是连锁的 所以
/// 这里的第一个改变数据是指 发起改变的红点是谁
/// </summary>
public class FirstRedDotChangeData
{
/// <summary>
/// 第一个改变的数据
/// </summary>
public RedDotData ChangeData { get; internal set; }
/// <summary>
/// 第一个改变的 本来数量
/// </summary>
public int OriginalCount { get; internal set; }
/// <summary>
/// 第一个改变的 改变数量
/// </summary>
public int ChangeCount { get; internal set; }
/// <summary>
/// 第一个改变的 当前是否提示
/// </summary>
public bool ChangeTips { get; internal set; }
internal FirstRedDotChangeData()
{
}
public FirstRedDotChangeData(RedDotData changeData,
int originalCount,
int changeCount,
bool changeTips)
{
ChangeData = changeData;
OriginalCount = originalCount;
ChangeCount = changeCount;
ChangeTips = changeTips;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: bf70fba40b164c5b88bfb44d855e5c14
timeCreated: 1686829479

View File

@@ -0,0 +1,312 @@
using System;
using System.Collections.Generic;
using UnityEngine;
namespace YIUIFramework
{
/// <summary>
/// 每个具体红点的 运行时数据
/// </summary>
public partial class RedDotData
{
/// <summary>
/// Key
/// </summary>
public ERedDotKeyType Key => Config.Key;
/// <summary>
/// 配置
/// </summary>
public RedDotConfigData Config { get; private set; }
/// <summary>
/// 操作堆栈
/// </summary>
public List<RedDotStack> StackList { get; private set; }
/// <summary>
/// 我的所有父级
/// </summary>
public HashSet<RedDotData> ParentList { get; private set; }
/// <summary>
/// 我的所有子级
/// </summary>
public HashSet<RedDotData> ChildList { get; private set; }
/// <summary>
/// 红点改变通知
/// </summary>
private Action<int> m_OnChangedAction;
/// <summary>
/// 当前是否提示
/// </summary>
public bool Tips { get; private set; }
/// <summary>
/// 当前红点的真实数量
/// </summary>
public int RealCount { get; private set; }
/// <summary>
/// 当前红点数量 如果关闭了红点永远=0
/// </summary>
public int Count => Tips ? RealCount : 0;
/// <summary>
/// 本地存储的唯一K
/// </summary>
private string m_PlayerTipsKey;
/// <summary>
/// 本地存储的值
/// </summary>
private BoolPrefs m_PlayerTipsKeyBoolPrefs;
private RedDotData()
{
}
internal RedDotData(RedDotConfigData config)
{
Config = config;
ParentList = new HashSet<RedDotData>();
ChildList = new HashSet<RedDotData>();
InitTips();
#if UNITY_EDITOR || YIUIMACRO_REDDOT_STACK
StackList = new List<RedDotStack>();
#endif
}
/// <summary>
/// 初始化 当前红点是否可显示
/// </summary>
private void InitTips()
{
//如果配置档中不允许开关提示 那么这个提示永远 = true 且不可修改
if (!Config.SwitchTips)
{
Tips = true;
return;
}
m_PlayerTipsKey = $"PlayerRedDotTips_{(int)Config.Key}";
m_PlayerTipsKeyBoolPrefs = new BoolPrefs(m_PlayerTipsKey, null, Config.SwitchTips);
Tips = m_PlayerTipsKeyBoolPrefs.Value;
}
internal void DeletePlayerTipsPrefs()
{
m_PlayerTipsKeyBoolPrefs.Delete();
}
/// <summary>
/// 添加父级对象
/// </summary>
internal bool AddParent(RedDotData data)
{
//所有父子关联关系 都在编辑器中检查完成
//要保证不会出现循环引用关系
ParentList.Add(data); //目标设定为我的父级
return data.AddChild(this); //因为他是我的父级所以我为他的子级
}
/// <summary>
/// 添加子对象
/// </summary>
private bool AddChild(RedDotData data)
{
return ChildList.Add(data);
}
/// <summary>
/// 这个是实时同步修改
/// 目前使用脏标修改 防止有人同步过快
/// 没有子级 说明是最后一级 最后一级才可以设置
/// </summary>
internal bool TrySetCount(int count)
{
if (ChildList.Count <= 0)
{
return SetCount(count);
}
Debug.LogError($"{Config.Key} 配置 不是最后一级红点 请不要直接修改");
return false;
}
/// <summary>
/// 设置当前红点数量
/// 返回值 false = 没有变化
/// </summary>
private bool SetCount(int count, RedDotStack stack = null)
{
if (RealCount == count)
{
return false;
}
#if UNITY_EDITOR || YIUIMACRO_REDDOT_STACK
if (stack == null)
{
var firstData = new FirstRedDotChangeData(this, RealCount, count, Tips);
stack = AddNewStack(ERedDotOSType.Count, RealCount, count, Tips, firstData);
}
else
{
AddStack(stack);
}
#endif
RealCount = count;
NotifyChange(stack);
return true;
}
/// <summary>
/// 通知父级 自己变化了
/// 此处会递归 直到没有父级
/// </summary>
private void NotifyChange(RedDotStack stack)
{
InvokeOnChanged();
foreach (var parent in ParentList)
{
parent.ChildChanged(stack);
}
}
/// <summary>
/// 子对象变化了
/// 然后自己变化 然后又通知递归
/// </summary>
private void ChildChanged(RedDotStack stack)
{
var count = 0;
foreach (var child in ChildList)
{
count += child.Count;
}
SetCount(count, stack);
}
/// <summary>
/// 设置当前是否提示
/// </summary>
internal bool SetTips(bool tips, RedDotStack stack = null)
{
if (!Config.SwitchTips)
{
Debug.LogError($"{Config.Key} 配置 关闭了红点的开关提示 目前永久提示 禁止修改 ");
return false;
}
if (Tips == tips)
{
return false;
}
Tips = tips;
#if UNITY_EDITOR || YIUIMACRO_REDDOT_STACK
if (stack == null)
{
var firstData = new FirstRedDotChangeData(this, RealCount, Count, Tips);
stack = AddNewStack(ERedDotOSType.Tips, RealCount, Count, Tips, firstData);
}
else
{
AddStack(stack);
}
#endif
m_PlayerTipsKeyBoolPrefs.Value = tips; //存储到本地
NotifyChange(stack); //提示改变后 通知 监听改变
return true;
}
/// <summary>
/// 添加一个回调
/// int = 当前红点数量 (非真实数量)
/// 并马上设置相关数据
/// (因为界面初始化时都是需要刷新界面的 所以默认调用一次)
/// </summary>
internal void AddOnChanged(Action<int> action)
{
m_OnChangedAction += action;
InvokeOnChanged();
}
/// <summary>
/// 移除回调
/// </summary>
/// <param name="action"></param>
internal void RemoveChanged(Action<int> action)
{
m_OnChangedAction -= action;
}
//try回调
private void InvokeOnChanged()
{
try
{
//回调不会使用真实数量
m_OnChangedAction?.Invoke(Count);
}
catch (Exception e)
{
Debug.LogError($"红点改变回调 try报错 请检查原因 {Key} {e}");
}
}
#if UNITY_EDITOR || YIUIMACRO_REDDOT_STACK
//因为有堆栈操作的需求 所以还是有可能 同一时间刷新2个节点 他们都有相同的路线时 会被刷新2次
//因为需要这2次的堆栈操作信息 如果去掉堆栈 可以合并 TODO
/// <summary>
/// 添加操作堆栈
/// 目前只有在编辑器下执行 以后可能修改成一个可开关的 这样在手机上也可以查看 debug模式
/// </summary>
private RedDotStack AddNewStack(
ERedDotOSType osType,
int originalCount,
int changeCount,
bool changeTips,
FirstRedDotChangeData firstData)
{
var stack = new RedDotStack
{
Id = StackList.Count + 1,
DataTime = DateTime.Now,
StackTrace = new System.Diagnostics.StackTrace(true),
RedDotOSType = osType,
OriginalCount = originalCount,
ChangeCount = changeCount,
ChangeTips = changeTips,
FirstData = firstData,
};
//新的在前 其他地方就不用翻转数据了
StackList.Insert(0, stack);
return stack;
}
private void AddStack(RedDotStack stack)
{
StackList.Insert(0, stack);
}
#endif
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 8a7cf1bfcd76490dad0bc5f2c06b6f71
timeCreated: 1686829122

View File

@@ -0,0 +1,95 @@
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace YIUIFramework
{
public partial class RedDotData
{
//已改变的脏标记
private bool m_ChangeDirty;
//即将改变的值
private int m_DirtyCount = -1;
//脏数据堆栈
private RedDotStack m_DirtyStack;
//脏数据第一个改变的数据
private FirstRedDotChangeData m_DirtyFirstRedDotChangeData;
/// <summary>
/// 脏数据设置数量
/// </summary>
internal bool TryDirtySetCount(int count)
{
if (ChildList.Count <= 0)
{
if (RealCount == count) //与现在真实数据相同 不需要改变
{
ResetDirty();
return false;
}
m_ChangeDirty = true;
m_DirtyCount = count;
SetDirtyOS(count);
return true;
}
Debug.LogError($"{Key} 配置 不是最后一级红点 请不要直接修改");
return false;
}
//刷新脏数据
internal void RefreshDirtyCount()
{
if (!m_ChangeDirty)
{
Debug.LogError($"{Key} 没有脏标 请勿调用此方法");
return;
}
SetCount(m_DirtyCount, m_DirtyStack);
ResetDirty();
}
private void SetDirtyOS(int count)
{
#if UNITY_EDITOR || YIUIMACRO_REDDOT_STACK
m_DirtyFirstRedDotChangeData ??= new FirstRedDotChangeData();
{
m_DirtyFirstRedDotChangeData.ChangeData = this;
m_DirtyFirstRedDotChangeData.OriginalCount = RealCount;
m_DirtyFirstRedDotChangeData.ChangeCount = count;
m_DirtyFirstRedDotChangeData.ChangeTips = Tips;
}
m_DirtyStack ??= new RedDotStack();
{
m_DirtyStack.Id = StackList.Count + 1;
m_DirtyStack.DataTime = DateTime.Now;
m_DirtyStack.StackTrace = new System.Diagnostics.StackTrace(true);
m_DirtyStack.RedDotOSType = ERedDotOSType.Count;
m_DirtyStack.OriginalCount = RealCount;
m_DirtyStack.ChangeCount = count;
m_DirtyStack.ChangeTips = Tips;
m_DirtyStack.FirstData = m_DirtyFirstRedDotChangeData;
}
#endif
}
//初始化脏标数据
private void ResetDirty()
{
m_ChangeDirty = false;
m_DirtyCount = -1;
m_DirtyStack = null;
m_DirtyFirstRedDotChangeData = null;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 281a1528c4c34c26a4788f057ba4c10e
timeCreated: 1686905885

View File

@@ -0,0 +1,56 @@
using System;
using System.Diagnostics;
namespace YIUIFramework
{
/// <summary>
/// 堆栈信息
/// </summary>
public class RedDotStack
{
/// <summary>
/// 当前的ID
/// 每一次堆栈增加+1
/// </summary>
public int Id { get; internal set; }
/// <summary>
/// 堆栈时间
/// </summary>
public DateTime DataTime { get; internal set; }
/// <summary>
/// 堆栈
/// </summary>
public StackTrace StackTrace { get; internal set; }
/// <summary>
/// 操作类型
/// </summary>
public ERedDotOSType RedDotOSType { get; internal set; }
/// <summary>
/// 本来数量
/// </summary>
public int OriginalCount { get; internal set; }
/// <summary>
/// 改变数量
/// </summary>
public int ChangeCount { get; internal set; }
/// <summary>
/// 当前是否提示
/// </summary>
public bool ChangeTips { get; internal set; }
/// <summary>
/// 第一个改变的数据
/// </summary>
public FirstRedDotChangeData FirstData { get; internal set; }
internal RedDotStack()
{
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 06e02fde800b45c6bf41a8997857f689
timeCreated: 1686829208

View File

@@ -0,0 +1,292 @@
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}";
/// <summary>
/// 获取操作拼接
/// </summary>
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}";
/// <summary>
/// 获取操作时间
/// </summary>
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}";
/// <summary>
/// 来源
/// </summary>
public static string GetSource(this RedDotStack self)
{
var data = self.FirstData;
var sb = SbPool.Get();
sb.AppendFormat(m_SourceFormat, (int)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
/// <summary>
/// 缓存堆栈解析数据
/// </summary>
private static Dictionary<StackTrace, string> m_StackContentDic = new Dictionary<StackTrace, string>();
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
/// <summary>
/// 根据堆栈 获取到已经解析后的详细信息
/// </summary>
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_StackContinueYIUIBind = "YIUIBind";
static readonly string m_StackContinueYIUIFramework = "YIUIFramework";
/// <summary>
/// 解析堆栈
/// 会隐藏 某些堆栈
/// </summary>
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 (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
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 5e446d14ea6f40968995d4b2cb799fb3
timeCreated: 1687344422

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 6a2479c407df40889d87bd36ae0e766c
timeCreated: 1686645753

View File

@@ -0,0 +1,18 @@
using System.Collections.Generic;
using Sirenix.OdinInspector;
using Sirenix.Serialization;
namespace YIUIFramework
{
//[CreateAssetMenu(fileName = "RedDotKeyAsset", menuName = "YIUI/RedDot/RedDotKeyAsset", order = 1)]
[LabelText("红点枚举配置资源")]
public class RedDotKeyAsset : SerializedScriptableObject
{
[OdinSerialize]
[ReadOnly]
[ShowInInspector]
internal Dictionary<int, RedDotKeyData> m_AllRedDotDic = new Dictionary<int, RedDotKeyData>();
public IReadOnlyDictionary<int, RedDotKeyData> AllRedDotDic => m_AllRedDotDic;
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 663fe2ae1bff4a59b18bf05ec0377719
timeCreated: 1686645475

View File

@@ -0,0 +1,46 @@
using System;
using Sirenix.OdinInspector;
using Sirenix.Serialization;
namespace YIUIFramework
{
[HideLabel]
[HideReferenceObjectPicker]
[Serializable]
public class RedDotKeyData
{
[LabelText("Id")]
[LabelWidth(50)]
[MinValue(1)]
[TableColumnWidth(150, resizable: false)]
[ShowInInspector]
[OdinSerialize]
public int Id { get; internal set; } = 1;
[LabelText("描述")]
[LabelWidth(50)]
[ShowInInspector]
[OdinSerialize]
public string Des { get; internal set; }
private RedDotKeyData()
{
}
public RedDotKeyData(int id)
{
Id = id;
}
public RedDotKeyData(int id, string des)
{
Id = id;
Des = des;
}
internal void ChangeDes(string des)
{
Des = des;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 4aef4cbd67fc4228989e83b0a8186b39
timeCreated: 1686645765

View File

@@ -0,0 +1,53 @@
using Sirenix.OdinInspector;
namespace YIUIFramework
{
/// <summary>
/// 红点系统 所有key枚举
/// 由YIUI工具自动创建 请勿手动修改
/// </summary>
public enum ERedDotKeyType
{
[LabelText("无")]
None = 0,
[LabelText("主界面统筹")]
Key1 = 1,
[LabelText("主界面背包")]
Key2 = 2,
[LabelText("主界面装备")]
Key3 = 3,
[LabelText("主界面商店")]
Key4 = 4,
[LabelText("背包材料")]
Key2001 = 2001,
[LabelText("背包装备")]
Key2002 = 2002,
[LabelText("背包任务")]
Key2003 = 2003,
[LabelText("装备强化")]
Key3001 = 3001,
[LabelText("装备锻造")]
Key3002 = 3002,
[LabelText("装备重铸")]
Key3003 = 3003,
[LabelText("商店钻石")]
Key4001 = 4001,
[LabelText("商店金币")]
Key4002 = 4002,
[LabelText("商店宝箱")]
Key4003 = 4003,
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 18d82c86165e49a4ad79ac800884eb4a
timeCreated: 1686711256

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: cd7d207d6cbf45f5a3423f061266f1bb
timeCreated: 1686833084

View File

@@ -0,0 +1,106 @@
//------------------------------------------------------------
// Author: 亦亦
// Mail: 379338943@qq.com
// Data: 2023年2月12日
//------------------------------------------------------------
using System;
using System.Collections.Generic;
using Cysharp.Threading.Tasks;
using UnityEngine;
namespace YIUIFramework
{
/// <summary>
/// 红点 管理器
/// </summary>
public partial class RedDotMgr : MgrSingleton<RedDotMgr>, IManagerAsyncInit
{
private const bool SyncSetCount = false; //实时修改红点还是异步脏标定时修改
private const string RedDotConfigAssetName = "RedDotConfigAsset";
private Dictionary<ERedDotKeyType, RedDotData> m_AllRedDotData = new Dictionary<ERedDotKeyType, RedDotData>();
public IReadOnlyDictionary<ERedDotKeyType, RedDotData> AllRedDotData => m_AllRedDotData;
private RedDotConfigAsset m_RedDotConfigAsset;
protected override void OnDispose()
{
DisposeDirty();
}
protected override async UniTask<bool> MgrAsyncInit()
{
var resultConfig = await LoadConfigAsset();
if (!resultConfig) return false;
#if UNITY_EDITOR || YIUIMACRO_REDDOT_STACK
var resultKey = await LoadKeyAsset();
if (!resultKey) return false;
#endif
if (!SyncSetCount)
{
InitAsyncDirty();
}
return true;
}
/// <summary>
/// 加载config
/// </summary>
private async UniTask<bool> LoadConfigAsset()
{
m_RedDotConfigAsset = await YIUILoadHelper.LoadAssetAsync<RedDotConfigAsset>(RedDotConfigAssetName);
if (m_RedDotConfigAsset == null)
{
Debug.LogError($"初始化失败 没有加载到目标数据 {RedDotConfigAssetName}");
return false;
}
InitNewAllData();
InitLinkData();
YIUILoadHelper.Release(m_RedDotConfigAsset);
return true;
}
/// <summary>
/// 初始化创建所有数据
/// </summary>
private void InitNewAllData()
{
m_AllRedDotData.Clear();
foreach (ERedDotKeyType key in Enum.GetValues(typeof(ERedDotKeyType)))
{
//有配置则使用配置 没有则使用默认配置
var config = m_RedDotConfigAsset.GetConfigData(key) ?? new RedDotConfigData { Key = key };
var data = new RedDotData(config);
m_AllRedDotData.Add(key, data);
}
}
/// <summary>
/// 初始化红点关联数据
/// </summary>
private void InitLinkData()
{
foreach (var config in m_RedDotConfigAsset.AllRedDotConfigDic.Values)
{
var data = GetData(config.Key);
if (data == null) continue;
foreach (var parentId in config.ParentList)
{
var parentData = GetData(parentId);
if (parentData != null)
{
data.AddParent(parentData);
}
}
}
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 9a253c9d27514b848582003f7af178e9
timeCreated: 1686833097

View File

@@ -0,0 +1,108 @@
using System;
using UnityEngine;
namespace YIUIFramework
{
/// <summary>
/// 红点 管理器
/// </summary>
public partial class RedDotMgr
{
/// <summary>
/// 获取这个红点数据
/// </summary>
public RedDotData GetData(ERedDotKeyType key)
{
m_AllRedDotData.TryGetValue(key, out var data);
if (data == null)
{
if (!Disposed)
Debug.LogError($"没有获取到这个红点数据 {key}");
}
return data;
}
/// <summary>
/// 添加变化监听
/// </summary>
public bool AddChanged(ERedDotKeyType key, Action<int> action)
{
var data = GetData(key);
if (data == null)
{
return false;
}
data.AddOnChanged(action);
return true;
}
/// <summary>
/// 移除变化监听
/// </summary>
public bool RemoveChanged(ERedDotKeyType key, Action<int> action)
{
var data = GetData(key);
if (data == null)
{
return false;
}
data.RemoveChanged(action);
return true;
}
/// <summary>
/// 设置对应红点的数量
/// </summary>
public bool SetCount(ERedDotKeyType key, int count)
{
var data = GetData(key);
if (data == null) return false;
if (SyncSetCount)
{
return data.TrySetCount(count);
}
else
{
return TryDirtySetCount(data, count);
}
}
/// <summary>
/// 获取某个红点的当前数量
/// 如果他的tips被关闭 数量=0
/// </summary>
/// <param name="key">key</param>
/// <param name="isReal">真实数量</param>
/// <returns></returns>
public int GetCount(ERedDotKeyType key, bool isReal = false)
{
var data = GetData(key);
if (data == null)
{
return 0;
}
return isReal ? data.RealCount : data.Count;
}
/// <summary>
/// 设置此红点是否提示
/// (可关闭红点 这样红点就不会一直提示了 给玩家设置的)
/// </summary>
public bool SetTips(ERedDotKeyType key, bool tips)
{
var data = GetData(key);
return data != null && data.SetTips(tips);
}
public void DeletePlayerTipsPrefs(ERedDotKeyType key)
{
var data = GetData(key);
data?.DeletePlayerTipsPrefs();
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 6d720844548f42c59215ced652eadfa7
timeCreated: 1686880352

View File

@@ -0,0 +1,59 @@
using System.Collections.Generic;
using YIUIBind;
namespace YIUIFramework
{
/// <summary>
/// 红点 管理器
/// 脏数据管理 防止频繁调用
/// </summary>
public partial class RedDotMgr
{
//已存标记
private HashSet<RedDotData> m_DirtyData;
//1秒内刷新多少次
private const int m_RedDotDirtyFrame = 2;
private int m_LoopId;
//初始化异步脏标
private void InitAsyncDirty()
{
m_DirtyData = new HashSet<RedDotData>();
m_LoopId = SchedulerMgr.Loop(RedDotUpdateRefresh, 1f / m_RedDotDirtyFrame);
}
private void DisposeDirty()
{
SchedulerMgr.StopLoop(m_LoopId);
}
private void RedDotUpdateRefresh()
{
RefreshDirtyCount();
}
private bool TryDirtySetCount(RedDotData data, int count)
{
m_DirtyData.Remove(data);
var result = data.TryDirtySetCount(count);
if (result)
{
m_DirtyData.Add(data);
}
return result;
}
private void RefreshDirtyCount()
{
foreach (var data in m_DirtyData)
{
data.RefreshDirtyCount();
}
m_DirtyData.Clear();
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: d91d2000c5a44da392f85e7adec5b1ea
timeCreated: 1686888682

View File

@@ -0,0 +1,64 @@
using System.Collections.Generic;
using Cysharp.Threading.Tasks;
using UnityEngine;
namespace YIUIFramework
{
public partial class RedDotMgr
{
private const string RedDotKeyAssetName = "RedDotKeyAsset";
private Dictionary<ERedDotKeyType, RedDotKeyData> m_AllRedDotKeyData =
new Dictionary<ERedDotKeyType, RedDotKeyData>();
public IReadOnlyDictionary<ERedDotKeyType, RedDotKeyData> AllRedDotKeyData => m_AllRedDotKeyData;
private RedDotKeyAsset m_RedDotKeyAsset;
/// <summary>
/// 加载key
/// </summary>
private async UniTask<bool> LoadKeyAsset()
{
m_RedDotKeyAsset = await YIUILoadHelper.LoadAssetAsync<RedDotKeyAsset>(RedDotKeyAssetName);
if (m_RedDotKeyAsset == null)
{
Debug.LogError($"初始化失败 没有加载到目标数据 {RedDotKeyAssetName}");
return false;
}
InitKeyData();
YIUILoadHelper.Release(m_RedDotKeyAsset);
return true;
}
/// <summary>
/// 初始化Key相关
/// </summary>
private void InitKeyData()
{
m_AllRedDotKeyData.Clear();
foreach (var keyData in m_RedDotKeyAsset.AllRedDotDic.Values)
{
m_AllRedDotKeyData.Add((ERedDotKeyType)keyData.Id, keyData);
}
}
/// <summary>
/// 获取key描述
/// </summary>
public string GetKeyDes(ERedDotKeyType keyType)
{
if (!m_AllRedDotKeyData.ContainsKey(keyType))
{
Debug.LogError($"不存在这个key {keyType}");
return "";
}
var keyData = m_AllRedDotKeyData[keyType];
return keyData.Des;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: bbadc6aca3de442bbd8cb203ed43ae89
timeCreated: 1687158260