增加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?
.Where(bindData => bindData?.BindCom?.FirstOrDefault() != null)
.Select(bindData => bindData.BindCom[0].GetType().Namespace)
.Where(bindData => bindData?.Objs?.FirstOrDefault() != null)
.Select(bindData => bindData.GetFirstOrDefaultType().Namespace)
.Where(ns => !string.IsNullOrEmpty(ns))
.ToList()
.ForEach(ns => namespaceSet.Add(ns));
@ -207,7 +207,7 @@ namespace AlicizaX.UI.Editor
{
var variableName = bindData.Name;
var publicName = GetPublicComponentByNameRule(variableName);
var firstType = bindData.BindCom?.FirstOrDefault()?.GetType();
var firstType = bindData.GetFirstOrDefaultType();
var typeName = firstType?.Name ?? "Component";
var declaration = new StringBuilder();
@ -222,7 +222,7 @@ namespace AlicizaX.UI.Editor
break;
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.Append($"\t\tpublic {typeName}[] {publicName} => {variableName};");
break;

View File

@ -22,18 +22,33 @@ namespace AlicizaX.UI.Editor
public class UIBindData
{
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));
BindCom = bindCom ?? new List<Component>();
BindType = bindType;
if (IsGameObject)
{
return typeof(GameObject);
}
return Objs.FirstOrDefault()?.GetComponent(TypeName).GetType();
}
public UIBindData(string name, Component bindCom, EBindType bindType = EBindType.None)
: this(name, new List<Component> { bindCom }, bindType)
public UIBindData(string name, List<GameObject> objs, string typeName = "", EBindType bindType = EBindType.None)
{
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);
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}");
continue;
var component = node.GetComponent(typeName);
if (component == null)
{
Debug.LogError($"{node.name} does not have component of type {typeName}");
continue;
}
}
var keyName = UIGeneratorRuleHelper.GetPrivateComponentByNameRule(com, node.name, EBindType.None);
@ -190,7 +210,7 @@ namespace AlicizaX.UI.Editor
continue;
}
_uiBindDatas.Add(new UIBindData(keyName, component));
_uiBindDatas.Add(new UIBindData(keyName, node.gameObject, typeName));
}
}
@ -220,7 +240,7 @@ namespace AlicizaX.UI.Editor
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)
@ -256,7 +276,7 @@ namespace AlicizaX.UI.Editor
return componentArray.Select((com, index) =>
{
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();
}
@ -269,13 +289,15 @@ namespace AlicizaX.UI.Editor
var typeName = GetUIElementComponentType(com);
if (string.IsNullOrEmpty(typeName)) continue;
tempBindDatas[index].TypeName = typeName;
foreach (var node in orderedNodes)
{
var component = node.GetComponent(typeName);
if (component != null)
var isGameObject = typeName.Equals(nameof(GameObject));
var component = isGameObject ? null : node.GetComponent(typeName);
if (component != null || isGameObject)
{
tempBindDatas[index].BindCom.Add(component);
tempBindDatas[index].Objs.Add(node.gameObject);
}
else
{
@ -396,8 +418,8 @@ namespace AlicizaX.UI.Editor
return;
}
var component = targetObject.GetOrAddComponent(scriptType);
BindFieldsToComponents(component, scriptType);
var targetHolder = targetObject.GetOrAddComponent(scriptType);
BindFieldsToComponents(targetHolder, scriptType);
}
private static Type FindScriptType(string scriptClassName)
@ -410,36 +432,37 @@ namespace AlicizaX.UI.Editor
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);
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)
{
Debug.LogError($"Field {field.Name} did not find matching component binding");
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)
{
SetArrayFieldValue(field, components, targetComponent);
SetArrayFieldValue(field, components, typeName, targetComponent);
}
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();
if (elementType == null)
@ -453,9 +476,12 @@ namespace AlicizaX.UI.Editor
{
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
{
@ -466,11 +492,12 @@ namespace AlicizaX.UI.Editor
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;
var firstComponent = components[0];
var isGameobject = typeName.Equals(nameof(GameObject));
object firstComponent = isGameobject ? components[0] : components[0].GetComponent(typeName);
if (firstComponent == null) return;
if (field.FieldType.IsInstanceOfType(firstComponent))