From f20033743d53f1aedf3cc483dd7a9989d7e2e450 Mon Sep 17 00:00:00 2001 From: lrc <571244399@qq.com> Date: Sun, 28 Jun 2026 23:08:17 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E8=A1=A8=E6=A0=BC=E7=9A=84?= =?UTF-8?q?=E5=BC=BA=E5=88=B6=E6=A0=B7=E5=BC=8F=E6=9B=B4=E6=96=B0=E3=80=82?= =?UTF-8?q?=20=E4=BC=98=E5=8C=96=E6=A0=B7=E5=BC=8F=E7=8A=B6=E6=80=81?= =?UTF-8?q?=E9=9B=86=EF=BC=8C=E6=B7=BB=E5=8A=A0=E4=BA=86=E6=A0=B7=E5=BC=8F?= =?UTF-8?q?=E9=9B=86=E5=9F=BA=E4=BA=8E=E9=BB=98=E8=AE=A4=E5=80=BC=E7=9A=84?= =?UTF-8?q?=E9=BB=98=E8=AE=A4=E6=A0=B7=E5=BC=8F=E8=B7=AF=E5=BE=84=E3=80=82?= =?UTF-8?q?=20=E4=BC=98=E5=8C=96=E6=A0=B7=E5=BC=8F=E8=A1=A8=E6=8C=89?= =?UTF-8?q?=E9=92=AE=E7=AD=89=E7=BB=84=E4=BB=B6=E7=9A=84=E5=88=B7=E6=96=B0?= =?UTF-8?q?=E5=8A=9F=E8=83=BD=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Editor/XTable/XericUIActionTableEditor.cs | 12 +- .../StyleSheetUI/DefaultXericStyleSheet.xsss | 3 +- Runtime/Core/StyleSheetUI/StyleSheetState.cs | 33 +- .../Test/xuiSceen.unity | 656 +++++++++--------- Runtime/OverrideUI/XericStyleButton.cs | 319 +++++---- Runtime/OverrideUI/XericStyleToggle.cs | 74 +- .../Rendering/Component/XericUIActionTable.cs | 153 +++- 7 files changed, 715 insertions(+), 535 deletions(-) diff --git a/Editor/XTable/XericUIActionTableEditor.cs b/Editor/XTable/XericUIActionTableEditor.cs index 73c49ef..2332bd3 100644 --- a/Editor/XTable/XericUIActionTableEditor.cs +++ b/Editor/XTable/XericUIActionTableEditor.cs @@ -37,6 +37,9 @@ namespace XericUIEditor.XTable m_ColWidthsProp = serializedObject.FindProperty("m_ColWidths"); m_DefaultStyleNsProp = serializedObject.FindProperty("m_DefaultStyleNamespace"); m_ScrollRectProp = serializedObject.FindProperty("m_ScrollRect"); + + // 同步表格的 ChildrenVisible 状态到编辑器 toggle + m_ShowChildren = m_Table.ChildrenVisible; } public override void OnInspectorGUI() @@ -78,7 +81,14 @@ namespace XericUIEditor.XTable if (GUILayout.Button("重新生成表格", GUILayout.Height(26))) { m_Table.FullRebuild(); - m_Table.SetChildrenVisible(!m_ShowChildren); + m_Table.SetChildrenVisible(m_ShowChildren); + } + + if (GUILayout.Button("强制刷新样式", GUILayout.Height(26))) + { + XericLibrary.Runtime.SuperStyleSheet.StyleManager.ForceRefresh(); + m_Table.FullRebuild(); + m_Table.SetChildrenVisible(m_ShowChildren); } EditorGUILayout.Space(4); diff --git a/Runtime/Core/StyleSheetUI/DefaultXericStyleSheet.xsss b/Runtime/Core/StyleSheetUI/DefaultXericStyleSheet.xsss index 2d742ac..eaed782 100644 --- a/Runtime/Core/StyleSheetUI/DefaultXericStyleSheet.xsss +++ b/Runtime/Core/StyleSheetUI/DefaultXericStyleSheet.xsss @@ -8,5 +8,6 @@ namespace: default .NormalColor = (1,1,1,1) .HighlightedColor = (0.96,0.96,0.96,1) .PressedColor = (0.78,0.78,0.78,1) -.DisabledColor = (0.78,0.78,0.78,0.5) +.SelectedColor = (0.96,0.96,0.96,1) +.DisabledColor = (0.6,0.6,0.6,0.8) } \ No newline at end of file diff --git a/Runtime/Core/StyleSheetUI/StyleSheetState.cs b/Runtime/Core/StyleSheetUI/StyleSheetState.cs index 885f5a8..507cbae 100644 --- a/Runtime/Core/StyleSheetUI/StyleSheetState.cs +++ b/Runtime/Core/StyleSheetUI/StyleSheetState.cs @@ -9,34 +9,36 @@ namespace XericUI.Core.StyleSheetUI /// /// 样式表驱动的 UI 交互状态块——仿 ColorBlock 设计。 /// 集中管理 Normal/Highlighted/Pressed/Selected/Disabled 五种状态的 StyleField。 - /// 职责单一:仅保存一组样式属性(如仅颜色、或仅纹理)。 - /// 在组件上声明多个实例分别实现颜色切换和纹理切换。 /// [Serializable] public class StyleSheetState { + private const string k_DefaultColorBasePath = "/button/TargetGraphic/ColorTint"; + private const string k_DefaultTextureBasePath = "/button/TargetGraphic/SpriteState"; + private const string k_DefaultNamespace = "default"; + #region 序列化字段 [Header("五态样式路径")] [SerializeField] [Tooltip("正常状态")] - private StyleField m_Normal = new StyleField(); + private StyleField m_Normal = new StyleField { Namespace = k_DefaultNamespace, StylePath = k_DefaultColorBasePath + "/NormalColor" }; [SerializeField] [Tooltip("高亮状态")] - private StyleField m_Highlighted = new StyleField(); + private StyleField m_Highlighted = new StyleField { Namespace = k_DefaultNamespace, StylePath = k_DefaultColorBasePath + "/HighlightedColor" }; [SerializeField] [Tooltip("按下状态")] - private StyleField m_Pressed = new StyleField(); + private StyleField m_Pressed = new StyleField { Namespace = k_DefaultNamespace, StylePath = k_DefaultColorBasePath + "/PressedColor" }; [SerializeField] [Tooltip("选中状态")] - private StyleField m_Selected = new StyleField(); + private StyleField m_Selected = new StyleField { Namespace = k_DefaultNamespace, StylePath = k_DefaultColorBasePath + "/SelectedColor" }; [SerializeField] [Tooltip("禁用状态")] - private StyleField m_Disabled = new StyleField(); + private StyleField m_Disabled = new StyleField { Namespace = k_DefaultNamespace, StylePath = k_DefaultColorBasePath + "/DisabledColor" }; [Header("过渡")] [SerializeField] @@ -66,9 +68,24 @@ namespace XericUI.Core.StyleSheetUI m_Normal, m_Highlighted, m_Pressed, m_Selected, m_Disabled }; - /// 默认实例 + /// 默认实例(五态默认匹配 ColorTint 颜色块) public static StyleSheetState Default => new StyleSheetState(); + /// + /// 创建纹理五态样式块,StylePath 默认匹配 SpriteState 块。 + /// + public static StyleSheetState CreateTexture(string ns = k_DefaultNamespace) + { + var state = new StyleSheetState(); + state.Normal.StylePath = k_DefaultTextureBasePath + "/NormalSprite"; + state.Highlighted.StylePath = k_DefaultTextureBasePath + "/HighlightedSprite"; + state.Pressed.StylePath = k_DefaultTextureBasePath + "/PressedSprite"; + state.Selected.StylePath = k_DefaultTextureBasePath + "/SelectedSprite"; + state.Disabled.StylePath = k_DefaultTextureBasePath + "/DisabledSprite"; + foreach (var f in state.AllFields) f.Namespace = ns; + return state; + } + #endregion #region 查找 diff --git a/Runtime/InterfaceAttributeReflectionGenerator/Test/xuiSceen.unity b/Runtime/InterfaceAttributeReflectionGenerator/Test/xuiSceen.unity index 45a77f6..a8937c5 100644 --- a/Runtime/InterfaceAttributeReflectionGenerator/Test/xuiSceen.unity +++ b/Runtime/InterfaceAttributeReflectionGenerator/Test/xuiSceen.unity @@ -153,7 +153,7 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: - {fileID: 1479413702} - - {fileID: 1558175926} + - {fileID: 1278174473} m_Father: {fileID: 1305945111} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0.5, y: 1} @@ -605,7 +605,7 @@ RectTransform: m_AnchorMin: {x: 0, y: 1} m_AnchorMax: {x: 0, y: 1} m_AnchoredPosition: {x: 0, y: 0} - m_SizeDelta: {x: 360, y: 60} + m_SizeDelta: {x: 260, y: 160} m_Pivot: {x: 0, y: 1} --- !u!114 &779072859 MonoBehaviour: @@ -636,7 +636,7 @@ MonoBehaviour: - Text: Age Image: {fileID: 0} Prefab: {fileID: 0} - StyleNamespace: xeric_table_default + StyleNamespace: - Text: City Image: {fileID: 0} Prefab: {fileID: 0} @@ -764,7 +764,7 @@ MonoBehaviour: - Text: 25 Image: {fileID: 0} Prefab: {fileID: 0} - StyleNamespace: + StyleNamespace: xeric_table_default - Text: NYC Image: {fileID: 0} Prefab: {fileID: 0} @@ -4727,14 +4727,14 @@ MonoBehaviour: StyleNamespace: MergeDescriptors: [] m_RowHeights: - - 20 - - 20 - - 20 + - 40 + - 40 + - 40 + - 40 m_ColWidths: - 80 - 80 - 100 - - 100 m_DefaultStyleNamespace: xeric_table_default m_ScrollRect: {fileID: 176805031} --- !u!222 &779072860 @@ -4745,6 +4745,140 @@ CanvasRenderer: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 779072857} m_CullTransparentMesh: 1 +--- !u!1 &824962586 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 824962587} + - component: {fileID: 824962589} + - component: {fileID: 824962588} + m_Layer: 5 + m_Name: Text (TMP) + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &824962587 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 824962586} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 1278174473} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &824962588 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 824962586} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_text: Button + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_fontSharedMaterials: [] + m_fontMaterial: {fileID: 0} + m_fontMaterials: [] + m_fontColor32: + serializedVersion: 2 + rgba: 4281479730 + m_fontColor: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1} + m_enableVertexGradient: 0 + m_colorMode: 3 + m_fontColorGradient: + topLeft: {r: 1, g: 1, b: 1, a: 1} + topRight: {r: 1, g: 1, b: 1, a: 1} + bottomLeft: {r: 1, g: 1, b: 1, a: 1} + bottomRight: {r: 1, g: 1, b: 1, a: 1} + m_fontColorGradientPreset: {fileID: 0} + m_spriteAsset: {fileID: 0} + m_tintAllSprites: 0 + m_StyleSheet: {fileID: 0} + m_TextStyleHashCode: -1183493901 + m_overrideHtmlColors: 0 + m_faceColor: + serializedVersion: 2 + rgba: 4294967295 + m_fontSize: 24 + m_fontSizeBase: 24 + m_fontWeight: 400 + m_enableAutoSizing: 0 + m_fontSizeMin: 18 + m_fontSizeMax: 72 + m_fontStyle: 0 + m_HorizontalAlignment: 2 + m_VerticalAlignment: 512 + m_textAlignment: 65535 + m_characterSpacing: 0 + m_wordSpacing: 0 + m_lineSpacing: 0 + m_lineSpacingMax: 0 + m_paragraphSpacing: 0 + m_charWidthMaxAdj: 0 + m_enableWordWrapping: 1 + m_wordWrappingRatios: 0.4 + m_overflowMode: 0 + m_linkedTextComponent: {fileID: 0} + parentLinkedComponent: {fileID: 0} + m_enableKerning: 1 + m_enableExtraPadding: 0 + checkPaddingRequired: 0 + m_isRichText: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 1 + m_isCullingEnabled: 0 + m_horizontalMapping: 0 + m_verticalMapping: 0 + m_uvLineOffset: 0 + m_geometrySortingOrder: 0 + m_IsTextObjectScaleStatic: 0 + m_VertexBufferAutoSizeReduction: 0 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 1 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + m_hasFontAssetChanged: 0 + m_baseMaterial: {fileID: 0} + m_maskOffset: {x: 0, y: 0, z: 0, w: 0} +--- !u!222 &824962589 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 824962586} + m_CullTransparentMesh: 1 --- !u!224 &879192284 stripped RectTransform: m_CorrespondingSourceObject: {fileID: 3719551361696879033, guid: 1715f06fee075eb45b68d43575e9aa88, type: 3} @@ -4954,6 +5088,192 @@ Transform: - {fileID: 1830323039} m_Father: {fileID: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1278174472 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1278174473} + - component: {fileID: 1278174476} + - component: {fileID: 1278174475} + - component: {fileID: 1278174474} + m_Layer: 5 + m_Name: Button + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1278174473 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1278174472} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 824962587} + m_Father: {fileID: 29274970} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 202.5, y: 0} + m_SizeDelta: {x: 160, y: 30} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1278174474 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1278174472} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: ac135f8a0c9ac114aabb20e033ab1331, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_WrapAround: 0 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 1} + m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} + m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_SelectedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_SelectedTrigger: Selected + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 1278174475} + m_OnClick: + m_PersistentCalls: + m_Calls: [] + m_ColorState: + m_Normal: + _namespace: default + _stylePath: /button/TargetGraphic/ColorTint/NormalColor + _member: + StylePath: /button/TargetGraphic/ColorTint/NormalColor + CurrentNamespace: default + m_Highlighted: + _namespace: default + _stylePath: /button/TargetGraphic/ColorTint/HighlightedColor + _member: + StylePath: /button/TargetGraphic/ColorTint/HighlightedColor + CurrentNamespace: default + m_Pressed: + _namespace: default + _stylePath: /button/TargetGraphic/ColorTint/PressedColor + _member: + StylePath: /button/TargetGraphic/ColorTint/PressedColor + CurrentNamespace: default + m_Selected: + _namespace: default + _stylePath: /button/TargetGraphic/ColorTint/SelectedColor + _member: + StylePath: /button/TargetGraphic/ColorTint/SelectedColor + CurrentNamespace: default + m_Disabled: + _namespace: default + _stylePath: /button/TargetGraphic/ColorTint/DisabledColor + _member: + StylePath: /button/TargetGraphic/ColorTint/DisabledColor + CurrentNamespace: default + m_FadeDuration: 0.1 + m_TextureState: + m_Normal: + _namespace: default + _stylePath: /button/TargetGraphic/ColorTint/NormalColor + _member: + StylePath: /button/TargetGraphic/ColorTint/NormalColor + CurrentNamespace: default + m_Highlighted: + _namespace: default + _stylePath: /button/TargetGraphic/ColorTint/HighlightedColor + _member: + StylePath: /button/TargetGraphic/ColorTint/HighlightedColor + CurrentNamespace: default + m_Pressed: + _namespace: default + _stylePath: /button/TargetGraphic/ColorTint/PressedColor + _member: + StylePath: /button/TargetGraphic/ColorTint/PressedColor + CurrentNamespace: default + m_Selected: + _namespace: default + _stylePath: /button/TargetGraphic/ColorTint/SelectedColor + _member: + StylePath: /button/TargetGraphic/ColorTint/SelectedColor + CurrentNamespace: default + m_Disabled: + _namespace: default + _stylePath: /button/TargetGraphic/ColorTint/DisabledColor + _member: + StylePath: /button/TargetGraphic/ColorTint/DisabledColor + CurrentNamespace: default + m_FadeDuration: 0.1 + m_EnableStyleTransition: 1 +--- !u!114 &1278174475 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1278174472} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!222 &1278174476 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1278174472} + m_CullTransparentMesh: 1 --- !u!1 &1305945107 GameObject: m_ObjectHideFlags: 0 @@ -5243,192 +5563,6 @@ CanvasRenderer: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1479413701} m_CullTransparentMesh: 1 ---- !u!1 &1558175925 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 1558175926} - - component: {fileID: 1558175929} - - component: {fileID: 1558175928} - - component: {fileID: 1558175927} - m_Layer: 5 - m_Name: Button - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!224 &1558175926 -RectTransform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1558175925} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_ConstrainProportionsScale: 0 - m_Children: - - {fileID: 1966406954} - m_Father: {fileID: 29274970} - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 0.5, y: 0.5} - m_AnchorMax: {x: 0.5, y: 0.5} - m_AnchoredPosition: {x: 159.8, y: 0} - m_SizeDelta: {x: 160, y: 30} - m_Pivot: {x: 0.5, y: 0.5} ---- !u!114 &1558175927 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1558175925} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: ac135f8a0c9ac114aabb20e033ab1331, type: 3} - m_Name: - m_EditorClassIdentifier: - m_Navigation: - m_Mode: 3 - m_WrapAround: 0 - m_SelectOnUp: {fileID: 0} - m_SelectOnDown: {fileID: 0} - m_SelectOnLeft: {fileID: 0} - m_SelectOnRight: {fileID: 0} - m_Transition: 1 - m_Colors: - m_NormalColor: {r: 1, g: 1, b: 1, a: 1} - m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} - m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} - m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} - m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} - m_ColorMultiplier: 1 - m_FadeDuration: 0.1 - m_SpriteState: - m_HighlightedSprite: {fileID: 0} - m_PressedSprite: {fileID: 0} - m_SelectedSprite: {fileID: 0} - m_DisabledSprite: {fileID: 0} - m_AnimationTriggers: - m_NormalTrigger: Normal - m_HighlightedTrigger: Highlighted - m_PressedTrigger: Pressed - m_SelectedTrigger: Selected - m_DisabledTrigger: Disabled - m_Interactable: 1 - m_TargetGraphic: {fileID: 1558175928} - m_OnClick: - m_PersistentCalls: - m_Calls: [] - m_ColorState: - m_Normal: - _namespace: xeric_table_default - _stylePath: - _member: - StylePath: - CurrentNamespace: xeric_table_default - m_Highlighted: - _namespace: xeric_table_default - _stylePath: - _member: - StylePath: - CurrentNamespace: xeric_table_default - m_Pressed: - _namespace: xeric_table_default - _stylePath: - _member: - StylePath: - CurrentNamespace: xeric_table_default - m_Selected: - _namespace: xeric_table_default - _stylePath: - _member: - StylePath: - CurrentNamespace: xeric_table_default - m_Disabled: - _namespace: xeric_table_default - _stylePath: - _member: - StylePath: - CurrentNamespace: xeric_table_default - m_FadeDuration: 0.1 - m_TextureState: - m_Normal: - _namespace: - _stylePath: - _member: - StylePath: - CurrentNamespace: - m_Highlighted: - _namespace: - _stylePath: - _member: - StylePath: - CurrentNamespace: - m_Pressed: - _namespace: - _stylePath: - _member: - StylePath: - CurrentNamespace: - m_Selected: - _namespace: - _stylePath: - _member: - StylePath: - CurrentNamespace: - m_Disabled: - _namespace: - _stylePath: - _member: - StylePath: - CurrentNamespace: - m_FadeDuration: 0.1 - m_EnableStyleTransition: 1 ---- !u!114 &1558175928 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1558175925} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} - m_Name: - m_EditorClassIdentifier: - m_Material: {fileID: 0} - m_Color: {r: 1, g: 1, b: 1, a: 1} - m_RaycastTarget: 1 - m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} - m_Maskable: 1 - m_OnCullStateChanged: - m_PersistentCalls: - m_Calls: [] - m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0} - m_Type: 1 - m_PreserveAspect: 0 - m_FillCenter: 1 - m_FillMethod: 4 - m_FillAmount: 1 - m_FillClockwise: 1 - m_FillOrigin: 0 - m_UseSpriteMesh: 0 - m_PixelsPerUnitMultiplier: 1 ---- !u!222 &1558175929 -CanvasRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1558175925} - m_CullTransparentMesh: 1 --- !u!1 &1586214055 GameObject: m_ObjectHideFlags: 0 @@ -6014,140 +6148,6 @@ Transform: m_Children: [] m_Father: {fileID: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!1 &1966406953 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 1966406954} - - component: {fileID: 1966406956} - - component: {fileID: 1966406955} - m_Layer: 5 - m_Name: Text (TMP) - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!224 &1966406954 -RectTransform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1966406953} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_ConstrainProportionsScale: 0 - m_Children: [] - m_Father: {fileID: 1558175926} - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 0, y: 0} - m_AnchorMax: {x: 1, y: 1} - m_AnchoredPosition: {x: 0, y: 0} - m_SizeDelta: {x: 0, y: 0} - m_Pivot: {x: 0.5, y: 0.5} ---- !u!114 &1966406955 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1966406953} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3} - m_Name: - m_EditorClassIdentifier: - m_Material: {fileID: 0} - m_Color: {r: 1, g: 1, b: 1, a: 1} - m_RaycastTarget: 1 - m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} - m_Maskable: 1 - m_OnCullStateChanged: - m_PersistentCalls: - m_Calls: [] - m_text: Button - m_isRightToLeft: 0 - m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} - m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} - m_fontSharedMaterials: [] - m_fontMaterial: {fileID: 0} - m_fontMaterials: [] - m_fontColor32: - serializedVersion: 2 - rgba: 4281479730 - m_fontColor: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1} - m_enableVertexGradient: 0 - m_colorMode: 3 - m_fontColorGradient: - topLeft: {r: 1, g: 1, b: 1, a: 1} - topRight: {r: 1, g: 1, b: 1, a: 1} - bottomLeft: {r: 1, g: 1, b: 1, a: 1} - bottomRight: {r: 1, g: 1, b: 1, a: 1} - m_fontColorGradientPreset: {fileID: 0} - m_spriteAsset: {fileID: 0} - m_tintAllSprites: 0 - m_StyleSheet: {fileID: 0} - m_TextStyleHashCode: -1183493901 - m_overrideHtmlColors: 0 - m_faceColor: - serializedVersion: 2 - rgba: 4294967295 - m_fontSize: 24 - m_fontSizeBase: 24 - m_fontWeight: 400 - m_enableAutoSizing: 0 - m_fontSizeMin: 18 - m_fontSizeMax: 72 - m_fontStyle: 0 - m_HorizontalAlignment: 2 - m_VerticalAlignment: 512 - m_textAlignment: 65535 - m_characterSpacing: 0 - m_wordSpacing: 0 - m_lineSpacing: 0 - m_lineSpacingMax: 0 - m_paragraphSpacing: 0 - m_charWidthMaxAdj: 0 - m_enableWordWrapping: 1 - m_wordWrappingRatios: 0.4 - m_overflowMode: 0 - m_linkedTextComponent: {fileID: 0} - parentLinkedComponent: {fileID: 0} - m_enableKerning: 1 - m_enableExtraPadding: 0 - checkPaddingRequired: 0 - m_isRichText: 1 - m_parseCtrlCharacters: 1 - m_isOrthographic: 1 - m_isCullingEnabled: 0 - m_horizontalMapping: 0 - m_verticalMapping: 0 - m_uvLineOffset: 0 - m_geometrySortingOrder: 0 - m_IsTextObjectScaleStatic: 0 - m_VertexBufferAutoSizeReduction: 0 - m_useMaxVisibleDescender: 1 - m_pageToDisplay: 1 - m_margin: {x: 0, y: 0, z: 0, w: 0} - m_isUsingLegacyAnimationComponent: 0 - m_isVolumetricText: 0 - m_hasFontAssetChanged: 0 - m_baseMaterial: {fileID: 0} - m_maskOffset: {x: 0, y: 0, z: 0, w: 0} ---- !u!222 &1966406956 -CanvasRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1966406953} - m_CullTransparentMesh: 1 --- !u!224 &1986399782 stripped RectTransform: m_CorrespondingSourceObject: {fileID: 101967088653580022, guid: f601d441cf135fe479d319c5eb01abd8, type: 3} diff --git a/Runtime/OverrideUI/XericStyleButton.cs b/Runtime/OverrideUI/XericStyleButton.cs index 0a24157..f31a6c2 100644 --- a/Runtime/OverrideUI/XericStyleButton.cs +++ b/Runtime/OverrideUI/XericStyleButton.cs @@ -1,203 +1,220 @@ using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.UI; - using XericLibrary.Runtime.SuperStyleSheet; using XericUI.Core.StyleSheetUI; using XericUI.Helper; namespace XericUI.OverrideUI { - /// - /// 基于 SuperStyleSheet 的按钮组件。 - /// 通过两个独立的 StyleSheetState 实例分别管理颜色和纹理的五态样式切换, - /// 替代 Unity 内置的 ColorBlock 和 SpriteState。 - /// - [AddComponentMenu("Xeric UI Vessel/UI/Style Button", 51)] - public class XericStyleButton : Button, IStyleRefreshable - { - #region 序列化字段 + /// + /// 基于 SuperStyleSheet 的按钮组件。 + /// 通过 TransitionMode 选择颜色切换、纹理切换或两者并用, + /// 替代 Unity 内置的 ColorBlock 和 SpriteState。 + /// + [AddComponentMenu("Xeric UI Vessel/UI/Style Button", 51)] + public class XericStyleButton : Button, IStyleRefreshable + { + /// 样式过渡模式 + public enum TransitionMode + { + /// 仅颜色切换 + Color, + /// 仅纹理/Sprite 切换 + Sprite, + /// 颜色 + 纹理切换 + ColorAndSprite + } - [Header("样式表状态")] - [SerializeField] - [Tooltip("五态颜色样式块")] + #region 序列化字段 + + [Header("过渡模式")] + [SerializeField] + [Tooltip("选择颜色 / 纹理 / 同时切换")] + private TransitionMode m_TransitionMode = TransitionMode.ColorAndSprite; + + [Header("样式表状态")] [SerializeField] + [Tooltip("五态颜色样式块(ColorTint)")] private StyleSheetState m_ColorState = StyleSheetState.Default; [SerializeField] - [Tooltip("五态纹理样式块")] - private StyleSheetState m_TextureState = StyleSheetState.Default; + [Tooltip("五态纹理样式块(SpriteState)")] + private StyleSheetState m_TextureState = StyleSheetState.CreateTexture(); - [SerializeField] - [Tooltip("启用样式表驱动过渡(关闭则回退为 Unity ColorBlock)")] - private bool m_EnableStyleTransition = true; + [SerializeField] [Tooltip("启用样式表驱动过渡(关闭则回退为 Unity ColorBlock)")] + private bool m_EnableStyleTransition = true; - #endregion + #endregion - #region 运行时 + #region 运行时 - [System.NonSerialized] private StyleSheetSelectionState m_CurrentState = StyleSheetSelectionState.Normal; - [System.NonSerialized] private Graphic m_TargetGraphic; - [System.NonSerialized] private Image m_TargetImage; + [System.NonSerialized] private StyleSheetSelectionState m_CurrentState = StyleSheetSelectionState.Normal; + [System.NonSerialized] private Graphic m_TargetGraphic; + [System.NonSerialized] private Image m_TargetImage; - #endregion + #endregion - #region 生命周期 + #region 生命周期 - protected override void Awake() - { - base.Awake(); - m_TargetGraphic = targetGraphic; - m_TargetImage = m_TargetGraphic as Image; - } + protected override void Awake() + { + base.Awake(); + m_TargetGraphic = targetGraphic; + m_TargetImage = m_TargetGraphic as Image; + } - protected override void OnEnable() - { - base.OnEnable(); + protected override void OnEnable() + { + base.OnEnable(); - RevalidateStyles(); + RevalidateStyles(); - StyleRefreshManager.Register(this); - ApplyForState(m_CurrentState); - } + StyleRefreshManager.Register(this); + ApplyForState(m_CurrentState); + } #if UNITY_EDITOR - protected override void OnValidate() - { - base.OnValidate(); - RevalidateStyles(); - ApplyForState(m_CurrentState); - } + protected override void OnValidate() + { + base.OnValidate(); + RevalidateStyles(); + ApplyForState(m_CurrentState); + } #endif - private void RevalidateStyles() - { - m_ColorState?.UnsubscribeAll(OnStyleChanged); - m_TextureState?.UnsubscribeAll(OnStyleChanged); + private void RevalidateStyles() + { + m_ColorState?.UnsubscribeAll(OnStyleChanged); + m_TextureState?.UnsubscribeAll(OnStyleChanged); - m_ColorState?.RegisterAll(); - m_TextureState?.RegisterAll(); - m_ColorState?.SubscribeAll(OnStyleChanged); - m_TextureState?.SubscribeAll(OnStyleChanged); - } + m_ColorState?.RegisterAll(); + m_TextureState?.RegisterAll(); + m_ColorState?.SubscribeAll(OnStyleChanged); + m_TextureState?.SubscribeAll(OnStyleChanged); + } - protected override void OnDisable() - { - StyleRefreshManager.Unregister(this); + protected override void OnDisable() + { + StyleRefreshManager.Unregister(this); - m_ColorState?.UnsubscribeAll(OnStyleChanged); - m_TextureState?.UnsubscribeAll(OnStyleChanged); - m_ColorState?.UnregisterAll(); - m_TextureState?.UnregisterAll(); + m_ColorState?.UnsubscribeAll(OnStyleChanged); + m_TextureState?.UnsubscribeAll(OnStyleChanged); + m_ColorState?.UnregisterAll(); + m_TextureState?.UnregisterAll(); - base.OnDisable(); - } + base.OnDisable(); + } - #endregion + #endregion - #region 状态过渡 + #region 状态过渡 - protected override void DoStateTransition(SelectionState state, bool instant) - { - if (!gameObject.activeInHierarchy) return; + protected override void DoStateTransition(SelectionState state, bool instant) + { + if (!gameObject.activeInHierarchy) return; - m_CurrentState = (StyleSheetSelectionState)(int)state; + m_CurrentState = (StyleSheetSelectionState)(int)state; - if (m_EnableStyleTransition) - ApplyForState(m_CurrentState, instant); - else - base.DoStateTransition(state, instant); - } + if (m_EnableStyleTransition) + ApplyForState(m_CurrentState, instant); + else + base.DoStateTransition(state, instant); + } - #endregion + #endregion - #region 样式应用 + #region 样式应用 - public void RefreshStyle() - { - ApplyForState(m_CurrentState, false); - } + public void RefreshStyle() + { + ApplyForState(m_CurrentState, false); + } - private void ApplyForState(StyleSheetSelectionState state, bool instant = false) - { - // 颜色 - if (m_ColorState != null) - { - StyleField colorField = m_ColorState.GetForState(state); - if (colorField != null && m_TargetGraphic != null) - { - StyleValue val = colorField.GetValue(); - if (val != null) - m_TargetGraphic.CrossFadeColor((Color)val, - instant ? 0f : m_ColorState.FadeDuration, true, true); - } - } + private void ApplyForState(StyleSheetSelectionState state, bool instant = false) + { + if (m_TransitionMode == TransitionMode.Color || m_TransitionMode == TransitionMode.ColorAndSprite) + { + if (m_ColorState != null) + { + StyleField colorField = m_ColorState.GetForState(state); + if (colorField != null && m_TargetGraphic != null) + { + StyleValue val = colorField.GetValue(); + if (val != null) + m_TargetGraphic.CrossFadeColor((Color)val, + instant ? 0f : m_ColorState.FadeDuration, true, true); + } + } + } - // 纹理 - if (m_TextureState != null && m_TargetImage != null) - { - StyleField texField = m_TextureState.GetForState(state); - if (texField != null) - { - StyleValue val = texField.GetValue(); - Texture2D tex = val?.GetValueAs(); - if (tex != null) - m_TargetImage.overrideSprite = Sprite.Create(tex, - new Rect(0, 0, tex.width, tex.height), - new Vector2(0.5f, 0.5f)); - } - } - } + if (m_TransitionMode == TransitionMode.Sprite || m_TransitionMode == TransitionMode.ColorAndSprite) + { + if (m_TextureState != null && m_TargetImage != null) + { + StyleField texField = m_TextureState.GetForState(state); + if (texField != null) + { + StyleValue val = texField.GetValue(); + Texture2D tex = val?.GetValueAs(); + if (tex != null) + m_TargetImage.overrideSprite = Sprite.Create(tex, + new Rect(0, 0, tex.width, tex.height), + new Vector2(0.5f, 0.5f)); + } + } + } + } - private void OnStyleChanged(StyleValue _) - { - if (gameObject.activeInHierarchy) - ApplyForState(m_CurrentState); - } + private void OnStyleChanged(StyleValue _) + { + if (gameObject.activeInHierarchy) + ApplyForState(m_CurrentState); + } - #endregion + #endregion - #region 组件替换 + #region 组件替换 #if UNITY_EDITOR - [UnityEditor.MenuItem("CONTEXT/XericStyleButton/Xeric UI/强制刷新样式", false, 1)] - private static void ForceRefreshStyle(UnityEditor.MenuCommand command) - { - StyleRefreshManager.ForceRefreshAll(); - } + [UnityEditor.MenuItem("CONTEXT/XericStyleButton/Xeric UI/强制刷新样式", false, 1)] + private static void ForceRefreshStyle(UnityEditor.MenuCommand command) + { + StyleRefreshManager.ForceRefreshAll(); + } - [UnityEditor.MenuItem("CONTEXT/Button/Replace To/Xeric (Style)", true)] - private static bool ValidateReplaceToStyleButton(UnityEditor.MenuCommand command) - => command.context is Button and not XericStyleButton; + [UnityEditor.MenuItem("CONTEXT/Button/Replace To/Xeric (Style)", true)] + private static bool ValidateReplaceToStyleButton(UnityEditor.MenuCommand command) + => command.context is Button and not XericStyleButton; - [UnityEditor.MenuItem("CONTEXT/Button/Replace To/Xeric (Style)", false, 11)] - private static void ReplaceToStyleButton(UnityEditor.MenuCommand command) - => command.ReplaceCommandContext( - o => (o.targetGraphic, o.onClick, o.navigation), - (t, d) => - { - t.targetGraphic = d.targetGraphic; - t.onClick = d.onClick; - t.navigation = d.navigation; - }); + [UnityEditor.MenuItem("CONTEXT/Button/Replace To/Xeric (Style)", false, 11)] + private static void ReplaceToStyleButton(UnityEditor.MenuCommand command) + => command.ReplaceCommandContext( + o => (o.targetGraphic, o.onClick, o.navigation), + (t, d) => + { + t.targetGraphic = d.targetGraphic; + t.onClick = d.onClick; + t.navigation = d.navigation; + }); - [UnityEditor.MenuItem("CONTEXT/Button/Replace To/Unity Button", true)] - private static bool ValidateReplaceStyleToUnity(UnityEditor.MenuCommand command) - => command.context is XericStyleButton; + [UnityEditor.MenuItem("CONTEXT/Button/Replace To/Unity Button", true)] + private static bool ValidateReplaceStyleToUnity(UnityEditor.MenuCommand command) + => command.context is XericStyleButton; - [UnityEditor.MenuItem("CONTEXT/Button/Replace To/Unity Button", false, 100)] - private static void ReplaceStyleToUnity(UnityEditor.MenuCommand command) - => command.ReplaceCommandContext( - o => (o.targetGraphic, o.onClick, o.navigation), - (t, d) => - { - t.targetGraphic = d.targetGraphic; - t.onClick = d.onClick; - t.navigation = d.navigation; - }); + [UnityEditor.MenuItem("CONTEXT/Button/Replace To/Unity Button", false, 100)] + private static void ReplaceStyleToUnity(UnityEditor.MenuCommand command) + => command.ReplaceCommandContext( + o => (o.targetGraphic, o.onClick, o.navigation), + (t, d) => + { + t.targetGraphic = d.targetGraphic; + t.onClick = d.onClick; + t.navigation = d.navigation; + }); #endif - #endregion - } -} + #endregion + } +} \ No newline at end of file diff --git a/Runtime/OverrideUI/XericStyleToggle.cs b/Runtime/OverrideUI/XericStyleToggle.cs index a1f0173..d47f4fa 100644 --- a/Runtime/OverrideUI/XericStyleToggle.cs +++ b/Runtime/OverrideUI/XericStyleToggle.cs @@ -9,20 +9,38 @@ namespace XericUI.OverrideUI { /// /// 基于 SuperStyleSheet 的开关组件。 - /// 使用两个 StyleSheetState 实例管理五态颜色和纹理样式, + /// 通过 TransitionMode 选择颜色切换、纹理切换或两者并用, /// 额外支持 isOn 覆盖和 Checkmark 样式。 /// [AddComponentMenu("Xeric UI Vessel/UI/Style Toggle", 52)] public class XericStyleToggle : Toggle, IStyleRefreshable { + /// 样式过渡模式 + public enum TransitionMode + { + /// 仅颜色切换 + Color, + /// 仅纹理/Sprite 切换 + Sprite, + /// 颜色 + 纹理切换 + ColorAndSprite + } + #region 序列化字段 + [Header("过渡模式")] + [SerializeField] + [Tooltip("选择颜色 / 纹理 / 同时切换")] + private TransitionMode m_TransitionMode = TransitionMode.ColorAndSprite; + [Header("样式表状态")] [SerializeField] + [Tooltip("五态颜色样式块(ColorTint)")] private StyleSheetState m_ColorState = StyleSheetState.Default; [SerializeField] - private StyleSheetState m_TextureState = StyleSheetState.Default; + [Tooltip("五态纹理样式块(SpriteState)")] + private StyleSheetState m_TextureState = StyleSheetState.CreateTexture(); [Header("Toggle 专用")] [SerializeField] @@ -163,37 +181,43 @@ namespace XericUI.OverrideUI private void ApplyForState(StyleSheetSelectionState state, bool instant = false) { - // 颜色:On 覆盖优先 - StyleField colorField = isOn && m_OnOverrideColor?.GetValue() != null - ? m_OnOverrideColor - : m_ColorState?.GetForState(state); - - if (colorField != null && m_TargetGraphic != null) + if (m_TransitionMode == TransitionMode.Color || m_TransitionMode == TransitionMode.ColorAndSprite) { - StyleValue val = colorField.GetValue(); - if (val != null) + // 颜色:On 覆盖优先 + StyleField colorField = isOn && m_OnOverrideColor?.GetValue() != null + ? m_OnOverrideColor + : m_ColorState?.GetForState(state); + + if (colorField != null && m_TargetGraphic != null) { - float dur = instant ? 0f : (m_ColorState?.FadeDuration ?? 0.1f); - m_TargetGraphic.CrossFadeColor((Color)val, dur, true, true); + StyleValue val = colorField.GetValue(); + if (val != null) + { + float dur = instant ? 0f : (m_ColorState?.FadeDuration ?? 0.1f); + m_TargetGraphic.CrossFadeColor((Color)val, dur, true, true); + } } } - // 纹理:On 覆盖优先 - StyleField texField = isOn && m_OnOverrideTexture?.GetValue() != null - ? m_OnOverrideTexture - : m_TextureState?.GetForState(state); - - if (texField != null && m_TargetImage != null) + if (m_TransitionMode == TransitionMode.Sprite || m_TransitionMode == TransitionMode.ColorAndSprite) { - StyleValue val = texField.GetValue(); - Texture2D tex = val?.GetValueAs(); - if (tex != null) - m_TargetImage.overrideSprite = Sprite.Create(tex, - new Rect(0, 0, tex.width, tex.height), - new Vector2(0.5f, 0.5f)); + // 纹理:On 覆盖优先 + StyleField texField = isOn && m_OnOverrideTexture?.GetValue() != null + ? m_OnOverrideTexture + : m_TextureState?.GetForState(state); + + if (texField != null && m_TargetImage != null) + { + StyleValue val = texField.GetValue(); + Texture2D tex = val?.GetValueAs(); + if (tex != null) + m_TargetImage.overrideSprite = Sprite.Create(tex, + new Rect(0, 0, tex.width, tex.height), + new Vector2(0.5f, 0.5f)); + } } - // Checkmark + // Checkmark(独立于 TransitionMode) if (m_CheckmarkGraphic != null && m_CheckmarkStyle != null) { StyleValue val = m_CheckmarkStyle.GetValue(); diff --git a/Runtime/XTable/Rendering/Component/XericUIActionTable.cs b/Runtime/XTable/Rendering/Component/XericUIActionTable.cs index dce28aa..d2b2985 100644 --- a/Runtime/XTable/Rendering/Component/XericUIActionTable.cs +++ b/Runtime/XTable/Rendering/Component/XericUIActionTable.cs @@ -39,6 +39,10 @@ namespace XericUI.XTable.Rendering.Component [SerializeField] private ScrollRect m_ScrollRect; + [SerializeField] + [Tooltip("在 Hierarchy 中显示动态生成的子对象(仅编辑器,不保存到场景)")] + private bool m_ChildrenVisible; + #endregion #region 私有字段 @@ -102,6 +106,13 @@ namespace XericUI.XTable.Rendering.Component public int SelectEndCol => m_SelectEndCol; public bool HasMultiSelection => m_SelectStartRow >= 0 && m_SelectEndRow >= 0; + /// 动态子对象在 Hierarchy 中是否可见(仅编辑器有效) + public bool ChildrenVisible + { + get => m_ChildrenVisible; + set => SetChildrenVisible(value); + } + /// 判断单元格是否在多选范围内 public bool IsInSelectionRange(int row, int col) { @@ -151,6 +162,15 @@ namespace XericUI.XTable.Rendering.Component MarkDirty(TableDirtyType.All); } +#if UNITY_EDITOR + protected override void OnValidate() + { + base.OnValidate(); + // 编辑器下属性变更 / 选中组件时即刻刷新样式 + MarkDirty(TableDirtyType.All); + } +#endif + protected override void OnDisable() { base.OnDisable(); @@ -606,6 +626,7 @@ namespace XericUI.XTable.Rendering.Component m_DirtyFlag.Clear(); OnTableRefreshed?.Invoke(); + SetChildrenVisible(m_ChildrenVisible); } #endregion @@ -629,7 +650,7 @@ namespace XericUI.XTable.Rendering.Component bgRt.sizeDelta = new Vector2(m_TotalWidth, m_TotalHeight); var bgImg = m_BackgroundGo.GetComponent(); - bgImg.color = new Color(0.18f, 0.18f, 0.18f, 1f); + bgImg.color = GetStyleColor(m_DefaultStyleNamespace, "/cell/bg/color", new Color(0.18f, 0.18f, 0.18f, 1f)); bgImg.raycastTarget = false; } @@ -661,14 +682,15 @@ namespace XericUI.XTable.Rendering.Component /// 设置所有动态子对象的可见性(仅编辑器) public void SetChildrenVisible(bool visible) { + m_ChildrenVisible = visible; #if UNITY_EDITOR if (rectTransform == null) return; for (int i = rectTransform.childCount - 1; i >= 0; i--) { var child = rectTransform.GetChild(i); child.gameObject.hideFlags = visible - ? HideFlags.DontSave // 可见但不保存 - : HideFlags.DontSave | HideFlags.HideInHierarchy; // 隐藏且不保存 + ? HideFlags.DontSave + : HideFlags.DontSave | HideFlags.HideInHierarchy; } #endif } @@ -689,6 +711,7 @@ namespace XericUI.XTable.Rendering.Component CreateBackground(); MarkDirty(TableDirtyType.All); RefreshView(); + SetChildrenVisible(m_ChildrenVisible); } #endregion @@ -698,9 +721,82 @@ namespace XericUI.XTable.Rendering.Component private void RenderCells(int sr, int er, int sc, int ec) { Color fgFallback = new Color(0.05f, 0.05f, 0.05f); - Color selectionColor = new Color(0.18f, 0.42f, 0.82f, 0.25f); - Color multiSelectColor = new Color(0.18f, 0.42f, 0.82f, 0.12f); - Color focusColor = new Color(0.22f, 0.55f, 0.95f, 0.35f); + string ns = m_DefaultStyleNamespace; + + // 编辑器模式:从样式表 pull 所有颜色值 +#if UNITY_EDITOR + if (!Application.isPlaying) + { + Color selectionColor = GetStyleColor(ns, "/cell/selection/bg/color", new Color(0.2f, 0.5f, 1f, 0.3f)); + Color borderColor = GetStyleColor(ns, "/cell/border/bottom/color", new Color(0.35f, 0.35f, 0.35f, 0.5f)); + float borderWidth = GetStyleFloat(ns, "/cell/border/bottom/width", 1f); + + Color multiSelectColor = new Color(selectionColor.r, selectionColor.g, selectionColor.b, selectionColor.a * 0.4f); + Color focusColor = new Color(selectionColor.r + 0.04f, selectionColor.g + 0.13f, selectionColor.b + 0.13f, selectionColor.a * 1.4f); + + for (int r = sr; r < er && r < m_RowHeights.Length; r++) + { + for (int c = sc; c < ec && c < m_ColWidths.Length; c++) + { + float cellX = GetColLeftX(c); + float cellY = -GetRowTopY(r); + float cellW = m_ColWidths[c]; + float cellH = m_RowHeights[r]; + XTableCellData data = TableData.GetCell(r, c); + string cellNS = (data != null && !string.IsNullOrEmpty(data.StyleNamespace)) + ? data.StyleNamespace : ns; + + // 多选高亮 + if (IsInSelectionRange(r, c)) + { + var selImg = m_Assembler.GetImage("cell_multiselect"); + selImg.Rect.anchoredPosition = new Vector2(cellX, cellY); + selImg.Rect.sizeDelta = new Vector2(cellW, cellH); + selImg.Image.color = (r == m_SelectedRow && c == m_SelectedCol) + ? focusColor : multiSelectColor; + } + else if (r == m_SelectedRow && c == m_SelectedCol) + { + var selImg = m_Assembler.GetImage("cell_select"); + selImg.Rect.anchoredPosition = new Vector2(cellX, cellY); + selImg.Rect.sizeDelta = new Vector2(cellW, cellH); + selImg.Image.color = selectionColor; + } + + // 水平网格线(单元格底部) + var hLine = m_Assembler.GetImage("cell_hline"); + hLine.Rect.anchoredPosition = new Vector2(cellX, cellY - cellH); + hLine.Rect.sizeDelta = new Vector2(cellW, borderWidth); + hLine.Image.color = borderColor; + + // 垂直网格线(单元格右侧) + var vLine = m_Assembler.GetImage("cell_vline"); + vLine.Rect.anchoredPosition = new Vector2(cellX + cellW - borderWidth, cellY); + vLine.Rect.sizeDelta = new Vector2(borderWidth, cellH); + vLine.Image.color = borderColor; + + if (data == null) continue; + + if (!string.IsNullOrEmpty(data.Text)) + { + var txt = m_Assembler.GetText("cell_text", cellNS); + txt.Rect.anchoredPosition = new Vector2(cellX + 4, cellY); + txt.Rect.sizeDelta = new Vector2(cellW - 8, cellH); + txt.Text.text = data.Text; + txt.Text.color = GetStyleColor(cellNS, "/cell/fg/color", fgFallback); + txt.Text.fontSize = GetStyleInt(cellNS, "/cell/font/size", 14); + txt.Text.alignment = TextAlignmentOptions.Midline; + } + } + } + return; + } +#endif + + // 运行时模式 + Color rtSelectionColor = new Color(0.18f, 0.42f, 0.82f, 0.25f); + Color rtMultiSelectColor = new Color(0.18f, 0.42f, 0.82f, 0.12f); + Color rtFocusColor = new Color(0.22f, 0.55f, 0.95f, 0.35f); for (int r = sr; r < er && r < m_RowHeights.Length; r++) { @@ -712,34 +808,29 @@ namespace XericUI.XTable.Rendering.Component float cellH = m_RowHeights[r]; XTableCellData data = TableData.GetCell(r, c); string cellNS = (data != null && !string.IsNullOrEmpty(data.StyleNamespace)) - ? data.StyleNamespace : m_DefaultStyleNamespace; + ? data.StyleNamespace : ns; - // 多选范围高亮(覆盖被选中范围内的所有格) if (IsInSelectionRange(r, c)) { var selImg = m_Assembler.GetImage("cell_multiselect"); selImg.Rect.anchoredPosition = new Vector2(cellX, cellY); selImg.Rect.sizeDelta = new Vector2(cellW, cellH); selImg.Image.color = (r == m_SelectedRow && c == m_SelectedCol) - ? focusColor - : multiSelectColor; + ? rtFocusColor : rtMultiSelectColor; } - // 单选高亮 else if (r == m_SelectedRow && c == m_SelectedCol) { var selImg = m_Assembler.GetImage("cell_select"); selImg.Rect.anchoredPosition = new Vector2(cellX, cellY); selImg.Rect.sizeDelta = new Vector2(cellW, cellH); - selImg.Image.color = selectionColor; + selImg.Image.color = rtSelectionColor; } - // 水平网格线 var hLine = m_Assembler.GetImage("cell_hline"); hLine.Rect.anchoredPosition = new Vector2(cellX, cellY - cellH); hLine.Rect.sizeDelta = new Vector2(cellW, 1f); hLine.Image.color = new Color(0.35f, 0.35f, 0.35f, 0.5f); - // 垂直网格线 var vLine = m_Assembler.GetImage("cell_vline"); vLine.Rect.anchoredPosition = new Vector2(cellX + cellW - 1, cellY); vLine.Rect.sizeDelta = new Vector2(1f, cellH); @@ -747,7 +838,6 @@ namespace XericUI.XTable.Rendering.Component if (data == null) continue; - // 文本:与 cell 同位置同尺寸 if (!string.IsNullOrEmpty(data.Text)) { var txt = m_Assembler.GetText("cell_text", cellNS); @@ -756,7 +846,6 @@ namespace XericUI.XTable.Rendering.Component txt.Text.text = data.Text; #if UNITY_EDITOR - // 编辑器模式:直接 pull 样式值(cellNS 可能是个性化命名空间) if (!Application.isPlaying) { txt.Text.color = GetStyleColor(cellNS, "/cell/fg/color", fgFallback); @@ -764,8 +853,6 @@ namespace XericUI.XTable.Rendering.Component txt.Text.alignment = TextAlignmentOptions.Midline; } #endif - // 运行时:颜色/字号/对齐由 StyleBoundElement 管理(push), - // GetText(_, cellNS) 已通过 BindStyle 注册了对应命名空间的 StyleField } } } @@ -879,6 +966,12 @@ namespace XericUI.XTable.Rendering.Component return val != null ? (int)val : fallback; } + private float GetStyleFloat(string ns, string path, float fallback) + { + StyleValue val = StyleManager.GetValue(ns, path); + return val != null ? (float)val : fallback; + } + private void EnsureDefaultStyleNamespace() { // 避免在样式表尚未加载时触发 HasStyle → GetValue 的命名空间不存在错误 @@ -888,11 +981,29 @@ namespace XericUI.XTable.Rendering.Component if (!StyleManager.HasStyle(m_DefaultStyleNamespace, "/cell/bg/color")) { - StyleManager.AddDynamicStyle(m_DefaultStyleNamespace, "/cell/bg/color", - new Color(0.18f, 0.18f, 0.18f)); + // 回退默认值匹配 DefaultTableStyles.xsss + StyleManager.AddDynamicStyle(m_DefaultStyleNamespace, "/cell/bg/color", Color.white); StyleManager.AddDynamicStyle(m_DefaultStyleNamespace, "/cell/fg/color", - new Color(0.05f, 0.05f, 0.05f)); + new Color(0.1f, 0.1f, 0.1f)); + StyleManager.AddDynamicStyle(m_DefaultStyleNamespace, "/cell/border/top/color", + new Color(0.8f, 0.8f, 0.8f)); + StyleManager.AddDynamicStyle(m_DefaultStyleNamespace, "/cell/border/top/width", 1f); + StyleManager.AddDynamicStyle(m_DefaultStyleNamespace, "/cell/border/bottom/color", + new Color(0.8f, 0.8f, 0.8f)); + StyleManager.AddDynamicStyle(m_DefaultStyleNamespace, "/cell/border/bottom/width", 1f); + StyleManager.AddDynamicStyle(m_DefaultStyleNamespace, "/cell/border/left/color", + new Color(0.8f, 0.8f, 0.8f)); + StyleManager.AddDynamicStyle(m_DefaultStyleNamespace, "/cell/border/left/width", 1f); + StyleManager.AddDynamicStyle(m_DefaultStyleNamespace, "/cell/border/right/color", + new Color(0.8f, 0.8f, 0.8f)); + StyleManager.AddDynamicStyle(m_DefaultStyleNamespace, "/cell/border/right/width", 1f); + StyleManager.AddDynamicStyle(m_DefaultStyleNamespace, "/cell/selection/bg/color", + new Color(0.2f, 0.5f, 1f, 0.3f)); StyleManager.AddDynamicStyle(m_DefaultStyleNamespace, "/cell/font/size", 14); + StyleManager.AddDynamicStyle(m_DefaultStyleNamespace, "/cell/font/alignment", "MiddleCenter"); + StyleManager.AddDynamicStyle(m_DefaultStyleNamespace, "/cell/font/richText", true); + StyleManager.AddDynamicStyle(m_DefaultStyleNamespace, "/cell/default/height", 40f); + StyleManager.AddDynamicStyle(m_DefaultStyleNamespace, "/cell/default/width", 100f); StyleManager.ForceRefresh(); } }