增加UI绑定对GameObject的支持 单个以及数组组件

This commit is contained in:
陈思海 2025-11-19 13:02:07 +08:00
parent 958364080f
commit 33922c9521
2 changed files with 63 additions and 36 deletions

View File

@ -181,8 +181,8 @@ namespace AlicizaX.UI.Editor
} }
uiBindDatas? uiBindDatas?
.Where(bindData => bindData?.BindCom?.FirstOrDefault() != null) .Where(bindData => bindData?.Objs?.FirstOrDefault() != null)
.Select(bindData => bindData.BindCom[0].GetType().Namespace) .Select(bindData => bindData.GetFirstOrDefaultType().Namespace)
.Where(ns => !string.IsNullOrEmpty(ns)) .Where(ns => !string.IsNullOrEmpty(ns))
.ToList() .ToList()
.ForEach(ns => namespaceSet.Add(ns)); .ForEach(ns => namespaceSet.Add(ns));
@ -207,7 +207,7 @@ namespace AlicizaX.UI.Editor
{ {
var variableName = bindData.Name; var variableName = bindData.Name;
var publicName = GetPublicComponentByNameRule(variableName); var publicName = GetPublicComponentByNameRule(variableName);
var firstType = bindData.BindCom?.FirstOrDefault()?.GetType(); var firstType = bindData.GetFirstOrDefaultType();
var typeName = firstType?.Name ?? "Component"; var typeName = firstType?.Name ?? "Component";
var declaration = new StringBuilder(); var declaration = new StringBuilder();
@ -222,7 +222,7 @@ namespace AlicizaX.UI.Editor
break; break;
case EBindType.ListCom: case EBindType.ListCom:
var count = Math.Max(0, bindData.BindCom?.Count ?? 0); var count = Math.Max(0, bindData.Objs?.Count ?? 0);
declaration.AppendLine($"\t\tprivate {typeName}[] {variableName} = new {typeName}[{count}];"); declaration.AppendLine($"\t\tprivate {typeName}[] {variableName} = new {typeName}[{count}];");
declaration.Append($"\t\tpublic {typeName}[] {publicName} => {variableName};"); declaration.Append($"\t\tpublic {typeName}[] {publicName} => {variableName};");
break; break;

View File

@ -22,18 +22,33 @@ namespace AlicizaX.UI.Editor
public class UIBindData public class UIBindData
{ {
public string Name { get; } public string Name { get; }
public List<Component> BindCom { get; }
public EBindType BindType { get; }
public UIBindData(string name, List<Component> bindCom, EBindType bindType = EBindType.None) public List<GameObject> Objs { get; set; }
public EBindType BindType { get; }
public bool IsGameObject => nameof(GameObject).Equals(TypeName);
public string TypeName = string.Empty;
public Type GetFirstOrDefaultType()
{ {
Name = name ?? throw new ArgumentNullException(nameof(name)); if (IsGameObject)
BindCom = bindCom ?? new List<Component>(); {
BindType = bindType; return typeof(GameObject);
}
return Objs.FirstOrDefault()?.GetComponent(TypeName).GetType();
} }
public UIBindData(string name, Component bindCom, EBindType bindType = EBindType.None) public UIBindData(string name, List<GameObject> objs, string typeName = "", EBindType bindType = EBindType.None)
: this(name, new List<Component> { bindCom }, bindType) {
Name = name;
Objs = objs ?? new List<GameObject>();
BindType = bindType;
TypeName = typeName;
}
public UIBindData(string name, GameObject obj, string typeName = "", EBindType bindType = EBindType.None)
: this(name, new List<GameObject> { obj }, typeName, bindType)
{ {
} }
} }
@ -176,11 +191,16 @@ namespace AlicizaX.UI.Editor
var typeName = GetUIElementComponentType(com); var typeName = GetUIElementComponentType(com);
if (string.IsNullOrEmpty(typeName)) continue; if (string.IsNullOrEmpty(typeName)) continue;
var component = node.GetComponent(typeName);
if (component == null) bool isGameObject = typeName.Equals(nameof(GameObject));
if (!isGameObject)
{ {
Debug.LogError($"{node.name} does not have component of type {typeName}"); var component = node.GetComponent(typeName);
continue; if (component == null)
{
Debug.LogError($"{node.name} does not have component of type {typeName}");
continue;
}
} }
var keyName = UIGeneratorRuleHelper.GetPrivateComponentByNameRule(com, node.name, EBindType.None); var keyName = UIGeneratorRuleHelper.GetPrivateComponentByNameRule(com, node.name, EBindType.None);
@ -190,7 +210,7 @@ namespace AlicizaX.UI.Editor
continue; continue;
} }
_uiBindDatas.Add(new UIBindData(keyName, component)); _uiBindDatas.Add(new UIBindData(keyName, node.gameObject, typeName));
} }
} }
@ -220,7 +240,7 @@ namespace AlicizaX.UI.Editor
return; return;
} }
_uiBindDatas.Add(new UIBindData(keyName, component, EBindType.Widget)); _uiBindDatas.Add(new UIBindData(keyName, component.gameObject, component.name, EBindType.Widget));
} }
private static void CollectArrayComponent(List<Transform> arrayNode, string nodeName) private static void CollectArrayComponent(List<Transform> arrayNode, string nodeName)
@ -256,7 +276,7 @@ namespace AlicizaX.UI.Editor
return componentArray.Select((com, index) => return componentArray.Select((com, index) =>
{ {
var keyName = UIGeneratorRuleHelper.GetPrivateComponentByNameRule(com, nodeName, EBindType.ListCom); var keyName = UIGeneratorRuleHelper.GetPrivateComponentByNameRule(com, nodeName, EBindType.ListCom);
return new UIBindData(keyName, new List<Component>(), EBindType.ListCom); return new UIBindData(keyName, new List<GameObject>(), com, EBindType.ListCom);
}).ToList(); }).ToList();
} }
@ -269,13 +289,15 @@ namespace AlicizaX.UI.Editor
var typeName = GetUIElementComponentType(com); var typeName = GetUIElementComponentType(com);
if (string.IsNullOrEmpty(typeName)) continue; if (string.IsNullOrEmpty(typeName)) continue;
tempBindDatas[index].TypeName = typeName;
foreach (var node in orderedNodes) foreach (var node in orderedNodes)
{ {
var component = node.GetComponent(typeName); var isGameObject = typeName.Equals(nameof(GameObject));
if (component != null) var component = isGameObject ? null : node.GetComponent(typeName);
if (component != null || isGameObject)
{ {
tempBindDatas[index].BindCom.Add(component); tempBindDatas[index].Objs.Add(node.gameObject);
} }
else else
{ {
@ -396,8 +418,8 @@ namespace AlicizaX.UI.Editor
return; return;
} }
var component = targetObject.GetOrAddComponent(scriptType); var targetHolder = targetObject.GetOrAddComponent(scriptType);
BindFieldsToComponents(component, scriptType); BindFieldsToComponents(targetHolder, scriptType);
} }
private static Type FindScriptType(string scriptClassName) private static Type FindScriptType(string scriptClassName)
@ -410,36 +432,37 @@ namespace AlicizaX.UI.Editor
type.Name.Equals(scriptClassName, StringComparison.Ordinal)); type.Name.Equals(scriptClassName, StringComparison.Ordinal));
} }
private static void BindFieldsToComponents(Component component, Type scriptType) private static void BindFieldsToComponents(Component targetHolder, Type scriptType)
{ {
var fields = scriptType.GetFields(BindingFlags.NonPublic | BindingFlags.Instance); var fields = scriptType.GetFields(BindingFlags.NonPublic | BindingFlags.Instance);
foreach (var field in fields.Where(field => !string.IsNullOrEmpty(field.Name))) foreach (var field in fields.Where(field => !string.IsNullOrEmpty(field.Name)))
{ {
var components = _uiBindDatas.Find(data => data.Name == field.Name)?.BindCom; var bindData = _uiBindDatas.Find(data => data.Name == field.Name);
var components = bindData.Objs;
if (components == null) if (components == null)
{ {
Debug.LogError($"Field {field.Name} did not find matching component binding"); Debug.LogError($"Field {field.Name} did not find matching component binding");
continue; continue;
} }
SetFieldValue(field, components, component); SetFieldValue(field, components, bindData.TypeName, targetHolder);
} }
} }
private static void SetFieldValue(FieldInfo field, IReadOnlyList<Component> components, Component targetComponent) private static void SetFieldValue(FieldInfo field, IReadOnlyList<GameObject> components, string typeName, Component targetComponent)
{ {
if (field.FieldType.IsArray) if (field.FieldType.IsArray)
{ {
SetArrayFieldValue(field, components, targetComponent); SetArrayFieldValue(field, components, typeName, targetComponent);
} }
else else
{ {
SetSingleFieldValue(field, components, targetComponent); SetSingleFieldValue(field, components, typeName, targetComponent);
} }
} }
private static void SetArrayFieldValue(FieldInfo field, IReadOnlyList<Component> components, Component targetComponent) private static void SetArrayFieldValue(FieldInfo field, IReadOnlyList<GameObject> components, string typeName, Component targetComponent)
{ {
var elementType = field.FieldType.GetElementType(); var elementType = field.FieldType.GetElementType();
if (elementType == null) if (elementType == null)
@ -453,9 +476,12 @@ namespace AlicizaX.UI.Editor
{ {
if (components[i] == null) continue; if (components[i] == null) continue;
if (elementType.IsInstanceOfType(components[i])) var isGameobject = typeName.Equals(nameof(GameObject));
object ComponentObject = isGameobject ? components[i] : components[i].GetComponent(typeName);
if (elementType.IsInstanceOfType(ComponentObject))
{ {
array.SetValue(components[i], i); array.SetValue(ComponentObject, i);
} }
else else
{ {
@ -466,11 +492,12 @@ namespace AlicizaX.UI.Editor
field.SetValue(targetComponent, array); field.SetValue(targetComponent, array);
} }
private static void SetSingleFieldValue(FieldInfo field, IReadOnlyList<Component> components, Component targetComponent) private static void SetSingleFieldValue(FieldInfo field, IReadOnlyList<GameObject> components, string typeName, Component targetComponent)
{ {
if (components.Count == 0) return; if (components.Count == 0) return;
var firstComponent = components[0]; var isGameobject = typeName.Equals(nameof(GameObject));
object firstComponent = isGameobject ? components[0] : components[0].GetComponent(typeName);
if (firstComponent == null) return; if (firstComponent == null) return;
if (field.FieldType.IsInstanceOfType(firstComponent)) if (field.FieldType.IsInstanceOfType(firstComponent))