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 } }