From 8acc85061d1c57721611f66a24f70ac54dc3586f Mon Sep 17 00:00:00 2001 From: sinaioutlander <49360850+sinaioutlander@users.noreply.github.com> Date: Mon, 16 Nov 2020 00:50:06 +1100 Subject: [PATCH] InteractiveBool, Il2Cpp>Mono type dict cache, some UI fixes --- src/CSConsole/CodeEditor.cs | 4 +- src/Helpers/ReflectionHelpers.cs | 28 ++++-- src/Inspectors/GameObjects/ChildList.cs | 1 - .../GameObjects/GameObjectControls.cs | 38 ++++----- .../Reflection/CacheObject/CacheEnumerated.cs | 7 +- .../Reflection/CacheObject/CacheFactory.cs | 60 ------------- .../Reflection/CacheObject/CacheMember.cs | 17 ++++ .../Reflection/CacheObject/CacheObjectBase.cs | 2 + .../Reflection/CacheObject/CachePaired.cs | 11 +-- .../Reflection/CacheObject/CacheProperty.cs | 2 +- .../Reflection/CacheObject/INestedValue.cs | 12 --- .../InteractiveValue/InteractiveBool.cs | 82 ++++++++++++++++++ .../InteractiveValue/InteractiveDictionary.cs | 37 +------- .../InteractiveValue/InteractiveEnumerable.cs | 33 +------ .../InteractiveValue/InteractiveNumber.cs | 32 +++++++ .../InteractiveValue/InteractiveString.cs | 32 +++++++ .../InteractiveValue/InteractiveValue.cs | 55 +++++++----- .../Reflection/ReflectionInspector.cs | 12 ++- src/Inspectors/SceneExplorer.cs | 85 +++++++++++++------ src/UI/UIFactory.cs | 2 +- src/UnityExplorer.csproj | 5 +- 21 files changed, 323 insertions(+), 234 deletions(-) delete mode 100644 src/Inspectors/Reflection/CacheObject/CacheFactory.cs delete mode 100644 src/Inspectors/Reflection/CacheObject/INestedValue.cs create mode 100644 src/Inspectors/Reflection/InteractiveValue/InteractiveBool.cs create mode 100644 src/Inspectors/Reflection/InteractiveValue/InteractiveNumber.cs create mode 100644 src/Inspectors/Reflection/InteractiveValue/InteractiveString.cs diff --git a/src/CSConsole/CodeEditor.cs b/src/CSConsole/CodeEditor.cs index 7c7bdda..5f3c654 100644 --- a/src/CSConsole/CodeEditor.cs +++ b/src/CSConsole/CodeEditor.cs @@ -388,11 +388,11 @@ The following helper methods are available: autoIndentToggle.onValueChanged.AddListener(OnIndentChanged); void OnIndentChanged(bool val) => EnableAutoIndent = val; - autoIndentToggleText.text = "Auto-indent"; + autoIndentToggleText.text = "Auto-indent on Enter"; autoIndentToggleText.alignment = TextAnchor.UpperLeft; var autoIndentLayout = autoIndentToggleObj.AddComponent(); - autoIndentLayout.minWidth = 120; + autoIndentLayout.minWidth = 180; autoIndentLayout.flexibleWidth = 0; autoIndentLayout.minHeight = 25; diff --git a/src/Helpers/ReflectionHelpers.cs b/src/Helpers/ReflectionHelpers.cs index a2e9fb9..59229b1 100644 --- a/src/Helpers/ReflectionHelpers.cs +++ b/src/Helpers/ReflectionHelpers.cs @@ -8,7 +8,7 @@ using UnityEngine; using BF = System.Reflection.BindingFlags; using System.Diagnostics.CodeAnalysis; #if CPP -using ILType = Il2CppSystem.Type; +using CppType = Il2CppSystem.Type; using UnhollowerBaseLib; using UnhollowerRuntimeLib; using System.Runtime.InteropServices; @@ -61,16 +61,16 @@ namespace UnityExplorer.Helpers #if CPP if (obj is Il2CppSystem.Object ilObject) { - if (obj is ILType) - return typeof(ILType); + if (ilObject is CppType) + return typeof(CppType); - if (!string.IsNullOrEmpty(type.Namespace)) - { + if (!string.IsNullOrEmpty(type.Namespace)) + { // Il2CppSystem-namespace objects should just return GetType, // because using GetIl2CppType returns the System namespace type instead. if (type.Namespace.StartsWith("System.") || type.Namespace.StartsWith("Il2CppSystem.")) return ilObject.GetType(); - } + } var il2cppType = ilObject.GetIl2CppType(); @@ -79,8 +79,8 @@ namespace UnityExplorer.Helpers if (RuntimeSpecificsStore.IsInjected(classPtr)) return GetTypeByName(il2cppType.FullName); - var getType = Type.GetType(il2cppType.AssemblyQualifiedName); - + // this should be fine for all other il2cpp objects + var getType = GetMonoType(il2cppType); if (getType != null) return getType; } @@ -89,6 +89,18 @@ namespace UnityExplorer.Helpers } #if CPP + private static readonly Dictionary Il2CppToMonoType = new Dictionary(); + + public static Type GetMonoType(CppType cppType) + { + if (Il2CppToMonoType.ContainsKey(cppType)) + return Il2CppToMonoType[cppType]; + + var getType = Type.GetType(cppType.AssemblyQualifiedName); + Il2CppToMonoType.Add(cppType, getType); + return getType; + } + private static readonly Dictionary ClassPointers = new Dictionary(); public static object Il2CppCast(this object obj, Type castTo) diff --git a/src/Inspectors/GameObjects/ChildList.cs b/src/Inspectors/GameObjects/ChildList.cs index ab12669..1d0d23a 100644 --- a/src/Inspectors/GameObjects/ChildList.cs +++ b/src/Inspectors/GameObjects/ChildList.cs @@ -4,7 +4,6 @@ using System.Linq; using UnityExplorer.Helpers; using UnityExplorer.UI; using UnityExplorer.UI.Shared; -//using TMPro; using UnityEngine; using UnityEngine.UI; using UnityExplorer.Input; diff --git a/src/Inspectors/GameObjects/GameObjectControls.cs b/src/Inspectors/GameObjects/GameObjectControls.cs index 0b045db..de2ba4e 100644 --- a/src/Inspectors/GameObjects/GameObjectControls.cs +++ b/src/Inspectors/GameObjects/GameObjectControls.cs @@ -496,25 +496,6 @@ namespace UnityExplorer.Inspectors.GameObjects valueLabelLayout.flexibleWidth = 0; valueLabelLayout.minHeight = 25; - // Slider - - var sliderObj = UIFactory.CreateSlider(rowObject); - sliderObj.transform.Find("Fill Area").gameObject.SetActive(false); - var sliderLayout = sliderObj.AddComponent(); - sliderLayout.minHeight = 20; - sliderLayout.flexibleHeight = 0; - sliderLayout.minWidth = 200; - sliderLayout.flexibleWidth = 9000; - var slider = sliderObj.GetComponent(); - var sliderColors = slider.colors; - sliderColors.normalColor = new Color(0.65f, 0.65f, 0.65f); - slider.colors = sliderColors; - slider.minValue = -2; - slider.maxValue = 2; - slider.value = 0; - slider.onValueChanged.AddListener((float val) => { OnSliderControlChanged(val, slider, type, vectorValue); }); - editor.sliders[(int)vectorValue] = slider; - // input field var inputHolder = UIFactory.CreateVerticalGroup(rowObject, new Color(1, 1, 1, 0)); @@ -549,6 +530,25 @@ namespace UnityExplorer.Inspectors.GameObjects applyBtn.onClick.AddListener(() => { OnVectorControlInputApplied(type, vectorValue); }); + // Slider + + var sliderObj = UIFactory.CreateSlider(rowObject); + sliderObj.transform.Find("Fill Area").gameObject.SetActive(false); + var sliderLayout = sliderObj.AddComponent(); + sliderLayout.minHeight = 20; + sliderLayout.flexibleHeight = 0; + sliderLayout.minWidth = 200; + sliderLayout.flexibleWidth = 9000; + var slider = sliderObj.GetComponent(); + var sliderColors = slider.colors; + sliderColors.normalColor = new Color(0.65f, 0.65f, 0.65f); + slider.colors = sliderColors; + slider.minValue = -2; + slider.maxValue = 2; + slider.value = 0; + slider.onValueChanged.AddListener((float val) => { OnSliderControlChanged(val, slider, type, vectorValue); }); + editor.sliders[(int)vectorValue] = slider; + return rowObject; } diff --git a/src/Inspectors/Reflection/CacheObject/CacheEnumerated.cs b/src/Inspectors/Reflection/CacheObject/CacheEnumerated.cs index d53daf1..94224dc 100644 --- a/src/Inspectors/Reflection/CacheObject/CacheEnumerated.cs +++ b/src/Inspectors/Reflection/CacheObject/CacheEnumerated.cs @@ -9,7 +9,7 @@ using UnityEngine.UI; namespace UnityExplorer.Inspectors.Reflection { - public class CacheEnumerated : CacheObjectBase, INestedValue + public class CacheEnumerated : CacheObjectBase { public override Type FallbackType => ParentEnumeration.m_baseEntryType; public override bool CanWrite => RefIList != null && ParentEnumeration.OwnerCacheObject.CanWrite; @@ -40,11 +40,6 @@ namespace UnityExplorer.Inspectors.Reflection ParentEnumeration.OwnerCacheObject.SetValue(); } - public void UpdateSubcontentHeight() - { - ParentEnumeration.UpdateSubcontentHeight(); - } - internal override void ConstructUI() { base.ConstructUI(); diff --git a/src/Inspectors/Reflection/CacheObject/CacheFactory.cs b/src/Inspectors/Reflection/CacheObject/CacheFactory.cs deleted file mode 100644 index ce5114f..0000000 --- a/src/Inspectors/Reflection/CacheObject/CacheFactory.cs +++ /dev/null @@ -1,60 +0,0 @@ -using System; -using System.Reflection; -using UnityEngine; -using UnityExplorer.Helpers; - -namespace UnityExplorer.Inspectors.Reflection -{ - public static class CacheFactory - { - public static CacheMember GetCacheObject(MemberInfo member, object declaringInstance, GameObject parentUIContent) - { - CacheMember ret; - - if (member is MethodInfo mi && CanProcessArgs(mi.GetParameters())) - { - ret = new CacheMethod(mi, declaringInstance); - } - else if (member is PropertyInfo pi && CanProcessArgs(pi.GetIndexParameters())) - { - ret = new CacheProperty(pi, declaringInstance); - } - else if (member is FieldInfo fi) - { - ret = new CacheField(fi, declaringInstance); - } - else - { - return null; - } - - ret.m_parentContent = parentUIContent; - - return ret; - } - - public static bool CanProcessArgs(ParameterInfo[] parameters) - { - foreach (var param in parameters) - { - var pType = param.ParameterType; - - if (pType.IsByRef && pType.HasElementType) - { - pType = pType.GetElementType(); - } - - if (pType != null && (pType.IsPrimitive || pType == typeof(string))) - { - continue; - } - else - { - return false; - } - } - - return true; - } - } -} diff --git a/src/Inspectors/Reflection/CacheObject/CacheMember.cs b/src/Inspectors/Reflection/CacheObject/CacheMember.cs index 6018a1c..999db90 100644 --- a/src/Inspectors/Reflection/CacheObject/CacheMember.cs +++ b/src/Inspectors/Reflection/CacheObject/CacheMember.cs @@ -50,6 +50,23 @@ namespace UnityExplorer.Inspectors.Reflection DeclaringInstance = declaringInstance; } + public static bool CanProcessArgs(ParameterInfo[] parameters) + { + foreach (var param in parameters) + { + var pType = param.ParameterType; + + if (pType.IsByRef && pType.HasElementType) + pType = pType.GetElementType(); + + if (pType != null && (pType.IsPrimitive || pType == typeof(string))) + continue; + else + return false; + } + return true; + } + public override void CreateIValue(object value, Type fallbackType) { IValue = InteractiveValue.Create(value, fallbackType); diff --git a/src/Inspectors/Reflection/CacheObject/CacheObjectBase.cs b/src/Inspectors/Reflection/CacheObject/CacheObjectBase.cs index c8a840b..ba7deb3 100644 --- a/src/Inspectors/Reflection/CacheObject/CacheObjectBase.cs +++ b/src/Inspectors/Reflection/CacheObject/CacheObjectBase.cs @@ -63,6 +63,8 @@ namespace UnityExplorer.Inspectors.Reflection } IValue.OnValueUpdated(); + + IValue.RefreshElementsAfterUpdate(); } public virtual void SetValue() => throw new NotImplementedException(); diff --git a/src/Inspectors/Reflection/CacheObject/CachePaired.cs b/src/Inspectors/Reflection/CacheObject/CachePaired.cs index e89af72..2706eee 100644 --- a/src/Inspectors/Reflection/CacheObject/CachePaired.cs +++ b/src/Inspectors/Reflection/CacheObject/CachePaired.cs @@ -16,7 +16,7 @@ namespace UnityExplorer.Inspectors.Reflection Value } - public class CachePaired : CacheObjectBase, INestedValue + public class CachePaired : CacheObjectBase { public override Type FallbackType => PairType == PairTypes.Key ? ParentDictionary.m_typeOfKeys @@ -27,13 +27,13 @@ namespace UnityExplorer.Inspectors.Reflection public PairTypes PairType; public int Index { get; private set; } public InteractiveDictionary ParentDictionary { get; private set; } - internal IDictionary RefIDIct; + internal IDictionary RefIDict; public CachePaired(int index, InteractiveDictionary parentDict, IDictionary refIDict, PairTypes pairType, GameObject parentContent) { Index = index; ParentDictionary = parentDict; - RefIDIct = refIDict; + RefIDict = refIDict; this.PairType = pairType; this.m_parentContent = parentContent; } @@ -44,11 +44,6 @@ namespace UnityExplorer.Inspectors.Reflection IValue.OwnerCacheObject = this; } - public void UpdateSubcontentHeight() - { - ParentDictionary.UpdateSubcontentHeight(); - } - #region UI CONSTRUCTION internal override void ConstructUI() diff --git a/src/Inspectors/Reflection/CacheObject/CacheProperty.cs b/src/Inspectors/Reflection/CacheObject/CacheProperty.cs index 2ea6c9d..2a7991e 100644 --- a/src/Inspectors/Reflection/CacheObject/CacheProperty.cs +++ b/src/Inspectors/Reflection/CacheObject/CacheProperty.cs @@ -43,7 +43,7 @@ namespace UnityExplorer.Inspectors.Reflection } else { - // todo write-only properties + // todo write-only properties? } } diff --git a/src/Inspectors/Reflection/CacheObject/INestedValue.cs b/src/Inspectors/Reflection/CacheObject/INestedValue.cs deleted file mode 100644 index 176217c..0000000 --- a/src/Inspectors/Reflection/CacheObject/INestedValue.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace UnityExplorer.Inspectors.Reflection -{ - public interface INestedValue - { - void UpdateSubcontentHeight(); - } -} diff --git a/src/Inspectors/Reflection/InteractiveValue/InteractiveBool.cs b/src/Inspectors/Reflection/InteractiveValue/InteractiveBool.cs new file mode 100644 index 0000000..a1843ed --- /dev/null +++ b/src/Inspectors/Reflection/InteractiveValue/InteractiveBool.cs @@ -0,0 +1,82 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using UnityEngine; +using UnityEngine.UI; +using UnityExplorer.Helpers; +using UnityExplorer.UI; + +namespace UnityExplorer.Inspectors.Reflection +{ + public class InteractiveBool : InteractiveValue + { + public InteractiveBool(object value, Type valueType) : base(value, valueType) + { + } + + public override IValueTypes IValueType => IValueTypes.Bool; + public override bool HasSubContent => false; + public override bool SubContentWanted => false; + public override bool WantInspectBtn => false; + + internal Toggle m_toggle; + + public override void OnValueUpdated() + { + base.OnValueUpdated(); + + if (!Value.IsNullOrDestroyed()) + { + if (OwnerCacheObject.CanWrite) + { + if (!m_toggle.gameObject.activeSelf) + m_toggle.gameObject.SetActive(true); + + var val = (bool)Value; + if (m_toggle.isOn != val) + m_toggle.isOn = val; + } + + RefreshUIElements(); + } + } + + internal void RefreshUIElements() + { + if (m_baseLabel) + { + var val = (bool)Value; + var color = val + ? "00FF00" // on + : "FF0000"; // off + + m_baseLabel.text = $"{val} ({m_richValueType})"; + } + } + + internal void OnToggleValueChanged(bool val) + { + Value = val; + OwnerCacheObject.SetValue(); + RefreshUIElements(); + } + + public override void ConstructUI(GameObject parent, GameObject subGroup) + { + base.ConstructUI(parent, subGroup); + + if (OwnerCacheObject.CanWrite) + { + var toggleObj = UIFactory.CreateToggle(m_valueContent, out m_toggle, out _, new Color(0.1f, 0.1f, 0.1f)); + toggleObj.SetActive(false); + var toggleLayout = toggleObj.AddComponent(); + toggleLayout.minWidth = 24; + + m_toggle.onValueChanged.AddListener(OnToggleValueChanged); + + m_baseLabel.transform.SetAsLastSibling(); + } + } + } +} diff --git a/src/Inspectors/Reflection/InteractiveValue/InteractiveDictionary.cs b/src/Inspectors/Reflection/InteractiveValue/InteractiveDictionary.cs index c211a85..7df7bc9 100644 --- a/src/Inspectors/Reflection/InteractiveValue/InteractiveDictionary.cs +++ b/src/Inspectors/Reflection/InteractiveValue/InteractiveDictionary.cs @@ -31,6 +31,7 @@ namespace UnityExplorer.Inspectors.Reflection public override IValueTypes IValueType => IValueTypes.Dictionary; public override bool HasSubContent => true; + public override bool SubContentWanted => (RefIDictionary?.Count ?? 1) > 0; public override bool WantInspectBtn => false; internal IDictionary RefIDictionary; @@ -44,8 +45,6 @@ namespace UnityExplorer.Inspectors.Reflection internal readonly KeyValuePair[] m_displayedEntries = new KeyValuePair[ModConfig.Instance.Default_Page_Limit]; - //internal readonly List m_entries = new List(); - //internal CacheKeyValuePair[] m_displayedEntries = new CacheKeyValuePair[ModConfig.Instance.Default_Page_Limit]; internal bool m_recacheWanted = true; public override void OnDestroy() @@ -176,7 +175,7 @@ namespace UnityExplorer.Inspectors.Reflection entry.Value.Enable(); } - UpdateSubcontentHeight(); + //UpdateSubcontentHeight(); } internal override void OnToggleSubcontent(bool active) @@ -193,38 +192,6 @@ namespace UnityExplorer.Inspectors.Reflection RefreshDisplay(); } - public void UpdateSubcontentHeight() - { - Canvas.ForceUpdateCanvases(); - - float totalHeight = 0f; - if (m_subContentParent.activeSelf) - { - foreach (var itemIndex in m_pageHandler) - { - if (itemIndex >= m_entries.Count) - break; - - var entry = m_entries[itemIndex]; - LayoutRebuilder.ForceRebuildLayoutImmediate(entry.Key.m_mainRect); - LayoutRebuilder.ForceRebuildLayoutImmediate(entry.Value.m_mainRect); - - totalHeight += Mathf.Max(entry.Key.m_mainRect.rect.height, entry.Value.m_mainRect.rect.height); - } - } - - m_listLayout.minHeight = Mathf.Min(350f, totalHeight); - //m_mainLayout.minHeight = totalHeight; - - LayoutRebuilder.ForceRebuildLayoutImmediate(OwnerCacheObject.m_mainRect); - - if (OwnerCacheObject is INestedValue nestedValue) - { - // nested enumerable - nestedValue.UpdateSubcontentHeight(); - } - } - #region UI CONSTRUCTION internal GameObject m_listContent; diff --git a/src/Inspectors/Reflection/InteractiveValue/InteractiveEnumerable.cs b/src/Inspectors/Reflection/InteractiveValue/InteractiveEnumerable.cs index e00f43c..6be31fb 100644 --- a/src/Inspectors/Reflection/InteractiveValue/InteractiveEnumerable.cs +++ b/src/Inspectors/Reflection/InteractiveValue/InteractiveEnumerable.cs @@ -25,6 +25,7 @@ namespace UnityExplorer.Inspectors.Reflection public override IValueTypes IValueType => IValueTypes.Enumerable; public override bool HasSubContent => true; + public override bool SubContentWanted => (RefIList?.Count ?? 1) > 0; public override bool WantInspectBtn => false; internal IEnumerable RefIEnumerable; @@ -137,7 +138,7 @@ namespace UnityExplorer.Inspectors.Reflection entry.Enable(); } - UpdateSubcontentHeight(); + //UpdateSubcontentHeight(); } internal override void OnToggleSubcontent(bool active) @@ -154,36 +155,6 @@ namespace UnityExplorer.Inspectors.Reflection RefreshDisplay(); } - public void UpdateSubcontentHeight() - { - Canvas.ForceUpdateCanvases(); - - float totalHeight = 0f; - if (m_subContentParent.activeSelf) - { - foreach (var itemIndex in m_pageHandler) - { - if (itemIndex >= m_entries.Count) - break; - - var entry = m_entries[itemIndex]; - LayoutRebuilder.ForceRebuildLayoutImmediate(entry.m_mainRect); - totalHeight += entry.m_mainRect.rect.height; - } - } - - m_listLayout.minHeight = Mathf.Min(350f, totalHeight); - //m_mainLayout.minHeight = totalHeight; - - LayoutRebuilder.ForceRebuildLayoutImmediate(OwnerCacheObject.m_mainRect); - - if (OwnerCacheObject is INestedValue nestedValue) - { - // nested enumerable - nestedValue.UpdateSubcontentHeight(); - } - } - #region UI CONSTRUCTION internal GameObject m_listContent; diff --git a/src/Inspectors/Reflection/InteractiveValue/InteractiveNumber.cs b/src/Inspectors/Reflection/InteractiveValue/InteractiveNumber.cs new file mode 100644 index 0000000..370abb4 --- /dev/null +++ b/src/Inspectors/Reflection/InteractiveValue/InteractiveNumber.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using UnityEngine; + +namespace UnityExplorer.Inspectors.Reflection +{ + public class InteractiveNumber : InteractiveValue + { + public InteractiveNumber(object value, Type valueType) : base(value, valueType) + { + } + + public override IValueTypes IValueType => IValueTypes.Number; + public override bool HasSubContent => false; + public override bool SubContentWanted => false; + public override bool WantInspectBtn => false; + + public override void ConstructUI(GameObject parent, GameObject subGroup) + { + base.ConstructUI(parent, subGroup); + + + } + + public override void OnValueUpdated() + { + base.OnValueUpdated(); + } + } +} diff --git a/src/Inspectors/Reflection/InteractiveValue/InteractiveString.cs b/src/Inspectors/Reflection/InteractiveValue/InteractiveString.cs new file mode 100644 index 0000000..c74dccf --- /dev/null +++ b/src/Inspectors/Reflection/InteractiveValue/InteractiveString.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using UnityEngine; + +namespace UnityExplorer.Inspectors.Reflection +{ + public class InteractiveString : InteractiveValue + { + public InteractiveString(object value, Type valueType) : base(value, valueType) + { + } + + public override IValueTypes IValueType => IValueTypes.String; + public override bool HasSubContent => false; + public override bool SubContentWanted => false; + public override bool WantInspectBtn => false; + + public override void ConstructUI(GameObject parent, GameObject subGroup) + { + base.ConstructUI(parent, subGroup); + + + } + + public override void OnValueUpdated() + { + base.OnValueUpdated(); + } + } +} diff --git a/src/Inspectors/Reflection/InteractiveValue/InteractiveValue.cs b/src/Inspectors/Reflection/InteractiveValue/InteractiveValue.cs index c353861..79bec99 100644 --- a/src/Inspectors/Reflection/InteractiveValue/InteractiveValue.cs +++ b/src/Inspectors/Reflection/InteractiveValue/InteractiveValue.cs @@ -16,6 +16,13 @@ namespace UnityExplorer.Inspectors.Reflection Any, Enumerable, Dictionary, + Bool, + String, + Number, + Enum, + Flags, + UnityStruct, + Color, // maybe } public class InteractiveValue @@ -28,15 +35,22 @@ namespace UnityExplorer.Inspectors.Reflection { IValueTypes.Any, typeof(InteractiveValue) }, { IValueTypes.Dictionary, typeof(InteractiveDictionary) }, { IValueTypes.Enumerable, typeof(InteractiveEnumerable) }, + { IValueTypes.Bool, typeof(InteractiveBool) }, + { IValueTypes.String, typeof(InteractiveString) }, + { IValueTypes.Number, typeof(InteractiveNumber) }, }; // WIP public static IValueTypes GetIValueForType(Type type) { - if (type.IsPrimitive || type == typeof(string)) - return IValueTypes.Any; // TODO Primitive + if (type == typeof(bool)) + return IValueTypes.Bool; + else if (type == typeof(string)) + return IValueTypes.String; + else if (type.IsPrimitive) + return IValueTypes.Number; else if (typeof(Transform).IsAssignableFrom(type)) - return IValueTypes.Any; // TODO Transform + return IValueTypes.Any; else if (ReflectionHelpers.IsDictionary(type)) return IValueTypes.Dictionary; else if (ReflectionHelpers.IsEnumerable(type)) @@ -69,6 +83,7 @@ namespace UnityExplorer.Inspectors.Reflection public virtual IValueTypes IValueType => IValueTypes.Any; public virtual bool HasSubContent => false; + public virtual bool SubContentWanted => false; public virtual bool WantInspectBtn => true; public string RichTextValue => m_richValue ?? GetLabelForValue(); @@ -87,16 +102,6 @@ namespace UnityExplorer.Inspectors.Reflection m_valueContent.transform.SetParent(null, false); m_valueContent.SetActive(false); GameObject.Destroy(this.m_valueContent.gameObject); - - //if (OwnerCacheObject.m_subContent) - //{ - // var subTrans = this.OwnerCacheObject.m_subContent.transform; - // for (int i = subTrans.childCount - 1; i >= 0; i--) - // { - // var child = subTrans.GetChild(i); - // GameObject.Destroy(child.gameObject); - // } - //} } } @@ -115,18 +120,28 @@ namespace UnityExplorer.Inspectors.Reflection GetLabelForValue(); m_baseLabel.text = RichTextValue; } + } - bool shouldShowBtns = !Value.IsNullOrDestroyed(); + public void RefreshElementsAfterUpdate() + { + if (WantInspectBtn) + { + bool shouldShowInspect = !Value.IsNullOrDestroyed(); - if (WantInspectBtn && m_inspectButton.activeSelf != shouldShowBtns) - m_inspectButton.SetActive(shouldShowBtns); + if (m_inspectButton.activeSelf != shouldShowInspect) + m_inspectButton.SetActive(shouldShowInspect); + } + + bool subContentWanted = SubContentWanted; + if (OwnerCacheObject is CacheMember cm && !cm.HasEvaluated) + subContentWanted = false; if (HasSubContent) { - if (m_subExpandBtn.gameObject.activeSelf != shouldShowBtns) - m_subExpandBtn.gameObject.SetActive(shouldShowBtns); + if (m_subExpandBtn.gameObject.activeSelf != subContentWanted) + m_subExpandBtn.gameObject.SetActive(subContentWanted); - if (!shouldShowBtns && m_subContentParent.activeSelf) + if (!subContentWanted && m_subContentParent.activeSelf) ToggleSubcontent(); } } @@ -151,6 +166,8 @@ namespace UnityExplorer.Inspectors.Reflection } OnToggleSubcontent(m_subContentParent.activeSelf); + + RefreshElementsAfterUpdate(); } internal virtual void OnToggleSubcontent(bool toggle) diff --git a/src/Inspectors/Reflection/ReflectionInspector.cs b/src/Inspectors/Reflection/ReflectionInspector.cs index fe5034e..73fae3f 100644 --- a/src/Inspectors/Reflection/ReflectionInspector.cs +++ b/src/Inspectors/Reflection/ReflectionInspector.cs @@ -347,7 +347,17 @@ namespace UnityExplorer.Inspectors try { - var cached = CacheFactory.GetCacheObject(member, target, m_scrollContent); + CacheMember cached; + if (mi != null && CacheMember.CanProcessArgs(mi.GetParameters())) + cached = new CacheMethod(mi, target); + else if (pi != null && CacheMember.CanProcessArgs(pi.GetIndexParameters())) + cached = new CacheProperty(pi, target); + else if (member is FieldInfo fi) + cached = new CacheField(fi, target); + else + continue; + + cached.m_parentContent = m_scrollContent; if (cached != null) { diff --git a/src/Inspectors/SceneExplorer.cs b/src/Inspectors/SceneExplorer.cs index 0e43081..e440357 100644 --- a/src/Inspectors/SceneExplorer.cs +++ b/src/Inspectors/SceneExplorer.cs @@ -39,11 +39,12 @@ namespace UnityExplorer.Inspectors private GameObject m_mainInspectBtn; private GameObject m_backButtonObj; - public PageHandler m_sceneListPageHandler; - private GameObject m_sceneListContent; - private GameObject[] m_allSceneListObjects = new GameObject[0]; - private readonly List m_sceneShortList = new List(); - private readonly List m_sceneListTexts = new List(); + public PageHandler m_pageHandler; + private GameObject m_pageContent; + private GameObject[] m_allObjects = new GameObject[0]; + private readonly List m_shortList = new List(); + private readonly List m_shortListTexts = new List(); + private readonly List m_shortListToggles = new List(); public static int DontDestroyHandle => DontDestroyObject.scene.handle; @@ -200,18 +201,22 @@ namespace UnityExplorer.Inspectors private void SetSceneObjectList(GameObject[] objects) { - m_allSceneListObjects = objects; + m_allObjects = objects; RefreshSceneObjectList(); } private void SceneListObjectClicked(int index) { - if (index >= m_sceneShortList.Count || !m_sceneShortList[index]) + if (index >= m_shortList.Count || !m_shortList[index]) { return; } - SetTargetObject(m_sceneShortList[index]); + var obj = m_shortList[index]; + if (obj.transform.childCount > 0) + SetTargetObject(obj); + else + InspectorManager.Instance.Inspect(obj); } private void OnSceneListPageTurn() @@ -219,30 +224,39 @@ namespace UnityExplorer.Inspectors RefreshSceneObjectList(); } + private void OnToggleClicked(int index, bool val) + { + if (index >= m_shortList.Count || !m_shortList[index]) + return; + + var obj = m_shortList[index]; + obj.SetActive(val); + } + private void RefreshSceneObjectList() { m_timeOfLastSceneUpdate = Time.realtimeSinceStartup; - var objects = m_allSceneListObjects; - m_sceneListPageHandler.ListCount = objects.Length; + var objects = m_allObjects; + m_pageHandler.ListCount = objects.Length; //int startIndex = m_sceneListPageHandler.StartIndex; int newCount = 0; - foreach (var itemIndex in m_sceneListPageHandler) + foreach (var itemIndex in m_pageHandler) { newCount++; // normalized index starting from 0 - var i = itemIndex - m_sceneListPageHandler.StartIndex; + var i = itemIndex - m_pageHandler.StartIndex; if (itemIndex >= objects.Length) { - if (i > m_lastCount || i >= m_sceneListTexts.Count) + if (i > m_lastCount || i >= m_shortListTexts.Count) break; - GameObject label = m_sceneListTexts[i].transform.parent.parent.gameObject; + GameObject label = m_shortListTexts[i].transform.parent.parent.gameObject; if (label.activeSelf) label.SetActive(false); } @@ -253,17 +267,17 @@ namespace UnityExplorer.Inspectors if (!obj) continue; - if (i >= m_sceneShortList.Count) + if (i >= m_shortList.Count) { - m_sceneShortList.Add(obj); + m_shortList.Add(obj); AddObjectListButton(); } else { - m_sceneShortList[i] = obj; + m_shortList[i] = obj; } - var text = m_sceneListTexts[i]; + var text = m_shortListTexts[i]; var name = obj.name; @@ -273,6 +287,9 @@ namespace UnityExplorer.Inspectors text.text = name; text.color = obj.activeSelf ? Color.green : Color.red; + var tog = m_shortListToggles[i]; + tog.isOn = obj.activeSelf; + var label = text.transform.parent.parent.gameObject; if (!label.activeSelf) { @@ -397,14 +414,17 @@ namespace UnityExplorer.Inspectors inspectButtonLayout.minWidth = 65; inspectButtonLayout.flexibleWidth = 0; Button inspectButton = m_mainInspectBtn.GetComponent