mirror of
https://github.com/GrahamKracker/UnityExplorer.git
synced 2025-07-04 20:42:22 +08:00
REPL console
This commit is contained in:
@ -1,131 +0,0 @@
|
||||
//using System;
|
||||
//using System.Collections;
|
||||
//using System.Collections.Generic;
|
||||
//using System.Linq;
|
||||
//using System.Reflection;
|
||||
//using System.Text;
|
||||
//using Mono.CSharp;
|
||||
//using UnityEngine;
|
||||
//using Attribute = System.Attribute;
|
||||
//using Object = UnityEngine.Object;
|
||||
|
||||
//namespace Explorer
|
||||
//{
|
||||
// public class REPL : InteractiveBase
|
||||
// {
|
||||
// static REPL()
|
||||
// {
|
||||
// var go = new GameObject("UnityREPL");
|
||||
// GameObject.DontDestroyOnLoad(go);
|
||||
// //go.transform.parent = HPExplorer.Instance.transform;
|
||||
// MB = go.AddComponent<ReplHelper>();
|
||||
// }
|
||||
|
||||
// [Documentation("MB - A dummy MonoBehaviour for accessing Unity.")]
|
||||
// public static ReplHelper MB { get; }
|
||||
|
||||
// [Documentation("find<T>() - find a UnityEngine.Object of type T.")]
|
||||
// public static T find<T>() where T : Object
|
||||
// {
|
||||
// return MB.Find<T>();
|
||||
// }
|
||||
|
||||
// [Documentation("findAll<T>() - find all UnityEngine.Object of type T.")]
|
||||
// public static T[] findAll<T>() where T : Object
|
||||
// {
|
||||
// return MB.FindAll<T>();
|
||||
// }
|
||||
|
||||
// [Documentation("runCoroutine(enumerator) - runs an IEnumerator as a Unity coroutine.")]
|
||||
// public static object runCoroutine(IEnumerator i)
|
||||
// {
|
||||
// return MB.RunCoroutine(i);
|
||||
// }
|
||||
|
||||
// [Documentation("endCoroutine(co) - ends a Unity coroutine.")]
|
||||
// public static void endCoroutine(Coroutine c)
|
||||
// {
|
||||
// MB.EndCoroutine(c);
|
||||
// }
|
||||
|
||||
// ////[Documentation("type<T>() - obtain type info about a type T. Provides some Reflection helpers.")]
|
||||
// ////public static TypeHelper type<T>()
|
||||
// ////{
|
||||
// //// return new TypeHelper(typeof(T));
|
||||
// ////}
|
||||
|
||||
// ////[Documentation("type(obj) - obtain type info about object obj. Provides some Reflection helpers.")]
|
||||
// ////public static TypeHelper type(object instance)
|
||||
// ////{
|
||||
// //// return new TypeHelper(instance);
|
||||
// ////}
|
||||
|
||||
// //[Documentation("dir(obj) - lists all available methods and fiels of a given obj.")]
|
||||
// //public static string dir(object instance)
|
||||
// //{
|
||||
// // return type(instance).info();
|
||||
// //}
|
||||
|
||||
// //[Documentation("dir<T>() - lists all available methods and fields of type T.")]
|
||||
// //public static string dir<T>()
|
||||
// //{
|
||||
// // return type<T>().info();
|
||||
// //}
|
||||
|
||||
// //[Documentation("findrefs(obj) - find references to the object in currently loaded components.")]
|
||||
// //public static Component[] findrefs(object obj)
|
||||
// //{
|
||||
// // if (obj == null) throw new ArgumentNullException(nameof(obj));
|
||||
|
||||
// // var results = new List<Component>();
|
||||
// // foreach (var component in Object.FindObjectsOfType<Component>())
|
||||
// // {
|
||||
// // var type = component.GetType();
|
||||
|
||||
// // var nameBlacklist = new[] { "parent", "parentInternal", "root", "transform", "gameObject" };
|
||||
// // var typeBlacklist = new[] { typeof(bool) };
|
||||
|
||||
// // foreach (var prop in type.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
|
||||
// // .Where(x => x.CanRead && !nameBlacklist.Contains(x.Name) && !typeBlacklist.Contains(x.PropertyType)))
|
||||
// // {
|
||||
// // try
|
||||
// // {
|
||||
// // if (Equals(prop.GetValue(component, null), obj))
|
||||
// // {
|
||||
// // results.Add(component);
|
||||
// // goto finish;
|
||||
// // }
|
||||
// // }
|
||||
// // catch { }
|
||||
// // }
|
||||
// // foreach (var field in type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
|
||||
// // .Where(x => !nameBlacklist.Contains(x.Name) && !typeBlacklist.Contains(x.FieldType)))
|
||||
// // {
|
||||
// // try
|
||||
// // {
|
||||
// // if (Equals(field.GetValue(component), obj))
|
||||
// // {
|
||||
// // results.Add(component);
|
||||
// // goto finish;
|
||||
// // }
|
||||
// // }
|
||||
// // catch { }
|
||||
// // }
|
||||
// // finish:;
|
||||
// // }
|
||||
|
||||
// // return results.ToArray();
|
||||
// //}
|
||||
|
||||
// [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property)]
|
||||
// private class DocumentationAttribute : Attribute
|
||||
// {
|
||||
// public DocumentationAttribute(string doc)
|
||||
// {
|
||||
// Docs = doc;
|
||||
// }
|
||||
|
||||
// public string Docs { get; }
|
||||
// }
|
||||
// }
|
||||
//}
|
@ -1,29 +0,0 @@
|
||||
//using System.Collections;
|
||||
//using MelonLoader;
|
||||
//using UnityEngine;
|
||||
|
||||
//namespace Explorer
|
||||
//{
|
||||
// public class ReplHelper : MonoBehaviour
|
||||
// {
|
||||
// public T Find<T>() where T : Object
|
||||
// {
|
||||
// return FindObjectOfType<T>();
|
||||
// }
|
||||
|
||||
// public T[] FindAll<T>() where T : Object
|
||||
// {
|
||||
// return FindObjectsOfType<T>();
|
||||
// }
|
||||
|
||||
// public object RunCoroutine(IEnumerator enumerator)
|
||||
// {
|
||||
// return MelonCoroutines.Start(enumerator);
|
||||
// }
|
||||
|
||||
// public void EndCoroutine(Coroutine c)
|
||||
// {
|
||||
// StopCoroutine(c);
|
||||
// }
|
||||
// }
|
||||
//}
|
@ -1,224 +0,0 @@
|
||||
//using System;
|
||||
//using System.Collections;
|
||||
//using System.Collections.Generic;
|
||||
//using System.Linq;
|
||||
//using System.Text;
|
||||
//using System.Threading.Tasks;
|
||||
//using UnityEngine;
|
||||
//using System.Reflection;
|
||||
//using Mono.CSharp;
|
||||
//using System.IO;
|
||||
//using MelonLoader;
|
||||
|
||||
//namespace Explorer
|
||||
//{
|
||||
// public class ConsolePage : MainMenu.WindowPage
|
||||
// {
|
||||
// public override string Name { get => "Console"; set => base.Name = value; }
|
||||
|
||||
// private ScriptEvaluator _evaluator;
|
||||
// private readonly StringBuilder _sb = new StringBuilder();
|
||||
|
||||
// private string MethodInput = "";
|
||||
// private string UsingInput = "";
|
||||
|
||||
// public static List<string> UsingDirectives;
|
||||
|
||||
// private static readonly string[] m_defaultUsing = new string[]
|
||||
// {
|
||||
// "System",
|
||||
// "UnityEngine",
|
||||
// "System.Linq",
|
||||
// "System.Collections",
|
||||
// "System.Collections.Generic",
|
||||
// "System.Reflection"
|
||||
// };
|
||||
|
||||
// public override void Init()
|
||||
// {
|
||||
// try
|
||||
// {
|
||||
// MethodInput = @"// This is a basic REPL console used to execute a method.
|
||||
//// Some common directives are added by default, you can add more below.
|
||||
//// If you want to return some output, Debug.Log() it.
|
||||
|
||||
//Debug.Log(""hello world"");";
|
||||
|
||||
// ResetConsole();
|
||||
// }
|
||||
// catch (Exception e)
|
||||
// {
|
||||
// MelonLogger.Log($"Error setting up console!\r\nMessage: {e.Message}\r\nStack: {e.StackTrace}");
|
||||
// }
|
||||
// }
|
||||
|
||||
// public void ResetConsole()
|
||||
// {
|
||||
// if (_evaluator != null)
|
||||
// {
|
||||
// _evaluator.Dispose();
|
||||
// }
|
||||
|
||||
// _evaluator = new ScriptEvaluator(new StringWriter(_sb)) { InteractiveBaseClass = typeof(REPL) };
|
||||
|
||||
// UsingDirectives = new List<string>();
|
||||
// UsingDirectives.AddRange(m_defaultUsing);
|
||||
// foreach (string asm in UsingDirectives)
|
||||
// {
|
||||
// Evaluate(AsmToUsing(asm));
|
||||
// }
|
||||
// }
|
||||
|
||||
// public string AsmToUsing(string asm, bool richtext = false)
|
||||
// {
|
||||
// if (richtext)
|
||||
// {
|
||||
// return $"<color=#569cd6>using</color> {asm};";
|
||||
// }
|
||||
// return $"using {asm};";
|
||||
// }
|
||||
|
||||
// public void AddUsing(string asm)
|
||||
// {
|
||||
// if (!UsingDirectives.Contains(asm))
|
||||
// {
|
||||
// UsingDirectives.Add(asm);
|
||||
// Evaluate(AsmToUsing(asm));
|
||||
// }
|
||||
// }
|
||||
|
||||
// public object Evaluate(string str)
|
||||
// {
|
||||
// object ret = VoidType.Value;
|
||||
|
||||
// _evaluator.Compile(str, out var compiled);
|
||||
|
||||
// try
|
||||
// {
|
||||
// compiled?.Invoke(ref ret);
|
||||
// }
|
||||
// catch (Exception e)
|
||||
// {
|
||||
// MelonLogger.LogWarning(e.ToString());
|
||||
// }
|
||||
|
||||
// return ret;
|
||||
// }
|
||||
|
||||
|
||||
// public override void DrawWindow()
|
||||
// {
|
||||
// GUILayout.Label("<b><size=15><color=cyan>REPL Console</color></size></b>", null);
|
||||
|
||||
// GUILayout.Label("Method:", null);
|
||||
// MethodInput = GUILayout.TextArea(MethodInput, new GUILayoutOption[] { GUILayout.Height(300) });
|
||||
|
||||
// if (GUILayout.Button("<color=cyan><b>Execute</b></color>", null))
|
||||
// {
|
||||
// try
|
||||
// {
|
||||
// MethodInput = MethodInput.Trim();
|
||||
|
||||
// if (!string.IsNullOrEmpty(MethodInput))
|
||||
// {
|
||||
// var result = Evaluate(MethodInput);
|
||||
|
||||
// if (result != null && !Equals(result, VoidType.Value))
|
||||
// {
|
||||
// MelonLogger.Log("[Console Output]\r\n" + result.ToString());
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// catch (Exception e)
|
||||
// {
|
||||
// MelonLogger.LogError("Exception compiling!\r\nMessage: " + e.Message + "\r\nStack: " + e.StackTrace);
|
||||
// }
|
||||
// }
|
||||
|
||||
// GUILayout.Label("<b>Using directives:</b>", null);
|
||||
// foreach (var asm in UsingDirectives)
|
||||
// {
|
||||
// GUILayout.Label(AsmToUsing(asm, true), null);
|
||||
// }
|
||||
// GUILayout.BeginHorizontal(null);
|
||||
// GUILayout.Label("Add namespace:", new GUILayoutOption[] { GUILayout.Width(110) });
|
||||
// UsingInput = GUILayout.TextField(UsingInput, new GUILayoutOption[] { GUILayout.Width(150) });
|
||||
// if (GUILayout.Button("Add", new GUILayoutOption[] { GUILayout.Width(50) }))
|
||||
// {
|
||||
// AddUsing(UsingInput);
|
||||
// }
|
||||
// if (GUILayout.Button("<color=red>Reset</color>", null))
|
||||
// {
|
||||
// ResetConsole();
|
||||
// }
|
||||
// GUILayout.EndHorizontal();
|
||||
// }
|
||||
|
||||
// public override void Update() { }
|
||||
|
||||
// private class VoidType
|
||||
// {
|
||||
// public static readonly VoidType Value = new VoidType();
|
||||
// private VoidType() { }
|
||||
// }
|
||||
|
||||
// }
|
||||
|
||||
// internal class ScriptEvaluator : Evaluator, IDisposable
|
||||
// {
|
||||
// private static readonly HashSet<string> StdLib =
|
||||
// new HashSet<string>(StringComparer.InvariantCultureIgnoreCase) { "mscorlib", "System.Core", "System", "System.Xml" };
|
||||
|
||||
// private readonly TextWriter _logger;
|
||||
|
||||
// public ScriptEvaluator(TextWriter logger) : base(BuildContext(logger))
|
||||
// {
|
||||
// _logger = logger;
|
||||
|
||||
// ImportAppdomainAssemblies(ReferenceAssembly);
|
||||
// AppDomain.CurrentDomain.AssemblyLoad += OnAssemblyLoad;
|
||||
// }
|
||||
|
||||
// public void Dispose()
|
||||
// {
|
||||
// AppDomain.CurrentDomain.AssemblyLoad -= OnAssemblyLoad;
|
||||
// _logger.Dispose();
|
||||
// }
|
||||
|
||||
// private void OnAssemblyLoad(object sender, AssemblyLoadEventArgs args)
|
||||
// {
|
||||
// string name = args.LoadedAssembly.GetName().Name;
|
||||
// if (StdLib.Contains(name))
|
||||
// return;
|
||||
// ReferenceAssembly(args.LoadedAssembly);
|
||||
// }
|
||||
|
||||
// private static CompilerContext BuildContext(TextWriter tw)
|
||||
// {
|
||||
// var reporter = new StreamReportPrinter(tw);
|
||||
|
||||
// var settings = new CompilerSettings
|
||||
// {
|
||||
// Version = LanguageVersion.Experimental,
|
||||
// GenerateDebugInfo = false,
|
||||
// StdLib = true,
|
||||
// Target = Target.Library,
|
||||
// WarningLevel = 0,
|
||||
// EnhancedWarnings = false
|
||||
// };
|
||||
|
||||
// return new CompilerContext(settings, reporter);
|
||||
// }
|
||||
|
||||
// private static void ImportAppdomainAssemblies(Action<Assembly> import)
|
||||
// {
|
||||
// foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
|
||||
// {
|
||||
// string name = assembly.GetName().Name;
|
||||
// if (StdLib.Contains(name))
|
||||
// continue;
|
||||
// import(assembly);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//}
|
@ -1,219 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using MelonLoader;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
|
||||
namespace Explorer
|
||||
{
|
||||
public class ScenePage : MainMenu.WindowPage
|
||||
{
|
||||
public static ScenePage Instance;
|
||||
|
||||
public override string Name { get => "Scene Explorer"; set => base.Name = value; }
|
||||
|
||||
// ----- Holders for GUI elements ----- //
|
||||
|
||||
private string m_currentScene = "";
|
||||
|
||||
// gameobject list
|
||||
private Transform m_currentTransform;
|
||||
private List<GameObject> m_objectList = new List<GameObject>();
|
||||
|
||||
// search bar
|
||||
private bool m_searching = false;
|
||||
private string m_searchInput = "";
|
||||
private List<GameObject> m_searchResults = new List<GameObject>();
|
||||
|
||||
// ------------ Init and Update ------------ //
|
||||
|
||||
public override void Init()
|
||||
{
|
||||
Instance = this;
|
||||
}
|
||||
|
||||
public void OnSceneChange()
|
||||
{
|
||||
m_currentScene = CppExplorer.ActiveSceneName;
|
||||
|
||||
m_currentTransform = null;
|
||||
CancelSearch();
|
||||
|
||||
}
|
||||
|
||||
public override void Update()
|
||||
{
|
||||
if (!m_searching)
|
||||
{
|
||||
m_objectList = new List<GameObject>();
|
||||
if (m_currentTransform)
|
||||
{
|
||||
var noChildren = new List<GameObject>();
|
||||
for (int i = 0; i < m_currentTransform.childCount; i++)
|
||||
{
|
||||
var child = m_currentTransform.GetChild(i);
|
||||
|
||||
if (child)
|
||||
{
|
||||
if (child.childCount > 0)
|
||||
m_objectList.Add(child.gameObject);
|
||||
else
|
||||
noChildren.Add(child.gameObject);
|
||||
}
|
||||
}
|
||||
m_objectList.AddRange(noChildren);
|
||||
noChildren = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
var scene = SceneManager.GetActiveScene();
|
||||
var rootObjects = scene.GetRootGameObjects();
|
||||
|
||||
// add objects with children first
|
||||
foreach (var obj in rootObjects.Where(x => x.transform.childCount > 0))
|
||||
{
|
||||
m_objectList.Add(obj);
|
||||
}
|
||||
foreach (var obj in rootObjects.Where(x => x.transform.childCount == 0))
|
||||
{
|
||||
m_objectList.Add(obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// --------- GUI Draw Functions --------- //
|
||||
|
||||
public override void DrawWindow()
|
||||
{
|
||||
try
|
||||
{
|
||||
// Current Scene label
|
||||
GUILayout.Label("Current Scene: <color=cyan>" + m_currentScene + "</color>", null);
|
||||
|
||||
// ----- GameObject Search -----
|
||||
GUILayout.BeginHorizontal(GUI.skin.box, null);
|
||||
GUILayout.Label("<b>Search Scene:</b>", new GUILayoutOption[] { GUILayout.Width(100) });
|
||||
m_searchInput = GUILayout.TextField(m_searchInput, null);
|
||||
if (GUILayout.Button("Search", new GUILayoutOption[] { GUILayout.Width(80) }))
|
||||
{
|
||||
Search();
|
||||
}
|
||||
GUILayout.EndHorizontal();
|
||||
|
||||
GUILayout.Space(15);
|
||||
|
||||
// ************** GameObject list ***************
|
||||
|
||||
// ----- main explorer ------
|
||||
if (!m_searching)
|
||||
{
|
||||
if (m_currentTransform != null)
|
||||
{
|
||||
GUILayout.BeginHorizontal(null);
|
||||
if (GUILayout.Button("<-", new GUILayoutOption[] { GUILayout.Width(35) }))
|
||||
{
|
||||
TraverseUp();
|
||||
}
|
||||
else
|
||||
{
|
||||
GUILayout.Label(CppExplorer.GetGameObjectPath(m_currentTransform), null);
|
||||
}
|
||||
GUILayout.EndHorizontal();
|
||||
}
|
||||
else
|
||||
{
|
||||
GUILayout.Label("Scene Root GameObjects:", null);
|
||||
}
|
||||
|
||||
if (m_objectList.Count > 0)
|
||||
{
|
||||
foreach (var obj in m_objectList)
|
||||
{
|
||||
UIStyles.GameobjButton(obj, SetTransformTarget, true, MainMenu.MainRect.width - 170);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// if m_currentTransform != null ...
|
||||
}
|
||||
}
|
||||
else // ------ Scene Search results ------
|
||||
{
|
||||
if (GUILayout.Button("<-", new GUILayoutOption[] { GUILayout.Width(35) }))
|
||||
{
|
||||
CancelSearch();
|
||||
}
|
||||
|
||||
GUILayout.Label("Search Results:", null);
|
||||
|
||||
if (m_searchResults.Count > 0)
|
||||
{
|
||||
foreach (var obj in m_searchResults)
|
||||
{
|
||||
UIStyles.GameobjButton(obj, SetTransformTarget, true, MainMenu.MainRect.width - 170);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
GUILayout.Label("<color=red><i>No results found!</i></color>", null);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
m_currentTransform = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// -------- Actual Methods (not drawing GUI) ---------- //
|
||||
|
||||
public void SetTransformTarget(GameObject obj)
|
||||
{
|
||||
m_currentTransform = obj.transform;
|
||||
CancelSearch();
|
||||
}
|
||||
|
||||
public void TraverseUp()
|
||||
{
|
||||
if (m_currentTransform.parent != null)
|
||||
{
|
||||
m_currentTransform = m_currentTransform.parent;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_currentTransform = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void Search()
|
||||
{
|
||||
m_searchResults = SearchSceneObjects(m_searchInput);
|
||||
m_searching = true;
|
||||
}
|
||||
|
||||
public void CancelSearch()
|
||||
{
|
||||
m_searching = false;
|
||||
}
|
||||
|
||||
public List<GameObject> SearchSceneObjects(string _search)
|
||||
{
|
||||
var matches = new List<GameObject>();
|
||||
|
||||
foreach (var obj in Resources.FindObjectsOfTypeAll<GameObject>())
|
||||
{
|
||||
if (obj.name.ToLower().Contains(_search.ToLower()) && obj.scene.name == CppExplorer.ActiveSceneName)
|
||||
{
|
||||
matches.Add(obj);
|
||||
}
|
||||
}
|
||||
|
||||
return matches;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,434 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using System.Reflection;
|
||||
using UnityEngine.SceneManagement;
|
||||
using Object = UnityEngine.Object;
|
||||
using UnhollowerRuntimeLib;
|
||||
using MelonLoader;
|
||||
using UnhollowerBaseLib;
|
||||
|
||||
namespace Explorer
|
||||
{
|
||||
public class SearchPage : MainMenu.WindowPage
|
||||
{
|
||||
public static SearchPage Instance;
|
||||
|
||||
public override string Name { get => "Advanced Search"; set => base.Name = value; }
|
||||
|
||||
private string m_searchInput = "";
|
||||
private string m_typeInput = "";
|
||||
private int m_limit = 100;
|
||||
|
||||
public SceneFilter SceneMode = SceneFilter.Any;
|
||||
public TypeFilter TypeMode = TypeFilter.Object;
|
||||
|
||||
public enum SceneFilter
|
||||
{
|
||||
Any,
|
||||
This,
|
||||
DontDestroy,
|
||||
None
|
||||
}
|
||||
|
||||
public enum TypeFilter
|
||||
{
|
||||
Object,
|
||||
GameObject,
|
||||
Component,
|
||||
Custom
|
||||
}
|
||||
|
||||
private List<object> m_searchResults = new List<object>();
|
||||
private Vector2 resultsScroll = Vector2.zero;
|
||||
|
||||
public override void Init()
|
||||
{
|
||||
Instance = this;
|
||||
}
|
||||
|
||||
public void OnSceneChange()
|
||||
{
|
||||
m_searchResults.Clear();
|
||||
}
|
||||
|
||||
public override void Update()
|
||||
{
|
||||
}
|
||||
|
||||
public override void DrawWindow()
|
||||
{
|
||||
try
|
||||
{
|
||||
// helpers
|
||||
GUILayout.BeginHorizontal(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) }))
|
||||
{
|
||||
m_searchResults = GetInstanceClassScanner().ToList();
|
||||
}
|
||||
GUILayout.EndHorizontal();
|
||||
|
||||
// search box
|
||||
SearchBox();
|
||||
|
||||
// results
|
||||
GUILayout.BeginVertical(GUI.skin.box, null);
|
||||
|
||||
GUI.skin.label.alignment = TextAnchor.MiddleCenter;
|
||||
GUILayout.Label("<b><color=orange>Results</color></b>", null);
|
||||
GUI.skin.label.alignment = TextAnchor.UpperLeft;
|
||||
|
||||
resultsScroll = GUILayout.BeginScrollView(resultsScroll, GUI.skin.scrollView);
|
||||
|
||||
var _temprect = new Rect(MainMenu.MainRect.x, MainMenu.MainRect.y, MainMenu.MainRect.width + 160, MainMenu.MainRect.height);
|
||||
|
||||
if (m_searchResults.Count > 0)
|
||||
{
|
||||
for (int i = 0; i < m_searchResults.Count; i++)
|
||||
{
|
||||
var obj = m_searchResults[i];
|
||||
|
||||
UIStyles.DrawValue(ref obj, _temprect);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
GUILayout.Label("<color=red><i>No results found!</i></color>", null);
|
||||
}
|
||||
|
||||
GUILayout.EndScrollView();
|
||||
|
||||
GUILayout.EndVertical();
|
||||
}
|
||||
catch
|
||||
{
|
||||
m_searchResults.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
private void SearchBox()
|
||||
{
|
||||
GUILayout.BeginVertical(GUI.skin.box, null);
|
||||
|
||||
// ----- GameObject Search -----
|
||||
GUI.skin.label.alignment = TextAnchor.MiddleCenter;
|
||||
GUILayout.Label("<b><color=orange>Search</color></b>", null);
|
||||
GUI.skin.label.alignment = TextAnchor.UpperLeft;
|
||||
|
||||
GUILayout.BeginHorizontal(null);
|
||||
|
||||
GUILayout.Label("Name Contains:", new GUILayoutOption[] { GUILayout.Width(100) });
|
||||
m_searchInput = GUILayout.TextField(m_searchInput, new GUILayoutOption[] { GUILayout.Width(200) });
|
||||
|
||||
GUI.skin.label.alignment = TextAnchor.MiddleRight;
|
||||
GUILayout.Label("Result limit:", new GUILayoutOption[] { GUILayout.Width(100) });
|
||||
var resultinput = m_limit.ToString();
|
||||
resultinput = GUILayout.TextField(resultinput, new GUILayoutOption[] { GUILayout.Width(55) });
|
||||
if (int.TryParse(resultinput, out int _i) && _i > 0)
|
||||
{
|
||||
m_limit = _i;
|
||||
}
|
||||
GUI.skin.label.alignment = TextAnchor.UpperLeft;
|
||||
|
||||
GUILayout.EndHorizontal();
|
||||
|
||||
GUILayout.BeginHorizontal(null);
|
||||
|
||||
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)
|
||||
{
|
||||
GUILayout.BeginHorizontal(null);
|
||||
GUI.skin.label.alignment = TextAnchor.MiddleRight;
|
||||
GUILayout.Label("Custom Class:", new GUILayoutOption[] { GUILayout.Width(250) });
|
||||
GUI.skin.label.alignment = TextAnchor.UpperLeft;
|
||||
m_typeInput = GUILayout.TextField(m_typeInput, new GUILayoutOption[] { GUILayout.Width(250) });
|
||||
GUILayout.EndHorizontal();
|
||||
}
|
||||
|
||||
GUILayout.BeginHorizontal(null);
|
||||
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>", null))
|
||||
{
|
||||
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) ----------------- //
|
||||
|
||||
// credit: ManlyMarco (RuntimeUnityEditor)
|
||||
public static IEnumerable<object> GetInstanceClassScanner()
|
||||
{
|
||||
var query = AppDomain.CurrentDomain.GetAssemblies()
|
||||
.Where(x => !x.FullName.StartsWith("Mono"))
|
||||
.SelectMany(GetTypesSafe)
|
||||
.Where(t => t.IsClass && !t.IsAbstract && !t.ContainsGenericParameters);
|
||||
|
||||
foreach (var type in query)
|
||||
{
|
||||
object obj = null;
|
||||
try
|
||||
{
|
||||
obj = type.GetProperty("Instance", BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy)?.GetValue(null, null);
|
||||
}
|
||||
catch
|
||||
{
|
||||
try
|
||||
{
|
||||
obj = type.GetField("Instance", BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy)?.GetValue(null);
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
if (obj != null && !obj.ToString().StartsWith("Mono"))
|
||||
{
|
||||
yield return obj;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static IEnumerable<Type> GetTypesSafe(Assembly asm)
|
||||
{
|
||||
try { return asm.GetTypes(); }
|
||||
catch (ReflectionTypeLoadException e) { return e.Types.Where(x => x != null); }
|
||||
catch { return Enumerable.Empty<Type>(); }
|
||||
}
|
||||
|
||||
// ======= search functions =======
|
||||
|
||||
private void Search()
|
||||
{
|
||||
m_searchResults = FindAllObjectsOfType(m_searchInput, m_typeInput);
|
||||
}
|
||||
|
||||
private List<object> FindAllObjectsOfType(string _search, string _type)
|
||||
{
|
||||
Il2CppSystem.Type type = null;
|
||||
|
||||
if (TypeMode == TypeFilter.Custom)
|
||||
{
|
||||
try
|
||||
{
|
||||
var findType = CppExplorer.GetType(_type);
|
||||
type = Il2CppSystem.Type.GetType(findType.AssemblyQualifiedName);
|
||||
MelonLogger.Log("Got type: " + type.AssemblyQualifiedName);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
MelonLogger.Log("Exception: " + e.GetType() + ", " + e.Message + "\r\n" + e.StackTrace);
|
||||
}
|
||||
}
|
||||
else if (TypeMode == TypeFilter.Object)
|
||||
{
|
||||
type = Il2CppType.Of<Object>();
|
||||
}
|
||||
else if (TypeMode == TypeFilter.GameObject)
|
||||
{
|
||||
type = Il2CppType.Of<GameObject>();
|
||||
}
|
||||
else if (TypeMode == TypeFilter.Component)
|
||||
{
|
||||
type = Il2CppType.Of<Component>();
|
||||
}
|
||||
|
||||
if (!Il2CppType.Of<Object>().IsAssignableFrom(type))
|
||||
{
|
||||
MelonLogger.LogError("Your Class Type must inherit from UnityEngine.Object! Leave blank to default to UnityEngine.Object");
|
||||
return new List<object>();
|
||||
}
|
||||
|
||||
var matches = new List<object>();
|
||||
int added = 0;
|
||||
|
||||
//MelonLogger.Log("Trying to get IL Type. ASM name: " + type.Assembly.GetName().Name + ", Namespace: " + type.Namespace + ", name: " + type.Name);
|
||||
|
||||
//var asmName = type.Assembly.GetName().Name;
|
||||
//if (asmName.Contains("UnityEngine"))
|
||||
//{
|
||||
// asmName = "UnityEngine";
|
||||
//}
|
||||
|
||||
//var intPtr = IL2CPP.GetIl2CppClass(asmName, type.Namespace, type.Name);
|
||||
//var ilType = Il2CppType.TypeFromPointer(intPtr);
|
||||
|
||||
foreach (var obj in Resources.FindObjectsOfTypeAll(type))
|
||||
{
|
||||
if (added == m_limit)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (_search != "" && !obj.name.ToLower().Contains(_search.ToLower()))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (SceneMode != SceneFilter.Any)
|
||||
{
|
||||
if (SceneMode == SceneFilter.None)
|
||||
{
|
||||
if (!NoSceneFilter(obj, obj.GetType()))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
GameObject go;
|
||||
|
||||
var objtype = obj.GetType();
|
||||
if (objtype == typeof(GameObject))
|
||||
{
|
||||
go = obj as GameObject;
|
||||
}
|
||||
else if (typeof(Component).IsAssignableFrom(objtype))
|
||||
{
|
||||
go = (obj as Component).gameObject;
|
||||
}
|
||||
else { continue; }
|
||||
|
||||
if (!go) { continue; }
|
||||
|
||||
if (SceneMode == SceneFilter.This)
|
||||
{
|
||||
if (go.scene.name != CppExplorer.ActiveSceneName || go.scene.name == "DontDestroyOnLoad")
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (SceneMode == SceneFilter.DontDestroy)
|
||||
{
|
||||
if (go.scene.name != "DontDestroyOnLoad")
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!matches.Contains(obj))
|
||||
{
|
||||
matches.Add(obj);
|
||||
added++;
|
||||
}
|
||||
}
|
||||
|
||||
return matches;
|
||||
}
|
||||
|
||||
public static bool ThisSceneFilter(object obj, Type type)
|
||||
{
|
||||
if (type == typeof(GameObject) || typeof(Component).IsAssignableFrom(type))
|
||||
{
|
||||
var go = obj as GameObject ?? (obj as Component).gameObject;
|
||||
|
||||
if (go != null && go.scene.name == CppExplorer.ActiveSceneName && go.scene.name != "DontDestroyOnLoad")
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool DontDestroyFilter(object obj, Type type)
|
||||
{
|
||||
if (type == typeof(GameObject) || typeof(Component).IsAssignableFrom(type))
|
||||
{
|
||||
var go = obj as GameObject ?? (obj as Component).gameObject;
|
||||
|
||||
if (go != null && go.scene.name == "DontDestroyOnLoad")
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool NoSceneFilter(object obj, Type type)
|
||||
{
|
||||
if (type == typeof(GameObject))
|
||||
{
|
||||
var go = obj as GameObject;
|
||||
|
||||
if (go.scene.name != CppExplorer.ActiveSceneName && go.scene.name != "DontDestroyOnLoad")
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (typeof(Component).IsAssignableFrom(type))
|
||||
{
|
||||
var go = (obj as Component).gameObject;
|
||||
|
||||
if (go == null || (go.scene.name != CppExplorer.ActiveSceneName && go.scene.name != "DontDestroyOnLoad"))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user