using System.Collections.Generic; using System.Linq; using System.Text; using System.Text.RegularExpressions; using UnityEditor; using UnityEngine; namespace TyphoonUI { /// /// 视图代码生成器 /// public class ViewCodeGenerator { //试图 public UIObject View; //名字计数 public Dictionary NameCounter = new Dictionary(); //已使用的名称 public HashSet NameUsed = new HashSet(); /*成员*/ public Dictionary Members = new Dictionary(); /*类名*/ public string ClassName; /*InitializeView 方法*/ private StringBuilder _methodInitializeViewCode = new StringBuilder(); /*视图成员属性代码*/ private StringBuilder _viewPropertyFieldCode = new StringBuilder(); public string GetNamespace() { return string.IsNullOrEmpty(View.NameSpace) ? GetDefaultNamespace() : View.NameSpace; } public string GetFullClassName() => string.IsNullOrEmpty(View.NameSpace) ? $"{GetDefaultNamespace()}.{ClassName}" : $"{View.NameSpace}.{ClassName}"; private string GetDefaultNamespace() { if (string.IsNullOrEmpty(Preferences.Default.DefaultNamespace)) { return "TyphoonUIExport"; } return Preferences.Default.DefaultNamespace; } private string GetExportFolder() { return $"{Paths.ExportCodeFolder}/{GetNamespace()}"; } public class MemberInfo { public Object Node; //后缀名 public string Suffix; //前缀名 public string Prefix; public MemberInfo(Object node, string suffix, string prefix) { Node = node; Suffix = suffix; Prefix = prefix; var type = node.GetType(); if (type == typeof(UIObject) || type.IsSubclassOf(typeof(UIObject))) { Prefix = $"ViewObject_{Prefix}"; } } public string GetBaseMemberName() { return !string.IsNullOrEmpty(Suffix) ? $"{Prefix}{Suffix}" : $"{Prefix}"; } public string GetMemberName(HashSet usedNames) { var name = GetBaseMemberName(); if (usedNames.Contains(name)) { var count = usedNames.Where(e => Regex.IsMatch(e, $"{name}_no[0-9]*")).Count(); name = $"{name}_no{count + 1}"; } return name; } } public ViewCodeGenerator(UIObject view) { View = view; var className = view.gameObject.name; var corresponding = PrefabUtility.GetCorrespondingObjectFromOriginalSource(view.gameObject); if (corresponding != null) { className = corresponding.gameObject.name; } ClassName = ToMemberName(className); NameCounter.Add(ClassName, 1); } private string ToMemberName(string member) { var result = TyphoonUIEditor.RemoveMemberInvalidCharacters(member); if (result == string.Empty) { result = $"_{GUID.Generate().ToString()}"; } //如果是数字开头,补充_ if (int.TryParse(result.Substring(0, 1), out var num)) { result = $"_{member}"; } return result; } public void Analysis() { var nodes = View.GetValidateNodesHashList(); //按gameobject分组 var group = new Dictionary>(); foreach (var node in nodes) { var go = node is GameObject ? node as GameObject : (node as Component).gameObject; if (go != null) { if (!group.ContainsKey(go)) { group.Add(go, new HashSet()); } group[go].Add(node); } } var infos = new List(); //生成名称 foreach (var kv in group) { var go = kv.Key; var children = kv.Value; var prefix = ToMemberName(go.name); foreach (var child in children) { //如果是导出节点 if (go == View.gameObject) { infos.Add(new MemberInfo(child, child.GetType().Name, prefix)); continue; } if (children.Count > 1) { //导出组件数量大于1,采用gameobject_类型名 infos.Add(new MemberInfo(child, child.GetType().Name, prefix)); } else { //只有前缀名 infos.Add(new MemberInfo(child, "", prefix)); } } } // //修改前缀名 // foreach (var info in infos) // { // var baseName = info.GetBaseMemberName(); // if (!NameCounter.ContainsKey(baseName)) // { // NameCounter.Add(baseName, 0); // } // // info.NameIndex = NameCounter[baseName]; // NameCounter[baseName] += 1; // } //生成清单名称 foreach (var info in infos) { var name = info.GetMemberName(NameUsed); Members.Add(info.Node, info.GetMemberName(NameUsed)); NameUsed.Add(name); } } public Dictionary GetUIObjectMember() { var result = new Dictionary(); foreach (var kv in Members) { if (kv.Key is UIObject) { result.Add(kv.Key as UIObject, kv.Value); } } return result; } public string GenerateCodeSting() { var sb = new StringBuilder(); sb.Clear(); sb.AppendLine($"namespace {GetNamespace()} {{"); sb.AppendLine($"public class {ClassName} : {typeof(IInitializeView).FullName} {{"); //补充初始化方法 sb.AppendLine(_methodInitializeViewCode.ToString()); //补充拓展属性 sb.AppendLine(_viewPropertyFieldCode.ToString()); sb.AppendLine("}"); sb.AppendLine("}"); return sb.ToString(); } //生成InitializeView方法 public void GenerateMethodInitializeView() { var sb = _methodInitializeViewCode; var members = Members; var obj = View; foreach (var member in members) { sb.AppendLine($"public {member.Key.GetType().FullName} {member.Value};"); } //补充构造函数 sb.AppendLine($"public void {nameof(IInitializeView.InitializeView)}({typeof(UIObject).FullName} view){{"); foreach (var member in members) { var index = obj.Nodes.IndexOf(member.Key); sb.AppendLine($"this.{member.Value} = view.Nodes[{index}] as {member.Key.GetType().FullName}; "); } sb.AppendLine("}"); } //生成拓展View属性字段 public void GenerateViewPropertyField(HashSet viewFullClass) { var sb = _viewPropertyFieldCode; //补充UIObject属性 var viewMember = GetUIObjectMember(); foreach (var view in viewMember) { var fullClassName = GetLinkUIObjectViewFullClass(view.Key); var viewField = view.Value; var prefix = "ViewObject_"; if (viewField.StartsWith(prefix)) { viewField = viewField.Substring(prefix.Length); } var private_view_member = $"__view__{viewField}"; var public_view_member = $"{viewField}"; if (viewFullClass.Contains(fullClassName) || TyphoonUIEditor.HasType(fullClassName)) { //补充view属性 sb.AppendLine($"private {fullClassName} {private_view_member}=null;"); sb.AppendLine( $"public {fullClassName} {public_view_member}=>this.{view.Value}.CreateView(ref this.{private_view_member} );"); } else { Debug.Log( $"找不到{fullClassName}.cs,补充view property 失败 请在{fullClassName}.cs生成后再次尝试"); } } } public static string GetLinkUIObjectViewFullClass(UIObject uiObject) { var original = PrefabUtility.GetCorrespondingObjectFromOriginalSource(uiObject); if (original == null) { original = uiObject; } var fullClass = new ViewCodeGenerator(original).GetFullClassName(); return fullClass; } //获取保存路径 public string GetSavePath() { return $"{GetExportFolder()}/{ClassName}.cs"; } } }