From f049177e20a276049c61edbad631c1b2bbdd5706 Mon Sep 17 00:00:00 2001 From: chai Date: Thu, 15 Oct 2020 19:05:22 +0800 Subject: -advanced inspector +odin --- .../Editor/FixBrokenUnityObjectWrapperDrawer.cs | 208 +++++++++++++++++++++ 1 file changed, 208 insertions(+) create mode 100644 Assets/Plugins/Sirenix/Odin Inspector/Scripts/Editor/FixBrokenUnityObjectWrapperDrawer.cs (limited to 'Assets/Plugins/Sirenix/Odin Inspector/Scripts/Editor/FixBrokenUnityObjectWrapperDrawer.cs') diff --git a/Assets/Plugins/Sirenix/Odin Inspector/Scripts/Editor/FixBrokenUnityObjectWrapperDrawer.cs b/Assets/Plugins/Sirenix/Odin Inspector/Scripts/Editor/FixBrokenUnityObjectWrapperDrawer.cs new file mode 100644 index 00000000..1f30e4e2 --- /dev/null +++ b/Assets/Plugins/Sirenix/Odin Inspector/Scripts/Editor/FixBrokenUnityObjectWrapperDrawer.cs @@ -0,0 +1,208 @@ +//----------------------------------------------------------------------- +// +// Copyright (c) Sirenix IVS. All rights reserved. +// +//----------------------------------------------------------------------- + +#if UNITY_EDITOR && UNITY_2018_3_OR_NEWER +#pragma warning disable + +namespace Sirenix.OdinInspector.Editor.Drawers +{ + using Sirenix.OdinInspector; + using Sirenix.OdinInspector.Editor; + using Sirenix.Utilities; + using Sirenix.Utilities.Editor; + using System.Linq; + using UnityEditor; + using UnityEngine; + + [DrawerPriority(0.001, 0, 0)] + public class FixBrokenUnityObjectWrapperDrawer : OdinValueDrawer, IDefinesGenericMenuItems + where T : UnityEngine.Component + { + private const string AUTO_FIX_PREFS_KEY = "TemporarilyBrokenUnityObjectWrapperDrawer.autoFix"; + + private bool isBroken = false; + private T realWrapperInstance; + private bool allowSceneViewObjects; + private static bool autoFix; + + protected override void Initialize() + { + this.allowSceneViewObjects = this.ValueEntry.Property.GetAttribute() == null; + autoFix = EditorPrefs.HasKey(AUTO_FIX_PREFS_KEY); + } + + protected override void DrawPropertyLayout(GUIContent label) + { + if (!(this.ValueEntry.ValueState == PropertyValueState.NullReference || this.ValueEntry.ValueState == PropertyValueState.ReferenceValueConflict)) + { + this.CallNextDrawer(label); + return; + } + + if (Event.current.type == EventType.Layout) + { + this.isBroken = false; + var count = this.ValueEntry.ValueCount; + for (int i = 0; i < count; i++) + { + var component = this.ValueEntry.Values[i]; + + if (ComponentIsBroken(component, ref this.realWrapperInstance)) + { + this.isBroken = true; + break; + } + } + + if (this.isBroken && autoFix) + { + this.isBroken = false; + + for (int i = 0; i < this.ValueEntry.ValueCount; i++) + { + T fixedComponent = null; + if (ComponentIsBroken(this.ValueEntry.Values[i], ref fixedComponent) && fixedComponent) + { + (this.ValueEntry as IValueEntryActualValueSetter).SetActualValue(i, fixedComponent); + } + } + + this.ValueEntry.Update(); + } + } + + if (!this.isBroken) + { + this.CallNextDrawer(label); + return; + } + + var rect = EditorGUILayout.GetControlRect(label != null); + var btnRect = rect.AlignRight(20); + var controlRect = rect.SetXMax(btnRect.xMin - 5); + + object newInstance = null; + + EditorGUI.BeginChangeCheck(); + { + if (this.ValueEntry.BaseValueType.IsInterface) + { + newInstance = SirenixEditorFields.PolymorphicObjectField(controlRect, + label, + this.realWrapperInstance, + this.ValueEntry.BaseValueType, + this.allowSceneViewObjects); + } + else + { + newInstance = SirenixEditorFields.UnityObjectField( + controlRect, + label, + this.realWrapperInstance, + this.ValueEntry.BaseValueType, + this.allowSceneViewObjects) as Component; + } + } + if (EditorGUI.EndChangeCheck()) + { + this.ValueEntry.WeakSmartValue = newInstance; + } + + if (GUI.Button(btnRect, " ", EditorStyles.miniButton)) + { + var popup = new FixBrokenUnityObjectWrapperPopup(this.ValueEntry); + OdinEditorWindow.InspectObjectInDropDown(popup, 300); + } + + if (Event.current.type == EventType.Repaint) + { + GUI.DrawTexture(btnRect, EditorIcons.ConsoleWarnicon, ScaleMode.ScaleToFit); + } + } + + private static bool ComponentIsBroken(T component, ref T realInstance) + { + var uObj = component; + var oObj = (object)uObj; + + if (oObj != null && uObj == null) + { + var instanceId = uObj.GetInstanceID(); + if (AssetDatabase.Contains(instanceId)) + { + var path = AssetDatabase.GetAssetPath(instanceId); + var realWrapper = AssetDatabase.LoadAllAssetsAtPath(path).FirstOrDefault(n => n.GetInstanceID() == instanceId) as T; + if (realWrapper) + { + realInstance = realWrapper; + return true; + } + } + } + + return false; + } + + public void PopulateGenericMenu(InspectorProperty property, GenericMenu genericMenu) + { + if (EditorPrefs.HasKey(AUTO_FIX_PREFS_KEY)) + { + genericMenu.AddItem(new GUIContent("Disable auto-fix of broken prefab instance references"), false, (x) => + { + EditorPrefs.DeleteKey(AUTO_FIX_PREFS_KEY); + autoFix = false; + }, null); + } + } + + [TypeInfoBox("This asset reference is temporarily broken until the next reload, because of an error in Unity where the C# wrapper object of a prefab asset is destroyed when changes are made to that prefab asset. This error has been reported to Unity.\n\nMeanwhile, Odin can fix this for you by getting a new, valid wrapper object from the asset database and replacing the broken wrapper instance with the new one.")] + private class FixBrokenUnityObjectWrapperPopup + { + private IPropertyValueEntry valueEntry; + + public FixBrokenUnityObjectWrapperPopup(IPropertyValueEntry valueEntry) + { + this.valueEntry = valueEntry; + } + + [HorizontalGroup, Button(ButtonSizes.Large)] + public void FixItThisTime() + { + for (int i = 0; i < this.valueEntry.ValueCount; i++) + { + var localI = i; + T fixedComponent = null; + if (ComponentIsBroken(this.valueEntry.Values[i], ref fixedComponent) && fixedComponent) + { + this.valueEntry.Property.Tree.DelayActionUntilRepaint(() => + { + (this.valueEntry as IValueEntryActualValueSetter).SetActualValue(localI, fixedComponent); + }); + } + } + + if (GUIHelper.CurrentWindow) + { + EditorApplication.delayCall += GUIHelper.CurrentWindow.Close; + } + } + + [HorizontalGroup, Button(ButtonSizes.Large)] + public void FixItAlways() + { + EditorPrefs.SetBool(AUTO_FIX_PREFS_KEY, true); + autoFix = true; + + if (GUIHelper.CurrentWindow) + { + EditorApplication.delayCall += GUIHelper.CurrentWindow.Close; + } + } + } + } +} + +#endif \ No newline at end of file -- cgit v1.1-26-g67d0