249 lines
8.1 KiB
C#
249 lines
8.1 KiB
C#
|
|
using System;
|
|||
|
|
using System.Reflection;
|
|||
|
|
using UnityEngine;
|
|||
|
|
//因为GradientPicker窗口,在窗口打开时使用的是Gradient对象的Cache。
|
|||
|
|
//如果有Undo操作,导致MaterialProperty更新了,但Gradient却更新不到ColorPicer里。所以在这里进行强制更新。
|
|||
|
|
//后续需要强制更新Picker的时候,也可以用这里。
|
|||
|
|
//DeepSeek写的。谨慎用。
|
|||
|
|
public static class GradientReflectionHelper
|
|||
|
|
{
|
|||
|
|
#region GradientPicker 相关
|
|||
|
|
|
|||
|
|
private static Type _gradientPickerType;
|
|||
|
|
|
|||
|
|
// SetCurrentGradient 方法
|
|||
|
|
private static MethodInfo _setGradientMethod;
|
|||
|
|
private static Action<Gradient> _setGradientDelegate;
|
|||
|
|
|
|||
|
|
// RefreshGradientData 方法
|
|||
|
|
private static MethodInfo _refreshMethod;
|
|||
|
|
private static Action _refreshDelegate;
|
|||
|
|
|
|||
|
|
#endregion
|
|||
|
|
|
|||
|
|
#region GradientPreviewCache 相关
|
|||
|
|
|
|||
|
|
private static Type _gradientCacheType;
|
|||
|
|
private static MethodInfo _clearCacheMethod;
|
|||
|
|
private static Action _clearCacheDelegate;
|
|||
|
|
|
|||
|
|
#endregion
|
|||
|
|
|
|||
|
|
// 初始化状态
|
|||
|
|
private static bool _initialized;
|
|||
|
|
private static bool _isValid;
|
|||
|
|
private static readonly object _initLock = new object();
|
|||
|
|
|
|||
|
|
#region 公共API
|
|||
|
|
|
|||
|
|
[System.Diagnostics.Conditional("UNITY_EDITOR")]
|
|||
|
|
public static void SetCurrentGradient(Gradient gradient)
|
|||
|
|
{
|
|||
|
|
ExecuteAction(() =>
|
|||
|
|
{
|
|||
|
|
if (_setGradientDelegate != null)
|
|||
|
|
_setGradientDelegate(gradient);
|
|||
|
|
else if (_setGradientMethod != null)
|
|||
|
|
_setGradientMethod.Invoke(null, new object[] { gradient });
|
|||
|
|
}, "SetCurrentGradient");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
[System.Diagnostics.Conditional("UNITY_EDITOR")]
|
|||
|
|
public static void RefreshGradientData()
|
|||
|
|
{
|
|||
|
|
ExecuteAction(() =>
|
|||
|
|
{
|
|||
|
|
if (_refreshDelegate != null)
|
|||
|
|
_refreshDelegate();
|
|||
|
|
else if (_refreshMethod != null)
|
|||
|
|
_refreshMethod.Invoke(null, null);
|
|||
|
|
}, "RefreshGradientData");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
[System.Diagnostics.Conditional("UNITY_EDITOR")]
|
|||
|
|
public static void ClearGradientCache()
|
|||
|
|
{
|
|||
|
|
ExecuteAction(() =>
|
|||
|
|
{
|
|||
|
|
if (_clearCacheDelegate != null)
|
|||
|
|
_clearCacheDelegate();
|
|||
|
|
else if (_clearCacheMethod != null)
|
|||
|
|
_clearCacheMethod.Invoke(null, null);
|
|||
|
|
}, "ClearGradientCache");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#endregion
|
|||
|
|
|
|||
|
|
#region 核心实现
|
|||
|
|
|
|||
|
|
private static void ExecuteAction(Action action, string methodName)
|
|||
|
|
{
|
|||
|
|
if (!Application.isEditor) return;
|
|||
|
|
|
|||
|
|
EnsureInitialized();
|
|||
|
|
if (!_isValid) return;
|
|||
|
|
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
action?.Invoke();
|
|||
|
|
}
|
|||
|
|
catch (Exception ex)
|
|||
|
|
{
|
|||
|
|
Debug.LogError($"[GradientReflection] {methodName} failed: {ex.Message}");
|
|||
|
|
// 可选择性地禁用后续调用
|
|||
|
|
// _isValid = false;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private static void EnsureInitialized()
|
|||
|
|
{
|
|||
|
|
if (_initialized) return;
|
|||
|
|
|
|||
|
|
lock (_initLock)
|
|||
|
|
{
|
|||
|
|
if (_initialized) return;
|
|||
|
|
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
// 1. 初始化 GradientPicker 类型
|
|||
|
|
_gradientPickerType = Type.GetType("UnityEditor.GradientPicker, UnityEditor");
|
|||
|
|
if (_gradientPickerType != null)
|
|||
|
|
{
|
|||
|
|
// 初始化 SetCurrentGradient
|
|||
|
|
_setGradientMethod = GetStaticMethod(
|
|||
|
|
_gradientPickerType,
|
|||
|
|
"SetCurrentGradient",
|
|||
|
|
new[] { typeof(Gradient) }
|
|||
|
|
);
|
|||
|
|
if (_setGradientMethod != null)
|
|||
|
|
{
|
|||
|
|
_setGradientDelegate = CreateActionDelegate<Gradient>(_setGradientMethod);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 初始化 RefreshGradientData
|
|||
|
|
_refreshMethod = GetStaticMethod(
|
|||
|
|
_gradientPickerType,
|
|||
|
|
"RefreshGradientData",
|
|||
|
|
Type.EmptyTypes
|
|||
|
|
);
|
|||
|
|
if (_refreshMethod != null)
|
|||
|
|
{
|
|||
|
|
_refreshDelegate = CreateActionDelegate(_refreshMethod);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
Debug.LogWarning("[GradientReflection] GradientPicker type not found");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 2. 初始化 GradientPreviewCache
|
|||
|
|
_gradientCacheType = Type.GetType("UnityEditorInternal.GradientPreviewCache, UnityEditor");
|
|||
|
|
if (_gradientCacheType != null)
|
|||
|
|
{
|
|||
|
|
_clearCacheMethod = GetStaticMethod(
|
|||
|
|
_gradientCacheType,
|
|||
|
|
"ClearCache",
|
|||
|
|
Type.EmptyTypes
|
|||
|
|
);
|
|||
|
|
if (_clearCacheMethod != null)
|
|||
|
|
{
|
|||
|
|
_clearCacheDelegate = CreateActionDelegate(_clearCacheMethod);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
Debug.LogWarning("[GradientReflection] GradientPreviewCache type not found");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 3. 验证初始化状态
|
|||
|
|
_isValid = (_setGradientMethod != null || _refreshMethod != null) &&
|
|||
|
|
_clearCacheMethod != null;
|
|||
|
|
|
|||
|
|
if (!_isValid)
|
|||
|
|
{
|
|||
|
|
Debug.LogWarning($"[GradientReflection] Initialization incomplete. " +
|
|||
|
|
$"SetCurrentGradient: {(_setGradientMethod != null ? "OK" : "Missing")}, " +
|
|||
|
|
$"RefreshGradientData: {(_refreshMethod != null ? "OK" : "Missing")}, " +
|
|||
|
|
$"ClearCache: {(_clearCacheMethod != null ? "OK" : "Missing")}");
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
// Debug.Log("[GradientReflection] Initialized successfully");
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
catch (Exception e)
|
|||
|
|
{
|
|||
|
|
Debug.LogError($"[GradientReflection] Initialization failed: {e}");
|
|||
|
|
_isValid = false;
|
|||
|
|
}
|
|||
|
|
finally
|
|||
|
|
{
|
|||
|
|
_initialized = true;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private static MethodInfo GetStaticMethod(Type type, string methodName, Type[] parameterTypes)
|
|||
|
|
{
|
|||
|
|
if (type == null) return null;
|
|||
|
|
|
|||
|
|
return type.GetMethod(
|
|||
|
|
methodName,
|
|||
|
|
BindingFlags.Public | BindingFlags.Static,
|
|||
|
|
null,
|
|||
|
|
parameterTypes,
|
|||
|
|
null
|
|||
|
|
);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private static Action CreateActionDelegate(MethodInfo method)
|
|||
|
|
{
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
return (Action)Delegate.CreateDelegate(typeof(Action), method);
|
|||
|
|
}
|
|||
|
|
catch (Exception ex)
|
|||
|
|
{
|
|||
|
|
Debug.LogWarning($"[GradientReflection] Failed to create delegate for {method.Name}: {ex.Message}");
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private static Action<T> CreateActionDelegate<T>(MethodInfo method)
|
|||
|
|
{
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
return (Action<T>)Delegate.CreateDelegate(typeof(Action<T>), method);
|
|||
|
|
}
|
|||
|
|
catch (Exception ex)
|
|||
|
|
{
|
|||
|
|
Debug.LogWarning($"[GradientReflection] Failed to create delegate for {method.Name}: {ex.Message}");
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#endregion
|
|||
|
|
|
|||
|
|
#region 辅助功能
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 检查是否所有反射方法都可用
|
|||
|
|
/// </summary>
|
|||
|
|
public static bool IsFullySupported => _isValid;
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 获取反射初始化状态
|
|||
|
|
/// </summary>
|
|||
|
|
public static string GetReflectionStatus()
|
|||
|
|
{
|
|||
|
|
if (!_initialized) return "Not Initialized";
|
|||
|
|
|
|||
|
|
return $"GradientPicker: {(_gradientPickerType != null ? "Found" : "Missing")}\n" +
|
|||
|
|
$"- SetCurrentGradient: {(_setGradientMethod != null ? "OK" : "Missing")}\n" +
|
|||
|
|
$"- RefreshGradientData: {(_refreshMethod != null ? "OK" : "Missing")}\n" +
|
|||
|
|
$"GradientPreviewCache: {(_gradientCacheType != null ? "Found" : "Missing")}\n" +
|
|||
|
|
$"- ClearCache: {(_clearCacheMethod != null ? "OK" : "Missing")}";
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#endregion
|
|||
|
|
}
|