This commit is contained in:
陈思海 2025-10-14 15:41:26 +08:00
parent d8fd91d32c
commit 761b7b1827
10 changed files with 236 additions and 43 deletions

View File

@ -16,6 +16,50 @@ namespace AlicizaX.UI.Extension.Editor
GUILayout.EndHorizontal();
}
public static void DrawProperty(SerializedProperty property, GUISkin skin, string content,
Action<object, object> changeCallBack)
{
GUILayout.BeginHorizontal(EditorStyles.helpBox);
EditorGUILayout.LabelField(new GUIContent(content), skin.FindStyle("Text"), GUILayout.Width(120));
// 保存变化前的值
object oldValue = SerializedPropertyUtility.GetPropertyValue(property);
EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(property, new GUIContent(""));
if (EditorGUI.EndChangeCheck())
{
// 获取变化后的值
object newValue = SerializedPropertyUtility.GetPropertyValue(property);
changeCallBack?.Invoke(oldValue, newValue);
}
GUILayout.EndHorizontal();
}
public static void DrawProperty<T>(SerializedProperty property, GUISkin skin, string content,
Action<T, T> changeCallBack, T defaultValue = default(T))
{
GUILayout.BeginHorizontal(EditorStyles.helpBox);
EditorGUILayout.LabelField(new GUIContent(content), skin.FindStyle("Text"), GUILayout.Width(120));
// 保存变化前的值
T oldValue = SerializedPropertyUtility.GetPropertyValue<T>(property, defaultValue);
EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(property, new GUIContent(""));
if (EditorGUI.EndChangeCheck())
{
// 获取变化后的值
T newValue = SerializedPropertyUtility.GetPropertyValue<T>(property, defaultValue);
changeCallBack?.Invoke(oldValue, newValue);
}
GUILayout.EndHorizontal();
}
public static void DrawProperty(SerializedProperty property, GUISkin skin, string content, string btnName, Action callback)
{
GUILayout.BeginHorizontal(EditorStyles.helpBox);

View File

@ -0,0 +1,102 @@
using System;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
public static class SerializedPropertyUtility
{
/// <summary>
/// 获取SerializedProperty的值返回object类型
/// </summary>
public static object GetPropertyValue(SerializedProperty property)
{
if (property == null) return null;
switch (property.propertyType)
{
case SerializedPropertyType.Integer:
return property.intValue;
case SerializedPropertyType.Boolean:
return property.boolValue;
case SerializedPropertyType.Float:
return property.floatValue;
case SerializedPropertyType.String:
return property.stringValue;
case SerializedPropertyType.Vector2:
return property.vector2Value;
case SerializedPropertyType.Vector3:
return property.vector3Value;
case SerializedPropertyType.Vector4:
return property.vector4Value;
case SerializedPropertyType.Quaternion:
return property.quaternionValue;
case SerializedPropertyType.Color:
return property.colorValue;
case SerializedPropertyType.ObjectReference:
return property.objectReferenceValue;
case SerializedPropertyType.Enum:
return property.enumValueIndex;
case SerializedPropertyType.Vector2Int:
return property.vector2IntValue;
case SerializedPropertyType.Vector3Int:
return property.vector3IntValue;
case SerializedPropertyType.Rect:
return property.rectValue;
case SerializedPropertyType.RectInt:
return property.rectIntValue;
case SerializedPropertyType.Bounds:
return property.boundsValue;
case SerializedPropertyType.BoundsInt:
return property.boundsIntValue;
case SerializedPropertyType.AnimationCurve:
return property.animationCurveValue;
case SerializedPropertyType.Generic:
default:
// 对于不支持的类型或复杂类型返回null或尝试其他处理
Debug.LogWarning($"Unsupported property type: {property.propertyType}");
return null;
}
}
/// <summary>
/// 获取SerializedProperty的值泛型版本
/// </summary>
public static T GetPropertyValue<T>(SerializedProperty property, T defaultValue = default(T))
{
try
{
object value = GetPropertyValue(property);
if (value == null) return defaultValue;
// 如果类型匹配,直接返回
if (value is T typedValue)
return typedValue;
// 尝试类型转换
return (T)Convert.ChangeType(value, typeof(T));
}
catch (Exception e)
{
Debug.LogWarning($"Failed to get property value as type {typeof(T).Name}: {e.Message}");
return defaultValue;
}
}
/// <summary>
/// 安全地获取属性值,返回是否成功
/// </summary>
public static bool TryGetPropertyValue<T>(SerializedProperty property, out T value, T defaultValue = default(T))
{
value = defaultValue;
try
{
value = GetPropertyValue<T>(property, defaultValue);
return true;
}
catch
{
return false;
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 7c7a9c6164c04b319c042aeee04ee262
timeCreated: 1760409703

View File

@ -27,8 +27,6 @@ internal class UXButtonEditor : Editor
private SerializedProperty m_TransitionData;
private SerializedProperty m_ChildTransitions;
private UXGroup group;
private int m_ButtonMode;
private SerializedProperty m_SelectionState;
private ReorderableList m_ChildTransitionList;
@ -57,9 +55,6 @@ internal class UXButtonEditor : Editor
m_ChildTransitions = serializedObject.FindProperty("m_ChildTransitions");
m_SelectionState = serializedObject.FindProperty("m_SelectionState");
group = (UXGroup)m_UXGroup.objectReferenceValue;
m_ButtonMode = m_Mode.enumValueIndex;
hoverAudioClip = serializedObject.FindProperty("hoverAudioClip");
clickAudioClip = serializedObject.FindProperty("clickAudioClip");
@ -187,7 +182,22 @@ internal class UXButtonEditor : Editor
private void DrawGraphicsTab()
{
EditorGUI.BeginDisabledGroup(EditorApplication.isPlaying);
EditorGUILayout.PropertyField(m_Mode);
var modeType = (ButtonModeType)EditorGUILayout.EnumPopup("Mode", (ButtonModeType)m_Mode.enumValueIndex);
if (modeType != (ButtonModeType)m_Mode.enumValueIndex)
{
if (modeType == ButtonModeType.Normal)
{
ResetEventProperty(m_OnValueChanged);
m_UXGroup.objectReferenceValue = null;
}
else
{
ResetEventProperty(m_OnClick);
}
m_Mode.enumValueIndex = (int)modeType;
}
EditorGUI.EndDisabledGroup();
var interactable = GUILayoutHelper.DrawToggle(m_Interactable.boolValue, customSkin, "Interactable");
@ -196,6 +206,7 @@ internal class UXButtonEditor : Editor
mTarget.Interactable = interactable;
m_SelectionState.enumValueIndex = interactable ? 0 : 4;
}
m_Interactable.boolValue = interactable;
GUILayout.Space(1);
@ -244,40 +255,21 @@ internal class UXButtonEditor : Editor
private void DrawBasicSettings()
{
if (m_Mode.enumValueIndex != m_ButtonMode)
{
if (m_ButtonMode == (int)ButtonModeType.Normal)
{
ResetEventProperty(m_OnValueChanged);
m_UXGroup.objectReferenceValue = null;
}
else
{
ResetEventProperty(m_OnClick);
}
m_ButtonMode = m_Mode.enumValueIndex;
}
if (m_Mode.enumValueIndex == (int)ButtonModeType.Toggle)
{
GUILayoutHelper.DrawProperty(m_UXGroup, customSkin, "UXGroup");
UXGroup newGroup = (UXGroup)m_UXGroup.objectReferenceValue;
if (newGroup != group)
GUILayoutHelper.DrawProperty<UXGroup>(m_UXGroup, customSkin, "UXGroup", (oldValue, newValue) =>
{
UXButton self = target as UXButton;
if (group != null)
if (oldValue != null)
{
group.UnregisterButton(self);
oldValue.UnregisterButton(self);
}
group = newGroup;
if (newGroup != null)
if (newValue != null)
{
newGroup.RegisterButton(self);
}
newValue.RegisterButton(self);
}
});
}
}

View File

@ -12,7 +12,7 @@ namespace AlicizaX.UI.RecyclerView
public GridLayoutManager()
{
this.unit = unit;
unit = cellCount;
}
public override Vector2 CalculateContentSize()

View File

@ -2,6 +2,7 @@ using System;
using System.Collections;
using System.Collections.Generic;
using AlicizaX.UI.Extension;
using AlicizaX.UI.Extension.Utility;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;
@ -138,7 +139,7 @@ public class UXButton : UIBehaviour, IButton,
public void OnPointerDown(PointerEventData eventData)
{
if (!CanProcess(eventData)) return;
if (!CanProcess()) return;
m_IsDown = true;
SetState(SelectionState.Pressed);
}
@ -160,7 +161,7 @@ public class UXButton : UIBehaviour, IButton,
public void OnPointerEnter(PointerEventData eventData)
{
if (!CanProcess(eventData)) return;
if (!CanProcess()) return;
m_HasExitedWhileDown = false;
if (m_IsDown) return;
@ -203,10 +204,9 @@ public class UXButton : UIBehaviour, IButton,
#region Logic
private bool CanProcess(PointerEventData eventData)
private bool CanProcess()
{
return m_Interactable &&
eventData.button == PointerEventData.InputButton.Left &&
!(m_Mode == ButtonModeType.Toggle && Selected);
}
@ -272,7 +272,19 @@ public class UXButton : UIBehaviour, IButton,
private void TweenColor(TransitionData data, Color color, bool instant)
{
data.targetGraphic.CrossFadeColor(color, instant ? 0f : data.colors.fadeDuration, true, true);
if (Application.isPlaying)
{
data.targetGraphic.CrossFadeColor(
color,
instant ? 0f : data.colors.fadeDuration,
true,
true
);
}
else
{
data.targetGraphic.canvasRenderer.SetColor(color);
}
}
private static void SwapSprite(TransitionData data, Sprite sprite)

View File

@ -11,7 +11,6 @@ public class UXGroup : UIBehaviour
[SerializeField] private List<UXButton> m_Buttons = new();
private UXButton _current;
private readonly HashSet<UXButton> _registered = new();
public UnityEvent<UXButton> onSelectedChanged = new();
@ -29,18 +28,18 @@ public class UXGroup : UIBehaviour
protected override void OnDestroy()
{
foreach (var btn in _registered)
foreach (var btn in m_Buttons)
if (btn)
btn.Selected = false;
_registered.Clear();
m_Buttons.Clear();
base.OnDestroy();
}
public void RegisterButton(UXButton button)
{
if (!button || !_registered.Add(button)) return;
if (!m_Buttons.Contains(button)) m_Buttons.Add(button);
if (!button) return;
if (m_Buttons.Contains(button)) return;
m_Buttons.Add(button);
if (button.Selected)
{
@ -54,7 +53,7 @@ public class UXGroup : UIBehaviour
public void UnregisterButton(UXButton button)
{
if (!button || !_registered.Remove(button)) return;
if (!button) return;
m_Buttons.Remove(button);
if (_current == button)
_current = null;

3
Runtime/Utility.meta Normal file
View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 2997e0ea45404b2bad0969025eb613a5
timeCreated: 1760407867

View File

@ -0,0 +1,35 @@
using System.Collections.Generic;
using UnityEngine;
namespace AlicizaX.UI.Extension.Utility
{
internal static class SetPropertyUtility
{
public static bool SetColor(ref Color currentValue, Color newValue)
{
if (currentValue.r == newValue.r && currentValue.g == newValue.g && currentValue.b == newValue.b && currentValue.a == newValue.a)
return false;
currentValue = newValue;
return true;
}
public static bool SetStruct<T>(ref T currentValue, T newValue) where T : struct
{
if (EqualityComparer<T>.Default.Equals(currentValue, newValue))
return false;
currentValue = newValue;
return true;
}
public static bool SetClass<T>(ref T currentValue, T newValue) where T : class
{
if ((currentValue == null && newValue == null) || (currentValue != null && currentValue.Equals(newValue)))
return false;
currentValue = newValue;
return true;
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: baab95df60ce49af96e3b0efcf82ed30
timeCreated: 1760407873