From d7b0fff94919af8a3a4366065ec07ccc61ca58ca Mon Sep 17 00:00:00 2001 From: Sinai Date: Mon, 17 May 2021 21:48:39 +1000 Subject: [PATCH] IL2CPP List/Dict support, cleanups --- src/ExplorerCore.cs | 3 - src/UI/CacheObject/CacheObjectBase.cs | 4 +- src/UI/IValues/InteractiveDictionary.cs | 92 +++++++++---------- src/UI/IValues/InteractiveList.cs | 84 +++++++++-------- src/UI/Inspectors/GameObjectInspector.cs | 3 + .../GameObjectWidgets/ComponentList.cs | 5 + src/UI/Widgets/TransformTree/TransformTree.cs | 21 +++-- 7 files changed, 117 insertions(+), 95 deletions(-) diff --git a/src/ExplorerCore.cs b/src/ExplorerCore.cs index 17e3dbd..e82a073 100644 --- a/src/ExplorerCore.cs +++ b/src/ExplorerCore.cs @@ -80,9 +80,6 @@ namespace UnityExplorer UIManager.InitUI(); Log($"{NAME} {VERSION} initialized."); - - //InspectorManager.Inspect(typeof(TestClass)); - InspectorManager.Inspect(Camera.main.gameObject); } /// diff --git a/src/UI/CacheObject/CacheObjectBase.cs b/src/UI/CacheObject/CacheObjectBase.cs index bdc2da4..ad623ac 100644 --- a/src/UI/CacheObject/CacheObjectBase.cs +++ b/src/UI/CacheObject/CacheObjectBase.cs @@ -183,9 +183,9 @@ namespace UnityExplorer.UI.CacheObject return ValueState.Color; else if (InteractiveValueStruct.SupportsType(type)) return ValueState.ValueStruct; - else if (typeof(IDictionary).IsAssignableFrom(type)) //(ReflectionUtility.IsDictionary(type)) + else if (ReflectionUtility.IsDictionary(type)) return ValueState.Dictionary; - else if (!typeof(Transform).IsAssignableFrom(type) && typeof(IEnumerable).IsAssignableFrom(type)) //ReflectionUtility.IsEnumerable(type)) + else if (!typeof(Transform).IsAssignableFrom(type) && ReflectionUtility.IsEnumerable(type)) return ValueState.Collection; else return ValueState.Unsupported; diff --git a/src/UI/IValues/InteractiveDictionary.cs b/src/UI/IValues/InteractiveDictionary.cs index c55a1bf..f17c447 100644 --- a/src/UI/IValues/InteractiveDictionary.cs +++ b/src/UI/IValues/InteractiveDictionary.cs @@ -25,13 +25,13 @@ namespace UnityExplorer.UI.IValues public Type ValueType; public IDictionary RefIDictionary; - public int ItemCount => values.Count; - private readonly List keys = new List(); - private readonly List values = new List(); + public int ItemCount => cachedEntries.Count; private readonly List cachedEntries = new List(); public ScrollPool DictScrollPool { get; private set; } + private Text NotSupportedLabel; + public Text TopLabel; public LayoutElement KeyTitleLayout; @@ -54,8 +54,6 @@ namespace UnityExplorer.UI.IValues private void ClearAndRelease() { RefIDictionary = null; - keys.Clear(); - values.Clear(); foreach (var entry in cachedEntries) { @@ -71,8 +69,8 @@ namespace UnityExplorer.UI.IValues if (value == null) { // should never be null - if (keys.Any()) - ClearAndRelease(); + ClearAndRelease(); + return; } else { @@ -101,53 +99,48 @@ namespace UnityExplorer.UI.IValues { RefIDictionary = value as IDictionary; - if (RefIDictionary == null) + if (ReflectionUtility.TryGetDictEnumerator(value, out IEnumerator dictEnumerator)) { - // todo il2cpp - return; - } + NotSupportedLabel.gameObject.SetActive(false); - keys.Clear(); - foreach (var k in RefIDictionary.Keys) - keys.Add(k); - - values.Clear(); - foreach (var v in RefIDictionary.Values) - values.Add(v); - - int idx = 0; - for (int i = 0; i < keys.Count; i++) - { - CacheKeyValuePair cache; - if (idx >= cachedEntries.Count) + int idx = 0; + while (dictEnumerator.MoveNext()) { - cache = new CacheKeyValuePair(); - cache.SetDictOwner(this, i); - cachedEntries.Add(cache); + CacheKeyValuePair cache; + if (idx >= cachedEntries.Count) + { + cache = new CacheKeyValuePair(); + cache.SetDictOwner(this, idx); + cachedEntries.Add(cache); + } + else + cache = cachedEntries[idx]; + + cache.SetFallbackType(ValueType); + cache.SetKey(dictEnumerator.Current.Key); + cache.SetValueFromSource(dictEnumerator.Current.Value); + + idx++; } - else - cache = cachedEntries[i]; - cache.SetFallbackType(ValueType); - cache.SetKey(keys[i]); - cache.SetValueFromSource(values[i]); - - idx++; - } - - // Remove excess cached entries if dict count decreased - if (cachedEntries.Count > values.Count) - { - for (int i = cachedEntries.Count - 1; i >= values.Count; i--) + // Remove excess cached entries if dict count decreased + if (cachedEntries.Count > idx) { - var cache = cachedEntries[i]; - if (cache.CellView != null) - cache.UnlinkFromView(); + for (int i = cachedEntries.Count - 1; i >= idx; i--) + { + var cache = cachedEntries[i]; + if (cache.CellView != null) + cache.UnlinkFromView(); - cache.ReleasePooledObjects(); - cachedEntries.RemoveAt(i); + cache.ReleasePooledObjects(); + cachedEntries.RemoveAt(i); + } } } + else + { + NotSupportedLabel.gameObject.SetActive(true); + } } // Setting value to dictionary @@ -156,8 +149,6 @@ namespace UnityExplorer.UI.IValues { try { - //key = key.TryCast(KeyType); - if (!RefIDictionary.Contains(key)) { ExplorerCore.LogWarning("Unable to set key! Key may have been boxed to/from Il2Cpp Object."); @@ -255,6 +246,13 @@ namespace UnityExplorer.UI.IValues DictScrollPool.Initialize(this, SetLayout); scrollLayout = scrollObj.GetComponent(); + NotSupportedLabel = UIFactory.CreateLabel(DictScrollPool.Content.gameObject, "NotSupportedMessage", + "The IDictionary failed to enumerate. This is likely due to an issue with Unhollowed interfaces.", + TextAnchor.MiddleLeft, Color.red); + + UIFactory.SetLayoutElement(NotSupportedLabel.gameObject, minHeight: 25, flexibleWidth: 9999); + NotSupportedLabel.gameObject.SetActive(false); + return UIRoot; } } diff --git a/src/UI/IValues/InteractiveList.cs b/src/UI/IValues/InteractiveList.cs index 9ddb33d..c861653 100644 --- a/src/UI/IValues/InteractiveList.cs +++ b/src/UI/IValues/InteractiveList.cs @@ -22,7 +22,6 @@ namespace UnityExplorer.UI.IValues public override bool CanWrite => base.CanWrite && RefIList != null && !RefIList.IsReadOnly; public Type EntryType; - //public IEnumerable RefIEnumerable; public IList RefIList; public int ItemCount => values.Count; @@ -49,7 +48,6 @@ namespace UnityExplorer.UI.IValues private void ClearAndRelease() { - //RefIEnumerable = null; RefIList = null; values.Clear(); @@ -94,49 +92,52 @@ namespace UnityExplorer.UI.IValues { RefIList = value as IList; - IEnumerator enumerator = (value as IEnumerable).GetEnumerator(); - - //if (value is IEnumerable enumerable) - // enumerator = enumerable.GetEnumerator(); - //else - // enumerator = Il2CppReflection.EnumerateCppList(value); - values.Clear(); int idx = 0; - while (enumerator.MoveNext()) + + if (ReflectionUtility.TryGetEnumerator(value, out IEnumerator enumerator)) { - var entry = enumerator.Current; + NotSupportedLabel.gameObject.SetActive(false); - values.Add(entry); - - // If list count increased, create new cache entries - CacheListEntry cache; - if (idx >= cachedEntries.Count) + while (enumerator.MoveNext()) { - cache = new CacheListEntry(); - cache.SetListOwner(this, idx); - cachedEntries.Add(cache); - } - else - cache = cachedEntries[idx]; + var entry = enumerator.Current; - cache.SetFallbackType(this.EntryType); - cache.SetValueFromSource(entry); - idx++; + values.Add(entry); + + // If list count increased, create new cache entries + CacheListEntry cache; + if (idx >= cachedEntries.Count) + { + cache = new CacheListEntry(); + cache.SetListOwner(this, idx); + cachedEntries.Add(cache); + } + else + cache = cachedEntries[idx]; + + cache.SetFallbackType(this.EntryType); + cache.SetValueFromSource(entry); + idx++; + } + + // Remove excess cached entries if list count decreased + if (cachedEntries.Count > values.Count) + { + for (int i = cachedEntries.Count - 1; i >= values.Count; i--) + { + var cache = cachedEntries[i]; + if (cache.CellView != null) + cache.UnlinkFromView(); + + cache.ReleasePooledObjects(); + cachedEntries.RemoveAt(i); + } + } } - - // Remove excess cached entries if list count decreased - if (cachedEntries.Count > values.Count) + else { - for (int i = cachedEntries.Count - 1; i >= values.Count; i--) - { - var cache = cachedEntries[i]; - if (cache.CellView != null) - cache.UnlinkFromView(); - - cache.ReleasePooledObjects(); - cachedEntries.RemoveAt(i); - } + NotSupportedLabel.gameObject.SetActive(true); } } @@ -185,6 +186,8 @@ namespace UnityExplorer.UI.IValues private LayoutElement scrollLayout; + private Text NotSupportedLabel; + public override GameObject CreateContent(GameObject parent) { UIRoot = UIFactory.CreateVerticalGroup(parent, "InteractiveList", true, true, true, true, 6, new Vector4(10, 3, 15, 4), @@ -205,6 +208,13 @@ namespace UnityExplorer.UI.IValues ListScrollPool.Initialize(this, SetLayout); scrollLayout = scrollObj.GetComponent(); + NotSupportedLabel = UIFactory.CreateLabel(ListScrollPool.Content.gameObject, "NotSupportedMessage", + "The IEnumerable failed to enumerate. This is likely due to an issue with Unhollowed interfaces.", + TextAnchor.MiddleLeft, Color.red); + + UIFactory.SetLayoutElement(NotSupportedLabel.gameObject, minHeight: 25, flexibleWidth: 9999); + NotSupportedLabel.gameObject.SetActive(false); + return UIRoot; } } diff --git a/src/UI/Inspectors/GameObjectInspector.cs b/src/UI/Inspectors/GameObjectInspector.cs index e664dff..b9f836b 100644 --- a/src/UI/Inspectors/GameObjectInspector.cs +++ b/src/UI/Inspectors/GameObjectInspector.cs @@ -62,6 +62,9 @@ namespace UnityExplorer.UI.Inspectors addChildInput.Text = ""; addCompInput.Text = ""; + + TransformTree.Clear(); + ComponentList.Clear(); } public override void CloseInspector() diff --git a/src/UI/Inspectors/GameObjectWidgets/ComponentList.cs b/src/UI/Inspectors/GameObjectWidgets/ComponentList.cs index 606dbbd..5f4338e 100644 --- a/src/UI/Inspectors/GameObjectWidgets/ComponentList.cs +++ b/src/UI/Inspectors/GameObjectWidgets/ComponentList.cs @@ -19,6 +19,11 @@ namespace UnityExplorer.UI.Inspectors base.OnCellClicked = OnComponentClicked; } + public void Clear() + { + this.currentEntries.Clear(); + } + private bool CheckShouldDisplay(Component _, string __) => true; public override void OnCellBorrowed(ComponentCell cell) diff --git a/src/UI/Widgets/TransformTree/TransformTree.cs b/src/UI/Widgets/TransformTree/TransformTree.cs index d2c13af..e4f0ddd 100644 --- a/src/UI/Widgets/TransformTree/TransformTree.cs +++ b/src/UI/Widgets/TransformTree/TransformTree.cs @@ -50,6 +50,21 @@ namespace UnityExplorer.UI.Widgets } private string currentFilter; + + public void Init() + { + ScrollPool.Initialize(this); + } + + public void Clear() + { + this.displayedObjects.Clear(); + displayIndex = 0; + autoExpandedIDs.Clear(); + expandedInstanceIDs.Clear(); + } + + public void OnGameObjectClicked(GameObject obj) { if (OnClickOverrideHandler != null) @@ -68,12 +83,6 @@ namespace UnityExplorer.UI.Widgets GetRootEntriesMethod = getRootEntriesMethod; } - public void Init() - { - ScrollPool.Initialize(this); - } - - public bool IsCellExpanded(int instanceID) { return Filtering ? autoExpandedIDs.Contains(instanceID)