From e13f19881569b6bd9ccd7c0fd711dc3e2e76c71a Mon Sep 17 00:00:00 2001 From: sinaioutlander <49360850+sinaioutlander@users.noreply.github.com> Date: Sun, 6 Sep 2020 16:55:39 +1000 Subject: [PATCH] 1.5.8 * Fixed a bug where the Page Helper would not update the total page count after changing the limit per page * Cleaned up the "Find Instances" helper, it will now filter out all types in the `System`, `Mono`, `Il2CppSystem` and `Iced` namespaces. * Improved the Find Instances helper so that it will avoid exceptions and get more results. * Enums now display their value type name * Changed the Scroll View unstrip so that it is less hard-coded for different unity versions and more dynamic. --- src/CachedObjects/CacheObjectBase.cs | 12 ++-- src/CachedObjects/Struct/CacheEnum.cs | 2 +- src/CachedObjects/Struct/CachePrimitive.cs | 59 ++++++-------------- src/CppExplorer.cs | 2 +- src/Helpers/PageHelper.cs | 13 ++++- src/MainMenu/Pages/ScenePage.cs | 15 ++--- src/MainMenu/Pages/SearchPage.cs | 55 +++++++++++++++---- src/UnstripFixes/GUIUnstrip.cs | 64 +++++++++++++--------- 8 files changed, 127 insertions(+), 95 deletions(-) diff --git a/src/CachedObjects/CacheObjectBase.cs b/src/CachedObjects/CacheObjectBase.cs index 1cd88fba..3e63c57a 100644 --- a/src/CachedObjects/CacheObjectBase.cs +++ b/src/CachedObjects/CacheObjectBase.cs @@ -14,6 +14,7 @@ public abstract class CacheObjectBase { public object Value; public string ValueTypeName; + public Type ValueType; // Reflection Inspector only public MemberInfo MemInfo { get; set; } @@ -79,11 +80,7 @@ public static CacheObjectBase GetCacheObject(object obj, MemberInfo memberInfo, { Type type = null; - if (obj != null) - { - type = ReflectionHelpers.GetActualType(obj); - } - else if (memberInfo != null) + if (memberInfo != null) { if (memberInfo is FieldInfo fi) { @@ -98,6 +95,10 @@ public static CacheObjectBase GetCacheObject(object obj, MemberInfo memberInfo, type = mi.ReturnType; } } + else if (obj != null) + { + type = ReflectionHelpers.GetActualType(obj); + } if (type == null) { @@ -167,6 +168,7 @@ private static CacheObjectBase GetCacheObjectImpl(object obj, MemberInfo memberI } holder.Value = obj; + holder.ValueType = valueType; holder.ValueTypeName = valueType.FullName; if (memberInfo != null) diff --git a/src/CachedObjects/Struct/CacheEnum.cs b/src/CachedObjects/Struct/CacheEnum.cs index 9bcd5bae..50cf834d 100644 --- a/src/CachedObjects/Struct/CacheEnum.cs +++ b/src/CachedObjects/Struct/CacheEnum.cs @@ -51,7 +51,7 @@ public override void DrawValue(Rect window, float width) } } - GUILayout.Label(Value.ToString(), null);// + " (" + ValueType + ")", null); + GUILayout.Label(Value.ToString() + " (" + ValueType + ")", null); } public void SetEnum(ref object value, int change) diff --git a/src/CachedObjects/Struct/CachePrimitive.cs b/src/CachedObjects/Struct/CachePrimitive.cs index 374d9b50..61cefbe7 100644 --- a/src/CachedObjects/Struct/CachePrimitive.cs +++ b/src/CachedObjects/Struct/CachePrimitive.cs @@ -8,58 +8,34 @@ namespace Explorer { public class CachePrimitive : CacheObjectBase { - public enum Types - { - Bool, - Double, - Float, - Int, - String, - Char - } + private bool m_isBool; + private bool m_isString; private string m_valueToString; - public Types PrimitiveType; - public MethodInfo ParseMethod => m_parseMethod ?? (m_parseMethod = Value.GetType().GetMethod("Parse", new Type[] { typeof(string) })); private MethodInfo m_parseMethod; public override void Init() { - if (Value == null) + if (ValueType == null) { - // this must mean it is a string. No other primitive type should be nullable. - PrimitiveType = Types.String; - return; - } + ValueType = Value?.GetType(); - m_valueToString = Value.ToString(); - - var type = Value.GetType(); - if (type == typeof(bool)) - { - PrimitiveType = Types.Bool; - } - else if (type == typeof(double)) - { - PrimitiveType = Types.Double; - } - else if (type == typeof(float)) - { - PrimitiveType = Types.Float; - } - else if (type == typeof(char)) - { - PrimitiveType = Types.Char; + // has to be a string at this point + if (ValueType == null) + { + ValueType = typeof(string); + } } - else if (typeof(int).IsAssignableFrom(type)) + + if (ValueType == typeof(string)) { - PrimitiveType = Types.Int; + m_isString = true; } - else + else if (ValueType == typeof(bool)) { - PrimitiveType = Types.String; + m_isBool = true; } } @@ -72,7 +48,7 @@ public override void UpdateValue() public override void DrawValue(Rect window, float width) { - if (PrimitiveType == Types.Bool) + if (m_isBool) { var b = (bool)Value; var label = $"{b}"; @@ -92,7 +68,8 @@ public override void DrawValue(Rect window, float width) } else { - GUILayout.Label("" + PrimitiveType + "", new GUILayoutOption[] { GUILayout.Width(50) }); + // using ValueType.Name instead of ValueTypeName, because we only want the short name. + GUILayout.Label("" + ValueType.Name + "", new GUILayoutOption[] { GUILayout.Width(50) }); int dynSize = 25 + (m_valueToString.Length * 15); var maxwidth = window.width - 300f; @@ -127,7 +104,7 @@ public void SetValueFromInput(string valueString) return; } - if (PrimitiveType == Types.String) + if (m_isString) { Value = valueString; } diff --git a/src/CppExplorer.cs b/src/CppExplorer.cs index 969f7e2d..27d6fa9f 100644 --- a/src/CppExplorer.cs +++ b/src/CppExplorer.cs @@ -12,7 +12,7 @@ namespace Explorer public class CppExplorer : MelonMod { public const string GUID = "com.sinai.cppexplorer"; - public const string VERSION = "1.5.7"; + public const string VERSION = "1.5.8"; public const string AUTHOR = "Sinai"; public const string NAME = "CppExplorer" diff --git a/src/Helpers/PageHelper.cs b/src/Helpers/PageHelper.cs index d64d76c1..1f22de2d 100644 --- a/src/Helpers/PageHelper.cs +++ b/src/Helpers/PageHelper.cs @@ -16,7 +16,18 @@ public enum Turn public class PageHelper { public int PageOffset { get; set; } - public int ItemsPerPage { get; set; } = 20; + + public int ItemsPerPage + { + get => m_itemsPerPage; + set + { + m_itemsPerPage = value; + CalculateMaxOffset(); + } + } + private int m_itemsPerPage = 20; + public int ItemCount { get => m_count; diff --git a/src/MainMenu/Pages/ScenePage.cs b/src/MainMenu/Pages/ScenePage.cs index 48100daf..26d173e1 100644 --- a/src/MainMenu/Pages/ScenePage.cs +++ b/src/MainMenu/Pages/ScenePage.cs @@ -21,8 +21,6 @@ public class ScenePage : WindowPage private static bool m_getRootObjectsFailed; - // ----- Holders for GUI elements ----- // - private static string m_currentScene = ""; // gameobject list @@ -34,8 +32,6 @@ public class ScenePage : WindowPage private string m_searchInput = ""; private List m_searchResults = new List(); - // ------------ Init and Update ------------ // - public override void Init() { Instance = this; @@ -126,9 +122,7 @@ private void Update_Impl(bool manual = false) } else { - if (!manual && m_getRootObjectsFailed) return; - - if (!manual) + if (!m_getRootObjectsFailed) { try { @@ -139,12 +133,19 @@ private void Update_Impl(bool manual = false) } catch { + MelonLogger.Log("Exception getting root scene objects, falling back to backup method..."); + m_getRootObjectsFailed = true; allTransforms.AddRange(GetRootObjectsManual_Impl()); } } else { + if (!manual) + { + return; + } + allTransforms.AddRange(GetRootObjectsManual_Impl()); } } diff --git a/src/MainMenu/Pages/SearchPage.cs b/src/MainMenu/Pages/SearchPage.cs index 33aee4f4..d27655ee 100644 --- a/src/MainMenu/Pages/SearchPage.cs +++ b/src/MainMenu/Pages/SearchPage.cs @@ -137,14 +137,11 @@ public override void DrawWindow() if (m_searchResults.Count > 0) { - //int offset = m_pageOffset * this.m_limit; - //if (offset >= count) m_pageOffset = 0; int offset = Pages.CalculateOffsetIndex(); for (int i = offset; i < offset + Pages.ItemsPerPage && i < count; i++) { m_searchResults[i].Draw(MainMenu.MainRect, 0f); - //m_searchResults[i].DrawValue(MainMenu.MainRect); } } else @@ -377,33 +374,67 @@ public static bool FilterScene(object obj, SceneFilter filter) // ====== other ======== + private static bool FilterName(string name) + { + // Don't really want these instances. + return !name.StartsWith("Mono") + && !name.StartsWith("System") + && !name.StartsWith("Il2CppSystem") + && !name.StartsWith("Iced"); + } + // credit: ManlyMarco (RuntimeUnityEditor) public static IEnumerable GetInstanceClassScanner() { var query = AppDomain.CurrentDomain.GetAssemblies() - .Where(x => !x.FullName.StartsWith("Mono")) .SelectMany(GetTypesSafe) .Where(t => t.IsClass && !t.IsAbstract && !t.ContainsGenericParameters); + var flags = BindingFlags.Public | BindingFlags.Static; + var flatFlags = flags | BindingFlags.FlattenHierarchy; + foreach (var type in query) { object obj = null; try { - obj = type.GetProperty("Instance", BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy)?.GetValue(null, null); - } - catch - { - try + var pi = type.GetProperty("Instance", flags); + + if (pi == null) { - obj = type.GetField("Instance", BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy)?.GetValue(null); + pi = type.GetProperty("Instance", flatFlags); } - catch + + if (pi != null) { + obj = pi.GetValue(null); + } + else + { + var fi = type.GetField("Instance", flags); + + if (fi == null) + { + fi = type.GetField("Instance", flatFlags); + } + + if (fi != null) + { + obj = fi.GetValue(null); + } } } - if (obj != null && !obj.ToString().StartsWith("Mono")) + catch { } + + if (obj != null) { + var t = ReflectionHelpers.GetActualType(obj); + + if (!FilterName(t.FullName) || ReflectionHelpers.IsArray(t) || ReflectionHelpers.IsList(t)) + { + continue; + } + yield return obj; } } diff --git a/src/UnstripFixes/GUIUnstrip.cs b/src/UnstripFixes/GUIUnstrip.cs index 95f94ea7..6067a112 100644 --- a/src/UnstripFixes/GUIUnstrip.cs +++ b/src/UnstripFixes/GUIUnstrip.cs @@ -24,13 +24,23 @@ private static GenericStack ScrollStack { get { -#if Release_2019 - return GUI.scrollViewStates; -#else - return GUI.s_ScrollViewStates; -#endif + if (m_scrollViewStatesInfo == null) + { + try + { + m_scrollViewStatesInfo = typeof(GUI).GetProperty("scrollViewStates"); + if (m_scrollViewStatesInfo == null) throw new Exception(); + } + catch + { + m_scrollViewStatesInfo = typeof(GUI).GetProperty("s_scrollViewStates"); + } + } + + return (GenericStack)m_scrollViewStatesInfo?.GetValue(null, null); } } + private static PropertyInfo m_scrollViewStatesInfo; // ======= public methods ======= // @@ -49,24 +59,6 @@ public static Rect GetLastRect() return last; } - public static float HorizontalScrollbar(Rect position, float value, float size, float leftValue, float rightValue, GUIStyle style) - { - return Scroller_Impl(position, value, size, leftValue, rightValue, style, - GUI.skin.GetStyle(style.name + "thumb"), - GUI.skin.GetStyle(style.name + "leftbutton"), - GUI.skin.GetStyle(style.name + "rightbutton"), - true); - } - - public static float VerticalScrollbar(Rect position, float value, float size, float topValue, float bottomValue, GUIStyle style) - { - return Scroller_Impl(position, value, size, topValue, bottomValue, style, - GUI.skin.GetStyle(style.name + "thumb"), - GUI.skin.GetStyle(style.name + "upbutton"), - GUI.skin.GetStyle(style.name + "downbutton"), - false); - } - // Fix for BeginScrollView. public static Vector2 BeginScrollView(Vector2 scroll, params GUILayoutOption[] options) @@ -221,7 +213,7 @@ private static Vector2 BeginScrollView_Impl(Rect position, Vector2 scrollPositio } if (flag2 && horizontalScrollbar != GUIStyle.none) { - scrollPosition.x = HorizontalScrollbar( + scrollPosition.x = HorizBar_Impl( new Rect( position.x, position.yMax - horizontalScrollbar.fixedHeight, @@ -243,7 +235,7 @@ private static Vector2 BeginScrollView_Impl(Rect position, Vector2 scrollPositio } if (flag && verticalScrollbar != GUIStyle.none) { - scrollPosition.y = VerticalScrollbar( + scrollPosition.y = VertBar_Impl( new Rect( screenRect.xMax + (float)verticalScrollbar.margin.left, screenRect.y, @@ -279,6 +271,24 @@ private static Vector2 BeginScrollView_Impl(Rect position, Vector2 scrollPositio return scrollPosition; } + public static float HorizBar_Impl(Rect position, float value, float size, float leftValue, float rightValue, GUIStyle style) + { + return Scroller_Impl(position, value, size, leftValue, rightValue, style, + GUI.skin.GetStyle(style.name + "thumb"), + GUI.skin.GetStyle(style.name + "leftbutton"), + GUI.skin.GetStyle(style.name + "rightbutton"), + true); + } + + public static float VertBar_Impl(Rect position, float value, float size, float topValue, float bottomValue, GUIStyle style) + { + return Scroller_Impl(position, value, size, topValue, bottomValue, style, + GUI.skin.GetStyle(style.name + "thumb"), + GUI.skin.GetStyle(style.name + "upbutton"), + GUI.skin.GetStyle(style.name + "downbutton"), + false); + } + private static void EndScrollView_Impl(bool handleScrollWheel) { GUIUtility.CheckOnGUI(); @@ -337,7 +347,7 @@ private static float Scroller_Impl(Rect position, float value, float size, float rect2 = new Rect(position.x, position.yMax - rightButton.fixedHeight, position.width, rightButton.fixedHeight); } - value = Slider(position2, value, size, leftValue, rightValue, slider, thumb, horiz, controlID); + value = Slider_Impl(position2, value, size, leftValue, rightValue, slider, thumb, horiz, controlID); bool flag = Event.current.type == EventType.MouseUp; if (ScrollerRepeatButton_Impl(controlID, rect, leftButton)) @@ -363,7 +373,7 @@ private static float Scroller_Impl(Rect position, float value, float size, float return value; } - public static float Slider(Rect position, float value, float size, float start, float end, GUIStyle slider, GUIStyle thumb, bool horiz, int id) + public static float Slider_Impl(Rect position, float value, float size, float start, float end, GUIStyle slider, GUIStyle thumb, bool horiz, int id) { if (id == 0) {