Files
Cielonos/Assets/Scripts/MainGame/Base/Attribute/StaticAttributeClassGenerationWindow.cs
SoulliesOfficial 9a9e48f8a5
2026-06-27 12:52:03 -04:00

175 lines
6.6 KiB
C#

using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using Sirenix.OdinInspector;
using UnityEditor;
using UnityEngine;
#if UNITY_EDITOR
using Sirenix.OdinInspector.Editor;
namespace SLSUtilities.General
{
public class DictionaryCodeGeneratorWindow : OdinEditorWindow
{
// 临时持有目标字典的引用
private SerializedDictionary<string, string> _targetDict;
[Title("代码生成设置")]
[LabelText("类名")]
public string ClassName = "AttributeKeys";
[LabelText("命名空间")]
public string NamespaceName = "Cielonos.Generated";
[FolderPath, LabelText("保存路径")]
public string SavePath = "Assets/Scripts/Generated";
// 静态打开方法
public static void Open(SerializedDictionary<string, string> targetDict,
string className, string nameSpaceName, string savePath = "Assets/Scripts/Generated")
{
var window = GetWindow<DictionaryCodeGeneratorWindow>();
window.titleContent = new GUIContent("常量生成器");
window._targetDict = targetDict;
window.ClassName = className; // 设置默认类名
window.NamespaceName = nameSpaceName; // 设置默认命名空间
window.SavePath = savePath; // 设置默认保存路径
window.Show();
}
[Button("生成代码 (Generate)", ButtonSizes.Large), PropertyOrder(10)]
[GUIColor(0.4f, 0.8f, 0.4f)]
public void Generate()
{
if (_targetDict == null)
{
Debug.LogError("字典引用丢失,请重新打开窗口。");
return;
}
StringBuilder sb = new StringBuilder();
// 1. 生成头部
sb.AppendLine("// ========================================================");
sb.AppendLine($"// Auto-generated from SerializedDictionary: {ClassName}");
sb.AppendLine("// ========================================================");
sb.AppendLine("");
if (!string.IsNullOrEmpty(NamespaceName))
{
sb.AppendLine($"namespace {NamespaceName}");
sb.AppendLine("{");
}
string indent = string.IsNullOrEmpty(NamespaceName) ? "" : " ";
sb.AppendLine($"{indent}public static class {ClassName}");
sb.AppendLine($"{indent}{{");
// 2. 遍历字典内容
// SerializedDictionary 实现了 IEnumerable<KeyValuePair<string, string>>
foreach (var kvp in _targetDict)
{
string key = kvp.Key;
string desc = kvp.Value;
// 简单的变量名过滤 (只保留字母数字下划线)
string varName = Regex.Replace(key, "[^a-zA-Z0-9_]", "");
// 修正:变量名不能以数字开头
if (varName.Length > 0 && char.IsDigit(varName[0]))
varName = "_" + varName;
if (string.IsNullOrEmpty(varName)) continue;
// 添加注释
if (!string.IsNullOrEmpty(desc))
{
sb.AppendLine($"{indent} /// <summary> {desc.Replace("\n", " ")} </summary>");
}
// 添加常量定义
sb.AppendLine($"{indent} public const string {varName} = \"{key}\";");
}
sb.AppendLine($"{indent}}}");
if (!string.IsNullOrEmpty(NamespaceName)) sb.AppendLine("}");
// 3. 写入文件
if (!Directory.Exists(SavePath)) Directory.CreateDirectory(SavePath);
string fullPath = Path.Combine(SavePath, $"{ClassName}.cs");
File.WriteAllText(fullPath, sb.ToString(), Encoding.UTF8);
AssetDatabase.Refresh();
ShowNotification(new GUIContent("生成成功!"));
Debug.Log($"[CodeGenerator] 文件已生成: {fullPath}");
}
[Button("反向同步 (Sync from Script)", ButtonSizes.Large), PropertyOrder(11)]
[GUIColor(0.4f, 0.6f, 0.8f)]
public void SyncFromScript()
{
if (_targetDict == null)
{
Debug.LogError("字典引用丢失,请重新打开窗口。");
return;
}
string fullPath = Path.Combine(SavePath, $"{ClassName}.cs");
if (!File.Exists(fullPath))
{
Debug.LogError($"[CodeGenerator] 找不到文件: {fullPath}");
return;
}
string[] lines = File.ReadAllLines(fullPath, Encoding.UTF8);
var newEntries = new System.Collections.Generic.List<System.Collections.Generic.KeyValuePair<string, string>>();
string currentSummary = "";
Regex summaryRegex = new Regex(@"///\s*<summary>\s*(.*?)\s*</summary>");
Regex constRegex = new Regex(@"public\s+const\s+string\s+\w+\s*=\s*""([^""]+)""\s*;");
foreach (var line in lines)
{
string trimmed = line.Trim();
Match sumMatch = summaryRegex.Match(trimmed);
if (sumMatch.Success)
{
currentSummary = sumMatch.Groups[1].Value;
continue;
}
Match constMatch = constRegex.Match(trimmed);
if (constMatch.Success)
{
string key = constMatch.Groups[1].Value;
newEntries.Add(new System.Collections.Generic.KeyValuePair<string, string>(key, currentSummary));
currentSummary = ""; // 匹配完毕后清空,准备匹配下一个
}
}
if (newEntries.Count > 0)
{
_targetDict.Clear();
foreach (var kvp in newEntries)
{
if (!_targetDict.ContainsKey(kvp.Key))
{
_targetDict.Add(kvp.Key, kvp.Value);
}
}
ShowNotification(new GUIContent("反向同步成功!"));
Debug.Log($"[CodeGenerator] 从 {fullPath} 成功同步了 {newEntries.Count} 个属性到字典中。由于直接修改了内存数据,请记得手动保存包含该字典的资源文件。");
}
else
{
Debug.LogWarning($"[CodeGenerator] 在 {fullPath} 中没有找到任何常量定义。");
}
}
}
}
#endif