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";
}
}
}