88 lines
3.4 KiB
C#
88 lines
3.4 KiB
C#
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
|
||
{
|
||
/// <summary>
|
||
/// 替换菜单组件上下文
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// 在组件上使用如下的方法定义替换
|
||
///
|
||
/// [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序列化也无法处理引用,还是需要手动将引用类型传过来
|
||
/// </remarks>
|
||
/// <param name="command"></param>
|
||
#if UNITY_EDITOR
|
||
public static TTarget ReplaceCommandContext<TSource, TTarget>(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<TTarget>();
|
||
EditorJsonUtility.FromJsonOverwrite(jsonData, newComponent);
|
||
|
||
EditorUtility.SetDirty(go);
|
||
|
||
// 结束撤销标记
|
||
Undo.RegisterCreatedObjectUndo(newComponent, "替换组件");
|
||
Undo.CollapseUndoOperations(undoGroup);
|
||
|
||
Debug.Log("组件替换完成");
|
||
return newComponent;
|
||
}
|
||
#else
|
||
private static void ReplaceCommandContext<T1, T2>(this Object command)
|
||
=> throw new Exception("不能在运行时使用XericUIActionVessel编辑器功能");
|
||
#endif
|
||
|
||
|
||
#if UNITY_EDITOR
|
||
public static void ReplaceCommandContext<TSource, TTarget, T>(
|
||
this MenuCommand command, Func<TSource, T> referenceExtractor, Action<TTarget, T> referenceApplier)
|
||
where TSource : Component
|
||
where TTarget : Component
|
||
{
|
||
TSource original = command.context as TSource;
|
||
var references = referenceExtractor(original);
|
||
|
||
TTarget component = command.ReplaceCommandContext<TSource, TTarget>();
|
||
|
||
referenceApplier(component, references);
|
||
}
|
||
#else
|
||
private static void ReplaceCommandContext<T1, T2, T3>(this Object command,
|
||
Func<T1, T3> referenceExtractor, Action<T2, T3> referenceApplier)
|
||
=> throw new Exception("不能在运行时使用XericUIActionVessel编辑器功能");
|
||
#endif
|
||
}
|
||
} |