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 _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 targetDict, string className, string nameSpaceName, string savePath = "Assets/Scripts/Generated") { var window = GetWindow(); 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> 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} /// {desc.Replace("\n", " ")} "); } // 添加常量定义 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>(); string currentSummary = ""; Regex summaryRegex = new Regex(@"///\s*\s*(.*?)\s*"); 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(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