初始化

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: f35579e501f24f1baebb5d53b2b99d6e
timeCreated: 1686645092

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

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 987b52bf5b7e4723a519484a75323c27
timeCreated: 1686645099

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 217e82662f0e4162a0e4b8a63922d6d2
timeCreated: 1686650020

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 28691dfc0100452f9a82c4bb55a4b49b
timeCreated: 1686715343

View File

@@ -0,0 +1,47 @@
#if UNITY_EDITOR
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
namespace YIUIFramework.Editor
{
public static class RedDotConfigAsset_Extend
{
internal static void SetAllRedDotConfigList(this RedDotConfigAsset self, List<RedDotConfigData> dataList)
{
self.m_AllRedDotConfigDic.Clear();
foreach (var data in dataList)
{
self.m_AllRedDotConfigDic.Add(data.Key, data);
}
EditorUtility.SetDirty(self);
}
internal static bool ContainsKey(this RedDotConfigAsset self, ERedDotKeyType key)
{
return self.m_AllRedDotConfigDic.ContainsKey(key);
}
internal static bool RemoveConfigData(this RedDotConfigAsset self, ERedDotKeyType key)
{
var result = self.m_AllRedDotConfigDic.Remove(key);
EditorUtility.SetDirty(self);
return result;
}
internal static bool AddConfigData(this RedDotConfigAsset self, RedDotConfigData data)
{
if (self.m_AllRedDotConfigDic.ContainsKey(data.Key))
{
Debug.LogError($"已存在 无法重复添加 {data.Key}");
return false;
}
self.m_AllRedDotConfigDic.Add(data.Key, data);
EditorUtility.SetDirty(self);
return true;
}
}
}
#endif

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: db15a7657a8a4caba8e09e044ab21e60
timeCreated: 1687341106

View File

@@ -0,0 +1,79 @@
#if UNITY_EDITOR
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace YIUIFramework.Editor
{
internal class Node
{
public ERedDotKeyType Key { get; set; }
public List<Node> Parents { get; set; }
public List<Node> Children { get; set; }
public Node(ERedDotKeyType key)
{
Key = key;
Parents = new List<Node>();
Children = new List<Node>();
}
}
internal class UIRedDotConfigDAG
{
private List<Node> Nodes { get; set; }
public UIRedDotConfigDAG()
{
Nodes = new List<Node>();
}
public void AddNode(ERedDotKeyType key)
{
Nodes.Add(new Node(key));
}
public void AddEdge(ERedDotKeyType parentKey, ERedDotKeyType childKey)
{
var parent = Nodes.Find(n => n.Key == parentKey);
var child = Nodes.Find(n => n.Key == childKey);
parent.Children.Add(child);
child.Parents.Add(parent);
}
public bool Check()
{
return CheckCyclesSort(Nodes);
}
//拓扑排序算法 检查循环引用
private static bool CheckCyclesSort(List<Node> nodes)
{
var sortedNodes = new List<Node>();
var nodesWithoutParents = new Queue<Node>(nodes.Where(n => n.Parents.Count == 0));
while (nodesWithoutParents.Count > 0)
{
var node = nodesWithoutParents.Dequeue();
sortedNodes.Add(node);
foreach (var child in node.Children)
{
child.Parents.Remove(node);
if (child.Parents.Count == 0)
{
nodesWithoutParents.Enqueue(child);
}
}
}
if (nodes.Any(n => n.Parents.Count > 0))
{
return false;
}
return true;
}
}
}
#endif

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: e918f6d75fc8420c906a73d0cd977451
timeCreated: 1686902612

View File

@@ -0,0 +1,231 @@
#if UNITY_EDITOR
using System;
using System.Collections.Generic;
using System.Text;
using Sirenix.OdinInspector;
using Sirenix.Serialization;
using UnityEngine;
using YIUIBind;
namespace YIUIFramework.Editor
{
[Serializable]
[HideLabel]
[HideReferenceObjectPicker]
internal class UIRedDotConfigEditorData
{
[VerticalGroup("Key")]
[HideLabel]
[TableColumnWidth(400, resizable: false)]
[DisableIf("ShowDeleteBtn")]
[OnValueChanged("OnValueChangedKeyType")]
[ShowInInspector]
[OdinSerialize]
internal ERedDotKeyType KeyType;
[VerticalGroup("Key")]
[LabelText("ID")]
[ReadOnly]
[ShowInInspector]
[OdinSerialize]
internal int Id;
[VerticalGroup("Key")]
[LabelText("可开关提示")]
[Tooltip("true = 玩家可开关 false = 不可开关 (永久提示)")]
[ShowInInspector]
[OnValueChanged("OnValueChangedSwitchTips")]
[OdinSerialize]
internal bool SwitchTips = true;
[VerticalGroup("所有父级列表")]
[HideLabel]
[TableList(DrawScrollView = true, AlwaysExpanded = true, HideToolbar = true, MaxScrollViewHeight = 100,
MinScrollViewHeight = 100)]
[OdinSerialize]
[ShowInInspector]
[OnValueChanged("OnValueChangedParentList")]
[PropertyOrder(1001)]
internal List<UIRedDotKeyEditorData> ParentList = new List<UIRedDotKeyEditorData>();
[VerticalGroup("所有父级列表")]
[Button("添加父级", 10)]
[GUIColor(0.7f, 0.4f, 0.8f)]
[PropertyOrder(1000)]
private void AddParentData()
{
ParentList.Add(new UIRedDotKeyEditorData(this));
}
[GUIColor(1, 1, 0)]
[VerticalGroup("删除")]
[TableColumnWidth(50, resizable: false)]
[Button("删除", 90)]
[ShowIf("ShowDeleteBtn")]
[PropertyOrder(10000)]
private void DeleteData()
{
UnityTipsHelper.CallBack($"确定移除当前配置数据? {KeyType}",
() =>
{
m_UIRedDotConfigView.m_EditorDataSyncDirty = true;
m_UIRedDotConfigView?.DeleteConfigEditorData(this);
});
}
[HideInInspector]
[OdinSerialize]
internal bool ShowDeleteBtn = true;
private UIRedDotConfigView m_UIRedDotConfigView;
internal UIRedDotConfigEditorData(UIRedDotConfigView configView)
{
m_UIRedDotConfigView = configView;
}
private void OnValueChangedSwitchTips()
{
if (ShowDeleteBtn)
{
m_UIRedDotConfigView.m_EditorDataSyncDirty = true;
}
}
private void OnValueChangedKeyType()
{
if (m_UIRedDotConfigView.EditorDataContains(KeyType))
{
KeyType = ERedDotKeyType.None;
UnityTipsHelper.Show($"当前配置已存在 {KeyType}");
}
Id = (int)KeyType;
}
#region ParentList Key设定是否合理
private void OnValueChangedParentList()
{
CheckParentList();
}
internal void CheckParentList(bool showTips = true)
{
if (ShowDeleteBtn)
{
m_UIRedDotConfigView.m_EditorDataSyncDirty = true;
}
var sb = SbPool.Get();
CheckParentListHaveSelf(sb);
CheckParentListHaveEqual(sb);
CheckParentListParentHaveSelf(sb);
var tipsContent = SbPool.PutAndToStr(sb);
if (!string.IsNullOrEmpty(tipsContent))
{
if (showTips)
{
UnityTipsHelper.Show(tipsContent);
}
else
{
Debug.LogError(tipsContent);
}
}
}
//是否有自身
private void CheckParentListHaveSelf(StringBuilder sb)
{
for (int i = 0; i < ParentList.Count; i++)
{
var data = ParentList[i];
if (data.KeyType == KeyType)
{
ParentList.Remove(data);
sb.AppendLine($"当前数据与自身相同 不能循环引用自身 已移除 {data.KeyType}");
}
}
}
//是否有相同数据
private void CheckParentListHaveEqual(StringBuilder sb)
{
for (int i = 0; i < ParentList.Count; i++)
{
var data = ParentList[i];
for (int j = 0; j < ParentList.Count; j++)
{
var data2 = ParentList[j];
if (data == data2)
{
continue;
}
if (data.KeyType == data2.KeyType)
{
ParentList.Remove(data);
sb.AppendLine($"已存在相同数据 已移除 {data.KeyType}");
CheckParentListHaveEqual(sb);
return;
}
}
}
}
//判断父级的父级的父级一直递归 他们中的父级是不是有我 否则会形成嵌套循环
private void CheckParentListParentHaveSelf(StringBuilder sb)
{
for (int i = 0; i < ParentList.Count; i++)
{
var data = ParentList[i];
var parentConfigData = m_UIRedDotConfigView?.m_RedDotConfigAsset?.GetConfigData(data.KeyType);
if (parentConfigData == null)
{
continue;
}
if (CheckParentConfigDataHaveSelf(parentConfigData))
{
ParentList.Remove(data);
sb.AppendLine($"我的当前父级{data.KeyType} 递归上父级中存在{KeyType} 无法循环引用 已移除 请规避循环问题");
CheckParentListParentHaveSelf(sb);
return;
}
}
}
private bool CheckParentConfigDataHaveSelf(RedDotConfigData configData)
{
foreach (var parentParentKey in configData.ParentList)
{
if (parentParentKey == KeyType)
{
return true;
}
var parentConfigData = m_UIRedDotConfigView?.m_RedDotConfigAsset?.GetConfigData(parentParentKey);
if (parentConfigData == null)
{
continue;
}
if (CheckParentConfigDataHaveSelf(parentConfigData))
{
return true;
}
}
return false;
}
#endregion
}
}
#endif

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 504e3a955e6047a7a25c82cab8dbcb4c
timeCreated: 1686724531

View File

@@ -0,0 +1,326 @@
#if UNITY_EDITOR
using System;
using System.Collections.Generic;
using System.Linq;
using Sirenix.OdinInspector;
using Sirenix.Serialization;
using Sirenix.Utilities;
using UnityEngine;
using YIUIBind;
namespace YIUIFramework.Editor
{
[HideLabel]
[HideReferenceObjectPicker]
internal class UIRedDotConfigView : BaseCreateModule
{
internal UIRedDotModule m_UIRedDotModule;
internal RedDotConfigAsset m_RedDotConfigAsset;
private EnumPrefs<ERedDotConfigViewIndexType> m_ERedDotConfigViewIndexTypePrefs =
new EnumPrefs<ERedDotConfigViewIndexType>("AutoUIRedDotModule_ERedDotConfigViewIndexType", null,
ERedDotConfigViewIndexType.Get);
[EnumToggleButtons]
[HideLabel]
[ShowInInspector]
[PropertyOrder(-100)]
[OnValueChanged("OnValueChangedConfigViewIndex")]
private ERedDotConfigViewIndexType m_ERedDotConfigViewIndexType = ERedDotConfigViewIndexType.Get;
public UIRedDotConfigView(UIRedDotModule redDotModule)
{
m_UIRedDotModule = redDotModule;
m_RedDotConfigAsset = redDotModule.m_RedDotConfigAsset;
}
public override void Initialize()
{
m_ERedDotConfigViewIndexType = m_ERedDotConfigViewIndexTypePrefs.Value;
NewAddConfigEditorData();
InitConfigEditorDataList();
m_UIRedDotModule.OnChangeViewSetIndex += OnChangeViewSetIndex;
}
public override void OnDestroy()
{
m_UIRedDotModule.OnChangeViewSetIndex -= OnChangeViewSetIndex;
AutoSyncEditorData();
}
private void OnChangeViewSetIndex(UIRedDotModule.EUIRedDotViewType obj)
{
if (obj != UIRedDotModule.EUIRedDotViewType.Config)
{
AutoSyncEditorData();
}
}
private void OnValueChangedConfigViewIndex()
{
m_ERedDotConfigViewIndexTypePrefs.Value = m_ERedDotConfigViewIndexType;
if (m_ERedDotConfigViewIndexType != ERedDotConfigViewIndexType.Get)
{
//AutoSyncEditorData(); //暂时取消这个同步 频率很高
}
}
#region
//编辑器数据同步脏标
internal bool m_EditorDataSyncDirty = false;
//自动同步数据
private void AutoSyncEditorData()
{
if (!m_EditorDataSyncDirty) return;
UnityTipsHelper.CallBack($"关联配置数据 已修改是否同步 \n\n取消同步将会丢失所有修改!!!", UpdateConfigEditorDataToAsset);
}
#endregion
#region
[OdinSerialize]
[ShowInInspector]
[BoxGroup("新增关联配置数据", centerLabel: true)]
[ShowIf("m_ERedDotConfigViewIndexType", ERedDotConfigViewIndexType.Add)]
[HideLabel]
[HideReferenceObjectPicker]
private UIRedDotConfigEditorData m_AddUIRedDotConfigEditorData;
[GUIColor(0, 1, 0)]
[Button("添加关联配置", 50)]
[ShowIf("m_ERedDotConfigViewIndexType", ERedDotConfigViewIndexType.Add)]
private void AddConfigEditorDataBtn()
{
var keyType = m_AddUIRedDotConfigEditorData.KeyType;
if (keyType == ERedDotKeyType.None)
{
UnityTipsHelper.Show($"请设置一个合理的key");
return;
}
if (EditorDataContains(keyType))
{
UnityTipsHelper.Show($"当前Key的相关配置已存在 无法重复添加 {keyType}");
return;
}
m_AddUIRedDotConfigEditorData.ShowDeleteBtn = true;
AddConfigEditorDataToList(m_AddUIRedDotConfigEditorData);
NewAddConfigEditorData();
m_EditorDataSyncDirty = true;
UnityTipsHelper.Show($"成功添加 {keyType}");
}
private void NewAddConfigEditorData()
{
m_AddUIRedDotConfigEditorData = new UIRedDotConfigEditorData(this)
{
ShowDeleteBtn = false,
};
m_AddUIRedDotConfigEditorData.ParentList.Add(new UIRedDotKeyEditorData(m_AddUIRedDotConfigEditorData));
}
#endregion
#region
[GUIColor(0.4f, 0.8f, 1)]
[Button("同步到Asset配置", 50)]
[ShowIf("m_ERedDotConfigViewIndexType", ERedDotConfigViewIndexType.Get)]
[PropertyOrder(-1)]
[EnableIf("m_EditorDataSyncDirty")]
private void UpdateConfigEditorDataToAsset()
{
m_EditorDataSyncDirty = false;
DeserializationEditorData();
InitConfigEditorDataList();
UnityTipsHelper.Show($"同步完成");
}
[TableList(DrawScrollView = true, AlwaysExpanded = true, IsReadOnly = true)]
[OdinSerialize]
[BoxGroup("所有关联配置数据", centerLabel: true)]
[HideLabel]
[ShowIf("m_ERedDotConfigViewIndexType", ERedDotConfigViewIndexType.Get)]
private List<UIRedDotConfigEditorData> m_RedDotConfigEditorDataList = new List<UIRedDotConfigEditorData>();
private HashSet<ERedDotKeyType> m_HashRedDotKeyType = new HashSet<ERedDotKeyType>();
#region Asset
private void InitConfigEditorDataList()
{
m_RedDotConfigEditorDataList.Clear();
m_HashRedDotKeyType.Clear();
foreach (var data in m_RedDotConfigAsset.AllRedDotConfigDic.Values)
{
var editorData = NewEditorDataByRuntimeData(data);
AddConfigEditorDataToList(editorData);
}
}
private UIRedDotConfigEditorData NewEditorDataByRuntimeData(RedDotConfigData data)
{
var editorData = new UIRedDotConfigEditorData(this)
{
Id = (int)data.Key,
KeyType = data.Key,
SwitchTips = data.SwitchTips,
ShowDeleteBtn = true
};
editorData.ParentList = GetParentListByRuntimeData(data, editorData);
return editorData;
}
private List<UIRedDotKeyEditorData> GetParentListByRuntimeData(RedDotConfigData data,
UIRedDotConfigEditorData editorData)
{
var parentList = new List<UIRedDotKeyEditorData>();
foreach (var key in data.ParentList)
{
parentList.Add(new UIRedDotKeyEditorData(editorData)
{
Id = (int)key,
KeyType = key,
});
}
return parentList;
}
#endregion
#region
private void DeserializationEditorData()
{
var list = GetRuntimeDataListToEditorData();
list.Sort(SortRuntimeData);
m_RedDotConfigAsset.SetAllRedDotConfigList(list);
}
private int SortRuntimeData(RedDotConfigData x, RedDotConfigData y)
{
return x.Key < y.Key ? -1 : 1;
}
private List<RedDotConfigData> GetRuntimeDataListToEditorData()
{
var runtimeDataList = new List<RedDotConfigData>();
foreach (var data in m_RedDotConfigEditorDataList)
{
var runtimeData = NewRuntimeDataByEditorData(data);
runtimeDataList.Add(runtimeData);
}
return runtimeDataList;
}
private RedDotConfigData NewRuntimeDataByEditorData(UIRedDotConfigEditorData data)
{
var runtimeData = new RedDotConfigData()
{
Key = data.KeyType,
ParentList = GetParentListByEditorData(data),
SwitchTips = data.SwitchTips,
};
return runtimeData;
}
private List<ERedDotKeyType> GetParentListByEditorData(UIRedDotConfigEditorData data)
{
var parentList = new List<ERedDotKeyType>();
foreach (var parentData in data.ParentList)
{
if (parentData.KeyType == ERedDotKeyType.None)
{
continue;
}
parentList.Add(parentData.KeyType);
}
return parentList;
}
#endregion
private bool AddConfigEditorDataToList(UIRedDotConfigEditorData data)
{
if (m_HashRedDotKeyType.Contains(data.KeyType))
{
Debug.LogError($"已存在 无法重复添加");
return false;
}
m_RedDotConfigEditorDataList.Add(data);
m_HashRedDotKeyType.Add(data.KeyType);
return true;
}
internal bool EditorDataContains(ERedDotKeyType keyType)
{
return m_HashRedDotKeyType.Contains(keyType);
}
internal void DeleteConfigEditorData(UIRedDotConfigEditorData data)
{
m_RedDotConfigEditorDataList.Remove(data);
m_HashRedDotKeyType.Remove(data.KeyType);
}
#endregion
#region DAG
[ShowIf("m_ERedDotConfigViewIndexType", ERedDotConfigViewIndexType.Get)]
[Button("额外检查是否有循环引用", 30)]
[PropertyOrder(-100)]
public void CheckDataCycles()
{
var redDotConfigDAG = new UIRedDotConfigDAG();
foreach (ERedDotKeyType key in Enum.GetValues(typeof(ERedDotKeyType)))
{
redDotConfigDAG.AddNode(key);
}
foreach (var data in m_RedDotConfigEditorDataList)
{
foreach (var parentData in data.ParentList)
{
redDotConfigDAG.AddEdge(parentData.KeyType, data.KeyType);
}
}
var result = redDotConfigDAG.Check();
UnityTipsHelper.Show(result ? "安全 无循环嵌套" : "有循环嵌套 请详细检查");
}
#endregion
[HideLabel]
private enum ERedDotConfigViewIndexType
{
[LabelText("增")]
Add = 1,
[LabelText("删/改/查")]
Get = 2,
}
}
}
#endif

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: b003f8081afc4ed88cbbde8fdbaa1f7a
timeCreated: 1686650480

View File

@@ -0,0 +1,37 @@
#if UNITY_EDITOR
using System;
using Sirenix.OdinInspector;
using Sirenix.Serialization;
namespace YIUIFramework.Editor
{
[Serializable]
internal class UIRedDotKeyEditorData
{
[HideLabel]
[OnValueChanged("OnValueChangedKeyType")]
[OdinSerialize]
public ERedDotKeyType KeyType;
[HideLabel]
[ReadOnly]
[TableColumnWidth(100, resizable: false)]
[OdinSerialize]
public int Id;
private UIRedDotConfigEditorData m_UIRedDotConfigEditorData;
public UIRedDotKeyEditorData(UIRedDotConfigEditorData editorData)
{
m_UIRedDotConfigEditorData = editorData;
}
private void OnValueChangedKeyType()
{
Id = (int)KeyType;
m_UIRedDotConfigEditorData?.CheckParentList();
}
}
}
#endif

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 83cb0703eba944f796567b6c4cd8ac65
timeCreated: 1686897697

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 4169a72de0cf49b9b23dcaa14074e2f7
timeCreated: 1686710409

View File

@@ -0,0 +1,174 @@
#if UNITY_EDITOR
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
namespace YIUIFramework
{
public static class RedDotKeyAsset_Extend
{
internal static List<RedDotKeyData> GetDataList(this RedDotKeyAsset self)
{
var listData = new List<RedDotKeyData>();
foreach (var data in self.AllRedDotDic.Values)
{
listData.Add(data);
}
listData.Sort(OnSortData);
return listData;
}
private static int OnSortData(RedDotKeyData x, RedDotKeyData y)
{
return x.Id < y.Id ? -1 : 1;
}
//获取当前空闲的ID 安全的ID 直接用这个ID
//建议就从ID 1开始 我不信你有超过MAX的需求
internal static int GetSafetyId(this RedDotKeyAsset self)
{
if (self.AllRedDotDic.Count <= 0)
{
return 1;
}
var listData = GetDataList(self);
var id = 1;
for (var i = 0; i < listData.Count; i++)
{
var data = listData[i];
var dataId = data.Id;
if (id != dataId)
{
if (!self.AllRedDotDic.ContainsKey(id))
{
break;
}
}
id = dataId + 1;
}
if (id >= int.MaxValue)
{
Debug.LogError($"ID 不能>= {int.MaxValue} ID不可能设计这么大 请检查");
return 1;
}
return id;
}
internal static bool ContainsKey(this RedDotKeyAsset self, int id)
{
return self.AllRedDotDic.ContainsKey(id);
}
internal static (bool, string) AddKey(this RedDotKeyAsset self, RedDotKeyData data)
{
if (data.Id <= 0)
{
const string tips = "ID <= 0 是不允许的";
Debug.LogError(tips);
return (false, tips);
}
if (self.AllRedDotDic.ContainsKey(data.Id))
{
var tips = $"当前ID已经存在 无法重复添加 {data.Id}";
Debug.LogError(tips);
return (false, tips);
}
self.Add(data);
return (true, $"成功添加ID {data.Id} {data.Des}");
}
internal static (bool, string) RemoveKey(this RedDotKeyAsset self, int id)
{
if (!self.AllRedDotDic.ContainsKey(id))
{
var tips = $"当前ID不存在 无法移除 {id}";
Debug.LogError(tips);
return (false, tips);
}
//移除前 需执行判断关联信息 提示删除警告
self.Remove(id);
return (true, $"成功移除ID {id}");
}
internal static (bool, string) ChangeKey(this RedDotKeyAsset self, int lastId, RedDotKeyData changeData)
{
if (!self.AllRedDotDic.ContainsKey(lastId))
{
var tips = $"修改的Id 不存在 {lastId}";
Debug.LogError(tips);
return (false, tips);
}
var lastData = self.AllRedDotDic[lastId];
if (lastId == changeData.Id)
{
if (lastData.Des == changeData.Des) return (false, $"修改前后数据相同 无法修改 请检查");
lastData.ChangeDes(changeData.Des);
return (true, $"成功修改 {lastId} 描述 >> {changeData.Des}");
}
if (self.AllRedDotDic.ContainsKey(changeData.Id))
{
var tips = $"修改后的Id {changeData.Id} 已存在 无法修改 {lastId}";
Debug.LogError(tips);
return (false, tips);
}
self.Remove(lastData);
self.Add(new RedDotKeyData(changeData.Id, changeData.Des));
//修改前 需执行判断关联信息 提示警告
return (true, $"修改完成 {lastId} >> {changeData.Id} >> {changeData.Des}");
}
internal static (RedDotKeyData, string) GetKey(this RedDotKeyAsset self, int id)
{
if (!self.AllRedDotDic.ContainsKey(id))
{
var tips = $"当前ID不存在 {id}";
Debug.LogError(tips);
return (null, tips);
}
var data = self.AllRedDotDic[id];
return (data, $"查询到数据 ID:{id} Des:{data.Des}");
}
private static void Add(this RedDotKeyAsset self, RedDotKeyData data)
{
if (self.ContainsKey(data.Id))
{
Debug.LogError($"当前ID 已存在无法重复添加 请检查");
return;
}
self.m_AllRedDotDic.Add(data.Id, data);
EditorUtility.SetDirty(self);
}
private static void Remove(this RedDotKeyAsset self, RedDotKeyData data)
{
Remove(self, data.Id);
}
private static void Remove(this RedDotKeyAsset self, int id)
{
self.m_AllRedDotDic.Remove(id);
EditorUtility.SetDirty(self);
}
}
}
#endif

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 176238426aaa4988b7346a5469c22864
timeCreated: 1687334636

View File

@@ -0,0 +1,17 @@
#if UNITY_EDITOR
using System.Collections.Generic;
namespace YIUIFramework.Editor
{
internal class RedDotLinkData
{
internal ERedDotKeyType Key;
internal bool ConfigSet;
internal List<ERedDotKeyType> LinkKey = new List<ERedDotKeyType>();
}
}
#endif

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 45ad68725d6e4adfa09c31d107d1acf9
timeCreated: 1686811551

View File

@@ -0,0 +1,29 @@
#if UNITY_EDITOR
namespace YIUIFramework.Editor
{
internal class UICreateRedDotKeyCode : BaseTemplate
{
public override string EventName => "红点系统 key 枚举自动生成";
private bool m_AutoRefresh = false;
public override bool AutoRefresh => m_AutoRefresh;
private bool m_ShowTips = false;
public override bool ShowTips => m_ShowTips;
public UICreateRedDotKeyCode(out bool result, string authorName, UICreateRedDotKeyData codeData) :
base(authorName)
{
var path = codeData.ClassPath;
var template = $"{UIStaticHelper.UITemplatePath}/UICreateRedDotKeyTemplate.txt";
CreateVo = new CreateVo(template, path);
m_AutoRefresh = codeData.AutoRefresh;
m_ShowTips = codeData.ShowTips;
ValueDic["Content"] = codeData.Content;
result = CreateNewFile();
}
}
}
#endif

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: bba379addaf9473d8b0147782a54c9e3
timeCreated: 1686710930

View File

@@ -0,0 +1,12 @@
#if UNITY_EDITOR
namespace YIUIFramework.Editor
{
internal class UICreateRedDotKeyData
{
public bool AutoRefresh;
public bool ShowTips;
public string ClassPath;
public string Content;
}
}
#endif

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 066487f915ca4aecb2317b1586371567
timeCreated: 1686710894

View File

@@ -0,0 +1,33 @@
#if UNITY_EDITOR
using System.Collections.Generic;
using System.Text;
namespace YIUIFramework.Editor
{
internal static class UICreateRedDotKeyGet
{
public static string Get(List<RedDotKeyData> dataList)
{
var sb = SbPool.Get();
foreach (var data in dataList)
{
data.AddKeyData(sb);
}
return SbPool.PutAndToStr(sb);
}
private const string m_EnumContent = @"
[LabelText(""{0}"")]
Key{1} = {1},
";
private static void AddKeyData(this RedDotKeyData data, StringBuilder sb)
{
var des = string.IsNullOrEmpty(data.Des) ? data.Id.ToString() : data.Des;
sb.AppendFormat(m_EnumContent, des, data.Id);
}
}
}
#endif

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 544747482f3d455595d68807c1109c38
timeCreated: 1686712141

View File

@@ -0,0 +1,99 @@
#if UNITY_EDITOR
using System.Collections.Generic;
using UnityEngine;
namespace YIUIFramework.Editor
{
internal static class UIRedDotKeyEditorHelper
{
internal static RedDotLinkData GetCheckKeyLink(RedDotConfigAsset configAsset, ERedDotKeyType key)
{
var linkData = new RedDotLinkData
{
Key = key
};
foreach (var data in configAsset.AllRedDotConfigDic.Values)
{
if (data.Key == key)
{
linkData.ConfigSet = true;
continue;
}
foreach (var parent in data.ParentList)
{
if (parent == key)
{
linkData.LinkKey.Add(data.Key);
break;
}
}
}
return linkData;
}
internal static void RemoveKeyByLink(RedDotConfigAsset configAsset, RedDotLinkData linkData)
{
if (linkData.ConfigSet)
{
configAsset.RemoveConfigData(linkData.Key);
}
foreach (var linkKey in linkData.LinkKey)
{
var configData = configAsset.GetConfigData(linkKey);
if (configData == null)
{
Debug.LogError($"这里不应该获取到一个未知的结果 请检查 {linkKey}");
continue;
}
configData.ParentList.Remove(linkData.Key);
}
}
internal static void ChangeKeyByLink(RedDotConfigAsset configAsset, RedDotLinkData linkData,
RedDotKeyData changeKeyData)
{
var newKey = (ERedDotKeyType)changeKeyData.Id;
if (linkData.ConfigSet)
{
var configData = configAsset.GetConfigData(linkData.Key);
if (configData == null)
{
Debug.LogError($"这里不应该获取到一个未知的结果 请检查 {linkData.Key}");
return;
}
//移除老的
configAsset.RemoveConfigData(linkData.Key);
//添加一个新的
var newConfigData = new RedDotConfigData
{
Key = newKey,
SwitchTips = configData.SwitchTips,
ParentList = configData.ParentList
};
configAsset.AddConfigData(newConfigData);
}
foreach (var linkKey in linkData.LinkKey)
{
var configData = configAsset.GetConfigData(linkKey);
if (configData == null)
{
Debug.LogError($"这里不应该获取到一个未知的结果 请检查 {linkKey}");
continue;
}
configData.ParentList.Remove(linkData.Key);
configData.ParentList.Add(newKey);
}
}
}
}
#endif

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 22c800e022884f0e801442f93a517518
timeCreated: 1686810792

View File

@@ -0,0 +1,449 @@
#if UNITY_EDITOR
using System;
using System.Collections.Generic;
using Sirenix.OdinInspector;
using Sirenix.Serialization;
using UnityEngine;
using YIUIBind;
namespace YIUIFramework.Editor
{
[HideLabel]
[HideReferenceObjectPicker]
internal class UIRedDotKeyView : BaseCreateModule
{
private UIRedDotModule m_UIRedDotModule;
private RedDotKeyAsset m_RedDotKeyAsset;
private EnumPrefs<ERedDotKeyViewIndexType> m_ERedDotKeyViewIndexTypePrefs =
new EnumPrefs<ERedDotKeyViewIndexType>("AutoUIRedDotModule_ERedDotKeyViewIndexTypePrefs", null,
ERedDotKeyViewIndexType.Add);
[EnumToggleButtons]
[HideLabel]
[ShowInInspector]
[OnValueChanged("OnValueChangedKeyViewIndex")]
private ERedDotKeyViewIndexType m_ERedDotKeyViewIndexType = ERedDotKeyViewIndexType.Add;
[HideInInspector]
private ERedDotKeyViewIndexType m_LastKeyViewIndex = ERedDotKeyViewIndexType.Add;
private void OnValueChangedKeyViewIndex()
{
m_ERedDotKeyViewIndexTypePrefs.Value = m_ERedDotKeyViewIndexType;
if (m_ERedDotKeyViewIndexType == ERedDotKeyViewIndexType.Add)
{
return;
}
if (m_LastKeyViewIndex != ERedDotKeyViewIndexType.Add)
{
return;
}
if (m_WaitCreate)
{
CreateKeyEnumClass();
}
}
[OdinSerialize]
[ReadOnly]
[PropertyOrder(1000000)]
[BoxGroup("预览", centerLabel: true)]
[HideLabel]
[ShowInInspector]
[DictionaryDrawerSettings(DisplayMode = DictionaryDisplayOptions.Foldout)]
private IReadOnlyDictionary<int, RedDotKeyData> m_AllRedDotKey;
public UIRedDotKeyView(UIRedDotModule redDotModule)
{
m_UIRedDotModule = redDotModule;
m_RedDotKeyAsset = redDotModule.m_RedDotKeyAsset;
m_AllRedDotKey = m_RedDotKeyAsset.AllRedDotDic;
}
public override void Initialize()
{
NewAddRedDataKeyData();
m_ERedDotKeyViewIndexType = m_ERedDotKeyViewIndexTypePrefs.Value;
OnValueChangedKeyViewIndex();
m_UIRedDotModule.OnChangeViewSetIndex += OnChangeViewSetIndex;
CheckContrastRedDotKey();
}
private void CheckContrastRedDotKey()
{
var enumKeyList = GetERedDotKeyTypeList();
if (m_AllRedDotKey.Count != enumKeyList.Count)
{
UnityTipsHelper.CallBack($"当前配置数据 长度:{m_AllRedDotKey.Count} 与 枚举数据 长度:{enumKeyList.Count} 不一致 请重新生成",
CreateKeyEnumClass);
}
}
private List<ERedDotKeyType> GetERedDotKeyTypeList()
{
var list = new List<ERedDotKeyType>();
foreach (ERedDotKeyType key in Enum.GetValues(typeof(ERedDotKeyType)))
{
if (key != ERedDotKeyType.None)
{
list.Add(key);
}
}
return list;
}
private void OnChangeViewSetIndex(UIRedDotModule.EUIRedDotViewType obj)
{
if (obj != UIRedDotModule.EUIRedDotViewType.Key)
{
if (m_WaitCreate)
{
CreateKeyEnumClass();
}
}
}
public override void OnDestroy()
{
m_UIRedDotModule.OnChangeViewSetIndex -= OnChangeViewSetIndex;
if (m_WaitCreate)
{
CreateKeyEnumClass();
}
}
private bool m_WaitCreate = false;
[BoxGroup("生成", centerLabel: true)]
[Button("自动生成Key枚举类", 50)]
[ShowIf("m_WaitCreate")]
[PropertyOrder(10000)]
[GUIColor(0.4f, 0.8f, 1)]
private void CreateKeyEnumClass()
{
m_WaitCreate = false;
var createData = new UICreateRedDotKeyData
{
AutoRefresh = true,
ShowTips = true,
ClassPath = m_UIRedDotModule.UIRedDotKeyClassPath,
Content = UICreateRedDotKeyGet.Get(m_RedDotKeyAsset.GetDataList()),
};
new UICreateRedDotKeyCode(out var resultBase, YIUIAutoTool.Author, createData);
if (!resultBase) return;
}
#region
#region
[HideLabel]
[ShowInInspector]
[ShowIf("m_ERedDotKeyViewIndexType", ERedDotKeyViewIndexType.Add)]
[PropertyOrder(2001)]
[BoxGroup("添加数据", centerLabel: true)]
private RedDotKeyData m_AddKeyData;
[ButtonGroup("添加")]
[Button("添加(生成)", 50)]
[GUIColor(0, 1, 0)]
[ShowIf("m_ERedDotKeyViewIndexType", ERedDotKeyViewIndexType.Add)]
[PropertyOrder(2002)]
private void AddKeyCreateBtn()
{
AddKey();
}
[ButtonGroup("添加")]
[Button("添加(不生成)", 50)]
[GUIColor(1, 1, 0)]
[ShowIf("m_ERedDotKeyViewIndexType", ERedDotKeyViewIndexType.Add)]
[PropertyOrder(2002)]
private void AddKeyBtn()
{
var result = AddKey(false);
if (result)
{
m_WaitCreate = true;
}
}
private bool AddKey(bool createKey = true)
{
var (result, tips) = m_RedDotKeyAsset.AddKey(m_AddKeyData);
NewAddRedDataKeyData();
if (!result)
{
UnityTipsHelper.Show($"{tips} 建议可以直接参考默认ID");
}
else
{
if (createKey)
{
CreateKeyEnumClass();
}
else
{
UnityTipsHelper.Show(tips);
}
}
return result;
}
private void NewAddRedDataKeyData()
{
var id = m_RedDotKeyAsset.GetSafetyId();
m_AddKeyData = new RedDotKeyData(id);
}
#endregion
#region
//TODO 目前删除/修改 前检测只做了配置档
//最终目标应该还额外扫描其他的
//1 预制体 关联了那些红点的预制体 上面会关联Key 这个对应的修改删除
//2 代码 某些代码会涉及到 获取 修改等 也对应的修改删除
[ShowInInspector]
[ShowIf("m_ERedDotKeyViewIndexType", ERedDotKeyViewIndexType.Delete)]
[LabelText("删除的ID")]
[PropertyOrder(3001)]
[BoxGroup("删除数据", centerLabel: true)]
private int m_DeleteId = 0;
[Button("删除", 50)]
[GUIColor(1f, 0.3f, 0.3f)]
[ShowIf("m_ERedDotKeyViewIndexType", ERedDotKeyViewIndexType.Delete)]
[PropertyOrder(3002)]
private void DeleteKeyBtn()
{
if (!m_RedDotKeyAsset.ContainsKey(m_DeleteId))
{
UnityTipsHelper.Show($"当前ID不存在 无法移除 {m_DeleteId}");
return;
}
var linkData =
UIRedDotKeyEditorHelper.GetCheckKeyLink(m_UIRedDotModule.m_RedDotConfigAsset,
(ERedDotKeyType)m_DeleteId);
if (linkData.ConfigSet || linkData.LinkKey.Count >= 1)
{
var configSetTips = linkData.ConfigSet ? "已配置" : "未配置";
var linkTips = $"关联引用 {linkData.LinkKey.Count}";
foreach (var linkKey in linkData.LinkKey)
{
linkTips += $"\n已被 {linkKey} 设定为父级";
}
var unityTips = $"{linkData.Key} 已被使用 确定删除吗?\n\n{configSetTips}\n{linkTips}\n\n同步的将会删除所有关联数据";
UnityTipsHelper.CallBack(unityTips, () =>
{
DeleteKey((result) =>
{
if (!result) return;
UIRedDotKeyEditorHelper.RemoveKeyByLink(m_UIRedDotModule.m_RedDotConfigAsset, linkData);
CreateKeyEnumClass();
YIUIAutoTool.CloseWindowRefresh();
}, false);
});
}
else
{
DeleteKey((result) =>
{
if (!result) return;
CreateKeyEnumClass();
});
}
}
private void DeleteKey(Action<bool> resultAction = null, bool showTips = true)
{
var (result, tips) = m_RedDotKeyAsset.RemoveKey(m_DeleteId);
if (showTips)
UnityTipsHelper.Show(tips);
m_DeleteId = 0;
resultAction?.Invoke(result);
}
#endregion
#region
//TODO 目前删除/修改 前检测只做了配置档
//最终目标应该还额外扫描其他的
//1 预制体 关联了那些红点的预制体 上面会关联Key 这个对应的修改删除
//2 代码 某些代码会涉及到 获取 修改等 也对应的修改删除
[HideLabel]
[ShowInInspector]
[ShowIf("ShowIfChangeKeyData")]
[PropertyOrder(4001)]
[BoxGroup("修改数据", centerLabel: true)]
private RedDotKeyData m_ChangeKeyData;
private bool ShowIfChangeKeyData()
{
if (m_ERedDotKeyViewIndexType != ERedDotKeyViewIndexType.Change)
{
return false;
}
return m_ChangeKeyData != null;
}
[Button("修改", 50)]
[GUIColor(0.7f, 0.4f, 0.8f)]
[ShowIf("m_ERedDotKeyViewIndexType", ERedDotKeyViewIndexType.Change)]
[PropertyOrder(4002)]
private void ChangeKeyBtn()
{
if (m_ChangeKeyData == null)
{
UnityTipsHelper.Show($"请先 查询>>设置 需要修改的数据");
return;
}
var linkData =
UIRedDotKeyEditorHelper.GetCheckKeyLink(m_UIRedDotModule.m_RedDotConfigAsset,
(ERedDotKeyType)m_GetKeyData.Id);
if (linkData.ConfigSet || linkData.LinkKey.Count >= 1)
{
var configSetTips = linkData.ConfigSet ? "已配置" : "未配置";
var linkTips = $"关联引用 {linkData.LinkKey.Count}";
foreach (var linkKey in linkData.LinkKey)
{
linkTips += $"\n已被 {linkKey} 设定为父级";
}
var unityTips = $"{linkData.Key} 已被使用 确定修改吗?\n\n{configSetTips}\n{linkTips}\n\n同步的将会修改所有关联数据";
UnityTipsHelper.CallBack(unityTips, () =>
{
ChangeKey((result) =>
{
if (!result) return;
CreateKeyEnumClass();
UIRedDotKeyEditorHelper.ChangeKeyByLink(m_UIRedDotModule.m_RedDotConfigAsset, linkData,
m_ChangeKeyData);
YIUIAutoTool.CloseWindowRefresh();
}, false);
});
}
else
{
ChangeKey((result) =>
{
if (!result) return;
CreateKeyEnumClass();
});
}
}
private void ChangeKey(Action<bool> resultAction = null, bool showTips = true)
{
if (m_ChangeKeyData == null)
{
UnityTipsHelper.Show($"请先 查询>>设置 需要修改的数据");
return;
}
var (result, tips) = m_RedDotKeyAsset.ChangeKey(m_GetKeyData.Id, m_ChangeKeyData);
if (showTips)
UnityTipsHelper.Show(tips);
resultAction?.Invoke(result);
if (result)
{
m_GetKeyData = null;
m_ChangeKeyData = null;
}
}
private void UpdateChangeData(RedDotKeyData getData)
{
if (getData == null)
{
m_ChangeKeyData = null;
return;
}
m_ChangeKeyData = new RedDotKeyData(getData.Id, getData.Des);
}
#endregion
#region
[ShowInInspector]
[HideIf("m_ERedDotKeyViewIndexType", ERedDotKeyViewIndexType.Add)]
[LabelText("查询的ID")]
[PropertyOrder(1001)]
[InlineButton("GetKey", "查询")]
[BoxGroup("查询数据", centerLabel: true)]
[GUIColor(1, 1, 0)]
private int m_GetId = 1;
[ShowInInspector]
[ReadOnly]
[ShowIf("ShowGetKeyData")]
[BoxGroup("查询数据", centerLabel: true)]
[PropertyOrder(1002)]
private RedDotKeyData m_GetKeyData;
private bool ShowGetKeyData()
{
if (m_ERedDotKeyViewIndexType == ERedDotKeyViewIndexType.Add)
{
return false;
}
return m_GetKeyData != null;
}
private void GetKey()
{
var (data, tips) = m_RedDotKeyAsset.GetKey(m_GetId);
m_GetKeyData = data;
UnityTipsHelper.Show(tips);
UpdateChangeData(data);
}
#endregion
#endregion
[HideLabel]
private enum ERedDotKeyViewIndexType
{
[LabelText("增")]
Add = 1,
[LabelText("删")]
Delete = 2,
[LabelText("改")]
Change = 3,
[LabelText("查")]
Get = 4,
}
}
}
#endif

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: c7e3a45933044e50a9e011abf50c938b
timeCreated: 1686650367

View File

@@ -0,0 +1,162 @@
//------------------------------------------------------------
// Author: 亦亦
// Mail: 379338943@qq.com
// Data: 2023年2月12日
//------------------------------------------------------------
#if UNITY_EDITOR
using System;
using System.IO;
using Sirenix.OdinInspector;
using UnityEditor;
using UnityEngine;
namespace YIUIFramework.Editor
{
internal class UIRedDotModule : BaseYIUIToolModule
{
private EnumPrefs<EUIRedDotViewType> m_EUIRedDotViewTypePrefs =
new EnumPrefs<EUIRedDotViewType>("AutoUIRedDotModule_EUIRedDotViewTypePrefs", null, EUIRedDotViewType.Key);
private const string UIRedDotAssetFolderPath = "Assets/GameRes/RedDot";
[LabelText("红点枚举资源路径")]
[FolderPath]
[ShowInInspector]
[ReadOnly]
public const string UIRedDotKeyAssetPath = "Assets/GameRes/RedDot/RedDotKeyAsset.asset";
[ShowInInspector]
[ReadOnly]
internal RedDotKeyAsset m_RedDotKeyAsset;
[LabelText("红点枚举类路径")]
[FolderPath]
[ShowInInspector]
[ReadOnly]
public string UIRedDotKeyClassPath =
$"{UIStaticHelper.UIFrameworkPath}/Plugins/YIUIRedDot/Runtime/Key/RedDotKeyEnum.cs";
[LabelText("红点关系配置资源路径")]
[FolderPath]
[ShowInInspector]
[ReadOnly]
public const string UIRedDotConfigAssetPath = "Assets/GameRes/RedDot/RedDotConfigAsset.asset";
[ShowInInspector]
[ReadOnly]
internal RedDotConfigAsset m_RedDotConfigAsset;
[EnumToggleButtons]
[HideLabel]
[ShowInInspector]
[BoxGroup("红点设置", centerLabel: true)]
[OnValueChanged("OnValueChangedViewSetIndex")]
private EUIRedDotViewType m_EUIRedDotViewType = EUIRedDotViewType.Key;
internal Action<EUIRedDotViewType> OnChangeViewSetIndex;
private void OnValueChangedViewSetIndex()
{
m_EUIRedDotViewTypePrefs.Value = m_EUIRedDotViewType;
OnChangeViewSetIndex?.Invoke(m_EUIRedDotViewType);
}
//key界面 (增删改查)
[ShowInInspector]
[ShowIf("m_EUIRedDotViewType", EUIRedDotViewType.Key)]
private UIRedDotKeyView m_KeyView;
//配置界面 所有key之间的关系配置
[ShowInInspector]
[ShowIf("m_EUIRedDotViewType", EUIRedDotViewType.Config)]
private UIRedDotConfigView m_ConfigView;
public override void Initialize()
{
m_EUIRedDotViewType = m_EUIRedDotViewTypePrefs.Value;
LoadRedDotKeyAsset();
LoadRedDotConfigAsset();
m_KeyView = new UIRedDotKeyView(this);
m_KeyView.Initialize();
m_ConfigView = new UIRedDotConfigView(this);
m_ConfigView.Initialize();
}
public override void OnDestroy()
{
m_KeyView.OnDestroy();
m_ConfigView.OnDestroy();
AssetDatabase.SaveAssets();
}
#region Key
private void LoadRedDotKeyAsset()
{
m_RedDotKeyAsset = AssetDatabase.LoadAssetAtPath<RedDotKeyAsset>(UIRedDotKeyAssetPath);
if (m_RedDotKeyAsset == null)
{
CreateRedDotKeyAsset();
}
if (m_RedDotKeyAsset == null)
{
Debug.LogError($"没有找到 Key 配置资源 且自动创建失败 请检查");
}
}
private void CreateRedDotKeyAsset()
{
m_RedDotKeyAsset = ScriptableObject.CreateInstance<RedDotKeyAsset>();
var assetFolder = Application.dataPath + UIRedDotAssetFolderPath.Replace("Assets", "");
if (!Directory.Exists(assetFolder))
Directory.CreateDirectory(assetFolder);
AssetDatabase.CreateAsset(m_RedDotKeyAsset, UIRedDotKeyAssetPath);
}
#endregion
#region Config
private void LoadRedDotConfigAsset()
{
m_RedDotConfigAsset = AssetDatabase.LoadAssetAtPath<RedDotConfigAsset>(UIRedDotConfigAssetPath);
if (m_RedDotConfigAsset == null)
{
CreateRedDotConfigAsset();
}
if (m_RedDotConfigAsset == null)
{
Debug.LogError($"没有找到 Config 配置资源 且自动创建失败 请检查");
}
}
private void CreateRedDotConfigAsset()
{
m_RedDotConfigAsset = ScriptableObject.CreateInstance<RedDotConfigAsset>();
var assetFolder = Application.dataPath + UIRedDotAssetFolderPath.Replace("Assets", "");
if (!Directory.Exists(assetFolder))
Directory.CreateDirectory(assetFolder);
AssetDatabase.CreateAsset(m_RedDotConfigAsset, UIRedDotConfigAssetPath);
}
#endregion
[HideLabel]
internal enum EUIRedDotViewType
{
[LabelText("枚举 Key")]
Key = 1,
[LabelText("配置 Config")]
Config = 2,
}
}
}
#endif

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: bf94993135a344e58bbfb1738e83cee0
timeCreated: 1686650033