* Added Max Results option to Search (default 5000)
* Fixed a TypeInitializationException which can happen when inspecting some classes with Dictionary members
* Fixed an issue which could prevent Input support from initializating
* Improved and fixed the display of TextAsset objects
* A few other minor fixes
This commit is contained in:
sinaioutlander 2020-10-12 20:15:41 +11:00
parent 39d9585f1d
commit f490203b10
15 changed files with 360 additions and 265 deletions

View File

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Reflection; using System.Reflection;
using Explorer.UI;
namespace Explorer.CacheObject namespace Explorer.CacheObject
{ {
@ -21,6 +22,15 @@ namespace Explorer.CacheObject
public override void UpdateValue() public override void UpdateValue()
{ {
if (IValue is InteractiveDictionary iDict)
{
if (!iDict.EnsureDictionaryIsSupported())
{
ReflectionException = "Not supported due to TypeInitializationException";
return;
}
}
try try
{ {
var fi = MemInfo as FieldInfo; var fi = MemInfo as FieldInfo;

View File

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Reflection; using System.Reflection;
using Explorer.UI;
namespace Explorer.CacheObject namespace Explorer.CacheObject
{ {
@ -32,6 +33,15 @@ namespace Explorer.CacheObject
return; return;
} }
if (IValue is InteractiveDictionary iDict)
{
if (!iDict.EnsureDictionaryIsSupported())
{
ReflectionException = "Not supported due to TypeInitializationException";
return;
}
}
try try
{ {
var pi = MemInfo as PropertyInfo; var pi = MemInfo as PropertyInfo;

View File

@ -231,7 +231,7 @@
<Compile Include="Extensions\UnityExtensions.cs" /> <Compile Include="Extensions\UnityExtensions.cs" />
<Compile Include="Helpers\ReflectionHelpers.cs" /> <Compile Include="Helpers\ReflectionHelpers.cs" />
<Compile Include="Helpers\UnityHelpers.cs" /> <Compile Include="Helpers\UnityHelpers.cs" />
<Compile Include="Input\AbstractInput.cs" /> <Compile Include="Input\IAbstractInput.cs" />
<Compile Include="Tests\TestClass.cs" /> <Compile Include="Tests\TestClass.cs" />
<Compile Include="UI\ForceUnlockCursor.cs" /> <Compile Include="UI\ForceUnlockCursor.cs" />
<Compile Include="Input\InputManager.cs" /> <Compile Include="Input\InputManager.cs" />

View File

@ -10,7 +10,7 @@ namespace Explorer
public class ExplorerCore public class ExplorerCore
{ {
public const string NAME = "Explorer " + VERSION + " (" + PLATFORM + ", " + MODLOADER + ")"; public const string NAME = "Explorer " + VERSION + " (" + PLATFORM + ", " + MODLOADER + ")";
public const string VERSION = "2.0.4"; public const string VERSION = "2.0.5";
public const string AUTHOR = "Sinai"; public const string AUTHOR = "Sinai";
public const string GUID = "com.sinai.explorer"; public const string GUID = "com.sinai.explorer";
@ -110,27 +110,27 @@ namespace Explorer
public static void Log(object message) public static void Log(object message)
{ {
#if ML #if ML
MelonLoader.MelonLogger.Log(message.ToString()); MelonLoader.MelonLogger.Log(message?.ToString());
#else #else
ExplorerBepInPlugin.Logging?.LogMessage(message.ToString()); ExplorerBepInPlugin.Logging?.LogMessage(message?.ToString());
#endif #endif
} }
public static void LogWarning(object message) public static void LogWarning(object message)
{ {
#if ML #if ML
MelonLoader.MelonLogger.LogWarning(message.ToString()); MelonLoader.MelonLogger.LogWarning(message?.ToString());
#else #else
ExplorerBepInPlugin.Logging?.LogWarning(message.ToString()); ExplorerBepInPlugin.Logging?.LogWarning(message?.ToString());
#endif #endif
} }
public static void LogError(object message) public static void LogError(object message)
{ {
#if ML #if ML
MelonLoader.MelonLogger.LogError(message.ToString()); MelonLoader.MelonLogger.LogError(message?.ToString());
#else #else
ExplorerBepInPlugin.Logging?.LogError(message.ToString()); ExplorerBepInPlugin.Logging?.LogError(message?.ToString());
#endif #endif
} }
} }

View File

@ -1,21 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
namespace Explorer.Input
{
public abstract class AbstractInput
{
public abstract void Init();
public abstract Vector2 MousePosition { get; }
public abstract bool GetKeyDown(KeyCode key);
public abstract bool GetKey(KeyCode key);
public abstract bool GetMouseButtonDown(int btn);
public abstract bool GetMouseButton(int btn);
}
}

View File

@ -0,0 +1,21 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
namespace Explorer.Input
{
public interface IAbstractInput
{
void Init();
Vector2 MousePosition { get; }
bool GetKeyDown(KeyCode key);
bool GetKey(KeyCode key);
bool GetMouseButtonDown(int btn);
bool GetMouseButton(int btn);
}
}

View File

@ -10,37 +10,35 @@ namespace Explorer
{ {
public static class InputManager public static class InputManager
{ {
private static AbstractInput inputModule; private static IAbstractInput m_inputModule;
public static void Init() public static void Init()
{ {
if (InputSystem.TKeyboard != null || TryLoadModule("Unity.InputSystem", InputSystem.TKeyboard)) if (InputSystem.TKeyboard != null || (ReflectionHelpers.LoadModule("Unity.InputSystem") && InputSystem.TKeyboard != null))
{ {
inputModule = new InputSystem(); m_inputModule = new InputSystem();
} }
else if (LegacyInput.TInput != null || TryLoadModule("UnityEngine.InputLegacyModule", LegacyInput.TInput)) else if (LegacyInput.TInput != null || (ReflectionHelpers.LoadModule("UnityEngine.InputLegacyModule") && LegacyInput.TInput != null))
{ {
inputModule = new LegacyInput(); m_inputModule = new LegacyInput();
} }
if (inputModule == null) if (m_inputModule == null)
{ {
ExplorerCore.LogWarning("Could not find any Input module!"); ExplorerCore.LogWarning("Could not find any Input module!");
inputModule = new NoInput(); m_inputModule = new NoInput();
} }
inputModule.Init(); m_inputModule.Init();
bool TryLoadModule(string dll, Type check) => ReflectionHelpers.LoadModule(dll) && check != null;
} }
public static Vector3 MousePosition => inputModule.MousePosition; public static Vector3 MousePosition => m_inputModule.MousePosition;
public static bool GetKeyDown(KeyCode key) => inputModule.GetKeyDown(key); public static bool GetKeyDown(KeyCode key) => m_inputModule.GetKeyDown(key);
public static bool GetKey(KeyCode key) => inputModule.GetKey(key); public static bool GetKey(KeyCode key) => m_inputModule.GetKey(key);
public static bool GetMouseButtonDown(int btn) => inputModule.GetMouseButtonDown(btn); public static bool GetMouseButtonDown(int btn) => m_inputModule.GetMouseButtonDown(btn);
public static bool GetMouseButton(int btn) => inputModule.GetMouseButton(btn); public static bool GetMouseButton(int btn) => m_inputModule.GetMouseButton(btn);
#if CPP #if CPP
internal delegate void d_ResetInputAxes(); internal delegate void d_ResetInputAxes();

View File

@ -7,7 +7,7 @@ using UnityEngine;
namespace Explorer.Input namespace Explorer.Input
{ {
public class InputSystem : AbstractInput public class InputSystem : IAbstractInput
{ {
public static Type TKeyboard => _keyboard ?? (_keyboard = ReflectionHelpers.GetTypeByName("UnityEngine.InputSystem.Keyboard")); public static Type TKeyboard => _keyboard ?? (_keyboard = ReflectionHelpers.GetTypeByName("UnityEngine.InputSystem.Keyboard"));
private static Type _keyboard; private static Type _keyboard;
@ -43,9 +43,9 @@ namespace Explorer.Input
private static PropertyInfo _positionProp; private static PropertyInfo _positionProp;
private static MethodInfo _readVector2InputMethod; private static MethodInfo _readVector2InputMethod;
public override Vector2 MousePosition => (Vector2)_readVector2InputMethod.Invoke(MousePositionInfo, new object[0]); public Vector2 MousePosition => (Vector2)_readVector2InputMethod.Invoke(MousePositionInfo, new object[0]);
public override bool GetKeyDown(KeyCode key) public bool GetKeyDown(KeyCode key)
{ {
var parsedKey = Enum.Parse(TKey, key.ToString()); var parsedKey = Enum.Parse(TKey, key.ToString());
var actualKey = _kbIndexer.GetValue(CurrentKeyboard, new object[] { parsedKey }); var actualKey = _kbIndexer.GetValue(CurrentKeyboard, new object[] { parsedKey });
@ -53,7 +53,7 @@ namespace Explorer.Input
return (bool)_btnWasPressedProp.GetValue(actualKey, null); return (bool)_btnWasPressedProp.GetValue(actualKey, null);
} }
public override bool GetKey(KeyCode key) public bool GetKey(KeyCode key)
{ {
var parsed = Enum.Parse(TKey, key.ToString()); var parsed = Enum.Parse(TKey, key.ToString());
var actualKey = _kbIndexer.GetValue(CurrentKeyboard, new object[] { parsed }); var actualKey = _kbIndexer.GetValue(CurrentKeyboard, new object[] { parsed });
@ -61,7 +61,7 @@ namespace Explorer.Input
return (bool)_btnIsPressedProp.GetValue(actualKey, null); return (bool)_btnIsPressedProp.GetValue(actualKey, null);
} }
public override bool GetMouseButtonDown(int btn) public bool GetMouseButtonDown(int btn)
{ {
switch (btn) switch (btn)
{ {
@ -72,7 +72,7 @@ namespace Explorer.Input
} }
} }
public override bool GetMouseButton(int btn) public bool GetMouseButton(int btn)
{ {
switch (btn) switch (btn)
{ {
@ -83,7 +83,7 @@ namespace Explorer.Input
} }
} }
public override void Init() public void Init()
{ {
ExplorerCore.Log("Initializing new InputSystem support..."); ExplorerCore.Log("Initializing new InputSystem support...");

View File

@ -7,7 +7,7 @@ using UnityEngine;
namespace Explorer.Input namespace Explorer.Input
{ {
public class LegacyInput : AbstractInput public class LegacyInput : IAbstractInput
{ {
public static Type TInput => _input ?? (_input = ReflectionHelpers.GetTypeByName("UnityEngine.Input")); public static Type TInput => _input ?? (_input = ReflectionHelpers.GetTypeByName("UnityEngine.Input"));
private static Type _input; private static Type _input;
@ -18,17 +18,17 @@ namespace Explorer.Input
private static MethodInfo _getMouseButtonMethod; private static MethodInfo _getMouseButtonMethod;
private static MethodInfo _getMouseButtonDownMethod; private static MethodInfo _getMouseButtonDownMethod;
public override Vector2 MousePosition => (Vector3)_mousePositionProp.GetValue(null, null); public Vector2 MousePosition => (Vector3)_mousePositionProp.GetValue(null, null);
public override bool GetKey(KeyCode key) => (bool)_getKeyMethod.Invoke(null, new object[] { key }); public bool GetKey(KeyCode key) => (bool)_getKeyMethod.Invoke(null, new object[] { key });
public override bool GetKeyDown(KeyCode key) => (bool)_getKeyDownMethod.Invoke(null, new object[] { key }); public bool GetKeyDown(KeyCode key) => (bool)_getKeyDownMethod.Invoke(null, new object[] { key });
public override bool GetMouseButton(int btn) => (bool)_getMouseButtonMethod.Invoke(null, new object[] { btn }); public bool GetMouseButton(int btn) => (bool)_getMouseButtonMethod.Invoke(null, new object[] { btn });
public override bool GetMouseButtonDown(int btn) => (bool)_getMouseButtonDownMethod.Invoke(null, new object[] { btn }); public bool GetMouseButtonDown(int btn) => (bool)_getMouseButtonDownMethod.Invoke(null, new object[] { btn });
public override void Init() public void Init()
{ {
ExplorerCore.Log("Initializing Legacy Input support..."); ExplorerCore.Log("Initializing Legacy Input support...");

View File

@ -8,18 +8,16 @@ namespace Explorer.Input
{ {
// Just a stub for games where no Input module was able to load at all. // Just a stub for games where no Input module was able to load at all.
public class NoInput : AbstractInput public class NoInput : IAbstractInput
{ {
public override Vector2 MousePosition => Vector2.zero; public Vector2 MousePosition => Vector2.zero;
public override bool GetKey(KeyCode key) => false; public bool GetKey(KeyCode key) => false;
public bool GetKeyDown(KeyCode key) => false;
public override bool GetKeyDown(KeyCode key) => false; public bool GetMouseButton(int btn) => false;
public bool GetMouseButtonDown(int btn) => false;
public override bool GetMouseButton(int btn) => false; public void Init() { }
public override bool GetMouseButtonDown(int btn) => false;
public override void Init() { }
} }
} }

View File

@ -169,6 +169,8 @@ namespace Explorer.UI.Inspectors
private void DestroyOnException(Exception e) private void DestroyOnException(Exception e)
{ {
if (pendingDestroy) return;
ExplorerCore.Log($"Exception drawing GameObject Window: {e.GetType()}, {e.Message}"); ExplorerCore.Log($"Exception drawing GameObject Window: {e.GetType()}, {e.Message}");
pendingDestroy = true; pendingDestroy = true;
DestroyWindow(); DestroyWindow();

View File

@ -208,8 +208,6 @@ namespace Explorer.UI.Inspectors
continue; continue;
} }
//ExplorerCore.Log($"Trying to cache member {sig}...");
try try
{ {
var cached = CacheFactory.GetCacheObject(member, target); var cached = CacheFactory.GetCacheObject(member, target);
@ -218,9 +216,13 @@ namespace Explorer.UI.Inspectors
{ {
cachedSigs.Add(sig); cachedSigs.Add(sig);
list.Add(cached); list.Add(cached);
if (string.IsNullOrEmpty(cached.ReflectionException))
{
cached.ReflectionException = exception; cached.ReflectionException = exception;
} }
} }
}
catch (Exception e) catch (Exception e)
{ {
ExplorerCore.LogWarning($"Exception caching member {sig}!"); ExplorerCore.LogWarning($"Exception caching member {sig}!");

View File

@ -204,7 +204,24 @@ namespace Explorer.UI
var valueType = ReflectionHelpers.GetActualType(Value); var valueType = ReflectionHelpers.GetActualType(Value);
string label = (string)ToStringMethod?.Invoke(Value, null) ?? Value.ToString(); string label;
if (valueType == typeof(TextAsset))
{
var textAsset = Value as TextAsset;
label = textAsset.text;
if (label.Length > 10)
{
label = $"{label.Substring(0, 10)}...";
}
label = $"\"{label}\" {textAsset.name} (<color={Syntax.Class_Instance}>UnityEngine.TextAsset</color>)";
}
else
{
label = (string)ToStringMethod?.Invoke(Value, null) ?? Value.ToString();
var classColor = valueType.IsAbstract && valueType.IsSealed var classColor = valueType.IsAbstract && valueType.IsSealed
? Syntax.Class_Static ? Syntax.Class_Static
@ -227,6 +244,7 @@ namespace Explorer.UI
label = label.Replace(valueType.FullName, typeLabel); label = label.Replace(valueType.FullName, typeLabel);
} }
} }
}
return m_btnLabel = label; return m_btnLabel = label;
} }

View File

@ -161,7 +161,7 @@ namespace Explorer.UI
m_cachedValues = values.ToArray(); m_cachedValues = values.ToArray();
} }
private bool EnsureDictionaryIsSupported() public bool EnsureDictionaryIsSupported()
{ {
if (typeof(IDictionary).IsAssignableFrom(ValueType)) if (typeof(IDictionary).IsAssignableFrom(ValueType))
{ {
@ -180,6 +180,11 @@ namespace Explorer.UI
.GetField("NativeClassPtr") .GetField("NativeClassPtr")
.GetValue(null); .GetValue(null);
if (ptr == IntPtr.Zero)
{
return false;
}
return Il2CppSystem.Type.internal_from_handle(IL2CPP.il2cpp_class_get_type(ptr)) is Il2CppSystem.Type; return Il2CppSystem.Type.internal_from_handle(IL2CPP.il2cpp_class_get_type(ptr)) is Il2CppSystem.Type;
} }
} }

View File

@ -6,6 +6,7 @@ using System.Reflection;
using UnityEngine; using UnityEngine;
using Explorer.UI.Shared; using Explorer.UI.Shared;
using Explorer.CacheObject; using Explorer.CacheObject;
using System.Threading;
namespace Explorer.UI.Main namespace Explorer.UI.Main
{ {
@ -15,9 +16,13 @@ namespace Explorer.UI.Main
public override string Name { get => "Search"; } public override string Name { get => "Search"; }
private int MaxSearchResults = 5000;
private string m_searchInput = ""; private string m_searchInput = "";
private string m_typeInput = ""; private string m_typeInput = "";
//private bool m_cachingResults;
private Vector2 resultsScroll = Vector2.zero; private Vector2 resultsScroll = Vector2.zero;
public PageHelper Pages = new PageHelper(); public PageHelper Pages = new PageHelper();
@ -58,6 +63,8 @@ namespace Explorer.UI.Main
private void CacheResults(IEnumerable results, bool isStaticClasses = false) private void CacheResults(IEnumerable results, bool isStaticClasses = false)
{ {
//m_cachingResults = true;
m_searchResults = new List<CacheObjectBase>(); m_searchResults = new List<CacheObjectBase>();
foreach (var obj in results) foreach (var obj in results)
@ -67,6 +74,9 @@ namespace Explorer.UI.Main
#if CPP #if CPP
if (toCache is Il2CppSystem.Object ilObject) if (toCache is Il2CppSystem.Object ilObject)
{ {
var type = ReflectionHelpers.GetActualType(ilObject);
ilObject = (Il2CppSystem.Object)ilObject.Il2CppCast(type);
toCache = ilObject.TryCast<GameObject>() ?? ilObject.TryCast<Transform>()?.gameObject ?? ilObject; toCache = ilObject.TryCast<GameObject>() ?? ilObject.TryCast<Transform>()?.gameObject ?? ilObject;
} }
#else #else
@ -76,6 +86,14 @@ namespace Explorer.UI.Main
} }
#endif #endif
if (toCache is TextAsset textAsset)
{
if (string.IsNullOrEmpty(textAsset.text))
{
continue;
}
}
var cache = CacheFactory.GetCacheObject(toCache); var cache = CacheFactory.GetCacheObject(toCache);
cache.IsStaticClassSearchResult = isStaticClasses; cache.IsStaticClassSearchResult = isStaticClasses;
m_searchResults.Add(cache); m_searchResults.Add(cache);
@ -83,190 +101,25 @@ namespace Explorer.UI.Main
Pages.ItemCount = m_searchResults.Count; Pages.ItemCount = m_searchResults.Count;
Pages.PageOffset = 0; Pages.PageOffset = 0;
results = null;
//m_cachingResults = false;
} }
public override void DrawWindow()
{
try
{
// helpers
GUIUnstrip.BeginHorizontal(GUIContent.none, GUI.skin.box, null);
GUILayout.Label("<b><color=orange>Helpers</color></b>", new GUILayoutOption[] { GUILayout.Width(70) });
if (GUILayout.Button("Find Static Instances", new GUILayoutOption[] { GUILayout.Width(180) }))
{
CacheResults(GetStaticInstances());
}
if (GUILayout.Button("Find Static Classes", new GUILayoutOption[] { GUILayout.Width(180) }))
{
CacheResults(GetStaticClasses(), true);
}
GUILayout.EndHorizontal();
// search box
SearchBox();
// results
GUIUnstrip.BeginVertical(GUIContent.none, GUI.skin.box, null);
GUI.skin.label.alignment = TextAnchor.MiddleCenter;
GUILayout.Label("<b><color=orange>Results </color></b>" + " (" + m_searchResults.Count + ")", new GUILayoutOption[0]);
GUI.skin.label.alignment = TextAnchor.UpperLeft;
int count = m_searchResults.Count;
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
Pages.DrawLimitInputArea();
if (count > Pages.ItemsPerPage)
{
// prev/next page buttons
if (Pages.ItemCount > Pages.ItemsPerPage)
{
if (GUILayout.Button("< Prev", new GUILayoutOption[] { GUILayout.Width(80) }))
{
Pages.TurnPage(Turn.Left, ref this.resultsScroll);
}
Pages.CurrentPageLabel();
if (GUILayout.Button("Next >", new GUILayoutOption[] { GUILayout.Width(80) }))
{
Pages.TurnPage(Turn.Right, ref this.resultsScroll);
}
}
}
GUILayout.EndHorizontal();
resultsScroll = GUIUnstrip.BeginScrollView(resultsScroll);
var _temprect = new Rect(MainMenu.MainRect.x, MainMenu.MainRect.y, MainMenu.MainRect.width + 160, MainMenu.MainRect.height);
if (m_searchResults.Count > 0)
{
int offset = Pages.CalculateOffsetIndex();
for (int i = offset; i < offset + Pages.ItemsPerPage && i < count; i++)
{
m_searchResults[i].Draw(MainMenu.MainRect, 0f);
}
}
else
{
GUILayout.Label("<color=red><i>No results found!</i></color>", new GUILayoutOption[0]);
}
GUIUnstrip.EndScrollView();
GUILayout.EndVertical();
}
catch (Exception e)
{
ExplorerCore.Log("Exception drawing search results!");
while (e != null)
{
ExplorerCore.Log(e);
e = e.InnerException;
}
m_searchResults.Clear();
}
}
private void SearchBox()
{
GUIUnstrip.BeginVertical(GUIContent.none, GUI.skin.box, null);
// ----- GameObject Search -----
GUI.skin.label.alignment = TextAnchor.MiddleCenter;
GUILayout.Label("<b><color=orange>Search</color></b>", new GUILayoutOption[0]);
GUI.skin.label.alignment = TextAnchor.UpperLeft;
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
GUILayout.Label("Name Contains:", new GUILayoutOption[] { GUILayout.Width(100) });
m_searchInput = GUIUnstrip.TextField(m_searchInput, new GUILayoutOption[] { GUILayout.Width(200) });
GUILayout.EndHorizontal();
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
GUILayout.Label("Class Filter:", new GUILayoutOption[] { GUILayout.Width(100) });
ClassFilterToggle(TypeFilter.Object, "Object");
ClassFilterToggle(TypeFilter.GameObject, "GameObject");
ClassFilterToggle(TypeFilter.Component, "Component");
ClassFilterToggle(TypeFilter.Custom, "Custom");
GUILayout.EndHorizontal();
if (TypeMode == TypeFilter.Custom)
{
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
GUI.skin.label.alignment = TextAnchor.MiddleRight;
GUILayout.Label("Custom Class:", new GUILayoutOption[] { GUILayout.Width(250) });
GUI.skin.label.alignment = TextAnchor.UpperLeft;
m_typeInput = GUIUnstrip.TextField(m_typeInput, new GUILayoutOption[] { GUILayout.Width(250) });
GUILayout.EndHorizontal();
}
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
GUILayout.Label("Scene Filter:", new GUILayoutOption[] { GUILayout.Width(100) });
SceneFilterToggle(SceneFilter.Any, "Any", 60);
SceneFilterToggle(SceneFilter.This, "This Scene", 100);
SceneFilterToggle(SceneFilter.DontDestroy, "DontDestroyOnLoad", 140);
SceneFilterToggle(SceneFilter.None, "No Scene", 80);
GUILayout.EndHorizontal();
if (GUILayout.Button("<b><color=cyan>Search</color></b>", new GUILayoutOption[0]))
{
Search();
}
GUILayout.EndVertical();
}
private void ClassFilterToggle(TypeFilter mode, string label)
{
if (TypeMode == mode)
{
GUI.color = Color.green;
}
else
{
GUI.color = Color.white;
}
if (GUILayout.Button(label, new GUILayoutOption[] { GUILayout.Width(100) }))
{
TypeMode = mode;
}
GUI.color = Color.white;
}
private void SceneFilterToggle(SceneFilter mode, string label, float width)
{
if (SceneMode == mode)
{
GUI.color = Color.green;
}
else
{
GUI.color = Color.white;
}
if (GUILayout.Button(label, new GUILayoutOption[] { GUILayout.Width(width) }))
{
SceneMode = mode;
}
GUI.color = Color.white;
}
// -------------- ACTUAL METHODS (not Gui draw) ----------------- //
// ======= search functions =======
private void Search() private void Search()
{ {
//if (m_cachingResults)
//{
// ExplorerCore.Log("Cannot search now, we are already caching results...");
// return;
//}
Pages.PageOffset = 0; Pages.PageOffset = 0;
CacheResults(FindAllObjectsOfType(m_searchInput, m_typeInput));
// Would use Task, but Explorer is .NET 3.5-compatible.
var objectsOfType = FindAllObjectsOfType(m_searchInput, m_typeInput);
CacheResults(objectsOfType);
} }
private List<object> FindAllObjectsOfType(string searchQuery, string typeName) private List<object> FindAllObjectsOfType(string searchQuery, string typeName)
@ -330,7 +183,7 @@ namespace Explorer.UI.Main
int i = 0; int i = 0;
foreach (var obj in allObjectsOfType) foreach (var obj in allObjectsOfType)
{ {
if (i >= 2000) break; if (i >= MaxSearchResults) break;
if (searchQuery != "" && !obj.name.ToLower().Contains(searchQuery.ToLower())) if (searchQuery != "" && !obj.name.ToLower().Contains(searchQuery.ToLower()))
{ {
@ -362,6 +215,10 @@ namespace Explorer.UI.Main
i++; i++;
} }
allObjectsOfType = null;
searchType = null;
searchQuery = null;
return matches; return matches;
} }
@ -401,8 +258,6 @@ namespace Explorer.UI.Main
return false; return false;
} }
// ====== other ========
private static bool FilterName(string name) private static bool FilterName(string name)
{ {
// Don't really want these instances. // Don't really want these instances.
@ -504,5 +359,202 @@ namespace Explorer.UI.Main
return list; return list;
} }
// =========== GUI DRAW ============= //
public override void DrawWindow()
{
try
{
// helpers
GUIUnstrip.BeginHorizontal(GUIContent.none, GUI.skin.box, null);
GUILayout.Label("<b><color=orange>Helpers</color></b>", new GUILayoutOption[] { GUILayout.Width(70) });
if (GUILayout.Button("Find Static Instances", new GUILayoutOption[] { GUILayout.Width(180) }))
{
CacheResults(GetStaticInstances());
}
if (GUILayout.Button("Find Static Classes", new GUILayoutOption[] { GUILayout.Width(180) }))
{
CacheResults(GetStaticClasses(), true);
}
GUILayout.EndHorizontal();
// search box
SearchBox();
// results
GUIUnstrip.BeginVertical(GUIContent.none, GUI.skin.box, null);
GUI.skin.label.alignment = TextAnchor.MiddleCenter;
GUILayout.Label("<b><color=orange>Results </color></b>" + " (" + m_searchResults.Count + ")", new GUILayoutOption[0]);
GUI.skin.label.alignment = TextAnchor.UpperLeft;
int count = m_searchResults.Count;
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
Pages.DrawLimitInputArea();
if (count > Pages.ItemsPerPage)
{
// prev/next page buttons
if (Pages.ItemCount > Pages.ItemsPerPage)
{
if (GUILayout.Button("< Prev", new GUILayoutOption[] { GUILayout.Width(80) }))
{
Pages.TurnPage(Turn.Left, ref this.resultsScroll);
}
Pages.CurrentPageLabel();
if (GUILayout.Button("Next >", new GUILayoutOption[] { GUILayout.Width(80) }))
{
Pages.TurnPage(Turn.Right, ref this.resultsScroll);
}
}
}
GUILayout.EndHorizontal();
resultsScroll = GUIUnstrip.BeginScrollView(resultsScroll);
var _temprect = new Rect(MainMenu.MainRect.x, MainMenu.MainRect.y, MainMenu.MainRect.width + 160, MainMenu.MainRect.height);
if (m_searchResults.Count > 0)
{
int offset = Pages.CalculateOffsetIndex();
for (int i = offset; i < offset + Pages.ItemsPerPage && i < count; i++)
{
if (i >= m_searchResults.Count) break;
m_searchResults[i].Draw(MainMenu.MainRect, 0f);
}
}
else
{
GUILayout.Label("<color=red><i>No results found!</i></color>", new GUILayoutOption[0]);
}
GUIUnstrip.EndScrollView();
GUILayout.EndVertical();
}
catch (Exception e)
{
if (!e.Message.Contains("in a group with only"))
{
ExplorerCore.Log("Exception drawing search results!");
while (e != null)
{
ExplorerCore.Log(e);
e = e.InnerException;
}
m_searchResults.Clear();
}
}
}
private void SearchBox()
{
GUIUnstrip.BeginVertical(GUIContent.none, GUI.skin.box, null);
// ----- GameObject Search -----
GUI.skin.label.alignment = TextAnchor.MiddleCenter;
GUILayout.Label("<b><color=orange>Search</color></b>", new GUILayoutOption[0]);
GUI.skin.label.alignment = TextAnchor.UpperLeft;
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
GUILayout.Label("Name Contains:", new GUILayoutOption[] { GUILayout.Width(100) });
m_searchInput = GUIUnstrip.TextField(m_searchInput, new GUILayoutOption[] { GUILayout.Width(200) });
GUILayout.Label("Max Results:", new GUILayoutOption[] { GUILayout.Width(100) });
var s = MaxSearchResults.ToString();
s = GUIUnstrip.TextField(s, new GUILayoutOption[] { GUILayout.Width(80) });
if (int.TryParse(s, out int i))
{
MaxSearchResults = i;
}
GUILayout.EndHorizontal();
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
GUILayout.Label("Class Filter:", new GUILayoutOption[] { GUILayout.Width(100) });
ClassFilterToggle(TypeFilter.Object, "Object");
ClassFilterToggle(TypeFilter.GameObject, "GameObject");
ClassFilterToggle(TypeFilter.Component, "Component");
ClassFilterToggle(TypeFilter.Custom, "Custom");
GUILayout.EndHorizontal();
if (TypeMode == TypeFilter.Custom)
{
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
GUI.skin.label.alignment = TextAnchor.MiddleRight;
GUILayout.Label("Custom Class:", new GUILayoutOption[] { GUILayout.Width(250) });
GUI.skin.label.alignment = TextAnchor.UpperLeft;
m_typeInput = GUIUnstrip.TextField(m_typeInput, new GUILayoutOption[] { GUILayout.Width(250) });
GUILayout.EndHorizontal();
}
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
GUILayout.Label("Scene Filter:", new GUILayoutOption[] { GUILayout.Width(100) });
SceneFilterToggle(SceneFilter.Any, "Any", 60);
SceneFilterToggle(SceneFilter.This, "This Scene", 100);
SceneFilterToggle(SceneFilter.DontDestroy, "DontDestroyOnLoad", 140);
SceneFilterToggle(SceneFilter.None, "No Scene", 80);
GUILayout.EndHorizontal();
if (GUILayout.Button("<b><color=cyan>Search</color></b>", new GUILayoutOption[0]))
{
Search();
}
//if (m_cachingResults)
//{
// GUILayout.Label("Searching...", new GUILayoutOption[0]);
//}
//else
//{
// if (GUILayout.Button("<b><color=cyan>Search</color></b>", new GUILayoutOption[0]))
// {
// Search();
// }
//}
GUILayout.EndVertical();
}
private void ClassFilterToggle(TypeFilter mode, string label)
{
if (TypeMode == mode)
{
GUI.color = Color.green;
}
else
{
GUI.color = Color.white;
}
if (GUILayout.Button(label, new GUILayoutOption[] { GUILayout.Width(100) }))
{
TypeMode = mode;
}
GUI.color = Color.white;
}
private void SceneFilterToggle(SceneFilter mode, string label, float width)
{
if (SceneMode == mode)
{
GUI.color = Color.green;
}
else
{
GUI.color = Color.white;
}
if (GUILayout.Button(label, new GUILayoutOption[] { GUILayout.Width(width) }))
{
SceneMode = mode;
}
GUI.color = Color.white;
}
} }
} }