Compare commits

...

6 Commits
1.6.6 ... 1.6.8

Author SHA1 Message Date
e23341c2b1 Update README.md 2020-09-10 20:36:24 +10:00
080bde4a63 Update README.md 2020-09-10 20:35:41 +10:00
1d739a1936 1.6.8
* Added a ModConfig, allowing you to define the main menu toggle keybind and the default window size (so far).
* Made the parsing of arguments more intelligent, should now behave as expected for null or empty arguments.
2020-09-10 20:31:09 +10:00
a927b5ed21 1.6.7
* Parameters (in Methods or Properties) with default values will now show these default values in the Inspector, and if you don't provide any input then this default value will be used as the argument.
* Removed an unnecessary update of cached members when you open a Reflection Inspector, should be a bit faster now.
* When entering arguments, the name of the argument is now white instead of cyan to avoid confusion with the Type name.
* A few clean ups
2020-09-10 18:02:41 +10:00
642c97812c fix img 2020-09-09 19:20:52 +10:00
e43d3579de Update img.png 2020-09-09 19:18:39 +10:00
18 changed files with 276 additions and 178 deletions

View File

@ -32,8 +32,24 @@ Requires [MelonLoader](https://github.com/HerpDerpinstine/MelonLoader) to be ins
* Press F7 to show or hide the menu. * Press F7 to show or hide the menu.
* Simply browse through the scene, search for objects, etc, most of it is pretty self-explanatory. * Simply browse through the scene, search for objects, etc, most of it is pretty self-explanatory.
### Mod Config
There is a simple Mod Config for the CppExplorer, which is generated the first time you run it.
This config is generated to `Mods\CppExplorer\config.xml`. Edit the config while the game is closed if you wish to change it.
`Main_Menu_Toggle` (KeyCode)
* Sets the keybinding for the Main Menu toggle (show/hide all CppExplorer windows)
* See [this article](https://docs.unity3d.com/ScriptReference/KeyCode.html) for a full list of all accepted KeyCodes.
* Default: `F7`
`Default_Window_Size` (Vector2)
* Sets the default width and height for all CppExplorer windows when created.
* `x` is width, `y` is height.
* Default: `<x>550</x> <y>700</y>`
### Features ### Features
[![](img.png)](img.png) [![](overview.png)](overview.png)
<i>An overview of the different CppExplorer menus.</i> <i>An overview of the different CppExplorer menus.</i>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 524 KiB

After

Width:  |  Height:  |  Size: 523 KiB

View File

@ -44,12 +44,9 @@ namespace Explorer
} }
} }
// ===== Abstract/Virtual Methods ===== //
public virtual void Init() { } public virtual void Init() { }
public abstract void DrawValue(Rect window, float width);
// ===== Static Methods ===== // public abstract void DrawValue(Rect window, float width);
/// <summary> /// <summary>
/// Get CacheObject from only an object instance /// Get CacheObject from only an object instance
@ -205,11 +202,8 @@ namespace Explorer
} }
holder.m_argumentInput = new string[holder.m_arguments.Length]; holder.m_argumentInput = new string[holder.m_arguments.Length];
if (!holder.HasParameters) holder.UpdateValue();
{
holder.UpdateValue();
}
holder.Init(); holder.Init();
@ -229,7 +223,18 @@ namespace Explorer
return true; return true;
} }
// ======== Instance Methods ========= public float CalcWhitespace(Rect window)
{
if (!(this is IExpandHeight)) return 0f;
float whitespace = (this as IExpandHeight).WhiteSpace;
if (whitespace > 0)
{
ClampLabelWidth(window, ref whitespace);
}
return whitespace;
}
public object[] ParseArguments() public object[] ParseArguments()
{ {
@ -239,26 +244,41 @@ namespace Explorer
var input = m_argumentInput[i]; var input = m_argumentInput[i];
var type = m_arguments[i].ParameterType; var type = m_arguments[i].ParameterType;
if (type == typeof(string)) // First, try parse the input and use that.
if (!string.IsNullOrEmpty(input))
{ {
parsedArgs.Add(input); // strings can obviously just be used directly
} if (type == typeof(string))
else
{
try
{ {
parsedArgs.Add(type.GetMethod("Parse", new Type[] { typeof(string) }).Invoke(null, new object[] { input })); parsedArgs.Add(input);
continue;
} }
catch else
{ {
//MelonLogger.Log($"Unable to parse '{input}' to type '{type.Name}'"); // try to invoke the parse method and use that.
try
{
parsedArgs.Add(type.GetMethod("Parse", new Type[] { typeof(string) })
.Invoke(null, new object[] { input }));
// try add a null arg i guess continue;
parsedArgs.Add(null); }
catch
//break; {
MelonLogger.Log($"Argument #{i} '{m_arguments[i].Name}' ({type.Name}), could not parse input '{input}'.");
}
} }
} }
// Didn't use input, see if there is a default value.
if (m_arguments[i].HasDefaultValue)
{
parsedArgs.Add(m_arguments[i].DefaultValue);
continue;
}
// Try add a null arg I guess
parsedArgs.Add(null);
} }
return parsedArgs.ToArray(); return parsedArgs.ToArray();
@ -271,6 +291,12 @@ namespace Explorer
return; return;
} }
if (HasParameters && !m_isEvaluating)
{
// Need to enter parameters first
return;
}
try try
{ {
if (MemInfo.MemberType == MemberTypes.Field) if (MemInfo.MemberType == MemberTypes.Field)
@ -332,7 +358,7 @@ namespace Explorer
} }
} }
// ========= Instance Gui Draw ========== // ========= Gui Draw ==========
public const float MAX_LABEL_WIDTH = 400f; public const float MAX_LABEL_WIDTH = 400f;
public const string EVALUATE_LABEL = "<color=lime>Evaluate</color>"; public const string EVALUATE_LABEL = "<color=lime>Evaluate</color>";
@ -375,10 +401,18 @@ namespace Explorer
var input = m_argumentInput[i]; var input = m_argumentInput[i];
var type = m_arguments[i].ParameterType.Name; var type = m_arguments[i].ParameterType.Name;
var label = "<color=#2df7b2>" + type + "</color> <color=#a6e9e9>" + name + "</color>";
if (m_arguments[i].HasDefaultValue)
{
label = $"<i>[{label} = {m_arguments[i].DefaultValue}]</i>";
}
GUILayout.BeginHorizontal(null); GUILayout.BeginHorizontal(null);
GUILayout.Label(i.ToString(), new GUILayoutOption[] { GUILayout.Width(30) });
GUILayout.Label(i.ToString(), new GUILayoutOption[] { GUILayout.Width(20) });
m_argumentInput[i] = GUILayout.TextField(input, new GUILayoutOption[] { GUILayout.Width(150) }); m_argumentInput[i] = GUILayout.TextField(input, new GUILayoutOption[] { GUILayout.Width(150) });
GUILayout.Label("<color=#2df7b2>" + type + "</color> <color=cyan>" + name + "</color>", null); GUILayout.Label(label, null);
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
} }
@ -438,7 +472,11 @@ namespace Explorer
{ {
GUILayout.Label("<color=red>Reflection failed!</color> (" + ReflectionException + ")", null); GUILayout.Label("<color=red>Reflection failed!</color> (" + ReflectionException + ")", null);
} }
else if (Value == null && MemInfo?.MemberType != MemberTypes.Method) else if ((HasParameters || this is CacheMethod) && !m_evaluated)
{
GUILayout.Label($"<color=grey><i>Not yet evaluated</i></color> (<color=#2df7b2>{ValueTypeName}</color>)", null);
}
else if (Value == null && !(this is CacheMethod))
{ {
GUILayout.Label("<i>null (" + ValueTypeName + ")</i>", null); GUILayout.Label("<i>null (" + ValueTypeName + ")</i>", null);
} }
@ -463,7 +501,7 @@ namespace Explorer
m_richTextName = $"<color=#2df7b2>{MemInfo.DeclaringType.Name}</color>.<color={memberColor}>{MemInfo.Name}</color>"; m_richTextName = $"<color=#2df7b2>{MemInfo.DeclaringType.Name}</color>.<color={memberColor}>{MemInfo.Name}</color>";
if (m_arguments.Length > 0) if (m_arguments.Length > 0 || this is CacheMethod)
{ {
m_richTextName += "("; m_richTextName += "(";
var _params = ""; var _params = "";

View File

@ -9,8 +9,6 @@ namespace Explorer
interface IExpandHeight interface IExpandHeight
{ {
bool IsExpanded { get; set; } bool IsExpanded { get; set; }
float WhiteSpace { get; set; }
float WhiteSpace { get; set; }
float ButtonWidthOffset { get; set; }
} }
} }

View File

@ -15,7 +15,6 @@ namespace Explorer
{ {
public bool IsExpanded { get; set; } public bool IsExpanded { get; set; }
public float WhiteSpace { get; set; } = 215f; public float WhiteSpace { get; set; } = 215f;
public float ButtonWidthOffset { get; set; } = 350f;
public PageHelper Pages = new PageHelper(); public PageHelper Pages = new PageHelper();
@ -126,6 +125,10 @@ namespace Explorer
m_keysType = type.GetGenericArguments()[0]; m_keysType = type.GetGenericArguments()[0];
m_valuesType = type.GetGenericArguments()[1]; m_valuesType = type.GetGenericArguments()[1];
} }
else
{
MelonLogger.Log("TODO? Dictionary is of type: " + Value.GetType().FullName);
}
} }
} }
@ -203,11 +206,7 @@ namespace Explorer
return; return;
} }
float whitespace = WhiteSpace; var whitespace = CalcWhitespace(window);
if (whitespace > 0)
{
ClampLabelWidth(window, ref whitespace);
}
int count = m_cachedKeys.Length; int count = m_cachedKeys.Length;

View File

@ -12,7 +12,6 @@ namespace Explorer
{ {
public bool IsExpanded { get; set; } public bool IsExpanded { get; set; }
public float WhiteSpace { get; set; } = 215f; public float WhiteSpace { get; set; } = 215f;
public float ButtonWidthOffset { get; set; } = 290f;
public PageHelper Pages = new PageHelper(); public PageHelper Pages = new PageHelper();
@ -245,11 +244,7 @@ namespace Explorer
return; return;
} }
float whitespace = WhiteSpace; var whitespace = CalcWhitespace(window);
if (whitespace > 0)
{
ClampLabelWidth(window, ref whitespace);
}
int count = m_cachedEntries.Length; int count = m_cachedEntries.Length;

View File

@ -44,11 +44,9 @@ namespace Explorer
} }
else else
{ {
var parsedArgs = ParseArguments();
try try
{ {
ret = mi.Invoke(mi.IsStatic ? null : DeclaringInstance, parsedArgs.ToArray()); ret = mi.Invoke(mi.IsStatic ? null : DeclaringInstance, ParseArguments());
m_evaluated = true; m_evaluated = true;
} }
catch (Exception e) catch (Exception e)

View File

@ -16,7 +16,6 @@ namespace Explorer
public bool IsExpanded { get; set; } public bool IsExpanded { get; set; }
public float WhiteSpace { get; set; } = 215f; public float WhiteSpace { get; set; } = 215f;
public float ButtonWidthOffset { get; set; } = 290f;
public override void UpdateValue() public override void UpdateValue()
{ {
@ -59,11 +58,7 @@ namespace Explorer
{ {
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
float whitespace = WhiteSpace; var whitespace = CalcWhitespace(window);
if (whitespace > 0)
{
ClampLabelWidth(window, ref whitespace);
}
GUILayout.BeginHorizontal(null); GUILayout.BeginHorizontal(null);
GUILayout.Space(whitespace); GUILayout.Space(whitespace);

View File

@ -15,7 +15,6 @@ namespace Explorer
public bool IsExpanded { get; set; } public bool IsExpanded { get; set; }
public float WhiteSpace { get; set; } = 215f; public float WhiteSpace { get; set; } = 215f;
public float ButtonWidthOffset { get; set; } = 290f;
public override void UpdateValue() public override void UpdateValue()
{ {
@ -54,11 +53,7 @@ namespace Explorer
{ {
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
float whitespace = WhiteSpace; var whitespace = CalcWhitespace(window);
if (whitespace > 0)
{
ClampLabelWidth(window, ref whitespace);
}
GUILayout.BeginHorizontal(null); GUILayout.BeginHorizontal(null);
GUILayout.Space(whitespace); GUILayout.Space(whitespace);

View File

@ -16,7 +16,6 @@ namespace Explorer
public bool IsExpanded { get; set; } public bool IsExpanded { get; set; }
public float WhiteSpace { get; set; } = 215f; public float WhiteSpace { get; set; } = 215f;
public float ButtonWidthOffset { get; set; } = 290f;
public override void UpdateValue() public override void UpdateValue()
{ {
@ -56,11 +55,7 @@ namespace Explorer
{ {
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
float whitespace = WhiteSpace; var whitespace = CalcWhitespace(window);
if (whitespace > 0)
{
ClampLabelWidth(window, ref whitespace);
}
GUILayout.BeginHorizontal(null); GUILayout.BeginHorizontal(null);
GUILayout.Space(whitespace); GUILayout.Space(whitespace);

View File

@ -21,7 +21,6 @@ namespace Explorer
public bool IsExpanded { get; set; } public bool IsExpanded { get; set; }
public float WhiteSpace { get; set; } = 215f; public float WhiteSpace { get; set; } = 215f;
public float ButtonWidthOffset { get; set; } = 290f;
public override void Init() public override void Init()
{ {
@ -90,11 +89,8 @@ namespace Explorer
if (CanWrite && IsExpanded) if (CanWrite && IsExpanded)
{ {
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
float whitespace = WhiteSpace;
if (whitespace > 0) var whitespace = CalcWhitespace(window);
{
ClampLabelWidth(window, ref whitespace);
}
// always draw x and y // always draw x and y
GUILayout.BeginHorizontal(null); GUILayout.BeginHorizontal(null);

62
src/Config/ModConfig.cs Normal file
View File

@ -0,0 +1,62 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Serialization;
using UnityEngine;
namespace Explorer
{
public class ModConfig
{
[XmlIgnore] public static readonly XmlSerializer Serializer = new XmlSerializer(typeof(ModConfig));
[XmlIgnore] private const string EXPLORER_FOLDER = @"Mods\CppExplorer";
[XmlIgnore] private const string SETTINGS_PATH = EXPLORER_FOLDER + @"\config.xml";
[XmlIgnore] public static ModConfig Instance;
public KeyCode Main_Menu_Toggle = KeyCode.F7;
public Vector2 Default_Window_Size = new Vector2(550, 700);
public static void OnLoad()
{
if (!Directory.Exists(EXPLORER_FOLDER))
{
Directory.CreateDirectory(EXPLORER_FOLDER);
}
if (File.Exists(SETTINGS_PATH))
{
LoadSettings(false);
}
else
{
Instance = new ModConfig();
SaveSettings(false);
}
}
public static void LoadSettings(bool checkExist = true)
{
if (checkExist && !File.Exists(SETTINGS_PATH))
return;
var file = File.OpenRead(SETTINGS_PATH);
Instance = (ModConfig)Serializer.Deserialize(file);
file.Close();
}
public static void SaveSettings(bool checkExist = true)
{
if (checkExist && File.Exists(SETTINGS_PATH))
File.Delete(SETTINGS_PATH);
FileStream file = File.Create(SETTINGS_PATH);
Serializer.Serialize(file, Instance);
file.Close();
}
}
}

View File

@ -13,7 +13,7 @@ namespace Explorer
public class CppExplorer : MelonMod public class CppExplorer : MelonMod
{ {
public const string NAME = "CppExplorer"; public const string NAME = "CppExplorer";
public const string VERSION = "1.6.5"; public const string VERSION = "1.6.8";
public const string AUTHOR = "Sinai"; public const string AUTHOR = "Sinai";
public const string GUID = "com.sinai.cppexplorer"; public const string GUID = "com.sinai.cppexplorer";
@ -44,12 +44,18 @@ namespace Explorer
UpdateCursorControl(); UpdateCursorControl();
} }
// ========== MonoBehaviour methods ========== private static void SetForceUnlock(bool unlock)
{
m_forceUnlock = unlock;
UpdateCursorControl();
}
public override void OnApplicationStart() public override void OnApplicationStart()
{ {
Instance = this; Instance = this;
ModConfig.OnLoad();
InputHelper.Init(); InputHelper.Init();
new MainMenu(); new MainMenu();
@ -60,9 +66,9 @@ namespace Explorer
m_lastVisibleState = Cursor.visible; m_lastVisibleState = Cursor.visible;
// Enable ShowMenu and ForceUnlockMouse // Enable ShowMenu and ForceUnlockMouse
// (set m_showMenu to not call UpdateCursorState twice) // (set m_showMenu directly to not call UpdateCursorState twice)
m_showMenu = true; m_showMenu = true;
SetForceUnlock(true); ForceUnlockMouse = true;
MelonLogger.Log($"CppExplorer {VERSION} initialized."); MelonLogger.Log($"CppExplorer {VERSION} initialized.");
} }
@ -76,7 +82,7 @@ namespace Explorer
public override void OnUpdate() public override void OnUpdate()
{ {
// Check main toggle key input // Check main toggle key input
if (InputHelper.GetKeyDown(KeyCode.F7)) if (InputHelper.GetKeyDown(ModConfig.Instance.Main_Menu_Toggle))
{ {
ShowMenu = !ShowMenu; ShowMenu = !ShowMenu;
} }
@ -104,14 +110,6 @@ namespace Explorer
InspectUnderMouse.OnGUI(); InspectUnderMouse.OnGUI();
} }
// =========== Cursor control ===========
private static void SetForceUnlock(bool unlock)
{
m_forceUnlock = unlock;
UpdateCursorControl();
}
private static void UpdateCursorControl() private static void UpdateCursorControl()
{ {
m_currentlySettingCursor = true; m_currentlySettingCursor = true;

View File

@ -73,7 +73,7 @@
</Reference> </Reference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="Helpers\IExpandHeight.cs" /> <Compile Include="CachedObjects\IExpandHeight.cs" />
<Compile Include="CachedObjects\Struct\CacheColor.cs" /> <Compile Include="CachedObjects\Struct\CacheColor.cs" />
<Compile Include="CachedObjects\Object\CacheDictionary.cs" /> <Compile Include="CachedObjects\Object\CacheDictionary.cs" />
<Compile Include="CachedObjects\Struct\CacheEnum.cs" /> <Compile Include="CachedObjects\Struct\CacheEnum.cs" />
@ -85,6 +85,7 @@
<Compile Include="CachedObjects\Struct\CacheQuaternion.cs" /> <Compile Include="CachedObjects\Struct\CacheQuaternion.cs" />
<Compile Include="CachedObjects\Struct\CacheVector.cs" /> <Compile Include="CachedObjects\Struct\CacheVector.cs" />
<Compile Include="CachedObjects\Struct\CacheRect.cs" /> <Compile Include="CachedObjects\Struct\CacheRect.cs" />
<Compile Include="Config\ModConfig.cs" />
<Compile Include="CppExplorer.cs" /> <Compile Include="CppExplorer.cs" />
<Compile Include="Extensions\ReflectionExtensions.cs" /> <Compile Include="Extensions\ReflectionExtensions.cs" />
<Compile Include="Helpers\InputHelper.cs" /> <Compile Include="Helpers\InputHelper.cs" />

View File

@ -27,8 +27,9 @@ namespace Explorer
} }
} }
public const int MainWindowID = 10; public const int MainWindowID = 5000;
public static Rect MainRect = new Rect(5, 5, 550, 700); public static Rect MainRect = new Rect(new Vector2(5,5), ModConfig.Instance.Default_Window_Size);
private static readonly List<WindowPage> Pages = new List<WindowPage>(); private static readonly List<WindowPage> Pages = new List<WindowPage>();
private static int m_currentPage = 0; private static int m_currentPage = 0;
@ -63,7 +64,7 @@ namespace Explorer
{ {
GUI.DragWindow(new Rect(0, 0, MainRect.width - 90, 20)); GUI.DragWindow(new Rect(0, 0, MainRect.width - 90, 20));
if (GUI.Button(new Rect(MainRect.width - 90, 2, 80, 20), "Hide (F7)")) if (GUI.Button(new Rect(MainRect.width - 90, 2, 80, 20), $"Hide ({ModConfig.Instance.Main_Menu_Toggle})"))
{ {
CppExplorer.ShowMenu = false; CppExplorer.ShowMenu = false;
return; return;

View File

@ -14,21 +14,7 @@ namespace Explorer.Tests
public static TestClass Instance => m_instance ?? (m_instance = new TestClass()); public static TestClass Instance => m_instance ?? (m_instance = new TestClass());
private static TestClass m_instance; private static TestClass m_instance;
public string this[int index] // Test indexed parameter
{
get
{
return $"int indexer: {index}";
}
}
public string this[string stringIndex]
{
get
{
return $"string indexer: {stringIndex}";
}
}
public string this[int arg0, string arg1] public string this[int arg0, string arg1]
{ {
@ -38,6 +24,8 @@ namespace Explorer.Tests
} }
} }
// Test basic list
public static List<string> TestList = new List<string> public static List<string> TestList = new List<string>
{ {
"1", "1",
@ -46,29 +34,48 @@ namespace Explorer.Tests
"etc..." "etc..."
}; };
public static Dictionary<int, List<string>> NestedDictionary = new Dictionary<int, List<string>> // Test a nested dictionary
public static Dictionary<int, Dictionary<string, int>> NestedDictionary = new Dictionary<int, Dictionary<string, int>>
{ {
{ {
123, 1,
new List<string> new Dictionary<string, int>
{ {
"One", {
"Two" "Sub 1", 123
},
{
"Sub 2", 456
},
} }
}, },
{ {
567, 2,
new List<string> new Dictionary<string, int>
{ {
"One", {
"Two" "Sub 3", 789
},
{
"Sub 4", 000
},
} }
}, },
}; };
// Test a basic method
public static Color TestMethod(float r, float g, float b, float a) public static Color TestMethod(float r, float g, float b, float a)
{ {
return new Color(r, g, b, a); return new Color(r, g, b, a);
} }
// A method with default arguments
public static Vector3 TestDefaultArgs(float arg0, float arg1, float arg2 = 5.0f)
{
return new Vector3(arg0, arg1, arg2);
}
} }
} }

View File

@ -28,20 +28,26 @@ namespace Explorer
public MemberTypes m_filter = MemberTypes.Property; public MemberTypes m_filter = MemberTypes.Property;
private bool m_hideFailedReflection = false; private bool m_hideFailedReflection = false;
// some extra caching // some extra cast-caching
private UnityEngine.Object m_uObj; private UnityEngine.Object m_uObj;
private Component m_component; private Component m_component;
private static readonly HashSet<string> _memberBlacklist = new HashSet<string>
{
// Causes a crash
"Type.DeclaringMethod",
// Pointless (handled by Properties)
"get_",
"set_"
};
public override void Init() public override void Init()
{ {
var type = ReflectionHelpers.GetActualType(Target); TargetType = ReflectionHelpers.GetActualType(Target);
TargetType = type; CacheMembers(ReflectionHelpers.GetAllBaseTypes(Target));
var types = ReflectionHelpers.GetAllBaseTypes(Target);
CacheMembers(types);
// cache the extra cast-caching
if (Target is Il2CppSystem.Object ilObject) if (Target is Il2CppSystem.Object ilObject)
{ {
var unityObj = ilObject.TryCast<UnityEngine.Object>(); var unityObj = ilObject.TryCast<UnityEngine.Object>();
@ -56,13 +62,6 @@ namespace Explorer
} }
} }
} }
m_filter = MemberTypes.All;
m_autoUpdate = true;
Update();
m_autoUpdate = false;
m_filter = MemberTypes.Property;
} }
public override void Update() public override void Update()
@ -99,28 +98,32 @@ namespace Explorer
private bool ShouldProcessMember(CacheObjectBase holder) private bool ShouldProcessMember(CacheObjectBase holder)
{ {
if (m_filter != MemberTypes.All && m_filter != holder.MemInfo?.MemberType) return false; // check MemberTypes filter
if (m_filter != MemberTypes.All && m_filter != holder.MemInfo?.MemberType)
return false;
if (!string.IsNullOrEmpty(holder.ReflectionException) && m_hideFailedReflection) return false; // hide failed reflection
if (!string.IsNullOrEmpty(holder.ReflectionException) && m_hideFailedReflection)
return false;
if (m_search == "" || holder.MemInfo == null) return true; // see if we should do name search
if (m_search == "" || holder.MemInfo == null)
return true;
var name = holder.MemInfo.DeclaringType.Name + "." + holder.MemInfo.Name; // ok do name search
return (holder.MemInfo.DeclaringType.Name + "." + holder.MemInfo.Name)
return name.ToLower().Contains(m_search.ToLower()); .ToLower()
.Contains(m_search.ToLower());
} }
private void CacheMembers(Type[] types) private void CacheMembers(Type[] types)
{ {
var list = new List<CacheObjectBase>(); var list = new List<CacheObjectBase>();
var cachedSigs = new List<string>();
var names = new List<string>();
foreach (var declaringType in types) foreach (var declaringType in types)
{ {
MemberInfo[] infos; MemberInfo[] infos;
string exception = null;
try try
{ {
infos = declaringType.GetMembers(ReflectionHelpers.CommonFlags); infos = declaringType.GetMembers(ReflectionHelpers.CommonFlags);
@ -132,6 +135,7 @@ namespace Explorer
} }
object target = Target; object target = Target;
string exception = null;
if (target is Il2CppSystem.Object ilObject) if (target is Il2CppSystem.Object ilObject)
{ {
@ -147,56 +151,56 @@ namespace Explorer
foreach (var member in infos) foreach (var member in infos)
{ {
if (member.MemberType == MemberTypes.Field || member.MemberType == MemberTypes.Property || member.MemberType == MemberTypes.Method) // make sure member type is Field, Method of Property (4 / 8 / 16)
int m = (int)member.MemberType;
if (m < 4 || m > 16)
continue;
// check blacklisted members
if (_memberBlacklist.Any(it => member.Name.StartsWith(it)))
continue;
// compare signature to already cached members
var signature = $"{member.DeclaringType.Name}.{member.Name}";
if (member is MethodInfo mi)
{ {
var name = $"{member.DeclaringType.Name}.{member.Name}"; AppendParams(mi.GetParameters());
}
else if (member is PropertyInfo pi)
{
AppendParams(pi.GetIndexParameters());
}
// blacklist (should probably make a proper implementation) void AppendParams(ParameterInfo[] _args)
if (name == "Type.DeclaringMethod" || member.Name.StartsWith("get_") || member.Name.StartsWith("set_")) //|| member.Name.Contains("Il2CppType") {
signature += " (";
foreach (var param in _args)
{ {
continue; signature += $"{param.ParameterType.Name} {param.Name}, ";
} }
signature += ")";
}
if (member is MethodInfo mi) if (cachedSigs.Contains(signature))
{ {
name += " ("; continue;
foreach (var param in mi.GetParameters()) }
{
name += $"{param.ParameterType.Name} {param.Name}, ";
}
name += ")";
}
else if (member is PropertyInfo pi)
{
name += " (";
foreach (var param in pi.GetIndexParameters())
{
name += $"{param.ParameterType.Name} {param.Name}, ";
}
name += ")";
}
if (names.Contains(name)) try
{
var cached = CacheObjectBase.GetCacheObject(member, target);
if (cached != null)
{ {
continue; cachedSigs.Add(signature);
} list.Add(cached);
cached.ReflectionException = exception;
try
{
var cached = CacheObjectBase.GetCacheObject(member, target);
if (cached != null)
{
names.Add(name);
list.Add(cached);
cached.ReflectionException = exception;
}
}
catch (Exception e)
{
MelonLogger.LogWarning($"Exception caching member {name}!");
MelonLogger.Log(e.ToString());
} }
} }
catch (Exception e)
{
MelonLogger.LogWarning($"Exception caching member {signature}!");
MelonLogger.Log(e.ToString());
}
} }
} }

View File

@ -17,7 +17,7 @@ namespace Explorer
public object Target; public object Target;
public int windowID; public int windowID;
public Rect m_rect = new Rect(0, 0, 550, 700); public Rect m_rect = new Rect(Vector2.zero, ModConfig.Instance.Default_Window_Size);
public Vector2 scroll = Vector2.zero; public Vector2 scroll = Vector2.zero;