mirror of
https://github.com/GrahamKracker/UnityExplorer.git
synced 2025-07-16 00:07:52 +08:00
WIP
* Using publicized mono assemblies * Remaking UI from scratch. Done the Scene Explorer so far.
This commit is contained in:
@ -5,9 +5,6 @@ using UnityEngine;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityExplorer.Core.Runtime;
|
||||
using UnityExplorer.UI.Main.CSConsole;
|
||||
using UnityExplorer.UI.Main.Home;
|
||||
using UnityExplorer.UI.Inspectors;
|
||||
|
||||
namespace UnityExplorer.Core.CSharp
|
||||
{
|
||||
@ -23,45 +20,45 @@ namespace UnityExplorer.Core.CSharp
|
||||
RuntimeProvider.Instance.StartCoroutine(ienumerator);
|
||||
}
|
||||
|
||||
public static void AddUsing(string directive)
|
||||
{
|
||||
CSharpConsole.Instance.AddUsing(directive);
|
||||
}
|
||||
//public static void AddUsing(string directive)
|
||||
//{
|
||||
// CSharpConsole.Instance.AddUsing(directive);
|
||||
//}
|
||||
|
||||
public static void GetUsing()
|
||||
{
|
||||
ExplorerCore.Log(CSharpConsole.Instance.Evaluator.GetUsing());
|
||||
}
|
||||
//public static void GetUsing()
|
||||
//{
|
||||
// ExplorerCore.Log(CSharpConsole.Instance.Evaluator.GetUsing());
|
||||
//}
|
||||
|
||||
public static void Reset()
|
||||
{
|
||||
CSharpConsole.Instance.ResetConsole();
|
||||
}
|
||||
//public static void Reset()
|
||||
//{
|
||||
// CSharpConsole.Instance.ResetConsole();
|
||||
//}
|
||||
|
||||
public static object CurrentTarget()
|
||||
{
|
||||
return InspectorManager.Instance?.m_activeInspector?.Target;
|
||||
}
|
||||
//public static object CurrentTarget()
|
||||
//{
|
||||
// return InspectorManager.Instance?.m_activeInspector?.Target;
|
||||
//}
|
||||
|
||||
public static object[] AllTargets()
|
||||
{
|
||||
int count = InspectorManager.Instance?.m_currentInspectors.Count ?? 0;
|
||||
object[] ret = new object[count];
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
ret[i] = InspectorManager.Instance?.m_currentInspectors[i].Target;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
//public static object[] AllTargets()
|
||||
//{
|
||||
// int count = InspectorManager.Instance?.m_currentInspectors.Count ?? 0;
|
||||
// object[] ret = new object[count];
|
||||
// for (int i = 0; i < count; i++)
|
||||
// {
|
||||
// ret[i] = InspectorManager.Instance?.m_currentInspectors[i].Target;
|
||||
// }
|
||||
// return ret;
|
||||
//}
|
||||
|
||||
public static void Inspect(object obj)
|
||||
{
|
||||
InspectorManager.Instance.Inspect(obj);
|
||||
}
|
||||
//public static void Inspect(object obj)
|
||||
//{
|
||||
// InspectorManager.Instance.Inspect(obj);
|
||||
//}
|
||||
|
||||
public static void Inspect(Type type)
|
||||
{
|
||||
InspectorManager.Instance.Inspect(type);
|
||||
}
|
||||
//public static void Inspect(Type type)
|
||||
//{
|
||||
// InspectorManager.Instance.Inspect(type);
|
||||
//}
|
||||
}
|
||||
}
|
@ -4,7 +4,6 @@ using System.Linq;
|
||||
using System.Reflection;
|
||||
using UnityEngine;
|
||||
using UnityExplorer.Core;
|
||||
using UnityExplorer.UI.Main.CSConsole;
|
||||
|
||||
namespace UnityExplorer.Core.CSharp
|
||||
{
|
||||
@ -49,8 +48,8 @@ namespace UnityExplorer.Core.CSharp
|
||||
public static HashSet<string> Namespaces => m_namespaces ?? GetNamespaces();
|
||||
private static HashSet<string> m_namespaces;
|
||||
|
||||
public static HashSet<string> Keywords => m_keywords ?? (m_keywords = new HashSet<string>(CSLexerHighlighter.validKeywordMatcher.Keywords));
|
||||
private static HashSet<string> m_keywords;
|
||||
public static HashSet<string> Keywords => throw new NotImplementedException("TODO!"); // m_keywords ?? (m_keywords = new HashSet<string>(CSLexerHighlighter.validKeywordMatcher.Keywords));
|
||||
//private static HashSet<string> m_keywords;
|
||||
|
||||
private static readonly Color keywordColor = new Color(80f / 255f, 150f / 255f, 215f / 255f);
|
||||
|
||||
|
@ -6,8 +6,6 @@ using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityExplorer.UI.Main;
|
||||
using UnityExplorer.UI.Main.Home;
|
||||
|
||||
namespace UnityExplorer.Core.Config
|
||||
{
|
||||
@ -19,7 +17,7 @@ namespace UnityExplorer.Core.Config
|
||||
|
||||
public static ConfigElement<KeyCode> Main_Menu_Toggle;
|
||||
public static ConfigElement<bool> Force_Unlock_Mouse;
|
||||
public static ConfigElement<MenuPages> Default_Tab;
|
||||
//public static ConfigElement<MenuPages> Default_Tab;
|
||||
public static ConfigElement<int> Default_Page_Limit;
|
||||
public static ConfigElement<string> Default_Output_Path;
|
||||
public static ConfigElement<bool> Log_Unity_Debug;
|
||||
@ -42,10 +40,10 @@ namespace UnityExplorer.Core.Config
|
||||
|
||||
Handler.LoadConfig();
|
||||
|
||||
SceneExplorer.OnToggleShow += SceneExplorer_OnToggleShow;
|
||||
PanelDragger.OnFinishResize += PanelDragger_OnFinishResize;
|
||||
PanelDragger.OnFinishDrag += PanelDragger_OnFinishDrag;
|
||||
DebugConsole.OnToggleShow += DebugConsole_OnToggleShow;
|
||||
//SceneExplorer.OnToggleShow += SceneExplorer_OnToggleShow;
|
||||
//PanelDragger.OnFinishResize += PanelDragger_OnFinishResize;
|
||||
//PanelDragger.OnFinishDrag += PanelDragger_OnFinishDrag;
|
||||
//DebugConsole.OnToggleShow += DebugConsole_OnToggleShow;
|
||||
|
||||
InitConsoleCallback();
|
||||
}
|
||||
@ -66,9 +64,9 @@ namespace UnityExplorer.Core.Config
|
||||
"Should UnityExplorer be hidden on startup?",
|
||||
false);
|
||||
|
||||
Default_Tab = new ConfigElement<MenuPages>("Default Tab",
|
||||
"The default menu page when starting the game.",
|
||||
MenuPages.Home);
|
||||
//Default_Tab = new ConfigElement<MenuPages>("Default Tab",
|
||||
// "The default menu page when starting the game.",
|
||||
// MenuPages.Home);
|
||||
|
||||
Log_Unity_Debug = new ConfigElement<bool>("Log Unity Debug",
|
||||
"Should UnityEngine.Debug.Log messages be printed to UnityExplorer's log?",
|
||||
|
@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using UnityExplorer.Core.Unity;
|
||||
using UnityEngine.EventSystems;
|
||||
using UnityExplorer.Core.Input;
|
||||
using BF = System.Reflection.BindingFlags;
|
||||
|
@ -1,11 +1,9 @@
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using UnityExplorer.Core.Unity;
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
using UnityExplorer.UI;
|
||||
using System.Collections.Generic;
|
||||
using UnityExplorer.UI.Inspectors;
|
||||
using System.Linq;
|
||||
|
||||
namespace UnityExplorer.Core.Input
|
||||
@ -164,13 +162,13 @@ namespace UnityExplorer.Core.Input
|
||||
var assetType = ReflectionUtility.GetTypeByName("UnityEngine.InputSystem.InputActionAsset");
|
||||
m_newInputModule = RuntimeProvider.Instance.AddComponent<BaseInputModule>(UIManager.CanvasRoot, TInputSystemUIInputModule);
|
||||
var asset = RuntimeProvider.Instance.CreateScriptable(assetType)
|
||||
.Cast(assetType);
|
||||
.TryCast(assetType);
|
||||
|
||||
inputExtensions = ReflectionUtility.GetTypeByName("UnityEngine.InputSystem.InputActionSetupExtensions");
|
||||
|
||||
var addMap = inputExtensions.GetMethod("AddActionMap", new Type[] { assetType, typeof(string) });
|
||||
var map = addMap.Invoke(null, new object[] { asset, "UI" })
|
||||
.Cast(ReflectionUtility.GetTypeByName("UnityEngine.InputSystem.InputActionMap"));
|
||||
.TryCast(ReflectionUtility.GetTypeByName("UnityEngine.InputSystem.InputActionMap"));
|
||||
|
||||
CreateAction(map, "point", new[] { "<Mouse>/position" }, "point");
|
||||
CreateAction(map, "click", new[] { "<Mouse>/leftButton" }, "leftClick");
|
||||
@ -191,22 +189,22 @@ namespace UnityExplorer.Core.Input
|
||||
var inputActionType = ReflectionUtility.GetTypeByName("UnityEngine.InputSystem.InputAction");
|
||||
var addAction = inputExtensions.GetMethod("AddAction");
|
||||
var action = addAction.Invoke(null, new object[] { map, actionName, default, null, null, null, null, null })
|
||||
.Cast(inputActionType);
|
||||
.TryCast(inputActionType);
|
||||
|
||||
var addBinding = inputExtensions.GetMethod("AddBinding",
|
||||
new Type[] { inputActionType, typeof(string), typeof(string), typeof(string), typeof(string) });
|
||||
|
||||
foreach (string binding in bindings)
|
||||
addBinding.Invoke(null, new object[] { action.Cast(inputActionType), binding, null, null, null });
|
||||
addBinding.Invoke(null, new object[] { action.TryCast(inputActionType), binding, null, null, null });
|
||||
|
||||
var refType = ReflectionUtility.GetTypeByName("UnityEngine.InputSystem.InputActionReference");
|
||||
var inputRef = refType.GetMethod("Create")
|
||||
.Invoke(null, new object[] { action })
|
||||
.Cast(refType);
|
||||
.TryCast(refType);
|
||||
|
||||
TInputSystemUIInputModule
|
||||
.GetProperty(propertyName)
|
||||
.SetValue(m_newInputModule.Cast(TInputSystemUIInputModule), inputRef, null);
|
||||
.SetValue(m_newInputModule.TryCast(TInputSystemUIInputModule), inputRef, null);
|
||||
}
|
||||
|
||||
public void ActivateModule()
|
||||
|
@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using UnityExplorer.Core.Unity;
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
using UnityExplorer.UI;
|
||||
|
@ -13,6 +13,36 @@ namespace UnityExplorer
|
||||
{
|
||||
public const BF AllFlags = BF.Public | BF.Instance | BF.NonPublic | BF.Static;
|
||||
|
||||
public static void Test()
|
||||
{
|
||||
AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(AssemblyResolver);
|
||||
}
|
||||
|
||||
private static Assembly AssemblyResolver(object sender, ResolveEventArgs args)
|
||||
{
|
||||
if (args.Name.StartsWith("UnityExplorer"))
|
||||
return typeof(ExplorerCore).Assembly;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static bool ValueEqual<T>(this T objA, T objB)
|
||||
{
|
||||
return (objA == null && objB == null) || (objA != null && objA.Equals(objB));
|
||||
}
|
||||
|
||||
public static bool ReferenceEqual(this object objA, object objB)
|
||||
{
|
||||
if (objA.TryCast<UnityEngine.Object>() is UnityEngine.Object unityA)
|
||||
{
|
||||
var unityB = objB.TryCast<UnityEngine.Object>();
|
||||
if (unityB && unityA.m_CachedPtr == unityB.m_CachedPtr)
|
||||
return true;
|
||||
}
|
||||
|
||||
return object.ReferenceEquals(objA, objB);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper for IL2CPP to get the underlying true Type (Unhollowed) of the object.
|
||||
/// </summary>
|
||||
@ -31,7 +61,7 @@ namespace UnityExplorer
|
||||
/// </summary>
|
||||
/// <param name="obj">The object to cast</param>
|
||||
/// <returns>The object, cast to the underlying Type if possible, otherwise the original object.</returns>
|
||||
public static object Cast(this object obj)
|
||||
public static object TryCast(this object obj)
|
||||
=> ReflectionProvider.Instance.Cast(obj, GetActualType(obj));
|
||||
|
||||
/// <summary>
|
||||
@ -40,7 +70,7 @@ namespace UnityExplorer
|
||||
/// <param name="obj">The object to cast</param>
|
||||
/// <param name="castTo">The Type to cast to </param>
|
||||
/// <returns>The object, cast to the Type provided if possible, otherwise the original object.</returns>
|
||||
public static object Cast(this object obj, Type castTo)
|
||||
public static object TryCast(this object obj, Type castTo)
|
||||
=> ReflectionProvider.Instance.Cast(obj, castTo);
|
||||
|
||||
public static T TryCast<T>(this object obj)
|
||||
|
@ -21,6 +21,7 @@ namespace UnityExplorer.Core.Runtime.Il2Cpp
|
||||
{
|
||||
public override void Initialize()
|
||||
{
|
||||
ExplorerCore.Context = RuntimeContext.IL2CPP;
|
||||
Reflection = new Il2CppReflection();
|
||||
TextureUtil = new Il2CppTextureUtil();
|
||||
}
|
||||
@ -80,18 +81,6 @@ namespace UnityExplorer.Core.Runtime.Il2Cpp
|
||||
list.AddRange(il2cppList.ToArray());
|
||||
}
|
||||
|
||||
public override bool IsReferenceEqual(object a, object b)
|
||||
{
|
||||
if (a.TryCast<UnityEngine.Object>() is UnityEngine.Object ua)
|
||||
{
|
||||
var ub = b.TryCast<UnityEngine.Object>();
|
||||
if (ub && ua.m_CachedPtr == ub.m_CachedPtr)
|
||||
return true;
|
||||
}
|
||||
|
||||
return base.IsReferenceEqual(a, b);
|
||||
}
|
||||
|
||||
// LayerMask.LayerToName
|
||||
|
||||
internal delegate IntPtr d_LayerToName(int layer);
|
||||
@ -117,9 +106,6 @@ namespace UnityExplorer.Core.Runtime.Il2Cpp
|
||||
return new Il2CppReferenceArray<UnityEngine.Object>(iCall.Invoke(Il2CppType.From(type).Pointer));
|
||||
}
|
||||
|
||||
public override int GetSceneHandle(Scene scene)
|
||||
=> scene.handle;
|
||||
|
||||
// Scene.GetRootGameObjects();
|
||||
|
||||
internal delegate void d_GetRootGameObjects(int handle, IntPtr list);
|
||||
@ -250,41 +236,31 @@ namespace UnityExplorer.Core.Runtime.Il2Cpp
|
||||
ExplorerCore.Log(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public override void FindSingleton(string[] possibleNames, Type type, BF flags, List<object> instances)
|
||||
{
|
||||
PropertyInfo pi;
|
||||
foreach (var name in possibleNames)
|
||||
{
|
||||
pi = type.GetProperty(name, flags);
|
||||
if (pi != null)
|
||||
{
|
||||
var instance = pi.GetValue(null, null);
|
||||
if (instance != null)
|
||||
{
|
||||
instances.Add(instance);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
base.FindSingleton(possibleNames, type, flags, instances);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class Il2CppExtensions
|
||||
{
|
||||
public static void AddListener(this UnityEvent action, Action listener)
|
||||
public static void AddListenerEx(this UnityEvent action, Action listener)
|
||||
{
|
||||
action.AddListener(listener);
|
||||
}
|
||||
|
||||
public static void AddListener<T>(this UnityEvent<T> action, Action<T> listener)
|
||||
public static void AddListenerEx<T>(this UnityEvent<T> action, Action<T> listener)
|
||||
{
|
||||
action.AddListener(listener);
|
||||
}
|
||||
|
||||
public static void RemoveListener(this UnityEvent action, Action listener)
|
||||
{
|
||||
action.RemoveListener(listener);
|
||||
}
|
||||
|
||||
public static void RemoveListener<T>(this UnityEvent<T> action, Action<T> listener)
|
||||
{
|
||||
action.RemoveListener(listener);
|
||||
}
|
||||
|
||||
public static void SetChildControlHeight(this HorizontalOrVerticalLayoutGroup group, bool value) => group.childControlHeight = value;
|
||||
public static void SetChildControlWidth(this HorizontalOrVerticalLayoutGroup group, bool value) => group.childControlWidth = value;
|
||||
}
|
||||
|
@ -412,7 +412,7 @@ namespace UnityExplorer.Core.Runtime.Il2Cpp
|
||||
var keyList = new List<object>();
|
||||
var valueList = new List<object>();
|
||||
|
||||
var hashtable = value.Cast(typeof(Il2CppSystem.Collections.Hashtable)) as Il2CppSystem.Collections.Hashtable;
|
||||
var hashtable = value.TryCast(typeof(Il2CppSystem.Collections.Hashtable)) as Il2CppSystem.Collections.Hashtable;
|
||||
|
||||
if (hashtable != null)
|
||||
{
|
||||
@ -465,6 +465,26 @@ namespace UnityExplorer.Core.Runtime.Il2Cpp
|
||||
}
|
||||
}
|
||||
|
||||
public override void FindSingleton(string[] possibleNames, Type type, BF flags, List<object> instances)
|
||||
{
|
||||
PropertyInfo pi;
|
||||
foreach (var name in possibleNames)
|
||||
{
|
||||
pi = type.GetProperty(name, flags);
|
||||
if (pi != null)
|
||||
{
|
||||
var instance = pi.GetValue(null, null);
|
||||
if (instance != null)
|
||||
{
|
||||
instances.Add(instance);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
base.FindSingleton(possibleNames, type, flags, instances);
|
||||
}
|
||||
|
||||
// ~~~~~~~~~~ not used ~~~~~~~~~~~~
|
||||
|
||||
// cached il2cpp unbox methods
|
||||
|
@ -19,6 +19,7 @@ namespace UnityExplorer.Core.Runtime.Mono
|
||||
{
|
||||
public override void Initialize()
|
||||
{
|
||||
ExplorerCore.Context = RuntimeContext.Mono;
|
||||
Reflection = new MonoReflection();
|
||||
TextureUtil = new MonoTextureUtil();
|
||||
|
||||
@ -66,12 +67,12 @@ namespace UnityExplorer.Core.Runtime.Mono
|
||||
public override UnityEngine.Object[] FindObjectsOfTypeAll(Type type)
|
||||
=> Resources.FindObjectsOfTypeAll(type);
|
||||
|
||||
private static readonly FieldInfo fi_Scene_handle = typeof(Scene).GetField("m_Handle", ReflectionUtility.AllFlags);
|
||||
//private static readonly FieldInfo fi_Scene_handle = typeof(Scene).GetField("m_Handle", ReflectionUtility.AllFlags);
|
||||
|
||||
public override int GetSceneHandle(Scene scene)
|
||||
{
|
||||
return (int)fi_Scene_handle.GetValue(scene);
|
||||
}
|
||||
//public override int GetSceneHandle(Scene scene)
|
||||
//{
|
||||
// return (int)fi_Scene_handle.GetValue(scene);
|
||||
//}
|
||||
|
||||
public override GameObject[] GetRootGameObjects(Scene scene)
|
||||
{
|
||||
@ -125,6 +126,16 @@ public static class MonoExtensions
|
||||
_event.AddListener(new UnityAction<T>(listener));
|
||||
}
|
||||
|
||||
public static void RemoveListener(this UnityEvent _event, Action listener)
|
||||
{
|
||||
_event.RemoveListener(new UnityAction(listener));
|
||||
}
|
||||
|
||||
public static void RemoveListener<T>(this UnityEvent<T> _event, Action<T> listener)
|
||||
{
|
||||
_event.RemoveListener(new UnityAction<T>(listener));
|
||||
}
|
||||
|
||||
public static void Clear(this StringBuilder sb)
|
||||
{
|
||||
sb.Remove(0, sb.Length);
|
||||
|
@ -2,6 +2,7 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
|
||||
namespace UnityExplorer.Core.Runtime
|
||||
@ -38,5 +39,24 @@ namespace UnityExplorer.Core.Runtime
|
||||
|
||||
public virtual IEnumerable EnumerateEnumerable(object value)
|
||||
=> null;
|
||||
|
||||
public virtual void FindSingleton(string[] s_instanceNames, Type type, BindingFlags flags, List<object> instances)
|
||||
{
|
||||
// Look for a typical Instance backing field.
|
||||
FieldInfo fi;
|
||||
foreach (var name in s_instanceNames)
|
||||
{
|
||||
fi = type.GetField(name, flags);
|
||||
if (fi != null)
|
||||
{
|
||||
var instance = fi.GetValue(null);
|
||||
if (instance != null)
|
||||
{
|
||||
instances.Add(instance);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
13
src/Core/Runtime/RuntimeContext.cs
Normal file
13
src/Core/Runtime/RuntimeContext.cs
Normal file
@ -0,0 +1,13 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace UnityExplorer.Core.Runtime
|
||||
{
|
||||
public enum RuntimeContext
|
||||
{
|
||||
Mono,
|
||||
IL2CPP
|
||||
}
|
||||
}
|
@ -2,7 +2,6 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
@ -42,7 +41,7 @@ namespace UnityExplorer
|
||||
|
||||
public abstract void Update();
|
||||
|
||||
public virtual bool IsReferenceEqual(object a, object b) => ReferenceEquals(a, b);
|
||||
//public virtual bool IsReferenceEqual(object a, object b) => ReferenceEquals(a, b);
|
||||
|
||||
// Unity API handlers
|
||||
|
||||
@ -56,7 +55,7 @@ namespace UnityExplorer
|
||||
|
||||
public abstract void GraphicRaycast(GraphicRaycaster raycaster, PointerEventData data, List<RaycastResult> list);
|
||||
|
||||
public abstract int GetSceneHandle(Scene scene);
|
||||
//public abstract int GetSceneHandle(Scene scene);
|
||||
|
||||
public abstract GameObject[] GetRootGameObjects(Scene scene);
|
||||
|
||||
@ -66,24 +65,5 @@ namespace UnityExplorer
|
||||
|
||||
public abstract void SetColorBlock(Selectable selectable, Color? normal = null, Color? highlighted = null, Color? pressed = null,
|
||||
Color? disabled = null);
|
||||
|
||||
public virtual void FindSingleton(string[] s_instanceNames, Type type, BindingFlags flags, List<object> instances)
|
||||
{
|
||||
// Look for a typical Instance backing field.
|
||||
FieldInfo fi;
|
||||
foreach (var name in s_instanceNames)
|
||||
{
|
||||
fi = type.GetField(name, flags);
|
||||
if (fi != null)
|
||||
{
|
||||
var instance = fi.GetValue(null);
|
||||
if (instance != null)
|
||||
{
|
||||
instances.Add(instance);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
194
src/Core/SceneHandler.cs
Normal file
194
src/Core/SceneHandler.cs
Normal file
@ -0,0 +1,194 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
|
||||
namespace UnityExplorer.Core
|
||||
{
|
||||
public static class SceneHandler
|
||||
{
|
||||
/// <summary>
|
||||
/// The currently inspected Scene.
|
||||
/// </summary>
|
||||
public static Scene? SelectedScene
|
||||
{
|
||||
get => m_selectedScene;
|
||||
internal set
|
||||
{
|
||||
if (m_selectedScene != null && m_selectedScene?.handle == value?.handle)
|
||||
return;
|
||||
m_selectedScene = value;
|
||||
OnInspectedSceneChanged?.Invoke((Scene)m_selectedScene);
|
||||
}
|
||||
}
|
||||
private static Scene? m_selectedScene;
|
||||
|
||||
/// <summary>
|
||||
/// The GameObjects in the currently inspected scene.
|
||||
/// </summary>
|
||||
public static ReadOnlyCollection<GameObject> CurrentRootObjects => new ReadOnlyCollection<GameObject>(rootObjects);
|
||||
private static GameObject[] rootObjects = new GameObject[0];
|
||||
|
||||
/// <summary>
|
||||
/// All currently loaded Scenes.
|
||||
/// </summary>
|
||||
public static ReadOnlyCollection<Scene> LoadedScenes => new ReadOnlyCollection<Scene>(allLoadedScenes);
|
||||
private static readonly List<Scene> allLoadedScenes = new List<Scene>();
|
||||
|
||||
/// <summary>
|
||||
/// The names of all scenes in the build settings, if they could be retrieved.
|
||||
/// </summary>
|
||||
public static ReadOnlyCollection<string> AllSceneNames => new ReadOnlyCollection<string>(allScenesInBuild);
|
||||
private static readonly List<string> allScenesInBuild = new List<string>();
|
||||
|
||||
/// <summary>
|
||||
/// Whether or not we successfuly retrieved the names of the scenes in the build settings.
|
||||
/// </summary>
|
||||
public static bool WasAbleToGetScenesInBuild => gotAllScenesInBuild;
|
||||
private static bool gotAllScenesInBuild = true;
|
||||
|
||||
/// <summary>
|
||||
/// Invoked when the currently inspected Scene changes. The argument is the new scene.
|
||||
/// </summary>
|
||||
public static event Action<Scene> OnInspectedSceneChanged;
|
||||
|
||||
/// <summary>
|
||||
/// Invoked whenever the list of currently loaded Scenes changes. The argument contains all loaded scenes after the change.
|
||||
/// </summary>
|
||||
public static event Action<ReadOnlyCollection<Scene>> OnLoadedScenesChanged;
|
||||
|
||||
/// <summary>
|
||||
/// Equivalent to <see cref="SceneManager.sceneCount"/> + 1, to include 'DontDestroyOnLoad'.
|
||||
/// </summary>
|
||||
public static int LoadedSceneCount => SceneManager.sceneCount + 1;
|
||||
|
||||
// Cached on startup, will never change during runtime (and generally doesn't change between Unity versions either)
|
||||
|
||||
internal static Scene DontDestroyScene => DontDestroyMe.scene;
|
||||
internal static int DontDestroyHandle => DontDestroyScene.handle;
|
||||
|
||||
internal static GameObject DontDestroyMe
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!dontDestroyObject)
|
||||
{
|
||||
dontDestroyObject = new GameObject("DontDestroyMe");
|
||||
GameObject.DontDestroyOnLoad(dontDestroyObject);
|
||||
}
|
||||
return dontDestroyObject;
|
||||
}
|
||||
}
|
||||
private static GameObject dontDestroyObject;
|
||||
|
||||
internal static Scene AssetScene => AssetObject.scene;
|
||||
internal static int AssetHandle => AssetScene.handle;
|
||||
|
||||
internal static GameObject AssetObject
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!assetObject)
|
||||
{
|
||||
assetObject = RuntimeProvider.Instance.FindObjectsOfTypeAll(typeof(GameObject))
|
||||
.First(it => !it.TryCast<GameObject>().scene.IsValid())
|
||||
.TryCast<GameObject>();
|
||||
}
|
||||
return assetObject;
|
||||
}
|
||||
}
|
||||
private static GameObject assetObject;
|
||||
|
||||
internal static void Init()
|
||||
{
|
||||
// Try to get all scenes in the build settings. This may not work.
|
||||
try
|
||||
{
|
||||
Type sceneUtil = ReflectionUtility.GetTypeByName("UnityEngine.SceneManagement.SceneUtility");
|
||||
if (sceneUtil == null)
|
||||
throw new Exception("This version of Unity does not ship with the 'SceneUtility' class, or it was not unstripped.");
|
||||
|
||||
var method = sceneUtil.GetMethod("GetScenePathByBuildIndex", ReflectionUtility.AllFlags);
|
||||
int sceneCount = SceneManager.sceneCountInBuildSettings;
|
||||
for (int i = 0; i < sceneCount; i++)
|
||||
{
|
||||
var scenePath = (string)method.Invoke(null, new object[] { i });
|
||||
allScenesInBuild.Add(scenePath);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
gotAllScenesInBuild = false;
|
||||
ExplorerCore.Log($"Unable to generate list of all Scenes in the build: {ex}");
|
||||
}
|
||||
}
|
||||
|
||||
internal static void Update()
|
||||
{
|
||||
int curHandle = SelectedScene?.handle ?? -1;
|
||||
// DontDestroyOnLoad always exists, so default to true if our curHandle is that handle.
|
||||
// otherwise we will check while iterating.
|
||||
bool inspectedExists = curHandle == DontDestroyHandle || curHandle == AssetHandle;
|
||||
|
||||
// Quick sanity check if the loaded scenes changed
|
||||
bool anyChange = LoadedSceneCount != allLoadedScenes.Count;
|
||||
// otherwise keep a lookup table of the previous handles to check if the list changed at all.
|
||||
HashSet<int> previousHandles = null;
|
||||
if (!anyChange)
|
||||
previousHandles = new HashSet<int>(allLoadedScenes.Select(it => it.handle));
|
||||
|
||||
allLoadedScenes.Clear();
|
||||
|
||||
for (int i = 0; i < SceneManager.sceneCount; i++)
|
||||
{
|
||||
Scene scene = SceneManager.GetSceneAt(i);
|
||||
if (scene == default || scene.handle == -1)
|
||||
continue;
|
||||
|
||||
// If no changes yet, ensure the previous list contained this handle.
|
||||
if (!anyChange && !previousHandles.Contains(scene.handle))
|
||||
anyChange = true;
|
||||
|
||||
// If we have not yet confirmed inspectedExists, check if this scene is our currently inspected one.
|
||||
if (curHandle != -1 && !inspectedExists && scene.handle == curHandle)
|
||||
inspectedExists = true;
|
||||
|
||||
allLoadedScenes.Add(scene);
|
||||
}
|
||||
|
||||
// Always add the DontDestroyOnLoad scene and the "none" scene.
|
||||
allLoadedScenes.Add(DontDestroyScene);
|
||||
allLoadedScenes.Add(AssetScene);
|
||||
|
||||
// Default to first scene if none selected or previous selection no longer exists.
|
||||
if (!inspectedExists)
|
||||
{
|
||||
SelectedScene = allLoadedScenes.First();
|
||||
}
|
||||
|
||||
// Notify on the list changing at all
|
||||
if (anyChange)
|
||||
{
|
||||
OnLoadedScenesChanged?.Invoke(LoadedScenes);
|
||||
}
|
||||
|
||||
// Finally, update the root objects list.
|
||||
if (SelectedScene != null && ((Scene)SelectedScene).IsValid())
|
||||
rootObjects = RuntimeProvider.Instance.GetRootGameObjects((Scene)SelectedScene);
|
||||
else
|
||||
{
|
||||
var allObjects = RuntimeProvider.Instance.FindObjectsOfTypeAll(typeof(GameObject));
|
||||
var list = new List<GameObject>();
|
||||
foreach (var obj in allObjects)
|
||||
{
|
||||
if (obj.TryCast<GameObject>() is GameObject go && !go.scene.IsValid() && go.transform.parent == null)
|
||||
list.Add(go);
|
||||
}
|
||||
rootObjects = list.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -5,8 +5,6 @@ using System.Reflection;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityExplorer.Core.Runtime;
|
||||
using UnityExplorer.UI.Main;
|
||||
using UnityExplorer.UI.Main.Search;
|
||||
|
||||
namespace UnityExplorer.Core.Search
|
||||
{
|
||||
@ -68,7 +66,7 @@ namespace UnityExplorer.Core.Search
|
||||
if (!string.IsNullOrEmpty(nameFilter) && !type.FullName.ToLower().Contains(nameFilter))
|
||||
continue;
|
||||
|
||||
RuntimeProvider.Instance.FindSingleton(s_instanceNames, type, flags, instances);
|
||||
ReflectionProvider.Instance.FindSingleton(s_instanceNames, type, flags, instances);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
@ -78,7 +76,7 @@ namespace UnityExplorer.Core.Search
|
||||
}
|
||||
|
||||
internal static object[] UnityObjectSearch(string input, string customTypeInput, SearchContext context,
|
||||
ChildFilter childFilter, SceneFilter sceneFilter)
|
||||
ChildFilter childFilter, SceneFilter sceneFilter, string sceneName = null)
|
||||
{
|
||||
Type searchType = null;
|
||||
switch (context)
|
||||
@ -134,7 +132,8 @@ namespace UnityExplorer.Core.Search
|
||||
if (sceneFilter == SceneFilter.DontDestroyOnLoad)
|
||||
sceneFilterString = "DontDestroyOnLoad";
|
||||
else if (sceneFilter == SceneFilter.Explicit)
|
||||
sceneFilterString = SearchPage.Instance.m_sceneDropdown.options[SearchPage.Instance.m_sceneDropdown.value].text;
|
||||
//sceneFilterString = SearchPage.Instance.m_sceneDropdown.options[SearchPage.Instance.m_sceneDropdown.value].text;
|
||||
sceneFilterString = sceneName;
|
||||
}
|
||||
|
||||
foreach (var obj in allObjects)
|
||||
|
@ -3,11 +3,11 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace UnityExplorer
|
||||
namespace UnityExplorer.Tests
|
||||
{
|
||||
public static class TestClass
|
||||
{
|
||||
public static UI.Main.PanelDragger.ResizeTypes flags = UI.Main.PanelDragger.ResizeTypes.NONE;
|
||||
//public static UI.Main.PanelDragger.ResizeTypes flags = UI.Main.PanelDragger.ResizeTypes.NONE;
|
||||
|
||||
#if CPP
|
||||
public static string testStringOne = "Test";
|
@ -4,9 +4,11 @@ using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
namespace UnityExplorer.Core.Unity
|
||||
// Project-wide namespace for accessibility
|
||||
namespace UnityExplorer
|
||||
{
|
||||
public static class UnityHelpers
|
||||
{
|
||||
|
Reference in New Issue
Block a user