From 3fbb82f40ed556587a397a753be98fe61eb602c3 Mon Sep 17 00:00:00 2001 From: lrc <571244399@qq.com> Date: Sat, 25 Jul 2026 22:47:14 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=86=E7=A6=BB=E5=85=B7=E4=BD=93=E5=B1=9E?= =?UTF-8?q?=E6=80=A7=E7=BB=84=E4=BB=B6=EF=BC=8C=E5=8A=A0=E5=85=A5=E6=A0=B7?= =?UTF-8?q?=E5=BC=8F=E8=A1=A8=E7=B3=BB=E7=BB=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Scripts/Accessors.meta | 8 ++ .../MaterialPropertyAccessor.cs.meta | 11 ++ .../Accessors/ReflectionValueAccessor.cs | 2 +- .../Accessors/ReflectionValueAccessor.cs.meta | 11 ++ .../XuiavrgFieldDropdownValueAttribute.cs | 5 + ...XuiavrgFieldDropdownValueAttribute.cs.meta | 11 ++ .../XuiavrgFieldToggleGroupValueAttribute.cs | 5 + ...avrgFieldToggleGroupValueAttribute.cs.meta | 11 ++ .../XuiavrgStyleNamespaceAttribute.cs | 33 +++++ .../XuiavrgStyleNamespaceAttribute.cs.meta | 11 ++ .../Scripts/AvrgMemberMetaData.cs | 6 + .../Scripts/Core.meta | 8 ++ .../Scripts/Core/IAvrgValueAccessor.cs.meta | 11 ++ .../Scripts/XuiavrgInspectorManager.cs | 21 ++- .../Scripts/XuiavrgUtilities.cs | 21 ++- Runtime/OverrideUI/AvrgValues.meta | 8 ++ .../AvrgValues/XUIAvrgMDColorValue.cs.meta | 11 ++ .../AvrgValues/XUIAvrgMDDropdownValue.cs | 11 +- .../AvrgValues/XUIAvrgMDDropdownValue.cs.meta | 11 ++ .../AvrgValues/XUIAvrgMDInputFieldValue.cs | 89 +++++++++++- .../XUIAvrgMDInputFieldValue.cs.meta | 11 ++ .../AvrgValues/XUIAvrgMDLabelValue.cs | 12 +- .../AvrgValues/XUIAvrgMDLabelValue.cs.meta | 11 ++ .../AvrgValues/XUIAvrgMDSliderValue.cs | 82 +++++++++++ .../AvrgValues/XUIAvrgMDSliderValue.cs.meta | 11 ++ .../AvrgValues/XUIAvrgMDTextureValue.cs | 6 + .../AvrgValues/XUIAvrgMDTextureValue.cs.meta | 11 ++ .../XUIAvrgMDToggleGroupValue.cs.meta | 11 ++ .../AvrgValues/XUIAvrgMDToggleValue.cs | 47 ++++++- .../AvrgValues/XUIAvrgMDToggleValue.cs.meta | 11 ++ .../{ => AvrgValues}/XUIAvrgMDValue.cs | 133 +++++++++++++++--- .../{ => AvrgValues}/XUIAvrgMDValue.cs.meta | 0 .../AvrgValues/XUIAvrgMDVectorValue.cs | 54 +++++++ .../AvrgValues/XUIAvrgMDVectorValue.cs.meta | 11 ++ .../{ => AvrgValues}/XuiAvrgMDGroup.cs | 0 .../{ => AvrgValues}/XuiAvrgMDGroup.cs.meta | 0 .../AvrgValues/XuiavrgStyleDefaults.cs | 53 +++++++ .../AvrgValues/XuiavrgStyleDefaults.cs.meta | 11 ++ 38 files changed, 742 insertions(+), 38 deletions(-) create mode 100644 Runtime/InterfaceAttributeReflectionGenerator/Scripts/Accessors.meta create mode 100644 Runtime/InterfaceAttributeReflectionGenerator/Scripts/Accessors/MaterialPropertyAccessor.cs.meta create mode 100644 Runtime/InterfaceAttributeReflectionGenerator/Scripts/Accessors/ReflectionValueAccessor.cs.meta create mode 100644 Runtime/InterfaceAttributeReflectionGenerator/Scripts/Attribute/XuiavrgFieldDropdownValueAttribute.cs.meta create mode 100644 Runtime/InterfaceAttributeReflectionGenerator/Scripts/Attribute/XuiavrgFieldToggleGroupValueAttribute.cs.meta create mode 100644 Runtime/InterfaceAttributeReflectionGenerator/Scripts/Attribute/XuiavrgStyleNamespaceAttribute.cs create mode 100644 Runtime/InterfaceAttributeReflectionGenerator/Scripts/Attribute/XuiavrgStyleNamespaceAttribute.cs.meta create mode 100644 Runtime/InterfaceAttributeReflectionGenerator/Scripts/Core.meta create mode 100644 Runtime/InterfaceAttributeReflectionGenerator/Scripts/Core/IAvrgValueAccessor.cs.meta create mode 100644 Runtime/OverrideUI/AvrgValues.meta create mode 100644 Runtime/OverrideUI/AvrgValues/XUIAvrgMDColorValue.cs.meta create mode 100644 Runtime/OverrideUI/AvrgValues/XUIAvrgMDDropdownValue.cs.meta create mode 100644 Runtime/OverrideUI/AvrgValues/XUIAvrgMDInputFieldValue.cs.meta create mode 100644 Runtime/OverrideUI/AvrgValues/XUIAvrgMDLabelValue.cs.meta create mode 100644 Runtime/OverrideUI/AvrgValues/XUIAvrgMDSliderValue.cs.meta create mode 100644 Runtime/OverrideUI/AvrgValues/XUIAvrgMDTextureValue.cs.meta create mode 100644 Runtime/OverrideUI/AvrgValues/XUIAvrgMDToggleGroupValue.cs.meta create mode 100644 Runtime/OverrideUI/AvrgValues/XUIAvrgMDToggleValue.cs.meta rename Runtime/OverrideUI/{ => AvrgValues}/XUIAvrgMDValue.cs (52%) rename Runtime/OverrideUI/{ => AvrgValues}/XUIAvrgMDValue.cs.meta (100%) create mode 100644 Runtime/OverrideUI/AvrgValues/XUIAvrgMDVectorValue.cs.meta rename Runtime/OverrideUI/{ => AvrgValues}/XuiAvrgMDGroup.cs (100%) rename Runtime/OverrideUI/{ => AvrgValues}/XuiAvrgMDGroup.cs.meta (100%) create mode 100644 Runtime/OverrideUI/AvrgValues/XuiavrgStyleDefaults.cs create mode 100644 Runtime/OverrideUI/AvrgValues/XuiavrgStyleDefaults.cs.meta diff --git a/Runtime/InterfaceAttributeReflectionGenerator/Scripts/Accessors.meta b/Runtime/InterfaceAttributeReflectionGenerator/Scripts/Accessors.meta new file mode 100644 index 0000000..0799b8b --- /dev/null +++ b/Runtime/InterfaceAttributeReflectionGenerator/Scripts/Accessors.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a12c0014da358274285d451595dcf212 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/InterfaceAttributeReflectionGenerator/Scripts/Accessors/MaterialPropertyAccessor.cs.meta b/Runtime/InterfaceAttributeReflectionGenerator/Scripts/Accessors/MaterialPropertyAccessor.cs.meta new file mode 100644 index 0000000..94483aa --- /dev/null +++ b/Runtime/InterfaceAttributeReflectionGenerator/Scripts/Accessors/MaterialPropertyAccessor.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 174ea317a2a5e8e44a0d96c6d7e43bd5 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/InterfaceAttributeReflectionGenerator/Scripts/Accessors/ReflectionValueAccessor.cs b/Runtime/InterfaceAttributeReflectionGenerator/Scripts/Accessors/ReflectionValueAccessor.cs index f4bbc76..51290b3 100644 --- a/Runtime/InterfaceAttributeReflectionGenerator/Scripts/Accessors/ReflectionValueAccessor.cs +++ b/Runtime/InterfaceAttributeReflectionGenerator/Scripts/Accessors/ReflectionValueAccessor.cs @@ -26,7 +26,7 @@ namespace XericUI.ReflectionUIGenerator _ => typeof(object) }; - IsReadOnly = memberInfo is PropertyInfo pi && !pi.CanWrite; + IsReadOnly = memberInfo is PropertyInfo pi2 && !pi2.CanWrite; } public object GetValue() diff --git a/Runtime/InterfaceAttributeReflectionGenerator/Scripts/Accessors/ReflectionValueAccessor.cs.meta b/Runtime/InterfaceAttributeReflectionGenerator/Scripts/Accessors/ReflectionValueAccessor.cs.meta new file mode 100644 index 0000000..517d55f --- /dev/null +++ b/Runtime/InterfaceAttributeReflectionGenerator/Scripts/Accessors/ReflectionValueAccessor.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 74ef75bd607ec5242a6bb9bb985bf436 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/InterfaceAttributeReflectionGenerator/Scripts/Attribute/XuiavrgFieldDropdownValueAttribute.cs b/Runtime/InterfaceAttributeReflectionGenerator/Scripts/Attribute/XuiavrgFieldDropdownValueAttribute.cs index 1df7fce..a29985d 100644 --- a/Runtime/InterfaceAttributeReflectionGenerator/Scripts/Attribute/XuiavrgFieldDropdownValueAttribute.cs +++ b/Runtime/InterfaceAttributeReflectionGenerator/Scripts/Attribute/XuiavrgFieldDropdownValueAttribute.cs @@ -23,6 +23,11 @@ namespace XericUI.ReflectionUIGenerator { Options = options ?? Array.Empty(); } + public XuiavrgFieldDropdownValueAttribute(PresetOptionsMergeMode mergeMode, params string[] options) + { + MergeMode = mergeMode; + Options = options ?? Array.Empty(); + } public void BindMetaData(AvrgMemberMetaData metaData) { diff --git a/Runtime/InterfaceAttributeReflectionGenerator/Scripts/Attribute/XuiavrgFieldDropdownValueAttribute.cs.meta b/Runtime/InterfaceAttributeReflectionGenerator/Scripts/Attribute/XuiavrgFieldDropdownValueAttribute.cs.meta new file mode 100644 index 0000000..0c26499 --- /dev/null +++ b/Runtime/InterfaceAttributeReflectionGenerator/Scripts/Attribute/XuiavrgFieldDropdownValueAttribute.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 917ba2bd8d59cce469d2c90b2201c529 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/InterfaceAttributeReflectionGenerator/Scripts/Attribute/XuiavrgFieldToggleGroupValueAttribute.cs b/Runtime/InterfaceAttributeReflectionGenerator/Scripts/Attribute/XuiavrgFieldToggleGroupValueAttribute.cs index 2affa9e..c5e210f 100644 --- a/Runtime/InterfaceAttributeReflectionGenerator/Scripts/Attribute/XuiavrgFieldToggleGroupValueAttribute.cs +++ b/Runtime/InterfaceAttributeReflectionGenerator/Scripts/Attribute/XuiavrgFieldToggleGroupValueAttribute.cs @@ -23,6 +23,11 @@ namespace XericUI.ReflectionUIGenerator { Options = options ?? Array.Empty(); } + public XuiavrgFieldToggleGroupValueAttribute(PresetOptionsMergeMode mergeMode, params string[] options) + { + MergeMode = mergeMode; + Options = options ?? Array.Empty(); + } public void BindMetaData(AvrgMemberMetaData metaData) { diff --git a/Runtime/InterfaceAttributeReflectionGenerator/Scripts/Attribute/XuiavrgFieldToggleGroupValueAttribute.cs.meta b/Runtime/InterfaceAttributeReflectionGenerator/Scripts/Attribute/XuiavrgFieldToggleGroupValueAttribute.cs.meta new file mode 100644 index 0000000..d456377 --- /dev/null +++ b/Runtime/InterfaceAttributeReflectionGenerator/Scripts/Attribute/XuiavrgFieldToggleGroupValueAttribute.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6dac053ad1c4ab043a815cb9b3c64d06 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/InterfaceAttributeReflectionGenerator/Scripts/Attribute/XuiavrgStyleNamespaceAttribute.cs b/Runtime/InterfaceAttributeReflectionGenerator/Scripts/Attribute/XuiavrgStyleNamespaceAttribute.cs new file mode 100644 index 0000000..0715e8b --- /dev/null +++ b/Runtime/InterfaceAttributeReflectionGenerator/Scripts/Attribute/XuiavrgStyleNamespaceAttribute.cs @@ -0,0 +1,33 @@ +using System; + +namespace XericUI.ReflectionUIGenerator +{ + /// + /// 样式命名空间特性 — 为元数据指定 SuperStyleSheet 查询时的命名空间。 + /// + /// 可标记在类上(作为该类型所有字段的默认命名空间), + /// 也可标记在字段/属性上(覆盖单个字段的命名空间)。 + /// + /// 类级标记先应用(设置默认值),字段级标记后应用(可覆盖), + /// 因此字段级 [XuiavrgStyleNamespace] 优先于类级。 + /// + /// 默认命名空间为 "default"。 + /// + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false)] + public class XuiavrgStyleNamespaceAttribute : Attribute, IXuiavrgAttribute + { + public readonly string StyleNamespace; + + /// SuperStyleSheet 命名空间名称(如 "my-theme") + public XuiavrgStyleNamespaceAttribute(string styleNamespace) + { + StyleNamespace = styleNamespace; + } + + public void BindMetaData(AvrgMemberMetaData metaData) + { + if (metaData != null) + metaData.StyleNamespace = StyleNamespace; + } + } +} diff --git a/Runtime/InterfaceAttributeReflectionGenerator/Scripts/Attribute/XuiavrgStyleNamespaceAttribute.cs.meta b/Runtime/InterfaceAttributeReflectionGenerator/Scripts/Attribute/XuiavrgStyleNamespaceAttribute.cs.meta new file mode 100644 index 0000000..79d5599 --- /dev/null +++ b/Runtime/InterfaceAttributeReflectionGenerator/Scripts/Attribute/XuiavrgStyleNamespaceAttribute.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ee38b82f1ec947d4da1981bac698fe96 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/InterfaceAttributeReflectionGenerator/Scripts/AvrgMemberMetaData.cs b/Runtime/InterfaceAttributeReflectionGenerator/Scripts/AvrgMemberMetaData.cs index 6e10eaa..dcfc649 100644 --- a/Runtime/InterfaceAttributeReflectionGenerator/Scripts/AvrgMemberMetaData.cs +++ b/Runtime/InterfaceAttributeReflectionGenerator/Scripts/AvrgMemberMetaData.cs @@ -29,6 +29,12 @@ namespace XericUI.ReflectionUIGenerator /// 值类型 public Type ValueType { get; set; } + /// + /// 样式表命名空间(用于 SuperStyleSheet 样式查询) + /// 默认 "default"。可由类级或字段级 [XuiavrgStyleNamespace] 覆写 + /// + public string StyleNamespace { get; set; } = "default"; + // ============ UI 映射 ============ /// 功能标记 diff --git a/Runtime/InterfaceAttributeReflectionGenerator/Scripts/Core.meta b/Runtime/InterfaceAttributeReflectionGenerator/Scripts/Core.meta new file mode 100644 index 0000000..b69c681 --- /dev/null +++ b/Runtime/InterfaceAttributeReflectionGenerator/Scripts/Core.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 3a2aac04058602749be2f5153db24b69 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/InterfaceAttributeReflectionGenerator/Scripts/Core/IAvrgValueAccessor.cs.meta b/Runtime/InterfaceAttributeReflectionGenerator/Scripts/Core/IAvrgValueAccessor.cs.meta new file mode 100644 index 0000000..15f4cc0 --- /dev/null +++ b/Runtime/InterfaceAttributeReflectionGenerator/Scripts/Core/IAvrgValueAccessor.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b6a7d2f0806496e45b383e7d26eca214 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/InterfaceAttributeReflectionGenerator/Scripts/XuiavrgInspectorManager.cs b/Runtime/InterfaceAttributeReflectionGenerator/Scripts/XuiavrgInspectorManager.cs index 60530cb..6aae0e9 100644 --- a/Runtime/InterfaceAttributeReflectionGenerator/Scripts/XuiavrgInspectorManager.cs +++ b/Runtime/InterfaceAttributeReflectionGenerator/Scripts/XuiavrgInspectorManager.cs @@ -85,6 +85,20 @@ namespace XericUI.ReflectionUIGenerator #endregion + #region Unity 生命周期 + + private void OnEnable() + { + XuiavrgStyleDefaults.EnsureDefaults(); + } + + private void OnDestroy() + { + ClearAll(); + } + + #endregion + #region 核心生命周期 public void BuildFromMetaDataSet(AvrgMemberMetaDataSet metaDataSet, @@ -443,12 +457,5 @@ namespace XericUI.ReflectionUIGenerator _leafGroupMap.Clear(); } - - private void OnDestroy() - { - ClearAll(); - } } - - #endregion } \ No newline at end of file diff --git a/Runtime/InterfaceAttributeReflectionGenerator/Scripts/XuiavrgUtilities.cs b/Runtime/InterfaceAttributeReflectionGenerator/Scripts/XuiavrgUtilities.cs index 5c6b17e..0a48194 100644 --- a/Runtime/InterfaceAttributeReflectionGenerator/Scripts/XuiavrgUtilities.cs +++ b/Runtime/InterfaceAttributeReflectionGenerator/Scripts/XuiavrgUtilities.cs @@ -35,6 +35,11 @@ namespace XericUI.ReflectionUIGenerator var metaDataSet = new AvrgMemberMetaDataSet(); + // ★ 收集类级别 IXuiavrgAttribute — 作为所有字段的基础模板 + var classAttributes = type.GetCustomAttributes() + .OfType() + .ToList(); + foreach (var memberInfo in type.GetRuntimeMemberInfo()) { // 检查隐藏标记 @@ -59,16 +64,22 @@ namespace XericUI.ReflectionUIGenerator PropertyCheckKey = valueType?.FullName, }; - // 收集并执行所有 IXuiavrgAttribute - var attributes = memberInfo.GetCustomAttributes() + // ★ 第1步: 先应用类级特性(设置默认值) + foreach (var classAttr in classAttributes) + { + classAttr.BindMetaData(metaData); + } + + // ★ 第2步: 再应用字段级特性(可覆盖类级设置) + var fieldAttributes = memberInfo.GetCustomAttributes() .OfType() .ToList(); - metaData.Attributes = attributes; + metaData.Attributes = fieldAttributes; - foreach (var attr in attributes) + foreach (var fieldAttr in fieldAttributes) { - attr.BindMetaData(metaData); + fieldAttr.BindMetaData(metaData); } metaDataSet.Add(metaData); diff --git a/Runtime/OverrideUI/AvrgValues.meta b/Runtime/OverrideUI/AvrgValues.meta new file mode 100644 index 0000000..5622718 --- /dev/null +++ b/Runtime/OverrideUI/AvrgValues.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c4541939417af914bab5ce5fcc60b4b7 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/OverrideUI/AvrgValues/XUIAvrgMDColorValue.cs.meta b/Runtime/OverrideUI/AvrgValues/XUIAvrgMDColorValue.cs.meta new file mode 100644 index 0000000..02499a9 --- /dev/null +++ b/Runtime/OverrideUI/AvrgValues/XUIAvrgMDColorValue.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 529d91d01ee305847a76f071fc11ad88 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/OverrideUI/AvrgValues/XUIAvrgMDDropdownValue.cs b/Runtime/OverrideUI/AvrgValues/XUIAvrgMDDropdownValue.cs index 0db3182..a62e344 100644 --- a/Runtime/OverrideUI/AvrgValues/XUIAvrgMDDropdownValue.cs +++ b/Runtime/OverrideUI/AvrgValues/XUIAvrgMDDropdownValue.cs @@ -14,11 +14,19 @@ namespace XericUI.ReflectionUIGenerator { [SerializeField] [Tooltip("关联的 Dropdown 组件(未设置则自动查找)")] +#if dUI_TextMeshPro + private TMPro.TMP_Dropdown _dropdown; +#else private Dropdown _dropdown; +#endif private void Awake() { +#if dUI_TextMeshPro + if (_dropdown == null) _dropdown = GetComponent(); +#else if (_dropdown == null) _dropdown = GetComponent(); +#endif } public override void BindToAccessor( @@ -64,15 +72,12 @@ namespace XericUI.ReflectionUIGenerator private List BuildOptions(System.Type valueType) { - // 1. 从元数据 PresetOptions 获取 if (BoundMetaData?.PresetOptions != null && BoundMetaData.PresetOptions.Count > 0) return BoundMetaData.PresetOptions.ToList(); - // 2. enum 类型:自动提取枚举名 if (valueType != null && valueType.IsEnum) return System.Enum.GetNames(valueType).ToList(); - // 3. 回退 return new List(); } diff --git a/Runtime/OverrideUI/AvrgValues/XUIAvrgMDDropdownValue.cs.meta b/Runtime/OverrideUI/AvrgValues/XUIAvrgMDDropdownValue.cs.meta new file mode 100644 index 0000000..988d2ce --- /dev/null +++ b/Runtime/OverrideUI/AvrgValues/XUIAvrgMDDropdownValue.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0328bccdc7751da418bd32d7ba8cb0b4 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/OverrideUI/AvrgValues/XUIAvrgMDInputFieldValue.cs b/Runtime/OverrideUI/AvrgValues/XUIAvrgMDInputFieldValue.cs index a66d113..32a7e9d 100644 --- a/Runtime/OverrideUI/AvrgValues/XUIAvrgMDInputFieldValue.cs +++ b/Runtime/OverrideUI/AvrgValues/XUIAvrgMDInputFieldValue.cs @@ -1,6 +1,7 @@ using System; using UnityEngine; using UnityEngine.UI; +using XericLibrary.Runtime.SuperStyleSheet; namespace XericUI.ReflectionUIGenerator { @@ -11,14 +12,48 @@ namespace XericUI.ReflectionUIGenerator public class XUIAvrgMDInputFieldValue : XUIAvrgMDValue { [SerializeField] - [Tooltip("关联的 InputField 组件(未设置则自动查找)")] + [Tooltip("关联的 InputField 组件")] +#if dUI_TextMeshPro + private TMPro.TMP_InputField _inputField; +#else private InputField _inputField; +#endif + + [Header("InputField 专属插槽")] + [SerializeField, Tooltip("增加按钮(点击按步进值 +)")] + private Button _incrementButton; + + [SerializeField, Tooltip("减少按钮(点击按步进值 -)")] + private Button _decrementButton; + + // ============ 样式表参数 ============ + private readonly StyleMember _styleStepValue = new() { StylePath = "xuiavrg/input/stepValue" }; + + // ============ 生命周期 ============ private void Awake() { +#if dUI_TextMeshPro + if (_inputField == null) _inputField = GetComponent(); +#else if (_inputField == null) _inputField = GetComponent(); +#endif } + protected override void OnEnable() + { + base.OnEnable(); + _styleStepValue.Register(); + } + + protected override void OnDisable() + { + base.OnDisable(); + _styleStepValue.Unregister(); + } + + // ============ 核心绑定 ============ + public override void BindToAccessor( IAvrgValueAccessor accessor, AvrgMvvmBinding binding, @@ -29,12 +64,25 @@ namespace XericUI.ReflectionUIGenerator if (binding == null || accessor == null || _inputField == null) return; - // 设置输入类型 +#if dUI_TextMeshPro + if (accessor.ValueType == typeof(float) || accessor.ValueType == typeof(int) + || accessor.ValueType == typeof(double)) + { + _inputField.contentType = TMPro.TMP_InputField.ContentType.DecimalNumber; + } +#else if (accessor.ValueType == typeof(float) || accessor.ValueType == typeof(int) || accessor.ValueType == typeof(double)) { _inputField.contentType = InputField.ContentType.DecimalNumber; } +#endif + + // 增减按钮 + if (_incrementButton != null) + _incrementButton.onClick.AddListener(OnIncrementClicked); + if (_decrementButton != null) + _decrementButton.onClick.AddListener(OnDecrementClicked); // UI → 数据 _inputField.onEndEdit.AddListener(val => @@ -53,6 +101,43 @@ namespace XericUI.ReflectionUIGenerator // 首次同步 var initialValue = accessor.GetValue(); _inputField.SetTextWithoutNotify(accessor.FormatDisplay(initialValue)); + + RefreshCommonNodes(); + } + + // ============ 步进 ============ + + private float GetStepValue() + { + var val = GetStyleValue(_styleStepValue); + return val?.GetValueAsFloat() ?? 1f; + } + + private void OnIncrementClicked() + { + if (CurrentAccessor?.IsReadOnly == true || _inputField == null) return; + if (!float.TryParse(_inputField.text, out float current)) return; + float step = GetStepValue(); + float newVal = current + step; + _inputField.text = CurrentAccessor.FormatDisplay( + ConvertValueForAccessor(newVal, CurrentAccessor.ValueType)); + } + + private void OnDecrementClicked() + { + if (CurrentAccessor?.IsReadOnly == true || _inputField == null) return; + if (!float.TryParse(_inputField.text, out float current)) return; + float step = GetStepValue(); + float newVal = current - step; + _inputField.text = CurrentAccessor.FormatDisplay( + ConvertValueForAccessor(newVal, CurrentAccessor.ValueType)); + } + + private static object ConvertValueForAccessor(float val, Type targetType) + { + if (targetType == typeof(int)) return (int)val; + if (targetType == typeof(double)) return (double)val; + return val; } private static object ConvertStringToValue(string s, Type targetType) diff --git a/Runtime/OverrideUI/AvrgValues/XUIAvrgMDInputFieldValue.cs.meta b/Runtime/OverrideUI/AvrgValues/XUIAvrgMDInputFieldValue.cs.meta new file mode 100644 index 0000000..3ed4498 --- /dev/null +++ b/Runtime/OverrideUI/AvrgValues/XUIAvrgMDInputFieldValue.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 66e550f9b0ba63448bf6add335a317a8 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/OverrideUI/AvrgValues/XUIAvrgMDLabelValue.cs b/Runtime/OverrideUI/AvrgValues/XUIAvrgMDLabelValue.cs index f2b69c1..b161c89 100644 --- a/Runtime/OverrideUI/AvrgValues/XUIAvrgMDLabelValue.cs +++ b/Runtime/OverrideUI/AvrgValues/XUIAvrgMDLabelValue.cs @@ -13,14 +13,18 @@ namespace XericUI.ReflectionUIGenerator [Tooltip("关联的 Text 组件(未设置则自动查找)")] private UnityEngine.UI.Text _uiText; +#if dUI_TextMeshPro [SerializeField] [Tooltip("关联的 TMP_Text 组件(未设置则自动查找)")] private TMPro.TMP_Text _tmpText; +#endif private void Awake() { if (_uiText == null) _uiText = GetComponent(); +#if dUI_TextMeshPro if (_tmpText == null) _tmpText = GetComponent(); +#endif } public override void BindToAccessor( @@ -48,9 +52,15 @@ namespace XericUI.ReflectionUIGenerator { string displayStr = value?.ToString() ?? ""; +#if dUI_TextMeshPro if (_tmpText != null) + { _tmpText.text = displayStr; - else if (_uiText != null) + return; + } +#endif + + if (_uiText != null) _uiText.text = displayStr; } } diff --git a/Runtime/OverrideUI/AvrgValues/XUIAvrgMDLabelValue.cs.meta b/Runtime/OverrideUI/AvrgValues/XUIAvrgMDLabelValue.cs.meta new file mode 100644 index 0000000..1907c65 --- /dev/null +++ b/Runtime/OverrideUI/AvrgValues/XUIAvrgMDLabelValue.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 64afed910d0f0f0408c6672fa3dd6917 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/OverrideUI/AvrgValues/XUIAvrgMDSliderValue.cs b/Runtime/OverrideUI/AvrgValues/XUIAvrgMDSliderValue.cs index a90b31a..f5d2cfb 100644 --- a/Runtime/OverrideUI/AvrgValues/XUIAvrgMDSliderValue.cs +++ b/Runtime/OverrideUI/AvrgValues/XUIAvrgMDSliderValue.cs @@ -1,6 +1,7 @@ using System; using UnityEngine; using UnityEngine.UI; +using XericLibrary.Runtime.SuperStyleSheet; namespace XericUI.ReflectionUIGenerator { @@ -15,15 +16,49 @@ namespace XericUI.ReflectionUIGenerator [Tooltip("关联的 Slider 组件(未设置则自动查找)")] private Slider _slider; + [Header("Slider 专属插槽")] + [SerializeField, Tooltip("增加按钮(点击按步进值 +)")] + private Button _incrementButton; + + [SerializeField, Tooltip("减少按钮(点击按步进值 -)")] + private Button _decrementButton; + +#if dUI_TextMeshPro [SerializeField] [Tooltip("值显示标签(可选,未设置则不更新)")] private TMPro.TMP_Text _valueLabel; +#endif + + // ============ 样式表参数 ============ + private readonly StyleMember _styleDefaultStep = new() { StylePath = "xuiavrg/slider/defaultStep" }; + private readonly StyleMember _styleMinStep = new() { StylePath = "xuiavrg/slider/minStep" }; + private readonly StyleMember _styleMaxStep = new() { StylePath = "xuiavrg/slider/maxStep" }; + + // ============ 生命周期 ============ private void Awake() { if (_slider == null) _slider = GetComponent(); } + protected override void OnEnable() + { + base.OnEnable(); + _styleDefaultStep.Register(); + _styleMinStep.Register(); + _styleMaxStep.Register(); + } + + protected override void OnDisable() + { + base.OnDisable(); + _styleDefaultStep.Unregister(); + _styleMinStep.Unregister(); + _styleMaxStep.Unregister(); + } + + // ============ 核心绑定 ============ + public override void BindToAccessor( IAvrgValueAccessor accessor, AvrgMvvmBinding binding, @@ -45,6 +80,12 @@ namespace XericUI.ReflectionUIGenerator _slider.maxValue = BoundMetaData.RangeMax.Value; } + // 增减按钮 + if (_incrementButton != null) + _incrementButton.onClick.AddListener(OnIncrementClicked); + if (_decrementButton != null) + _decrementButton.onClick.AddListener(OnDecrementClicked); + // UI → 数据 _slider.onValueChanged.AddListener(val => { @@ -52,8 +93,10 @@ namespace XericUI.ReflectionUIGenerator binding.WriteFromUI(convertedVal); scheduler?.MarkUIDirty(binding); +#if dUI_TextMeshPro if (_valueLabel != null) _valueLabel.text = accessor.FormatDisplay(convertedVal); +#endif }); // 数据 → UI @@ -62,8 +105,10 @@ namespace XericUI.ReflectionUIGenerator float sliderVal = Convert.ToSingle(value); _slider.SetValueWithoutNotify(sliderVal); +#if dUI_TextMeshPro if (_valueLabel != null) _valueLabel.text = accessor.FormatDisplay(value); +#endif }; // 首次同步 @@ -71,9 +116,46 @@ namespace XericUI.ReflectionUIGenerator if (initialValue != null) { _slider.SetValueWithoutNotify(Convert.ToSingle(initialValue)); +#if dUI_TextMeshPro if (_valueLabel != null) _valueLabel.text = accessor.FormatDisplay(initialValue); +#endif } + + RefreshCommonNodes(); + } + + // ============ 步进值 ============ + + private float GetStepValue() + { + var val = GetStyleValue(_styleDefaultStep); + if (val != null) + { + float step = val.GetValueAsFloat(); + float min = GetStyleValue(_styleMinStep)?.GetValueAsFloat() ?? 0.001f; + float max = GetStyleValue(_styleMaxStep)?.GetValueAsFloat() ?? 1000f; + return Mathf.Clamp(step, min, max); + } + return _slider.wholeNumbers ? 1f : 0.1f; + } + + private void OnIncrementClicked() + { + if (CurrentAccessor?.IsReadOnly == true || _slider == null) return; + float step = GetStepValue(); + float current = Convert.ToSingle(CurrentAccessor.GetValue()); + float newVal = Mathf.Clamp(current + step, _slider.minValue, _slider.maxValue); + _slider.value = newVal; + } + + private void OnDecrementClicked() + { + if (CurrentAccessor?.IsReadOnly == true || _slider == null) return; + float step = GetStepValue(); + float current = Convert.ToSingle(CurrentAccessor.GetValue()); + float newVal = Mathf.Clamp(current - step, _slider.minValue, _slider.maxValue); + _slider.value = newVal; } private static object ConvertValueForAccessor(float val, Type targetType) diff --git a/Runtime/OverrideUI/AvrgValues/XUIAvrgMDSliderValue.cs.meta b/Runtime/OverrideUI/AvrgValues/XUIAvrgMDSliderValue.cs.meta new file mode 100644 index 0000000..a6ace60 --- /dev/null +++ b/Runtime/OverrideUI/AvrgValues/XUIAvrgMDSliderValue.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2b55bbe984d79124ba933f6d7cc2232f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/OverrideUI/AvrgValues/XUIAvrgMDTextureValue.cs b/Runtime/OverrideUI/AvrgValues/XUIAvrgMDTextureValue.cs index b05f0d7..35e109f 100644 --- a/Runtime/OverrideUI/AvrgValues/XUIAvrgMDTextureValue.cs +++ b/Runtime/OverrideUI/AvrgValues/XUIAvrgMDTextureValue.cs @@ -14,9 +14,11 @@ namespace XericUI.ReflectionUIGenerator [Tooltip("用于展示纹理的 RawImage 组件(未设置则自动查找)")] private RawImage _textureDisplay; +#if dUI_TextMeshPro [SerializeField] [Tooltip("纹理名称标签(可选,用于显示纹理资源名)")] private TMPro.TMP_Text _nameLabel; +#endif private void Awake() { @@ -41,10 +43,12 @@ namespace XericUI.ReflectionUIGenerator _textureDisplay.texture = tex; } +#if dUI_TextMeshPro if (_nameLabel != null) { _nameLabel.text = value is Texture t && t != null ? t.name : "None"; } +#endif }; // 首次同步 @@ -54,10 +58,12 @@ namespace XericUI.ReflectionUIGenerator _textureDisplay.texture = initTex; } +#if dUI_TextMeshPro if (_nameLabel != null) { _nameLabel.text = initialValue is Texture t && t != null ? t.name : "None"; } +#endif } } } diff --git a/Runtime/OverrideUI/AvrgValues/XUIAvrgMDTextureValue.cs.meta b/Runtime/OverrideUI/AvrgValues/XUIAvrgMDTextureValue.cs.meta new file mode 100644 index 0000000..024d534 --- /dev/null +++ b/Runtime/OverrideUI/AvrgValues/XUIAvrgMDTextureValue.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0655c30e41dc2884f91f4acb4666a271 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/OverrideUI/AvrgValues/XUIAvrgMDToggleGroupValue.cs.meta b/Runtime/OverrideUI/AvrgValues/XUIAvrgMDToggleGroupValue.cs.meta new file mode 100644 index 0000000..3a02558 --- /dev/null +++ b/Runtime/OverrideUI/AvrgValues/XUIAvrgMDToggleGroupValue.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 330c7c83db7ef3141a8097a27d2cf61d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/OverrideUI/AvrgValues/XUIAvrgMDToggleValue.cs b/Runtime/OverrideUI/AvrgValues/XUIAvrgMDToggleValue.cs index 84927d0..3d741cf 100644 --- a/Runtime/OverrideUI/AvrgValues/XUIAvrgMDToggleValue.cs +++ b/Runtime/OverrideUI/AvrgValues/XUIAvrgMDToggleValue.cs @@ -1,10 +1,12 @@ using UnityEngine; using UnityEngine.UI; +using XericLibrary.Runtime.SuperStyleSheet; namespace XericUI.ReflectionUIGenerator { /// /// Toggle 值组件 — 处理 bool 类型的开关交互 + /// 支持样式表控制开关颜色 /// [AddComponentMenu("Xeric Library/UI Action Vessel/Values/XUIAvrgMDToggleValue")] public class XUIAvrgMDToggleValue : XUIAvrgMDValue @@ -13,11 +15,33 @@ namespace XericUI.ReflectionUIGenerator [Tooltip("关联的 Toggle 组件(未设置则自动查找)")] private Toggle _toggle; + // ============ 样式表参数 ============ + private readonly StyleMember _styleOnColor = new() { StylePath = "xuiavrg/toggle/onColor" }; + private readonly StyleMember _styleOffColor = new() { StylePath = "xuiavrg/toggle/offColor" }; + + // ============ 生命周期 ============ + private void Awake() { if (_toggle == null) _toggle = GetComponent(); } + protected override void OnEnable() + { + base.OnEnable(); + _styleOnColor.Register(); + _styleOffColor.Register(); + } + + protected override void OnDisable() + { + base.OnDisable(); + _styleOnColor.Unregister(); + _styleOffColor.Unregister(); + } + + // ============ 核心绑定 ============ + public override void BindToAccessor( IAvrgValueAccessor accessor, AvrgMvvmBinding binding, @@ -36,17 +60,36 @@ namespace XericUI.ReflectionUIGenerator { binding.WriteFromUI(val); scheduler?.MarkUIDirty(binding); + ApplyToggleColor(val); }); // 数据 → UI binding.OnUIDataChanged += value => { - _toggle.SetIsOnWithoutNotify(value is bool b && b); + bool isOn = value is bool b && b; + _toggle.SetIsOnWithoutNotify(isOn); + ApplyToggleColor(isOn); }; // 首次同步 var initialValue = accessor.GetValue(); - _toggle.SetIsOnWithoutNotify(initialValue is bool bv && bv); + bool initialOn = initialValue is bool bv && bv; + _toggle.SetIsOnWithoutNotify(initialOn); + ApplyToggleColor(initialOn); + + RefreshCommonNodes(); + } + + // ============ 样式颜色 ============ + + private void ApplyToggleColor(bool isOn) + { + var target = _toggle.targetGraphic; + if (target == null) return; + + var colorVal = isOn ? GetStyleValue(_styleOnColor) : GetStyleValue(_styleOffColor); + if (colorVal != null) + target.color = colorVal; } } } diff --git a/Runtime/OverrideUI/AvrgValues/XUIAvrgMDToggleValue.cs.meta b/Runtime/OverrideUI/AvrgValues/XUIAvrgMDToggleValue.cs.meta new file mode 100644 index 0000000..b1305bd --- /dev/null +++ b/Runtime/OverrideUI/AvrgValues/XUIAvrgMDToggleValue.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 00fd149c9a8dacd478a5adcad14a11f2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/OverrideUI/XUIAvrgMDValue.cs b/Runtime/OverrideUI/AvrgValues/XUIAvrgMDValue.cs similarity index 52% rename from Runtime/OverrideUI/XUIAvrgMDValue.cs rename to Runtime/OverrideUI/AvrgValues/XUIAvrgMDValue.cs index 01be1f9..6948365 100644 --- a/Runtime/OverrideUI/XUIAvrgMDValue.cs +++ b/Runtime/OverrideUI/AvrgValues/XUIAvrgMDValue.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using UnityEngine; +using XericLibrary.Runtime.SuperStyleSheet; namespace XericUI.ReflectionUIGenerator { @@ -12,6 +13,7 @@ namespace XericUI.ReflectionUIGenerator /// 3. 通过 virtual BindToAccessor() 让子类自行管理 UI 交互事件和显示更新 /// 4. 初始化时广播元数据到所有子节点上的 IXUIAvrgMDValueStyle /// 5. 定义绑定槽(BindingSlots),供拆分属性子绑定匹配 + /// 6. 管理通用 UI 插槽(标签、警告、只读、单位、值显示)+ SuperStyleSheet 样式读取 /// [AddComponentMenu("Xeric Library/UI Action Vessel/XUIAvrgMDValue")] public class XUIAvrgMDValue : MonoBehaviour @@ -31,6 +33,8 @@ namespace XericUI.ReflectionUIGenerator public XuiavrgFieldTag tag = XuiavrgFieldTag.Context; } + // ============ 匹配标记 ============ + [SerializeField] [Tooltip("功能标记,用于与 Entry 的 Tag 匹配")] private XuiavrgFieldTag _entryTag = XuiavrgFieldTag.None; @@ -43,6 +47,32 @@ namespace XericUI.ReflectionUIGenerator [Tooltip("拆分属性子绑定槽列表 — 用于 XuiavrgSplit 的子属性匹配")] private List _bindingSlots = new List(); + // ============ 通用 UI 插槽 ============ + + [Header("通用 UI 插槽")] + [SerializeField, Tooltip("字段标签节点 — 显示字段名称 + 只读前缀。为 null 则不显示标签行")] + protected GameObject fieldLabelNode; + + [SerializeField, Tooltip("警告样式节点 — 验证失败时 SetActive(true),颜色由样式表控制")] + protected GameObject warningNode; + + [SerializeField, Tooltip("只读标记节点 — IsReadOnly 时 SetActive(true)")] + protected GameObject readOnlyNode; + + [SerializeField, Tooltip("单位文本节点 — 显示元数据的 UnitLabelName")] + protected GameObject unitTextNode; + + [SerializeField, Tooltip("值显示文本节点 — 可为 null(子类如 Slider/Color 不依赖文本)")] + protected GameObject valueTextNode; + + // ============ 样式表参数(路径硬编码,命名空间从 BoundMetaData.StyleNamespace 获取)============ + + private readonly StyleMember _styleStepValue = new() { StylePath = "xuiavrg/base/stepValue" }; + private readonly StyleMember _styleReadOnlyPrefix = new() { StylePath = "xuiavrg/base/readOnlyPrefix" }; + private readonly StyleMember _styleWarningColor = new() { StylePath = "xuiavrg/base/warningColor" }; + + // ============ 公共属性 ============ + /// 绑定的元数据引用 public AvrgMemberMetaData BoundMetaData { get; protected set; } @@ -58,15 +88,27 @@ namespace XericUI.ReflectionUIGenerator /// 只读访问绑定槽列表 public IReadOnlyList AvailableBindingSlots => _bindingSlots; + // ============ 生命周期 ============ + + protected virtual void OnEnable() + { + _styleStepValue.Register(); + _styleReadOnlyPrefix.Register(); + _styleWarningColor.Register(); + } + + protected virtual void OnDisable() + { + _styleStepValue.Unregister(); + _styleReadOnlyPrefix.Unregister(); + _styleWarningColor.Unregister(); + } + + // ============ 核心绑定接口 ============ + /// /// 由 XuiFieldTempEntry 调用,将值访问器和 MVVM 绑定连接到此 UI 组件 - /// - /// 基类实现提供一个默认的通用绑定逻辑(适用于 Label/Context/Unit 等简单展示型 Tag)。 - /// 子类(如 SliderValue, DropdownValue)应覆写此方法以处理其专属 UI 交互。 /// - /// 值访问器 — 提供统一的数据读写 - /// MVVM 绑定 — 提供脏标记和 UI→数据通信通道 - /// MVVM 调度器 — 可空,用于标记脏状态 public virtual void BindToAccessor( IAvrgValueAccessor accessor, AvrgMvvmBinding binding, @@ -86,6 +128,9 @@ namespace XericUI.ReflectionUIGenerator // 首次同步 var initialValue = accessor.GetValue(); UpdateDisplayValue(initialValue); + + // 刷新通用插槽 + RefreshCommonNodes(); } /// @@ -96,19 +141,19 @@ namespace XericUI.ReflectionUIGenerator { if (value == null) return; - // 尝试 Text - var uiText = GetComponent(); - if (uiText != null) - { - uiText.text = CurrentAccessor?.FormatDisplay(value) ?? value.ToString(); - return; - } - - // 尝试 TMP_Text +#if dUI_TextMeshPro var tmpText = GetComponent(); if (tmpText != null) { tmpText.text = CurrentAccessor?.FormatDisplay(value) ?? value.ToString(); + return; + } +#endif + + var uiText = GetComponent(); + if (uiText != null) + { + uiText.text = CurrentAccessor?.FormatDisplay(value) ?? value.ToString(); } } @@ -121,16 +166,70 @@ namespace XericUI.ReflectionUIGenerator if (metaData == null) return; - // 查找子节点上的所有样式扩展组件并广播元数据 + // 广播元数据到子节点样式组件 var styles = GetComponentsInChildren(true); foreach (var style in styles) { - // 跳过自身(XUIAvrgMDValue 不是 IXUIAvrgMDValueStyle) if (style is MonoBehaviour mb && mb.gameObject == gameObject) continue; style.ApplyMetaData(metaData); } } + + // ============ 样式读取 ============ + + /// + /// 从样式表获取值(自动使用 BoundMetaData.StyleNamespace) + /// + protected StyleValue GetStyleValue(StyleMember member) + { + if (member == null) return null; + string ns = BoundMetaData?.StyleNamespace ?? "default"; + return StyleManager.GetValue(ns, member.StylePath); + } + + // ============ 通用 UI 插槽刷新 ============ + + /// 刷新所有通用 UI 插槽(标签、单位、只读、警告标记) + protected void RefreshCommonNodes() + { + var meta = BoundMetaData; + if (meta == null) return; + + // 1. 字段标签节点 + if (fieldLabelNode != null) + { + string prefix = ""; + if (CurrentAccessor?.IsReadOnly == true) + { + var pv = GetStyleValue(_styleReadOnlyPrefix); + prefix = pv?.GetValueAsString() ?? "[只读] "; + } + SetNodeText(fieldLabelNode, prefix + (meta.LabelName ?? meta.MemberName)); + } + + // 2. 单位文本节点 + if (unitTextNode != null) + SetNodeText(unitTextNode, meta.UnitLabelName ?? ""); + + // 3. 只读标记节点 + if (readOnlyNode != null) + readOnlyNode.SetActive(CurrentAccessor?.IsReadOnly == true); + + // 4. warningNode 由外部验证系统触发,此方法不直接控制 + } + + /// 在节点及其子节点上查找 Text / TMP_Text 并设置文本 + protected static void SetNodeText(GameObject node, string text) + { + if (node == null) return; +#if dUI_TextMeshPro + var t = node.GetComponentInChildren(true); + if (t != null) { t.text = text; return; } +#endif + var ut = node.GetComponentInChildren(true); + if (ut != null) ut.text = text; + } } } diff --git a/Runtime/OverrideUI/XUIAvrgMDValue.cs.meta b/Runtime/OverrideUI/AvrgValues/XUIAvrgMDValue.cs.meta similarity index 100% rename from Runtime/OverrideUI/XUIAvrgMDValue.cs.meta rename to Runtime/OverrideUI/AvrgValues/XUIAvrgMDValue.cs.meta diff --git a/Runtime/OverrideUI/AvrgValues/XUIAvrgMDVectorValue.cs b/Runtime/OverrideUI/AvrgValues/XUIAvrgMDVectorValue.cs index c80d324..470eb39 100644 --- a/Runtime/OverrideUI/AvrgValues/XUIAvrgMDVectorValue.cs +++ b/Runtime/OverrideUI/AvrgValues/XUIAvrgMDVectorValue.cs @@ -1,5 +1,6 @@ using UnityEngine; using UnityEngine.UI; +using XericLibrary.Runtime.SuperStyleSheet; namespace XericUI.ReflectionUIGenerator { @@ -26,6 +27,25 @@ namespace XericUI.ReflectionUIGenerator [Tooltip("W 分量 InputField(Vector4 时使用)")] private InputField _inputW; + // ============ 样式表参数 ============ + private readonly StyleMember _styleLayoutDirection = new() { StylePath = "xuiavrg/vector/layoutDirection" }; + + // ============ 生命周期 ============ + + protected override void OnEnable() + { + base.OnEnable(); + _styleLayoutDirection.Register(); + } + + protected override void OnDisable() + { + base.OnDisable(); + _styleLayoutDirection.Unregister(); + } + + // ============ 核心绑定 ============ + public override void BindToAccessor( IAvrgValueAccessor accessor, AvrgMvvmBinding binding, @@ -43,6 +63,11 @@ namespace XericUI.ReflectionUIGenerator SetInputActive(_inputZ, 2, componentCount); SetInputActive(_inputW, 3, componentCount); + // 样式表控制排列方向 + var dirVal = GetStyleValue(_styleLayoutDirection); + string dir = dirVal?.GetValueAsString() ?? "Horizontal"; + ApplyLayoutDirection(dir); + // 为每个输入注册事件 BindInputField(_inputX, 0, accessor, binding, scheduler); BindInputField(_inputY, 1, accessor, binding, scheduler); @@ -58,8 +83,37 @@ namespace XericUI.ReflectionUIGenerator // 首次同步 var initialValue = accessor.GetValue(); UpdateAllInputs(initialValue); + + RefreshCommonNodes(); } + // ============ 布局 ============ + + private void ApplyLayoutDirection(string dir) + { + var layout = GetComponent(); + if (layout == null) return; + + if (dir == "Vertical") + { + if (layout is HorizontalLayoutGroup) + { + Destroy(layout); + gameObject.AddComponent(); + } + } + else + { + if (layout is VerticalLayoutGroup) + { + Destroy(layout); + gameObject.AddComponent(); + } + } + } + + // ============ 输入绑定 ============ + private void BindInputField(InputField input, int componentIndex, IAvrgValueAccessor accessor, AvrgMvvmBinding binding, AvrgMvvmScheduler scheduler) { diff --git a/Runtime/OverrideUI/AvrgValues/XUIAvrgMDVectorValue.cs.meta b/Runtime/OverrideUI/AvrgValues/XUIAvrgMDVectorValue.cs.meta new file mode 100644 index 0000000..90b97a2 --- /dev/null +++ b/Runtime/OverrideUI/AvrgValues/XUIAvrgMDVectorValue.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 128edc3f2c56f784d8a3acca12c960b4 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/OverrideUI/XuiAvrgMDGroup.cs b/Runtime/OverrideUI/AvrgValues/XuiAvrgMDGroup.cs similarity index 100% rename from Runtime/OverrideUI/XuiAvrgMDGroup.cs rename to Runtime/OverrideUI/AvrgValues/XuiAvrgMDGroup.cs diff --git a/Runtime/OverrideUI/XuiAvrgMDGroup.cs.meta b/Runtime/OverrideUI/AvrgValues/XuiAvrgMDGroup.cs.meta similarity index 100% rename from Runtime/OverrideUI/XuiAvrgMDGroup.cs.meta rename to Runtime/OverrideUI/AvrgValues/XuiAvrgMDGroup.cs.meta diff --git a/Runtime/OverrideUI/AvrgValues/XuiavrgStyleDefaults.cs b/Runtime/OverrideUI/AvrgValues/XuiavrgStyleDefaults.cs new file mode 100644 index 0000000..2bf6ba4 --- /dev/null +++ b/Runtime/OverrideUI/AvrgValues/XuiavrgStyleDefaults.cs @@ -0,0 +1,53 @@ +using UnityEngine; + +namespace XericUI.ReflectionUIGenerator +{ + /// + /// Xuiavrg 样式默认值注入 + /// + /// 在应用启动时通过 StyleManager.AddDynamicStyle() 将 xuiavrg 各组件的 + /// 默认样式参数注入到 "default" 命名空间下。用户可在 .xsss 文件中覆写。 + /// + /// 触发时机:XuiavrgInspectorManager.OnEnable() 调用 EnsureDefaults() + /// + public static class XuiavrgStyleDefaults + { + private static bool _defaultsInjected; + private const string NS = "default"; + + /// 确保 "default" 命名空间下有所有的 xuiavrg 默认样式值(幂等) + public static void EnsureDefaults() + { + if (_defaultsInjected) return; + _defaultsInjected = true; + + // ===== 基类通用 ===== + AddIfMissing(NS, "xuiavrg/base/stepValue", 1f); + AddIfMissing(NS, "xuiavrg/base/readOnlyPrefix", "[只读] "); + AddIfMissing(NS, "xuiavrg/base/warningColor", Color.yellow); + + // ===== Slider ===== + AddIfMissing(NS, "xuiavrg/slider/defaultStep", 0.1f); + AddIfMissing(NS, "xuiavrg/slider/minStep", 0.001f); + AddIfMissing(NS, "xuiavrg/slider/maxStep", 1000f); + + // ===== InputField ===== + AddIfMissing(NS, "xuiavrg/input/stepValue", 1f); + + // ===== Toggle ===== + AddIfMissing(NS, "xuiavrg/toggle/onColor", Color.green); + AddIfMissing(NS, "xuiavrg/toggle/offColor", new Color(0.5f, 0.5f, 0.5f, 1f)); + + // ===== Vector ===== + AddIfMissing(NS, "xuiavrg/vector/layoutDirection", "Horizontal"); + + XericLibrary.Runtime.SuperStyleSheet.StyleManager.ForceRefresh(); + } + + private static void AddIfMissing(string ns, string path, object value) + { + if (XericLibrary.Runtime.SuperStyleSheet.StyleManager.HasStyle(ns, path)) return; + XericLibrary.Runtime.SuperStyleSheet.StyleManager.AddDynamicStyle(ns, path, value); + } + } +} diff --git a/Runtime/OverrideUI/AvrgValues/XuiavrgStyleDefaults.cs.meta b/Runtime/OverrideUI/AvrgValues/XuiavrgStyleDefaults.cs.meta new file mode 100644 index 0000000..9093073 --- /dev/null +++ b/Runtime/OverrideUI/AvrgValues/XuiavrgStyleDefaults.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d14548d93d7669346a061384defd8460 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: