2026-03-21 19:57:49 +08:00
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using TMPro;
|
|
|
|
|
|
2026-03-23 14:45:12 +08:00
|
|
|
namespace UnityEngine.UI
|
2026-03-21 19:57:49 +08:00
|
|
|
{
|
|
|
|
|
public sealed class UXBindingPropertyMetadata
|
|
|
|
|
{
|
|
|
|
|
public UXBindingPropertyMetadata(
|
|
|
|
|
UXBindingProperty property,
|
|
|
|
|
string displayName,
|
|
|
|
|
UXBindingValueKind valueKind,
|
|
|
|
|
Type objectReferenceType)
|
|
|
|
|
{
|
|
|
|
|
Property = property;
|
|
|
|
|
DisplayName = displayName;
|
|
|
|
|
ValueKind = valueKind;
|
|
|
|
|
ObjectReferenceType = objectReferenceType;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public UXBindingProperty Property { get; }
|
|
|
|
|
public string DisplayName { get; }
|
|
|
|
|
public UXBindingValueKind ValueKind { get; }
|
|
|
|
|
public Type ObjectReferenceType { get; }
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-28 20:52:06 +08:00
|
|
|
public struct UXBindingResolvedTarget
|
|
|
|
|
{
|
|
|
|
|
public GameObject GameObject;
|
|
|
|
|
public Transform Transform;
|
|
|
|
|
public CanvasGroup CanvasGroup;
|
|
|
|
|
public Graphic Graphic;
|
|
|
|
|
public Image Image;
|
|
|
|
|
public Text Text;
|
|
|
|
|
public TextMeshProUGUI TmpText;
|
|
|
|
|
public RectTransform RectTransform;
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-21 19:57:49 +08:00
|
|
|
public static class UXBindingPropertyUtility
|
|
|
|
|
{
|
|
|
|
|
private static readonly UXBindingPropertyMetadata[] Metadata =
|
|
|
|
|
{
|
|
|
|
|
new UXBindingPropertyMetadata(UXBindingProperty.GameObjectActive, "GameObject/Active", UXBindingValueKind.Boolean, null),
|
|
|
|
|
new UXBindingPropertyMetadata(UXBindingProperty.CanvasGroupAlpha, "CanvasGroup/Alpha", UXBindingValueKind.Float, null),
|
|
|
|
|
new UXBindingPropertyMetadata(UXBindingProperty.CanvasGroupInteractable, "CanvasGroup/Interactable", UXBindingValueKind.Boolean, null),
|
|
|
|
|
new UXBindingPropertyMetadata(UXBindingProperty.CanvasGroupBlocksRaycasts, "CanvasGroup/Blocks Raycasts", UXBindingValueKind.Boolean, null),
|
|
|
|
|
new UXBindingPropertyMetadata(UXBindingProperty.GraphicColor, "Graphic/Color", UXBindingValueKind.Color, null),
|
|
|
|
|
new UXBindingPropertyMetadata(UXBindingProperty.GraphicMaterial, "Graphic/Material", UXBindingValueKind.ObjectReference, typeof(Material)),
|
|
|
|
|
new UXBindingPropertyMetadata(UXBindingProperty.ImageSprite, "Image/Sprite", UXBindingValueKind.ObjectReference, typeof(Sprite)),
|
|
|
|
|
new UXBindingPropertyMetadata(UXBindingProperty.TextContent, "Text/Content", UXBindingValueKind.String, null),
|
|
|
|
|
new UXBindingPropertyMetadata(UXBindingProperty.TextColor, "Text/Color", UXBindingValueKind.Color, null),
|
|
|
|
|
new UXBindingPropertyMetadata(UXBindingProperty.RectTransformAnchoredPosition, "RectTransform/Anchored Position", UXBindingValueKind.Vector2, null),
|
|
|
|
|
new UXBindingPropertyMetadata(UXBindingProperty.TransformLocalScale, "Transform/Local Scale", UXBindingValueKind.Vector3, null),
|
|
|
|
|
new UXBindingPropertyMetadata(UXBindingProperty.TransformLocalEulerAngles, "Transform/Local Rotation", UXBindingValueKind.Vector3, null)
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
public static IReadOnlyList<UXBindingPropertyMetadata> AllMetadata => Metadata;
|
|
|
|
|
|
|
|
|
|
public static UXBindingPropertyMetadata GetMetadata(UXBindingProperty property)
|
|
|
|
|
{
|
2026-04-28 20:52:06 +08:00
|
|
|
int index = (int)property;
|
|
|
|
|
if ((uint)index < (uint)Metadata.Length && Metadata[index].Property == property)
|
|
|
|
|
{
|
|
|
|
|
return Metadata[index];
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-21 19:57:49 +08:00
|
|
|
for (int i = 0; i < Metadata.Length; i++)
|
|
|
|
|
{
|
|
|
|
|
if (Metadata[i].Property == property)
|
|
|
|
|
{
|
|
|
|
|
return Metadata[i];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return Metadata[0];
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-28 20:52:06 +08:00
|
|
|
public static bool Resolve(GameObject target, UXBindingProperty property, out UXBindingResolvedTarget resolvedTarget)
|
2026-03-21 19:57:49 +08:00
|
|
|
{
|
2026-04-28 20:52:06 +08:00
|
|
|
resolvedTarget = default;
|
2026-03-21 19:57:49 +08:00
|
|
|
if (target == null)
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-28 20:52:06 +08:00
|
|
|
resolvedTarget.GameObject = target;
|
|
|
|
|
resolvedTarget.Transform = target.transform;
|
|
|
|
|
|
2026-03-21 19:57:49 +08:00
|
|
|
switch (property)
|
|
|
|
|
{
|
|
|
|
|
case UXBindingProperty.GameObjectActive:
|
|
|
|
|
case UXBindingProperty.TransformLocalScale:
|
|
|
|
|
case UXBindingProperty.TransformLocalEulerAngles:
|
|
|
|
|
return true;
|
|
|
|
|
case UXBindingProperty.CanvasGroupAlpha:
|
|
|
|
|
case UXBindingProperty.CanvasGroupInteractable:
|
|
|
|
|
case UXBindingProperty.CanvasGroupBlocksRaycasts:
|
2026-04-28 20:52:06 +08:00
|
|
|
return target.TryGetComponent(out resolvedTarget.CanvasGroup);
|
2026-03-21 19:57:49 +08:00
|
|
|
case UXBindingProperty.GraphicColor:
|
|
|
|
|
case UXBindingProperty.GraphicMaterial:
|
2026-04-28 20:52:06 +08:00
|
|
|
return target.TryGetComponent(out resolvedTarget.Graphic);
|
2026-03-21 19:57:49 +08:00
|
|
|
case UXBindingProperty.ImageSprite:
|
2026-04-28 20:52:06 +08:00
|
|
|
return target.TryGetComponent(out resolvedTarget.Image);
|
2026-03-21 19:57:49 +08:00
|
|
|
case UXBindingProperty.TextContent:
|
|
|
|
|
case UXBindingProperty.TextColor:
|
2026-04-28 20:52:06 +08:00
|
|
|
if (target.TryGetComponent(out resolvedTarget.Text))
|
|
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return target.TryGetComponent(out resolvedTarget.TmpText);
|
2026-03-21 19:57:49 +08:00
|
|
|
case UXBindingProperty.RectTransformAnchoredPosition:
|
2026-04-28 20:52:06 +08:00
|
|
|
return target.TryGetComponent(out resolvedTarget.RectTransform);
|
2026-03-21 19:57:49 +08:00
|
|
|
default:
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-28 20:52:06 +08:00
|
|
|
public static bool IsSupported(GameObject target, UXBindingProperty property)
|
|
|
|
|
{
|
|
|
|
|
return Resolve(target, property, out _);
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-21 19:57:49 +08:00
|
|
|
public static void GetSupportedProperties(GameObject target, List<UXBindingProperty> output)
|
|
|
|
|
{
|
|
|
|
|
output.Clear();
|
|
|
|
|
if (target == null)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < Metadata.Length; i++)
|
|
|
|
|
{
|
|
|
|
|
UXBindingProperty property = Metadata[i].Property;
|
|
|
|
|
if (IsSupported(target, property))
|
|
|
|
|
{
|
|
|
|
|
output.Add(property);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-28 20:52:06 +08:00
|
|
|
public static bool CaptureValue(GameObject target, UXBindingProperty property, UXBindingValue destination)
|
2026-03-21 19:57:49 +08:00
|
|
|
{
|
2026-04-28 20:52:06 +08:00
|
|
|
if (!Resolve(target, property, out UXBindingResolvedTarget resolvedTarget))
|
2026-03-21 19:57:49 +08:00
|
|
|
{
|
2026-04-28 20:52:06 +08:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return CaptureValue(in resolvedTarget, property, destination);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static bool CaptureValue(in UXBindingResolvedTarget target, UXBindingProperty property, UXBindingValue destination)
|
|
|
|
|
{
|
|
|
|
|
if (destination == null || target.GameObject == null)
|
|
|
|
|
{
|
|
|
|
|
return false;
|
2026-03-21 19:57:49 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch (property)
|
|
|
|
|
{
|
|
|
|
|
case UXBindingProperty.GameObjectActive:
|
2026-04-28 20:52:06 +08:00
|
|
|
destination.BoolValue = target.GameObject.activeSelf;
|
|
|
|
|
return true;
|
2026-03-21 19:57:49 +08:00
|
|
|
case UXBindingProperty.CanvasGroupAlpha:
|
2026-04-28 20:52:06 +08:00
|
|
|
if (target.CanvasGroup == null) return false;
|
|
|
|
|
destination.FloatValue = target.CanvasGroup.alpha;
|
|
|
|
|
return true;
|
2026-03-21 19:57:49 +08:00
|
|
|
case UXBindingProperty.CanvasGroupInteractable:
|
2026-04-28 20:52:06 +08:00
|
|
|
if (target.CanvasGroup == null) return false;
|
|
|
|
|
destination.BoolValue = target.CanvasGroup.interactable;
|
|
|
|
|
return true;
|
2026-03-21 19:57:49 +08:00
|
|
|
case UXBindingProperty.CanvasGroupBlocksRaycasts:
|
2026-04-28 20:52:06 +08:00
|
|
|
if (target.CanvasGroup == null) return false;
|
|
|
|
|
destination.BoolValue = target.CanvasGroup.blocksRaycasts;
|
|
|
|
|
return true;
|
2026-03-21 19:57:49 +08:00
|
|
|
case UXBindingProperty.GraphicColor:
|
2026-04-28 20:52:06 +08:00
|
|
|
if (target.Graphic == null) return false;
|
|
|
|
|
destination.ColorValue = target.Graphic.color;
|
|
|
|
|
return true;
|
2026-03-21 19:57:49 +08:00
|
|
|
case UXBindingProperty.GraphicMaterial:
|
2026-04-28 20:52:06 +08:00
|
|
|
if (target.Graphic == null) return false;
|
|
|
|
|
destination.ObjectValue = target.Graphic.defaultMaterial;
|
|
|
|
|
return true;
|
2026-03-21 19:57:49 +08:00
|
|
|
case UXBindingProperty.ImageSprite:
|
2026-04-28 20:52:06 +08:00
|
|
|
if (target.Image == null) return false;
|
|
|
|
|
destination.ObjectValue = target.Image.sprite;
|
|
|
|
|
return true;
|
2026-03-21 19:57:49 +08:00
|
|
|
case UXBindingProperty.TextContent:
|
2026-04-28 20:52:06 +08:00
|
|
|
if (target.Text != null)
|
2026-03-21 19:57:49 +08:00
|
|
|
{
|
2026-04-28 20:52:06 +08:00
|
|
|
destination.StringValue = target.Text.text;
|
|
|
|
|
return true;
|
2026-03-21 19:57:49 +08:00
|
|
|
}
|
2026-04-28 20:52:06 +08:00
|
|
|
|
|
|
|
|
if (target.TmpText != null)
|
2026-03-21 19:57:49 +08:00
|
|
|
{
|
2026-04-28 20:52:06 +08:00
|
|
|
destination.StringValue = target.TmpText.text;
|
|
|
|
|
return true;
|
2026-03-21 19:57:49 +08:00
|
|
|
}
|
2026-04-28 20:52:06 +08:00
|
|
|
|
|
|
|
|
return false;
|
2026-03-21 19:57:49 +08:00
|
|
|
case UXBindingProperty.TextColor:
|
2026-04-28 20:52:06 +08:00
|
|
|
if (target.Text != null)
|
2026-03-21 19:57:49 +08:00
|
|
|
{
|
2026-04-28 20:52:06 +08:00
|
|
|
destination.ColorValue = target.Text.color;
|
|
|
|
|
return true;
|
2026-03-21 19:57:49 +08:00
|
|
|
}
|
2026-04-28 20:52:06 +08:00
|
|
|
|
|
|
|
|
if (target.TmpText != null)
|
2026-03-21 19:57:49 +08:00
|
|
|
{
|
2026-04-28 20:52:06 +08:00
|
|
|
destination.ColorValue = target.TmpText.color;
|
|
|
|
|
return true;
|
2026-03-21 19:57:49 +08:00
|
|
|
}
|
2026-04-28 20:52:06 +08:00
|
|
|
|
|
|
|
|
return false;
|
2026-03-21 19:57:49 +08:00
|
|
|
case UXBindingProperty.RectTransformAnchoredPosition:
|
2026-04-28 20:52:06 +08:00
|
|
|
if (target.RectTransform == null) return false;
|
|
|
|
|
destination.Vector2Value = target.RectTransform.anchoredPosition;
|
|
|
|
|
return true;
|
2026-03-21 19:57:49 +08:00
|
|
|
case UXBindingProperty.TransformLocalScale:
|
2026-04-28 20:52:06 +08:00
|
|
|
if (target.Transform == null) return false;
|
|
|
|
|
destination.Vector3Value = target.Transform.localScale;
|
|
|
|
|
return true;
|
2026-03-21 19:57:49 +08:00
|
|
|
case UXBindingProperty.TransformLocalEulerAngles:
|
2026-04-28 20:52:06 +08:00
|
|
|
if (target.Transform == null) return false;
|
|
|
|
|
destination.Vector3Value = target.Transform.localEulerAngles;
|
|
|
|
|
return true;
|
|
|
|
|
default:
|
|
|
|
|
return false;
|
2026-03-21 19:57:49 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-28 20:52:06 +08:00
|
|
|
public static bool ApplyValue(GameObject target, UXBindingProperty property, UXBindingValue value)
|
2026-03-21 19:57:49 +08:00
|
|
|
{
|
2026-04-28 20:52:06 +08:00
|
|
|
if (!Resolve(target, property, out UXBindingResolvedTarget resolvedTarget))
|
2026-03-21 19:57:49 +08:00
|
|
|
{
|
2026-04-28 20:52:06 +08:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ApplyValue(in resolvedTarget, property, value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static bool ApplyValue(in UXBindingResolvedTarget target, UXBindingProperty property, UXBindingValue value)
|
|
|
|
|
{
|
|
|
|
|
if (value == null || target.GameObject == null)
|
|
|
|
|
{
|
|
|
|
|
return false;
|
2026-03-21 19:57:49 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch (property)
|
|
|
|
|
{
|
|
|
|
|
case UXBindingProperty.GameObjectActive:
|
2026-04-28 20:52:06 +08:00
|
|
|
target.GameObject.SetActive(value.BoolValue);
|
|
|
|
|
return true;
|
2026-03-21 19:57:49 +08:00
|
|
|
case UXBindingProperty.CanvasGroupAlpha:
|
2026-04-28 20:52:06 +08:00
|
|
|
if (target.CanvasGroup == null) return false;
|
|
|
|
|
target.CanvasGroup.alpha = value.FloatValue;
|
|
|
|
|
return true;
|
2026-03-21 19:57:49 +08:00
|
|
|
case UXBindingProperty.CanvasGroupInteractable:
|
2026-04-28 20:52:06 +08:00
|
|
|
if (target.CanvasGroup == null) return false;
|
|
|
|
|
target.CanvasGroup.interactable = value.BoolValue;
|
|
|
|
|
return true;
|
2026-03-21 19:57:49 +08:00
|
|
|
case UXBindingProperty.CanvasGroupBlocksRaycasts:
|
2026-04-28 20:52:06 +08:00
|
|
|
if (target.CanvasGroup == null) return false;
|
|
|
|
|
target.CanvasGroup.blocksRaycasts = value.BoolValue;
|
|
|
|
|
return true;
|
2026-03-21 19:57:49 +08:00
|
|
|
case UXBindingProperty.GraphicColor:
|
2026-04-28 20:52:06 +08:00
|
|
|
if (target.Graphic == null) return false;
|
|
|
|
|
target.Graphic.color = value.ColorValue;
|
|
|
|
|
return true;
|
2026-03-21 19:57:49 +08:00
|
|
|
case UXBindingProperty.GraphicMaterial:
|
2026-04-28 20:52:06 +08:00
|
|
|
if (target.Graphic == null) return false;
|
|
|
|
|
target.Graphic.material = value.ObjectValue as Material;
|
|
|
|
|
return true;
|
2026-03-21 19:57:49 +08:00
|
|
|
case UXBindingProperty.ImageSprite:
|
2026-04-28 20:52:06 +08:00
|
|
|
if (target.Image == null) return false;
|
|
|
|
|
target.Image.sprite = value.ObjectValue as Sprite;
|
|
|
|
|
return true;
|
2026-03-21 19:57:49 +08:00
|
|
|
case UXBindingProperty.TextContent:
|
2026-04-28 20:52:06 +08:00
|
|
|
if (target.Text != null)
|
2026-03-21 19:57:49 +08:00
|
|
|
{
|
2026-04-28 20:52:06 +08:00
|
|
|
target.Text.text = value.StringValue;
|
|
|
|
|
return true;
|
2026-03-21 19:57:49 +08:00
|
|
|
}
|
2026-04-28 20:52:06 +08:00
|
|
|
|
|
|
|
|
if (target.TmpText != null)
|
2026-03-21 19:57:49 +08:00
|
|
|
{
|
2026-04-28 20:52:06 +08:00
|
|
|
target.TmpText.text = value.StringValue;
|
|
|
|
|
return true;
|
2026-03-21 19:57:49 +08:00
|
|
|
}
|
2026-04-28 20:52:06 +08:00
|
|
|
|
|
|
|
|
return false;
|
2026-03-21 19:57:49 +08:00
|
|
|
case UXBindingProperty.TextColor:
|
2026-04-28 20:52:06 +08:00
|
|
|
if (target.Text != null)
|
2026-03-21 19:57:49 +08:00
|
|
|
{
|
2026-04-28 20:52:06 +08:00
|
|
|
target.Text.color = value.ColorValue;
|
|
|
|
|
return true;
|
2026-03-21 19:57:49 +08:00
|
|
|
}
|
2026-04-28 20:52:06 +08:00
|
|
|
|
|
|
|
|
if (target.TmpText != null)
|
2026-03-21 19:57:49 +08:00
|
|
|
{
|
2026-04-28 20:52:06 +08:00
|
|
|
target.TmpText.color = value.ColorValue;
|
|
|
|
|
return true;
|
2026-03-21 19:57:49 +08:00
|
|
|
}
|
2026-04-28 20:52:06 +08:00
|
|
|
|
|
|
|
|
return false;
|
2026-03-21 19:57:49 +08:00
|
|
|
case UXBindingProperty.RectTransformAnchoredPosition:
|
2026-04-28 20:52:06 +08:00
|
|
|
if (target.RectTransform == null) return false;
|
|
|
|
|
target.RectTransform.anchoredPosition = value.Vector2Value;
|
|
|
|
|
return true;
|
2026-03-21 19:57:49 +08:00
|
|
|
case UXBindingProperty.TransformLocalScale:
|
2026-04-28 20:52:06 +08:00
|
|
|
if (target.Transform == null) return false;
|
|
|
|
|
target.Transform.localScale = value.Vector3Value;
|
|
|
|
|
return true;
|
2026-03-21 19:57:49 +08:00
|
|
|
case UXBindingProperty.TransformLocalEulerAngles:
|
2026-04-28 20:52:06 +08:00
|
|
|
if (target.Transform == null) return false;
|
|
|
|
|
target.Transform.localEulerAngles = value.Vector3Value;
|
|
|
|
|
return true;
|
|
|
|
|
default:
|
|
|
|
|
return false;
|
2026-03-21 19:57:49 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|