From 60d5822a8247082a2b0ad18423e02dc97c229848 Mon Sep 17 00:00:00 2001 From: LiRuoChen <571244399@qq.com> Date: Thu, 16 Apr 2026 10:22:39 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E4=BA=86=E4=B8=80=E9=94=AE?= =?UTF-8?q?=E6=9B=BF=E6=8D=A2=E7=BB=84=E4=BB=B6=E7=9A=84=E6=96=B9=E6=B3=95?= =?UTF-8?q?=E3=80=82=20=E4=BF=AE=E6=94=B9=E4=BA=86xericlibrary=E7=9A=84api?= =?UTF-8?q?=E3=80=82=20=E4=BF=AE=E6=94=B9=E4=BA=86=E8=8F=9C=E5=8D=95?= =?UTF-8?q?=E8=B7=AF=E5=BE=84=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Editor/OverrideUI.meta | 3 + Editor/OverrideUI/XericToggleEditor.cs | 105 +++++++++ Editor/OverrideUI/XericToggleEditor.cs.meta | 3 + Runtime/Core/Vessel/ObjectVessel.cs | 1 - .../UIDynamicActiveImpact.cs | 2 +- Runtime/Helper/EditorOverrideUIHelper.cs | 88 ++++++++ Runtime/Helper/EditorOverrideUIHelper.cs.meta | 3 + Runtime/OverrideLayout/XericScrollRect.cs | 54 ++++- Runtime/OverrideUI/XericToggle.cs | 209 ++++++++++++++++++ Runtime/OverrideUI/XericToggle.cs.meta | 11 + Runtime/OverrideUI/XericToggleGroup.cs | 24 +- 11 files changed, 497 insertions(+), 6 deletions(-) create mode 100644 Editor/OverrideUI.meta create mode 100644 Editor/OverrideUI/XericToggleEditor.cs create mode 100644 Editor/OverrideUI/XericToggleEditor.cs.meta create mode 100644 Runtime/Helper/EditorOverrideUIHelper.cs create mode 100644 Runtime/Helper/EditorOverrideUIHelper.cs.meta create mode 100644 Runtime/OverrideUI/XericToggle.cs create mode 100644 Runtime/OverrideUI/XericToggle.cs.meta diff --git a/Editor/OverrideUI.meta b/Editor/OverrideUI.meta new file mode 100644 index 0000000..1384eff --- /dev/null +++ b/Editor/OverrideUI.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: c99b9ff93a76477b997558ce3f14ec78 +timeCreated: 1776232260 \ No newline at end of file diff --git a/Editor/OverrideUI/XericToggleEditor.cs b/Editor/OverrideUI/XericToggleEditor.cs new file mode 100644 index 0000000..efb8840 --- /dev/null +++ b/Editor/OverrideUI/XericToggleEditor.cs @@ -0,0 +1,105 @@ +using UnityEditor; +using UnityEditor.SceneManagement; +using UnityEditor.UI; +using UnityEngine; +using UnityEngine.UI; + +namespace XericUI +{ + [CustomEditor(typeof(XericToggle))] + internal class XericToggleEditor : SelectableEditor + { + SerializedProperty m_OnValueChangedProperty; + SerializedProperty m_TransitionProperty; + SerializedProperty m_GraphicProperty; + SerializedProperty m_GroupProperty; + SerializedProperty m_IsOnProperty; + + SerializedProperty m_TextProperty; + SerializedProperty m_EnableTextColorTransitionProperty; + SerializedProperty m_TextTransitionColorModeProperty; + SerializedProperty m_enableTextContextTransitionProperty; + SerializedProperty m_textTransitionContextModeProperty; + + protected override void OnEnable() + { + base.OnEnable(); + + m_TransitionProperty = serializedObject.FindProperty("toggleTransition"); + m_GraphicProperty = serializedObject.FindProperty("graphic"); + m_GroupProperty = serializedObject.FindProperty("m_Group"); + m_IsOnProperty = serializedObject.FindProperty("m_IsOn"); + m_OnValueChangedProperty = serializedObject.FindProperty("onValueChanged"); + + m_TextProperty = serializedObject.FindProperty("m_text"); + m_EnableTextColorTransitionProperty = serializedObject.FindProperty("m_enableTextColorTransition"); + m_TextTransitionColorModeProperty = serializedObject.FindProperty("m_textTransitionColorMode"); + m_enableTextContextTransitionProperty = serializedObject.FindProperty("m_enableTextContextTransition"); + m_textTransitionContextModeProperty = serializedObject.FindProperty("m_textTransitionContextMode"); + } + + public override void OnInspectorGUI() + { + base.OnInspectorGUI(); + EditorGUILayout.Space(); + + serializedObject.Update(); + Toggle toggle = serializedObject.targetObject as Toggle; + EditorGUI.BeginChangeCheck(); + EditorGUILayout.PropertyField(m_IsOnProperty); + if (EditorGUI.EndChangeCheck()) + { + if (!Application.isPlaying) + EditorSceneManager.MarkSceneDirty(toggle.gameObject.scene); + + ToggleGroup group = m_GroupProperty.objectReferenceValue as ToggleGroup; + + toggle.isOn = m_IsOnProperty.boolValue; + + if (group != null && group.isActiveAndEnabled && toggle.IsActive()) + { + if (toggle.isOn || (!group.AnyTogglesOn() && !group.allowSwitchOff)) + { + toggle.isOn = true; + group.NotifyToggleOn(toggle); + } + } + } + + EditorGUILayout.PropertyField(m_TransitionProperty); + EditorGUILayout.PropertyField(m_GraphicProperty); + EditorGUILayout.PropertyField(m_TextProperty); + EditorGUILayout.PropertyField(m_EnableTextColorTransitionProperty); + if (EditorGUILayout.BeginFadeGroup(m_EnableTextColorTransitionProperty.boolValue ? 1 : 0)) + { + EditorGUILayout.PropertyField(m_TextTransitionColorModeProperty); + } + EditorGUILayout.EndFadeGroup(); + + EditorGUILayout.PropertyField(m_enableTextContextTransitionProperty); + if (EditorGUILayout.BeginFadeGroup(m_enableTextContextTransitionProperty.boolValue ? 1 : 0)) + { + EditorGUILayout.PropertyField(m_textTransitionContextModeProperty); + } + EditorGUILayout.EndFadeGroup(); + + EditorGUI.BeginChangeCheck(); + EditorGUILayout.PropertyField(m_GroupProperty); + if (EditorGUI.EndChangeCheck()) + { + if (!Application.isPlaying) + EditorSceneManager.MarkSceneDirty(toggle.gameObject.scene); + + ToggleGroup group = m_GroupProperty.objectReferenceValue as ToggleGroup; + toggle.group = group; + } + + EditorGUILayout.Space(); + + // Draw the event notification options + EditorGUILayout.PropertyField(m_OnValueChangedProperty); + + serializedObject.ApplyModifiedProperties(); + } + } +} \ No newline at end of file diff --git a/Editor/OverrideUI/XericToggleEditor.cs.meta b/Editor/OverrideUI/XericToggleEditor.cs.meta new file mode 100644 index 0000000..aff2390 --- /dev/null +++ b/Editor/OverrideUI/XericToggleEditor.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 1e5373a0c37349fd81182d57ec1d3d0b +timeCreated: 1776232270 \ No newline at end of file diff --git a/Runtime/Core/Vessel/ObjectVessel.cs b/Runtime/Core/Vessel/ObjectVessel.cs index bc32db2..7c84964 100644 --- a/Runtime/Core/Vessel/ObjectVessel.cs +++ b/Runtime/Core/Vessel/ObjectVessel.cs @@ -1,5 +1,4 @@ using System; -using OfficeOpenXml.FormulaParsing.Excel.Operators; using UnityEngine; using Object = UnityEngine.Object; diff --git a/Runtime/DynamicActivitiesImpact/UIDynamicActiveImpact.cs b/Runtime/DynamicActivitiesImpact/UIDynamicActiveImpact.cs index 8c0e7b6..dde3a14 100644 --- a/Runtime/DynamicActivitiesImpact/UIDynamicActiveImpact.cs +++ b/Runtime/DynamicActivitiesImpact/UIDynamicActiveImpact.cs @@ -125,7 +125,7 @@ namespace XericUI.DynamicActivitiesImpact Gizmos.color = Color.yellow; MacroGizmosDraw.DrawPolygonLineByPointArray(vertex3); - MacroGizmosDraw.DrawGizmosRectLinkLine(vertex1, vertex2, Color.grey, Color.cyan, true); + MacroGizmosDraw.DrawGizmos2RectLinkCube(vertex1, vertex2, Color.grey, Color.cyan, true); } #endif diff --git a/Runtime/Helper/EditorOverrideUIHelper.cs b/Runtime/Helper/EditorOverrideUIHelper.cs new file mode 100644 index 0000000..fa8dc5d --- /dev/null +++ b/Runtime/Helper/EditorOverrideUIHelper.cs @@ -0,0 +1,88 @@ +using System; +using System.Linq; +using UnityEngine; +using UnityEngine.UI; +using Action = Unity.Plastic.Antlr3.Runtime.Misc.Action; +using Object = UnityEngine.Object; + +#if UNITY_EDITOR +using System.Collections.Generic; +using UnityEditor; +#endif + +namespace XericUI.Helper +{ + public static class EditorOverrideUIHelper + { + /// + /// 替换菜单组件上下文 + /// + /// + /// 在组件上使用如下的方法定义替换 + /// + /// [MenuItem("CONTEXT/XXX/ReplaceToXXX", true)] + /// private static bool ValidateReplaceWithCustomScrollRect(MenuCommand command) + /// => command.context is ScrollRect; + /// + /// [MenuItem("CONTEXT/XXX/ReplaceToXXX", false, 10)] + /// private static void ReplaceWithCustomScrollRect(MenuCommand command) + /// => command.ReplaceCommandContext<SourceXXX, TargetXXX>(); + /// + /// 不过实测unity的json序列化也无法处理引用,还是需要手动将引用类型传过来 + /// + /// +#if UNITY_EDITOR + public static TTarget ReplaceCommandContext(this MenuCommand command) + where TSource : Component + where TTarget : Component + { + TSource original = command.context as TSource; + if (original == null) return null; + GameObject go = original.gameObject; + + // 标记撤销 + Undo.SetCurrentGroupName($"替换{typeof(TSource).Name}为{typeof(TTarget).Name}"); + int undoGroup = Undo.GetCurrentGroup(); + Undo.RecordObject(go, "替换组件"); + + // 主要的替换流程,不过unity好像也只能处理非引用对象,废物Unity + string jsonData = EditorJsonUtility.ToJson(original); + Object.DestroyImmediate(original); + TTarget newComponent = go.AddComponent(); + EditorJsonUtility.FromJsonOverwrite(jsonData, newComponent); + + EditorUtility.SetDirty(go); + + // 结束撤销标记 + Undo.RegisterCreatedObjectUndo(newComponent, "替换组件"); + Undo.CollapseUndoOperations(undoGroup); + + Debug.Log("组件替换完成"); + return newComponent; + } +#else + private static void ReplaceCommandContext(this Object command) + => throw new Exception("不能在运行时使用XericUIActionVessel编辑器功能"); +#endif + + +#if UNITY_EDITOR + public static void ReplaceCommandContext( + this MenuCommand command, Func referenceExtractor, Action referenceApplier) + where TSource : Component + where TTarget : Component + { + TSource original = command.context as TSource; + var references = referenceExtractor(original); + + TTarget component = command.ReplaceCommandContext(); + + referenceApplier(component, references); + } +#else + private static void ReplaceCommandContext(this Object command, + Func referenceExtractor, Action referenceApplier) + => throw new Exception("不能在运行时使用XericUIActionVessel编辑器功能"); +#endif + } +} \ No newline at end of file diff --git a/Runtime/Helper/EditorOverrideUIHelper.cs.meta b/Runtime/Helper/EditorOverrideUIHelper.cs.meta new file mode 100644 index 0000000..b422786 --- /dev/null +++ b/Runtime/Helper/EditorOverrideUIHelper.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 37496e81b4a34a179470e8f3c21e2851 +timeCreated: 1776300621 \ No newline at end of file diff --git a/Runtime/OverrideLayout/XericScrollRect.cs b/Runtime/OverrideLayout/XericScrollRect.cs index 84409a7..5b699e6 100644 --- a/Runtime/OverrideLayout/XericScrollRect.cs +++ b/Runtime/OverrideLayout/XericScrollRect.cs @@ -4,8 +4,10 @@ using UnityEngine; using UnityEngine.Pool; using UnityEngine.UI; using XericLibrary.Runtime.MacroLibrary; +using XericUI.Helper; #if UNITY_EDITOR +using UnityEditor; using XericLibraryEditor.Debug; #endif #if ODIN_INSPECTOR @@ -14,7 +16,7 @@ using Sirenix.OdinInspector; namespace XericUI.OverrideLayout { - [AddComponentMenu("Xeric UI Vessel/UI/Xeric Scroll Rect", 50)] + [AddComponentMenu("Xeric UI Vessel/ScrollRect", 50)] [SelectionBase] [ExecuteAlways] [DisallowMultipleComponent] @@ -101,7 +103,8 @@ namespace XericUI.OverrideLayout vertex3[3] = new Vector3(rect.max.x + scale.x, rect.min.y - scale.y, vertex2[3].z); Gizmos.color = Color.yellow; - MacroGizmosDraw.DrawGizmosRectLinkLine(vertex1, vertex3, Color.grey, Color.cyan, true); + MacroGizmosDraw.DrawGizmos2RectLinkCube(vertex1, vertex3, Color.grey, Color.cyan, true); + } #endif @@ -208,6 +211,53 @@ namespace XericUI.OverrideLayout _lastActiveSet = nowActiveChildrenSet; } + + protected override void SetContentAnchoredPosition(Vector2 position) + { + base.SetContentAnchoredPosition(position); + Debug.Log("123"); + } + + #endregion + + #region 组件替换 +#if UNITY_EDITOR + [UnityEditor.MenuItem("CONTEXT/ScrollRect/Replace To XericScrollView", true)] + private static bool ValidateReplaceToXeric(UnityEditor.MenuCommand command) + => command.context is ScrollRect and not XericScrollRect; + + [UnityEditor.MenuItem("CONTEXT/ScrollRect/Replace To XericScrollView", false, 10)] + private static void ReplaceToXeric(UnityEditor.MenuCommand command) + => command.ReplaceCommandContext( + o => + (o.viewport, o.content, o.horizontalScrollbar, o.verticalScrollbar), + (t, d) => + { + t.viewport = d.Viewport; + t.content = d.Content; + t.horizontalScrollbar = d.HScrollbar; + t.verticalScrollbar = d.VScrollbar; + }); + + [UnityEditor.MenuItem("CONTEXT/ScrollRect/Replace To ScrollView", true)] + private static bool ValidateReplaceToUnity(UnityEditor.MenuCommand command) + => command.context is XericScrollRect; + + [UnityEditor.MenuItem("CONTEXT/ScrollRect/Replace To ScrollView", false, 10)] + private static void ReplaceToUnity(UnityEditor.MenuCommand command) + => command.ReplaceCommandContext( + o => + (o.viewport, o.content, o.horizontalScrollbar, o.verticalScrollbar), + (t, d) => + { + t.viewport = d.Viewport; + t.content = d.Content; + t.horizontalScrollbar = d.HScrollbar; + t.verticalScrollbar = d.VScrollbar; + }); +#endif #endregion } } \ No newline at end of file diff --git a/Runtime/OverrideUI/XericToggle.cs b/Runtime/OverrideUI/XericToggle.cs new file mode 100644 index 0000000..d165622 --- /dev/null +++ b/Runtime/OverrideUI/XericToggle.cs @@ -0,0 +1,209 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using TMPro; +using UnityEngine; +using UnityEngine.Serialization; +using UnityEngine.UI; +using XericUI.Helper; + +namespace XericUI +{ + + [AddComponentMenu("Xeric UI Vessel/Toggle", 31)] + [DisallowMultipleComponent] + public class XericToggle : Toggle + { +#if dUI_TextMeshPro + public TMP_Text m_text; + + public string TextContent + { + get => m_text?.text ?? string.Empty; + set { if(m_text) m_text.text = value; } + } + + public Color TextColor + { + get => m_text?.color ?? Color.black; + set { if(m_text) m_text.color = value; } + } +#else + public Text m_text; + + public string TextContent + { + get => m_text.text; + set => m_text.text = value; + } + + public Color TextColor + { + get => m_text.color; + set => m_text.color = value; + } +#endif + + public bool m_enableTextColorTransition = true; + public ColorBlock m_textTransitionColorMode = ColorBlock.defaultColorBlock; + public bool m_enableTextContextTransition = false; + public AnimationTriggers m_textTransitionContextMode = new AnimationTriggers() + { + normalTrigger = "toggle_normal", + highlightedTrigger = "toggle_highlight", + pressedTrigger = "toggle_pressed", + selectedTrigger = "toggle_selected", + disabledTrigger = "toggle_disabled", + }; + + public bool EnableTextColorTransition + { + get => m_enableTextColorTransition; + set => m_enableTextColorTransition = value; + } + + public ColorBlock TextTransitionColorMode + { + get => m_textTransitionColorMode; + set => m_textTransitionColorMode = value; + } + + protected override void DoStateTransition(SelectionState state, bool instant) + { + if (!gameObject.activeInHierarchy) + return; + + Color tintColor; + Sprite transitionSprite; + string triggerName; + Color textColor; + + switch (state) + { + case SelectionState.Normal: + tintColor = colors.normalColor; + textColor = m_textTransitionColorMode.normalColor; + transitionSprite = null; + triggerName = animationTriggers.normalTrigger; + break; + case SelectionState.Highlighted: + tintColor = colors.highlightedColor; + textColor = m_textTransitionColorMode.highlightedColor; + transitionSprite = spriteState.highlightedSprite; + triggerName = animationTriggers.highlightedTrigger; + break; + case SelectionState.Pressed: + tintColor = colors.pressedColor; + textColor = m_textTransitionColorMode.pressedColor; + transitionSprite = spriteState.pressedSprite; + triggerName = animationTriggers.pressedTrigger; + break; + case SelectionState.Selected: + tintColor = colors.selectedColor; + textColor = m_textTransitionColorMode.selectedColor; + transitionSprite = spriteState.selectedSprite; + triggerName = animationTriggers.selectedTrigger; + break; + case SelectionState.Disabled: + tintColor = colors.disabledColor; + textColor = m_textTransitionColorMode.disabledColor; + transitionSprite = spriteState.disabledSprite; + triggerName = animationTriggers.disabledTrigger; + break; + default: + tintColor = Color.black; + textColor = Color.black; + transitionSprite = null; + triggerName = string.Empty; + break; + } + + switch (transition) + { + case Transition.ColorTint: + StartColorTween(tintColor * colors.colorMultiplier, instant); + break; + case Transition.SpriteSwap: + DoSpriteSwap(transitionSprite); + break; + case Transition.Animation: + TriggerAnimation(triggerName); + break; + } + + if (m_enableTextColorTransition) + TextColor = isOn ? m_textTransitionColorMode.selectedColor : textColor; + } + + + void StartColorTween(Color targetColor, bool instant) + { + if (targetGraphic == null) + return; + + targetGraphic.CrossFadeColor(targetColor, instant ? 0f : colors.fadeDuration, true, true); + } + + void DoSpriteSwap(Sprite newSprite) + { + if (image == null) + return; + + image.overrideSprite = newSprite; + } + + void TriggerAnimation(string triggername) + { +#if PACKAGE_ANIMATION + if (transition != Transition.Animation || animator == null || !animator.isActiveAndEnabled || !animator.hasBoundPlayables || string.IsNullOrEmpty(triggername)) + return; + + animator.ResetTrigger(animationTriggers.normalTrigger); + animator.ResetTrigger(animationTriggers.highlightedTrigger); + animator.ResetTrigger(animationTriggers.pressedTrigger); + animator.ResetTrigger(animationTriggers.selectedTrigger); + animator.ResetTrigger(animationTriggers.disabledTrigger); + + animator.SetTrigger(triggername); +#endif + } + + #region ×é¼þÌ滻 +#if UNITY_EDITOR + [UnityEditor.MenuItem("CONTEXT/Toggle/Replace To XericToggle", true)] + private static bool ValidateReplaceToXeric(UnityEditor.MenuCommand command) + => command.context is Toggle and not XericToggle; + + [UnityEditor.MenuItem("CONTEXT/Toggle/Replace To XericToggle", false, 10)] + private static void ReplaceToXeric(UnityEditor.MenuCommand command) + => command.ReplaceCommandContext( + o => + (o.graphic, o.group, o.onValueChanged), + (t, d) => + { + t.graphic = d.graphic; + t.group = d.group; + t.onValueChanged = d.onValueChanged; + }); + + [UnityEditor.MenuItem("CONTEXT/Toggle/Replace To Toggle", true)] + private static bool ValidateReplaceToUnity(UnityEditor.MenuCommand command) + => command.context is XericToggle; + + [UnityEditor.MenuItem("CONTEXT/Toggle/Replace To Toggle", false, 10)] + private static void ReplaceToUnity(UnityEditor.MenuCommand command) + => command.ReplaceCommandContext( + o => + (o.graphic, o.group, o.onValueChanged), + (t, d) => + { + t.graphic = d.graphic; + t.group = d.group; + t.onValueChanged = d.onValueChanged; + }); +#endif + #endregion + } +} diff --git a/Runtime/OverrideUI/XericToggle.cs.meta b/Runtime/OverrideUI/XericToggle.cs.meta new file mode 100644 index 0000000..3abb266 --- /dev/null +++ b/Runtime/OverrideUI/XericToggle.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d97ffd764ce4bdb40b75652a0a7c9adb +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/OverrideUI/XericToggleGroup.cs b/Runtime/OverrideUI/XericToggleGroup.cs index 9205076..6cbe47c 100644 --- a/Runtime/OverrideUI/XericToggleGroup.cs +++ b/Runtime/OverrideUI/XericToggleGroup.cs @@ -1,13 +1,33 @@ using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; +using XericUI.Helper; namespace XericUI.OverrideUI { - [AddComponentMenu("Xeric UI Vessel/Toggle Group", 31)] + [AddComponentMenu("Xeric UI Vessel/ToggleGroup", 31)] [DisallowMultipleComponent] public class XericToggleGroup : ToggleGroup { - // public List<> + + #region 组件替换 +#if UNITY_EDITOR + [UnityEditor.MenuItem("CONTEXT/ToggleGroup/Replace To XericToggleGroup", true)] + private static bool ValidateReplaceToXeric(UnityEditor.MenuCommand command) + => command.context is ToggleGroup and not XericToggleGroup; + + [UnityEditor.MenuItem("CONTEXT/ToggleGroup/Replace To XericToggleGroup", false, 10)] + private static void ReplaceToXeric(UnityEditor.MenuCommand command) + => command.ReplaceCommandContext(); + + [UnityEditor.MenuItem("CONTEXT/ToggleGroup/Replace To ToggleGroup", true)] + private static bool ValidateReplaceToUnity(UnityEditor.MenuCommand command) + => command.context is XericToggleGroup; + + [UnityEditor.MenuItem("CONTEXT/ToggleGroup/Replace To ToggleGroup", false, 10)] + private static void ReplaceToUnity(UnityEditor.MenuCommand command) + => command.ReplaceCommandContext(); +#endif + #endregion } } \ No newline at end of file