mirror of
https://github.com/GrahamKracker/UnityExplorer.git
synced 2025-07-01 19:13:03 +08:00
Project refactor, namespace cleanup, splitting UI/functionality.
This commit is contained in:
@ -4,9 +4,9 @@ using System.IO;
|
|||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using Mono.CSharp;
|
using Mono.CSharp;
|
||||||
|
|
||||||
// Thanks to ManlyMarco for this
|
// Thanks to ManlyMarco for most of this
|
||||||
|
|
||||||
namespace UnityExplorer.CSConsole
|
namespace UnityExplorer.Core.CSharp
|
||||||
{
|
{
|
||||||
public class ScriptEvaluator : Evaluator, IDisposable
|
public class ScriptEvaluator : Evaluator, IDisposable
|
||||||
{
|
{
|
@ -1,10 +1,10 @@
|
|||||||
using System;
|
using System;
|
||||||
using Mono.CSharp;
|
using Mono.CSharp;
|
||||||
using UnityExplorer.UI;
|
using UnityExplorer.UI;
|
||||||
using UnityExplorer.UI.Modules;
|
using UnityExplorer.UI.Main;
|
||||||
using UnityExplorer.Inspectors;
|
using UnityExplorer.Core.Inspectors;
|
||||||
|
|
||||||
namespace UnityExplorer.CSConsole
|
namespace UnityExplorer.Core.CSharp
|
||||||
{
|
{
|
||||||
public class ScriptInteraction : InteractiveBase
|
public class ScriptInteraction : InteractiveBase
|
||||||
{
|
{
|
||||||
@ -15,17 +15,17 @@ namespace UnityExplorer.CSConsole
|
|||||||
|
|
||||||
public static void AddUsing(string directive)
|
public static void AddUsing(string directive)
|
||||||
{
|
{
|
||||||
CSConsolePage.Instance.AddUsing(directive);
|
CSharpConsole.Instance.AddUsing(directive);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void GetUsing()
|
public static void GetUsing()
|
||||||
{
|
{
|
||||||
ExplorerCore.Log(CSConsolePage.Instance.m_evaluator.GetUsing());
|
ExplorerCore.Log(CSharpConsole.Instance.m_evaluator.GetUsing());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Reset()
|
public static void Reset()
|
||||||
{
|
{
|
||||||
CSConsolePage.Instance.ResetConsole();
|
CSharpConsole.Instance.ResetConsole();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static object CurrentTarget()
|
public static object CurrentTarget()
|
@ -3,9 +3,11 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityExplorer.Helpers;
|
using UnityExplorer.Core;
|
||||||
|
using UnityExplorer.Core.Unity;
|
||||||
|
using UnityExplorer.UI.CSConsole;
|
||||||
|
|
||||||
namespace UnityExplorer.CSConsole
|
namespace UnityExplorer.Core.CSharp
|
||||||
{
|
{
|
||||||
public struct Suggestion
|
public struct Suggestion
|
||||||
{
|
{
|
||||||
@ -48,7 +50,7 @@ namespace UnityExplorer.CSConsole
|
|||||||
public static HashSet<string> Namespaces => m_namspaces ?? GetNamespaces();
|
public static HashSet<string> Namespaces => m_namspaces ?? GetNamespaces();
|
||||||
private static HashSet<string> m_namspaces;
|
private static HashSet<string> m_namspaces;
|
||||||
|
|
||||||
public static HashSet<string> Keywords => m_keywords ?? (m_keywords = new HashSet<string>(CSharpLexer.validKeywordMatcher.Keywords));
|
public static HashSet<string> Keywords => m_keywords ?? (m_keywords = new HashSet<string>(CSLexerHighlighter.validKeywordMatcher.Keywords));
|
||||||
private static HashSet<string> m_keywords;
|
private static HashSet<string> m_keywords;
|
||||||
|
|
||||||
private static readonly Color keywordColor = new Color(80f / 255f, 150f / 255f, 215f / 255f);
|
private static readonly Color keywordColor = new Color(80f / 255f, 150f / 255f, 215f / 255f);
|
@ -5,7 +5,7 @@ using IniParser;
|
|||||||
using IniParser.Parser;
|
using IniParser.Parser;
|
||||||
using UnityExplorer.UI;
|
using UnityExplorer.UI;
|
||||||
|
|
||||||
namespace UnityExplorer.Config
|
namespace UnityExplorer.Core.Config
|
||||||
{
|
{
|
||||||
public class ExplorerConfig
|
public class ExplorerConfig
|
||||||
{
|
{
|
@ -1,7 +1,7 @@
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.EventSystems;
|
using UnityEngine.EventSystems;
|
||||||
|
|
||||||
namespace UnityExplorer.Input
|
namespace UnityExplorer.Core.Input
|
||||||
{
|
{
|
||||||
public interface IHandleInput
|
public interface IHandleInput
|
||||||
{
|
{
|
@ -1,13 +1,9 @@
|
|||||||
using System;
|
using System;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityExplorer.Helpers;
|
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using UnityEngine.EventSystems;
|
using UnityEngine.EventSystems;
|
||||||
#if CPP
|
|
||||||
using UnhollowerBaseLib;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace UnityExplorer.Input
|
namespace UnityExplorer.Core.Input
|
||||||
{
|
{
|
||||||
public enum InputType
|
public enum InputType
|
||||||
{
|
{
|
||||||
@ -43,12 +39,12 @@ namespace UnityExplorer.Input
|
|||||||
|
|
||||||
public static void Init()
|
public static void Init()
|
||||||
{
|
{
|
||||||
if (InputSystem.TKeyboard != null || (ReflectionHelpers.LoadModule("Unity.InputSystem") && InputSystem.TKeyboard != null))
|
if (InputSystem.TKeyboard != null || (ReflectionUtility.LoadModule("Unity.InputSystem") && InputSystem.TKeyboard != null))
|
||||||
{
|
{
|
||||||
m_inputModule = new InputSystem();
|
m_inputModule = new InputSystem();
|
||||||
CurrentType = InputType.InputSystem;
|
CurrentType = InputType.InputSystem;
|
||||||
}
|
}
|
||||||
else if (LegacyInput.TInput != null || (ReflectionHelpers.LoadModule("UnityEngine.InputLegacyModule") && LegacyInput.TInput != null))
|
else if (LegacyInput.TInput != null || (ReflectionUtility.LoadModule("UnityEngine.InputLegacyModule") && LegacyInput.TInput != null))
|
||||||
{
|
{
|
||||||
m_inputModule = new LegacyInput();
|
m_inputModule = new LegacyInput();
|
||||||
CurrentType = InputType.Legacy;
|
CurrentType = InputType.Legacy;
|
@ -1,12 +1,12 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using UnityExplorer.Helpers;
|
using UnityExplorer.Core.Unity;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.EventSystems;
|
using UnityEngine.EventSystems;
|
||||||
using UnityExplorer.UI;
|
using UnityExplorer.UI;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace UnityExplorer.Input
|
namespace UnityExplorer.Core.Input
|
||||||
{
|
{
|
||||||
public class InputSystem : IHandleInput
|
public class InputSystem : IHandleInput
|
||||||
{
|
{
|
||||||
@ -17,7 +17,7 @@ namespace UnityExplorer.Input
|
|||||||
m_kbCurrentProp = TKeyboard.GetProperty("current");
|
m_kbCurrentProp = TKeyboard.GetProperty("current");
|
||||||
m_kbIndexer = TKeyboard.GetProperty("Item", new Type[] { TKey });
|
m_kbIndexer = TKeyboard.GetProperty("Item", new Type[] { TKey });
|
||||||
|
|
||||||
var btnControl = ReflectionHelpers.GetTypeByName("UnityEngine.InputSystem.Controls.ButtonControl");
|
var btnControl = ReflectionUtility.GetTypeByName("UnityEngine.InputSystem.Controls.ButtonControl");
|
||||||
m_btnIsPressedProp = btnControl.GetProperty("isPressed");
|
m_btnIsPressedProp = btnControl.GetProperty("isPressed");
|
||||||
m_btnWasPressedProp = btnControl.GetProperty("wasPressedThisFrame");
|
m_btnWasPressedProp = btnControl.GetProperty("wasPressedThisFrame");
|
||||||
|
|
||||||
@ -25,21 +25,21 @@ namespace UnityExplorer.Input
|
|||||||
m_leftButtonProp = TMouse.GetProperty("leftButton");
|
m_leftButtonProp = TMouse.GetProperty("leftButton");
|
||||||
m_rightButtonProp = TMouse.GetProperty("rightButton");
|
m_rightButtonProp = TMouse.GetProperty("rightButton");
|
||||||
|
|
||||||
m_positionProp = ReflectionHelpers.GetTypeByName("UnityEngine.InputSystem.Pointer")
|
m_positionProp = ReflectionUtility.GetTypeByName("UnityEngine.InputSystem.Pointer")
|
||||||
.GetProperty("position");
|
.GetProperty("position");
|
||||||
|
|
||||||
m_readVector2InputMethod = ReflectionHelpers.GetTypeByName("UnityEngine.InputSystem.InputControl`1")
|
m_readVector2InputMethod = ReflectionUtility.GetTypeByName("UnityEngine.InputSystem.InputControl`1")
|
||||||
.MakeGenericType(typeof(Vector2))
|
.MakeGenericType(typeof(Vector2))
|
||||||
.GetMethod("ReadValue");
|
.GetMethod("ReadValue");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Type TKeyboard => m_tKeyboard ?? (m_tKeyboard = ReflectionHelpers.GetTypeByName("UnityEngine.InputSystem.Keyboard"));
|
public static Type TKeyboard => m_tKeyboard ?? (m_tKeyboard = ReflectionUtility.GetTypeByName("UnityEngine.InputSystem.Keyboard"));
|
||||||
private static Type m_tKeyboard;
|
private static Type m_tKeyboard;
|
||||||
|
|
||||||
public static Type TMouse => m_tMouse ?? (m_tMouse = ReflectionHelpers.GetTypeByName("UnityEngine.InputSystem.Mouse"));
|
public static Type TMouse => m_tMouse ?? (m_tMouse = ReflectionUtility.GetTypeByName("UnityEngine.InputSystem.Mouse"));
|
||||||
private static Type m_tMouse;
|
private static Type m_tMouse;
|
||||||
|
|
||||||
public static Type TKey => m_tKey ?? (m_tKey = ReflectionHelpers.GetTypeByName("UnityEngine.InputSystem.Key"));
|
public static Type TKey => m_tKey ?? (m_tKey = ReflectionUtility.GetTypeByName("UnityEngine.InputSystem.Key"));
|
||||||
private static Type m_tKey;
|
private static Type m_tKey;
|
||||||
|
|
||||||
private static PropertyInfo m_btnIsPressedProp;
|
private static PropertyInfo m_btnIsPressedProp;
|
@ -1,11 +1,11 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using UnityExplorer.Helpers;
|
using UnityExplorer.Core.Unity;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.EventSystems;
|
using UnityEngine.EventSystems;
|
||||||
using UnityExplorer.UI;
|
using UnityExplorer.UI;
|
||||||
|
|
||||||
namespace UnityExplorer.Input
|
namespace UnityExplorer.Core.Input
|
||||||
{
|
{
|
||||||
public class LegacyInput : IHandleInput
|
public class LegacyInput : IHandleInput
|
||||||
{
|
{
|
||||||
@ -20,7 +20,7 @@ namespace UnityExplorer.Input
|
|||||||
m_getMouseButtonDownMethod = TInput.GetMethod("GetMouseButtonDown", new Type[] { typeof(int) });
|
m_getMouseButtonDownMethod = TInput.GetMethod("GetMouseButtonDown", new Type[] { typeof(int) });
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Type TInput => m_tInput ?? (m_tInput = ReflectionHelpers.GetTypeByName("UnityEngine.Input"));
|
public static Type TInput => m_tInput ?? (m_tInput = ReflectionUtility.GetTypeByName("UnityEngine.Input"));
|
||||||
private static Type m_tInput;
|
private static Type m_tInput;
|
||||||
|
|
||||||
private static PropertyInfo m_mousePositionProp;
|
private static PropertyInfo m_mousePositionProp;
|
@ -1,7 +1,7 @@
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.EventSystems;
|
using UnityEngine.EventSystems;
|
||||||
|
|
||||||
namespace UnityExplorer.Input
|
namespace UnityExplorer.Core.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.
|
||||||
|
|
138
src/Core/InspectorManager.cs
Normal file
138
src/Core/InspectorManager.cs
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using UnityExplorer.Core.Unity;
|
||||||
|
using UnityExplorer.UI;
|
||||||
|
using UnityExplorer.UI.Main;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.SceneManagement;
|
||||||
|
using UnityEngine.UI;
|
||||||
|
using UnityExplorer.Core.Inspectors.Reflection;
|
||||||
|
using UnityExplorer.Core.Runtime;
|
||||||
|
using UnityExplorer.UI.Main.Home;
|
||||||
|
|
||||||
|
namespace UnityExplorer.Core.Inspectors
|
||||||
|
{
|
||||||
|
public class InspectorManager
|
||||||
|
{
|
||||||
|
public static InspectorManager Instance { get; private set; }
|
||||||
|
|
||||||
|
internal static InspectorManagerUI UI;
|
||||||
|
|
||||||
|
public InspectorManager()
|
||||||
|
{
|
||||||
|
Instance = this;
|
||||||
|
|
||||||
|
UI = new InspectorManagerUI();
|
||||||
|
UI.ConstructInspectorPane();
|
||||||
|
}
|
||||||
|
|
||||||
|
public InspectorBase m_activeInspector;
|
||||||
|
public readonly List<InspectorBase> m_currentInspectors = new List<InspectorBase>();
|
||||||
|
|
||||||
|
public void Update()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < m_currentInspectors.Count; i++)
|
||||||
|
{
|
||||||
|
if (i >= m_currentInspectors.Count)
|
||||||
|
break;
|
||||||
|
|
||||||
|
m_currentInspectors[i].Update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Inspect(object obj, CacheObjectBase parentMember = null)
|
||||||
|
{
|
||||||
|
obj = ReflectionProvider.Instance.Cast(obj, ReflectionProvider.Instance.GetActualType(obj));
|
||||||
|
|
||||||
|
UnityEngine.Object unityObj = obj as UnityEngine.Object;
|
||||||
|
|
||||||
|
if (obj.IsNullOrDestroyed(false))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if currently inspecting this object
|
||||||
|
foreach (InspectorBase tab in m_currentInspectors)
|
||||||
|
{
|
||||||
|
if (ReferenceEquals(obj, tab.Target))
|
||||||
|
{
|
||||||
|
SetInspectorTab(tab);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#if CPP
|
||||||
|
else if (unityObj && tab.Target is UnityEngine.Object uTabObj)
|
||||||
|
{
|
||||||
|
if (unityObj.m_CachedPtr == uTabObj.m_CachedPtr)
|
||||||
|
{
|
||||||
|
SetInspectorTab(tab);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
InspectorBase inspector;
|
||||||
|
if (obj is GameObject go)
|
||||||
|
inspector = new GameObjectInspector(go);
|
||||||
|
else
|
||||||
|
inspector = new InstanceInspector(obj);
|
||||||
|
|
||||||
|
if (inspector is ReflectionInspector ri)
|
||||||
|
ri.ParentMember = parentMember;
|
||||||
|
|
||||||
|
m_currentInspectors.Add(inspector);
|
||||||
|
SetInspectorTab(inspector);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Inspect(Type type)
|
||||||
|
{
|
||||||
|
if (type == null)
|
||||||
|
{
|
||||||
|
ExplorerCore.LogWarning("The provided type was null!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var tab in m_currentInspectors.Where(x => x is StaticInspector))
|
||||||
|
{
|
||||||
|
if (ReferenceEquals(tab.Target as Type, type))
|
||||||
|
{
|
||||||
|
SetInspectorTab(tab);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var inspector = new StaticInspector(type);
|
||||||
|
|
||||||
|
m_currentInspectors.Add(inspector);
|
||||||
|
SetInspectorTab(inspector);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetInspectorTab(InspectorBase inspector)
|
||||||
|
{
|
||||||
|
MainMenu.Instance.SetPage(HomePage.Instance);
|
||||||
|
|
||||||
|
if (m_activeInspector == inspector)
|
||||||
|
return;
|
||||||
|
|
||||||
|
UnsetInspectorTab();
|
||||||
|
|
||||||
|
m_activeInspector = inspector;
|
||||||
|
inspector.SetActive();
|
||||||
|
|
||||||
|
UI.OnSetInspectorTab(inspector);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UnsetInspectorTab()
|
||||||
|
{
|
||||||
|
if (m_activeInspector == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_activeInspector.SetInactive();
|
||||||
|
|
||||||
|
UI.OnUnsetInspectorTab();
|
||||||
|
|
||||||
|
m_activeInspector = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
101
src/Core/Inspectors/GameObjects/GameObjectInspector.cs
Normal file
101
src/Core/Inspectors/GameObjects/GameObjectInspector.cs
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using UnityExplorer.UI;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.UI;
|
||||||
|
using UnityExplorer.Core.Runtime;
|
||||||
|
using UnityExplorer.Core.Unity;
|
||||||
|
using UnityExplorer.UI.Main.Home.Inspectors;
|
||||||
|
|
||||||
|
namespace UnityExplorer.Core.Inspectors
|
||||||
|
{
|
||||||
|
public class GameObjectInspector : InspectorBase
|
||||||
|
{
|
||||||
|
public override string TabLabel => $" <color=cyan>[G]</color> {TargetGO?.name}";
|
||||||
|
|
||||||
|
public static GameObjectInspector ActiveInstance { get; private set; }
|
||||||
|
|
||||||
|
public GameObject TargetGO;
|
||||||
|
|
||||||
|
public GameObjectInspectorUI UIModule;
|
||||||
|
|
||||||
|
// sub modules
|
||||||
|
internal static ChildList s_childList;
|
||||||
|
internal static ComponentList s_compList;
|
||||||
|
internal static GameObjectControls s_controls;
|
||||||
|
|
||||||
|
internal static bool m_UIConstructed;
|
||||||
|
|
||||||
|
public GameObjectInspector(GameObject target) : base(target)
|
||||||
|
{
|
||||||
|
ActiveInstance = this;
|
||||||
|
|
||||||
|
TargetGO = target;
|
||||||
|
|
||||||
|
if (!TargetGO)
|
||||||
|
{
|
||||||
|
ExplorerCore.LogWarning("Target GameObject is null!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// one UI is used for all gameobject inspectors. no point recreating it.
|
||||||
|
if (!m_UIConstructed)
|
||||||
|
{
|
||||||
|
m_UIConstructed = true;
|
||||||
|
|
||||||
|
s_childList = new ChildList();
|
||||||
|
s_compList = new ComponentList();
|
||||||
|
s_controls = new GameObjectControls();
|
||||||
|
|
||||||
|
UIModule.ConstructUI();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void SetActive()
|
||||||
|
{
|
||||||
|
base.SetActive();
|
||||||
|
ActiveInstance = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void SetInactive()
|
||||||
|
{
|
||||||
|
base.SetInactive();
|
||||||
|
ActiveInstance = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void ChangeInspectorTarget(GameObject newTarget)
|
||||||
|
{
|
||||||
|
if (!newTarget)
|
||||||
|
return;
|
||||||
|
|
||||||
|
this.Target = this.TargetGO = newTarget;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update
|
||||||
|
|
||||||
|
public override void Update()
|
||||||
|
{
|
||||||
|
base.Update();
|
||||||
|
|
||||||
|
if (m_pendingDestroy || !this.IsActive)
|
||||||
|
return;
|
||||||
|
|
||||||
|
UIModule.RefreshTopInfo();
|
||||||
|
|
||||||
|
s_childList.RefreshChildObjectList();
|
||||||
|
|
||||||
|
s_compList.RefreshComponentList();
|
||||||
|
|
||||||
|
s_controls.RefreshControls();
|
||||||
|
|
||||||
|
if (GameObjectControls.s_sliderChangedWanted)
|
||||||
|
GameObjectControls.UpdateSliderControl();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void CreateUIModule()
|
||||||
|
{
|
||||||
|
base.BaseUI = UIModule = new GameObjectInspectorUI();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -5,14 +5,17 @@ using System.Text;
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.EventSystems;
|
using UnityEngine.EventSystems;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using UnityExplorer.Helpers;
|
using UnityExplorer.Core;
|
||||||
using UnityExplorer.Input;
|
using UnityExplorer.Core.Unity;
|
||||||
|
using UnityExplorer.Core.Input;
|
||||||
|
using UnityExplorer.Core.Runtime;
|
||||||
using UnityExplorer.UI;
|
using UnityExplorer.UI;
|
||||||
using UnityExplorer.Unstrip;
|
using UnityExplorer.UI.Main;
|
||||||
|
using UnityExplorer.UI.Main.Home.Inspectors;
|
||||||
|
|
||||||
namespace UnityExplorer.Inspectors
|
namespace UnityExplorer.Core.Inspectors
|
||||||
{
|
{
|
||||||
public class MouseInspector
|
public class InspectUnderMouse
|
||||||
{
|
{
|
||||||
public enum MouseInspectMode
|
public enum MouseInspectMode
|
||||||
{
|
{
|
||||||
@ -24,31 +27,29 @@ namespace UnityExplorer.Inspectors
|
|||||||
|
|
||||||
public static MouseInspectMode Mode { get; set; }
|
public static MouseInspectMode Mode { get; set; }
|
||||||
|
|
||||||
internal static Text s_objNameLabel;
|
|
||||||
internal static Text s_objPathLabel;
|
|
||||||
internal static Text s_mousePosLabel;
|
|
||||||
|
|
||||||
private static GameObject s_lastHit;
|
private static GameObject s_lastHit;
|
||||||
private static Vector3 s_lastMousePos;
|
private static Vector3 s_lastMousePos;
|
||||||
|
|
||||||
internal static GameObject s_UIContent;
|
internal static MouseInspectorUI UI;
|
||||||
|
|
||||||
|
static InspectUnderMouse()
|
||||||
|
{
|
||||||
|
UI = new MouseInspectorUI();
|
||||||
|
}
|
||||||
|
|
||||||
public static void StartInspect()
|
public static void StartInspect()
|
||||||
{
|
{
|
||||||
Enabled = true;
|
Enabled = true;
|
||||||
MainMenu.Instance.MainPanel.SetActive(false);
|
MainMenu.Instance.MainPanel.SetActive(false);
|
||||||
s_UIContent.SetActive(true);
|
|
||||||
|
UI.s_UIContent.SetActive(true);
|
||||||
|
|
||||||
// recache Graphic Raycasters each time we start
|
// recache Graphic Raycasters each time we start
|
||||||
var casters = ResourcesUnstrip.FindObjectsOfTypeAll(typeof(GraphicRaycaster));
|
var casters = RuntimeProvider.Instance.FindObjectsOfTypeAll(typeof(GraphicRaycaster));
|
||||||
m_gCasters = new GraphicRaycaster[casters.Length];
|
m_gCasters = new GraphicRaycaster[casters.Length];
|
||||||
for (int i = 0; i < casters.Length; i++)
|
for (int i = 0; i < casters.Length; i++)
|
||||||
{
|
{
|
||||||
#if CPP
|
m_gCasters[i] = casters[i].Cast(typeof(GraphicRaycaster)) as GraphicRaycaster;
|
||||||
m_gCasters[i] = casters[i].TryCast<GraphicRaycaster>();
|
|
||||||
#else
|
|
||||||
m_gCasters[i] = casters[i] as GraphicRaycaster;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,7 +57,7 @@ namespace UnityExplorer.Inspectors
|
|||||||
{
|
{
|
||||||
Enabled = false;
|
Enabled = false;
|
||||||
MainMenu.Instance.MainPanel.SetActive(true);
|
MainMenu.Instance.MainPanel.SetActive(true);
|
||||||
s_UIContent.SetActive(false);
|
UI.s_UIContent.SetActive(false);
|
||||||
|
|
||||||
ClearHitData();
|
ClearHitData();
|
||||||
}
|
}
|
||||||
@ -76,7 +77,7 @@ namespace UnityExplorer.Inspectors
|
|||||||
if (mousePos != s_lastMousePos)
|
if (mousePos != s_lastMousePos)
|
||||||
UpdatePosition(mousePos);
|
UpdatePosition(mousePos);
|
||||||
|
|
||||||
if (!UnityHelpers.MainCamera)
|
if (!UnityHelper.MainCamera)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// actual inspect raycast
|
// actual inspect raycast
|
||||||
@ -95,8 +96,8 @@ namespace UnityExplorer.Inspectors
|
|||||||
if (obj != s_lastHit)
|
if (obj != s_lastHit)
|
||||||
{
|
{
|
||||||
s_lastHit = obj;
|
s_lastHit = obj;
|
||||||
s_objNameLabel.text = $"<b>Click to Inspect:</b> <color=cyan>{obj.name}</color>";
|
UI.s_objNameLabel.text = $"<b>Click to Inspect:</b> <color=cyan>{obj.name}</color>";
|
||||||
s_objPathLabel.text = $"Path: {obj.transform.GetTransformPath(true)}";
|
UI.s_objPathLabel.text = $"Path: {obj.transform.GetTransformPath(true)}";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (InputManager.GetMouseButtonDown(0))
|
if (InputManager.GetMouseButtonDown(0))
|
||||||
@ -108,7 +109,7 @@ namespace UnityExplorer.Inspectors
|
|||||||
|
|
||||||
internal static void RaycastWorld(Vector2 mousePos)
|
internal static void RaycastWorld(Vector2 mousePos)
|
||||||
{
|
{
|
||||||
var ray = UnityHelpers.MainCamera.ScreenPointToRay(mousePos);
|
var ray = UnityHelper.MainCamera.ScreenPointToRay(mousePos);
|
||||||
Physics.Raycast(ray, out RaycastHit hit, 1000f);
|
Physics.Raycast(ray, out RaycastHit hit, 1000f);
|
||||||
|
|
||||||
if (hit.transform)
|
if (hit.transform)
|
||||||
@ -167,64 +168,17 @@ namespace UnityExplorer.Inspectors
|
|||||||
|
|
||||||
var inversePos = UIManager.CanvasRoot.transform.InverseTransformPoint(mousePos);
|
var inversePos = UIManager.CanvasRoot.transform.InverseTransformPoint(mousePos);
|
||||||
|
|
||||||
s_mousePosLabel.text = $"<color=grey>Mouse Position:</color> {mousePos.ToString()}";
|
UI.s_mousePosLabel.text = $"<color=grey>Mouse Position:</color> {mousePos.ToString()}";
|
||||||
|
|
||||||
float yFix = mousePos.y < 120 ? 80 : -80;
|
float yFix = mousePos.y < 120 ? 80 : -80;
|
||||||
s_UIContent.transform.localPosition = new Vector3(inversePos.x, inversePos.y + yFix, 0);
|
UI.s_UIContent.transform.localPosition = new Vector3(inversePos.x, inversePos.y + yFix, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void ClearHitData()
|
internal static void ClearHitData()
|
||||||
{
|
{
|
||||||
s_lastHit = null;
|
s_lastHit = null;
|
||||||
s_objNameLabel.text = "No hits...";
|
UI.s_objNameLabel.text = "No hits...";
|
||||||
s_objPathLabel.text = "";
|
UI.s_objPathLabel.text = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
#region UI Construction
|
|
||||||
|
|
||||||
internal static void ConstructUI()
|
|
||||||
{
|
|
||||||
s_UIContent = UIFactory.CreatePanel(UIManager.CanvasRoot, "MouseInspect", out GameObject content);
|
|
||||||
|
|
||||||
s_UIContent.AddComponent<Mask>();
|
|
||||||
|
|
||||||
var baseRect = s_UIContent.GetComponent<RectTransform>();
|
|
||||||
var half = new Vector2(0.5f, 0.5f);
|
|
||||||
baseRect.anchorMin = half;
|
|
||||||
baseRect.anchorMax = half;
|
|
||||||
baseRect.pivot = half;
|
|
||||||
baseRect.sizeDelta = new Vector2(700, 150);
|
|
||||||
|
|
||||||
var group = content.GetComponent<VerticalLayoutGroup>();
|
|
||||||
group.childForceExpandHeight = true;
|
|
||||||
|
|
||||||
// Title text
|
|
||||||
|
|
||||||
var titleObj = UIFactory.CreateLabel(content, TextAnchor.MiddleCenter);
|
|
||||||
var titleText = titleObj.GetComponent<Text>();
|
|
||||||
titleText.text = "<b>Mouse Inspector</b> (press <b>ESC</b> to cancel)";
|
|
||||||
|
|
||||||
var mousePosObj = UIFactory.CreateLabel(content, TextAnchor.MiddleCenter);
|
|
||||||
s_mousePosLabel = mousePosObj.GetComponent<Text>();
|
|
||||||
s_mousePosLabel.text = "Mouse Position:";
|
|
||||||
|
|
||||||
var hitLabelObj = UIFactory.CreateLabel(content, TextAnchor.MiddleLeft);
|
|
||||||
s_objNameLabel = hitLabelObj.GetComponent<Text>();
|
|
||||||
s_objNameLabel.text = "No hits...";
|
|
||||||
s_objNameLabel.horizontalOverflow = HorizontalWrapMode.Overflow;
|
|
||||||
|
|
||||||
var pathLabelObj = UIFactory.CreateLabel(content, TextAnchor.MiddleLeft);
|
|
||||||
s_objPathLabel = pathLabelObj.GetComponent<Text>();
|
|
||||||
s_objPathLabel.fontStyle = FontStyle.Italic;
|
|
||||||
s_objPathLabel.horizontalOverflow = HorizontalWrapMode.Wrap;
|
|
||||||
|
|
||||||
var pathLayout = pathLabelObj.AddComponent<LayoutElement>();
|
|
||||||
pathLayout.minHeight = 75;
|
|
||||||
pathLayout.flexibleHeight = 0;
|
|
||||||
|
|
||||||
s_UIContent.SetActive(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
}
|
||||||
}
|
}
|
92
src/Core/Inspectors/InspectorBase.cs
Normal file
92
src/Core/Inspectors/InspectorBase.cs
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
using System;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.UI;
|
||||||
|
using UnityExplorer.Core.Unity;
|
||||||
|
using UnityExplorer.UI;
|
||||||
|
using UnityExplorer.UI.Main.Home.Inspectors;
|
||||||
|
|
||||||
|
namespace UnityExplorer.Core.Inspectors
|
||||||
|
{
|
||||||
|
public abstract class InspectorBase
|
||||||
|
{
|
||||||
|
public object Target;
|
||||||
|
|
||||||
|
public InspectorBaseUI BaseUI;
|
||||||
|
|
||||||
|
public abstract string TabLabel { get; }
|
||||||
|
|
||||||
|
public bool IsActive { get; private set; }
|
||||||
|
|
||||||
|
internal bool m_pendingDestroy;
|
||||||
|
|
||||||
|
public InspectorBase(object target)
|
||||||
|
{
|
||||||
|
Target = target;
|
||||||
|
|
||||||
|
if (Target.IsNullOrDestroyed(false))
|
||||||
|
{
|
||||||
|
Destroy();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CreateUIModule();
|
||||||
|
|
||||||
|
BaseUI.AddInspectorTab(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract void CreateUIModule();
|
||||||
|
|
||||||
|
public virtual void SetActive()
|
||||||
|
{
|
||||||
|
this.IsActive = true;
|
||||||
|
BaseUI.Content?.SetActive(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void SetInactive()
|
||||||
|
{
|
||||||
|
this.IsActive = false;
|
||||||
|
BaseUI.Content?.SetActive(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void Update()
|
||||||
|
{
|
||||||
|
if (Target.IsNullOrDestroyed(false))
|
||||||
|
{
|
||||||
|
Destroy();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
BaseUI.tabText.text = TabLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void Destroy()
|
||||||
|
{
|
||||||
|
m_pendingDestroy = true;
|
||||||
|
|
||||||
|
GameObject tabGroup = BaseUI.tabButton?.transform.parent.gameObject;
|
||||||
|
|
||||||
|
if (tabGroup)
|
||||||
|
{
|
||||||
|
GameObject.Destroy(tabGroup);
|
||||||
|
}
|
||||||
|
|
||||||
|
int thisIndex = -1;
|
||||||
|
if (InspectorManager.Instance.m_currentInspectors.Contains(this))
|
||||||
|
{
|
||||||
|
thisIndex = InspectorManager.Instance.m_currentInspectors.IndexOf(this);
|
||||||
|
InspectorManager.Instance.m_currentInspectors.Remove(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ReferenceEquals(InspectorManager.Instance.m_activeInspector, this))
|
||||||
|
{
|
||||||
|
InspectorManager.Instance.UnsetInspectorTab();
|
||||||
|
|
||||||
|
if (InspectorManager.Instance.m_currentInspectors.Count > 0)
|
||||||
|
{
|
||||||
|
var prevTab = InspectorManager.Instance.m_currentInspectors[thisIndex > 0 ? thisIndex - 1 : 0];
|
||||||
|
InspectorManager.Instance.SetInspectorTab(prevTab);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -7,7 +7,7 @@ using UnityExplorer.UI;
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
|
|
||||||
namespace UnityExplorer.Inspectors.Reflection
|
namespace UnityExplorer.Core.Inspectors.Reflection
|
||||||
{
|
{
|
||||||
public class CacheEnumerated : CacheObjectBase
|
public class CacheEnumerated : CacheObjectBase
|
||||||
{
|
{
|
@ -4,10 +4,9 @@ using System.Linq;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using UnityExplorer.UI;
|
using UnityExplorer.UI;
|
||||||
using UnityExplorer.Helpers;
|
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace UnityExplorer.Inspectors.Reflection
|
namespace UnityExplorer.Core.Inspectors.Reflection
|
||||||
{
|
{
|
||||||
public class CacheField : CacheMember
|
public class CacheField : CacheMember
|
||||||
{
|
{
|
@ -5,13 +5,13 @@ using System.Reflection;
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using UnityExplorer.UI;
|
using UnityExplorer.UI;
|
||||||
using UnityExplorer.UI.Shared;
|
using UnityExplorer.UI.Reusable;
|
||||||
using UnityExplorer.Helpers;
|
using UnityExplorer.Core.Unity;
|
||||||
#if CPP
|
using UnityExplorer.Core.Runtime;
|
||||||
using UnhollowerBaseLib;
|
using UnityExplorer.Core;
|
||||||
#endif
|
using UnityExplorer.UI.Utility;
|
||||||
|
|
||||||
namespace UnityExplorer.Inspectors.Reflection
|
namespace UnityExplorer.Core.Inspectors.Reflection
|
||||||
{
|
{
|
||||||
public abstract class CacheMember : CacheObjectBase
|
public abstract class CacheMember : CacheObjectBase
|
||||||
{
|
{
|
||||||
@ -50,10 +50,8 @@ namespace UnityExplorer.Inspectors.Reflection
|
|||||||
DeclaringType = memberInfo.DeclaringType;
|
DeclaringType = memberInfo.DeclaringType;
|
||||||
DeclaringInstance = declaringInstance;
|
DeclaringInstance = declaringInstance;
|
||||||
this.m_parentContent = parentContent;
|
this.m_parentContent = parentContent;
|
||||||
#if CPP
|
|
||||||
if (DeclaringInstance != null)
|
DeclaringInstance = ReflectionProvider.Instance.Cast(declaringInstance, DeclaringType);
|
||||||
DeclaringInstance = DeclaringInstance.Il2CppCast(DeclaringType);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool CanProcessArgs(ParameterInfo[] parameters)
|
public static bool CanProcessArgs(ParameterInfo[] parameters)
|
||||||
@ -87,19 +85,19 @@ namespace UnityExplorer.Inspectors.Reflection
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
#if CPP
|
Type baseType = ReflectionUtility.GetType(IValue.Value) ?? FallbackType;
|
||||||
if (!IsReflectionSupported())
|
|
||||||
throw new Exception("Type not supported with Reflection");
|
if (!ReflectionProvider.Instance.IsReflectionSupported(baseType))
|
||||||
#endif
|
throw new Exception("Type not supported with reflection");
|
||||||
|
|
||||||
UpdateReflection();
|
UpdateReflection();
|
||||||
#if CPP
|
|
||||||
if (IValue.Value != null)
|
if (IValue.Value != null)
|
||||||
IValue.Value = IValue.Value.Il2CppCast(ReflectionHelpers.GetActualType(IValue.Value));
|
IValue.Value = IValue.Value.Cast(ReflectionUtility.GetType(IValue.Value));
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
ReflectionException = ReflectionHelpers.ExceptionToString(e, true);
|
ReflectionException = e.ReflectionExToString(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -179,46 +177,9 @@ namespace UnityExplorer.Inspectors.Reflection
|
|||||||
|
|
||||||
private string GetRichTextName()
|
private string GetRichTextName()
|
||||||
{
|
{
|
||||||
return m_richTextName = UISyntaxHighlight.ParseFullSyntax(MemInfo.DeclaringType, false, MemInfo);
|
return m_richTextName = SignatureHighlighter.ParseFullSyntax(MemInfo.DeclaringType, false, MemInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if CPP
|
|
||||||
internal bool IsReflectionSupported()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var baseType = ReflectionHelpers.GetActualType(IValue.Value) ?? IValue.FallbackType;
|
|
||||||
|
|
||||||
var gArgs = baseType.GetGenericArguments();
|
|
||||||
if (gArgs.Length < 1)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
foreach (var arg in gArgs)
|
|
||||||
{
|
|
||||||
if (!Check(arg))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
|
|
||||||
bool Check(Type type)
|
|
||||||
{
|
|
||||||
if (!typeof(Il2CppSystem.Object).IsAssignableFrom(type))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
if (!ReflectionHelpers.Il2CppTypeNotNull(type, out IntPtr ptr))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return Il2CppSystem.Type.internal_from_handle(IL2CPP.il2cpp_class_get_type(ptr)) is Il2CppSystem.Type;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#region UI
|
#region UI
|
||||||
|
|
||||||
internal float GetMemberLabelWidth(RectTransform scrollRect)
|
internal float GetMemberLabelWidth(RectTransform scrollRect)
|
||||||
@ -380,8 +341,8 @@ namespace UnityExplorer.Inspectors.Reflection
|
|||||||
var argLabelLayout = argLabelObj.AddComponent<LayoutElement>();
|
var argLabelLayout = argLabelObj.AddComponent<LayoutElement>();
|
||||||
argLabelLayout.minHeight = 25;
|
argLabelLayout.minHeight = 25;
|
||||||
var argText = argLabelObj.GetComponent<Text>();
|
var argText = argLabelObj.GetComponent<Text>();
|
||||||
var argTypeTxt = UISyntaxHighlight.ParseFullSyntax(arg.ParameterType, false);
|
var argTypeTxt = SignatureHighlighter.ParseFullSyntax(arg.ParameterType, false);
|
||||||
argText.text = $"{argTypeTxt} <color={UISyntaxHighlight.LOCAL_ARG}>{arg.Name}</color>";
|
argText.text = $"{argTypeTxt} <color={SignatureHighlighter.LOCAL_ARG}>{arg.Name}</color>";
|
||||||
|
|
||||||
var argInputObj = UIFactory.CreateInputField(rowObj, 14, (int)TextAnchor.MiddleLeft, 1);
|
var argInputObj = UIFactory.CreateInputField(rowObj, 14, (int)TextAnchor.MiddleLeft, 1);
|
||||||
var argInputLayout = argInputObj.AddComponent<LayoutElement>();
|
var argInputLayout = argInputObj.AddComponent<LayoutElement>();
|
@ -5,9 +5,11 @@ using System.Reflection;
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using UnityExplorer.UI;
|
using UnityExplorer.UI;
|
||||||
using UnityExplorer.Helpers;
|
using UnityExplorer.Core.Unity;
|
||||||
|
using UnityExplorer.Core;
|
||||||
|
using UnityExplorer.UI.Utility;
|
||||||
|
|
||||||
namespace UnityExplorer.Inspectors.Reflection
|
namespace UnityExplorer.Core.Inspectors.Reflection
|
||||||
{
|
{
|
||||||
public class CacheMethod : CacheMember
|
public class CacheMethod : CacheMember
|
||||||
{
|
{
|
||||||
@ -75,7 +77,7 @@ namespace UnityExplorer.Inspectors.Reflection
|
|||||||
e = e.InnerException;
|
e = e.InnerException;
|
||||||
|
|
||||||
ExplorerCore.LogWarning($"Exception evaluating: {e.GetType()}, {e.Message}");
|
ExplorerCore.LogWarning($"Exception evaluating: {e.GetType()}, {e.Message}");
|
||||||
ReflectionException = ReflectionHelpers.ExceptionToString(e);
|
ReflectionException = ReflectionUtility.ReflectionExToString(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
IValue.Value = ret;
|
IValue.Value = ret;
|
||||||
@ -90,7 +92,7 @@ namespace UnityExplorer.Inspectors.Reflection
|
|||||||
for (int i = 0; i < GenericArgs.Length; i++)
|
for (int i = 0; i < GenericArgs.Length; i++)
|
||||||
{
|
{
|
||||||
var input = m_genericArgInput[i];
|
var input = m_genericArgInput[i];
|
||||||
if (ReflectionHelpers.GetTypeByName(input) is Type t)
|
if (ReflectionUtility.GetTypeByName(input) is Type t)
|
||||||
{
|
{
|
||||||
if (GenericConstraints[i].Length == 0)
|
if (GenericConstraints[i].Length == 0)
|
||||||
{
|
{
|
||||||
@ -150,7 +152,7 @@ namespace UnityExplorer.Inspectors.Reflection
|
|||||||
if (constrainTxt != "")
|
if (constrainTxt != "")
|
||||||
constrainTxt += ", ";
|
constrainTxt += ", ";
|
||||||
|
|
||||||
constrainTxt += $"{UISyntaxHighlight.ParseFullSyntax(constraint, false)}";
|
constrainTxt += $"{SignatureHighlighter.ParseFullSyntax(constraint, false)}";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -168,7 +170,7 @@ namespace UnityExplorer.Inspectors.Reflection
|
|||||||
//var argLayout = argLabelObj.AddComponent<LayoutElement>();
|
//var argLayout = argLabelObj.AddComponent<LayoutElement>();
|
||||||
//argLayout.minWidth = 20;
|
//argLayout.minWidth = 20;
|
||||||
var argText = argLabelObj.GetComponent<Text>();
|
var argText = argLabelObj.GetComponent<Text>();
|
||||||
argText.text = $"{constrainTxt} <color={UISyntaxHighlight.CONST_VAR}>{arg.Name}</color>";
|
argText.text = $"{constrainTxt} <color={SignatureHighlighter.CONST_VAR}>{arg.Name}</color>";
|
||||||
|
|
||||||
var argInputObj = UIFactory.CreateInputField(rowObj, 14, (int)TextAnchor.MiddleLeft, 1);
|
var argInputObj = UIFactory.CreateInputField(rowObj, 14, (int)TextAnchor.MiddleLeft, 1);
|
||||||
var argInputLayout = argInputObj.AddComponent<LayoutElement>();
|
var argInputLayout = argInputObj.AddComponent<LayoutElement>();
|
@ -4,11 +4,12 @@ using System.Linq;
|
|||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityExplorer.UI;
|
using UnityExplorer.UI;
|
||||||
using UnityExplorer.UI.Shared;
|
using UnityExplorer.UI.Reusable;
|
||||||
using UnityExplorer.Helpers;
|
using UnityExplorer.Core.Unity;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
|
using UnityExplorer.Core;
|
||||||
|
|
||||||
namespace UnityExplorer.Inspectors.Reflection
|
namespace UnityExplorer.Core.Inspectors.Reflection
|
||||||
{
|
{
|
||||||
public abstract class CacheObjectBase
|
public abstract class CacheObjectBase
|
||||||
{
|
{
|
||||||
@ -54,7 +55,7 @@ namespace UnityExplorer.Inspectors.Reflection
|
|||||||
// if the type has changed fundamentally, make a new interactivevalue for it
|
// if the type has changed fundamentally, make a new interactivevalue for it
|
||||||
var type = value == null
|
var type = value == null
|
||||||
? FallbackType
|
? FallbackType
|
||||||
: ReflectionHelpers.GetActualType(value);
|
: ReflectionUtility.GetType(value);
|
||||||
|
|
||||||
var ivalueType = InteractiveValue.GetIValueForType(type);
|
var ivalueType = InteractiveValue.GetIValueForType(type);
|
||||||
|
|
@ -8,7 +8,7 @@ using UnityEngine;
|
|||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
|
|
||||||
|
|
||||||
namespace UnityExplorer.Inspectors.Reflection
|
namespace UnityExplorer.Core.Inspectors.Reflection
|
||||||
{
|
{
|
||||||
public enum PairTypes
|
public enum PairTypes
|
||||||
{
|
{
|
@ -4,10 +4,10 @@ using System.Linq;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using UnityExplorer.UI;
|
using UnityExplorer.UI;
|
||||||
using UnityExplorer.Helpers;
|
using UnityExplorer.Core.Unity;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace UnityExplorer.Inspectors.Reflection
|
namespace UnityExplorer.Core.Inspectors.Reflection
|
||||||
{
|
{
|
||||||
public class CacheProperty : CacheMember
|
public class CacheProperty : CacheMember
|
||||||
{
|
{
|
54
src/Core/Inspectors/Reflection/InstanceInspector.cs
Normal file
54
src/Core/Inspectors/Reflection/InstanceInspector.cs
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
using System;
|
||||||
|
using System.Reflection;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityExplorer.UI;
|
||||||
|
using UnityEngine.UI;
|
||||||
|
using System.IO;
|
||||||
|
using UnityExplorer.Core.Runtime;
|
||||||
|
using UnityExplorer.UI.Main.Home.Inspectors;
|
||||||
|
|
||||||
|
namespace UnityExplorer.Core.Inspectors.Reflection
|
||||||
|
{
|
||||||
|
public enum MemberScopes
|
||||||
|
{
|
||||||
|
All,
|
||||||
|
Instance,
|
||||||
|
Static
|
||||||
|
}
|
||||||
|
|
||||||
|
public class InstanceInspector : ReflectionInspector
|
||||||
|
{
|
||||||
|
public override string TabLabel => $" <color=cyan>[R]</color> {base.TabLabel}";
|
||||||
|
|
||||||
|
internal MemberScopes m_scopeFilter;
|
||||||
|
internal Button m_lastActiveScopeButton;
|
||||||
|
|
||||||
|
public InstanceInspector(object target) : base(target) { }
|
||||||
|
|
||||||
|
internal InstanceInspectorUI InstanceUI;
|
||||||
|
public void CreateInstanceUIModule()
|
||||||
|
{
|
||||||
|
InstanceUI = new InstanceInspectorUI(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void OnScopeFilterClicked(MemberScopes type, Button button)
|
||||||
|
{
|
||||||
|
if (m_lastActiveScopeButton)
|
||||||
|
{
|
||||||
|
var lastColors = m_lastActiveScopeButton.colors;
|
||||||
|
lastColors.normalColor = new Color(0.2f, 0.2f, 0.2f);
|
||||||
|
m_lastActiveScopeButton.colors = lastColors;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_scopeFilter = type;
|
||||||
|
m_lastActiveScopeButton = button;
|
||||||
|
|
||||||
|
var colors = m_lastActiveScopeButton.colors;
|
||||||
|
colors.normalColor = new Color(0.2f, 0.6f, 0.2f);
|
||||||
|
m_lastActiveScopeButton.colors = colors;
|
||||||
|
|
||||||
|
FilterMembers(null, true);
|
||||||
|
base.ReflectionUI.m_sliderScroller.m_slider.value = 1f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -4,10 +4,10 @@ using System.Linq;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using UnityExplorer.Helpers;
|
using UnityExplorer.Core.Unity;
|
||||||
using UnityExplorer.UI;
|
using UnityExplorer.UI;
|
||||||
|
|
||||||
namespace UnityExplorer.Inspectors.Reflection
|
namespace UnityExplorer.Core.Inspectors.Reflection
|
||||||
{
|
{
|
||||||
public class InteractiveBool : InteractiveValue
|
public class InteractiveBool : InteractiveValue
|
||||||
{
|
{
|
@ -5,16 +5,16 @@ using System.Linq;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using UnityExplorer.Config;
|
using UnityExplorer.Core.Config;
|
||||||
using UnityExplorer.Helpers;
|
using UnityExplorer.Core.Unity;
|
||||||
using UnityExplorer.UI;
|
using UnityExplorer.UI;
|
||||||
using UnityExplorer.UI.Shared;
|
using UnityExplorer.UI.Reusable;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
#if CPP
|
#if CPP
|
||||||
using CppDictionary = Il2CppSystem.Collections.IDictionary;
|
using CppDictionary = Il2CppSystem.Collections.IDictionary;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace UnityExplorer.Inspectors.Reflection
|
namespace UnityExplorer.Core.Inspectors.Reflection
|
||||||
{
|
{
|
||||||
public class InteractiveDictionary : InteractiveValue
|
public class InteractiveDictionary : InteractiveValue
|
||||||
{
|
{
|
@ -4,10 +4,10 @@ using System.Linq;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using UnityExplorer.Helpers;
|
using UnityExplorer.Core.Unity;
|
||||||
using UnityExplorer.UI;
|
using UnityExplorer.UI;
|
||||||
|
|
||||||
namespace UnityExplorer.Inspectors.Reflection
|
namespace UnityExplorer.Core.Inspectors.Reflection
|
||||||
{
|
{
|
||||||
public class InteractiveEnum : InteractiveValue
|
public class InteractiveEnum : InteractiveValue
|
||||||
{
|
{
|
@ -6,12 +6,12 @@ using System.Reflection;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using UnityExplorer.Config;
|
using UnityExplorer.Core.Config;
|
||||||
using UnityExplorer.Helpers;
|
using UnityExplorer.Core.Unity;
|
||||||
using UnityExplorer.UI;
|
using UnityExplorer.UI;
|
||||||
using UnityExplorer.UI.Shared;
|
using UnityExplorer.UI.Reusable;
|
||||||
|
|
||||||
namespace UnityExplorer.Inspectors.Reflection
|
namespace UnityExplorer.Core.Inspectors.Reflection
|
||||||
{
|
{
|
||||||
public class InteractiveEnumerable : InteractiveValue
|
public class InteractiveEnumerable : InteractiveValue
|
||||||
{
|
{
|
@ -4,10 +4,10 @@ using System.Linq;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using UnityExplorer.Helpers;
|
using UnityExplorer.Core.Unity;
|
||||||
using UnityExplorer.UI;
|
using UnityExplorer.UI;
|
||||||
|
|
||||||
namespace UnityExplorer.Inspectors.Reflection
|
namespace UnityExplorer.Core.Inspectors.Reflection
|
||||||
{
|
{
|
||||||
public class InteractiveFlags : InteractiveEnum
|
public class InteractiveFlags : InteractiveEnum
|
||||||
{
|
{
|
@ -5,10 +5,12 @@ using System.Text;
|
|||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using UnityExplorer.Helpers;
|
using UnityExplorer.Core.Unity;
|
||||||
using UnityExplorer.UI;
|
using UnityExplorer.UI;
|
||||||
|
using UnityExplorer.Core;
|
||||||
|
using UnityExplorer.UI.Utility;
|
||||||
|
|
||||||
namespace UnityExplorer.Inspectors.Reflection
|
namespace UnityExplorer.Core.Inspectors.Reflection
|
||||||
{
|
{
|
||||||
public class InteractiveNumber : InteractiveValue
|
public class InteractiveNumber : InteractiveValue
|
||||||
{
|
{
|
||||||
@ -46,7 +48,7 @@ namespace UnityExplorer.Inspectors.Reflection
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_baseLabel.text = UISyntaxHighlight.ParseFullSyntax(FallbackType, false);
|
m_baseLabel.text = SignatureHighlighter.ParseFullSyntax(FallbackType, false);
|
||||||
m_valueInput.text = Value.ToString();
|
m_valueInput.text = Value.ToString();
|
||||||
|
|
||||||
var type = Value.GetType();
|
var type = Value.GetType();
|
||||||
@ -84,7 +86,7 @@ namespace UnityExplorer.Inspectors.Reflection
|
|||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
ExplorerCore.LogWarning("Could not parse input! " + ReflectionHelpers.ExceptionToString(e, true));
|
ExplorerCore.LogWarning("Could not parse input! " + ReflectionUtility.ReflectionExToString(e, true));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -5,10 +5,11 @@ using System.Text;
|
|||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using UnityExplorer.Helpers;
|
using UnityExplorer.Core.Unity;
|
||||||
using UnityExplorer.UI;
|
using UnityExplorer.UI;
|
||||||
|
using UnityExplorer.UI.Utility;
|
||||||
|
|
||||||
namespace UnityExplorer.Inspectors.Reflection
|
namespace UnityExplorer.Core.Inspectors.Reflection
|
||||||
{
|
{
|
||||||
public class InteractiveString : InteractiveValue
|
public class InteractiveString : InteractiveValue
|
||||||
{
|
{
|
||||||
@ -109,7 +110,7 @@ namespace UnityExplorer.Inspectors.Reflection
|
|||||||
base.ConstructUI(parent, subGroup);
|
base.ConstructUI(parent, subGroup);
|
||||||
|
|
||||||
GetDefaultLabel(false);
|
GetDefaultLabel(false);
|
||||||
m_richValueType = UISyntaxHighlight.ParseFullSyntax(FallbackType, false);
|
m_richValueType = SignatureHighlighter.ParseFullSyntax(FallbackType, false);
|
||||||
|
|
||||||
m_labelLayout = m_baseLabel.gameObject.GetComponent<LayoutElement>();
|
m_labelLayout = m_baseLabel.gameObject.GetComponent<LayoutElement>();
|
||||||
|
|
@ -4,10 +4,10 @@ using System.Linq;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using UnityExplorer.Helpers;
|
using UnityExplorer.Core.Unity;
|
||||||
using UnityExplorer.UI;
|
using UnityExplorer.UI;
|
||||||
|
|
||||||
namespace UnityExplorer.Inspectors.Reflection
|
namespace UnityExplorer.Core.Inspectors.Reflection
|
||||||
{
|
{
|
||||||
#region IStructInfo helper
|
#region IStructInfo helper
|
||||||
|
|
@ -5,10 +5,13 @@ using System.Reflection;
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.EventSystems;
|
using UnityEngine.EventSystems;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using UnityExplorer.Helpers;
|
using UnityExplorer.Core;
|
||||||
|
using UnityExplorer.Core.Unity;
|
||||||
|
using UnityExplorer.Core.Runtime;
|
||||||
using UnityExplorer.UI;
|
using UnityExplorer.UI;
|
||||||
|
using UnityExplorer.UI.Utility;
|
||||||
|
|
||||||
namespace UnityExplorer.Inspectors.Reflection
|
namespace UnityExplorer.Core.Inspectors.Reflection
|
||||||
{
|
{
|
||||||
public class InteractiveValue
|
public class InteractiveValue
|
||||||
{
|
{
|
||||||
@ -47,10 +50,10 @@ namespace UnityExplorer.Inspectors.Reflection
|
|||||||
else if (typeof(Transform).IsAssignableFrom(type))
|
else if (typeof(Transform).IsAssignableFrom(type))
|
||||||
return typeof(InteractiveValue);
|
return typeof(InteractiveValue);
|
||||||
// check Dictionaries before Enumerables
|
// check Dictionaries before Enumerables
|
||||||
else if (ReflectionHelpers.IsDictionary(type))
|
else if (ReflectionUtility.IsDictionary(type))
|
||||||
return typeof(InteractiveDictionary);
|
return typeof(InteractiveDictionary);
|
||||||
// finally check for Enumerables
|
// finally check for Enumerables
|
||||||
else if (ReflectionHelpers.IsEnumerable(type))
|
else if (ReflectionUtility.IsEnumerable(type))
|
||||||
return typeof(InteractiveEnumerable);
|
return typeof(InteractiveEnumerable);
|
||||||
// fallback to default
|
// fallback to default
|
||||||
else
|
else
|
||||||
@ -59,7 +62,7 @@ namespace UnityExplorer.Inspectors.Reflection
|
|||||||
|
|
||||||
public static InteractiveValue Create(object value, Type fallbackType)
|
public static InteractiveValue Create(object value, Type fallbackType)
|
||||||
{
|
{
|
||||||
var type = ReflectionHelpers.GetActualType(value) ?? fallbackType;
|
var type = ReflectionUtility.GetType(value) ?? fallbackType;
|
||||||
var iType = GetIValueForType(type);
|
var iType = GetIValueForType(type);
|
||||||
|
|
||||||
return (InteractiveValue)Activator.CreateInstance(iType, new object[] { value, type });
|
return (InteractiveValue)Activator.CreateInstance(iType, new object[] { value, type });
|
||||||
@ -202,7 +205,7 @@ namespace UnityExplorer.Inspectors.Reflection
|
|||||||
{
|
{
|
||||||
var valueType = Value?.GetType() ?? this.FallbackType;
|
var valueType = Value?.GetType() ?? this.FallbackType;
|
||||||
if (updateType)
|
if (updateType)
|
||||||
m_richValueType = UISyntaxHighlight.ParseFullSyntax(valueType, true);
|
m_richValueType = SignatureHighlighter.ParseFullSyntax(valueType, true);
|
||||||
|
|
||||||
if (!Owner.HasEvaluated)
|
if (!Owner.HasEvaluated)
|
||||||
return m_defaultLabel = $"<i><color=grey>Not yet evaluated</color> ({m_richValueType})</i>";
|
return m_defaultLabel = $"<i><color=grey>Not yet evaluated</color> ({m_richValueType})</i>";
|
||||||
@ -255,14 +258,8 @@ namespace UnityExplorer.Inspectors.Reflection
|
|||||||
string typeName = valueType.FullName;
|
string typeName = valueType.FullName;
|
||||||
if (typeName.StartsWith("Il2CppSystem."))
|
if (typeName.StartsWith("Il2CppSystem."))
|
||||||
typeName = typeName.Substring(6, typeName.Length - 6);
|
typeName = typeName.Substring(6, typeName.Length - 6);
|
||||||
#if CPP
|
|
||||||
var cppType = UnhollowerRuntimeLib.Il2CppType.From(valueType);
|
toString = ReflectionProvider.Instance.ProcessTypeNameInString(valueType, toString, ref typeName);
|
||||||
if (cppType != null && ReflectionHelpers.UnobfuscatedTypeNames.ContainsKey(cppType.FullName))
|
|
||||||
{
|
|
||||||
typeName = ReflectionHelpers.UnobfuscatedTypeNames[cppType.FullName];
|
|
||||||
toString = toString.Replace(cppType.FullName, typeName);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// If the ToString is just the type name, use our syntax highlighted type name instead.
|
// If the ToString is just the type name, use our syntax highlighted type name instead.
|
||||||
if (toString == typeName)
|
if (toString == typeName)
|
360
src/Core/Inspectors/Reflection/ReflectionInspector.cs
Normal file
360
src/Core/Inspectors/Reflection/ReflectionInspector.cs
Normal file
@ -0,0 +1,360 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using UnityExplorer.Core.Unity;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityExplorer.Core.Inspectors.Reflection;
|
||||||
|
using UnityExplorer.UI.Reusable;
|
||||||
|
using System.Reflection;
|
||||||
|
using UnityExplorer.UI;
|
||||||
|
using UnityEngine.UI;
|
||||||
|
using UnityExplorer.Core.Config;
|
||||||
|
using UnityExplorer.Core;
|
||||||
|
using UnityExplorer.UI.Utility;
|
||||||
|
using UnityExplorer.UI.Main.Home.Inspectors;
|
||||||
|
|
||||||
|
namespace UnityExplorer.Core.Inspectors
|
||||||
|
{
|
||||||
|
public class ReflectionInspector : InspectorBase
|
||||||
|
{
|
||||||
|
#region STATIC
|
||||||
|
|
||||||
|
public static ReflectionInspector ActiveInstance { get; private set; }
|
||||||
|
|
||||||
|
static ReflectionInspector()
|
||||||
|
{
|
||||||
|
PanelDragger.OnFinishResize += OnContainerResized;
|
||||||
|
SceneExplorer.OnToggleShow += OnContainerResized;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void OnContainerResized()
|
||||||
|
{
|
||||||
|
if (ActiveInstance == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ActiveInstance.ReflectionUI.m_widthUpdateWanted = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Blacklists
|
||||||
|
private static readonly HashSet<string> bl_typeAndMember = new HashSet<string>
|
||||||
|
{
|
||||||
|
#if CPP
|
||||||
|
// these cause a crash in IL2CPP
|
||||||
|
"Type.DeclaringMethod",
|
||||||
|
"Rigidbody2D.Cast",
|
||||||
|
"Collider2D.Cast",
|
||||||
|
"Collider2D.Raycast",
|
||||||
|
"Texture2D.SetPixelDataImpl",
|
||||||
|
"Camera.CalculateProjectionMatrixFromPhysicalProperties",
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
private static readonly HashSet<string> bl_memberNameStartsWith = new HashSet<string>
|
||||||
|
{
|
||||||
|
// these are redundant
|
||||||
|
"get_",
|
||||||
|
"set_",
|
||||||
|
};
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region INSTANCE
|
||||||
|
|
||||||
|
public override string TabLabel => m_targetTypeShortName;
|
||||||
|
|
||||||
|
internal CacheObjectBase ParentMember { get; set; }
|
||||||
|
|
||||||
|
internal ReflectionInspectorUI ReflectionUI;
|
||||||
|
|
||||||
|
internal readonly Type m_targetType;
|
||||||
|
internal readonly string m_targetTypeShortName;
|
||||||
|
|
||||||
|
// all cached members of the target
|
||||||
|
internal CacheMember[] m_allMembers;
|
||||||
|
// filtered members based on current filters
|
||||||
|
internal readonly List<CacheMember> m_membersFiltered = new List<CacheMember>();
|
||||||
|
// actual shortlist of displayed members
|
||||||
|
internal readonly CacheMember[] m_displayedMembers = new CacheMember[ExplorerConfig.Instance.Default_Page_Limit];
|
||||||
|
|
||||||
|
internal bool m_autoUpdate;
|
||||||
|
|
||||||
|
public ReflectionInspector(object target) : base(target)
|
||||||
|
{
|
||||||
|
if (this is StaticInspector)
|
||||||
|
m_targetType = target as Type;
|
||||||
|
else
|
||||||
|
m_targetType = ReflectionUtility.GetType(target);
|
||||||
|
|
||||||
|
m_targetTypeShortName = SignatureHighlighter.ParseFullSyntax(m_targetType, false);
|
||||||
|
|
||||||
|
ReflectionUI.ConstructUI();
|
||||||
|
|
||||||
|
CacheMembers(m_targetType);
|
||||||
|
|
||||||
|
FilterMembers();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void CreateUIModule()
|
||||||
|
{
|
||||||
|
BaseUI = ReflectionUI = new ReflectionInspectorUI(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void SetActive()
|
||||||
|
{
|
||||||
|
base.SetActive();
|
||||||
|
ActiveInstance = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void SetInactive()
|
||||||
|
{
|
||||||
|
base.SetInactive();
|
||||||
|
ActiveInstance = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Destroy()
|
||||||
|
{
|
||||||
|
base.Destroy();
|
||||||
|
|
||||||
|
if (this.BaseUI.Content)
|
||||||
|
GameObject.Destroy(this.BaseUI.Content);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void OnPageTurned()
|
||||||
|
{
|
||||||
|
RefreshDisplay();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal bool IsBlacklisted(string sig) => bl_typeAndMember.Any(it => sig.Contains(it));
|
||||||
|
internal bool IsBlacklisted(MethodInfo method) => bl_memberNameStartsWith.Any(it => method.Name.StartsWith(it));
|
||||||
|
|
||||||
|
internal string GetSig(MemberInfo member) => $"{member.DeclaringType.Name}.{member.Name}";
|
||||||
|
internal string AppendArgsToSig(ParameterInfo[] args)
|
||||||
|
{
|
||||||
|
string ret = " (";
|
||||||
|
foreach (var param in args)
|
||||||
|
ret += $"{param.ParameterType.Name} {param.Name}, ";
|
||||||
|
ret += ")";
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CacheMembers(Type type)
|
||||||
|
{
|
||||||
|
var list = new List<CacheMember>();
|
||||||
|
var cachedSigs = new HashSet<string>();
|
||||||
|
|
||||||
|
var types = ReflectionUtility.GetAllBaseTypes(type);
|
||||||
|
|
||||||
|
var flags = BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static;
|
||||||
|
if (this is InstanceInspector)
|
||||||
|
flags |= BindingFlags.Instance;
|
||||||
|
|
||||||
|
foreach (var declaringType in types)
|
||||||
|
{
|
||||||
|
var target = Target;
|
||||||
|
target = target.Cast(declaringType);
|
||||||
|
|
||||||
|
IEnumerable<MemberInfo> infos = declaringType.GetMethods(flags);
|
||||||
|
infos = infos.Concat(declaringType.GetProperties(flags));
|
||||||
|
infos = infos.Concat(declaringType.GetFields(flags));
|
||||||
|
|
||||||
|
foreach (var member in infos)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var sig = GetSig(member);
|
||||||
|
|
||||||
|
//ExplorerCore.Log($"Trying to cache member {sig}...");
|
||||||
|
//ExplorerCore.Log(member.DeclaringType.FullName + "." + member.Name);
|
||||||
|
|
||||||
|
var mi = member as MethodInfo;
|
||||||
|
var pi = member as PropertyInfo;
|
||||||
|
var fi = member as FieldInfo;
|
||||||
|
|
||||||
|
if (IsBlacklisted(sig) || (mi != null && IsBlacklisted(mi)))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
var args = mi?.GetParameters() ?? pi?.GetIndexParameters();
|
||||||
|
if (args != null)
|
||||||
|
{
|
||||||
|
if (!CacheMember.CanProcessArgs(args))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
sig += AppendArgsToSig(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cachedSigs.Contains(sig))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
cachedSigs.Add(sig);
|
||||||
|
|
||||||
|
if (mi != null)
|
||||||
|
list.Add(new CacheMethod(mi, target, ReflectionUI.m_scrollContent));
|
||||||
|
else if (pi != null)
|
||||||
|
list.Add(new CacheProperty(pi, target, ReflectionUI.m_scrollContent));
|
||||||
|
else
|
||||||
|
list.Add(new CacheField(fi, target, ReflectionUI.m_scrollContent));
|
||||||
|
|
||||||
|
list.Last().ParentInspector = this;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
ExplorerCore.LogWarning($"Exception caching member {member.DeclaringType.FullName}.{member.Name}!");
|
||||||
|
ExplorerCore.Log(e.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var typeList = types.ToList();
|
||||||
|
|
||||||
|
var sorted = new List<CacheMember>();
|
||||||
|
sorted.AddRange(list.Where(it => it is CacheMethod)
|
||||||
|
.OrderBy(it => typeList.IndexOf(it.DeclaringType))
|
||||||
|
.ThenBy(it => it.NameForFiltering));
|
||||||
|
sorted.AddRange(list.Where(it => it is CacheProperty)
|
||||||
|
.OrderBy(it => typeList.IndexOf(it.DeclaringType))
|
||||||
|
.ThenBy(it => it.NameForFiltering));
|
||||||
|
sorted.AddRange(list.Where(it => it is CacheField)
|
||||||
|
.OrderBy(it => typeList.IndexOf(it.DeclaringType))
|
||||||
|
.ThenBy(it => it.NameForFiltering));
|
||||||
|
|
||||||
|
m_allMembers = sorted.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Update()
|
||||||
|
{
|
||||||
|
base.Update();
|
||||||
|
|
||||||
|
if (m_autoUpdate)
|
||||||
|
{
|
||||||
|
foreach (var member in m_displayedMembers)
|
||||||
|
{
|
||||||
|
if (member == null) break;
|
||||||
|
member.UpdateValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ReflectionUI.m_widthUpdateWanted)
|
||||||
|
{
|
||||||
|
if (!ReflectionUI.m_widthUpdateWaiting)
|
||||||
|
ReflectionUI.m_widthUpdateWaiting = true;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UpdateWidths();
|
||||||
|
ReflectionUI.m_widthUpdateWaiting = false;
|
||||||
|
ReflectionUI.m_widthUpdateWanted = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void OnMemberFilterClicked(MemberTypes type, Button button)
|
||||||
|
{
|
||||||
|
if (ReflectionUI.m_lastActiveMemButton)
|
||||||
|
{
|
||||||
|
var lastColors = ReflectionUI.m_lastActiveMemButton.colors;
|
||||||
|
lastColors.normalColor = new Color(0.2f, 0.2f, 0.2f);
|
||||||
|
ReflectionUI.m_lastActiveMemButton.colors = lastColors;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReflectionUI.m_memberFilter = type;
|
||||||
|
ReflectionUI.m_lastActiveMemButton = button;
|
||||||
|
|
||||||
|
var colors = ReflectionUI.m_lastActiveMemButton.colors;
|
||||||
|
colors.normalColor = new Color(0.2f, 0.6f, 0.2f);
|
||||||
|
ReflectionUI.m_lastActiveMemButton.colors = colors;
|
||||||
|
|
||||||
|
FilterMembers(null, true);
|
||||||
|
ReflectionUI.m_sliderScroller.m_slider.value = 1f;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void FilterMembers(string nameFilter = null, bool force = false)
|
||||||
|
{
|
||||||
|
int lastCount = m_membersFiltered.Count;
|
||||||
|
m_membersFiltered.Clear();
|
||||||
|
|
||||||
|
nameFilter = nameFilter?.ToLower() ?? ReflectionUI.m_nameFilterText.text.ToLower();
|
||||||
|
|
||||||
|
foreach (var mem in m_allMembers)
|
||||||
|
{
|
||||||
|
// membertype filter
|
||||||
|
if (ReflectionUI.m_memberFilter != MemberTypes.All && mem.MemInfo.MemberType != ReflectionUI.m_memberFilter)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (this is InstanceInspector ii && ii.m_scopeFilter != MemberScopes.All)
|
||||||
|
{
|
||||||
|
if (mem.IsStatic && ii.m_scopeFilter != MemberScopes.Static)
|
||||||
|
continue;
|
||||||
|
else if (!mem.IsStatic && ii.m_scopeFilter != MemberScopes.Instance)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// name filter
|
||||||
|
if (!string.IsNullOrEmpty(nameFilter) && !mem.NameForFiltering.Contains(nameFilter))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
m_membersFiltered.Add(mem);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (force || lastCount != m_membersFiltered.Count)
|
||||||
|
RefreshDisplay();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RefreshDisplay()
|
||||||
|
{
|
||||||
|
var members = m_membersFiltered;
|
||||||
|
ReflectionUI.m_pageHandler.ListCount = members.Count;
|
||||||
|
|
||||||
|
// disable current members
|
||||||
|
for (int i = 0; i < m_displayedMembers.Length; i++)
|
||||||
|
{
|
||||||
|
var mem = m_displayedMembers[i];
|
||||||
|
if (mem != null)
|
||||||
|
mem.Disable();
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (members.Count < 1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
foreach (var itemIndex in ReflectionUI.m_pageHandler)
|
||||||
|
{
|
||||||
|
if (itemIndex >= members.Count)
|
||||||
|
break;
|
||||||
|
|
||||||
|
CacheMember member = members[itemIndex];
|
||||||
|
m_displayedMembers[itemIndex - ReflectionUI.m_pageHandler.StartIndex] = member;
|
||||||
|
member.Enable();
|
||||||
|
}
|
||||||
|
|
||||||
|
ReflectionUI.m_widthUpdateWanted = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void UpdateWidths()
|
||||||
|
{
|
||||||
|
float labelWidth = 125;
|
||||||
|
|
||||||
|
foreach (var cache in m_displayedMembers)
|
||||||
|
{
|
||||||
|
if (cache == null)
|
||||||
|
break;
|
||||||
|
|
||||||
|
var width = cache.GetMemberLabelWidth(ReflectionUI.m_scrollContentRect);
|
||||||
|
|
||||||
|
if (width > labelWidth)
|
||||||
|
labelWidth = width;
|
||||||
|
}
|
||||||
|
|
||||||
|
float valueWidth = ReflectionUI.m_scrollContentRect.rect.width - labelWidth - 20;
|
||||||
|
|
||||||
|
foreach (var cache in m_displayedMembers)
|
||||||
|
{
|
||||||
|
if (cache == null)
|
||||||
|
break;
|
||||||
|
cache.SetWidths(labelWidth, valueWidth);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endregion // end instance
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace UnityExplorer.Inspectors.Reflection
|
namespace UnityExplorer.Core.Inspectors.Reflection
|
||||||
{
|
{
|
||||||
public class StaticInspector : ReflectionInspector
|
public class StaticInspector : ReflectionInspector
|
||||||
{
|
{
|
186
src/Core/ReflectionUtility.cs
Normal file
186
src/Core/ReflectionUtility.cs
Normal file
@ -0,0 +1,186 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using BF = System.Reflection.BindingFlags;
|
||||||
|
using UnityExplorer.Core.Runtime;
|
||||||
|
|
||||||
|
namespace UnityExplorer.Core
|
||||||
|
{
|
||||||
|
public static class ReflectionUtility
|
||||||
|
{
|
||||||
|
public static BF CommonFlags = BF.Public | BF.Instance | BF.NonPublic | BF.Static;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Helper for IL2CPP to get the underlying true Type (Unhollowed) of the object.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="obj">The object to get the true Type for.</param>
|
||||||
|
/// <returns>The most accurate Type of the object which could be identified.</returns>
|
||||||
|
public static Type GetType(this object obj)
|
||||||
|
{
|
||||||
|
if (obj == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return ReflectionProvider.Instance.GetActualType(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Cast an object to its underlying Type.
|
||||||
|
/// </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)
|
||||||
|
=> Cast(obj, GetType(obj));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Cast an object to a Type, if possible.
|
||||||
|
/// </summary>
|
||||||
|
/// <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)
|
||||||
|
=> ReflectionProvider.Instance.Cast(obj, castTo);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Check if the provided Type is assignable to IEnumerable.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="t">The Type to check</param>
|
||||||
|
/// <returns>True if the Type is assignable to IEnumerable, otherwise false.</returns>
|
||||||
|
public static bool IsEnumerable(this Type t)
|
||||||
|
=> ReflectionProvider.Instance.IsAssignableFrom(typeof(IEnumerable), t);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Check if the provided Type is assignable to IDictionary.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="t">The Type to check</param>
|
||||||
|
/// <returns>True if the Type is assignable to IDictionary, otherwise false.</returns>
|
||||||
|
public static bool IsDictionary(this Type t)
|
||||||
|
=> ReflectionProvider.Instance.IsAssignableFrom(typeof(IDictionary), t);
|
||||||
|
|
||||||
|
public static bool LoadModule(string module)
|
||||||
|
=> ReflectionProvider.Instance.LoadModule(module);
|
||||||
|
|
||||||
|
// cache for GetTypeByName
|
||||||
|
internal static readonly Dictionary<string, Type> s_typesByName = new Dictionary<string, Type>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Find a <see cref="Type"/> in the current AppDomain whose <see cref="Type.FullName"/> matches the provided <paramref name="fullName"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="fullName">The <see cref="Type.FullName"/> you want to search for - case sensitive and full matches only.</param>
|
||||||
|
/// <returns>The Type if found, otherwise null.</returns>
|
||||||
|
public static Type GetTypeByName(string fullName)
|
||||||
|
{
|
||||||
|
s_typesByName.TryGetValue(fullName, out Type ret);
|
||||||
|
|
||||||
|
if (ret != null)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
foreach (var type in from asm in AppDomain.CurrentDomain.GetAssemblies()
|
||||||
|
from type in asm.TryGetTypes()
|
||||||
|
select type)
|
||||||
|
{
|
||||||
|
if (type.FullName == fullName)
|
||||||
|
{
|
||||||
|
ret = type;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s_typesByName.ContainsKey(fullName))
|
||||||
|
s_typesByName[fullName] = ret;
|
||||||
|
else
|
||||||
|
s_typesByName.Add(fullName, ret);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// cache for GetBaseTypes
|
||||||
|
internal static readonly Dictionary<string, Type[]> s_cachedTypeInheritance = new Dictionary<string, Type[]>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get all base types of the provided Type, including itself.
|
||||||
|
/// </summary>
|
||||||
|
public static Type[] GetAllBaseTypes(this object obj) => GetAllBaseTypes(GetType(obj));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get all base types of the provided Type, including itself.
|
||||||
|
/// </summary>
|
||||||
|
public static Type[] GetAllBaseTypes(this Type type)
|
||||||
|
{
|
||||||
|
if (type == null)
|
||||||
|
throw new ArgumentNullException("type");
|
||||||
|
|
||||||
|
var name = type.AssemblyQualifiedName;
|
||||||
|
|
||||||
|
if (s_cachedTypeInheritance.TryGetValue(name, out Type[] ret))
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
List<Type> list = new List<Type>();
|
||||||
|
|
||||||
|
while (type != null)
|
||||||
|
{
|
||||||
|
list.Add(type);
|
||||||
|
type = type.BaseType;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = list.ToArray();
|
||||||
|
|
||||||
|
s_cachedTypeInheritance.Add(name, ret);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Safely get all valid Types inside an Assembly.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="asm">The Assembly to find Types in.</param>
|
||||||
|
/// <returns>All possible Types which could be retrieved from the Assembly, or an empty array.</returns>
|
||||||
|
public static IEnumerable<Type> TryGetTypes(this Assembly asm)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return asm.GetTypes();
|
||||||
|
}
|
||||||
|
catch (ReflectionTypeLoadException e)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return asm.GetExportedTypes();
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return e.Types.Where(t => t != null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return Enumerable.Empty<Type>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Helper to display a simple "{ExceptionType}: {Message}" of the exception, and optionally use the inner-most exception.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="e">The Exception to convert to string.</param>
|
||||||
|
/// <param name="innerMost">Should the inner-most Exception of the stack be used? If false, the Exception you provided will be used directly.</param>
|
||||||
|
/// <returns>The exception to string.</returns>
|
||||||
|
public static string ReflectionExToString(this Exception e, bool innerMost = false)
|
||||||
|
{
|
||||||
|
if (innerMost)
|
||||||
|
{
|
||||||
|
while (e.InnerException != null)
|
||||||
|
{
|
||||||
|
#if CPP
|
||||||
|
if (e.InnerException is System.Runtime.CompilerServices.RuntimeWrappedException)
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
e = e.InnerException;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $"{e.GetType()}: {e.Message}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -6,9 +6,9 @@ using System.Text;
|
|||||||
using UnhollowerBaseLib;
|
using UnhollowerBaseLib;
|
||||||
using UnhollowerRuntimeLib;
|
using UnhollowerRuntimeLib;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityExplorer.Helpers;
|
using UnityExplorer.Core.Runtime.Il2Cpp;
|
||||||
|
|
||||||
namespace UnityExplorer.Unstrip
|
namespace UnityExplorer
|
||||||
{
|
{
|
||||||
public class AssetBundle
|
public class AssetBundle
|
||||||
{
|
{
|
||||||
@ -18,7 +18,7 @@ namespace UnityExplorer.Unstrip
|
|||||||
|
|
||||||
public static AssetBundle LoadFromFile(string path)
|
public static AssetBundle LoadFromFile(string path)
|
||||||
{
|
{
|
||||||
var iCall = ICallHelper.GetICall<d_LoadFromFile>("UnityEngine.AssetBundle::LoadFromFile_Internal");
|
var iCall = ICallManager.GetICall<d_LoadFromFile>("UnityEngine.AssetBundle::LoadFromFile_Internal");
|
||||||
|
|
||||||
var ptr = iCall.Invoke(IL2CPP.ManagedStringToIl2Cpp(path), 0u, 0UL);
|
var ptr = iCall.Invoke(IL2CPP.ManagedStringToIl2Cpp(path), 0u, 0UL);
|
||||||
|
|
||||||
@ -29,7 +29,7 @@ namespace UnityExplorer.Unstrip
|
|||||||
|
|
||||||
public static AssetBundle LoadFromMemory(byte[] binary, uint crc = 0)
|
public static AssetBundle LoadFromMemory(byte[] binary, uint crc = 0)
|
||||||
{
|
{
|
||||||
var iCall = ICallHelper.GetICall<d_LoadFromMemory>("UnityEngine.AssetBundle::LoadFromMemory_Internal");
|
var iCall = ICallManager.GetICall<d_LoadFromMemory>("UnityEngine.AssetBundle::LoadFromMemory_Internal");
|
||||||
|
|
||||||
var ptr = iCall(((Il2CppStructArray<byte>) binary).Pointer, crc);
|
var ptr = iCall(((Il2CppStructArray<byte>) binary).Pointer, crc);
|
||||||
|
|
||||||
@ -48,7 +48,7 @@ namespace UnityExplorer.Unstrip
|
|||||||
|
|
||||||
public UnityEngine.Object[] LoadAllAssets()
|
public UnityEngine.Object[] LoadAllAssets()
|
||||||
{
|
{
|
||||||
var iCall = ICallHelper.GetICall<d_LoadAssetWithSubAssets_Internal>("UnityEngine.AssetBundle::LoadAssetWithSubAssets_Internal");
|
var iCall = ICallManager.GetICall<d_LoadAssetWithSubAssets_Internal>("UnityEngine.AssetBundle::LoadAssetWithSubAssets_Internal");
|
||||||
var ptr = iCall.Invoke(m_bundlePtr, IL2CPP.ManagedStringToIl2Cpp(""), Il2CppType.Of<UnityEngine.Object>().Pointer);
|
var ptr = iCall.Invoke(m_bundlePtr, IL2CPP.ManagedStringToIl2Cpp(""), Il2CppType.Of<UnityEngine.Object>().Pointer);
|
||||||
|
|
||||||
if (ptr == IntPtr.Zero)
|
if (ptr == IntPtr.Zero)
|
||||||
@ -63,7 +63,7 @@ namespace UnityExplorer.Unstrip
|
|||||||
|
|
||||||
public T LoadAsset<T>(string name) where T : UnityEngine.Object
|
public T LoadAsset<T>(string name) where T : UnityEngine.Object
|
||||||
{
|
{
|
||||||
var iCall = ICallHelper.GetICall<d_LoadAsset_Internal>("UnityEngine.AssetBundle::LoadAsset_Internal");
|
var iCall = ICallManager.GetICall<d_LoadAsset_Internal>("UnityEngine.AssetBundle::LoadAsset_Internal");
|
||||||
var ptr = iCall.Invoke(m_bundlePtr, IL2CPP.ManagedStringToIl2Cpp(name), Il2CppType.Of<T>().Pointer);
|
var ptr = iCall.Invoke(m_bundlePtr, IL2CPP.ManagedStringToIl2Cpp(name), Il2CppType.Of<T>().Pointer);
|
||||||
|
|
||||||
if (ptr == IntPtr.Zero)
|
if (ptr == IntPtr.Zero)
|
@ -4,10 +4,10 @@ using System.Collections.Generic;
|
|||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
namespace UnityExplorer.Helpers
|
namespace UnityExplorer.Core.Runtime.Il2Cpp
|
||||||
{
|
{
|
||||||
[SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "External methods")]
|
[SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "External methods")]
|
||||||
public static class ICallHelper
|
public static class ICallManager
|
||||||
{
|
{
|
||||||
private static readonly Dictionary<string, Delegate> iCallCache = new Dictionary<string, Delegate>();
|
private static readonly Dictionary<string, Delegate> iCallCache = new Dictionary<string, Delegate>();
|
||||||
|
|
107
src/Core/Runtime/Il2Cpp/Il2CppProvider.cs
Normal file
107
src/Core/Runtime/Il2Cpp/Il2CppProvider.cs
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
#if CPP
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using UnhollowerBaseLib;
|
||||||
|
using UnhollowerRuntimeLib;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.Events;
|
||||||
|
using UnityEngine.SceneManagement;
|
||||||
|
|
||||||
|
namespace UnityExplorer.Core.Runtime.Il2Cpp
|
||||||
|
{
|
||||||
|
public class Il2CppProvider : RuntimeProvider
|
||||||
|
{
|
||||||
|
public override void Initialize()
|
||||||
|
{
|
||||||
|
Reflection = new Il2CppReflection();
|
||||||
|
TextureUtil = new Il2CppTextureUtil();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void SetupEvents()
|
||||||
|
{
|
||||||
|
Application.add_logMessageReceived(
|
||||||
|
new Action<string, string, LogType>(ExplorerCore.Instance.OnUnityLog));
|
||||||
|
|
||||||
|
//SceneManager.add_sceneLoaded(
|
||||||
|
// new Action<Scene, LoadSceneMode>(ExplorerCore.Instance.OnSceneLoaded1));
|
||||||
|
|
||||||
|
//SceneManager.add_activeSceneChanged(
|
||||||
|
// new Action<Scene, Scene>(ExplorerCore.Instance.OnSceneLoaded2));
|
||||||
|
}
|
||||||
|
|
||||||
|
internal delegate IntPtr d_LayerToName(int layer);
|
||||||
|
|
||||||
|
public override string LayerToName(int layer)
|
||||||
|
{
|
||||||
|
var iCall = ICallManager.GetICall<d_LayerToName>("UnityEngine.LayerMask::LayerToName");
|
||||||
|
return IL2CPP.Il2CppStringToManaged(iCall.Invoke(layer));
|
||||||
|
}
|
||||||
|
|
||||||
|
internal delegate IntPtr d_FindObjectsOfTypeAll(IntPtr type);
|
||||||
|
|
||||||
|
public override UnityEngine.Object[] FindObjectsOfTypeAll(Type type)
|
||||||
|
{
|
||||||
|
var iCall = ICallManager.GetICall<d_FindObjectsOfTypeAll>("UnityEngine.Resources::FindObjectsOfTypeAll");
|
||||||
|
var cppType = Il2CppType.From(type);
|
||||||
|
|
||||||
|
return new Il2CppReferenceArray<UnityEngine.Object>(iCall.Invoke(cppType.Pointer));
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetSceneHandle(Scene scene)
|
||||||
|
=> scene.handle;
|
||||||
|
|
||||||
|
//Scene.GetRootGameObjects();
|
||||||
|
|
||||||
|
internal delegate void d_GetRootGameObjects(int handle, IntPtr list);
|
||||||
|
|
||||||
|
public override GameObject[] GetRootGameObjects(Scene scene) => GetRootGameObjects(scene.handle);
|
||||||
|
|
||||||
|
public static GameObject[] GetRootGameObjects(int handle)
|
||||||
|
{
|
||||||
|
if (handle == -1)
|
||||||
|
return new GameObject[0];
|
||||||
|
|
||||||
|
int count = GetRootCount(handle);
|
||||||
|
|
||||||
|
if (count < 1)
|
||||||
|
return new GameObject[0];
|
||||||
|
|
||||||
|
var list = new Il2CppSystem.Collections.Generic.List<GameObject>(count);
|
||||||
|
|
||||||
|
var iCall = ICallManager.GetICall<d_GetRootGameObjects>("UnityEngine.SceneManagement.Scene::GetRootGameObjectsInternal");
|
||||||
|
|
||||||
|
iCall.Invoke(handle, list.Pointer);
|
||||||
|
|
||||||
|
return list.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
//Scene.rootCount;
|
||||||
|
|
||||||
|
internal delegate int d_GetRootCountInternal(int handle);
|
||||||
|
|
||||||
|
public override int GetRootCount(Scene scene) => GetRootCount(scene.handle);
|
||||||
|
|
||||||
|
public static int GetRootCount(int handle)
|
||||||
|
{
|
||||||
|
return ICallManager.GetICall<d_GetRootCountInternal>("UnityEngine.SceneManagement.Scene::GetRootCountInternal")
|
||||||
|
.Invoke(handle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class UnityEventExtensions
|
||||||
|
{
|
||||||
|
public static void AddListener(this UnityEvent action, Action listener)
|
||||||
|
{
|
||||||
|
action.AddListener(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void AddListener<T>(this UnityEvent<T> action, Action<T> listener)
|
||||||
|
{
|
||||||
|
action.AddListener(listener);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -1,110 +1,63 @@
|
|||||||
using System;
|
#if CPP
|
||||||
using System.Collections;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Text;
|
||||||
using UnityEngine;
|
using System.Threading.Tasks;
|
||||||
using BF = System.Reflection.BindingFlags;
|
|
||||||
using System.Diagnostics.CodeAnalysis;
|
|
||||||
#if CPP
|
|
||||||
using CppType = Il2CppSystem.Type;
|
|
||||||
using UnhollowerBaseLib;
|
using UnhollowerBaseLib;
|
||||||
|
using UnityExplorer.Core.Unity;
|
||||||
using UnhollowerRuntimeLib;
|
using UnhollowerRuntimeLib;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
#endif
|
using System.Reflection;
|
||||||
|
using System.Collections;
|
||||||
|
using System.IO;
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
using UnityExplorer.Core;
|
||||||
|
using CppType = Il2CppSystem.Type;
|
||||||
|
using BF = System.Reflection.BindingFlags;
|
||||||
|
|
||||||
namespace UnityExplorer.Helpers
|
namespace UnityExplorer.Core.Runtime.Il2Cpp
|
||||||
{
|
{
|
||||||
[SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "External methods")]
|
[SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "External methods")]
|
||||||
public static class ReflectionHelpers
|
public class Il2CppReflection : ReflectionProvider
|
||||||
{
|
{
|
||||||
public static BF CommonFlags = BF.Public | BF.Instance | BF.NonPublic | BF.Static;
|
public Il2CppReflection() : base()
|
||||||
|
|
||||||
// cache for GetTypeByName
|
|
||||||
internal static readonly Dictionary<string, Type> s_typesByName = new Dictionary<string, Type>();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Find a <see cref="Type"/> in the current AppDomain whose <see cref="Type.FullName"/> matches the provided <paramref name="fullName"/>.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="fullName">The <see cref="Type.FullName"/> you want to search for - case sensitive and full matches only.</param>
|
|
||||||
/// <returns>The Type if found, otherwise null.</returns>
|
|
||||||
public static Type GetTypeByName(string fullName)
|
|
||||||
{
|
{
|
||||||
s_typesByName.TryGetValue(fullName, out Type ret);
|
Instance = this;
|
||||||
|
|
||||||
if (ret != null)
|
TryLoadGameModules();
|
||||||
return ret;
|
|
||||||
|
|
||||||
foreach (var type in from asm in AppDomain.CurrentDomain.GetAssemblies()
|
|
||||||
from type in asm.TryGetTypes()
|
|
||||||
select type)
|
|
||||||
{
|
|
||||||
if (type.FullName == fullName)
|
|
||||||
{
|
|
||||||
ret = type;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (s_typesByName.ContainsKey(fullName))
|
|
||||||
s_typesByName[fullName] = ret;
|
|
||||||
else
|
|
||||||
s_typesByName.Add(fullName, ret);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// cache for GetBaseTypes
|
public override object Cast(object obj, Type castTo)
|
||||||
internal static readonly Dictionary<string, Type[]> s_cachedTypeInheritance = new Dictionary<string, Type[]>();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Get all base types of the provided Type, including itself.
|
|
||||||
/// </summary>
|
|
||||||
public static Type[] GetAllBaseTypes(object obj) => GetAllBaseTypes(GetActualType(obj));
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Get all base types of the provided Type, including itself.
|
|
||||||
/// </summary>
|
|
||||||
public static Type[] GetAllBaseTypes(Type type)
|
|
||||||
{
|
{
|
||||||
if (type == null)
|
return Il2CppCast(obj, castTo);
|
||||||
throw new ArgumentNullException("type");
|
|
||||||
|
|
||||||
var name = type.AssemblyQualifiedName;
|
|
||||||
|
|
||||||
if (s_cachedTypeInheritance.TryGetValue(name, out Type[] ret))
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
List<Type> list = new List<Type>();
|
|
||||||
|
|
||||||
while (type != null)
|
|
||||||
{
|
|
||||||
list.Add(type);
|
|
||||||
type = type.BaseType;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = list.ToArray();
|
|
||||||
|
|
||||||
s_cachedTypeInheritance.Add(name, ret);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
public override string ProcessTypeNameInString(Type type, string theString, ref string typeName)
|
||||||
/// Helper for IL2CPP to get the underlying true Type (Unhollowed) of the object.
|
{
|
||||||
/// </summary>
|
if (!Il2CppTypeNotNull(type))
|
||||||
/// <param name="obj">The object to get the true Type for.</param>
|
return theString;
|
||||||
/// <returns>The most accurate Type of the object which could be identified.</returns>
|
|
||||||
public static Type GetActualType(this object obj)
|
var cppType = Il2CppType.From(type);
|
||||||
|
if (cppType != null && s_deobfuscatedTypeNames.ContainsKey(cppType.FullName))
|
||||||
|
{
|
||||||
|
typeName = s_deobfuscatedTypeNames[cppType.FullName];
|
||||||
|
theString = theString.Replace(cppType.FullName, typeName);
|
||||||
|
}
|
||||||
|
|
||||||
|
return theString;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Type GetActualType(object obj)
|
||||||
{
|
{
|
||||||
if (obj == null)
|
if (obj == null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
var type = obj.GetType();
|
var type = obj.GetType();
|
||||||
#if CPP
|
|
||||||
if (obj is Il2CppSystem.Object cppObject)
|
if (obj is Il2CppSystem.Object cppObject)
|
||||||
{
|
{
|
||||||
|
// weird specific case - if the object is an Il2CppSystem.Type, then return so manually.
|
||||||
if (cppObject is CppType)
|
if (cppObject is CppType)
|
||||||
return typeof(CppType);
|
return typeof(CppType);
|
||||||
|
|
||||||
@ -122,7 +75,7 @@ namespace UnityExplorer.Helpers
|
|||||||
IntPtr classPtr = il2cpp_object_get_class(cppObject.Pointer);
|
IntPtr classPtr = il2cpp_object_get_class(cppObject.Pointer);
|
||||||
if (RuntimeSpecificsStore.IsInjected(classPtr))
|
if (RuntimeSpecificsStore.IsInjected(classPtr))
|
||||||
{
|
{
|
||||||
var typeByName = GetTypeByName(cppType.FullName);
|
var typeByName = ReflectionUtility.GetTypeByName(cppType.FullName);
|
||||||
if (typeByName != null)
|
if (typeByName != null)
|
||||||
return typeByName;
|
return typeByName;
|
||||||
}
|
}
|
||||||
@ -132,16 +85,15 @@ namespace UnityExplorer.Helpers
|
|||||||
if (getType != null)
|
if (getType != null)
|
||||||
return getType;
|
return getType;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if CPP
|
|
||||||
// caching for GetMonoType
|
// caching for GetMonoType
|
||||||
private static readonly Dictionary<string, Type> Il2CppToMonoType = new Dictionary<string, Type>();
|
private static readonly Dictionary<string, Type> Il2CppToMonoType = new Dictionary<string, Type>();
|
||||||
|
|
||||||
// keep unobfuscated type name cache, used to display proper name.
|
// keep deobfuscated type name cache, used to display proper name.
|
||||||
internal static Dictionary<string, string> UnobfuscatedTypeNames = new Dictionary<string, string>();
|
internal static Dictionary<string, string> s_deobfuscatedTypeNames = new Dictionary<string, string>();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Try to get the Mono (Unhollowed) Type representation of the provided <see cref="Il2CppSystem.Type"/>.
|
/// Try to get the Mono (Unhollowed) Type representation of the provided <see cref="Il2CppSystem.Type"/>.
|
||||||
@ -156,7 +108,7 @@ namespace UnityExplorer.Helpers
|
|||||||
return Il2CppToMonoType[name];
|
return Il2CppToMonoType[name];
|
||||||
|
|
||||||
Type ret = Type.GetType(name);
|
Type ret = Type.GetType(name);
|
||||||
|
|
||||||
if (ret == null)
|
if (ret == null)
|
||||||
{
|
{
|
||||||
string baseName = cppType.FullName;
|
string baseName = cppType.FullName;
|
||||||
@ -164,18 +116,18 @@ namespace UnityExplorer.Helpers
|
|||||||
|
|
||||||
ret = AppDomain.CurrentDomain
|
ret = AppDomain.CurrentDomain
|
||||||
.GetAssemblies()
|
.GetAssemblies()
|
||||||
.FirstOrDefault(a
|
.FirstOrDefault(a
|
||||||
=> a.GetName().Name == baseAssembly)?
|
=> a.GetName().Name == baseAssembly)?
|
||||||
.TryGetTypes()
|
.TryGetTypes()
|
||||||
.FirstOrDefault(t
|
.FirstOrDefault(t
|
||||||
=> t.CustomAttributes.Any(ca
|
=> t.CustomAttributes.Any(ca
|
||||||
=> ca.AttributeType.Name == "ObfuscatedNameAttribute"
|
=> ca.AttributeType.Name == "ObfuscatedNameAttribute"
|
||||||
&& (string)ca.ConstructorArguments[0].Value == baseName));
|
&& (string)ca.ConstructorArguments[0].Value == baseName));
|
||||||
|
|
||||||
if (ret != null)
|
if (ret != null)
|
||||||
{
|
{
|
||||||
// unobfuscated type was found, add to cache.
|
// deobfuscated type was found, add to cache.
|
||||||
UnobfuscatedTypeNames.Add(cppType.FullName, ret.FullName);
|
s_deobfuscatedTypeNames.Add(cppType.FullName, ret.FullName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -185,14 +137,14 @@ namespace UnityExplorer.Helpers
|
|||||||
}
|
}
|
||||||
|
|
||||||
// cached class pointers for Il2CppCast
|
// cached class pointers for Il2CppCast
|
||||||
private static readonly Dictionary<string, IntPtr> CppClassPointers = new Dictionary<string, IntPtr>();
|
private static readonly Dictionary<string, IntPtr> s_cppClassPointers = new Dictionary<string, IntPtr>();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Attempt to cast the object to its underlying type.
|
/// Attempt to cast the object to its underlying type.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="obj">The object you want to cast.</param>
|
/// <param name="obj">The object you want to cast.</param>
|
||||||
/// <returns>The object, as the underlying type if successful or the input value if not.</returns>
|
/// <returns>The object, as the underlying type if successful or the input value if not.</returns>
|
||||||
public static object Il2CppCast(this object obj) => Il2CppCast(obj, GetActualType(obj));
|
public static object Il2CppCast(object obj) => Il2CppCast(obj, Instance.GetActualType(obj));
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Attempt to cast the object to the provided type.
|
/// Attempt to cast the object to the provided type.
|
||||||
@ -200,7 +152,7 @@ namespace UnityExplorer.Helpers
|
|||||||
/// <param name="obj">The object you want to cast.</param>
|
/// <param name="obj">The object you want to cast.</param>
|
||||||
/// <param name="castTo">The Type you want to cast to.</param>
|
/// <param name="castTo">The Type you want to cast to.</param>
|
||||||
/// <returns>The object, as the type (or a normal C# object) if successful or the input value if not.</returns>
|
/// <returns>The object, as the type (or a normal C# object) if successful or the input value if not.</returns>
|
||||||
public static object Il2CppCast(this object obj, Type castTo)
|
public static object Il2CppCast(object obj, Type castTo)
|
||||||
{
|
{
|
||||||
if (!(obj is Il2CppSystem.Object ilObj))
|
if (!(obj is Il2CppSystem.Object ilObj))
|
||||||
return obj;
|
return obj;
|
||||||
@ -234,7 +186,7 @@ namespace UnityExplorer.Helpers
|
|||||||
/// <returns>True if successful, false if not.</returns>
|
/// <returns>True if successful, false if not.</returns>
|
||||||
public static bool Il2CppTypeNotNull(Type type, out IntPtr il2cppPtr)
|
public static bool Il2CppTypeNotNull(Type type, out IntPtr il2cppPtr)
|
||||||
{
|
{
|
||||||
if (CppClassPointers.TryGetValue(type.AssemblyQualifiedName, out il2cppPtr))
|
if (s_cppClassPointers.TryGetValue(type.AssemblyQualifiedName, out il2cppPtr))
|
||||||
return il2cppPtr != IntPtr.Zero;
|
return il2cppPtr != IntPtr.Zero;
|
||||||
|
|
||||||
il2cppPtr = (IntPtr)typeof(Il2CppClassPointerStore<>)
|
il2cppPtr = (IntPtr)typeof(Il2CppClassPointerStore<>)
|
||||||
@ -242,7 +194,7 @@ namespace UnityExplorer.Helpers
|
|||||||
.GetField("NativeClassPtr", BF.Public | BF.Static)
|
.GetField("NativeClassPtr", BF.Public | BF.Static)
|
||||||
.GetValue(null);
|
.GetValue(null);
|
||||||
|
|
||||||
CppClassPointers.Add(type.AssemblyQualifiedName, il2cppPtr);
|
s_cppClassPointers.Add(type.AssemblyQualifiedName, il2cppPtr);
|
||||||
|
|
||||||
return il2cppPtr != IntPtr.Zero;
|
return il2cppPtr != IntPtr.Zero;
|
||||||
}
|
}
|
||||||
@ -254,143 +206,92 @@ namespace UnityExplorer.Helpers
|
|||||||
[DllImport("GameAssembly", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
|
[DllImport("GameAssembly", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
|
||||||
public static extern IntPtr il2cpp_object_get_class(IntPtr obj);
|
public static extern IntPtr il2cpp_object_get_class(IntPtr obj);
|
||||||
|
|
||||||
// cached il2cpp unbox methods
|
internal static IntPtr s_cppEnumerableClassPtr;
|
||||||
internal static readonly Dictionary<string, MethodInfo> s_unboxMethods = new Dictionary<string, MethodInfo>();
|
internal static IntPtr s_cppDictionaryClassPtr;
|
||||||
|
|
||||||
/// <summary>
|
public override bool IsAssignableFrom(Type toAssignTo, Type toAssignFrom)
|
||||||
/// Attempt to unbox the object to the underlying struct type.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="obj">The object which is a struct underneath.</param>
|
|
||||||
/// <returns>The struct if successful, otherwise null.</returns>
|
|
||||||
public static object Unbox(this object obj) => Unbox(obj, GetActualType(obj));
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Attempt to unbox the object to the struct type.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="obj">The object which is a struct underneath.</param>
|
|
||||||
/// <param name="type">The type of the struct you want to unbox to.</param>
|
|
||||||
/// <returns>The struct if successful, otherwise null.</returns>
|
|
||||||
public static object Unbox(this object obj, Type type)
|
|
||||||
{
|
{
|
||||||
if (!type.IsValueType)
|
if (toAssignTo.IsAssignableFrom(toAssignFrom))
|
||||||
return null;
|
return true;
|
||||||
|
|
||||||
if (!(obj is Il2CppSystem.Object))
|
if (toAssignTo == typeof(IEnumerable))
|
||||||
return obj;
|
|
||||||
|
|
||||||
var name = type.AssemblyQualifiedName;
|
|
||||||
|
|
||||||
if (!s_unboxMethods.ContainsKey(name))
|
|
||||||
{
|
|
||||||
s_unboxMethods.Add(name, typeof(Il2CppObjectBase)
|
|
||||||
.GetMethod("Unbox")
|
|
||||||
.MakeGenericMethod(type));
|
|
||||||
}
|
|
||||||
|
|
||||||
return s_unboxMethods[name].Invoke(obj, new object[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
public static IEnumerable<Type> TryGetTypes(this Assembly asm)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return asm.GetTypes();
|
|
||||||
}
|
|
||||||
catch (ReflectionTypeLoadException e)
|
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return asm.GetExportedTypes();
|
if (s_cppEnumerableClassPtr == IntPtr.Zero)
|
||||||
|
Il2CppTypeNotNull(typeof(Il2CppSystem.Collections.IEnumerable), out s_cppEnumerableClassPtr);
|
||||||
|
|
||||||
|
if (s_cppEnumerableClassPtr != IntPtr.Zero
|
||||||
|
&& Il2CppTypeNotNull(toAssignFrom, out IntPtr assignFromPtr)
|
||||||
|
&& il2cpp_class_is_assignable_from(s_cppEnumerableClassPtr, assignFromPtr))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch
|
catch { }
|
||||||
|
}
|
||||||
|
else if (toAssignTo == typeof(IDictionary))
|
||||||
|
{
|
||||||
|
try
|
||||||
{
|
{
|
||||||
return e.Types.Where(t => t != null);
|
if (s_cppDictionaryClassPtr == IntPtr.Zero)
|
||||||
|
if (!Il2CppTypeNotNull(typeof(Il2CppSystem.Collections.IDictionary), out s_cppDictionaryClassPtr))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (Il2CppTypeNotNull(toAssignFrom, out IntPtr classPtr))
|
||||||
|
{
|
||||||
|
if (il2cpp_class_is_assignable_from(s_cppDictionaryClassPtr, classPtr))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool IsReflectionSupported(Type type)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var gArgs = type.GetGenericArguments();
|
||||||
|
if (!gArgs.Any())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
foreach (var gType in gArgs)
|
||||||
|
{
|
||||||
|
if (!Supported(gType))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
bool Supported(Type t)
|
||||||
|
{
|
||||||
|
if (!typeof(Il2CppSystem.Object).IsAssignableFrom(t))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (!Il2CppTypeNotNull(t, out IntPtr ptr))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return CppType.internal_from_handle(IL2CPP.il2cpp_class_get_type(ptr)) is CppType;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
return Enumerable.Empty<Type>();
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper for IL2CPP to check if a Type is assignable to IEnumerable
|
|
||||||
|
|
||||||
#if CPP
|
|
||||||
internal static IntPtr s_cppEnumerableClassPtr;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Check if the provided Type is assignable to IEnumerable.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="t">The Type to check</param>
|
|
||||||
/// <returns>True if the Type is assignable to IEnumerable, otherwise false.</returns>
|
|
||||||
public static bool IsEnumerable(Type t)
|
|
||||||
{
|
|
||||||
if (typeof(IEnumerable).IsAssignableFrom(t))
|
|
||||||
return true;
|
|
||||||
#if CPP
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (s_cppEnumerableClassPtr == IntPtr.Zero)
|
|
||||||
Il2CppTypeNotNull(typeof(Il2CppSystem.Collections.IEnumerable), out s_cppEnumerableClassPtr);
|
|
||||||
|
|
||||||
if (s_cppEnumerableClassPtr != IntPtr.Zero
|
|
||||||
&& Il2CppTypeNotNull(t, out IntPtr classPtr)
|
|
||||||
&& il2cpp_class_is_assignable_from(s_cppEnumerableClassPtr, classPtr))
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch { }
|
|
||||||
#endif
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Helper for IL2CPP to check if a Type is assignable to IDictionary
|
|
||||||
|
|
||||||
#if CPP
|
|
||||||
internal static IntPtr s_cppDictionaryClassPtr;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Check if the provided Type is assignable to IDictionary.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="t">The Type to check</param>
|
|
||||||
/// <returns>True if the Type is assignable to IDictionary, otherwise false.</returns>
|
|
||||||
public static bool IsDictionary(Type t)
|
|
||||||
{
|
|
||||||
if (typeof(IDictionary).IsAssignableFrom(t))
|
|
||||||
return true;
|
|
||||||
#if CPP
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (s_cppDictionaryClassPtr == IntPtr.Zero)
|
|
||||||
if (!Il2CppTypeNotNull(typeof(Il2CppSystem.Collections.IDictionary), out s_cppDictionaryClassPtr))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (Il2CppTypeNotNull(t, out IntPtr classPtr))
|
|
||||||
{
|
|
||||||
if (il2cpp_class_is_assignable_from(s_cppDictionaryClassPtr, classPtr))
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch { }
|
|
||||||
#endif
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Helper for IL2CPP to try to make sure the Unhollowed game assemblies are actually loaded.
|
// Helper for IL2CPP to try to make sure the Unhollowed game assemblies are actually loaded.
|
||||||
|
|
||||||
#if CPP
|
|
||||||
internal static void TryLoadGameModules()
|
internal static void TryLoadGameModules()
|
||||||
{
|
{
|
||||||
LoadModule("Assembly-CSharp");
|
Instance.LoadModule("Assembly-CSharp");
|
||||||
LoadModule("Assembly-CSharp-firstpass");
|
Instance.LoadModule("Assembly-CSharp-firstpass");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool LoadModule(string module)
|
public override bool LoadModule(string module)
|
||||||
{
|
{
|
||||||
#if ML
|
#if ML
|
||||||
var path = Path.Combine("MelonLoader", "Managed", $"{module}.dll");
|
var path = Path.Combine("MelonLoader", "Managed", $"{module}.dll");
|
||||||
@ -417,32 +318,45 @@ namespace UnityExplorer.Helpers
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
// For Mono, just return true and do nothing, Mono will sort it out itself.
|
// ~~~~~~~~~~ not used ~~~~~~~~~~~~
|
||||||
public static bool LoadModule(string module) => true;
|
|
||||||
#endif
|
// cached il2cpp unbox methods
|
||||||
|
internal static readonly Dictionary<string, MethodInfo> s_unboxMethods = new Dictionary<string, MethodInfo>();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Helper to display a simple "{ExceptionType}: {Message}" of the exception, and optionally use the inner-most exception.
|
/// Attempt to unbox the object to the underlying struct type.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="e">The Exception to convert to string.</param>
|
/// <param name="obj">The object which is a struct underneath.</param>
|
||||||
/// <param name="innerMost">Should the inner-most Exception of the stack be used? If false, the Exception you provided will be used directly.</param>
|
/// <returns>The struct if successful, otherwise null.</returns>
|
||||||
/// <returns>The exception to string.</returns>
|
public static object Unbox(object obj) => Unbox(obj, Instance.GetActualType(obj));
|
||||||
public static string ExceptionToString(Exception e, bool innerMost = false)
|
|
||||||
|
/// <summary>
|
||||||
|
/// Attempt to unbox the object to the struct type.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="obj">The object which is a struct underneath.</param>
|
||||||
|
/// <param name="type">The type of the struct you want to unbox to.</param>
|
||||||
|
/// <returns>The struct if successful, otherwise null.</returns>
|
||||||
|
public static object Unbox(object obj, Type type)
|
||||||
{
|
{
|
||||||
if (innerMost)
|
if (!type.IsValueType)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (!(obj is Il2CppSystem.Object))
|
||||||
|
return obj;
|
||||||
|
|
||||||
|
var name = type.AssemblyQualifiedName;
|
||||||
|
|
||||||
|
if (!s_unboxMethods.ContainsKey(name))
|
||||||
{
|
{
|
||||||
while (e.InnerException != null)
|
s_unboxMethods.Add(name, typeof(Il2CppObjectBase)
|
||||||
{
|
.GetMethod("Unbox")
|
||||||
#if CPP
|
.MakeGenericMethod(type));
|
||||||
if (e.InnerException is System.Runtime.CompilerServices.RuntimeWrappedException)
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
e = e.InnerException;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $"{e.GetType()}: {e.Message}";
|
return s_unboxMethods[name].Invoke(obj, new object[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
77
src/Core/Runtime/Il2Cpp/Il2CppTextureUtil.cs
Normal file
77
src/Core/Runtime/Il2Cpp/Il2CppTextureUtil.cs
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
#if CPP
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using UnhollowerBaseLib;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace UnityExplorer.Core.Runtime.Il2Cpp
|
||||||
|
{
|
||||||
|
public class Il2CppTextureUtil : TextureUtilProvider
|
||||||
|
{
|
||||||
|
public override Texture2D NewTexture2D(int width, int height)
|
||||||
|
=> new Texture2D((int)width, (int)height, TextureFormat.RGBA32, Texture.GenerateAllMips, false, IntPtr.Zero);
|
||||||
|
|
||||||
|
internal delegate void d_Blit2(IntPtr source, IntPtr dest);
|
||||||
|
|
||||||
|
public override void Blit(Texture2D tex, RenderTexture rt)
|
||||||
|
{
|
||||||
|
var iCall = ICallManager.GetICall<d_Blit2>("UnityEngine.Graphics::Blit2");
|
||||||
|
iCall.Invoke(tex.Pointer, rt.Pointer);
|
||||||
|
}
|
||||||
|
|
||||||
|
// byte[] ImageConversion.EncodeToPNG(this Texture2D image);
|
||||||
|
|
||||||
|
internal delegate IntPtr d_EncodeToPNG(IntPtr tex);
|
||||||
|
|
||||||
|
public override byte[] EncodeToPNG(Texture2D tex)
|
||||||
|
{
|
||||||
|
var iCall = ICallManager.GetICall<d_EncodeToPNG>("UnityEngine.ImageConversion::EncodeToPNG");
|
||||||
|
|
||||||
|
IntPtr ptr = iCall.Invoke(tex.Pointer);
|
||||||
|
|
||||||
|
if (ptr == IntPtr.Zero)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return new Il2CppStructArray<byte>(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// bool ImageConversion.LoadImage(this Texture2D tex, byte[] data, bool markNonReadable);
|
||||||
|
|
||||||
|
internal delegate bool d_LoadImage(IntPtr tex, IntPtr data, bool markNonReadable);
|
||||||
|
|
||||||
|
public override bool LoadImage(Texture2D tex, byte[] data, bool markNonReadable)
|
||||||
|
{
|
||||||
|
var il2cppArray = (Il2CppStructArray<byte>)data;
|
||||||
|
|
||||||
|
var iCall = ICallManager.GetICall<d_LoadImage>("UnityEngine.ImageConversion::LoadImage");
|
||||||
|
|
||||||
|
return iCall.Invoke(tex.Pointer, il2cppArray.Pointer, markNonReadable);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sprite Sprite.Create
|
||||||
|
|
||||||
|
public override Sprite CreateSprite(Texture2D texture)
|
||||||
|
{
|
||||||
|
return CreateSpriteImpl(texture, new Rect(0, 0, texture.width, texture.height), Vector2.zero, 100f, 0u, Vector4.zero);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal delegate IntPtr d_CreateSprite(IntPtr texture, ref Rect rect, ref Vector2 pivot, float pixelsPerUnit,
|
||||||
|
uint extrude, int meshType, ref Vector4 border, bool generateFallbackPhysicsShape);
|
||||||
|
|
||||||
|
public static Sprite CreateSpriteImpl(Texture texture, Rect rect, Vector2 pivot, float pixelsPerUnit, uint extrude, Vector4 border)
|
||||||
|
{
|
||||||
|
var iCall = ICallManager.GetICall<d_CreateSprite>("UnityEngine.Sprite::CreateSprite_Injected");
|
||||||
|
|
||||||
|
var ptr = iCall.Invoke(texture.Pointer, ref rect, ref pivot, pixelsPerUnit, extrude, 1, ref border, false);
|
||||||
|
|
||||||
|
if (ptr == IntPtr.Zero)
|
||||||
|
return null;
|
||||||
|
else
|
||||||
|
return new Sprite(ptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
53
src/Core/Runtime/Mono/MonoProvider.cs
Normal file
53
src/Core/Runtime/Mono/MonoProvider.cs
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
#if MONO
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Text;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.SceneManagement;
|
||||||
|
using UnityExplorer.Core;
|
||||||
|
|
||||||
|
namespace UnityExplorer.Core.Runtime.Mono
|
||||||
|
{
|
||||||
|
public class MonoProvider : RuntimeProvider
|
||||||
|
{
|
||||||
|
public override void Initialize()
|
||||||
|
{
|
||||||
|
Reflection = new MonoReflection();
|
||||||
|
TextureUtil = new MonoTextureUtil();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void SetupEvents()
|
||||||
|
{
|
||||||
|
Application.logMessageReceived += ExplorerCore.Instance.OnUnityLog;
|
||||||
|
//SceneManager.sceneLoaded += ExplorerCore.Instance.OnSceneLoaded1;
|
||||||
|
//SceneManager.activeSceneChanged += ExplorerCore.Instance.OnSceneLoaded2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string LayerToName(int layer)
|
||||||
|
=> LayerMask.LayerToName(layer);
|
||||||
|
|
||||||
|
public override UnityEngine.Object[] FindObjectsOfTypeAll(Type type)
|
||||||
|
=> Resources.FindObjectsOfTypeAll(type);
|
||||||
|
|
||||||
|
private static readonly FieldInfo fi_Scene_handle = typeof(Scene).GetField("m_Handle", ReflectionUtility.CommonFlags);
|
||||||
|
|
||||||
|
public override int GetSceneHandle(Scene scene)
|
||||||
|
{
|
||||||
|
return (int)fi_Scene_handle.GetValue(scene);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override GameObject[] GetRootGameObjects(Scene scene)
|
||||||
|
{
|
||||||
|
return scene.GetRootGameObjects();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetRootCount(Scene scene)
|
||||||
|
{
|
||||||
|
return scene.rootCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
33
src/Core/Runtime/Mono/MonoReflection.cs
Normal file
33
src/Core/Runtime/Mono/MonoReflection.cs
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
#if MONO
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace UnityExplorer.Core.Runtime.Mono
|
||||||
|
{
|
||||||
|
public class MonoReflection : ReflectionProvider
|
||||||
|
{
|
||||||
|
// Mono doesn't need to explicitly cast things.
|
||||||
|
public override object Cast(object obj, Type castTo)
|
||||||
|
=> obj;
|
||||||
|
|
||||||
|
// Vanilla GetType is fine for mono
|
||||||
|
public override Type GetActualType(object obj)
|
||||||
|
=> obj.GetType();
|
||||||
|
|
||||||
|
public override bool IsAssignableFrom(Type toAssignTo, Type toAssignFrom)
|
||||||
|
=> toAssignTo.IsAssignableFrom(toAssignFrom);
|
||||||
|
|
||||||
|
public override bool IsReflectionSupported(Type type)
|
||||||
|
=> true;
|
||||||
|
|
||||||
|
public override bool LoadModule(string module)
|
||||||
|
=> true;
|
||||||
|
|
||||||
|
public override string ProcessTypeNameInString(Type type, string theString, ref string typeName)
|
||||||
|
=> theString;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
66
src/Core/Runtime/Mono/MonoTextureUtil.cs
Normal file
66
src/Core/Runtime/Mono/MonoTextureUtil.cs
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
#if MONO
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Text;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityExplorer.Core;
|
||||||
|
|
||||||
|
namespace UnityExplorer.Core.Runtime.Mono
|
||||||
|
{
|
||||||
|
public class MonoTextureUtil : TextureUtilProvider
|
||||||
|
{
|
||||||
|
public override void Blit(Texture2D tex, RenderTexture rt)
|
||||||
|
{
|
||||||
|
Graphics.Blit(tex, rt);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Sprite CreateSprite(Texture2D texture)
|
||||||
|
{
|
||||||
|
return Sprite.Create(texture, new Rect(0, 0, texture.width, texture.height), Vector2.zero);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool LoadImage(Texture2D tex, byte[] data, bool markNonReadable)
|
||||||
|
{
|
||||||
|
return tex.LoadImage(data, markNonReadable);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Texture2D NewTexture2D(int width, int height)
|
||||||
|
{
|
||||||
|
return new Texture2D(width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override byte[] EncodeToPNG(Texture2D tex)
|
||||||
|
{
|
||||||
|
return EncodeToPNGSafe(tex);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static MethodInfo EncodeToPNGMethod => m_encodeToPNGMethod ?? GetEncodeToPNGMethod();
|
||||||
|
private static MethodInfo m_encodeToPNGMethod;
|
||||||
|
|
||||||
|
public static byte[] EncodeToPNGSafe(Texture2D tex)
|
||||||
|
{
|
||||||
|
var method = EncodeToPNGMethod;
|
||||||
|
|
||||||
|
if (method.IsStatic)
|
||||||
|
return (byte[])method.Invoke(null, new object[] { tex });
|
||||||
|
else
|
||||||
|
return (byte[])method.Invoke(tex, new object[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static MethodInfo GetEncodeToPNGMethod()
|
||||||
|
{
|
||||||
|
if (ReflectionUtility.GetTypeByName("UnityEngine.ImageConversion") is Type imageConversion)
|
||||||
|
return m_encodeToPNGMethod = imageConversion.GetMethod("EncodeToPNG", ReflectionUtility.CommonFlags);
|
||||||
|
|
||||||
|
var method = typeof(Texture2D).GetMethod("EncodeToPNG", ReflectionUtility.CommonFlags);
|
||||||
|
if (method != null)
|
||||||
|
return m_encodeToPNGMethod = method;
|
||||||
|
|
||||||
|
ExplorerCore.Log("ERROR: Cannot get any EncodeToPNG method!");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
29
src/Core/Runtime/ReflectionProvider.cs
Normal file
29
src/Core/Runtime/ReflectionProvider.cs
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace UnityExplorer.Core.Runtime
|
||||||
|
{
|
||||||
|
public abstract class ReflectionProvider
|
||||||
|
{
|
||||||
|
public static ReflectionProvider Instance;
|
||||||
|
|
||||||
|
public ReflectionProvider()
|
||||||
|
{
|
||||||
|
Instance = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract Type GetActualType(object obj);
|
||||||
|
|
||||||
|
public abstract object Cast(object obj, Type castTo);
|
||||||
|
|
||||||
|
public abstract bool IsAssignableFrom(Type toAssignTo, Type toAssignFrom);
|
||||||
|
|
||||||
|
public abstract bool IsReflectionSupported(Type type);
|
||||||
|
|
||||||
|
public abstract string ProcessTypeNameInString(Type type, string theString, ref string typeName);
|
||||||
|
|
||||||
|
public abstract bool LoadModule(string module);
|
||||||
|
}
|
||||||
|
}
|
@ -2,8 +2,10 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.SceneManagement;
|
||||||
|
|
||||||
namespace UnityExplorer.Runtime
|
namespace UnityExplorer.Core.Runtime
|
||||||
{
|
{
|
||||||
// Work in progress, this will be used to replace all the "if CPP / if MONO"
|
// Work in progress, this will be used to replace all the "if CPP / if MONO"
|
||||||
// pre-processor directives all over the codebase.
|
// pre-processor directives all over the codebase.
|
||||||
@ -12,6 +14,9 @@ namespace UnityExplorer.Runtime
|
|||||||
{
|
{
|
||||||
public static RuntimeProvider Instance;
|
public static RuntimeProvider Instance;
|
||||||
|
|
||||||
|
public ReflectionProvider Reflection;
|
||||||
|
public TextureUtilProvider TextureUtil;
|
||||||
|
|
||||||
public RuntimeProvider()
|
public RuntimeProvider()
|
||||||
{
|
{
|
||||||
Initialize();
|
Initialize();
|
||||||
@ -31,5 +36,16 @@ namespace UnityExplorer.Runtime
|
|||||||
|
|
||||||
public abstract void SetupEvents();
|
public abstract void SetupEvents();
|
||||||
|
|
||||||
|
// Unity API handlers
|
||||||
|
|
||||||
|
public abstract string LayerToName(int layer);
|
||||||
|
|
||||||
|
public abstract UnityEngine.Object[] FindObjectsOfTypeAll(Type type);
|
||||||
|
|
||||||
|
public abstract int GetSceneHandle(Scene scene);
|
||||||
|
|
||||||
|
public abstract GameObject[] GetRootGameObjects(Scene scene);
|
||||||
|
|
||||||
|
public abstract int GetRootCount(Scene scene);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,50 +1,32 @@
|
|||||||
using System;
|
using System;
|
||||||
using UnityEngine;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Reflection;
|
using System.Linq;
|
||||||
#if CPP
|
using System.Text;
|
||||||
using UnityExplorer.Unstrip;
|
using UnityEngine;
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace UnityExplorer.Helpers
|
namespace UnityExplorer.Core.Runtime
|
||||||
{
|
{
|
||||||
public static class Texture2DHelpers
|
public abstract class TextureUtilProvider
|
||||||
{
|
{
|
||||||
#if MONO
|
public static TextureUtilProvider Instance;
|
||||||
private static bool isNewEncodeMethod = false;
|
|
||||||
private static MethodInfo EncodeToPNGMethod => m_encodeToPNGMethod ?? GetEncodeToPNGMethod();
|
|
||||||
private static MethodInfo m_encodeToPNGMethod;
|
|
||||||
|
|
||||||
public static byte[] EncodeToPNGSafe(this Texture2D tex)
|
public TextureUtilProvider()
|
||||||
{
|
{
|
||||||
var method = EncodeToPNGMethod;
|
Instance = this;
|
||||||
|
|
||||||
if (method.IsStatic)
|
|
||||||
return (byte[])method.Invoke(null, new object[] { tex });
|
|
||||||
else
|
|
||||||
return (byte[])method.Invoke(tex, new object[0]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static MethodInfo GetEncodeToPNGMethod()
|
public abstract byte[] EncodeToPNG(Texture2D tex);
|
||||||
{
|
|
||||||
if (ReflectionHelpers.GetTypeByName("UnityEngine.ImageConversion") is Type imageConversion)
|
|
||||||
{
|
|
||||||
isNewEncodeMethod = true;
|
|
||||||
return m_encodeToPNGMethod = imageConversion.GetMethod("EncodeToPNG", ReflectionHelpers.CommonFlags);
|
|
||||||
}
|
|
||||||
|
|
||||||
var method = typeof(Texture2D).GetMethod("EncodeToPNG", ReflectionHelpers.CommonFlags);
|
public abstract Texture2D NewTexture2D(int width, int height);
|
||||||
if (method != null)
|
|
||||||
{
|
|
||||||
return m_encodeToPNGMethod = method;
|
|
||||||
}
|
|
||||||
|
|
||||||
ExplorerCore.Log("ERROR: Cannot get any EncodeToPNG method!");
|
public abstract void Blit(Texture2D tex, RenderTexture rt);
|
||||||
return null;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
public static bool IsReadable(this Texture2D tex)
|
public abstract bool LoadImage(Texture2D tex, byte[] data, bool markNonReadable);
|
||||||
|
|
||||||
|
public abstract Sprite CreateSprite(Texture2D texture);
|
||||||
|
|
||||||
|
public static bool IsReadable(Texture2D tex)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -61,30 +43,30 @@ namespace UnityExplorer.Helpers
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static bool LoadImage(Texture2D tex, string filePath, bool markNonReadable)
|
||||||
|
{
|
||||||
|
if (!File.Exists(filePath))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return Instance.LoadImage(tex, File.ReadAllBytes(filePath), markNonReadable);
|
||||||
|
}
|
||||||
|
|
||||||
public static Texture2D Copy(Texture2D orig, Rect rect)
|
public static Texture2D Copy(Texture2D orig, Rect rect)
|
||||||
{
|
{
|
||||||
Color[] pixels;
|
Color[] pixels;
|
||||||
|
|
||||||
if (!orig.IsReadable())
|
if (IsReadable(orig))
|
||||||
orig = ForceReadTexture(orig);
|
orig = ForceReadTexture(orig);
|
||||||
|
|
||||||
pixels = orig.GetPixels((int)rect.x, (int)rect.y, (int)rect.width, (int)rect.height);
|
pixels = orig.GetPixels((int)rect.x, (int)rect.y, (int)rect.width, (int)rect.height);
|
||||||
|
|
||||||
// use full constructor for better compatibility
|
Texture2D newTex = Instance.NewTexture2D((int)rect.width, (int)rect.height);
|
||||||
#if CPP
|
|
||||||
var _newTex = new Texture2D((int)rect.width, (int)rect.height, TextureFormat.RGBA32, Texture.GenerateAllMips, false, IntPtr.Zero);
|
|
||||||
#else
|
|
||||||
var _newTex = new Texture2D((int)rect.width, (int)rect.height);
|
|
||||||
#endif
|
|
||||||
_newTex.SetPixels(pixels);
|
|
||||||
|
|
||||||
return _newTex;
|
newTex.SetPixels(pixels);
|
||||||
|
|
||||||
|
return newTex;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if CPP
|
|
||||||
internal delegate void d_Blit2(IntPtr source, IntPtr dest);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
public static Texture2D ForceReadTexture(Texture2D tex)
|
public static Texture2D ForceReadTexture(Texture2D tex)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@ -96,12 +78,7 @@ namespace UnityExplorer.Helpers
|
|||||||
rt.filterMode = FilterMode.Point;
|
rt.filterMode = FilterMode.Point;
|
||||||
RenderTexture.active = rt;
|
RenderTexture.active = rt;
|
||||||
|
|
||||||
#if MONO
|
Instance.Blit(tex, rt);
|
||||||
Graphics.Blit(tex, rt);
|
|
||||||
#else
|
|
||||||
var iCall = ICallHelper.GetICall<d_Blit2>("UnityEngine.Graphics::Blit2");
|
|
||||||
iCall.Invoke(tex.Pointer, rt.Pointer);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
var _newTex = new Texture2D(tex.width, tex.height, TextureFormat.ARGB32, false);
|
var _newTex = new Texture2D(tex.width, tex.height, TextureFormat.ARGB32, false);
|
||||||
|
|
||||||
@ -129,7 +106,7 @@ namespace UnityExplorer.Helpers
|
|||||||
string savepath = dir + @"\" + name + ".png";
|
string savepath = dir + @"\" + name + ".png";
|
||||||
|
|
||||||
// Make sure we can EncodeToPNG it.
|
// Make sure we can EncodeToPNG it.
|
||||||
if (tex.format != TextureFormat.ARGB32 || !tex.IsReadable())
|
if (tex.format != TextureFormat.ARGB32 || !IsReadable(tex))
|
||||||
{
|
{
|
||||||
tex = ForceReadTexture(tex);
|
tex = ForceReadTexture(tex);
|
||||||
}
|
}
|
||||||
@ -140,20 +117,9 @@ namespace UnityExplorer.Helpers
|
|||||||
tex.Apply(false, false);
|
tex.Apply(false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if CPP
|
data = Instance.EncodeToPNG(tex);
|
||||||
data = tex.EncodeToPNG();
|
|
||||||
#else
|
|
||||||
if (isNewEncodeMethod)
|
|
||||||
{
|
|
||||||
data = (byte[])EncodeToPNGMethod.Invoke(null, new object[] { tex });
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
data = (byte[])EncodeToPNGMethod.Invoke(tex, new object[0]);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (data == null || data.Length < 1)
|
if (data == null || !data.Any())
|
||||||
{
|
{
|
||||||
ExplorerCore.LogWarning("Couldn't get any data for the texture!");
|
ExplorerCore.LogWarning("Couldn't get any data for the texture!");
|
||||||
}
|
}
|
204
src/Core/SceneExplorer.cs
Normal file
204
src/Core/SceneExplorer.cs
Normal file
@ -0,0 +1,204 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using UnityExplorer.UI;
|
||||||
|
using UnityExplorer.UI.Main;
|
||||||
|
using UnityExplorer.UI.Reusable;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.SceneManagement;
|
||||||
|
using UnityEngine.UI;
|
||||||
|
using UnityExplorer.Core.Runtime;
|
||||||
|
using UnityExplorer.UI.Main.Home;
|
||||||
|
|
||||||
|
namespace UnityExplorer.Core.Inspectors
|
||||||
|
{
|
||||||
|
public class SceneExplorer
|
||||||
|
{
|
||||||
|
public static SceneExplorer Instance;
|
||||||
|
|
||||||
|
public static SceneExplorerUI UI;
|
||||||
|
|
||||||
|
internal static Action OnToggleShow;
|
||||||
|
|
||||||
|
public SceneExplorer()
|
||||||
|
{
|
||||||
|
Instance = this;
|
||||||
|
|
||||||
|
UI = new SceneExplorerUI();
|
||||||
|
UI.ConstructScenePane();
|
||||||
|
}
|
||||||
|
|
||||||
|
private const float UPDATE_INTERVAL = 1f;
|
||||||
|
private float m_timeOfLastSceneUpdate;
|
||||||
|
|
||||||
|
// private int m_currentSceneHandle = -1;
|
||||||
|
public static Scene DontDestroyScene => DontDestroyObject.scene;
|
||||||
|
internal Scene m_currentScene;
|
||||||
|
internal Scene[] m_currentScenes = new Scene[0];
|
||||||
|
|
||||||
|
internal GameObject[] m_allObjects = new GameObject[0];
|
||||||
|
|
||||||
|
internal GameObject m_selectedSceneObject;
|
||||||
|
internal int m_lastCount;
|
||||||
|
|
||||||
|
internal static GameObject DontDestroyObject
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (!s_dontDestroyObject)
|
||||||
|
{
|
||||||
|
s_dontDestroyObject = new GameObject("DontDestroyMe");
|
||||||
|
GameObject.DontDestroyOnLoad(s_dontDestroyObject);
|
||||||
|
}
|
||||||
|
return s_dontDestroyObject;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
internal static GameObject s_dontDestroyObject;
|
||||||
|
|
||||||
|
public void Init()
|
||||||
|
{
|
||||||
|
RefreshSceneSelector();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Update()
|
||||||
|
{
|
||||||
|
if (SceneExplorerUI.Hiding || Time.realtimeSinceStartup - m_timeOfLastSceneUpdate < UPDATE_INTERVAL)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
RefreshSceneSelector();
|
||||||
|
|
||||||
|
if (!m_selectedSceneObject)
|
||||||
|
{
|
||||||
|
if (m_currentScene != default)
|
||||||
|
{
|
||||||
|
var rootObjects = RuntimeProvider.Instance.GetRootGameObjects(m_currentScene);
|
||||||
|
SetSceneObjectList(rootObjects);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RefreshSelectedSceneObject();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RefreshSceneSelector()
|
||||||
|
{
|
||||||
|
var newNames = new List<string>();
|
||||||
|
var newScenes = new List<Scene>();
|
||||||
|
|
||||||
|
if (m_currentScenes == null)
|
||||||
|
m_currentScenes = new Scene[0];
|
||||||
|
|
||||||
|
bool anyChange = SceneManager.sceneCount != m_currentScenes.Length - 1;
|
||||||
|
|
||||||
|
for (int i = 0; i < SceneManager.sceneCount; i++)
|
||||||
|
{
|
||||||
|
Scene scene = SceneManager.GetSceneAt(i);
|
||||||
|
|
||||||
|
if (scene == default)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
int handle = RuntimeProvider.Instance.GetSceneHandle(scene);
|
||||||
|
|
||||||
|
if (!anyChange && !m_currentScenes.Any(it => handle == RuntimeProvider.Instance.GetSceneHandle(it)))
|
||||||
|
anyChange = true;
|
||||||
|
|
||||||
|
newScenes.Add(scene);
|
||||||
|
newNames.Add(scene.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (anyChange)
|
||||||
|
{
|
||||||
|
newNames.Add("DontDestroyOnLoad");
|
||||||
|
newScenes.Add(DontDestroyScene);
|
||||||
|
m_currentScenes = newScenes.ToArray();
|
||||||
|
|
||||||
|
UI.OnActiveScenesChanged(newNames);
|
||||||
|
|
||||||
|
SetTargetScene(newScenes[0]);
|
||||||
|
|
||||||
|
SearchPage.Instance.OnSceneChange();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetTargetScene(int index)
|
||||||
|
=> SetTargetScene(m_currentScenes[index]);
|
||||||
|
|
||||||
|
public void SetTargetScene(Scene scene)
|
||||||
|
{
|
||||||
|
if (scene == default)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_currentScene = scene;
|
||||||
|
var rootObjs = RuntimeProvider.Instance.GetRootGameObjects(scene);
|
||||||
|
SetSceneObjectList(rootObjs);
|
||||||
|
|
||||||
|
m_selectedSceneObject = null;
|
||||||
|
|
||||||
|
UI.OnSceneSelected();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetSceneObjectParent()
|
||||||
|
{
|
||||||
|
if (!m_selectedSceneObject || !m_selectedSceneObject.transform.parent?.gameObject)
|
||||||
|
{
|
||||||
|
m_selectedSceneObject = null;
|
||||||
|
SetTargetScene(m_currentScene);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SetTargetObject(m_selectedSceneObject.transform.parent.gameObject);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetTargetObject(GameObject obj)
|
||||||
|
{
|
||||||
|
if (!obj)
|
||||||
|
return;
|
||||||
|
|
||||||
|
UI.OnGameObjectSelected(obj);
|
||||||
|
|
||||||
|
m_selectedSceneObject = obj;
|
||||||
|
|
||||||
|
RefreshSelectedSceneObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RefreshSelectedSceneObject()
|
||||||
|
{
|
||||||
|
GameObject[] list = new GameObject[m_selectedSceneObject.transform.childCount];
|
||||||
|
for (int i = 0; i < m_selectedSceneObject.transform.childCount; i++)
|
||||||
|
{
|
||||||
|
list[i] = m_selectedSceneObject.transform.GetChild(i).gameObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
SetSceneObjectList(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetSceneObjectList(GameObject[] objects)
|
||||||
|
{
|
||||||
|
m_allObjects = objects;
|
||||||
|
RefreshSceneObjectList();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void RefreshSceneObjectList()
|
||||||
|
{
|
||||||
|
m_timeOfLastSceneUpdate = Time.realtimeSinceStartup;
|
||||||
|
|
||||||
|
UI.RefreshSceneObjectList(m_allObjects, out int newCount);
|
||||||
|
|
||||||
|
m_lastCount = newCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void InspectSelectedGameObject()
|
||||||
|
{
|
||||||
|
InspectorManager.Instance.Inspect(Instance.m_selectedSceneObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void InvokeOnToggleShow()
|
||||||
|
{
|
||||||
|
OnToggleShow?.Invoke();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
14
src/Core/Search/ChildFilter.cs
Normal file
14
src/Core/Search/ChildFilter.cs
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace UnityExplorer.Search
|
||||||
|
{
|
||||||
|
internal enum ChildFilter
|
||||||
|
{
|
||||||
|
Any,
|
||||||
|
RootObject,
|
||||||
|
HasParent
|
||||||
|
}
|
||||||
|
}
|
15
src/Core/Search/SceneFilter.cs
Normal file
15
src/Core/Search/SceneFilter.cs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace UnityExplorer.Search
|
||||||
|
{
|
||||||
|
internal enum SceneFilter
|
||||||
|
{
|
||||||
|
Any,
|
||||||
|
Asset,
|
||||||
|
DontDestroyOnLoad,
|
||||||
|
Explicit,
|
||||||
|
}
|
||||||
|
}
|
17
src/Core/Search/SearchContext.cs
Normal file
17
src/Core/Search/SearchContext.cs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace UnityExplorer.Search
|
||||||
|
{
|
||||||
|
internal enum SearchContext
|
||||||
|
{
|
||||||
|
UnityObject,
|
||||||
|
GameObject,
|
||||||
|
Component,
|
||||||
|
Custom,
|
||||||
|
Singleton,
|
||||||
|
StaticClass
|
||||||
|
}
|
||||||
|
}
|
227
src/Core/Search/SearchProvider.cs
Normal file
227
src/Core/Search/SearchProvider.cs
Normal file
@ -0,0 +1,227 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Text;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityExplorer.Core;
|
||||||
|
using UnityExplorer.Core.Runtime;
|
||||||
|
using UnityExplorer.UI.Main;
|
||||||
|
|
||||||
|
namespace UnityExplorer.Search
|
||||||
|
{
|
||||||
|
public static class SearchProvider
|
||||||
|
{
|
||||||
|
internal static object[] StaticClassSearch(string input)
|
||||||
|
{
|
||||||
|
var list = new List<Type>();
|
||||||
|
|
||||||
|
var nameFilter = "";
|
||||||
|
if (!string.IsNullOrEmpty(input))
|
||||||
|
nameFilter = input.ToLower();
|
||||||
|
|
||||||
|
foreach (var asm in AppDomain.CurrentDomain.GetAssemblies())
|
||||||
|
{
|
||||||
|
foreach (var type in asm.TryGetTypes().Where(it => it.IsSealed && it.IsAbstract))
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(nameFilter) && !type.FullName.ToLower().Contains(nameFilter))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
list.Add(type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return list.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static string[] s_instanceNames = new string[]
|
||||||
|
{
|
||||||
|
"m_instance",
|
||||||
|
"m_Instance",
|
||||||
|
"s_instance",
|
||||||
|
"s_Instance",
|
||||||
|
"_instance",
|
||||||
|
"_Instance",
|
||||||
|
"instance",
|
||||||
|
"Instance",
|
||||||
|
"<Instance>k__BackingField",
|
||||||
|
"<instance>k__BackingField",
|
||||||
|
};
|
||||||
|
|
||||||
|
internal static object[] SingletonSearch(string input)
|
||||||
|
{
|
||||||
|
var instances = new List<object>();
|
||||||
|
|
||||||
|
var nameFilter = "";
|
||||||
|
if (!string.IsNullOrEmpty(input))
|
||||||
|
nameFilter = input.ToLower();
|
||||||
|
|
||||||
|
var flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static;
|
||||||
|
|
||||||
|
foreach (var asm in AppDomain.CurrentDomain.GetAssemblies())
|
||||||
|
{
|
||||||
|
// Search all non-static, non-enum classes.
|
||||||
|
foreach (var type in asm.TryGetTypes().Where(it => !(it.IsSealed && it.IsAbstract) && !it.IsEnum))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(nameFilter) && !type.FullName.ToLower().Contains(nameFilter))
|
||||||
|
continue;
|
||||||
|
#if CPP
|
||||||
|
// Only look for Properties in IL2CPP, not for Mono.
|
||||||
|
PropertyInfo pi;
|
||||||
|
foreach (var name in s_instanceNames)
|
||||||
|
{
|
||||||
|
pi = type.GetProperty(name, flags);
|
||||||
|
if (pi != null)
|
||||||
|
{
|
||||||
|
var instance = pi.GetValue(null, null);
|
||||||
|
if (instance != null)
|
||||||
|
{
|
||||||
|
instances.Add(instance);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
// 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);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return instances.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static object[] UnityObjectSearch(string input, string customTypeInput, SearchContext context,
|
||||||
|
ChildFilter childFilter, SceneFilter sceneFilter)
|
||||||
|
{
|
||||||
|
Type searchType = null;
|
||||||
|
switch (context)
|
||||||
|
{
|
||||||
|
case SearchContext.GameObject:
|
||||||
|
searchType = typeof(GameObject); break;
|
||||||
|
|
||||||
|
case SearchContext.Component:
|
||||||
|
searchType = typeof(Component); break;
|
||||||
|
|
||||||
|
case SearchContext.Custom:
|
||||||
|
if (string.IsNullOrEmpty(customTypeInput))
|
||||||
|
{
|
||||||
|
ExplorerCore.LogWarning("Custom Type input must not be empty!");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (ReflectionUtility.GetTypeByName(customTypeInput) is Type customType)
|
||||||
|
if (typeof(UnityEngine.Object).IsAssignableFrom(customType))
|
||||||
|
searchType = customType;
|
||||||
|
else
|
||||||
|
ExplorerCore.LogWarning($"Custom type '{customType.FullName}' is not assignable from UnityEngine.Object!");
|
||||||
|
else
|
||||||
|
ExplorerCore.LogWarning($"Could not find a type by the name '{customTypeInput}'!");
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
searchType = typeof(UnityEngine.Object); break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (searchType == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
var allObjects = RuntimeProvider.Instance.FindObjectsOfTypeAll(searchType);
|
||||||
|
var results = new List<object>();
|
||||||
|
|
||||||
|
// perform filter comparers
|
||||||
|
|
||||||
|
string nameFilter = null;
|
||||||
|
if (!string.IsNullOrEmpty(input))
|
||||||
|
nameFilter = input.ToLower();
|
||||||
|
|
||||||
|
bool canGetGameObject = (sceneFilter != SceneFilter.Any || childFilter != ChildFilter.Any)
|
||||||
|
&& (context == SearchContext.GameObject || typeof(Component).IsAssignableFrom(searchType));
|
||||||
|
|
||||||
|
string sceneFilterString = null;
|
||||||
|
if (!canGetGameObject)
|
||||||
|
{
|
||||||
|
if (context != SearchContext.UnityObject && (sceneFilter != SceneFilter.Any || childFilter != ChildFilter.Any))
|
||||||
|
ExplorerCore.LogWarning($"Type '{searchType}' cannot have Scene or Child filters applied to it");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (sceneFilter == SceneFilter.DontDestroyOnLoad)
|
||||||
|
sceneFilterString = "DontDestroyOnLoad";
|
||||||
|
else if (sceneFilter == SceneFilter.Explicit)
|
||||||
|
sceneFilterString = SearchPage.Instance.m_sceneDropdown.options[SearchPage.Instance.m_sceneDropdown.value].text;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var obj in allObjects)
|
||||||
|
{
|
||||||
|
// name check
|
||||||
|
if (!string.IsNullOrEmpty(nameFilter) && !obj.name.ToLower().Contains(nameFilter))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (canGetGameObject)
|
||||||
|
{
|
||||||
|
#if MONO
|
||||||
|
var go = context == SearchContext.GameObject
|
||||||
|
? obj as GameObject
|
||||||
|
: (obj as Component).gameObject;
|
||||||
|
#else
|
||||||
|
var go = context == SearchContext.GameObject
|
||||||
|
? obj.TryCast<GameObject>()
|
||||||
|
: obj.TryCast<Component>().gameObject;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// scene check
|
||||||
|
if (sceneFilter != SceneFilter.Any)
|
||||||
|
{
|
||||||
|
if (!go)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
switch (context)
|
||||||
|
{
|
||||||
|
case SearchContext.GameObject:
|
||||||
|
if (go.scene.name != sceneFilterString)
|
||||||
|
continue;
|
||||||
|
break;
|
||||||
|
case SearchContext.Custom:
|
||||||
|
case SearchContext.Component:
|
||||||
|
if (go.scene.name != sceneFilterString)
|
||||||
|
continue;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (childFilter != ChildFilter.Any)
|
||||||
|
{
|
||||||
|
if (!go)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// root object check (no parent)
|
||||||
|
if (childFilter == ChildFilter.HasParent && !go.transform.parent)
|
||||||
|
continue;
|
||||||
|
else if (childFilter == ChildFilter.RootObject && go.transform.parent)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
results.Add(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
return results.ToArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
290
src/Core/Tests/Tests.cs
Normal file
290
src/Core/Tests/Tests.cs
Normal file
@ -0,0 +1,290 @@
|
|||||||
|
//using System.Collections;
|
||||||
|
//using System.Collections.Generic;
|
||||||
|
//using UnityExplorer.UI;
|
||||||
|
//using UnityEngine;
|
||||||
|
//using System;
|
||||||
|
//using System.Runtime.InteropServices;
|
||||||
|
//using System.Text;
|
||||||
|
//using UnityExplorer.Core.Runtime;
|
||||||
|
|
||||||
|
//namespace UnityExplorer.Core.Tests
|
||||||
|
//{
|
||||||
|
// internal enum TestByteEnum : byte
|
||||||
|
// {
|
||||||
|
// One,
|
||||||
|
// Two,
|
||||||
|
// Three,
|
||||||
|
// TwoFiftyFive = 255,
|
||||||
|
// }
|
||||||
|
|
||||||
|
// public static class StaticTestClass
|
||||||
|
// {
|
||||||
|
// public static int StaticProperty => 5;
|
||||||
|
// public static int StaticField = 69;
|
||||||
|
// public static List<string> StaticList = new List<string>
|
||||||
|
// {
|
||||||
|
// "one",
|
||||||
|
// "two",
|
||||||
|
// "three",
|
||||||
|
// };
|
||||||
|
// public static void StaticMethod() { }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// public class TestClass
|
||||||
|
// {
|
||||||
|
// internal static TestByteEnum testingByte = TestByteEnum.One;
|
||||||
|
|
||||||
|
// public string AAALongString = @"1
|
||||||
|
//2
|
||||||
|
//3
|
||||||
|
//4
|
||||||
|
//5";
|
||||||
|
|
||||||
|
// public Vector2 AATestVector2 = new Vector2(1, 2);
|
||||||
|
// public Vector3 AATestVector3 = new Vector3(1, 2, 3);
|
||||||
|
// public Vector4 AATestVector4 = new Vector4(1, 2, 3, 4);
|
||||||
|
// public Rect AATestRect = new Rect(1, 2, 3, 4);
|
||||||
|
// public Color AATestColor = new Color(0.1f, 0.2f, 0.3f, 0.4f);
|
||||||
|
|
||||||
|
// public bool ATestBoolMethod() => false;
|
||||||
|
|
||||||
|
// public bool this[int index]
|
||||||
|
// {
|
||||||
|
// get => index % 2 == 0;
|
||||||
|
// set => m_thisBool = value;
|
||||||
|
// }
|
||||||
|
// internal bool m_thisBool;
|
||||||
|
|
||||||
|
// static int testInt;
|
||||||
|
// public static List<string> ExceptionList
|
||||||
|
// {
|
||||||
|
// get
|
||||||
|
// {
|
||||||
|
// testInt++;
|
||||||
|
// if (testInt % 2 == 0)
|
||||||
|
// throw new Exception("its even");
|
||||||
|
// else
|
||||||
|
// return new List<string> { "one" };
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// static bool abool;
|
||||||
|
// public static bool ATestExceptionBool
|
||||||
|
// {
|
||||||
|
// get
|
||||||
|
// {
|
||||||
|
// abool = !abool;
|
||||||
|
// if (!abool)
|
||||||
|
// throw new Exception("false");
|
||||||
|
// else
|
||||||
|
// return true;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// public static string ExceptionString => throw new NotImplementedException();
|
||||||
|
|
||||||
|
// public static string ANullString = null;
|
||||||
|
// public static float ATestFloat = 420.69f;
|
||||||
|
// public static int ATestInt = -1;
|
||||||
|
// public static string ATestString = "hello world";
|
||||||
|
// public static uint ATestUInt = 1u;
|
||||||
|
// public static byte ATestByte = 255;
|
||||||
|
// public static ulong AReadonlyUlong = 82934UL;
|
||||||
|
|
||||||
|
// public static TestClass Instance => m_instance ?? (m_instance = new TestClass());
|
||||||
|
// private static TestClass m_instance;
|
||||||
|
|
||||||
|
// public object AmbigObject;
|
||||||
|
|
||||||
|
// public List<List<List<string>>> ANestedNestedList = new List<List<List<string>>>
|
||||||
|
// {
|
||||||
|
// new List<List<string>>
|
||||||
|
// {
|
||||||
|
// new List<string>
|
||||||
|
// {
|
||||||
|
// "one",
|
||||||
|
// "two",
|
||||||
|
// },
|
||||||
|
// new List<string>
|
||||||
|
// {
|
||||||
|
// "three",
|
||||||
|
// "four"
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// new List<List<string>>
|
||||||
|
// {
|
||||||
|
// new List<string>
|
||||||
|
// {
|
||||||
|
// "five",
|
||||||
|
// "six"
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
|
||||||
|
// public static bool SetOnlyProperty
|
||||||
|
// {
|
||||||
|
// set => m_setOnlyProperty = value;
|
||||||
|
// }
|
||||||
|
// private static bool m_setOnlyProperty;
|
||||||
|
// public static bool ReadSetOnlyProperty => m_setOnlyProperty;
|
||||||
|
|
||||||
|
// public Texture2D TestTexture;
|
||||||
|
// public static Sprite TestSprite;
|
||||||
|
|
||||||
|
//#if CPP
|
||||||
|
// public static Il2CppSystem.Collections.Generic.HashSet<string> CppHashSetTest;
|
||||||
|
// public static Il2CppSystem.Collections.Generic.List<string> CppStringTest;
|
||||||
|
// public static Il2CppSystem.Collections.IList CppIList;
|
||||||
|
// //public static Il2CppSystem.Collections.Generic.Dictionary<string, string> CppDictTest;
|
||||||
|
// //public static Il2CppSystem.Collections.Generic.Dictionary<int, float> CppDictTest2;
|
||||||
|
//#endif
|
||||||
|
|
||||||
|
// public TestClass()
|
||||||
|
// {
|
||||||
|
// int a = 0;
|
||||||
|
// foreach (var list in ANestedNestedList)
|
||||||
|
// {
|
||||||
|
// foreach (var list2 in list)
|
||||||
|
// {
|
||||||
|
// for (int i = 0; i < 33; i++)
|
||||||
|
// list2.Add(a++.ToString());
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
//#if CPP
|
||||||
|
// //TextureSpriteTest();
|
||||||
|
|
||||||
|
// CppHashSetTest = new Il2CppSystem.Collections.Generic.HashSet<string>();
|
||||||
|
// CppHashSetTest.Add("1");
|
||||||
|
// CppHashSetTest.Add("2");
|
||||||
|
// CppHashSetTest.Add("3");
|
||||||
|
|
||||||
|
// CppStringTest = new Il2CppSystem.Collections.Generic.List<string>();
|
||||||
|
// CppStringTest.Add("1");
|
||||||
|
// CppStringTest.Add("2");
|
||||||
|
|
||||||
|
// //CppDictTest = new Il2CppSystem.Collections.Generic.Dictionary<string, string>();
|
||||||
|
// //CppDictTest.Add("key1", "value1");
|
||||||
|
// //CppDictTest.Add("key2", "value2");
|
||||||
|
// //CppDictTest.Add("key3", "value3");
|
||||||
|
|
||||||
|
// //CppDictTest2 = new Il2CppSystem.Collections.Generic.Dictionary<int, float>();
|
||||||
|
// //CppDictTest2.Add(0, 0.5f);
|
||||||
|
// //CppDictTest2.Add(1, 0.5f);
|
||||||
|
// //CppDictTest2.Add(2, 0.5f);
|
||||||
|
//#endif
|
||||||
|
// }
|
||||||
|
|
||||||
|
// //private void TextureSpriteTest()
|
||||||
|
// //{
|
||||||
|
// // TestTexture = new Texture2D(32, 32, TextureFormat.ARGB32, false)
|
||||||
|
// // {
|
||||||
|
// // name = "TestTexture"
|
||||||
|
// // };
|
||||||
|
// // TestSprite = TextureUtilProvider.Instance.CreateSprite(TestTexture);
|
||||||
|
|
||||||
|
// // GameObject.DontDestroyOnLoad(TestTexture);
|
||||||
|
// // GameObject.DontDestroyOnLoad(TestSprite);
|
||||||
|
|
||||||
|
// // // test loading a tex from file
|
||||||
|
// // if (System.IO.File.Exists(@"D:\Downloads\test.png"))
|
||||||
|
// // {
|
||||||
|
// // var dataToLoad = System.IO.File.ReadAllBytes(@"D:\Downloads\test.png");
|
||||||
|
// // ExplorerCore.Log($"Tex load success: {TestTexture.LoadImage(dataToLoad, false)}");
|
||||||
|
// // }
|
||||||
|
// //}
|
||||||
|
|
||||||
|
// //public static string TestRefInOutGeneric<T>(ref string arg0, in int arg1, out string arg2) where T : Component
|
||||||
|
// //{
|
||||||
|
// // arg2 = "this is arg2";
|
||||||
|
|
||||||
|
// // return $"T: '{typeof(T).FullName}', ref arg0: '{arg0}', in arg1: '{arg1}', out arg2: '{arg2}'";
|
||||||
|
// //}
|
||||||
|
|
||||||
|
// // test a non-generic dictionary
|
||||||
|
|
||||||
|
// public Hashtable TestNonGenericDict()
|
||||||
|
// {
|
||||||
|
// return new Hashtable
|
||||||
|
// {
|
||||||
|
// { "One", 1 },
|
||||||
|
// { "Two", 2 },
|
||||||
|
// { "Three", 3 },
|
||||||
|
// };
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // test HashSets
|
||||||
|
|
||||||
|
// public static HashSet<string> HashSetTest = new HashSet<string>
|
||||||
|
// {
|
||||||
|
// "One",
|
||||||
|
// "Two",
|
||||||
|
// "Three"
|
||||||
|
// };
|
||||||
|
|
||||||
|
|
||||||
|
// // Test indexed parameter
|
||||||
|
|
||||||
|
// public string this[int arg0, string arg1]
|
||||||
|
// {
|
||||||
|
// get
|
||||||
|
// {
|
||||||
|
// return $"arg0: {arg0}, arg1: {arg1}";
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // Test basic list
|
||||||
|
|
||||||
|
// public static List<string> TestList = new List<string>
|
||||||
|
// {
|
||||||
|
// "1",
|
||||||
|
// "2",
|
||||||
|
// "3",
|
||||||
|
// "etc..."
|
||||||
|
// };
|
||||||
|
|
||||||
|
// // Test a nested dictionary
|
||||||
|
|
||||||
|
// public static Dictionary<int, Dictionary<string, int>> NestedDictionary = new Dictionary<int, Dictionary<string, int>>
|
||||||
|
// {
|
||||||
|
// {
|
||||||
|
// 1,
|
||||||
|
// new Dictionary<string, int>
|
||||||
|
// {
|
||||||
|
// {
|
||||||
|
// "Sub 1", 123
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// "Sub 2", 456
|
||||||
|
// },
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// 2,
|
||||||
|
// new Dictionary<string, int>
|
||||||
|
// {
|
||||||
|
// {
|
||||||
|
// "Sub 3", 789
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// "Sub 4", 000
|
||||||
|
// },
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// };
|
||||||
|
|
||||||
|
// // Test a basic method
|
||||||
|
|
||||||
|
// public static Color TestMethod(float r, float g, float b, float 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);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//}
|
@ -1,9 +1,9 @@
|
|||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace UnityExplorer.Unstrip
|
namespace UnityExplorer.Core.Unity
|
||||||
{
|
{
|
||||||
public static class ColorUtilityUnstrip
|
public static class ColorHelper
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Converts Color to 6-digit RGB hex code (without # symbol). Eg, RGBA(1,0,0,1) -> FF0000
|
/// Converts Color to 6-digit RGB hex code (without # symbol). Eg, RGBA(1,0,0,1) -> FF0000
|
@ -1,8 +1,8 @@
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace UnityExplorer.Helpers
|
namespace UnityExplorer.Core.Unity
|
||||||
{
|
{
|
||||||
public static class UnityHelpers
|
public static class UnityHelper
|
||||||
{
|
{
|
||||||
private static Camera m_mainCamera;
|
private static Camera m_mainCamera;
|
||||||
|
|
@ -3,13 +3,14 @@ using System.IO;
|
|||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.SceneManagement;
|
using UnityEngine.SceneManagement;
|
||||||
using UnityExplorer.Config;
|
using UnityExplorer.Core.Config;
|
||||||
using UnityExplorer.Helpers;
|
using UnityExplorer.Core.Unity;
|
||||||
using UnityExplorer.Input;
|
using UnityExplorer.Core.Input;
|
||||||
using UnityExplorer.Inspectors;
|
using UnityExplorer.Core.Inspectors;
|
||||||
using UnityExplorer.Runtime;
|
using UnityExplorer.Core.Runtime;
|
||||||
using UnityExplorer.UI;
|
using UnityExplorer.UI;
|
||||||
using UnityExplorer.UI.Modules;
|
using UnityExplorer.UI.Main;
|
||||||
|
using UnityExplorer.UI.Utility;
|
||||||
|
|
||||||
namespace UnityExplorer
|
namespace UnityExplorer
|
||||||
{
|
{
|
||||||
@ -52,7 +53,7 @@ namespace UnityExplorer
|
|||||||
|
|
||||||
InputManager.Init();
|
InputManager.Init();
|
||||||
|
|
||||||
ForceUnlockCursor.Init();
|
CursorUnlocker.Init();
|
||||||
|
|
||||||
UIManager.ShowMenu = true;
|
UIManager.ShowMenu = true;
|
||||||
|
|
||||||
@ -63,8 +64,8 @@ namespace UnityExplorer
|
|||||||
{
|
{
|
||||||
UIManager.CheckUIInit();
|
UIManager.CheckUIInit();
|
||||||
|
|
||||||
if (MouseInspector.Enabled)
|
if (InspectUnderMouse.Enabled)
|
||||||
MouseInspector.UpdateInspect();
|
InspectUnderMouse.UpdateInspect();
|
||||||
else
|
else
|
||||||
UIManager.Update();
|
UIManager.Update();
|
||||||
}
|
}
|
||||||
|
@ -1,138 +0,0 @@
|
|||||||
using System;
|
|
||||||
using UnityEngine;
|
|
||||||
using UnityEngine.UI;
|
|
||||||
using UnityExplorer.Helpers;
|
|
||||||
using UnityExplorer.UI;
|
|
||||||
|
|
||||||
namespace UnityExplorer.Inspectors
|
|
||||||
{
|
|
||||||
public abstract class InspectorBase
|
|
||||||
{
|
|
||||||
public object Target;
|
|
||||||
|
|
||||||
public abstract string TabLabel { get; }
|
|
||||||
|
|
||||||
public bool IsActive { get; private set; }
|
|
||||||
public abstract GameObject Content { get; set; }
|
|
||||||
public Button tabButton;
|
|
||||||
public Text tabText;
|
|
||||||
|
|
||||||
internal bool m_pendingDestroy;
|
|
||||||
|
|
||||||
public InspectorBase(object target)
|
|
||||||
{
|
|
||||||
Target = target;
|
|
||||||
|
|
||||||
if (Target.IsNullOrDestroyed(false))
|
|
||||||
{
|
|
||||||
Destroy();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
AddInspectorTab();
|
|
||||||
}
|
|
||||||
|
|
||||||
public virtual void SetActive()
|
|
||||||
{
|
|
||||||
this.IsActive = true;
|
|
||||||
Content?.SetActive(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public virtual void SetInactive()
|
|
||||||
{
|
|
||||||
this.IsActive = false;
|
|
||||||
Content?.SetActive(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public virtual void Update()
|
|
||||||
{
|
|
||||||
if (Target.IsNullOrDestroyed(false))
|
|
||||||
{
|
|
||||||
Destroy();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
tabText.text = TabLabel;
|
|
||||||
}
|
|
||||||
|
|
||||||
public virtual void Destroy()
|
|
||||||
{
|
|
||||||
m_pendingDestroy = true;
|
|
||||||
|
|
||||||
GameObject tabGroup = tabButton?.transform.parent.gameObject;
|
|
||||||
|
|
||||||
if (tabGroup)
|
|
||||||
{
|
|
||||||
GameObject.Destroy(tabGroup);
|
|
||||||
}
|
|
||||||
|
|
||||||
int thisIndex = -1;
|
|
||||||
if (InspectorManager.Instance.m_currentInspectors.Contains(this))
|
|
||||||
{
|
|
||||||
thisIndex = InspectorManager.Instance.m_currentInspectors.IndexOf(this);
|
|
||||||
InspectorManager.Instance.m_currentInspectors.Remove(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ReferenceEquals(InspectorManager.Instance.m_activeInspector, this))
|
|
||||||
{
|
|
||||||
InspectorManager.Instance.UnsetInspectorTab();
|
|
||||||
|
|
||||||
if (InspectorManager.Instance.m_currentInspectors.Count > 0)
|
|
||||||
{
|
|
||||||
var prevTab = InspectorManager.Instance.m_currentInspectors[thisIndex > 0 ? thisIndex - 1 : 0];
|
|
||||||
InspectorManager.Instance.SetInspectorTab(prevTab);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#region UI CONSTRUCTION
|
|
||||||
|
|
||||||
public void AddInspectorTab()
|
|
||||||
{
|
|
||||||
var tabContent = InspectorManager.Instance.m_tabBarContent;
|
|
||||||
|
|
||||||
var tabGroupObj = UIFactory.CreateHorizontalGroup(tabContent);
|
|
||||||
var tabGroup = tabGroupObj.GetComponent<HorizontalLayoutGroup>();
|
|
||||||
tabGroup.childForceExpandWidth = true;
|
|
||||||
tabGroup.childControlWidth = true;
|
|
||||||
var tabLayout = tabGroupObj.AddComponent<LayoutElement>();
|
|
||||||
tabLayout.minWidth = 185;
|
|
||||||
tabLayout.flexibleWidth = 0;
|
|
||||||
tabGroupObj.AddComponent<Mask>();
|
|
||||||
|
|
||||||
var targetButtonObj = UIFactory.CreateButton(tabGroupObj);
|
|
||||||
targetButtonObj.AddComponent<Mask>();
|
|
||||||
var targetButtonLayout = targetButtonObj.AddComponent<LayoutElement>();
|
|
||||||
targetButtonLayout.minWidth = 165;
|
|
||||||
targetButtonLayout.flexibleWidth = 0;
|
|
||||||
|
|
||||||
tabText = targetButtonObj.GetComponentInChildren<Text>();
|
|
||||||
tabText.horizontalOverflow = HorizontalWrapMode.Overflow;
|
|
||||||
tabText.alignment = TextAnchor.MiddleLeft;
|
|
||||||
|
|
||||||
tabButton = targetButtonObj.GetComponent<Button>();
|
|
||||||
|
|
||||||
tabButton.onClick.AddListener(() => { InspectorManager.Instance.SetInspectorTab(this); });
|
|
||||||
|
|
||||||
var closeBtnObj = UIFactory.CreateButton(tabGroupObj);
|
|
||||||
var closeBtnLayout = closeBtnObj.AddComponent<LayoutElement>();
|
|
||||||
closeBtnLayout.minWidth = 20;
|
|
||||||
closeBtnLayout.flexibleWidth = 0;
|
|
||||||
var closeBtnText = closeBtnObj.GetComponentInChildren<Text>();
|
|
||||||
closeBtnText.text = "X";
|
|
||||||
closeBtnText.color = new Color(1, 0, 0, 1);
|
|
||||||
|
|
||||||
var closeBtn = closeBtnObj.GetComponent<Button>();
|
|
||||||
|
|
||||||
closeBtn.onClick.AddListener(Destroy);
|
|
||||||
|
|
||||||
var closeColors = closeBtn.colors;
|
|
||||||
closeColors.normalColor = new Color(0.2f, 0.2f, 0.2f, 1);
|
|
||||||
closeBtn.colors = closeColors;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,617 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using UnityExplorer.Helpers;
|
|
||||||
using UnityEngine;
|
|
||||||
using UnityExplorer.Inspectors.Reflection;
|
|
||||||
using UnityExplorer.UI.Shared;
|
|
||||||
using System.Reflection;
|
|
||||||
using UnityExplorer.UI;
|
|
||||||
using UnityEngine.UI;
|
|
||||||
using UnityExplorer.Config;
|
|
||||||
|
|
||||||
namespace UnityExplorer.Inspectors
|
|
||||||
{
|
|
||||||
public class ReflectionInspector : InspectorBase
|
|
||||||
{
|
|
||||||
#region STATIC
|
|
||||||
|
|
||||||
public static ReflectionInspector ActiveInstance { get; private set; }
|
|
||||||
|
|
||||||
static ReflectionInspector()
|
|
||||||
{
|
|
||||||
PanelDragger.OnFinishResize += OnContainerResized;
|
|
||||||
SceneExplorer.OnToggleShow += OnContainerResized;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void OnContainerResized()
|
|
||||||
{
|
|
||||||
if (ActiveInstance == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
ActiveInstance.m_widthUpdateWanted = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Blacklists
|
|
||||||
private static readonly HashSet<string> bl_typeAndMember = new HashSet<string>
|
|
||||||
{
|
|
||||||
#if CPP
|
|
||||||
// these cause a crash in IL2CPP
|
|
||||||
"Type.DeclaringMethod",
|
|
||||||
"Rigidbody2D.Cast",
|
|
||||||
"Collider2D.Cast",
|
|
||||||
"Collider2D.Raycast",
|
|
||||||
"Texture2D.SetPixelDataImpl",
|
|
||||||
"Camera.CalculateProjectionMatrixFromPhysicalProperties",
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
private static readonly HashSet<string> bl_memberNameStartsWith = new HashSet<string>
|
|
||||||
{
|
|
||||||
// these are redundant
|
|
||||||
"get_",
|
|
||||||
"set_",
|
|
||||||
};
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region INSTANCE
|
|
||||||
|
|
||||||
public override string TabLabel => m_targetTypeShortName;
|
|
||||||
|
|
||||||
internal CacheObjectBase ParentMember { get; set; }
|
|
||||||
|
|
||||||
internal readonly Type m_targetType;
|
|
||||||
internal readonly string m_targetTypeShortName;
|
|
||||||
|
|
||||||
// all cached members of the target
|
|
||||||
internal CacheMember[] m_allMembers;
|
|
||||||
// filtered members based on current filters
|
|
||||||
internal readonly List<CacheMember> m_membersFiltered = new List<CacheMember>();
|
|
||||||
// actual shortlist of displayed members
|
|
||||||
internal readonly CacheMember[] m_displayedMembers = new CacheMember[ExplorerConfig.Instance.Default_Page_Limit];
|
|
||||||
|
|
||||||
internal bool m_autoUpdate;
|
|
||||||
|
|
||||||
// UI members
|
|
||||||
|
|
||||||
private GameObject m_content;
|
|
||||||
public override GameObject Content
|
|
||||||
{
|
|
||||||
get => m_content;
|
|
||||||
set => m_content = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal Text m_nameFilterText;
|
|
||||||
internal MemberTypes m_memberFilter;
|
|
||||||
internal Button m_lastActiveMemButton;
|
|
||||||
|
|
||||||
internal PageHandler m_pageHandler;
|
|
||||||
internal SliderScrollbar m_sliderScroller;
|
|
||||||
internal GameObject m_scrollContent;
|
|
||||||
internal RectTransform m_scrollContentRect;
|
|
||||||
|
|
||||||
internal bool m_widthUpdateWanted;
|
|
||||||
internal bool m_widthUpdateWaiting;
|
|
||||||
|
|
||||||
public ReflectionInspector(object target) : base(target)
|
|
||||||
{
|
|
||||||
if (this is StaticInspector)
|
|
||||||
m_targetType = target as Type;
|
|
||||||
else
|
|
||||||
m_targetType = ReflectionHelpers.GetActualType(target);
|
|
||||||
|
|
||||||
m_targetTypeShortName = UISyntaxHighlight.ParseFullSyntax(m_targetType, false);
|
|
||||||
|
|
||||||
ConstructUI();
|
|
||||||
|
|
||||||
CacheMembers(m_targetType);
|
|
||||||
|
|
||||||
FilterMembers();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void SetActive()
|
|
||||||
{
|
|
||||||
base.SetActive();
|
|
||||||
ActiveInstance = this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void SetInactive()
|
|
||||||
{
|
|
||||||
base.SetInactive();
|
|
||||||
ActiveInstance = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Destroy()
|
|
||||||
{
|
|
||||||
base.Destroy();
|
|
||||||
|
|
||||||
if (this.Content)
|
|
||||||
GameObject.Destroy(this.Content);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnPageTurned()
|
|
||||||
{
|
|
||||||
RefreshDisplay();
|
|
||||||
}
|
|
||||||
|
|
||||||
internal bool IsBlacklisted(string sig) => bl_typeAndMember.Any(it => sig.Contains(it));
|
|
||||||
internal bool IsBlacklisted(MethodInfo method) => bl_memberNameStartsWith.Any(it => method.Name.StartsWith(it));
|
|
||||||
|
|
||||||
internal string GetSig(MemberInfo member) => $"{member.DeclaringType.Name}.{member.Name}";
|
|
||||||
internal string AppendArgsToSig(ParameterInfo[] args)
|
|
||||||
{
|
|
||||||
string ret = " (";
|
|
||||||
foreach (var param in args)
|
|
||||||
ret += $"{param.ParameterType.Name} {param.Name}, ";
|
|
||||||
ret += ")";
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void CacheMembers(Type type)
|
|
||||||
{
|
|
||||||
var list = new List<CacheMember>();
|
|
||||||
var cachedSigs = new HashSet<string>();
|
|
||||||
|
|
||||||
var types = ReflectionHelpers.GetAllBaseTypes(type);
|
|
||||||
|
|
||||||
var flags = BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static;
|
|
||||||
if (this is InstanceInspector)
|
|
||||||
flags |= BindingFlags.Instance;
|
|
||||||
|
|
||||||
foreach (var declaringType in types)
|
|
||||||
{
|
|
||||||
var target = Target;
|
|
||||||
#if CPP
|
|
||||||
target = target.Il2CppCast(declaringType);
|
|
||||||
#endif
|
|
||||||
IEnumerable<MemberInfo> infos = declaringType.GetMethods(flags);
|
|
||||||
infos = infos.Concat(declaringType.GetProperties(flags));
|
|
||||||
infos = infos.Concat(declaringType.GetFields(flags));
|
|
||||||
|
|
||||||
foreach (var member in infos)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var sig = GetSig(member);
|
|
||||||
|
|
||||||
//ExplorerCore.Log($"Trying to cache member {sig}...");
|
|
||||||
//ExplorerCore.Log(member.DeclaringType.FullName + "." + member.Name);
|
|
||||||
|
|
||||||
var mi = member as MethodInfo;
|
|
||||||
var pi = member as PropertyInfo;
|
|
||||||
var fi = member as FieldInfo;
|
|
||||||
|
|
||||||
if (IsBlacklisted(sig) || (mi != null && IsBlacklisted(mi)))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
var args = mi?.GetParameters() ?? pi?.GetIndexParameters();
|
|
||||||
if (args != null)
|
|
||||||
{
|
|
||||||
if (!CacheMember.CanProcessArgs(args))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
sig += AppendArgsToSig(args);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cachedSigs.Contains(sig))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
cachedSigs.Add(sig);
|
|
||||||
|
|
||||||
if (mi != null)
|
|
||||||
list.Add(new CacheMethod(mi, target, m_scrollContent));
|
|
||||||
else if (pi != null)
|
|
||||||
list.Add(new CacheProperty(pi, target, m_scrollContent));
|
|
||||||
else
|
|
||||||
list.Add(new CacheField(fi, target, m_scrollContent));
|
|
||||||
|
|
||||||
list.Last().ParentInspector = this;
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
ExplorerCore.LogWarning($"Exception caching member {member.DeclaringType.FullName}.{member.Name}!");
|
|
||||||
ExplorerCore.Log(e.ToString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var typeList = types.ToList();
|
|
||||||
|
|
||||||
var sorted = new List<CacheMember>();
|
|
||||||
sorted.AddRange(list.Where(it => it is CacheMethod)
|
|
||||||
.OrderBy(it => typeList.IndexOf(it.DeclaringType))
|
|
||||||
.ThenBy(it => it.NameForFiltering));
|
|
||||||
sorted.AddRange(list.Where(it => it is CacheProperty)
|
|
||||||
.OrderBy(it => typeList.IndexOf(it.DeclaringType))
|
|
||||||
.ThenBy(it => it.NameForFiltering));
|
|
||||||
sorted.AddRange(list.Where(it => it is CacheField)
|
|
||||||
.OrderBy(it => typeList.IndexOf(it.DeclaringType))
|
|
||||||
.ThenBy(it => it.NameForFiltering));
|
|
||||||
|
|
||||||
m_allMembers = sorted.ToArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Update()
|
|
||||||
{
|
|
||||||
base.Update();
|
|
||||||
|
|
||||||
if (m_autoUpdate)
|
|
||||||
{
|
|
||||||
foreach (var member in m_displayedMembers)
|
|
||||||
{
|
|
||||||
if (member == null) break;
|
|
||||||
member.UpdateValue();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_widthUpdateWanted)
|
|
||||||
{
|
|
||||||
if (!m_widthUpdateWaiting)
|
|
||||||
m_widthUpdateWaiting = true;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UpdateWidths();
|
|
||||||
m_widthUpdateWaiting = false;
|
|
||||||
m_widthUpdateWanted = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnMemberFilterClicked(MemberTypes type, Button button)
|
|
||||||
{
|
|
||||||
if (m_lastActiveMemButton)
|
|
||||||
{
|
|
||||||
var lastColors = m_lastActiveMemButton.colors;
|
|
||||||
lastColors.normalColor = new Color(0.2f, 0.2f, 0.2f);
|
|
||||||
m_lastActiveMemButton.colors = lastColors;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_memberFilter = type;
|
|
||||||
m_lastActiveMemButton = button;
|
|
||||||
|
|
||||||
var colors = m_lastActiveMemButton.colors;
|
|
||||||
colors.normalColor = new Color(0.2f, 0.6f, 0.2f);
|
|
||||||
m_lastActiveMemButton.colors = colors;
|
|
||||||
|
|
||||||
FilterMembers(null, true);
|
|
||||||
m_sliderScroller.m_slider.value = 1f;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void FilterMembers(string nameFilter = null, bool force = false)
|
|
||||||
{
|
|
||||||
int lastCount = m_membersFiltered.Count;
|
|
||||||
m_membersFiltered.Clear();
|
|
||||||
|
|
||||||
nameFilter = nameFilter?.ToLower() ?? m_nameFilterText.text.ToLower();
|
|
||||||
|
|
||||||
foreach (var mem in m_allMembers)
|
|
||||||
{
|
|
||||||
// membertype filter
|
|
||||||
if (m_memberFilter != MemberTypes.All && mem.MemInfo.MemberType != m_memberFilter)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (this is InstanceInspector ii && ii.m_scopeFilter != MemberScopes.All)
|
|
||||||
{
|
|
||||||
if (mem.IsStatic && ii.m_scopeFilter != MemberScopes.Static)
|
|
||||||
continue;
|
|
||||||
else if (!mem.IsStatic && ii.m_scopeFilter != MemberScopes.Instance)
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// name filter
|
|
||||||
if (!string.IsNullOrEmpty(nameFilter) && !mem.NameForFiltering.Contains(nameFilter))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
m_membersFiltered.Add(mem);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (force || lastCount != m_membersFiltered.Count)
|
|
||||||
RefreshDisplay();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void RefreshDisplay()
|
|
||||||
{
|
|
||||||
var members = m_membersFiltered;
|
|
||||||
m_pageHandler.ListCount = members.Count;
|
|
||||||
|
|
||||||
// disable current members
|
|
||||||
for (int i = 0; i < m_displayedMembers.Length; i++)
|
|
||||||
{
|
|
||||||
var mem = m_displayedMembers[i];
|
|
||||||
if (mem != null)
|
|
||||||
mem.Disable();
|
|
||||||
else
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (members.Count < 1)
|
|
||||||
return;
|
|
||||||
|
|
||||||
foreach (var itemIndex in m_pageHandler)
|
|
||||||
{
|
|
||||||
if (itemIndex >= members.Count)
|
|
||||||
break;
|
|
||||||
|
|
||||||
CacheMember member = members[itemIndex];
|
|
||||||
m_displayedMembers[itemIndex - m_pageHandler.StartIndex] = member;
|
|
||||||
member.Enable();
|
|
||||||
}
|
|
||||||
|
|
||||||
m_widthUpdateWanted = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal void UpdateWidths()
|
|
||||||
{
|
|
||||||
float labelWidth = 125;
|
|
||||||
|
|
||||||
foreach (var cache in m_displayedMembers)
|
|
||||||
{
|
|
||||||
if (cache == null)
|
|
||||||
break;
|
|
||||||
|
|
||||||
var width = cache.GetMemberLabelWidth(m_scrollContentRect);
|
|
||||||
|
|
||||||
if (width > labelWidth)
|
|
||||||
labelWidth = width;
|
|
||||||
}
|
|
||||||
|
|
||||||
float valueWidth = m_scrollContentRect.rect.width - labelWidth - 20;
|
|
||||||
|
|
||||||
foreach (var cache in m_displayedMembers)
|
|
||||||
{
|
|
||||||
if (cache == null)
|
|
||||||
break;
|
|
||||||
cache.SetWidths(labelWidth, valueWidth);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#region UI CONSTRUCTION
|
|
||||||
|
|
||||||
internal GameObject m_filterAreaObj;
|
|
||||||
internal GameObject m_updateRowObj;
|
|
||||||
internal GameObject m_memberListObj;
|
|
||||||
|
|
||||||
internal void ConstructUI()
|
|
||||||
{
|
|
||||||
var parent = InspectorManager.Instance.m_inspectorContent;
|
|
||||||
this.Content = UIFactory.CreateVerticalGroup(parent, new Color(0.15f, 0.15f, 0.15f));
|
|
||||||
var mainGroup = Content.GetComponent<VerticalLayoutGroup>();
|
|
||||||
mainGroup.childForceExpandHeight = false;
|
|
||||||
mainGroup.childForceExpandWidth = true;
|
|
||||||
mainGroup.childControlHeight = true;
|
|
||||||
mainGroup.childControlWidth = true;
|
|
||||||
mainGroup.spacing = 5;
|
|
||||||
mainGroup.padding.top = 4;
|
|
||||||
mainGroup.padding.left = 4;
|
|
||||||
mainGroup.padding.right = 4;
|
|
||||||
mainGroup.padding.bottom = 4;
|
|
||||||
|
|
||||||
ConstructTopArea();
|
|
||||||
|
|
||||||
ConstructMemberList();
|
|
||||||
}
|
|
||||||
|
|
||||||
internal void ConstructTopArea()
|
|
||||||
{
|
|
||||||
var nameRowObj = UIFactory.CreateHorizontalGroup(Content, new Color(1, 1, 1, 0));
|
|
||||||
var nameRow = nameRowObj.GetComponent<HorizontalLayoutGroup>();
|
|
||||||
nameRow.childForceExpandWidth = true;
|
|
||||||
nameRow.childForceExpandHeight = true;
|
|
||||||
nameRow.childControlHeight = true;
|
|
||||||
nameRow.childControlWidth = true;
|
|
||||||
nameRow.padding.top = 2;
|
|
||||||
var nameRowLayout = nameRowObj.AddComponent<LayoutElement>();
|
|
||||||
nameRowLayout.minHeight = 25;
|
|
||||||
nameRowLayout.flexibleHeight = 0;
|
|
||||||
nameRowLayout.minWidth = 200;
|
|
||||||
nameRowLayout.flexibleWidth = 5000;
|
|
||||||
|
|
||||||
var typeLabel = UIFactory.CreateLabel(nameRowObj, TextAnchor.MiddleLeft);
|
|
||||||
var typeLabelText = typeLabel.GetComponent<Text>();
|
|
||||||
typeLabelText.text = "Type:";
|
|
||||||
typeLabelText.horizontalOverflow = HorizontalWrapMode.Overflow;
|
|
||||||
var typeLabelTextLayout = typeLabel.AddComponent<LayoutElement>();
|
|
||||||
typeLabelTextLayout.minWidth = 40;
|
|
||||||
typeLabelTextLayout.flexibleWidth = 0;
|
|
||||||
typeLabelTextLayout.minHeight = 25;
|
|
||||||
|
|
||||||
var typeDisplayObj = UIFactory.CreateLabel(nameRowObj, TextAnchor.MiddleLeft);
|
|
||||||
var typeDisplayText = typeDisplayObj.GetComponent<Text>();
|
|
||||||
typeDisplayText.text = UISyntaxHighlight.ParseFullSyntax(m_targetType, true);
|
|
||||||
var typeDisplayLayout = typeDisplayObj.AddComponent<LayoutElement>();
|
|
||||||
typeDisplayLayout.minHeight = 25;
|
|
||||||
typeDisplayLayout.flexibleWidth = 5000;
|
|
||||||
|
|
||||||
// Helper tools
|
|
||||||
|
|
||||||
if (this is InstanceInspector)
|
|
||||||
{
|
|
||||||
(this as InstanceInspector).ConstructInstanceHelpers();
|
|
||||||
}
|
|
||||||
|
|
||||||
ConstructFilterArea();
|
|
||||||
|
|
||||||
ConstructUpdateRow();
|
|
||||||
}
|
|
||||||
|
|
||||||
internal void ConstructFilterArea()
|
|
||||||
{
|
|
||||||
// Filters
|
|
||||||
|
|
||||||
var filterAreaObj = UIFactory.CreateVerticalGroup(Content, new Color(0.1f, 0.1f, 0.1f));
|
|
||||||
var filterLayout = filterAreaObj.AddComponent<LayoutElement>();
|
|
||||||
filterLayout.minHeight = 60;
|
|
||||||
var filterGroup = filterAreaObj.GetComponent<VerticalLayoutGroup>();
|
|
||||||
filterGroup.childForceExpandWidth = true;
|
|
||||||
filterGroup.childForceExpandHeight = true;
|
|
||||||
filterGroup.childControlWidth = true;
|
|
||||||
filterGroup.childControlHeight = true;
|
|
||||||
filterGroup.spacing = 4;
|
|
||||||
filterGroup.padding.left = 4;
|
|
||||||
filterGroup.padding.right = 4;
|
|
||||||
filterGroup.padding.top = 4;
|
|
||||||
filterGroup.padding.bottom = 4;
|
|
||||||
|
|
||||||
m_filterAreaObj = filterAreaObj;
|
|
||||||
|
|
||||||
// name filter
|
|
||||||
|
|
||||||
var nameFilterRowObj = UIFactory.CreateHorizontalGroup(filterAreaObj, new Color(1, 1, 1, 0));
|
|
||||||
var nameFilterGroup = nameFilterRowObj.GetComponent<HorizontalLayoutGroup>();
|
|
||||||
nameFilterGroup.childForceExpandHeight = false;
|
|
||||||
nameFilterGroup.childForceExpandWidth = false;
|
|
||||||
nameFilterGroup.childControlWidth = true;
|
|
||||||
nameFilterGroup.childControlHeight = true;
|
|
||||||
nameFilterGroup.spacing = 5;
|
|
||||||
var nameFilterLayout = nameFilterRowObj.AddComponent<LayoutElement>();
|
|
||||||
nameFilterLayout.minHeight = 25;
|
|
||||||
nameFilterLayout.flexibleHeight = 0;
|
|
||||||
nameFilterLayout.flexibleWidth = 5000;
|
|
||||||
|
|
||||||
var nameLabelObj = UIFactory.CreateLabel(nameFilterRowObj, TextAnchor.MiddleLeft);
|
|
||||||
var nameLabelLayout = nameLabelObj.AddComponent<LayoutElement>();
|
|
||||||
nameLabelLayout.minWidth = 100;
|
|
||||||
nameLabelLayout.minHeight = 25;
|
|
||||||
nameLabelLayout.flexibleWidth = 0;
|
|
||||||
var nameLabelText = nameLabelObj.GetComponent<Text>();
|
|
||||||
nameLabelText.text = "Filter names:";
|
|
||||||
nameLabelText.color = Color.grey;
|
|
||||||
|
|
||||||
var nameInputObj = UIFactory.CreateInputField(nameFilterRowObj, 14, (int)TextAnchor.MiddleLeft, (int)HorizontalWrapMode.Overflow);
|
|
||||||
var nameInputLayout = nameInputObj.AddComponent<LayoutElement>();
|
|
||||||
nameInputLayout.flexibleWidth = 5000;
|
|
||||||
nameInputLayout.minWidth = 100;
|
|
||||||
nameInputLayout.minHeight = 25;
|
|
||||||
var nameInput = nameInputObj.GetComponent<InputField>();
|
|
||||||
nameInput.onValueChanged.AddListener((string val) => { FilterMembers(val); });
|
|
||||||
m_nameFilterText = nameInput.textComponent;
|
|
||||||
|
|
||||||
// membertype filter
|
|
||||||
|
|
||||||
var memberFilterRowObj = UIFactory.CreateHorizontalGroup(filterAreaObj, new Color(1, 1, 1, 0));
|
|
||||||
var memFilterGroup = memberFilterRowObj.GetComponent<HorizontalLayoutGroup>();
|
|
||||||
memFilterGroup.childForceExpandHeight = false;
|
|
||||||
memFilterGroup.childForceExpandWidth = false;
|
|
||||||
memFilterGroup.childControlWidth = true;
|
|
||||||
memFilterGroup.childControlHeight = true;
|
|
||||||
memFilterGroup.spacing = 5;
|
|
||||||
var memFilterLayout = memberFilterRowObj.AddComponent<LayoutElement>();
|
|
||||||
memFilterLayout.minHeight = 25;
|
|
||||||
memFilterLayout.flexibleHeight = 0;
|
|
||||||
memFilterLayout.flexibleWidth = 5000;
|
|
||||||
|
|
||||||
var memLabelObj = UIFactory.CreateLabel(memberFilterRowObj, TextAnchor.MiddleLeft);
|
|
||||||
var memLabelLayout = memLabelObj.AddComponent<LayoutElement>();
|
|
||||||
memLabelLayout.minWidth = 100;
|
|
||||||
memLabelLayout.minHeight = 25;
|
|
||||||
memLabelLayout.flexibleWidth = 0;
|
|
||||||
var memLabelText = memLabelObj.GetComponent<Text>();
|
|
||||||
memLabelText.text = "Filter members:";
|
|
||||||
memLabelText.color = Color.grey;
|
|
||||||
|
|
||||||
AddFilterButton(memberFilterRowObj, MemberTypes.All);
|
|
||||||
AddFilterButton(memberFilterRowObj, MemberTypes.Method);
|
|
||||||
AddFilterButton(memberFilterRowObj, MemberTypes.Property, true);
|
|
||||||
AddFilterButton(memberFilterRowObj, MemberTypes.Field);
|
|
||||||
|
|
||||||
// Instance filters
|
|
||||||
|
|
||||||
if (this is InstanceInspector)
|
|
||||||
{
|
|
||||||
(this as InstanceInspector).ConstructInstanceFilters(filterAreaObj);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void AddFilterButton(GameObject parent, MemberTypes type, bool setEnabled = false)
|
|
||||||
{
|
|
||||||
var btnObj = UIFactory.CreateButton(parent, new Color(0.2f, 0.2f, 0.2f));
|
|
||||||
|
|
||||||
var btnLayout = btnObj.AddComponent<LayoutElement>();
|
|
||||||
btnLayout.minHeight = 25;
|
|
||||||
btnLayout.minWidth = 70;
|
|
||||||
|
|
||||||
var text = btnObj.GetComponentInChildren<Text>();
|
|
||||||
text.text = type.ToString();
|
|
||||||
|
|
||||||
var btn = btnObj.GetComponent<Button>();
|
|
||||||
|
|
||||||
btn.onClick.AddListener(() => { OnMemberFilterClicked(type, btn); });
|
|
||||||
|
|
||||||
var colors = btn.colors;
|
|
||||||
colors.highlightedColor = new Color(0.3f, 0.7f, 0.3f);
|
|
||||||
|
|
||||||
if (setEnabled)
|
|
||||||
{
|
|
||||||
colors.normalColor = new Color(0.2f, 0.6f, 0.2f);
|
|
||||||
m_memberFilter = type;
|
|
||||||
m_lastActiveMemButton = btn;
|
|
||||||
}
|
|
||||||
|
|
||||||
btn.colors = colors;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal void ConstructUpdateRow()
|
|
||||||
{
|
|
||||||
var optionsRowObj = UIFactory.CreateHorizontalGroup(Content, new Color(1, 1, 1, 0));
|
|
||||||
var optionsLayout = optionsRowObj.AddComponent<LayoutElement>();
|
|
||||||
optionsLayout.minHeight = 25;
|
|
||||||
var optionsGroup = optionsRowObj.GetComponent<HorizontalLayoutGroup>();
|
|
||||||
optionsGroup.childForceExpandHeight = true;
|
|
||||||
optionsGroup.childForceExpandWidth = false;
|
|
||||||
optionsGroup.childAlignment = TextAnchor.MiddleLeft;
|
|
||||||
optionsGroup.spacing = 10;
|
|
||||||
|
|
||||||
m_updateRowObj = optionsRowObj;
|
|
||||||
|
|
||||||
// update button
|
|
||||||
|
|
||||||
var updateButtonObj = UIFactory.CreateButton(optionsRowObj, new Color(0.2f, 0.2f, 0.2f));
|
|
||||||
var updateBtnLayout = updateButtonObj.AddComponent<LayoutElement>();
|
|
||||||
updateBtnLayout.minWidth = 110;
|
|
||||||
updateBtnLayout.flexibleWidth = 0;
|
|
||||||
var updateText = updateButtonObj.GetComponentInChildren<Text>();
|
|
||||||
updateText.text = "Update Values";
|
|
||||||
var updateBtn = updateButtonObj.GetComponent<Button>();
|
|
||||||
updateBtn.onClick.AddListener(() =>
|
|
||||||
{
|
|
||||||
bool orig = m_autoUpdate;
|
|
||||||
m_autoUpdate = true;
|
|
||||||
Update();
|
|
||||||
if (!orig) m_autoUpdate = orig;
|
|
||||||
});
|
|
||||||
|
|
||||||
// auto update
|
|
||||||
|
|
||||||
var autoUpdateObj = UIFactory.CreateToggle(optionsRowObj, out Toggle autoUpdateToggle, out Text autoUpdateText);
|
|
||||||
var autoUpdateLayout = autoUpdateObj.AddComponent<LayoutElement>();
|
|
||||||
autoUpdateLayout.minWidth = 150;
|
|
||||||
autoUpdateLayout.minHeight = 25;
|
|
||||||
autoUpdateText.text = "Auto-update?";
|
|
||||||
autoUpdateToggle.isOn = false;
|
|
||||||
autoUpdateToggle.onValueChanged.AddListener((bool val) => { m_autoUpdate = val; });
|
|
||||||
}
|
|
||||||
|
|
||||||
internal void ConstructMemberList()
|
|
||||||
{
|
|
||||||
var scrollobj = UIFactory.CreateScrollView(Content, out m_scrollContent, out m_sliderScroller, new Color(0.05f, 0.05f, 0.05f));
|
|
||||||
|
|
||||||
m_memberListObj = scrollobj;
|
|
||||||
m_scrollContentRect = m_scrollContent.GetComponent<RectTransform>();
|
|
||||||
|
|
||||||
var scrollGroup = m_scrollContent.GetComponent<VerticalLayoutGroup>();
|
|
||||||
scrollGroup.spacing = 3;
|
|
||||||
scrollGroup.padding.left = 0;
|
|
||||||
scrollGroup.padding.right = 0;
|
|
||||||
scrollGroup.childForceExpandHeight = true;
|
|
||||||
|
|
||||||
m_pageHandler = new PageHandler(m_sliderScroller);
|
|
||||||
m_pageHandler.ConstructUI(Content);
|
|
||||||
m_pageHandler.OnPageChanged += OnPageTurned;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion // end UI
|
|
||||||
|
|
||||||
#endregion // end instance
|
|
||||||
}
|
|
||||||
}
|
|
@ -8,7 +8,7 @@ using HarmonyLib;
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.SceneManagement;
|
using UnityEngine.SceneManagement;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using UnityExplorer.UI.Modules;
|
using UnityExplorer.UI.Main;
|
||||||
#if CPP
|
#if CPP
|
||||||
using UnhollowerRuntimeLib;
|
using UnhollowerRuntimeLib;
|
||||||
using BepInEx.IL2CPP;
|
using BepInEx.IL2CPP;
|
||||||
|
@ -1,47 +0,0 @@
|
|||||||
#if CPP
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using UnityEngine;
|
|
||||||
using UnityEngine.Events;
|
|
||||||
using UnityEngine.SceneManagement;
|
|
||||||
using UnityExplorer.Helpers;
|
|
||||||
|
|
||||||
namespace UnityExplorer.Runtime.Il2Cpp
|
|
||||||
{
|
|
||||||
public class Il2CppProvider : RuntimeProvider
|
|
||||||
{
|
|
||||||
public override void Initialize()
|
|
||||||
{
|
|
||||||
ReflectionHelpers.TryLoadGameModules();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void SetupEvents()
|
|
||||||
{
|
|
||||||
Application.add_logMessageReceived(
|
|
||||||
new Action<string, string, LogType>(ExplorerCore.Instance.OnUnityLog));
|
|
||||||
|
|
||||||
//SceneManager.add_sceneLoaded(
|
|
||||||
// new Action<Scene, LoadSceneMode>(ExplorerCore.Instance.OnSceneLoaded1));
|
|
||||||
|
|
||||||
//SceneManager.add_activeSceneChanged(
|
|
||||||
// new Action<Scene, Scene>(ExplorerCore.Instance.OnSceneLoaded2));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class UnityEventExtensions
|
|
||||||
{
|
|
||||||
public static void AddListener(this UnityEvent action, Action listener)
|
|
||||||
{
|
|
||||||
action.AddListener(listener);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void AddListener<T>(this UnityEvent<T> action, Action<T> listener)
|
|
||||||
{
|
|
||||||
action.AddListener(listener);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,26 +0,0 @@
|
|||||||
#if MONO
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using UnityEngine;
|
|
||||||
using UnityEngine.SceneManagement;
|
|
||||||
|
|
||||||
namespace UnityExplorer.Runtime.Mono
|
|
||||||
{
|
|
||||||
public class MonoProvider : RuntimeProvider
|
|
||||||
{
|
|
||||||
public override void Initialize()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void SetupEvents()
|
|
||||||
{
|
|
||||||
Application.logMessageReceived += ExplorerCore.Instance.OnUnityLog;
|
|
||||||
//SceneManager.sceneLoaded += ExplorerCore.Instance.OnSceneLoaded1;
|
|
||||||
//SceneManager.activeSceneChanged += ExplorerCore.Instance.OnSceneLoaded2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,294 +0,0 @@
|
|||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using UnityExplorer.UI;
|
|
||||||
using UnityEngine;
|
|
||||||
using System;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
using System.Text;
|
|
||||||
using UnityExplorer.Unstrip;
|
|
||||||
#if CPP
|
|
||||||
using UnhollowerBaseLib;
|
|
||||||
using UnityExplorer.Helpers;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace UnityExplorer.Tests
|
|
||||||
{
|
|
||||||
internal enum TestByteEnum : byte
|
|
||||||
{
|
|
||||||
One,
|
|
||||||
Two,
|
|
||||||
Three,
|
|
||||||
TwoFiftyFive = 255,
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class StaticTestClass
|
|
||||||
{
|
|
||||||
public static int StaticProperty => 5;
|
|
||||||
public static int StaticField = 69;
|
|
||||||
public static List<string> StaticList = new List<string>
|
|
||||||
{
|
|
||||||
"one",
|
|
||||||
"two",
|
|
||||||
"three",
|
|
||||||
};
|
|
||||||
public static void StaticMethod() { }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class TestClass
|
|
||||||
{
|
|
||||||
internal static TestByteEnum testingByte = TestByteEnum.One;
|
|
||||||
|
|
||||||
public string AAALongString = @"1
|
|
||||||
2
|
|
||||||
3
|
|
||||||
4
|
|
||||||
5";
|
|
||||||
|
|
||||||
public Vector2 AATestVector2 = new Vector2(1, 2);
|
|
||||||
public Vector3 AATestVector3 = new Vector3(1, 2, 3);
|
|
||||||
public Vector4 AATestVector4 = new Vector4(1, 2, 3, 4);
|
|
||||||
public Rect AATestRect = new Rect(1, 2, 3, 4);
|
|
||||||
public Color AATestColor = new Color(0.1f, 0.2f, 0.3f, 0.4f);
|
|
||||||
|
|
||||||
public bool ATestBoolMethod() => false;
|
|
||||||
|
|
||||||
public bool this[int index]
|
|
||||||
{
|
|
||||||
get => index % 2 == 0;
|
|
||||||
set => m_thisBool = value;
|
|
||||||
}
|
|
||||||
internal bool m_thisBool;
|
|
||||||
|
|
||||||
static int testInt;
|
|
||||||
public static List<string> ExceptionList
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
testInt++;
|
|
||||||
if (testInt % 2 == 0)
|
|
||||||
throw new Exception("its even");
|
|
||||||
else
|
|
||||||
return new List<string> { "one" };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool abool;
|
|
||||||
public static bool ATestExceptionBool
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
abool = !abool;
|
|
||||||
if (!abool)
|
|
||||||
throw new Exception("false");
|
|
||||||
else
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string ExceptionString => throw new NotImplementedException();
|
|
||||||
|
|
||||||
public static string ANullString = null;
|
|
||||||
public static float ATestFloat = 420.69f;
|
|
||||||
public static int ATestInt = -1;
|
|
||||||
public static string ATestString = "hello world";
|
|
||||||
public static uint ATestUInt = 1u;
|
|
||||||
public static byte ATestByte = 255;
|
|
||||||
public static ulong AReadonlyUlong = 82934UL;
|
|
||||||
|
|
||||||
public static TestClass Instance => m_instance ?? (m_instance = new TestClass());
|
|
||||||
private static TestClass m_instance;
|
|
||||||
|
|
||||||
public object AmbigObject;
|
|
||||||
|
|
||||||
public List<List<List<string>>> ANestedNestedList = new List<List<List<string>>>
|
|
||||||
{
|
|
||||||
new List<List<string>>
|
|
||||||
{
|
|
||||||
new List<string>
|
|
||||||
{
|
|
||||||
"one",
|
|
||||||
"two",
|
|
||||||
},
|
|
||||||
new List<string>
|
|
||||||
{
|
|
||||||
"three",
|
|
||||||
"four"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
new List<List<string>>
|
|
||||||
{
|
|
||||||
new List<string>
|
|
||||||
{
|
|
||||||
"five",
|
|
||||||
"six"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
public static bool SetOnlyProperty
|
|
||||||
{
|
|
||||||
set => m_setOnlyProperty = value;
|
|
||||||
}
|
|
||||||
private static bool m_setOnlyProperty;
|
|
||||||
public static bool ReadSetOnlyProperty => m_setOnlyProperty;
|
|
||||||
|
|
||||||
public Texture2D TestTexture;
|
|
||||||
public static Sprite TestSprite;
|
|
||||||
|
|
||||||
#if CPP
|
|
||||||
public static Il2CppSystem.Collections.Generic.HashSet<string> CppHashSetTest;
|
|
||||||
public static Il2CppSystem.Collections.Generic.List<string> CppStringTest;
|
|
||||||
public static Il2CppSystem.Collections.IList CppIList;
|
|
||||||
//public static Il2CppSystem.Collections.Generic.Dictionary<string, string> CppDictTest;
|
|
||||||
//public static Il2CppSystem.Collections.Generic.Dictionary<int, float> CppDictTest2;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
public TestClass()
|
|
||||||
{
|
|
||||||
int a = 0;
|
|
||||||
foreach (var list in ANestedNestedList)
|
|
||||||
{
|
|
||||||
foreach (var list2 in list)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < 33; i++)
|
|
||||||
list2.Add(a++.ToString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#if CPP
|
|
||||||
TextureSpriteTest();
|
|
||||||
|
|
||||||
CppHashSetTest = new Il2CppSystem.Collections.Generic.HashSet<string>();
|
|
||||||
CppHashSetTest.Add("1");
|
|
||||||
CppHashSetTest.Add("2");
|
|
||||||
CppHashSetTest.Add("3");
|
|
||||||
|
|
||||||
CppStringTest = new Il2CppSystem.Collections.Generic.List<string>();
|
|
||||||
CppStringTest.Add("1");
|
|
||||||
CppStringTest.Add("2");
|
|
||||||
|
|
||||||
//CppDictTest = new Il2CppSystem.Collections.Generic.Dictionary<string, string>();
|
|
||||||
//CppDictTest.Add("key1", "value1");
|
|
||||||
//CppDictTest.Add("key2", "value2");
|
|
||||||
//CppDictTest.Add("key3", "value3");
|
|
||||||
|
|
||||||
//CppDictTest2 = new Il2CppSystem.Collections.Generic.Dictionary<int, float>();
|
|
||||||
//CppDictTest2.Add(0, 0.5f);
|
|
||||||
//CppDictTest2.Add(1, 0.5f);
|
|
||||||
//CppDictTest2.Add(2, 0.5f);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
private void TextureSpriteTest()
|
|
||||||
{
|
|
||||||
TestTexture = new Texture2D(32, 32, TextureFormat.ARGB32, false)
|
|
||||||
{
|
|
||||||
name = "TestTexture"
|
|
||||||
};
|
|
||||||
TestSprite = ImageConversionUnstrip.CreateSprite(TestTexture);
|
|
||||||
|
|
||||||
GameObject.DontDestroyOnLoad(TestTexture);
|
|
||||||
GameObject.DontDestroyOnLoad(TestSprite);
|
|
||||||
|
|
||||||
// test loading a tex from file
|
|
||||||
if (System.IO.File.Exists(@"D:\Downloads\test.png"))
|
|
||||||
{
|
|
||||||
var dataToLoad = System.IO.File.ReadAllBytes(@"D:\Downloads\test.png");
|
|
||||||
ExplorerCore.Log($"Tex load success: {TestTexture.LoadImage(dataToLoad, false)}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//public static string TestRefInOutGeneric<T>(ref string arg0, in int arg1, out string arg2) where T : Component
|
|
||||||
//{
|
|
||||||
// arg2 = "this is arg2";
|
|
||||||
|
|
||||||
// return $"T: '{typeof(T).FullName}', ref arg0: '{arg0}', in arg1: '{arg1}', out arg2: '{arg2}'";
|
|
||||||
//}
|
|
||||||
|
|
||||||
// test a non-generic dictionary
|
|
||||||
|
|
||||||
public Hashtable TestNonGenericDict()
|
|
||||||
{
|
|
||||||
return new Hashtable
|
|
||||||
{
|
|
||||||
{ "One", 1 },
|
|
||||||
{ "Two", 2 },
|
|
||||||
{ "Three", 3 },
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// test HashSets
|
|
||||||
|
|
||||||
public static HashSet<string> HashSetTest = new HashSet<string>
|
|
||||||
{
|
|
||||||
"One",
|
|
||||||
"Two",
|
|
||||||
"Three"
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// Test indexed parameter
|
|
||||||
|
|
||||||
public string this[int arg0, string arg1]
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return $"arg0: {arg0}, arg1: {arg1}";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test basic list
|
|
||||||
|
|
||||||
public static List<string> TestList = new List<string>
|
|
||||||
{
|
|
||||||
"1",
|
|
||||||
"2",
|
|
||||||
"3",
|
|
||||||
"etc..."
|
|
||||||
};
|
|
||||||
|
|
||||||
// Test a nested dictionary
|
|
||||||
|
|
||||||
public static Dictionary<int, Dictionary<string, int>> NestedDictionary = new Dictionary<int, Dictionary<string, int>>
|
|
||||||
{
|
|
||||||
{
|
|
||||||
1,
|
|
||||||
new Dictionary<string, int>
|
|
||||||
{
|
|
||||||
{
|
|
||||||
"Sub 1", 123
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Sub 2", 456
|
|
||||||
},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
2,
|
|
||||||
new Dictionary<string, int>
|
|
||||||
{
|
|
||||||
{
|
|
||||||
"Sub 3", 789
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Sub 4", 000
|
|
||||||
},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
// Test a basic method
|
|
||||||
|
|
||||||
public static Color TestMethod(float r, float g, float b, float 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
27
src/UI/Main/BaseMenuPage.cs
Normal file
27
src/UI/Main/BaseMenuPage.cs
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.UI;
|
||||||
|
|
||||||
|
namespace UnityExplorer.UI.Main
|
||||||
|
{
|
||||||
|
public abstract class BaseMenuPage
|
||||||
|
{
|
||||||
|
public abstract string Name { get; }
|
||||||
|
|
||||||
|
public GameObject Content;
|
||||||
|
public Button RefNavbarButton { get; set; }
|
||||||
|
|
||||||
|
public bool Enabled
|
||||||
|
{
|
||||||
|
get => Content?.activeSelf ?? false;
|
||||||
|
set => Content?.SetActive(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public abstract void Init();
|
||||||
|
public abstract void Update();
|
||||||
|
}
|
||||||
|
}
|
@ -4,11 +4,13 @@ using System.Linq;
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.EventSystems;
|
using UnityEngine.EventSystems;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using UnityExplorer.Helpers;
|
using UnityExplorer.Core.CSharp;
|
||||||
|
using UnityExplorer.Core.Unity;
|
||||||
using UnityExplorer.UI;
|
using UnityExplorer.UI;
|
||||||
using UnityExplorer.UI.Modules;
|
using UnityExplorer.UI.CSConsole;
|
||||||
|
using UnityExplorer.UI.Main;
|
||||||
|
|
||||||
namespace UnityExplorer.CSConsole
|
namespace UnityExplorer.UI.Main.CSConsole
|
||||||
{
|
{
|
||||||
public class AutoCompleter
|
public class AutoCompleter
|
||||||
{
|
{
|
||||||
@ -45,7 +47,7 @@ namespace UnityExplorer.CSConsole
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!CodeEditor.EnableAutocompletes)
|
if (!CSharpConsole.EnableAutocompletes)
|
||||||
{
|
{
|
||||||
if (m_mainObj.activeSelf)
|
if (m_mainObj.activeSelf)
|
||||||
{
|
{
|
||||||
@ -132,7 +134,7 @@ namespace UnityExplorer.CSConsole
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var editor = CSConsolePage.Instance.m_codeEditor;
|
var editor = CSharpConsole.Instance;
|
||||||
|
|
||||||
if (!editor.InputField.isFocused)
|
if (!editor.InputField.isFocused)
|
||||||
return;
|
return;
|
||||||
@ -164,7 +166,7 @@ namespace UnityExplorer.CSConsole
|
|||||||
|
|
||||||
public static void CheckAutocomplete()
|
public static void CheckAutocomplete()
|
||||||
{
|
{
|
||||||
var m_codeEditor = CSConsolePage.Instance.m_codeEditor;
|
var m_codeEditor = CSharpConsole.Instance;
|
||||||
string input = m_codeEditor.InputField.text;
|
string input = m_codeEditor.InputField.text;
|
||||||
int caretIndex = m_codeEditor.InputField.caretPosition;
|
int caretIndex = m_codeEditor.InputField.caretPosition;
|
||||||
|
|
||||||
@ -192,9 +194,9 @@ namespace UnityExplorer.CSConsole
|
|||||||
|
|
||||||
public static void ClearAutocompletes()
|
public static void ClearAutocompletes()
|
||||||
{
|
{
|
||||||
if (CodeEditor.AutoCompletes.Any())
|
if (CSharpConsole.AutoCompletes.Any())
|
||||||
{
|
{
|
||||||
CodeEditor.AutoCompletes.Clear();
|
CSharpConsole.AutoCompletes.Clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -203,8 +205,8 @@ namespace UnityExplorer.CSConsole
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
// Credit ManylMarco
|
// Credit ManylMarco
|
||||||
CodeEditor.AutoCompletes.Clear();
|
CSharpConsole.AutoCompletes.Clear();
|
||||||
string[] completions = CSConsolePage.Instance.m_evaluator.GetCompletions(input, out string prefix);
|
string[] completions = CSharpConsole.Instance.m_evaluator.GetCompletions(input, out string prefix);
|
||||||
if (completions != null)
|
if (completions != null)
|
||||||
{
|
{
|
||||||
if (prefix == null)
|
if (prefix == null)
|
||||||
@ -212,7 +214,7 @@ namespace UnityExplorer.CSConsole
|
|||||||
prefix = input;
|
prefix = input;
|
||||||
}
|
}
|
||||||
|
|
||||||
CodeEditor.AutoCompletes.AddRange(completions
|
CSharpConsole.AutoCompletes.AddRange(completions
|
||||||
.Where(x => !string.IsNullOrEmpty(x))
|
.Where(x => !string.IsNullOrEmpty(x))
|
||||||
.Select(x => new Suggestion(x, prefix, Suggestion.Contexts.Other))
|
.Select(x => new Suggestion(x, prefix, Suggestion.Contexts.Other))
|
||||||
);
|
);
|
||||||
@ -231,7 +233,7 @@ namespace UnityExplorer.CSConsole
|
|||||||
x.Substring(0, trimmed.Length),
|
x.Substring(0, trimmed.Length),
|
||||||
Suggestion.Contexts.Namespace));
|
Suggestion.Contexts.Namespace));
|
||||||
|
|
||||||
CodeEditor.AutoCompletes.AddRange(namespaces);
|
CSharpConsole.AutoCompletes.AddRange(namespaces);
|
||||||
|
|
||||||
IEnumerable<Suggestion> keywords = Suggestion.Keywords
|
IEnumerable<Suggestion> keywords = Suggestion.Keywords
|
||||||
.Where(x => x.StartsWith(trimmed) && x.Length > trimmed.Length)
|
.Where(x => x.StartsWith(trimmed) && x.Length > trimmed.Length)
|
||||||
@ -240,7 +242,7 @@ namespace UnityExplorer.CSConsole
|
|||||||
x.Substring(0, trimmed.Length),
|
x.Substring(0, trimmed.Length),
|
||||||
Suggestion.Contexts.Keyword));
|
Suggestion.Contexts.Keyword));
|
||||||
|
|
||||||
CodeEditor.AutoCompletes.AddRange(keywords);
|
CSharpConsole.AutoCompletes.AddRange(keywords);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@ -301,7 +303,7 @@ namespace UnityExplorer.CSConsole
|
|||||||
|
|
||||||
void UseAutocompleteButton()
|
void UseAutocompleteButton()
|
||||||
{
|
{
|
||||||
CSConsolePage.Instance.m_codeEditor.UseAutocomplete(hiddenText.text);
|
CSharpConsole.Instance.UseAutocomplete(hiddenText.text);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_suggestionButtons.Add(buttonObj);
|
m_suggestionButtons.Add(buttonObj);
|
@ -1,9 +1,9 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityExplorer.CSConsole.Lexer;
|
using UnityExplorer.UI.CSConsole.Lexer;
|
||||||
|
|
||||||
namespace UnityExplorer.CSConsole
|
namespace UnityExplorer.UI.CSConsole
|
||||||
{
|
{
|
||||||
public struct LexerMatchInfo
|
public struct LexerMatchInfo
|
||||||
{
|
{
|
||||||
@ -18,7 +18,7 @@ namespace UnityExplorer.CSConsole
|
|||||||
End,
|
End,
|
||||||
};
|
};
|
||||||
|
|
||||||
public class CSharpLexer
|
public class CSLexerHighlighter
|
||||||
{
|
{
|
||||||
private string inputString;
|
private string inputString;
|
||||||
private readonly Matcher[] matchers;
|
private readonly Matcher[] matchers;
|
||||||
@ -66,7 +66,7 @@ namespace UnityExplorer.CSConsole
|
|||||||
|
|
||||||
// ~~~~~~~ ctor ~~~~~~~
|
// ~~~~~~~ ctor ~~~~~~~
|
||||||
|
|
||||||
public CSharpLexer()
|
public CSLexerHighlighter()
|
||||||
{
|
{
|
||||||
startDelimiters = new HashSet<char>(delimiters);
|
startDelimiters = new HashSet<char>(delimiters);
|
||||||
endDelimiters = new HashSet<char>(delimiters);
|
endDelimiters = new HashSet<char>(delimiters);
|
@ -1,24 +1,128 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Reflection;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using UnityExplorer.Input;
|
using UnityExplorer.Core.CSharp;
|
||||||
using UnityExplorer.CSConsole.Lexer;
|
using UnityExplorer.UI.CSConsole;
|
||||||
|
using System.Linq;
|
||||||
|
using UnityExplorer.Core.Input;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.EventSystems;
|
using UnityEngine.EventSystems;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using UnityExplorer.UI;
|
using UnityExplorer.UI.Reusable;
|
||||||
using UnityExplorer.UI.Modules;
|
using UnityExplorer.UI.Main.CSConsole;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Reflection;
|
|
||||||
using UnityExplorer.UI.Shared;
|
|
||||||
using UnityExplorer.Helpers;
|
|
||||||
|
|
||||||
namespace UnityExplorer.CSConsole
|
namespace UnityExplorer.UI.Main
|
||||||
{
|
{
|
||||||
// Handles most of the UI side of the C# console, including syntax highlighting.
|
public class CSharpConsole : BaseMenuPage
|
||||||
|
|
||||||
public class CodeEditor
|
|
||||||
{
|
{
|
||||||
|
public override string Name => "C# Console";
|
||||||
|
|
||||||
|
public static CSharpConsole Instance { get; private set; }
|
||||||
|
|
||||||
|
//public UI.CSConsole.CSharpConsole m_codeEditor;
|
||||||
|
public ScriptEvaluator m_evaluator;
|
||||||
|
|
||||||
|
public static List<string> UsingDirectives;
|
||||||
|
|
||||||
|
public static readonly string[] DefaultUsing = new string[]
|
||||||
|
{
|
||||||
|
"System",
|
||||||
|
"System.Linq",
|
||||||
|
"System.Collections",
|
||||||
|
"System.Collections.Generic",
|
||||||
|
"System.Reflection",
|
||||||
|
"UnityEngine",
|
||||||
|
#if CPP
|
||||||
|
"UnhollowerBaseLib",
|
||||||
|
"UnhollowerRuntimeLib",
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
public override void Init()
|
||||||
|
{
|
||||||
|
Instance = this;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
//m_codeEditor = new UI.CSConsole.CSharpConsole();
|
||||||
|
InitConsole();
|
||||||
|
|
||||||
|
AutoCompleter.Init();
|
||||||
|
|
||||||
|
ResetConsole();
|
||||||
|
|
||||||
|
// Make sure compiler is supported on this platform
|
||||||
|
m_evaluator.Compile("");
|
||||||
|
|
||||||
|
foreach (string use in DefaultUsing)
|
||||||
|
{
|
||||||
|
AddUsing(use);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
ExplorerCore.LogWarning($"Error setting up console!\r\nMessage: {e.Message}");
|
||||||
|
MainMenu.Instance.Pages.RemoveAll(it => it is CSharpConsole);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Update()
|
||||||
|
{
|
||||||
|
UpdateConsole();
|
||||||
|
AutoCompleter.Update();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddUsing(string asm)
|
||||||
|
{
|
||||||
|
if (!UsingDirectives.Contains(asm))
|
||||||
|
{
|
||||||
|
Evaluate($"using {asm};", true);
|
||||||
|
UsingDirectives.Add(asm);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Evaluate(string code, bool suppressWarning = false)
|
||||||
|
{
|
||||||
|
m_evaluator.Compile(code, out Mono.CSharp.CompiledMethod compiled);
|
||||||
|
|
||||||
|
if (compiled == null)
|
||||||
|
{
|
||||||
|
if (!suppressWarning)
|
||||||
|
ExplorerCore.LogWarning("Unable to compile the code!");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
object ret = VoidType.Value;
|
||||||
|
compiled.Invoke(ref ret);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
if (!suppressWarning)
|
||||||
|
ExplorerCore.LogWarning($"Exception executing code: {e.GetType()}, {e.Message}\r\n{e.StackTrace}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ResetConsole()
|
||||||
|
{
|
||||||
|
if (m_evaluator != null)
|
||||||
|
{
|
||||||
|
m_evaluator.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_evaluator = new ScriptEvaluator(new StringWriter(new StringBuilder())) { InteractiveBaseClass = typeof(ScriptInteraction) };
|
||||||
|
|
||||||
|
UsingDirectives = new List<string>();
|
||||||
|
}
|
||||||
|
|
||||||
|
// =================================================================================================
|
||||||
|
|
||||||
|
// UI stuff
|
||||||
|
|
||||||
public InputField InputField { get; internal set; }
|
public InputField InputField { get; internal set; }
|
||||||
public Text InputText { get; internal set; }
|
public Text InputText { get; internal set; }
|
||||||
public int CurrentIndent { get; private set; }
|
public int CurrentIndent { get; private set; }
|
||||||
@ -31,8 +135,7 @@ namespace UnityExplorer.CSConsole
|
|||||||
public string HighlightedText => inputHighlightText.text;
|
public string HighlightedText => inputHighlightText.text;
|
||||||
private Text inputHighlightText;
|
private Text inputHighlightText;
|
||||||
|
|
||||||
private readonly CSharpLexer highlightLexer;
|
private CSLexerHighlighter highlightLexer;
|
||||||
//private readonly StringBuilder sbHighlight;
|
|
||||||
|
|
||||||
internal int m_lastCaretPos;
|
internal int m_lastCaretPos;
|
||||||
internal int m_fixCaretPos;
|
internal int m_fixCaretPos;
|
||||||
@ -66,9 +169,9 @@ The following helper methods are available:
|
|||||||
* <color=#add490>Reset()</color> resets all using directives and variables
|
* <color=#add490>Reset()</color> resets all using directives and variables
|
||||||
";
|
";
|
||||||
|
|
||||||
public CodeEditor()
|
public void InitConsole()
|
||||||
{
|
{
|
||||||
highlightLexer = new CSharpLexer();
|
highlightLexer = new CSLexerHighlighter();
|
||||||
|
|
||||||
ConstructUI();
|
ConstructUI();
|
||||||
|
|
||||||
@ -81,7 +184,7 @@ The following helper methods are available:
|
|||||||
&& InputManager.GetKeyDown(KeyCode.V);
|
&& InputManager.GetKeyDown(KeyCode.V);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Update()
|
public void UpdateConsole()
|
||||||
{
|
{
|
||||||
if (s_copyPasteBuffer != null)
|
if (s_copyPasteBuffer != null)
|
||||||
{
|
{
|
||||||
@ -101,7 +204,7 @@ The following helper methods are available:
|
|||||||
var text = InputField.text.Trim();
|
var text = InputField.text.Trim();
|
||||||
if (!string.IsNullOrEmpty(text))
|
if (!string.IsNullOrEmpty(text))
|
||||||
{
|
{
|
||||||
CSConsolePage.Instance.Evaluate(text);
|
Evaluate(text);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -121,7 +224,7 @@ The following helper methods are available:
|
|||||||
if (!m_fixwanted)
|
if (!m_fixwanted)
|
||||||
{
|
{
|
||||||
EventSystem.current.SetSelectedGameObject(InputField.gameObject, null);
|
EventSystem.current.SetSelectedGameObject(InputField.gameObject, null);
|
||||||
m_fixwanted = true;
|
m_fixwanted = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -209,9 +312,9 @@ The following helper methods are available:
|
|||||||
|
|
||||||
if (character == '"')
|
if (character == '"')
|
||||||
stringState = !stringState;
|
stringState = !stringState;
|
||||||
else if (!stringState && character == CSharpLexer.indentOpen)
|
else if (!stringState && character == CSLexerHighlighter.indentOpen)
|
||||||
CurrentIndent++;
|
CurrentIndent++;
|
||||||
else if (!stringState && character == CSharpLexer.indentClose)
|
else if (!stringState && character == CSLexerHighlighter.indentClose)
|
||||||
CurrentIndent--;
|
CurrentIndent--;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -278,8 +381,8 @@ The following helper methods are available:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// check if should add auto-close }
|
// check if should add auto-close }
|
||||||
int numOpen = InputField.text.Where(x => x == CSharpLexer.indentOpen).Count();
|
int numOpen = InputField.text.Where(x => x == CSLexerHighlighter.indentOpen).Count();
|
||||||
int numClose = InputField.text.Where(x => x == CSharpLexer.indentClose).Count();
|
int numClose = InputField.text.Where(x => x == CSLexerHighlighter.indentClose).Count();
|
||||||
|
|
||||||
if (numOpen > numClose)
|
if (numOpen > numClose)
|
||||||
{
|
{
|
||||||
@ -324,13 +427,13 @@ The following helper methods are available:
|
|||||||
|
|
||||||
public void ConstructUI()
|
public void ConstructUI()
|
||||||
{
|
{
|
||||||
CSConsolePage.Instance.Content = UIFactory.CreateUIObject("C# Console", MainMenu.Instance.PageViewport);
|
Content = UIFactory.CreateUIObject("C# Console", MainMenu.Instance.PageViewport);
|
||||||
|
|
||||||
var mainLayout = CSConsolePage.Instance.Content.AddComponent<LayoutElement>();
|
var mainLayout = Content.AddComponent<LayoutElement>();
|
||||||
mainLayout.preferredHeight = 500;
|
mainLayout.preferredHeight = 500;
|
||||||
mainLayout.flexibleHeight = 9000;
|
mainLayout.flexibleHeight = 9000;
|
||||||
|
|
||||||
var mainGroup = CSConsolePage.Instance.Content.AddComponent<VerticalLayoutGroup>();
|
var mainGroup = Content.AddComponent<VerticalLayoutGroup>();
|
||||||
mainGroup.childControlHeight = true;
|
mainGroup.childControlHeight = true;
|
||||||
mainGroup.childControlWidth = true;
|
mainGroup.childControlWidth = true;
|
||||||
mainGroup.childForceExpandHeight = true;
|
mainGroup.childForceExpandHeight = true;
|
||||||
@ -340,7 +443,7 @@ The following helper methods are available:
|
|||||||
|
|
||||||
// Main group object
|
// Main group object
|
||||||
|
|
||||||
var topBarObj = UIFactory.CreateHorizontalGroup(CSConsolePage.Instance.Content);
|
var topBarObj = UIFactory.CreateHorizontalGroup(Content);
|
||||||
LayoutElement topBarLayout = topBarObj.AddComponent<LayoutElement>();
|
LayoutElement topBarLayout = topBarObj.AddComponent<LayoutElement>();
|
||||||
topBarLayout.minHeight = 50;
|
topBarLayout.minHeight = 50;
|
||||||
topBarLayout.flexibleHeight = 0;
|
topBarLayout.flexibleHeight = 0;
|
||||||
@ -418,7 +521,7 @@ The following helper methods are available:
|
|||||||
|
|
||||||
int fontSize = 16;
|
int fontSize = 16;
|
||||||
|
|
||||||
var inputObj = UIFactory.CreateSrollInputField(CSConsolePage.Instance.Content, out InputFieldScroller consoleScroll, fontSize);
|
var inputObj = UIFactory.CreateSrollInputField(Content, out InputFieldScroller consoleScroll, fontSize);
|
||||||
|
|
||||||
var inputField = consoleScroll.inputField;
|
var inputField = consoleScroll.inputField;
|
||||||
|
|
||||||
@ -447,7 +550,7 @@ The following helper methods are available:
|
|||||||
|
|
||||||
#region COMPILE BUTTON
|
#region COMPILE BUTTON
|
||||||
|
|
||||||
var compileBtnObj = UIFactory.CreateButton(CSConsolePage.Instance.Content);
|
var compileBtnObj = UIFactory.CreateButton(Content);
|
||||||
var compileBtnLayout = compileBtnObj.AddComponent<LayoutElement>();
|
var compileBtnLayout = compileBtnObj.AddComponent<LayoutElement>();
|
||||||
compileBtnLayout.preferredWidth = 80;
|
compileBtnLayout.preferredWidth = 80;
|
||||||
compileBtnLayout.flexibleWidth = 0;
|
compileBtnLayout.flexibleWidth = 0;
|
||||||
@ -468,7 +571,7 @@ The following helper methods are available:
|
|||||||
{
|
{
|
||||||
if (!string.IsNullOrEmpty(inputField.text))
|
if (!string.IsNullOrEmpty(inputField.text))
|
||||||
{
|
{
|
||||||
CSConsolePage.Instance.Evaluate(inputField.text.Trim());
|
Evaluate(inputField.text.Trim());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -493,5 +596,15 @@ The following helper methods are available:
|
|||||||
this.InputText = mainTextInput;
|
this.InputText = mainTextInput;
|
||||||
this.inputHighlightText = highlightTextInput;
|
this.inputHighlightText = highlightTextInput;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// ================================================================================================
|
||||||
|
|
||||||
|
private class VoidType
|
||||||
|
{
|
||||||
|
public static readonly VoidType Value = new VoidType();
|
||||||
|
private VoidType() { }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,7 +1,7 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace UnityExplorer.CSConsole.Lexer
|
namespace UnityExplorer.UI.CSConsole.Lexer
|
||||||
{
|
{
|
||||||
public class CommentMatch : Matcher
|
public class CommentMatch : Matcher
|
||||||
{
|
{
|
||||||
@ -12,9 +12,9 @@ namespace UnityExplorer.CSConsole.Lexer
|
|||||||
public override Color HighlightColor => new Color(0.34f, 0.65f, 0.29f, 1.0f);
|
public override Color HighlightColor => new Color(0.34f, 0.65f, 0.29f, 1.0f);
|
||||||
public override IEnumerable<char> StartChars => new char[] { lineCommentStart[0], blockCommentStart[0] };
|
public override IEnumerable<char> StartChars => new char[] { lineCommentStart[0], blockCommentStart[0] };
|
||||||
public override IEnumerable<char> EndChars => new char[] { blockCommentEnd[0] };
|
public override IEnumerable<char> EndChars => new char[] { blockCommentEnd[0] };
|
||||||
public override bool IsImplicitMatch(CSharpLexer lexer) => IsMatch(lexer, lineCommentStart) || IsMatch(lexer, blockCommentStart);
|
public override bool IsImplicitMatch(CSLexerHighlighter lexer) => IsMatch(lexer, lineCommentStart) || IsMatch(lexer, blockCommentStart);
|
||||||
|
|
||||||
private bool IsMatch(CSharpLexer lexer, string commentType)
|
private bool IsMatch(CSLexerHighlighter lexer, string commentType)
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrEmpty(commentType))
|
if (!string.IsNullOrEmpty(commentType))
|
||||||
{
|
{
|
||||||
@ -41,6 +41,6 @@ namespace UnityExplorer.CSConsole.Lexer
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool IsEndLineOrEndFile(CSharpLexer lexer, char character) => lexer.EndOfStream || character == '\n' || character == '\r';
|
private bool IsEndLineOrEndFile(CSLexerHighlighter lexer, char character) => lexer.EndOfStream || character == '\n' || character == '\r';
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,7 +1,7 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace UnityExplorer.CSConsole.Lexer
|
namespace UnityExplorer.UI.CSConsole.Lexer
|
||||||
{
|
{
|
||||||
// I use two different KeywordMatch instances (valid and invalid).
|
// I use two different KeywordMatch instances (valid and invalid).
|
||||||
// This class just contains common implementations.
|
// This class just contains common implementations.
|
||||||
@ -15,7 +15,7 @@ namespace UnityExplorer.CSConsole.Lexer
|
|||||||
private readonly HashSet<string> shortlist = new HashSet<string>();
|
private readonly HashSet<string> shortlist = new HashSet<string>();
|
||||||
private readonly Stack<string> removeList = new Stack<string>();
|
private readonly Stack<string> removeList = new Stack<string>();
|
||||||
|
|
||||||
public override bool IsImplicitMatch(CSharpLexer lexer)
|
public override bool IsImplicitMatch(CSLexerHighlighter lexer)
|
||||||
{
|
{
|
||||||
if (!char.IsWhiteSpace(lexer.Previous) &&
|
if (!char.IsWhiteSpace(lexer.Previous) &&
|
||||||
!lexer.IsSpecialSymbol(lexer.Previous, DelimiterType.End))
|
!lexer.IsSpecialSymbol(lexer.Previous, DelimiterType.End))
|
@ -1,9 +1,9 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using UnityExplorer.Unstrip;
|
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using UnityExplorer.Core.Unity;
|
||||||
|
|
||||||
namespace UnityExplorer.CSConsole.Lexer
|
namespace UnityExplorer.UI.CSConsole.Lexer
|
||||||
{
|
{
|
||||||
public abstract class Matcher
|
public abstract class Matcher
|
||||||
{
|
{
|
||||||
@ -15,9 +15,9 @@ namespace UnityExplorer.CSConsole.Lexer
|
|||||||
public virtual IEnumerable<char> StartChars => Enumerable.Empty<char>();
|
public virtual IEnumerable<char> StartChars => Enumerable.Empty<char>();
|
||||||
public virtual IEnumerable<char> EndChars => Enumerable.Empty<char>();
|
public virtual IEnumerable<char> EndChars => Enumerable.Empty<char>();
|
||||||
|
|
||||||
public abstract bool IsImplicitMatch(CSharpLexer lexer);
|
public abstract bool IsImplicitMatch(CSLexerHighlighter lexer);
|
||||||
|
|
||||||
public bool IsMatch(CSharpLexer lexer)
|
public bool IsMatch(CSLexerHighlighter lexer)
|
||||||
{
|
{
|
||||||
if (IsImplicitMatch(lexer))
|
if (IsImplicitMatch(lexer))
|
||||||
{
|
{
|
@ -1,12 +1,12 @@
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace UnityExplorer.CSConsole.Lexer
|
namespace UnityExplorer.UI.CSConsole.Lexer
|
||||||
{
|
{
|
||||||
public class NumberMatch : Matcher
|
public class NumberMatch : Matcher
|
||||||
{
|
{
|
||||||
public override Color HighlightColor => new Color(0.58f, 0.33f, 0.33f, 1.0f);
|
public override Color HighlightColor => new Color(0.58f, 0.33f, 0.33f, 1.0f);
|
||||||
|
|
||||||
public override bool IsImplicitMatch(CSharpLexer lexer)
|
public override bool IsImplicitMatch(CSLexerHighlighter lexer)
|
||||||
{
|
{
|
||||||
if (!char.IsWhiteSpace(lexer.Previous) &&
|
if (!char.IsWhiteSpace(lexer.Previous) &&
|
||||||
!lexer.IsSpecialSymbol(lexer.Previous, DelimiterType.End))
|
!lexer.IsSpecialSymbol(lexer.Previous, DelimiterType.End))
|
@ -1,7 +1,7 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace UnityExplorer.CSConsole.Lexer
|
namespace UnityExplorer.UI.CSConsole.Lexer
|
||||||
{
|
{
|
||||||
public class StringMatch : Matcher
|
public class StringMatch : Matcher
|
||||||
{
|
{
|
||||||
@ -10,7 +10,7 @@ namespace UnityExplorer.CSConsole.Lexer
|
|||||||
public override IEnumerable<char> StartChars => new[] { '"' };
|
public override IEnumerable<char> StartChars => new[] { '"' };
|
||||||
public override IEnumerable<char> EndChars => new[] { '"' };
|
public override IEnumerable<char> EndChars => new[] { '"' };
|
||||||
|
|
||||||
public override bool IsImplicitMatch(CSharpLexer lexer)
|
public override bool IsImplicitMatch(CSLexerHighlighter lexer)
|
||||||
{
|
{
|
||||||
if (lexer.ReadNext() == '"')
|
if (lexer.ReadNext() == '"')
|
||||||
{
|
{
|
||||||
@ -21,6 +21,6 @@ namespace UnityExplorer.CSConsole.Lexer
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool IsClosingQuoteOrEndFile(CSharpLexer lexer, char character) => lexer.EndOfStream || character == '"';
|
private bool IsClosingQuoteOrEndFile(CSLexerHighlighter lexer, char character) => lexer.EndOfStream || character == '"';
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -2,7 +2,7 @@
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace UnityExplorer.CSConsole.Lexer
|
namespace UnityExplorer.UI.CSConsole.Lexer
|
||||||
{
|
{
|
||||||
public class SymbolMatch : Matcher
|
public class SymbolMatch : Matcher
|
||||||
{
|
{
|
||||||
@ -21,7 +21,7 @@ namespace UnityExplorer.CSConsole.Lexer
|
|||||||
public override IEnumerable<char> StartChars => symbols.Select(s => s[0]);
|
public override IEnumerable<char> StartChars => symbols.Select(s => s[0]);
|
||||||
public override IEnumerable<char> EndChars => symbols.Select(s => s[0]);
|
public override IEnumerable<char> EndChars => symbols.Select(s => s[0]);
|
||||||
|
|
||||||
public override bool IsImplicitMatch(CSharpLexer lexer)
|
public override bool IsImplicitMatch(CSLexerHighlighter lexer)
|
||||||
{
|
{
|
||||||
if (lexer == null)
|
if (lexer == null)
|
||||||
return false;
|
return false;
|
@ -1,15 +1,14 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using UnityExplorer.Unstrip;
|
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using UnityExplorer.Config;
|
using UnityExplorer.Core.Config;
|
||||||
using UnityExplorer.UI.Shared;
|
using UnityExplorer.UI.Reusable;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using UnityExplorer.Helpers;
|
using UnityExplorer.Core.Unity;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.Modules
|
namespace UnityExplorer.UI.Main
|
||||||
{
|
{
|
||||||
public class DebugConsole
|
public class DebugConsole
|
||||||
{
|
{
|
@ -3,11 +3,11 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using UnityExplorer.Inspectors;
|
using UnityExplorer.Core.Inspectors;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.Modules
|
namespace UnityExplorer.UI.Main
|
||||||
{
|
{
|
||||||
public class HomePage : MainMenu.Page
|
public class HomePage : BaseMenuPage
|
||||||
{
|
{
|
||||||
public override string Name => "Home";
|
public override string Name => "Home";
|
||||||
|
|
@ -1,147 +1,36 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using UnityExplorer.Helpers;
|
using System.Text;
|
||||||
using UnityExplorer.UI;
|
|
||||||
using UnityExplorer.UI.Modules;
|
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.SceneManagement;
|
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using UnityExplorer.Inspectors.Reflection;
|
using UnityExplorer.Core.Inspectors;
|
||||||
|
using UnityExplorer.UI.Main;
|
||||||
|
|
||||||
namespace UnityExplorer.Inspectors
|
namespace UnityExplorer.UI.Main.Home
|
||||||
{
|
{
|
||||||
public class InspectorManager
|
public class InspectorManagerUI
|
||||||
{
|
{
|
||||||
public static InspectorManager Instance { get; private set; }
|
|
||||||
|
|
||||||
public InspectorManager()
|
|
||||||
{
|
|
||||||
Instance = this;
|
|
||||||
ConstructInspectorPane();
|
|
||||||
}
|
|
||||||
|
|
||||||
public InspectorBase m_activeInspector;
|
|
||||||
public readonly List<InspectorBase> m_currentInspectors = new List<InspectorBase>();
|
|
||||||
|
|
||||||
public GameObject m_tabBarContent;
|
public GameObject m_tabBarContent;
|
||||||
public GameObject m_inspectorContent;
|
public GameObject m_inspectorContent;
|
||||||
|
|
||||||
public void Update()
|
public void OnSetInspectorTab(InspectorBase inspector)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < m_currentInspectors.Count; i++)
|
|
||||||
{
|
|
||||||
if (i >= m_currentInspectors.Count)
|
|
||||||
break;
|
|
||||||
|
|
||||||
m_currentInspectors[i].Update();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Inspect(object obj, CacheObjectBase parentMember = null)
|
|
||||||
{
|
|
||||||
#if CPP
|
|
||||||
obj = obj.Il2CppCast(ReflectionHelpers.GetActualType(obj));
|
|
||||||
#endif
|
|
||||||
UnityEngine.Object unityObj = obj as UnityEngine.Object;
|
|
||||||
|
|
||||||
if (obj.IsNullOrDestroyed(false))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// check if currently inspecting this object
|
|
||||||
foreach (InspectorBase tab in m_currentInspectors)
|
|
||||||
{
|
|
||||||
if (ReferenceEquals(obj, tab.Target))
|
|
||||||
{
|
|
||||||
SetInspectorTab(tab);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#if CPP
|
|
||||||
else if (unityObj && tab.Target is UnityEngine.Object uTabObj)
|
|
||||||
{
|
|
||||||
if (unityObj.m_CachedPtr == uTabObj.m_CachedPtr)
|
|
||||||
{
|
|
||||||
SetInspectorTab(tab);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
InspectorBase inspector;
|
|
||||||
if (obj is GameObject go)
|
|
||||||
inspector = new GameObjectInspector(go);
|
|
||||||
else
|
|
||||||
inspector = new InstanceInspector(obj);
|
|
||||||
|
|
||||||
if (inspector is ReflectionInspector ri)
|
|
||||||
ri.ParentMember = parentMember;
|
|
||||||
|
|
||||||
m_currentInspectors.Add(inspector);
|
|
||||||
SetInspectorTab(inspector);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Inspect(Type type)
|
|
||||||
{
|
|
||||||
if (type == null)
|
|
||||||
{
|
|
||||||
ExplorerCore.LogWarning("The provided type was null!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var tab in m_currentInspectors.Where(x => x is StaticInspector))
|
|
||||||
{
|
|
||||||
if (ReferenceEquals(tab.Target as Type, type))
|
|
||||||
{
|
|
||||||
SetInspectorTab(tab);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var inspector = new StaticInspector(type);
|
|
||||||
|
|
||||||
m_currentInspectors.Add(inspector);
|
|
||||||
SetInspectorTab(inspector);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetInspectorTab(InspectorBase inspector)
|
|
||||||
{
|
|
||||||
MainMenu.Instance.SetPage(HomePage.Instance);
|
|
||||||
|
|
||||||
if (m_activeInspector == inspector)
|
|
||||||
return;
|
|
||||||
|
|
||||||
UnsetInspectorTab();
|
|
||||||
|
|
||||||
m_activeInspector = inspector;
|
|
||||||
inspector.SetActive();
|
|
||||||
|
|
||||||
Color activeColor = new Color(0, 0.25f, 0, 1);
|
Color activeColor = new Color(0, 0.25f, 0, 1);
|
||||||
ColorBlock colors = inspector.tabButton.colors;
|
ColorBlock colors = inspector.BaseUI.tabButton.colors;
|
||||||
colors.normalColor = activeColor;
|
colors.normalColor = activeColor;
|
||||||
colors.highlightedColor = activeColor;
|
colors.highlightedColor = activeColor;
|
||||||
inspector.tabButton.colors = colors;
|
inspector.BaseUI.tabButton.colors = colors;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UnsetInspectorTab()
|
public void OnUnsetInspectorTab()
|
||||||
{
|
{
|
||||||
if (m_activeInspector == null)
|
ColorBlock colors = InspectorManager.Instance.m_activeInspector.BaseUI.tabButton.colors;
|
||||||
return;
|
|
||||||
|
|
||||||
m_activeInspector.SetInactive();
|
|
||||||
|
|
||||||
ColorBlock colors = m_activeInspector.tabButton.colors;
|
|
||||||
colors.normalColor = new Color(0.2f, 0.2f, 0.2f, 1);
|
colors.normalColor = new Color(0.2f, 0.2f, 0.2f, 1);
|
||||||
colors.highlightedColor = new Color(0.1f, 0.3f, 0.1f, 1);
|
colors.highlightedColor = new Color(0.1f, 0.3f, 0.1f, 1);
|
||||||
m_activeInspector.tabButton.colors = colors;
|
InspectorManager.Instance.m_activeInspector.BaseUI.tabButton.colors = colors;
|
||||||
|
|
||||||
m_activeInspector = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#region INSPECTOR PANE
|
|
||||||
|
|
||||||
public void ConstructInspectorPane()
|
public void ConstructInspectorPane()
|
||||||
{
|
{
|
||||||
var mainObj = UIFactory.CreateVerticalGroup(HomePage.Instance.Content, new Color(72f / 255f, 72f / 255f, 72f / 255f));
|
var mainObj = UIFactory.CreateVerticalGroup(HomePage.Instance.Content, new Color(72f / 255f, 72f / 255f, 72f / 255f));
|
||||||
@ -234,11 +123,11 @@ namespace UnityExplorer.Inspectors
|
|||||||
invisGroup.spacing = 10;
|
invisGroup.spacing = 10;
|
||||||
|
|
||||||
// inspect under mouse button
|
// inspect under mouse button
|
||||||
AddMouseInspectButton(topRowObj, MouseInspector.MouseInspectMode.UI);
|
AddMouseInspectButton(topRowObj, InspectUnderMouse.MouseInspectMode.UI);
|
||||||
AddMouseInspectButton(topRowObj, MouseInspector.MouseInspectMode.World);
|
AddMouseInspectButton(topRowObj, InspectUnderMouse.MouseInspectMode.World);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void AddMouseInspectButton(GameObject topRowObj, MouseInspector.MouseInspectMode mode)
|
private static void AddMouseInspectButton(GameObject topRowObj, InspectUnderMouse.MouseInspectMode mode)
|
||||||
{
|
{
|
||||||
var inspectObj = UIFactory.CreateButton(topRowObj);
|
var inspectObj = UIFactory.CreateButton(topRowObj);
|
||||||
var inspectLayout = inspectObj.AddComponent<LayoutElement>();
|
var inspectLayout = inspectObj.AddComponent<LayoutElement>();
|
||||||
@ -249,7 +138,7 @@ namespace UnityExplorer.Inspectors
|
|||||||
inspectText.text = "Mouse Inspect";
|
inspectText.text = "Mouse Inspect";
|
||||||
inspectText.fontSize = 13;
|
inspectText.fontSize = 13;
|
||||||
|
|
||||||
if (mode == MouseInspector.MouseInspectMode.UI)
|
if (mode == InspectUnderMouse.MouseInspectMode.UI)
|
||||||
inspectText.text += " (UI)";
|
inspectText.text += " (UI)";
|
||||||
|
|
||||||
var inspectBtn = inspectObj.GetComponent<Button>();
|
var inspectBtn = inspectObj.GetComponent<Button>();
|
||||||
@ -261,11 +150,10 @@ namespace UnityExplorer.Inspectors
|
|||||||
|
|
||||||
void OnInspectMouseClicked()
|
void OnInspectMouseClicked()
|
||||||
{
|
{
|
||||||
MouseInspector.Mode = mode;
|
InspectUnderMouse.Mode = mode;
|
||||||
MouseInspector.StartInspect();
|
InspectUnderMouse.StartInspect();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,14 +1,15 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using UnityExplorer.Helpers;
|
using UnityExplorer.Core.Unity;
|
||||||
using UnityExplorer.UI;
|
using UnityExplorer.UI;
|
||||||
using UnityExplorer.UI.Shared;
|
using UnityExplorer.UI.Reusable;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using UnityExplorer.Input;
|
using UnityExplorer.Core.Input;
|
||||||
|
using UnityExplorer.Core.Inspectors;
|
||||||
|
|
||||||
namespace UnityExplorer.Inspectors.GameObjects
|
namespace UnityExplorer.UI.Main.Home.Inspectors
|
||||||
{
|
{
|
||||||
public class ChildList
|
public class ChildList
|
||||||
{
|
{
|
@ -1,16 +1,16 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using UnityExplorer.Helpers;
|
|
||||||
using UnityExplorer.UI;
|
using UnityExplorer.UI;
|
||||||
using UnityExplorer.UI.Shared;
|
using UnityExplorer.UI.Reusable;
|
||||||
using UnityExplorer.Unstrip;
|
|
||||||
//using TMPro;
|
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using UnityExplorer.Input;
|
using UnityExplorer.Core.Input;
|
||||||
|
using UnityExplorer.Core;
|
||||||
|
using UnityExplorer.UI.Utility;
|
||||||
|
using UnityExplorer.Core.Inspectors;
|
||||||
|
|
||||||
namespace UnityExplorer.Inspectors.GameObjects
|
namespace UnityExplorer.UI.Main.Home.Inspectors
|
||||||
{
|
{
|
||||||
public class ComponentList
|
public class ComponentList
|
||||||
{
|
{
|
||||||
@ -77,7 +77,7 @@ namespace UnityExplorer.Inspectors.GameObjects
|
|||||||
|
|
||||||
var text = s_compListTexts[i];
|
var text = s_compListTexts[i];
|
||||||
|
|
||||||
text.text = UISyntaxHighlight.ParseFullSyntax(ReflectionHelpers.GetActualType(comp), true);
|
text.text = SignatureHighlighter.ParseFullSyntax(ReflectionUtility.GetType(comp), true);
|
||||||
|
|
||||||
var toggle = s_compToggles[i];
|
var toggle = s_compToggles[i];
|
||||||
#if CPP
|
#if CPP
|
@ -1,15 +1,14 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using UnityExplorer.Helpers;
|
|
||||||
using UnityExplorer.UI;
|
using UnityExplorer.UI;
|
||||||
//using TMPro;
|
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using UnityExplorer.Input;
|
using UnityExplorer.Core.Input;
|
||||||
using UnityExplorer.Unstrip;
|
using UnityExplorer.Core.Unity;
|
||||||
|
using UnityExplorer.Core.Inspectors;
|
||||||
|
|
||||||
namespace UnityExplorer.Inspectors.GameObjects
|
namespace UnityExplorer.UI.Main.Home.Inspectors
|
||||||
{
|
{
|
||||||
public class GameObjectControls
|
public class GameObjectControls
|
||||||
{
|
{
|
@ -1,33 +1,17 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using UnityExplorer.Helpers;
|
using System.Text;
|
||||||
using UnityExplorer.UI;
|
|
||||||
using UnityExplorer.Unstrip;
|
|
||||||
//using TMPro;
|
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using UnityExplorer.Inspectors.GameObjects;
|
using UnityExplorer.Core.Unity;
|
||||||
|
using UnityExplorer.Core.Inspectors;
|
||||||
|
using UnityExplorer.Core.Runtime;
|
||||||
|
|
||||||
namespace UnityExplorer.Inspectors
|
namespace UnityExplorer.UI.Main.Home.Inspectors
|
||||||
{
|
{
|
||||||
public class GameObjectInspector : InspectorBase
|
public class GameObjectInspectorUI : InspectorBaseUI
|
||||||
{
|
{
|
||||||
public override string TabLabel => $" <color=cyan>[G]</color> {TargetGO?.name}";
|
|
||||||
|
|
||||||
public static GameObjectInspector ActiveInstance { get; private set; }
|
|
||||||
|
|
||||||
public GameObject TargetGO;
|
|
||||||
|
|
||||||
// sub modules
|
|
||||||
private static ChildList s_childList;
|
|
||||||
private static ComponentList s_compList;
|
|
||||||
private static GameObjectControls s_controls;
|
|
||||||
|
|
||||||
// static UI elements (only constructed once)
|
|
||||||
|
|
||||||
private static bool m_UIConstructed;
|
|
||||||
|
|
||||||
private static GameObject s_content;
|
private static GameObject s_content;
|
||||||
public override GameObject Content
|
public override GameObject Content
|
||||||
{
|
{
|
||||||
@ -55,86 +39,23 @@ namespace UnityExplorer.Inspectors
|
|||||||
private static Text m_sceneText;
|
private static Text m_sceneText;
|
||||||
private static string m_lastScene;
|
private static string m_lastScene;
|
||||||
|
|
||||||
public GameObjectInspector(GameObject target) : base(target)
|
internal void RefreshTopInfo()
|
||||||
{
|
{
|
||||||
ActiveInstance = this;
|
var target = GameObjectInspector.ActiveInstance.TargetGO;
|
||||||
|
string name = target.name;
|
||||||
|
|
||||||
TargetGO = target;
|
if (m_lastName != name)
|
||||||
|
|
||||||
if (!TargetGO)
|
|
||||||
{
|
{
|
||||||
ExplorerCore.LogWarning("Target GameObject is null!");
|
m_lastName = name;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// one UI is used for all gameobject inspectors. no point recreating it.
|
|
||||||
if (!m_UIConstructed)
|
|
||||||
{
|
|
||||||
m_UIConstructed = true;
|
|
||||||
|
|
||||||
s_childList = new ChildList();
|
|
||||||
s_compList = new ComponentList();
|
|
||||||
s_controls = new GameObjectControls();
|
|
||||||
|
|
||||||
ConstructUI();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void SetActive()
|
|
||||||
{
|
|
||||||
base.SetActive();
|
|
||||||
ActiveInstance = this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void SetInactive()
|
|
||||||
{
|
|
||||||
base.SetInactive();
|
|
||||||
ActiveInstance = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal void ChangeInspectorTarget(GameObject newTarget)
|
|
||||||
{
|
|
||||||
if (!newTarget)
|
|
||||||
return;
|
|
||||||
|
|
||||||
this.Target = this.TargetGO = newTarget;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update
|
|
||||||
|
|
||||||
public override void Update()
|
|
||||||
{
|
|
||||||
base.Update();
|
|
||||||
|
|
||||||
if (m_pendingDestroy || !this.IsActive)
|
|
||||||
return;
|
|
||||||
|
|
||||||
RefreshTopInfo();
|
|
||||||
|
|
||||||
s_childList.RefreshChildObjectList();
|
|
||||||
|
|
||||||
s_compList.RefreshComponentList();
|
|
||||||
|
|
||||||
s_controls.RefreshControls();
|
|
||||||
|
|
||||||
if (GameObjectControls.s_sliderChangedWanted)
|
|
||||||
GameObjectControls.UpdateSliderControl();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void RefreshTopInfo()
|
|
||||||
{
|
|
||||||
if (m_lastName != TargetGO.name)
|
|
||||||
{
|
|
||||||
m_lastName = TargetGO.name;
|
|
||||||
m_nameInput.text = m_lastName;
|
m_nameInput.text = m_lastName;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TargetGO.transform.parent)
|
if (target.transform.parent)
|
||||||
{
|
{
|
||||||
if (!m_pathGroupObj.activeSelf)
|
if (!m_pathGroupObj.activeSelf)
|
||||||
m_pathGroupObj.SetActive(true);
|
m_pathGroupObj.SetActive(true);
|
||||||
|
|
||||||
var path = TargetGO.transform.GetTransformPath(true);
|
var path = target.transform.GetTransformPath(true);
|
||||||
if (m_lastPath != path)
|
if (m_lastPath != path)
|
||||||
{
|
{
|
||||||
m_lastPath = path;
|
m_lastPath = path;
|
||||||
@ -149,26 +70,26 @@ namespace UnityExplorer.Inspectors
|
|||||||
else if (m_pathGroupObj.activeSelf)
|
else if (m_pathGroupObj.activeSelf)
|
||||||
m_pathGroupObj.SetActive(false);
|
m_pathGroupObj.SetActive(false);
|
||||||
|
|
||||||
if (m_lastEnabledState != TargetGO.activeSelf)
|
if (m_lastEnabledState != target.activeSelf)
|
||||||
{
|
{
|
||||||
m_lastEnabledState = TargetGO.activeSelf;
|
m_lastEnabledState = target.activeSelf;
|
||||||
|
|
||||||
m_enabledToggle.isOn = TargetGO.activeSelf;
|
m_enabledToggle.isOn = target.activeSelf;
|
||||||
m_enabledText.text = TargetGO.activeSelf ? "Enabled" : "Disabled";
|
m_enabledText.text = target.activeSelf ? "Enabled" : "Disabled";
|
||||||
m_enabledText.color = TargetGO.activeSelf ? Color.green : Color.red;
|
m_enabledText.color = target.activeSelf ? Color.green : Color.red;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_lastLayer != TargetGO.layer)
|
if (m_lastLayer != target.layer)
|
||||||
{
|
{
|
||||||
m_lastLayer = TargetGO.layer;
|
m_lastLayer = target.layer;
|
||||||
m_layerDropdown.value = TargetGO.layer;
|
m_layerDropdown.value = target.layer;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(m_lastScene) || m_lastScene != TargetGO.scene.name)
|
if (string.IsNullOrEmpty(m_lastScene) || m_lastScene != target.scene.name)
|
||||||
{
|
{
|
||||||
m_lastScene = TargetGO.scene.name;
|
m_lastScene = target.scene.name;
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(TargetGO.scene.name))
|
if (!string.IsNullOrEmpty(target.scene.name))
|
||||||
m_sceneText.text = m_lastScene;
|
m_sceneText.text = m_lastScene;
|
||||||
else
|
else
|
||||||
m_sceneText.text = "None (Asset/Resource)";
|
m_sceneText.text = "None (Asset/Resource)";
|
||||||
@ -179,41 +100,42 @@ namespace UnityExplorer.Inspectors
|
|||||||
|
|
||||||
private static void OnApplyNameClicked()
|
private static void OnApplyNameClicked()
|
||||||
{
|
{
|
||||||
if (ActiveInstance == null)
|
if (GameObjectInspector.ActiveInstance == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ActiveInstance.TargetGO.name = m_nameInput.text;
|
GameObjectInspector.ActiveInstance.TargetGO.name = m_nameInput.text;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void OnEnableToggled(bool enabled)
|
private static void OnEnableToggled(bool enabled)
|
||||||
{
|
{
|
||||||
if (ActiveInstance == null)
|
if (GameObjectInspector.ActiveInstance == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ActiveInstance.TargetGO.SetActive(enabled);
|
GameObjectInspector.ActiveInstance.TargetGO.SetActive(enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void OnLayerSelected(int layer)
|
private static void OnLayerSelected(int layer)
|
||||||
{
|
{
|
||||||
if (ActiveInstance == null)
|
if (GameObjectInspector.ActiveInstance == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ActiveInstance.TargetGO.layer = layer;
|
GameObjectInspector.ActiveInstance.TargetGO.layer = layer;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void OnBackButtonClicked()
|
internal static void OnBackButtonClicked()
|
||||||
{
|
{
|
||||||
if (ActiveInstance == null)
|
if (GameObjectInspector.ActiveInstance == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ActiveInstance.ChangeInspectorTarget(ActiveInstance.TargetGO.transform.parent.gameObject);
|
GameObjectInspector.ActiveInstance.ChangeInspectorTarget(
|
||||||
|
GameObjectInspector.ActiveInstance.TargetGO.transform.parent.gameObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
#region UI CONSTRUCTION
|
#region UI CONSTRUCTION
|
||||||
|
|
||||||
private void ConstructUI()
|
internal void ConstructUI()
|
||||||
{
|
{
|
||||||
var parent = InspectorManager.Instance.m_inspectorContent;
|
var parent = InspectorManager.UI.m_inspectorContent;
|
||||||
|
|
||||||
s_content = UIFactory.CreateScrollView(parent, out GameObject scrollContent, out _, new Color(0.1f, 0.1f, 0.1f));
|
s_content = UIFactory.CreateScrollView(parent, out GameObject scrollContent, out _, new Color(0.1f, 0.1f, 0.1f));
|
||||||
|
|
||||||
@ -234,12 +156,12 @@ namespace UnityExplorer.Inspectors
|
|||||||
|
|
||||||
ConstructTopArea(scrollContent);
|
ConstructTopArea(scrollContent);
|
||||||
|
|
||||||
s_controls.ConstructControls(scrollContent);
|
GameObjectInspector.s_controls.ConstructControls(scrollContent);
|
||||||
|
|
||||||
var midGroupObj = ConstructMidGroup(scrollContent);
|
var midGroupObj = ConstructMidGroup(scrollContent);
|
||||||
|
|
||||||
s_childList.ConstructChildList(midGroupObj);
|
GameObjectInspector.s_childList.ConstructChildList(midGroupObj);
|
||||||
s_compList.ConstructCompList(midGroupObj);
|
GameObjectInspector.s_compList.ConstructCompList(midGroupObj);
|
||||||
|
|
||||||
LayoutRebuilder.ForceRebuildLayoutImmediate(s_content.GetComponent<RectTransform>());
|
LayoutRebuilder.ForceRebuildLayoutImmediate(s_content.GetComponent<RectTransform>());
|
||||||
Canvas.ForceUpdateCanvases();
|
Canvas.ForceUpdateCanvases();
|
||||||
@ -301,7 +223,7 @@ namespace UnityExplorer.Inspectors
|
|||||||
var pathInputRect = pathInputObj.GetComponent<RectTransform>();
|
var pathInputRect = pathInputObj.GetComponent<RectTransform>();
|
||||||
pathInputRect.sizeDelta = new Vector2(pathInputRect.sizeDelta.x, 25);
|
pathInputRect.sizeDelta = new Vector2(pathInputRect.sizeDelta.x, 25);
|
||||||
m_pathInput = pathInputObj.GetComponent<InputField>();
|
m_pathInput = pathInputObj.GetComponent<InputField>();
|
||||||
m_pathInput.text = TargetGO.transform.GetTransformPath();
|
m_pathInput.text = GameObjectInspector.ActiveInstance.TargetGO.transform.GetTransformPath();
|
||||||
m_pathInput.readOnly = true;
|
m_pathInput.readOnly = true;
|
||||||
m_pathInput.lineType = InputField.LineType.MultiLineNewline;
|
m_pathInput.lineType = InputField.LineType.MultiLineNewline;
|
||||||
var pathInputLayout = pathInputObj.AddComponent<LayoutElement>();
|
var pathInputLayout = pathInputObj.AddComponent<LayoutElement>();
|
||||||
@ -348,7 +270,7 @@ namespace UnityExplorer.Inspectors
|
|||||||
var nameInputRect = nameInputObj.GetComponent<RectTransform>();
|
var nameInputRect = nameInputObj.GetComponent<RectTransform>();
|
||||||
nameInputRect.sizeDelta = new Vector2(nameInputRect.sizeDelta.x, 25);
|
nameInputRect.sizeDelta = new Vector2(nameInputRect.sizeDelta.x, 25);
|
||||||
m_nameInput = nameInputObj.GetComponent<InputField>();
|
m_nameInput = nameInputObj.GetComponent<InputField>();
|
||||||
m_nameInput.text = TargetGO.name;
|
m_nameInput.text = GameObjectInspector.ActiveInstance.TargetGO.name;
|
||||||
|
|
||||||
var applyNameBtnObj = UIFactory.CreateButton(nameRowObj);
|
var applyNameBtnObj = UIFactory.CreateButton(nameRowObj);
|
||||||
var applyNameBtn = applyNameBtnObj.GetComponent<Button>();
|
var applyNameBtn = applyNameBtnObj.GetComponent<Button>();
|
||||||
@ -405,7 +327,7 @@ namespace UnityExplorer.Inspectors
|
|||||||
m_layerDropdown.options.Clear();
|
m_layerDropdown.options.Clear();
|
||||||
for (int i = 0; i < 32; i++)
|
for (int i = 0; i < 32; i++)
|
||||||
{
|
{
|
||||||
var layer = LayerMaskUnstrip.LayerToName(i);
|
var layer = RuntimeProvider.Instance.LayerToName(i);
|
||||||
m_layerDropdown.options.Add(new Dropdown.OptionData { text = $"{i}: {layer}" });
|
m_layerDropdown.options.Add(new Dropdown.OptionData { text = $"{i}: {layer}" });
|
||||||
}
|
}
|
||||||
//var itemText = layerDropdownObj.transform.Find("Label").GetComponent<Text>();
|
//var itemText = layerDropdownObj.transform.Find("Label").GetComponent<Text>();
|
||||||
@ -451,6 +373,6 @@ namespace UnityExplorer.Inspectors
|
|||||||
|
|
||||||
return midGroupObj;
|
return midGroupObj;
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
61
src/UI/Main/Home/Inspectors/InspectorBaseUI.cs
Normal file
61
src/UI/Main/Home/Inspectors/InspectorBaseUI.cs
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.UI;
|
||||||
|
using UnityExplorer.Core.Inspectors;
|
||||||
|
|
||||||
|
namespace UnityExplorer.UI.Main.Home.Inspectors
|
||||||
|
{
|
||||||
|
public abstract class InspectorBaseUI
|
||||||
|
{
|
||||||
|
public abstract GameObject Content { get; set; }
|
||||||
|
public Button tabButton;
|
||||||
|
public Text tabText;
|
||||||
|
|
||||||
|
public void AddInspectorTab(InspectorBase parent)
|
||||||
|
{
|
||||||
|
var tabContent = InspectorManager.UI.m_tabBarContent;
|
||||||
|
|
||||||
|
var tabGroupObj = UIFactory.CreateHorizontalGroup(tabContent);
|
||||||
|
var tabGroup = tabGroupObj.GetComponent<HorizontalLayoutGroup>();
|
||||||
|
tabGroup.childForceExpandWidth = true;
|
||||||
|
tabGroup.childControlWidth = true;
|
||||||
|
var tabLayout = tabGroupObj.AddComponent<LayoutElement>();
|
||||||
|
tabLayout.minWidth = 185;
|
||||||
|
tabLayout.flexibleWidth = 0;
|
||||||
|
tabGroupObj.AddComponent<Mask>();
|
||||||
|
|
||||||
|
var targetButtonObj = UIFactory.CreateButton(tabGroupObj);
|
||||||
|
targetButtonObj.AddComponent<Mask>();
|
||||||
|
var targetButtonLayout = targetButtonObj.AddComponent<LayoutElement>();
|
||||||
|
targetButtonLayout.minWidth = 165;
|
||||||
|
targetButtonLayout.flexibleWidth = 0;
|
||||||
|
|
||||||
|
tabText = targetButtonObj.GetComponentInChildren<Text>();
|
||||||
|
tabText.horizontalOverflow = HorizontalWrapMode.Overflow;
|
||||||
|
tabText.alignment = TextAnchor.MiddleLeft;
|
||||||
|
|
||||||
|
tabButton = targetButtonObj.GetComponent<Button>();
|
||||||
|
|
||||||
|
tabButton.onClick.AddListener(() => { InspectorManager.Instance.SetInspectorTab(parent); });
|
||||||
|
|
||||||
|
var closeBtnObj = UIFactory.CreateButton(tabGroupObj);
|
||||||
|
var closeBtnLayout = closeBtnObj.AddComponent<LayoutElement>();
|
||||||
|
closeBtnLayout.minWidth = 20;
|
||||||
|
closeBtnLayout.flexibleWidth = 0;
|
||||||
|
var closeBtnText = closeBtnObj.GetComponentInChildren<Text>();
|
||||||
|
closeBtnText.text = "X";
|
||||||
|
closeBtnText.color = new Color(1, 0, 0, 1);
|
||||||
|
|
||||||
|
var closeBtn = closeBtnObj.GetComponent<Button>();
|
||||||
|
|
||||||
|
closeBtn.onClick.AddListener(parent.Destroy);
|
||||||
|
|
||||||
|
var closeColors = closeBtn.colors;
|
||||||
|
closeColors.normalColor = new Color(0.2f, 0.2f, 0.2f, 1);
|
||||||
|
closeBtn.colors = closeColors;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
69
src/UI/Main/Home/Inspectors/MouseInspectorUI.cs
Normal file
69
src/UI/Main/Home/Inspectors/MouseInspectorUI.cs
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.UI;
|
||||||
|
|
||||||
|
namespace UnityExplorer.UI.Main.Home.Inspectors
|
||||||
|
{
|
||||||
|
public class MouseInspectorUI
|
||||||
|
{
|
||||||
|
internal Text s_objNameLabel;
|
||||||
|
internal Text s_objPathLabel;
|
||||||
|
internal Text s_mousePosLabel;
|
||||||
|
internal GameObject s_UIContent;
|
||||||
|
|
||||||
|
public MouseInspectorUI()
|
||||||
|
{
|
||||||
|
ConstructUI();
|
||||||
|
}
|
||||||
|
|
||||||
|
#region UI Construction
|
||||||
|
|
||||||
|
internal void ConstructUI()
|
||||||
|
{
|
||||||
|
s_UIContent = UIFactory.CreatePanel(UIManager.CanvasRoot, "MouseInspect", out GameObject content);
|
||||||
|
|
||||||
|
s_UIContent.AddComponent<Mask>();
|
||||||
|
|
||||||
|
var baseRect = s_UIContent.GetComponent<RectTransform>();
|
||||||
|
var half = new Vector2(0.5f, 0.5f);
|
||||||
|
baseRect.anchorMin = half;
|
||||||
|
baseRect.anchorMax = half;
|
||||||
|
baseRect.pivot = half;
|
||||||
|
baseRect.sizeDelta = new Vector2(700, 150);
|
||||||
|
|
||||||
|
var group = content.GetComponent<VerticalLayoutGroup>();
|
||||||
|
group.childForceExpandHeight = true;
|
||||||
|
|
||||||
|
// Title text
|
||||||
|
|
||||||
|
var titleObj = UIFactory.CreateLabel(content, TextAnchor.MiddleCenter);
|
||||||
|
var titleText = titleObj.GetComponent<Text>();
|
||||||
|
titleText.text = "<b>Mouse Inspector</b> (press <b>ESC</b> to cancel)";
|
||||||
|
|
||||||
|
var mousePosObj = UIFactory.CreateLabel(content, TextAnchor.MiddleCenter);
|
||||||
|
s_mousePosLabel = mousePosObj.GetComponent<Text>();
|
||||||
|
s_mousePosLabel.text = "Mouse Position:";
|
||||||
|
|
||||||
|
var hitLabelObj = UIFactory.CreateLabel(content, TextAnchor.MiddleLeft);
|
||||||
|
s_objNameLabel = hitLabelObj.GetComponent<Text>();
|
||||||
|
s_objNameLabel.text = "No hits...";
|
||||||
|
s_objNameLabel.horizontalOverflow = HorizontalWrapMode.Overflow;
|
||||||
|
|
||||||
|
var pathLabelObj = UIFactory.CreateLabel(content, TextAnchor.MiddleLeft);
|
||||||
|
s_objPathLabel = pathLabelObj.GetComponent<Text>();
|
||||||
|
s_objPathLabel.fontStyle = FontStyle.Italic;
|
||||||
|
s_objPathLabel.horizontalOverflow = HorizontalWrapMode.Wrap;
|
||||||
|
|
||||||
|
var pathLayout = pathLabelObj.AddComponent<LayoutElement>();
|
||||||
|
pathLayout.minHeight = 75;
|
||||||
|
pathLayout.flexibleHeight = 0;
|
||||||
|
|
||||||
|
s_UIContent.SetActive(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
@ -1,56 +1,31 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Reflection;
|
using System.Collections.Generic;
|
||||||
using UnityEngine;
|
|
||||||
using UnityExplorer.Helpers;
|
|
||||||
using UnityExplorer.UI;
|
|
||||||
using UnityEngine.UI;
|
|
||||||
using UnityExplorer.Unstrip;
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.UI;
|
||||||
|
using UnityExplorer.Core.Inspectors;
|
||||||
|
using UnityExplorer.Core.Inspectors.Reflection;
|
||||||
|
using UnityExplorer.Core.Runtime;
|
||||||
|
|
||||||
namespace UnityExplorer.Inspectors.Reflection
|
namespace UnityExplorer.UI.Main.Home.Inspectors
|
||||||
{
|
{
|
||||||
public enum MemberScopes
|
public class InstanceInspectorUI
|
||||||
{
|
{
|
||||||
All,
|
public InstanceInspectorUI(InstanceInspector parent)
|
||||||
Instance,
|
|
||||||
Static
|
|
||||||
}
|
|
||||||
|
|
||||||
public class InstanceInspector : ReflectionInspector
|
|
||||||
{
|
|
||||||
public override string TabLabel => $" <color=cyan>[R]</color> {base.TabLabel}";
|
|
||||||
|
|
||||||
internal MemberScopes m_scopeFilter;
|
|
||||||
internal Button m_lastActiveScopeButton;
|
|
||||||
|
|
||||||
public InstanceInspector(object target) : base(target) { }
|
|
||||||
|
|
||||||
private void OnScopeFilterClicked(MemberScopes type, Button button)
|
|
||||||
{
|
{
|
||||||
if (m_lastActiveScopeButton)
|
Parent = parent;
|
||||||
{
|
|
||||||
var lastColors = m_lastActiveScopeButton.colors;
|
|
||||||
lastColors.normalColor = new Color(0.2f, 0.2f, 0.2f);
|
|
||||||
m_lastActiveScopeButton.colors = lastColors;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_scopeFilter = type;
|
|
||||||
m_lastActiveScopeButton = button;
|
|
||||||
|
|
||||||
var colors = m_lastActiveScopeButton.colors;
|
|
||||||
colors.normalColor = new Color(0.2f, 0.6f, 0.2f);
|
|
||||||
m_lastActiveScopeButton.colors = colors;
|
|
||||||
|
|
||||||
FilterMembers(null, true);
|
|
||||||
m_sliderScroller.m_slider.value = 1f;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal InstanceInspector Parent;
|
||||||
|
|
||||||
public void ConstructInstanceHelpers()
|
public void ConstructInstanceHelpers()
|
||||||
{
|
{
|
||||||
if (!typeof(Component).IsAssignableFrom(m_targetType) && !typeof(UnityEngine.Object).IsAssignableFrom(m_targetType))
|
if (!typeof(Component).IsAssignableFrom(Parent.m_targetType) && !typeof(UnityEngine.Object).IsAssignableFrom(Parent.m_targetType))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var rowObj = UIFactory.CreateHorizontalGroup(Content, new Color(0.1f, 0.1f, 0.1f));
|
var rowObj = UIFactory.CreateHorizontalGroup(Parent.ReflectionUI.Content, new Color(0.1f, 0.1f, 0.1f));
|
||||||
var rowGroup = rowObj.GetComponent<HorizontalLayoutGroup>();
|
var rowGroup = rowObj.GetComponent<HorizontalLayoutGroup>();
|
||||||
rowGroup.childForceExpandWidth = true;
|
rowGroup.childForceExpandWidth = true;
|
||||||
rowGroup.childControlWidth = true;
|
rowGroup.childControlWidth = true;
|
||||||
@ -63,16 +38,14 @@ namespace UnityExplorer.Inspectors.Reflection
|
|||||||
rowLayout.minHeight = 25;
|
rowLayout.minHeight = 25;
|
||||||
rowLayout.flexibleWidth = 5000;
|
rowLayout.flexibleWidth = 5000;
|
||||||
|
|
||||||
if (typeof(Component).IsAssignableFrom(m_targetType))
|
if (typeof(Component).IsAssignableFrom(Parent.m_targetType))
|
||||||
{
|
{
|
||||||
ConstructCompHelper(rowObj);
|
ConstructCompHelper(rowObj);
|
||||||
}
|
}
|
||||||
|
|
||||||
ConstructUObjHelper(rowObj);
|
ConstructUObjHelper(rowObj);
|
||||||
|
|
||||||
// WIP
|
if (Parent.m_targetType == typeof(Texture2D))
|
||||||
|
|
||||||
if (m_targetType == typeof(Texture2D))
|
|
||||||
ConstructTextureHelper();
|
ConstructTextureHelper();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -87,9 +60,9 @@ namespace UnityExplorer.Inspectors.Reflection
|
|||||||
labelText.text = "GameObject:";
|
labelText.text = "GameObject:";
|
||||||
|
|
||||||
#if MONO
|
#if MONO
|
||||||
var comp = Target as Component;
|
var comp = Parent.Target as Component;
|
||||||
#else
|
#else
|
||||||
var comp = (Target as Il2CppSystem.Object).TryCast<Component>();
|
var comp = (Parent.Target as Il2CppSystem.Object).TryCast<Component>();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
var goBtnObj = UIFactory.CreateButton(rowObj, new Color(0.2f, 0.5f, 0.2f));
|
var goBtnObj = UIFactory.CreateButton(rowObj, new Color(0.2f, 0.5f, 0.2f));
|
||||||
@ -114,9 +87,9 @@ namespace UnityExplorer.Inspectors.Reflection
|
|||||||
labelText.text = "Name:";
|
labelText.text = "Name:";
|
||||||
|
|
||||||
#if MONO
|
#if MONO
|
||||||
var uObj = Target as UnityEngine.Object;
|
var uObj = Parent.Target as UnityEngine.Object;
|
||||||
#else
|
#else
|
||||||
var uObj = (Target as Il2CppSystem.Object).TryCast<UnityEngine.Object>();
|
var uObj = (Parent.Target as Il2CppSystem.Object).TryCast<UnityEngine.Object>();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
var inputObj = UIFactory.CreateInputField(rowObj, 14, 3, 1);
|
var inputObj = UIFactory.CreateInputField(rowObj, 14, 3, 1);
|
||||||
@ -126,16 +99,6 @@ namespace UnityExplorer.Inspectors.Reflection
|
|||||||
var inputField = inputObj.GetComponent<InputField>();
|
var inputField = inputObj.GetComponent<InputField>();
|
||||||
inputField.readOnly = true;
|
inputField.readOnly = true;
|
||||||
inputField.text = uObj.name;
|
inputField.text = uObj.name;
|
||||||
|
|
||||||
//var goBtnObj = UIFactory.CreateButton(rowObj, new Color(0.2f, 0.5f, 0.2f));
|
|
||||||
//var goBtnLayout = goBtnObj.AddComponent<LayoutElement>();
|
|
||||||
//goBtnLayout.minHeight = 25;
|
|
||||||
//goBtnLayout.minWidth = 200;
|
|
||||||
//goBtnLayout.flexibleWidth = 0;
|
|
||||||
//var text = goBtnObj.GetComponentInChildren<Text>();
|
|
||||||
//text.text = comp.name;
|
|
||||||
//var btn = goBtnObj.GetComponent<Button>();
|
|
||||||
//btn.onClick.AddListener(() => { InspectorManager.Instance.Inspect(comp.gameObject); });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal bool showingTextureHelper;
|
internal bool showingTextureHelper;
|
||||||
@ -145,7 +108,7 @@ namespace UnityExplorer.Inspectors.Reflection
|
|||||||
|
|
||||||
internal void ConstructTextureHelper()
|
internal void ConstructTextureHelper()
|
||||||
{
|
{
|
||||||
var rowObj = UIFactory.CreateHorizontalGroup(Content, new Color(0.1f, 0.1f, 0.1f));
|
var rowObj = UIFactory.CreateHorizontalGroup(Parent.ReflectionUI.Content, new Color(0.1f, 0.1f, 0.1f));
|
||||||
var rowLayout = rowObj.AddComponent<LayoutElement>();
|
var rowLayout = rowObj.AddComponent<LayoutElement>();
|
||||||
rowLayout.minHeight = 25;
|
rowLayout.minHeight = 25;
|
||||||
rowLayout.flexibleHeight = 0;
|
rowLayout.flexibleHeight = 0;
|
||||||
@ -170,7 +133,7 @@ namespace UnityExplorer.Inspectors.Reflection
|
|||||||
var labelText = labelObj.GetComponent<Text>();
|
var labelText = labelObj.GetComponent<Text>();
|
||||||
labelText.text = "Texture Viewer";
|
labelText.text = "Texture Viewer";
|
||||||
|
|
||||||
var textureViewerObj = UIFactory.CreateScrollView(Content, out GameObject scrollContent, out _, new Color(0.1f, 0.1f, 0.1f));
|
var textureViewerObj = UIFactory.CreateScrollView(Parent.ReflectionUI.Content, out GameObject scrollContent, out _, new Color(0.1f, 0.1f, 0.1f));
|
||||||
var viewerGroup = scrollContent.GetComponent<VerticalLayoutGroup>();
|
var viewerGroup = scrollContent.GetComponent<VerticalLayoutGroup>();
|
||||||
viewerGroup.childForceExpandHeight = false;
|
viewerGroup.childForceExpandHeight = false;
|
||||||
viewerGroup.childForceExpandWidth = false;
|
viewerGroup.childForceExpandWidth = false;
|
||||||
@ -209,10 +172,10 @@ namespace UnityExplorer.Inspectors.Reflection
|
|||||||
{
|
{
|
||||||
constructedTextureViewer = true;
|
constructedTextureViewer = true;
|
||||||
|
|
||||||
var tex = Target as Texture2D;
|
var tex = Parent.Target as Texture2D;
|
||||||
#if CPP
|
#if CPP
|
||||||
if (!tex)
|
if (!tex)
|
||||||
tex = (Target as Il2CppSystem.Object).TryCast<Texture2D>();
|
tex = (Parent.Target as Il2CppSystem.Object).TryCast<Texture2D>();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!tex)
|
if (!tex)
|
||||||
@ -251,10 +214,10 @@ namespace UnityExplorer.Inspectors.Reflection
|
|||||||
if (string.IsNullOrEmpty(name))
|
if (string.IsNullOrEmpty(name))
|
||||||
name = "untitled";
|
name = "untitled";
|
||||||
|
|
||||||
var savePath = $@"{Config.ExplorerConfig.Instance.Default_Output_Path}\{name}.png";
|
var savePath = $@"{Core.Config.ExplorerConfig.Instance.Default_Output_Path}\{name}.png";
|
||||||
inputField.text = savePath;
|
inputField.text = savePath;
|
||||||
|
|
||||||
saveBtn.onClick.AddListener(() =>
|
saveBtn.onClick.AddListener(() =>
|
||||||
{
|
{
|
||||||
if (tex && !string.IsNullOrEmpty(inputField.text))
|
if (tex && !string.IsNullOrEmpty(inputField.text))
|
||||||
{
|
{
|
||||||
@ -272,13 +235,10 @@ namespace UnityExplorer.Inspectors.Reflection
|
|||||||
if (File.Exists(path))
|
if (File.Exists(path))
|
||||||
File.Delete(path);
|
File.Delete(path);
|
||||||
|
|
||||||
if (!tex.IsReadable())
|
if (TextureUtilProvider.IsReadable(tex))
|
||||||
tex = Texture2DHelpers.ForceReadTexture(tex);
|
tex = TextureUtilProvider.ForceReadTexture(tex);
|
||||||
#if CPP
|
|
||||||
byte[] data = tex.EncodeToPNG();
|
byte[] data = TextureUtilProvider.Instance.EncodeToPNG(tex);
|
||||||
#else
|
|
||||||
byte[] data = tex.EncodeToPNGSafe();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
File.WriteAllBytes(path, data);
|
File.WriteAllBytes(path, data);
|
||||||
}
|
}
|
||||||
@ -288,7 +248,7 @@ namespace UnityExplorer.Inspectors.Reflection
|
|||||||
|
|
||||||
var imageObj = UIFactory.CreateUIObject("TextureViewerImage", parent);
|
var imageObj = UIFactory.CreateUIObject("TextureViewerImage", parent);
|
||||||
var image = imageObj.AddComponent<Image>();
|
var image = imageObj.AddComponent<Image>();
|
||||||
var sprite = ImageConversionUnstrip.CreateSprite(tex);
|
var sprite = TextureUtilProvider.Instance.CreateSprite(tex);
|
||||||
image.sprite = sprite;
|
image.sprite = sprite;
|
||||||
|
|
||||||
var fitter = imageObj.AddComponent<ContentSizeFitter>();
|
var fitter = imageObj.AddComponent<ContentSizeFitter>();
|
||||||
@ -304,9 +264,9 @@ namespace UnityExplorer.Inspectors.Reflection
|
|||||||
{
|
{
|
||||||
m_textureViewerObj.SetActive(enabled);
|
m_textureViewerObj.SetActive(enabled);
|
||||||
|
|
||||||
m_filterAreaObj.SetActive(!enabled);
|
Parent.ReflectionUI.m_filterAreaObj.SetActive(!enabled);
|
||||||
m_memberListObj.SetActive(!enabled);
|
Parent.ReflectionUI.m_memberListObj.SetActive(!enabled);
|
||||||
m_updateRowObj.SetActive(!enabled);
|
Parent.ReflectionUI.m_updateRowObj.SetActive(!enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ConstructInstanceFilters(GameObject parent)
|
public void ConstructInstanceFilters(GameObject parent)
|
||||||
@ -350,7 +310,7 @@ namespace UnityExplorer.Inspectors.Reflection
|
|||||||
|
|
||||||
var btn = btnObj.GetComponent<Button>();
|
var btn = btnObj.GetComponent<Button>();
|
||||||
|
|
||||||
btn.onClick.AddListener(() => { OnScopeFilterClicked(type, btn); });
|
btn.onClick.AddListener(() => { Parent.OnScopeFilterClicked(type, btn); });
|
||||||
|
|
||||||
var colors = btn.colors;
|
var colors = btn.colors;
|
||||||
colors.highlightedColor = new Color(0.3f, 0.7f, 0.3f);
|
colors.highlightedColor = new Color(0.3f, 0.7f, 0.3f);
|
||||||
@ -358,8 +318,8 @@ namespace UnityExplorer.Inspectors.Reflection
|
|||||||
if (setEnabled)
|
if (setEnabled)
|
||||||
{
|
{
|
||||||
colors.normalColor = new Color(0.2f, 0.6f, 0.2f);
|
colors.normalColor = new Color(0.2f, 0.6f, 0.2f);
|
||||||
m_scopeFilter = type;
|
Parent.m_scopeFilter = type;
|
||||||
m_lastActiveScopeButton = btn;
|
Parent.m_lastActiveScopeButton = btn;
|
||||||
}
|
}
|
||||||
|
|
||||||
btn.colors = colors;
|
btn.colors = colors;
|
288
src/UI/Main/Home/Inspectors/Reflection/ReflectionInspectorUI.cs
Normal file
288
src/UI/Main/Home/Inspectors/Reflection/ReflectionInspectorUI.cs
Normal file
@ -0,0 +1,288 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Text;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.UI;
|
||||||
|
using UnityExplorer.Core.Inspectors;
|
||||||
|
using UnityExplorer.Core.Inspectors.Reflection;
|
||||||
|
using UnityExplorer.UI.Reusable;
|
||||||
|
using UnityExplorer.UI.Utility;
|
||||||
|
|
||||||
|
namespace UnityExplorer.UI.Main.Home.Inspectors
|
||||||
|
{
|
||||||
|
public class ReflectionInspectorUI : InspectorBaseUI
|
||||||
|
{
|
||||||
|
public ReflectionInspectorUI(ReflectionInspector parent)
|
||||||
|
{
|
||||||
|
this.Parent = parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ReflectionInspector Parent;
|
||||||
|
|
||||||
|
// UI members
|
||||||
|
|
||||||
|
private GameObject m_content;
|
||||||
|
public override GameObject Content
|
||||||
|
{
|
||||||
|
get => m_content;
|
||||||
|
set => m_content = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal Text m_nameFilterText;
|
||||||
|
internal MemberTypes m_memberFilter;
|
||||||
|
internal Button m_lastActiveMemButton;
|
||||||
|
|
||||||
|
internal PageHandler m_pageHandler;
|
||||||
|
internal SliderScrollbar m_sliderScroller;
|
||||||
|
internal GameObject m_scrollContent;
|
||||||
|
internal RectTransform m_scrollContentRect;
|
||||||
|
|
||||||
|
internal bool m_widthUpdateWanted;
|
||||||
|
internal bool m_widthUpdateWaiting;
|
||||||
|
|
||||||
|
internal GameObject m_filterAreaObj;
|
||||||
|
internal GameObject m_updateRowObj;
|
||||||
|
internal GameObject m_memberListObj;
|
||||||
|
|
||||||
|
internal void ConstructUI()
|
||||||
|
{
|
||||||
|
var parent = InspectorManager.UI.m_inspectorContent;
|
||||||
|
this.Content = UIFactory.CreateVerticalGroup(parent, new Color(0.15f, 0.15f, 0.15f));
|
||||||
|
var mainGroup = Content.GetComponent<VerticalLayoutGroup>();
|
||||||
|
mainGroup.childForceExpandHeight = false;
|
||||||
|
mainGroup.childForceExpandWidth = true;
|
||||||
|
mainGroup.childControlHeight = true;
|
||||||
|
mainGroup.childControlWidth = true;
|
||||||
|
mainGroup.spacing = 5;
|
||||||
|
mainGroup.padding.top = 4;
|
||||||
|
mainGroup.padding.left = 4;
|
||||||
|
mainGroup.padding.right = 4;
|
||||||
|
mainGroup.padding.bottom = 4;
|
||||||
|
|
||||||
|
ConstructTopArea();
|
||||||
|
|
||||||
|
ConstructMemberList();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void ConstructTopArea()
|
||||||
|
{
|
||||||
|
var nameRowObj = UIFactory.CreateHorizontalGroup(Content, new Color(1, 1, 1, 0));
|
||||||
|
var nameRow = nameRowObj.GetComponent<HorizontalLayoutGroup>();
|
||||||
|
nameRow.childForceExpandWidth = true;
|
||||||
|
nameRow.childForceExpandHeight = true;
|
||||||
|
nameRow.childControlHeight = true;
|
||||||
|
nameRow.childControlWidth = true;
|
||||||
|
nameRow.padding.top = 2;
|
||||||
|
var nameRowLayout = nameRowObj.AddComponent<LayoutElement>();
|
||||||
|
nameRowLayout.minHeight = 25;
|
||||||
|
nameRowLayout.flexibleHeight = 0;
|
||||||
|
nameRowLayout.minWidth = 200;
|
||||||
|
nameRowLayout.flexibleWidth = 5000;
|
||||||
|
|
||||||
|
var typeLabel = UIFactory.CreateLabel(nameRowObj, TextAnchor.MiddleLeft);
|
||||||
|
var typeLabelText = typeLabel.GetComponent<Text>();
|
||||||
|
typeLabelText.text = "Type:";
|
||||||
|
typeLabelText.horizontalOverflow = HorizontalWrapMode.Overflow;
|
||||||
|
var typeLabelTextLayout = typeLabel.AddComponent<LayoutElement>();
|
||||||
|
typeLabelTextLayout.minWidth = 40;
|
||||||
|
typeLabelTextLayout.flexibleWidth = 0;
|
||||||
|
typeLabelTextLayout.minHeight = 25;
|
||||||
|
|
||||||
|
var typeDisplayObj = UIFactory.CreateLabel(nameRowObj, TextAnchor.MiddleLeft);
|
||||||
|
var typeDisplayText = typeDisplayObj.GetComponent<Text>();
|
||||||
|
typeDisplayText.text = SignatureHighlighter.ParseFullSyntax(Parent.m_targetType, true);
|
||||||
|
var typeDisplayLayout = typeDisplayObj.AddComponent<LayoutElement>();
|
||||||
|
typeDisplayLayout.minHeight = 25;
|
||||||
|
typeDisplayLayout.flexibleWidth = 5000;
|
||||||
|
|
||||||
|
// instance helper tools
|
||||||
|
|
||||||
|
if (Parent is InstanceInspector instanceInspector)
|
||||||
|
{
|
||||||
|
instanceInspector.CreateInstanceUIModule();
|
||||||
|
instanceInspector.InstanceUI.ConstructInstanceHelpers();
|
||||||
|
}
|
||||||
|
|
||||||
|
ConstructFilterArea();
|
||||||
|
|
||||||
|
ConstructUpdateRow();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void ConstructFilterArea()
|
||||||
|
{
|
||||||
|
// Filters
|
||||||
|
|
||||||
|
var filterAreaObj = UIFactory.CreateVerticalGroup(Content, new Color(0.1f, 0.1f, 0.1f));
|
||||||
|
var filterLayout = filterAreaObj.AddComponent<LayoutElement>();
|
||||||
|
filterLayout.minHeight = 60;
|
||||||
|
var filterGroup = filterAreaObj.GetComponent<VerticalLayoutGroup>();
|
||||||
|
filterGroup.childForceExpandWidth = true;
|
||||||
|
filterGroup.childForceExpandHeight = true;
|
||||||
|
filterGroup.childControlWidth = true;
|
||||||
|
filterGroup.childControlHeight = true;
|
||||||
|
filterGroup.spacing = 4;
|
||||||
|
filterGroup.padding.left = 4;
|
||||||
|
filterGroup.padding.right = 4;
|
||||||
|
filterGroup.padding.top = 4;
|
||||||
|
filterGroup.padding.bottom = 4;
|
||||||
|
|
||||||
|
m_filterAreaObj = filterAreaObj;
|
||||||
|
|
||||||
|
// name filter
|
||||||
|
|
||||||
|
var nameFilterRowObj = UIFactory.CreateHorizontalGroup(filterAreaObj, new Color(1, 1, 1, 0));
|
||||||
|
var nameFilterGroup = nameFilterRowObj.GetComponent<HorizontalLayoutGroup>();
|
||||||
|
nameFilterGroup.childForceExpandHeight = false;
|
||||||
|
nameFilterGroup.childForceExpandWidth = false;
|
||||||
|
nameFilterGroup.childControlWidth = true;
|
||||||
|
nameFilterGroup.childControlHeight = true;
|
||||||
|
nameFilterGroup.spacing = 5;
|
||||||
|
var nameFilterLayout = nameFilterRowObj.AddComponent<LayoutElement>();
|
||||||
|
nameFilterLayout.minHeight = 25;
|
||||||
|
nameFilterLayout.flexibleHeight = 0;
|
||||||
|
nameFilterLayout.flexibleWidth = 5000;
|
||||||
|
|
||||||
|
var nameLabelObj = UIFactory.CreateLabel(nameFilterRowObj, TextAnchor.MiddleLeft);
|
||||||
|
var nameLabelLayout = nameLabelObj.AddComponent<LayoutElement>();
|
||||||
|
nameLabelLayout.minWidth = 100;
|
||||||
|
nameLabelLayout.minHeight = 25;
|
||||||
|
nameLabelLayout.flexibleWidth = 0;
|
||||||
|
var nameLabelText = nameLabelObj.GetComponent<Text>();
|
||||||
|
nameLabelText.text = "Filter names:";
|
||||||
|
nameLabelText.color = Color.grey;
|
||||||
|
|
||||||
|
var nameInputObj = UIFactory.CreateInputField(nameFilterRowObj, 14, (int)TextAnchor.MiddleLeft, (int)HorizontalWrapMode.Overflow);
|
||||||
|
var nameInputLayout = nameInputObj.AddComponent<LayoutElement>();
|
||||||
|
nameInputLayout.flexibleWidth = 5000;
|
||||||
|
nameInputLayout.minWidth = 100;
|
||||||
|
nameInputLayout.minHeight = 25;
|
||||||
|
var nameInput = nameInputObj.GetComponent<InputField>();
|
||||||
|
nameInput.onValueChanged.AddListener((string val) => { Parent.FilterMembers(val); });
|
||||||
|
m_nameFilterText = nameInput.textComponent;
|
||||||
|
|
||||||
|
// membertype filter
|
||||||
|
|
||||||
|
var memberFilterRowObj = UIFactory.CreateHorizontalGroup(filterAreaObj, new Color(1, 1, 1, 0));
|
||||||
|
var memFilterGroup = memberFilterRowObj.GetComponent<HorizontalLayoutGroup>();
|
||||||
|
memFilterGroup.childForceExpandHeight = false;
|
||||||
|
memFilterGroup.childForceExpandWidth = false;
|
||||||
|
memFilterGroup.childControlWidth = true;
|
||||||
|
memFilterGroup.childControlHeight = true;
|
||||||
|
memFilterGroup.spacing = 5;
|
||||||
|
var memFilterLayout = memberFilterRowObj.AddComponent<LayoutElement>();
|
||||||
|
memFilterLayout.minHeight = 25;
|
||||||
|
memFilterLayout.flexibleHeight = 0;
|
||||||
|
memFilterLayout.flexibleWidth = 5000;
|
||||||
|
|
||||||
|
var memLabelObj = UIFactory.CreateLabel(memberFilterRowObj, TextAnchor.MiddleLeft);
|
||||||
|
var memLabelLayout = memLabelObj.AddComponent<LayoutElement>();
|
||||||
|
memLabelLayout.minWidth = 100;
|
||||||
|
memLabelLayout.minHeight = 25;
|
||||||
|
memLabelLayout.flexibleWidth = 0;
|
||||||
|
var memLabelText = memLabelObj.GetComponent<Text>();
|
||||||
|
memLabelText.text = "Filter members:";
|
||||||
|
memLabelText.color = Color.grey;
|
||||||
|
|
||||||
|
AddFilterButton(memberFilterRowObj, MemberTypes.All);
|
||||||
|
AddFilterButton(memberFilterRowObj, MemberTypes.Method);
|
||||||
|
AddFilterButton(memberFilterRowObj, MemberTypes.Property, true);
|
||||||
|
AddFilterButton(memberFilterRowObj, MemberTypes.Field);
|
||||||
|
|
||||||
|
// Instance filters
|
||||||
|
|
||||||
|
if (Parent is InstanceInspector instanceInspector)
|
||||||
|
{
|
||||||
|
instanceInspector.InstanceUI.ConstructInstanceFilters(filterAreaObj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AddFilterButton(GameObject parent, MemberTypes type, bool setEnabled = false)
|
||||||
|
{
|
||||||
|
var btnObj = UIFactory.CreateButton(parent, new Color(0.2f, 0.2f, 0.2f));
|
||||||
|
|
||||||
|
var btnLayout = btnObj.AddComponent<LayoutElement>();
|
||||||
|
btnLayout.minHeight = 25;
|
||||||
|
btnLayout.minWidth = 70;
|
||||||
|
|
||||||
|
var text = btnObj.GetComponentInChildren<Text>();
|
||||||
|
text.text = type.ToString();
|
||||||
|
|
||||||
|
var btn = btnObj.GetComponent<Button>();
|
||||||
|
|
||||||
|
btn.onClick.AddListener(() => { Parent.OnMemberFilterClicked(type, btn); });
|
||||||
|
|
||||||
|
var colors = btn.colors;
|
||||||
|
colors.highlightedColor = new Color(0.3f, 0.7f, 0.3f);
|
||||||
|
|
||||||
|
if (setEnabled)
|
||||||
|
{
|
||||||
|
colors.normalColor = new Color(0.2f, 0.6f, 0.2f);
|
||||||
|
m_memberFilter = type;
|
||||||
|
m_lastActiveMemButton = btn;
|
||||||
|
}
|
||||||
|
|
||||||
|
btn.colors = colors;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void ConstructUpdateRow()
|
||||||
|
{
|
||||||
|
var optionsRowObj = UIFactory.CreateHorizontalGroup(Content, new Color(1, 1, 1, 0));
|
||||||
|
var optionsLayout = optionsRowObj.AddComponent<LayoutElement>();
|
||||||
|
optionsLayout.minHeight = 25;
|
||||||
|
var optionsGroup = optionsRowObj.GetComponent<HorizontalLayoutGroup>();
|
||||||
|
optionsGroup.childForceExpandHeight = true;
|
||||||
|
optionsGroup.childForceExpandWidth = false;
|
||||||
|
optionsGroup.childAlignment = TextAnchor.MiddleLeft;
|
||||||
|
optionsGroup.spacing = 10;
|
||||||
|
|
||||||
|
m_updateRowObj = optionsRowObj;
|
||||||
|
|
||||||
|
// update button
|
||||||
|
|
||||||
|
var updateButtonObj = UIFactory.CreateButton(optionsRowObj, new Color(0.2f, 0.2f, 0.2f));
|
||||||
|
var updateBtnLayout = updateButtonObj.AddComponent<LayoutElement>();
|
||||||
|
updateBtnLayout.minWidth = 110;
|
||||||
|
updateBtnLayout.flexibleWidth = 0;
|
||||||
|
var updateText = updateButtonObj.GetComponentInChildren<Text>();
|
||||||
|
updateText.text = "Update Values";
|
||||||
|
var updateBtn = updateButtonObj.GetComponent<Button>();
|
||||||
|
updateBtn.onClick.AddListener(() =>
|
||||||
|
{
|
||||||
|
bool orig = Parent.m_autoUpdate;
|
||||||
|
Parent.m_autoUpdate = true;
|
||||||
|
Parent.Update();
|
||||||
|
if (!orig) Parent.m_autoUpdate = orig;
|
||||||
|
});
|
||||||
|
|
||||||
|
// auto update
|
||||||
|
|
||||||
|
var autoUpdateObj = UIFactory.CreateToggle(optionsRowObj, out Toggle autoUpdateToggle, out Text autoUpdateText);
|
||||||
|
var autoUpdateLayout = autoUpdateObj.AddComponent<LayoutElement>();
|
||||||
|
autoUpdateLayout.minWidth = 150;
|
||||||
|
autoUpdateLayout.minHeight = 25;
|
||||||
|
autoUpdateText.text = "Auto-update?";
|
||||||
|
autoUpdateToggle.isOn = false;
|
||||||
|
autoUpdateToggle.onValueChanged.AddListener((bool val) => { Parent.m_autoUpdate = val; });
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void ConstructMemberList()
|
||||||
|
{
|
||||||
|
var scrollobj = UIFactory.CreateScrollView(Content, out m_scrollContent, out m_sliderScroller, new Color(0.05f, 0.05f, 0.05f));
|
||||||
|
|
||||||
|
m_memberListObj = scrollobj;
|
||||||
|
m_scrollContentRect = m_scrollContent.GetComponent<RectTransform>();
|
||||||
|
|
||||||
|
var scrollGroup = m_scrollContent.GetComponent<VerticalLayoutGroup>();
|
||||||
|
scrollGroup.spacing = 3;
|
||||||
|
scrollGroup.padding.left = 0;
|
||||||
|
scrollGroup.padding.right = 0;
|
||||||
|
scrollGroup.childForceExpandHeight = true;
|
||||||
|
|
||||||
|
m_pageHandler = new PageHandler(m_sliderScroller);
|
||||||
|
m_pageHandler.ConstructUI(Content);
|
||||||
|
m_pageHandler.OnPageChanged += Parent.OnPageTurned;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,41 +1,18 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using UnityExplorer.UI;
|
using System.Text;
|
||||||
using UnityExplorer.UI.Modules;
|
|
||||||
using UnityExplorer.UI.Shared;
|
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.SceneManagement;
|
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using UnityExplorer.Unstrip;
|
using UnityExplorer.Core.Inspectors;
|
||||||
using UnityExplorer.Helpers;
|
using UnityExplorer.UI.Main;
|
||||||
|
using UnityExplorer.UI.Reusable;
|
||||||
|
|
||||||
namespace UnityExplorer.Inspectors
|
namespace UnityExplorer.UI.Main.Home
|
||||||
{
|
{
|
||||||
public class SceneExplorer
|
public class SceneExplorerUI
|
||||||
{
|
{
|
||||||
public static SceneExplorer Instance;
|
internal static bool Hiding;
|
||||||
|
|
||||||
internal static Action OnToggleShow;
|
|
||||||
|
|
||||||
public SceneExplorer()
|
|
||||||
{
|
|
||||||
Instance = this;
|
|
||||||
ConstructScenePane();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static bool Hiding;
|
|
||||||
|
|
||||||
private const float UPDATE_INTERVAL = 1f;
|
|
||||||
private float m_timeOfLastSceneUpdate;
|
|
||||||
|
|
||||||
// private int m_currentSceneHandle = -1;
|
|
||||||
public static Scene DontDestroyScene => DontDestroyObject.scene;
|
|
||||||
internal Scene m_currentScene;
|
|
||||||
internal Scene[] m_currentScenes = new Scene[0];
|
|
||||||
|
|
||||||
private GameObject m_selectedSceneObject;
|
|
||||||
private int m_lastCount;
|
|
||||||
|
|
||||||
private Dropdown m_sceneDropdown;
|
private Dropdown m_sceneDropdown;
|
||||||
private Text m_sceneDropdownText;
|
private Text m_sceneDropdownText;
|
||||||
@ -45,90 +22,13 @@ namespace UnityExplorer.Inspectors
|
|||||||
|
|
||||||
public PageHandler m_pageHandler;
|
public PageHandler m_pageHandler;
|
||||||
private GameObject m_pageContent;
|
private GameObject m_pageContent;
|
||||||
private GameObject[] m_allObjects = new GameObject[0];
|
|
||||||
private readonly List<GameObject> m_shortList = new List<GameObject>();
|
|
||||||
private readonly List<Text> m_shortListTexts = new List<Text>();
|
private readonly List<Text> m_shortListTexts = new List<Text>();
|
||||||
private readonly List<Toggle> m_shortListToggles = new List<Toggle>();
|
private readonly List<Toggle> m_shortListToggles = new List<Toggle>();
|
||||||
|
|
||||||
|
internal readonly List<GameObject> m_shortList = new List<GameObject>();
|
||||||
|
|
||||||
internal static GameObject DontDestroyObject
|
public void OnActiveScenesChanged(List<string> newNames)
|
||||||
{
|
{
|
||||||
get
|
|
||||||
{
|
|
||||||
if (!s_dontDestroyObject)
|
|
||||||
{
|
|
||||||
s_dontDestroyObject = new GameObject("DontDestroyMe");
|
|
||||||
GameObject.DontDestroyOnLoad(s_dontDestroyObject);
|
|
||||||
}
|
|
||||||
return s_dontDestroyObject;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
internal static GameObject s_dontDestroyObject;
|
|
||||||
|
|
||||||
public void Init()
|
|
||||||
{
|
|
||||||
RefreshSceneSelector();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Update()
|
|
||||||
{
|
|
||||||
if (Hiding || Time.realtimeSinceStartup - m_timeOfLastSceneUpdate < UPDATE_INTERVAL)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
RefreshSceneSelector();
|
|
||||||
|
|
||||||
if (!m_selectedSceneObject)
|
|
||||||
{
|
|
||||||
if (m_currentScene != default)
|
|
||||||
{
|
|
||||||
#if CPP
|
|
||||||
SetSceneObjectList(SceneUnstrip.GetRootGameObjects(m_currentScene.handle));
|
|
||||||
#else
|
|
||||||
SetSceneObjectList(m_currentScene.GetRootGameObjects());
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
RefreshSelectedSceneObject();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//internal void OnSceneChange()
|
|
||||||
//{
|
|
||||||
// m_sceneDropdown.OnCancel(null);
|
|
||||||
// RefreshSceneSelector();
|
|
||||||
//}
|
|
||||||
|
|
||||||
private void RefreshSceneSelector()
|
|
||||||
{
|
|
||||||
var newNames = new List<string>();
|
|
||||||
var newScenes = new List<Scene>();
|
|
||||||
|
|
||||||
if (m_currentScenes == null)
|
|
||||||
m_currentScenes = new Scene[0];
|
|
||||||
|
|
||||||
bool anyChange = SceneManager.sceneCount != m_currentScenes.Length - 1;
|
|
||||||
|
|
||||||
for (int i = 0; i < SceneManager.sceneCount; i++)
|
|
||||||
{
|
|
||||||
Scene scene = SceneManager.GetSceneAt(i);
|
|
||||||
|
|
||||||
if (scene == default)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (!anyChange && !m_currentScenes.Any(it => it.GetHandle() == scene.GetHandle()))
|
|
||||||
anyChange = true;
|
|
||||||
|
|
||||||
newScenes.Add(scene);
|
|
||||||
newNames.Add(scene.name);
|
|
||||||
}
|
|
||||||
|
|
||||||
newNames.Add("DontDestroyOnLoad");
|
|
||||||
newScenes.Add(DontDestroyScene);
|
|
||||||
|
|
||||||
m_sceneDropdown.options.Clear();
|
m_sceneDropdown.options.Clear();
|
||||||
|
|
||||||
foreach (string scene in newNames)
|
foreach (string scene in newNames)
|
||||||
@ -136,77 +36,8 @@ namespace UnityExplorer.Inspectors
|
|||||||
m_sceneDropdown.options.Add(new Dropdown.OptionData { text = scene });
|
m_sceneDropdown.options.Add(new Dropdown.OptionData { text = scene });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (anyChange)
|
m_sceneDropdown.OnCancel(null);
|
||||||
{
|
m_sceneDropdownText.text = newNames[0];
|
||||||
m_sceneDropdown.OnCancel(null);
|
|
||||||
m_sceneDropdownText.text = newNames[0];
|
|
||||||
SetTargetScene(newScenes[0]);
|
|
||||||
|
|
||||||
SearchPage.Instance.OnSceneChange();
|
|
||||||
}
|
|
||||||
|
|
||||||
m_currentScenes = newScenes.ToArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetTargetScene(Scene scene)
|
|
||||||
{
|
|
||||||
if (scene == default)
|
|
||||||
return;
|
|
||||||
|
|
||||||
m_currentScene = scene;
|
|
||||||
#if CPP
|
|
||||||
GameObject[] rootObjs = SceneUnstrip.GetRootGameObjects(scene.handle);
|
|
||||||
#else
|
|
||||||
GameObject[] rootObjs = scene.GetRootGameObjects();
|
|
||||||
#endif
|
|
||||||
SetSceneObjectList(rootObjs);
|
|
||||||
|
|
||||||
m_selectedSceneObject = null;
|
|
||||||
|
|
||||||
if (m_backButtonObj.activeSelf)
|
|
||||||
{
|
|
||||||
m_backButtonObj.SetActive(false);
|
|
||||||
m_mainInspectBtn.SetActive(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_scenePathText.text = "Scene root:";
|
|
||||||
//m_scenePathText.ForceMeshUpdate();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetTargetObject(GameObject obj)
|
|
||||||
{
|
|
||||||
if (!obj)
|
|
||||||
return;
|
|
||||||
|
|
||||||
m_scenePathText.text = obj.name;
|
|
||||||
//m_scenePathText.ForceMeshUpdate();
|
|
||||||
|
|
||||||
m_selectedSceneObject = obj;
|
|
||||||
|
|
||||||
RefreshSelectedSceneObject();
|
|
||||||
|
|
||||||
if (!m_backButtonObj.activeSelf)
|
|
||||||
{
|
|
||||||
m_backButtonObj.SetActive(true);
|
|
||||||
m_mainInspectBtn.SetActive(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void RefreshSelectedSceneObject()
|
|
||||||
{
|
|
||||||
GameObject[] list = new GameObject[m_selectedSceneObject.transform.childCount];
|
|
||||||
for (int i = 0; i < m_selectedSceneObject.transform.childCount; i++)
|
|
||||||
{
|
|
||||||
list[i] = m_selectedSceneObject.transform.GetChild(i).gameObject;
|
|
||||||
}
|
|
||||||
|
|
||||||
SetSceneObjectList(list);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SetSceneObjectList(GameObject[] objects)
|
|
||||||
{
|
|
||||||
m_allObjects = objects;
|
|
||||||
RefreshSceneObjectList();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SceneListObjectClicked(int index)
|
private void SceneListObjectClicked(int index)
|
||||||
@ -218,35 +49,19 @@ namespace UnityExplorer.Inspectors
|
|||||||
|
|
||||||
var obj = m_shortList[index];
|
var obj = m_shortList[index];
|
||||||
if (obj.transform.childCount > 0)
|
if (obj.transform.childCount > 0)
|
||||||
SetTargetObject(obj);
|
SceneExplorer.Instance.SetTargetObject(obj);
|
||||||
else
|
else
|
||||||
InspectorManager.Instance.Inspect(obj);
|
InspectorManager.Instance.Inspect(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnSceneListPageTurn()
|
internal void RefreshSceneObjectList(GameObject[] allObjects, out int newCount)
|
||||||
{
|
{
|
||||||
RefreshSceneObjectList();
|
var objects = allObjects;
|
||||||
}
|
|
||||||
|
|
||||||
private void OnToggleClicked(int index, bool val)
|
|
||||||
{
|
|
||||||
if (index >= m_shortList.Count || !m_shortList[index])
|
|
||||||
return;
|
|
||||||
|
|
||||||
var obj = m_shortList[index];
|
|
||||||
obj.SetActive(val);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void RefreshSceneObjectList()
|
|
||||||
{
|
|
||||||
m_timeOfLastSceneUpdate = Time.realtimeSinceStartup;
|
|
||||||
|
|
||||||
var objects = m_allObjects;
|
|
||||||
m_pageHandler.ListCount = objects.Length;
|
m_pageHandler.ListCount = objects.Length;
|
||||||
|
|
||||||
//int startIndex = m_sceneListPageHandler.StartIndex;
|
//int startIndex = m_sceneListPageHandler.StartIndex;
|
||||||
|
|
||||||
int newCount = 0;
|
newCount = 0;
|
||||||
|
|
||||||
foreach (var itemIndex in m_pageHandler)
|
foreach (var itemIndex in m_pageHandler)
|
||||||
{
|
{
|
||||||
@ -257,7 +72,7 @@ namespace UnityExplorer.Inspectors
|
|||||||
|
|
||||||
if (itemIndex >= objects.Length)
|
if (itemIndex >= objects.Length)
|
||||||
{
|
{
|
||||||
if (i > m_lastCount || i >= m_shortListTexts.Count)
|
if (i > SceneExplorer.Instance.m_lastCount || i >= m_shortListTexts.Count)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
GameObject label = m_shortListTexts[i].transform.parent.parent.gameObject;
|
GameObject label = m_shortListTexts[i].transform.parent.parent.gameObject;
|
||||||
@ -301,11 +116,46 @@ namespace UnityExplorer.Inspectors
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_lastCount = newCount;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#region UI CONSTRUCTION
|
private void OnSceneListPageTurn()
|
||||||
|
{
|
||||||
|
SceneExplorer.Instance.RefreshSceneObjectList();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnToggleClicked(int index, bool val)
|
||||||
|
{
|
||||||
|
if (index >= m_shortList.Count || !m_shortList[index])
|
||||||
|
return;
|
||||||
|
|
||||||
|
var obj = m_shortList[index];
|
||||||
|
obj.SetActive(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void OnGameObjectSelected(GameObject obj)
|
||||||
|
{
|
||||||
|
m_scenePathText.text = obj.name;
|
||||||
|
//m_scenePathText.ForceMeshUpdate();
|
||||||
|
if (!m_backButtonObj.activeSelf)
|
||||||
|
{
|
||||||
|
m_backButtonObj.SetActive(true);
|
||||||
|
m_mainInspectBtn.SetActive(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void OnSceneSelected()
|
||||||
|
{
|
||||||
|
if (m_backButtonObj.activeSelf)
|
||||||
|
{
|
||||||
|
m_backButtonObj.SetActive(false);
|
||||||
|
m_mainInspectBtn.SetActive(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_scenePathText.text = "Scene root:";
|
||||||
|
//m_scenePathText.ForceMeshUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
#region UI CONSTRUCTION
|
||||||
|
|
||||||
public void ConstructScenePane()
|
public void ConstructScenePane()
|
||||||
{
|
{
|
||||||
@ -346,7 +196,7 @@ namespace UnityExplorer.Inspectors
|
|||||||
void SetSceneFromDropdown(int val)
|
void SetSceneFromDropdown(int val)
|
||||||
{
|
{
|
||||||
//string scene = m_sceneDropdown.options[val].text;
|
//string scene = m_sceneDropdown.options[val].text;
|
||||||
SetTargetScene(m_currentScenes[val]);
|
SceneExplorer.Instance.SetTargetScene(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
GameObject scenePathGroupObj = UIFactory.CreateHorizontalGroup(leftPane, new Color(1, 1, 1, 0f));
|
GameObject scenePathGroupObj = UIFactory.CreateHorizontalGroup(leftPane, new Color(1, 1, 1, 0f));
|
||||||
@ -372,20 +222,7 @@ namespace UnityExplorer.Inspectors
|
|||||||
colors.normalColor = new Color(0.12f, 0.12f, 0.12f);
|
colors.normalColor = new Color(0.12f, 0.12f, 0.12f);
|
||||||
backButton.colors = colors;
|
backButton.colors = colors;
|
||||||
|
|
||||||
backButton.onClick.AddListener(() => { SetSceneObjectParent(); });
|
backButton.onClick.AddListener(() => { SceneExplorer.Instance.SetSceneObjectParent(); });
|
||||||
|
|
||||||
void SetSceneObjectParent()
|
|
||||||
{
|
|
||||||
if (!m_selectedSceneObject || !m_selectedSceneObject.transform.parent?.gameObject)
|
|
||||||
{
|
|
||||||
m_selectedSceneObject = null;
|
|
||||||
SetTargetScene(m_currentScene);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
SetTargetObject(m_selectedSceneObject.transform.parent.gameObject);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
GameObject scenePathLabel = UIFactory.CreateHorizontalGroup(scenePathGroupObj);
|
GameObject scenePathLabel = UIFactory.CreateHorizontalGroup(scenePathGroupObj);
|
||||||
Image image = scenePathLabel.GetComponent<Image>();
|
Image image = scenePathLabel.GetComponent<Image>();
|
||||||
@ -422,7 +259,7 @@ namespace UnityExplorer.Inspectors
|
|||||||
colors.normalColor = new Color(0.12f, 0.12f, 0.12f);
|
colors.normalColor = new Color(0.12f, 0.12f, 0.12f);
|
||||||
inspectButton.colors = colors;
|
inspectButton.colors = colors;
|
||||||
|
|
||||||
inspectButton.onClick.AddListener(() => { InspectorManager.Instance.Inspect(m_selectedSceneObject); });
|
inspectButton.onClick.AddListener(() => { SceneExplorer.InspectSelectedGameObject(); });
|
||||||
|
|
||||||
GameObject scrollObj = UIFactory.CreateScrollView(leftPane, out m_pageContent, out SliderScrollbar scroller, new Color(0.1f, 0.1f, 0.1f));
|
GameObject scrollObj = UIFactory.CreateScrollView(leftPane, out m_pageContent, out SliderScrollbar scroller, new Color(0.1f, 0.1f, 0.1f));
|
||||||
|
|
||||||
@ -474,10 +311,10 @@ namespace UnityExplorer.Inspectors
|
|||||||
|
|
||||||
leftLayout.minWidth = 350;
|
leftLayout.minWidth = 350;
|
||||||
|
|
||||||
Update();
|
SceneExplorer.Instance.Update();
|
||||||
}
|
}
|
||||||
|
|
||||||
OnToggleShow?.Invoke();
|
SceneExplorer.InvokeOnToggleShow();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -544,6 +381,6 @@ namespace UnityExplorer.Inspectors
|
|||||||
inspectBtn.onClick.AddListener(() => { InspectorManager.Instance.Inspect(m_shortList[thisIndex]); });
|
inspectBtn.onClick.AddListener(() => { InspectorManager.Instance.Inspect(m_shortList[thisIndex]); });
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,34 +1,18 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using UnityExplorer.CSConsole;
|
using UnityExplorer.Core.CSharp;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using UnityExplorer.UI.Modules;
|
using UnityExplorer.Core.Config;
|
||||||
using UnityExplorer.Config;
|
using UnityExplorer.Core.Unity;
|
||||||
using UnityExplorer.Helpers;
|
using UnityExplorer.UI.CSConsole;
|
||||||
|
using UnityExplorer.UI.Main;
|
||||||
|
using UnityExplorer.UI.Main.CSConsole;
|
||||||
|
|
||||||
namespace UnityExplorer.UI
|
namespace UnityExplorer.UI.Main
|
||||||
{
|
{
|
||||||
public class MainMenu
|
public class MainMenu
|
||||||
{
|
{
|
||||||
public abstract class Page
|
|
||||||
{
|
|
||||||
public abstract string Name { get; }
|
|
||||||
|
|
||||||
public GameObject Content;
|
|
||||||
public Button RefNavbarButton { get; set; }
|
|
||||||
|
|
||||||
public bool Enabled
|
|
||||||
{
|
|
||||||
get => Content?.activeSelf ?? false;
|
|
||||||
set => Content?.SetActive(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public abstract void Init();
|
|
||||||
public abstract void Update();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static MainMenu Instance { get; set; }
|
public static MainMenu Instance { get; set; }
|
||||||
|
|
||||||
public PanelDragger Dragger { get; private set; }
|
public PanelDragger Dragger { get; private set; }
|
||||||
@ -36,8 +20,8 @@ namespace UnityExplorer.UI
|
|||||||
public GameObject MainPanel { get; private set; }
|
public GameObject MainPanel { get; private set; }
|
||||||
public GameObject PageViewport { get; private set; }
|
public GameObject PageViewport { get; private set; }
|
||||||
|
|
||||||
public readonly List<Page> Pages = new List<Page>();
|
public readonly List<BaseMenuPage> Pages = new List<BaseMenuPage>();
|
||||||
private Page m_activePage;
|
private BaseMenuPage m_activePage;
|
||||||
|
|
||||||
// Navbar buttons
|
// Navbar buttons
|
||||||
private Button m_lastNavButtonPressed;
|
private Button m_lastNavButtonPressed;
|
||||||
@ -57,14 +41,18 @@ namespace UnityExplorer.UI
|
|||||||
|
|
||||||
Pages.Add(new HomePage());
|
Pages.Add(new HomePage());
|
||||||
Pages.Add(new SearchPage());
|
Pages.Add(new SearchPage());
|
||||||
Pages.Add(new CSConsolePage());
|
Pages.Add(new CSharpConsole());
|
||||||
Pages.Add(new OptionsPage());
|
Pages.Add(new OptionsPage());
|
||||||
|
|
||||||
ConstructMenu();
|
ConstructMenu();
|
||||||
|
|
||||||
foreach (Page page in Pages)
|
for (int i = 0; i < Pages.Count; i++)
|
||||||
{
|
{
|
||||||
|
var page = Pages[i];
|
||||||
page.Init();
|
page.Init();
|
||||||
|
|
||||||
|
if (!Pages.Contains(page))
|
||||||
|
i--;
|
||||||
}
|
}
|
||||||
|
|
||||||
// hide menu until each page has init layout (bit of a hack)
|
// hide menu until each page has init layout (bit of a hack)
|
||||||
@ -97,7 +85,7 @@ namespace UnityExplorer.UI
|
|||||||
m_activePage?.Update();
|
m_activePage?.Update();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetPage(Page page)
|
public void SetPage(BaseMenuPage page)
|
||||||
{
|
{
|
||||||
if (page == null || m_activePage == page)
|
if (page == null || m_activePage == page)
|
||||||
return;
|
return;
|
||||||
@ -118,7 +106,7 @@ namespace UnityExplorer.UI
|
|||||||
m_activePage?.Content?.SetActive(false);
|
m_activePage?.Content?.SetActive(false);
|
||||||
|
|
||||||
// unique case for console page, at the moment this will just go here
|
// unique case for console page, at the moment this will just go here
|
||||||
if (m_activePage is CSConsolePage)
|
if (m_activePage is CSharpConsole)
|
||||||
AutoCompleter.m_mainObj?.SetActive(false);
|
AutoCompleter.m_mainObj?.SetActive(false);
|
||||||
|
|
||||||
m_activePage = page;
|
m_activePage = page;
|
||||||
@ -252,7 +240,7 @@ namespace UnityExplorer.UI
|
|||||||
navLayout.minHeight = 25;
|
navLayout.minHeight = 25;
|
||||||
navLayout.flexibleHeight = 0;
|
navLayout.flexibleHeight = 0;
|
||||||
|
|
||||||
foreach (Page page in Pages)
|
foreach (BaseMenuPage page in Pages)
|
||||||
{
|
{
|
||||||
GameObject btnObj = UIFactory.CreateButton(navbarObj);
|
GameObject btnObj = UIFactory.CreateButton(navbarObj);
|
||||||
Button btn = btnObj.GetComponent<Button>();
|
Button btn = btnObj.GetComponent<Button>();
|
@ -3,14 +3,12 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using UnityExplorer.Config;
|
using UnityExplorer.Core.Config;
|
||||||
using UnityExplorer.Helpers;
|
using UnityExplorer.UI.Reusable;
|
||||||
using UnityExplorer.UI.Shared;
|
|
||||||
using UnityExplorer.Unstrip;
|
|
||||||
|
|
||||||
namespace UnityExplorer.UI.Modules
|
namespace UnityExplorer.UI.Main
|
||||||
{
|
{
|
||||||
public class OptionsPage : MainMenu.Page
|
public class OptionsPage : BaseMenuPage
|
||||||
{
|
{
|
||||||
public override string Name => "Options";
|
public override string Name => "Options";
|
||||||
|
|
@ -2,12 +2,9 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using UnityExplorer.Input;
|
using UnityExplorer.Core.Input;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using UnityExplorer.Inspectors;
|
using UnityExplorer.Core.Inspectors;
|
||||||
#if CPP
|
|
||||||
using UnityExplorer.Unstrip;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace UnityExplorer.UI
|
namespace UnityExplorer.UI
|
||||||
{
|
{
|
@ -4,43 +4,17 @@ using System.Linq;
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.SceneManagement;
|
using UnityEngine.SceneManagement;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using UnityExplorer.Helpers;
|
using UnityExplorer.Core.Inspectors;
|
||||||
using UnityExplorer.Inspectors;
|
using UnityExplorer.UI.Reusable;
|
||||||
using UnityExplorer.UI.Shared;
|
|
||||||
using UnityExplorer.Unstrip;
|
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
#if CPP
|
using UnityExplorer.Core.Runtime;
|
||||||
using UnhollowerRuntimeLib;
|
using UnityExplorer.Core;
|
||||||
#endif
|
using UnityExplorer.Search;
|
||||||
|
using UnityExplorer.UI.Utility;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.Modules
|
namespace UnityExplorer.UI.Main
|
||||||
{
|
{
|
||||||
internal enum SearchContext
|
public class SearchPage : BaseMenuPage
|
||||||
{
|
|
||||||
UnityObject,
|
|
||||||
GameObject,
|
|
||||||
Component,
|
|
||||||
Custom,
|
|
||||||
Singleton,
|
|
||||||
StaticClass
|
|
||||||
}
|
|
||||||
|
|
||||||
internal enum SceneFilter
|
|
||||||
{
|
|
||||||
Any,
|
|
||||||
Asset,
|
|
||||||
DontDestroyOnLoad,
|
|
||||||
Explicit,
|
|
||||||
}
|
|
||||||
|
|
||||||
internal enum ChildFilter
|
|
||||||
{
|
|
||||||
Any,
|
|
||||||
RootObject,
|
|
||||||
HasParent
|
|
||||||
}
|
|
||||||
|
|
||||||
public class SearchPage : MainMenu.Page
|
|
||||||
{
|
{
|
||||||
public override string Name => "Search";
|
public override string Name => "Search";
|
||||||
|
|
||||||
@ -61,7 +35,7 @@ namespace UnityExplorer.UI.Modules
|
|||||||
private Button m_selectedContextButton;
|
private Button m_selectedContextButton;
|
||||||
private readonly Dictionary<SearchContext, Button> m_contextButtons = new Dictionary<SearchContext, Button>();
|
private readonly Dictionary<SearchContext, Button> m_contextButtons = new Dictionary<SearchContext, Button>();
|
||||||
|
|
||||||
private Dropdown m_sceneDropdown;
|
internal Dropdown m_sceneDropdown;
|
||||||
private int m_lastSceneCount = -1;
|
private int m_lastSceneCount = -1;
|
||||||
|
|
||||||
private GameObject m_extraFilterRow;
|
private GameObject m_extraFilterRow;
|
||||||
@ -154,7 +128,7 @@ namespace UnityExplorer.UI.Modules
|
|||||||
|
|
||||||
if (m_context != SearchContext.StaticClass)
|
if (m_context != SearchContext.StaticClass)
|
||||||
{
|
{
|
||||||
var name = UISyntaxHighlight.ParseFullSyntax(obj.GetActualType(), true);
|
var name = SignatureHighlighter.ParseFullSyntax(ReflectionUtility.GetType(obj), true);
|
||||||
|
|
||||||
if (unityObj && m_context != SearchContext.Singleton)
|
if (unityObj && m_context != SearchContext.Singleton)
|
||||||
{
|
{
|
||||||
@ -169,7 +143,7 @@ namespace UnityExplorer.UI.Modules
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
var type = obj as Type;
|
var type = obj as Type;
|
||||||
text.text = UISyntaxHighlight.ParseFullSyntax(type, true);
|
text.text = SignatureHighlighter.ParseFullSyntax(type, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
var label = text.transform.parent.parent.gameObject;
|
var label = text.transform.parent.parent.gameObject;
|
||||||
@ -242,11 +216,14 @@ namespace UnityExplorer.UI.Modules
|
|||||||
m_resultListPageHandler.CurrentPage = 0;
|
m_resultListPageHandler.CurrentPage = 0;
|
||||||
|
|
||||||
if (m_context == SearchContext.StaticClass)
|
if (m_context == SearchContext.StaticClass)
|
||||||
StaticClassSearch();
|
m_results = SearchProvider.StaticClassSearch(m_nameInput.text);
|
||||||
else if (m_context == SearchContext.Singleton)
|
else if (m_context == SearchContext.Singleton)
|
||||||
SingletonSearch();
|
m_results = SearchProvider.SingletonSearch(m_nameInput.text);
|
||||||
else
|
else
|
||||||
UnityObjectSearch();
|
m_results = SearchProvider.UnityObjectSearch(m_nameInput.text, m_customTypeInput.text, m_context, m_childFilter, m_sceneFilter);
|
||||||
|
|
||||||
|
if (m_results == null)
|
||||||
|
m_results = new object[0];
|
||||||
|
|
||||||
RefreshResultList();
|
RefreshResultList();
|
||||||
|
|
||||||
@ -256,217 +233,6 @@ namespace UnityExplorer.UI.Modules
|
|||||||
m_resultCountText.text = "No results...";
|
m_resultCountText.text = "No results...";
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void StaticClassSearch()
|
|
||||||
{
|
|
||||||
var list = new List<Type>();
|
|
||||||
|
|
||||||
var nameFilter = "";
|
|
||||||
if (!string.IsNullOrEmpty(m_nameInput.text))
|
|
||||||
nameFilter = m_nameInput.text.ToLower();
|
|
||||||
|
|
||||||
foreach (var asm in AppDomain.CurrentDomain.GetAssemblies())
|
|
||||||
{
|
|
||||||
foreach (var type in asm.TryGetTypes().Where(it => it.IsSealed && it.IsAbstract))
|
|
||||||
{
|
|
||||||
if (!string.IsNullOrEmpty(nameFilter) && !type.FullName.ToLower().Contains(nameFilter))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
list.Add(type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m_results = list.ToArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
internal string[] s_instanceNames = new string[]
|
|
||||||
{
|
|
||||||
"m_instance",
|
|
||||||
"m_Instance",
|
|
||||||
"s_instance",
|
|
||||||
"s_Instance",
|
|
||||||
"_instance",
|
|
||||||
"_Instance",
|
|
||||||
"instance",
|
|
||||||
"Instance",
|
|
||||||
"<Instance>k__BackingField",
|
|
||||||
"<instance>k__BackingField",
|
|
||||||
};
|
|
||||||
|
|
||||||
private void SingletonSearch()
|
|
||||||
{
|
|
||||||
var instances = new List<object>();
|
|
||||||
|
|
||||||
var nameFilter = "";
|
|
||||||
if (!string.IsNullOrEmpty(m_nameInput.text))
|
|
||||||
nameFilter = m_nameInput.text.ToLower();
|
|
||||||
|
|
||||||
var flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static;
|
|
||||||
|
|
||||||
foreach (var asm in AppDomain.CurrentDomain.GetAssemblies())
|
|
||||||
{
|
|
||||||
// Search all non-static, non-enum classes.
|
|
||||||
foreach (var type in asm.TryGetTypes().Where(it => !(it.IsSealed && it.IsAbstract) && !it.IsEnum))
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (!string.IsNullOrEmpty(nameFilter) && !type.FullName.ToLower().Contains(nameFilter))
|
|
||||||
continue;
|
|
||||||
#if CPP
|
|
||||||
// Only look for Properties in IL2CPP, not for Mono.
|
|
||||||
PropertyInfo pi;
|
|
||||||
foreach (var name in s_instanceNames)
|
|
||||||
{
|
|
||||||
pi = type.GetProperty(name, flags);
|
|
||||||
if (pi != null)
|
|
||||||
{
|
|
||||||
var instance = pi.GetValue(null, null);
|
|
||||||
if (instance != null)
|
|
||||||
{
|
|
||||||
instances.Add(instance);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
// 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);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch { }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m_results = instances.ToArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
internal void UnityObjectSearch()
|
|
||||||
{
|
|
||||||
Type searchType = null;
|
|
||||||
switch (m_context)
|
|
||||||
{
|
|
||||||
case SearchContext.GameObject:
|
|
||||||
searchType = typeof(GameObject); break;
|
|
||||||
|
|
||||||
case SearchContext.Component:
|
|
||||||
searchType = typeof(Component); break;
|
|
||||||
|
|
||||||
case SearchContext.Custom:
|
|
||||||
if (string.IsNullOrEmpty(m_customTypeInput.text))
|
|
||||||
{
|
|
||||||
ExplorerCore.LogWarning("Custom Type input must not be empty!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (ReflectionHelpers.GetTypeByName(m_customTypeInput.text) is Type customType)
|
|
||||||
if (typeof(UnityEngine.Object).IsAssignableFrom(customType))
|
|
||||||
searchType = customType;
|
|
||||||
else
|
|
||||||
ExplorerCore.LogWarning($"Custom type '{customType.FullName}' is not assignable from UnityEngine.Object!");
|
|
||||||
else
|
|
||||||
ExplorerCore.LogWarning($"Could not find a type by the name '{m_customTypeInput.text}'!");
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
searchType = typeof(UnityEngine.Object); break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (searchType == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
var allObjects = ResourcesUnstrip.FindObjectsOfTypeAll(searchType);
|
|
||||||
var results = new List<object>();
|
|
||||||
|
|
||||||
// perform filter comparers
|
|
||||||
|
|
||||||
string nameFilter = null;
|
|
||||||
if (!string.IsNullOrEmpty(m_nameInput.text))
|
|
||||||
nameFilter = m_nameInput.text.ToLower();
|
|
||||||
|
|
||||||
bool canGetGameObject = (m_sceneFilter != SceneFilter.Any || m_childFilter != ChildFilter.Any)
|
|
||||||
&& (m_context == SearchContext.GameObject || typeof(Component).IsAssignableFrom(searchType));
|
|
||||||
|
|
||||||
string sceneFilter = null;
|
|
||||||
if (!canGetGameObject)
|
|
||||||
{
|
|
||||||
if (m_context != SearchContext.UnityObject && (m_sceneFilter != SceneFilter.Any || m_childFilter != ChildFilter.Any))
|
|
||||||
ExplorerCore.LogWarning($"Type '{searchType}' cannot have Scene or Child filters applied to it");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (m_sceneFilter == SceneFilter.DontDestroyOnLoad)
|
|
||||||
sceneFilter = "DontDestroyOnLoad";
|
|
||||||
else if (m_sceneFilter == SceneFilter.Explicit)
|
|
||||||
sceneFilter = m_sceneDropdown.options[m_sceneDropdown.value].text;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var obj in allObjects)
|
|
||||||
{
|
|
||||||
// name check
|
|
||||||
if (!string.IsNullOrEmpty(nameFilter) && !obj.name.ToLower().Contains(nameFilter))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (canGetGameObject)
|
|
||||||
{
|
|
||||||
#if MONO
|
|
||||||
var go = m_context == SearchContext.GameObject
|
|
||||||
? obj as GameObject
|
|
||||||
: (obj as Component).gameObject;
|
|
||||||
#else
|
|
||||||
var go = m_context == SearchContext.GameObject
|
|
||||||
? obj.TryCast<GameObject>()
|
|
||||||
: obj.TryCast<Component>().gameObject;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// scene check
|
|
||||||
if (m_sceneFilter != SceneFilter.Any)
|
|
||||||
{
|
|
||||||
if (!go)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
switch (m_context)
|
|
||||||
{
|
|
||||||
case SearchContext.GameObject:
|
|
||||||
if (go.scene.name != sceneFilter)
|
|
||||||
continue;
|
|
||||||
break;
|
|
||||||
case SearchContext.Custom:
|
|
||||||
case SearchContext.Component:
|
|
||||||
if (go.scene.name != sceneFilter)
|
|
||||||
continue;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_childFilter != ChildFilter.Any)
|
|
||||||
{
|
|
||||||
if (!go)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// root object check (no parent)
|
|
||||||
if (m_childFilter == ChildFilter.HasParent && !go.transform.parent)
|
|
||||||
continue;
|
|
||||||
else if (m_childFilter == ChildFilter.RootObject && go.transform.parent)
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
results.Add(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_results = results.ToArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnResultPageTurn()
|
private void OnResultPageTurn()
|
||||||
{
|
{
|
||||||
RefreshResultList();
|
RefreshResultList();
|
@ -1,120 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Reflection;
|
|
||||||
using System.Text;
|
|
||||||
using UnityExplorer.CSConsole;
|
|
||||||
|
|
||||||
namespace UnityExplorer.UI.Modules
|
|
||||||
{
|
|
||||||
public class CSConsolePage : MainMenu.Page
|
|
||||||
{
|
|
||||||
public override string Name => "C# Console";
|
|
||||||
|
|
||||||
public static CSConsolePage Instance { get; private set; }
|
|
||||||
|
|
||||||
public CodeEditor m_codeEditor;
|
|
||||||
public ScriptEvaluator m_evaluator;
|
|
||||||
|
|
||||||
public static List<string> UsingDirectives;
|
|
||||||
|
|
||||||
public static readonly string[] DefaultUsing = new string[]
|
|
||||||
{
|
|
||||||
"System",
|
|
||||||
"System.Linq",
|
|
||||||
"System.Collections",
|
|
||||||
"System.Collections.Generic",
|
|
||||||
"System.Reflection",
|
|
||||||
"UnityEngine",
|
|
||||||
#if CPP
|
|
||||||
"UnhollowerBaseLib",
|
|
||||||
"UnhollowerRuntimeLib",
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
public override void Init()
|
|
||||||
{
|
|
||||||
Instance = this;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
m_codeEditor = new CodeEditor();
|
|
||||||
|
|
||||||
AutoCompleter.Init();
|
|
||||||
|
|
||||||
ResetConsole();
|
|
||||||
|
|
||||||
// Make sure compiler is supported on this platform
|
|
||||||
m_evaluator.Compile("");
|
|
||||||
|
|
||||||
foreach (string use in DefaultUsing)
|
|
||||||
{
|
|
||||||
AddUsing(use);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
// TODO remove page button from menu?
|
|
||||||
ExplorerCore.LogWarning($"Error setting up console!\r\nMessage: {e.Message}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Update()
|
|
||||||
{
|
|
||||||
m_codeEditor?.Update();
|
|
||||||
|
|
||||||
AutoCompleter.Update();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void AddUsing(string asm)
|
|
||||||
{
|
|
||||||
if (!UsingDirectives.Contains(asm))
|
|
||||||
{
|
|
||||||
Evaluate($"using {asm};", true);
|
|
||||||
UsingDirectives.Add(asm);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Evaluate(string code, bool suppressWarning = false)
|
|
||||||
{
|
|
||||||
m_evaluator.Compile(code, out Mono.CSharp.CompiledMethod compiled);
|
|
||||||
|
|
||||||
if (compiled == null)
|
|
||||||
{
|
|
||||||
if (!suppressWarning)
|
|
||||||
ExplorerCore.LogWarning("Unable to compile the code!");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
object ret = VoidType.Value;
|
|
||||||
compiled.Invoke(ref ret);
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
if (!suppressWarning)
|
|
||||||
ExplorerCore.LogWarning($"Exception executing code: {e.GetType()}, {e.Message}\r\n{e.StackTrace}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ResetConsole()
|
|
||||||
{
|
|
||||||
if (m_evaluator != null)
|
|
||||||
{
|
|
||||||
m_evaluator.Dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
m_evaluator = new ScriptEvaluator(new StringWriter(new StringBuilder())) { InteractiveBaseClass = typeof(ScriptInteraction) };
|
|
||||||
|
|
||||||
UsingDirectives = new List<string>();
|
|
||||||
}
|
|
||||||
|
|
||||||
private class VoidType
|
|
||||||
{
|
|
||||||
public static readonly VoidType Value = new VoidType();
|
|
||||||
private VoidType() { }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -7,9 +7,9 @@ using UnityEngine;
|
|||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using UnityEngine.EventSystems;
|
using UnityEngine.EventSystems;
|
||||||
using UnityEngine.Events;
|
using UnityEngine.Events;
|
||||||
using UnityExplorer.Helpers;
|
using UnityExplorer.Core.Unity;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.Shared
|
namespace UnityExplorer.UI.Reusable
|
||||||
{
|
{
|
||||||
// To fix an issue with Input Fields and allow them to go inside a ScrollRect nicely.
|
// To fix an issue with Input Fields and allow them to go inside a ScrollRect nicely.
|
||||||
|
|
@ -1,12 +1,12 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using UnityExplorer.Config;
|
using UnityExplorer.Core.Config;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using UnityExplorer.Helpers;
|
using UnityExplorer.Core.Unity;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.Shared
|
namespace UnityExplorer.UI.Reusable
|
||||||
{
|
{
|
||||||
public enum Turn
|
public enum Turn
|
||||||
{
|
{
|
@ -5,10 +5,11 @@ using UnityEngine;
|
|||||||
using UnityEngine.Events;
|
using UnityEngine.Events;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using UnityExplorer;
|
using UnityExplorer;
|
||||||
using UnityExplorer.Helpers;
|
using UnityExplorer.Core;
|
||||||
|
using UnityExplorer.Core.Unity;
|
||||||
using UnityExplorer.UI;
|
using UnityExplorer.UI;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.Shared
|
namespace UnityExplorer.UI.Reusable
|
||||||
{
|
{
|
||||||
// Basically just to fix an issue with Scrollbars, instead we use a Slider as the scrollbar.
|
// Basically just to fix an issue with Scrollbars, instead we use a Slider as the scrollbar.
|
||||||
public class SliderScrollbar
|
public class SliderScrollbar
|
||||||
@ -168,7 +169,7 @@ public static class SliderExtensions
|
|||||||
{
|
{
|
||||||
if (m_setMethod == null)
|
if (m_setMethod == null)
|
||||||
{
|
{
|
||||||
m_setMethod = typeof(Slider).GetMethod("Set", ReflectionHelpers.CommonFlags, null, new[] { typeof(float), typeof(bool) }, null);
|
m_setMethod = typeof(Slider).GetMethod("Set", ReflectionUtility.CommonFlags, null, new[] { typeof(float), typeof(bool) }, null);
|
||||||
}
|
}
|
||||||
return m_setMethod;
|
return m_setMethod;
|
||||||
}
|
}
|
@ -1,71 +0,0 @@
|
|||||||
//using UnityEngine;
|
|
||||||
//using System.Collections;
|
|
||||||
//using UnityEngine.UI;
|
|
||||||
//using System;
|
|
||||||
//using UnityEngine.EventSystems;
|
|
||||||
|
|
||||||
|
|
||||||
/////////////// kinda works, not really
|
|
||||||
|
|
||||||
|
|
||||||
//public class ScrollRectEx : ScrollRect, IEventSystemHandler
|
|
||||||
//{
|
|
||||||
// internal SliderScrollbar sliderScrollbar;
|
|
||||||
|
|
||||||
// private bool ShouldRouteToParent(PointerEventData data)
|
|
||||||
// => !sliderScrollbar.IsActive
|
|
||||||
// || sliderScrollbar.m_slider.value < 0.001f && data.delta.y > 0
|
|
||||||
// || sliderScrollbar.m_slider.value == 1f && data.delta.y < 0;
|
|
||||||
|
|
||||||
// private void DoForParents<T>(Action<T> action) where T : IEventSystemHandler
|
|
||||||
// {
|
|
||||||
// Transform parent = transform.parent;
|
|
||||||
// while (parent != null)
|
|
||||||
// {
|
|
||||||
// foreach (var component in parent.GetComponents<Component>())
|
|
||||||
// {
|
|
||||||
// if (component is T)
|
|
||||||
// action((T)(IEventSystemHandler)component);
|
|
||||||
// }
|
|
||||||
// parent = parent.parent;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public override void OnScroll(PointerEventData data)
|
|
||||||
// {
|
|
||||||
// if (ShouldRouteToParent(data))
|
|
||||||
// DoForParents<IScrollHandler>((parent) => { parent.OnScroll(data); });
|
|
||||||
// else
|
|
||||||
// base.OnScroll(data);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public override void OnInitializePotentialDrag(PointerEventData eventData)
|
|
||||||
// {
|
|
||||||
// DoForParents<IInitializePotentialDragHandler>((parent) => { parent.OnInitializePotentialDrag(eventData); });
|
|
||||||
// base.OnInitializePotentialDrag(eventData);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public override void OnDrag(PointerEventData data)
|
|
||||||
// {
|
|
||||||
// if (ShouldRouteToParent(data))
|
|
||||||
// DoForParents<IDragHandler>((parent) => { parent.OnDrag(data); });
|
|
||||||
// else
|
|
||||||
// base.OnDrag(data);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public override void OnBeginDrag(UnityEngine.EventSystems.PointerEventData data)
|
|
||||||
// {
|
|
||||||
// if (ShouldRouteToParent(data))
|
|
||||||
// DoForParents<IBeginDragHandler>((parent) => { parent.OnBeginDrag(data); });
|
|
||||||
// else
|
|
||||||
// base.OnBeginDrag(data);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public override void OnEndDrag(UnityEngine.EventSystems.PointerEventData data)
|
|
||||||
// {
|
|
||||||
// if (ShouldRouteToParent(data))
|
|
||||||
// DoForParents<IEndDragHandler>((parent) => { parent.OnEndDrag(data); });
|
|
||||||
// else
|
|
||||||
// base.OnEndDrag(data);
|
|
||||||
// }
|
|
||||||
//}
|
|
@ -2,8 +2,8 @@
|
|||||||
//using TMPro;
|
//using TMPro;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using UnityExplorer.Helpers;
|
using UnityExplorer.Core.Unity;
|
||||||
using UnityExplorer.UI.Shared;
|
using UnityExplorer.UI.Reusable;
|
||||||
|
|
||||||
namespace UnityExplorer.UI
|
namespace UnityExplorer.UI
|
||||||
{
|
{
|
||||||
|
@ -1,18 +1,15 @@
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.EventSystems;
|
using UnityEngine.EventSystems;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using UnityExplorer.Inspectors;
|
using UnityExplorer.Core.Inspectors;
|
||||||
using UnityExplorer.UI.Modules;
|
using UnityExplorer.UI.Main;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using UnityExplorer.Helpers;
|
using UnityExplorer.UI.Reusable;
|
||||||
using UnityExplorer.UI.Shared;
|
using UnityExplorer.Core.Input;
|
||||||
using UnityExplorer.Input;
|
|
||||||
using System;
|
using System;
|
||||||
using UnityExplorer.Config;
|
using UnityExplorer.Core.Config;
|
||||||
#if CPP
|
using UnityExplorer.UI.Utility;
|
||||||
using UnityExplorer.Unstrip;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace UnityExplorer.UI
|
namespace UnityExplorer.UI
|
||||||
{
|
{
|
||||||
@ -72,7 +69,7 @@ namespace UnityExplorer.UI
|
|||||||
|
|
||||||
// Create submodules
|
// Create submodules
|
||||||
new MainMenu();
|
new MainMenu();
|
||||||
MouseInspector.ConstructUI();
|
InspectUnderMouse.UI.ConstructUI();
|
||||||
PanelDragger.LoadCursorImage();
|
PanelDragger.LoadCursorImage();
|
||||||
|
|
||||||
// Force refresh of anchors
|
// Force refresh of anchors
|
||||||
@ -91,12 +88,12 @@ namespace UnityExplorer.UI
|
|||||||
CanvasRoot.SetActive(show);
|
CanvasRoot.SetActive(show);
|
||||||
|
|
||||||
if (show)
|
if (show)
|
||||||
ForceUnlockCursor.SetEventSystem();
|
CursorUnlocker.SetEventSystem();
|
||||||
else
|
else
|
||||||
ForceUnlockCursor.ReleaseEventSystem();
|
CursorUnlocker.ReleaseEventSystem();
|
||||||
}
|
}
|
||||||
|
|
||||||
ForceUnlockCursor.UpdateCursorControl();
|
CursorUnlocker.UpdateCursorControl();
|
||||||
}
|
}
|
||||||
|
|
||||||
//public static void OnSceneChange()
|
//public static void OnSceneChange()
|
||||||
@ -118,7 +115,7 @@ namespace UnityExplorer.UI
|
|||||||
if (EventSys)
|
if (EventSys)
|
||||||
{
|
{
|
||||||
if (EventSystem.current != EventSys)
|
if (EventSystem.current != EventSys)
|
||||||
ForceUnlockCursor.SetEventSystem();
|
CursorUnlocker.SetEventSystem();
|
||||||
#if CPP
|
#if CPP
|
||||||
// Some IL2CPP games behave weird with multiple UI Input Systems, some fixes for them.
|
// Some IL2CPP games behave weird with multiple UI Input Systems, some fixes for them.
|
||||||
var evt = InputManager.InputPointerEvent;
|
var evt = InputManager.InputPointerEvent;
|
||||||
|
@ -1,19 +1,20 @@
|
|||||||
using System;
|
using System;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityExplorer.Helpers;
|
using UnityExplorer.Core.Unity;
|
||||||
using UnityEngine.EventSystems;
|
using UnityEngine.EventSystems;
|
||||||
using UnityExplorer.Input;
|
using UnityExplorer.Core.Input;
|
||||||
using BF = System.Reflection.BindingFlags;
|
using BF = System.Reflection.BindingFlags;
|
||||||
using UnityExplorer.Config;
|
using UnityExplorer.Core.Config;
|
||||||
|
using UnityExplorer.Core;
|
||||||
#if ML
|
#if ML
|
||||||
using Harmony;
|
using Harmony;
|
||||||
#else
|
#else
|
||||||
using HarmonyLib;
|
using HarmonyLib;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace UnityExplorer.UI
|
namespace UnityExplorer.UI.Utility
|
||||||
{
|
{
|
||||||
public class ForceUnlockCursor
|
public class CursorUnlocker
|
||||||
{
|
{
|
||||||
public static bool Unlock
|
public static bool Unlock
|
||||||
{
|
{
|
||||||
@ -37,7 +38,7 @@ namespace UnityExplorer.UI
|
|||||||
|
|
||||||
private static Type CursorType
|
private static Type CursorType
|
||||||
=> m_cursorType
|
=> m_cursorType
|
||||||
?? (m_cursorType = ReflectionHelpers.GetTypeByName("UnityEngine.Cursor"));
|
?? (m_cursorType = ReflectionUtility.GetTypeByName("UnityEngine.Cursor"));
|
||||||
private static Type m_cursorType;
|
private static Type m_cursorType;
|
||||||
|
|
||||||
public static void Init()
|
public static void Init()
|
||||||
@ -79,17 +80,17 @@ namespace UnityExplorer.UI
|
|||||||
// Setup Harmony Patches
|
// Setup Harmony Patches
|
||||||
TryPatch(typeof(Cursor),
|
TryPatch(typeof(Cursor),
|
||||||
"lockState",
|
"lockState",
|
||||||
new HarmonyMethod(typeof(ForceUnlockCursor).GetMethod(nameof(Prefix_set_lockState))),
|
new HarmonyMethod(typeof(CursorUnlocker).GetMethod(nameof(Prefix_set_lockState))),
|
||||||
true);
|
true);
|
||||||
|
|
||||||
TryPatch(typeof(Cursor),
|
TryPatch(typeof(Cursor),
|
||||||
"visible",
|
"visible",
|
||||||
new HarmonyMethod(typeof(ForceUnlockCursor).GetMethod(nameof(Prefix_set_visible))),
|
new HarmonyMethod(typeof(CursorUnlocker).GetMethod(nameof(Prefix_set_visible))),
|
||||||
true);
|
true);
|
||||||
|
|
||||||
TryPatch(typeof(EventSystem),
|
TryPatch(typeof(EventSystem),
|
||||||
"current",
|
"current",
|
||||||
new HarmonyMethod(typeof(ForceUnlockCursor).GetMethod(nameof(Prefix_EventSystem_set_current))),
|
new HarmonyMethod(typeof(CursorUnlocker).GetMethod(nameof(Prefix_EventSystem_set_current))),
|
||||||
true);
|
true);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
@ -2,11 +2,14 @@
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityExplorer.Unstrip;
|
using UnityExplorer.Core.Unity;
|
||||||
|
|
||||||
namespace UnityExplorer.UI
|
namespace UnityExplorer.UI.Utility
|
||||||
{
|
{
|
||||||
public class UISyntaxHighlight
|
/// <summary>
|
||||||
|
/// Syntax-highlights a member's signature, by either the Type name or a Type and Member together.
|
||||||
|
/// </summary>
|
||||||
|
public class SignatureHighlighter
|
||||||
{
|
{
|
||||||
public const string FIELD_STATIC = "#8d8dc6";
|
public const string FIELD_STATIC = "#8d8dc6";
|
||||||
public const string FIELD_INSTANCE = "#c266ff";
|
public const string FIELD_INSTANCE = "#c266ff";
|
@ -263,83 +263,94 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="Loader\ExplorerBepIn6Plugin.cs" />
|
<Compile Include="Loader\ExplorerBepIn6Plugin.cs" />
|
||||||
<Compile Include="Loader\ExplorerStandalone.cs" />
|
<Compile Include="Loader\ExplorerStandalone.cs" />
|
||||||
<Compile Include="Inspectors\MouseInspector.cs" />
|
<Compile Include="Core\Runtime\Il2Cpp\Il2CppReflection.cs" />
|
||||||
<Compile Include="Inspectors\Reflection\CacheObject\CacheEnumerated.cs" />
|
<Compile Include="Core\Runtime\Il2Cpp\Il2CppTextureUtil.cs" />
|
||||||
<Compile Include="Inspectors\Reflection\CacheObject\CacheField.cs" />
|
<Compile Include="Core\Runtime\Mono\MonoReflection.cs" />
|
||||||
<Compile Include="Inspectors\Reflection\CacheObject\CachePaired.cs" />
|
<Compile Include="Core\Runtime\Mono\MonoTextureUtil.cs" />
|
||||||
<Compile Include="Inspectors\Reflection\CacheObject\CacheMember.cs" />
|
<Compile Include="Core\Runtime\ReflectionProvider.cs" />
|
||||||
<Compile Include="Inspectors\Reflection\CacheObject\CacheMethod.cs" />
|
<Compile Include="Core\Runtime\TextureUtilProvider.cs" />
|
||||||
<Compile Include="Inspectors\Reflection\CacheObject\CacheProperty.cs" />
|
<Compile Include="Core\Inspectors\InspectUnderMouse.cs" />
|
||||||
<Compile Include="Inspectors\Reflection\CacheObject\CacheObjectBase.cs" />
|
<Compile Include="Core\Inspectors\Reflection\CacheObject\CacheEnumerated.cs" />
|
||||||
<Compile Include="Helpers\Texture2DHelpers.cs" />
|
<Compile Include="Core\Inspectors\Reflection\CacheObject\CacheField.cs" />
|
||||||
<Compile Include="Config\ExplorerConfig.cs" />
|
<Compile Include="Core\Inspectors\Reflection\CacheObject\CachePaired.cs" />
|
||||||
|
<Compile Include="Core\Inspectors\Reflection\CacheObject\CacheMember.cs" />
|
||||||
|
<Compile Include="Core\Inspectors\Reflection\CacheObject\CacheMethod.cs" />
|
||||||
|
<Compile Include="Core\Inspectors\Reflection\CacheObject\CacheProperty.cs" />
|
||||||
|
<Compile Include="Core\Inspectors\Reflection\CacheObject\CacheObjectBase.cs" />
|
||||||
|
<Compile Include="Core\Config\ExplorerConfig.cs" />
|
||||||
<Compile Include="ExplorerCore.cs" />
|
<Compile Include="ExplorerCore.cs" />
|
||||||
<Compile Include="Loader\ExplorerBepIn5Plugin.cs" />
|
<Compile Include="Loader\ExplorerBepIn5Plugin.cs" />
|
||||||
<Compile Include="Loader\ExplorerMelonMod.cs" />
|
<Compile Include="Loader\ExplorerMelonMod.cs" />
|
||||||
<Compile Include="Helpers\ReflectionHelpers.cs" />
|
<Compile Include="Core\ReflectionUtility.cs" />
|
||||||
<Compile Include="Helpers\UnityHelpers.cs" />
|
<Compile Include="Core\Unity\UnityHelper.cs" />
|
||||||
<Compile Include="Inspectors\GameObjects\ChildList.cs" />
|
<Compile Include="UI\Main\Home\Inspectors\GameObjects\ChildList.cs" />
|
||||||
<Compile Include="Inspectors\GameObjects\ComponentList.cs" />
|
<Compile Include="UI\Main\Home\Inspectors\GameObjects\ComponentList.cs" />
|
||||||
<Compile Include="Inspectors\GameObjects\GameObjectControls.cs" />
|
<Compile Include="UI\Main\Home\Inspectors\GameObjects\GameObjectControls.cs" />
|
||||||
<Compile Include="Inspectors\Reflection\InteractiveValue\InteractiveBool.cs" />
|
<Compile Include="Core\Inspectors\Reflection\InteractiveValue\InteractiveBool.cs" />
|
||||||
<Compile Include="Inspectors\Reflection\InteractiveValue\InteractiveDictionary.cs" />
|
<Compile Include="Core\Inspectors\Reflection\InteractiveValue\InteractiveDictionary.cs" />
|
||||||
<Compile Include="Inspectors\Reflection\InteractiveValue\InteractiveEnum.cs" />
|
<Compile Include="Core\Inspectors\Reflection\InteractiveValue\InteractiveEnum.cs" />
|
||||||
<Compile Include="Inspectors\Reflection\InteractiveValue\InteractiveEnumerable.cs" />
|
<Compile Include="Core\Inspectors\Reflection\InteractiveValue\InteractiveEnumerable.cs" />
|
||||||
<Compile Include="Inspectors\Reflection\InteractiveValue\InteractiveFlags.cs" />
|
<Compile Include="Core\Inspectors\Reflection\InteractiveValue\InteractiveFlags.cs" />
|
||||||
<Compile Include="Inspectors\Reflection\InteractiveValue\InteractiveNumber.cs" />
|
<Compile Include="Core\Inspectors\Reflection\InteractiveValue\InteractiveNumber.cs" />
|
||||||
<Compile Include="Inspectors\Reflection\InteractiveValue\InteractiveString.cs" />
|
<Compile Include="Core\Inspectors\Reflection\InteractiveValue\InteractiveString.cs" />
|
||||||
<Compile Include="Inspectors\Reflection\InteractiveValue\InteractiveUnityStruct.cs" />
|
<Compile Include="Core\Inspectors\Reflection\InteractiveValue\InteractiveUnityStruct.cs" />
|
||||||
<Compile Include="Loader\IExplorerLoader.cs" />
|
<Compile Include="Loader\IExplorerLoader.cs" />
|
||||||
<Compile Include="Runtime\Il2Cpp\Il2CppProvider.cs" />
|
<Compile Include="Core\Runtime\Il2Cpp\Il2CppProvider.cs" />
|
||||||
<Compile Include="Runtime\RuntimeProvider.cs" />
|
<Compile Include="Core\Runtime\RuntimeProvider.cs" />
|
||||||
<Compile Include="Runtime\Mono\MonoProvider.cs" />
|
<Compile Include="Core\Runtime\Mono\MonoProvider.cs" />
|
||||||
<Compile Include="UI\ForceUnlockCursor.cs" />
|
<Compile Include="Core\Search\ChildFilter.cs" />
|
||||||
<Compile Include="Input\IHandleInput.cs" />
|
<Compile Include="Core\Search\SceneFilter.cs" />
|
||||||
<Compile Include="Tests\Tests.cs" />
|
<Compile Include="Core\Search\SearchContext.cs" />
|
||||||
<Compile Include="Input\InputManager.cs" />
|
<Compile Include="Core\Search\SearchProvider.cs" />
|
||||||
<Compile Include="Input\InputSystem.cs" />
|
<Compile Include="UI\Main\Home\InspectorManagerUI.cs" />
|
||||||
<Compile Include="Input\LegacyInput.cs" />
|
<Compile Include="UI\Main\Home\Inspectors\GameObjects\GameObjectInspectorUI.cs" />
|
||||||
<Compile Include="Input\NoInput.cs" />
|
<Compile Include="UI\Main\Home\Inspectors\InspectorBaseUI.cs" />
|
||||||
<Compile Include="UI\Modules\DebugConsole.cs" />
|
<Compile Include="UI\Main\Home\Inspectors\Reflection\InstanceInspectorUI.cs" />
|
||||||
<Compile Include="Inspectors\InspectorManager.cs" />
|
<Compile Include="UI\Main\Home\Inspectors\MouseInspectorUI.cs" />
|
||||||
<Compile Include="Inspectors\Reflection\ReflectionInspector.cs" />
|
<Compile Include="UI\Main\Home\Inspectors\Reflection\ReflectionInspectorUI.cs" />
|
||||||
<Compile Include="UI\MainMenu.cs" />
|
<Compile Include="UI\Main\Home\SceneExplorerUI.cs" />
|
||||||
<Compile Include="UI\Modules\CSConsolePage.cs" />
|
<Compile Include="UI\Utility\CursorUnlocker.cs" />
|
||||||
<Compile Include="CSConsole\AutoCompleter.cs" />
|
<Compile Include="Core\Input\IHandleInput.cs" />
|
||||||
<Compile Include="CSConsole\CodeEditor.cs" />
|
<Compile Include="Core\Tests\Tests.cs" />
|
||||||
<Compile Include="CSConsole\Lexer\CommentMatch.cs" />
|
<Compile Include="Core\Input\InputManager.cs" />
|
||||||
<Compile Include="CSConsole\CSharpLexer.cs" />
|
<Compile Include="Core\Input\InputSystem.cs" />
|
||||||
<Compile Include="CSConsole\Lexer\KeywordMatch.cs" />
|
<Compile Include="Core\Input\LegacyInput.cs" />
|
||||||
<Compile Include="CSConsole\Lexer\StringMatch.cs" />
|
<Compile Include="Core\Input\NoInput.cs" />
|
||||||
<Compile Include="CSConsole\Lexer\Matcher.cs" />
|
<Compile Include="UI\Main\DebugConsole.cs" />
|
||||||
<Compile Include="CSConsole\Lexer\NumberMatch.cs" />
|
<Compile Include="Core\InspectorManager.cs" />
|
||||||
<Compile Include="CSConsole\Lexer\SymbolMatch.cs" />
|
<Compile Include="Core\Inspectors\Reflection\ReflectionInspector.cs" />
|
||||||
<Compile Include="CSConsole\Suggestion.cs" />
|
<Compile Include="UI\Main\MainMenu.cs" />
|
||||||
<Compile Include="CSConsole\ScriptEvaluator.cs" />
|
<Compile Include="UI\Main\CSConsole\CSharpConsole.cs" />
|
||||||
<Compile Include="CSConsole\ScriptInteraction.cs" />
|
<Compile Include="UI\Main\CSConsole\AutoCompleter.cs" />
|
||||||
<Compile Include="UI\Modules\HomePage.cs" />
|
<Compile Include="UI\Main\CSConsole\Lexer\CommentMatch.cs" />
|
||||||
<Compile Include="Inspectors\GameObjects\GameObjectInspector.cs" />
|
<Compile Include="UI\Main\CSConsole\CSLexerHighlighter.cs" />
|
||||||
<Compile Include="Inspectors\InspectorBase.cs" />
|
<Compile Include="UI\Main\CSConsole\Lexer\KeywordMatch.cs" />
|
||||||
<Compile Include="Inspectors\Reflection\InstanceInspector.cs" />
|
<Compile Include="UI\Main\CSConsole\Lexer\StringMatch.cs" />
|
||||||
<Compile Include="Inspectors\Reflection\StaticInspector.cs" />
|
<Compile Include="UI\Main\CSConsole\Lexer\Matcher.cs" />
|
||||||
<Compile Include="UI\Modules\OptionsPage.cs" />
|
<Compile Include="UI\Main\CSConsole\Lexer\NumberMatch.cs" />
|
||||||
<Compile Include="Inspectors\SceneExplorer.cs" />
|
<Compile Include="UI\Main\CSConsole\Lexer\SymbolMatch.cs" />
|
||||||
<Compile Include="UI\Modules\SearchPage.cs" />
|
<Compile Include="Core\CSharp\Suggestion.cs" />
|
||||||
<Compile Include="UI\PanelDragger.cs" />
|
<Compile Include="Core\CSharp\ScriptEvaluator.cs" />
|
||||||
<Compile Include="Inspectors\Reflection\InteractiveValue\InteractiveValue.cs" />
|
<Compile Include="Core\CSharp\ScriptInteraction.cs" />
|
||||||
<Compile Include="UI\Shared\InputFieldScroller.cs" />
|
<Compile Include="UI\Main\Home\HomePage.cs" />
|
||||||
<Compile Include="UI\Shared\ScrollRectEx.cs" />
|
<Compile Include="Core\Inspectors\GameObjects\GameObjectInspector.cs" />
|
||||||
<Compile Include="UI\Shared\SliderScrollbar.cs" />
|
<Compile Include="Core\Inspectors\InspectorBase.cs" />
|
||||||
<Compile Include="UI\Shared\PageHandler.cs" />
|
<Compile Include="Core\Inspectors\Reflection\InstanceInspector.cs" />
|
||||||
<Compile Include="UI\UISyntaxHighlight.cs" />
|
<Compile Include="Core\Inspectors\Reflection\StaticInspector.cs" />
|
||||||
|
<Compile Include="UI\Main\BaseMenuPage.cs" />
|
||||||
|
<Compile Include="UI\Main\Options\OptionsPage.cs" />
|
||||||
|
<Compile Include="Core\SceneExplorer.cs" />
|
||||||
|
<Compile Include="UI\Main\Search\SearchPage.cs" />
|
||||||
|
<Compile Include="UI\Main\PanelDragger.cs" />
|
||||||
|
<Compile Include="Core\Inspectors\Reflection\InteractiveValue\InteractiveValue.cs" />
|
||||||
|
<Compile Include="UI\Reusable\InputFieldScroller.cs" />
|
||||||
|
<Compile Include="UI\Reusable\SliderScrollbar.cs" />
|
||||||
|
<Compile Include="UI\Reusable\PageHandler.cs" />
|
||||||
|
<Compile Include="UI\Utility\SignatureHighlighter.cs" />
|
||||||
<Compile Include="UI\UIManager.cs" />
|
<Compile Include="UI\UIManager.cs" />
|
||||||
<Compile Include="Unstrip\AssetBundleUnstrip.cs" />
|
<Compile Include="Core\Runtime\Il2Cpp\AssetBundle.cs" />
|
||||||
<Compile Include="Unstrip\ColorUtilityUnstrip.cs" />
|
<Compile Include="Core\Unity\ColorHelper.cs" />
|
||||||
<Compile Include="Unstrip\ImageConversionUnstrip.cs" />
|
<Compile Include="Core\Runtime\Il2Cpp\ICallManager.cs" />
|
||||||
<Compile Include="Helpers\ICallHelper.cs" />
|
|
||||||
<Compile Include="Unstrip\LayerMaskUnstrip.cs" />
|
|
||||||
<Compile Include="Unstrip\ResourcesUnstrip.cs" />
|
|
||||||
<Compile Include="Unstrip\SceneUnstrip.cs" />
|
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
<Compile Include="UI\UIFactory.cs" />
|
<Compile Include="UI\UIFactory.cs" />
|
||||||
<EmbeddedResource Include="Resources\*" />
|
<EmbeddedResource Include="Resources\*" />
|
||||||
|
@ -1,82 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.IO;
|
|
||||||
using UnityExplorer.Helpers;
|
|
||||||
using UnityEngine;
|
|
||||||
#if CPP
|
|
||||||
using UnhollowerBaseLib;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace UnityExplorer.Unstrip
|
|
||||||
{
|
|
||||||
public static class ImageConversionUnstrip
|
|
||||||
{
|
|
||||||
// LoadImage helper from a filepath
|
|
||||||
|
|
||||||
public static bool LoadImage(Texture2D tex, string filePath, bool markNonReadable)
|
|
||||||
{
|
|
||||||
if (!File.Exists(filePath))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return tex.LoadImage(File.ReadAllBytes(filePath), markNonReadable);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if CPP
|
|
||||||
// byte[] ImageConversion.EncodeToPNG(this Texture2D image);
|
|
||||||
|
|
||||||
internal delegate IntPtr d_EncodeToPNG(IntPtr tex);
|
|
||||||
|
|
||||||
public static byte[] EncodeToPNG(this Texture2D tex)
|
|
||||||
{
|
|
||||||
var iCall = ICallHelper.GetICall<d_EncodeToPNG>("UnityEngine.ImageConversion::EncodeToPNG");
|
|
||||||
|
|
||||||
IntPtr ptr = iCall.Invoke(tex.Pointer);
|
|
||||||
|
|
||||||
if (ptr == IntPtr.Zero)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
return new Il2CppStructArray<byte>(ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
// bool ImageConversion.LoadImage(this Texture2D tex, byte[] data, bool markNonReadable);
|
|
||||||
|
|
||||||
internal delegate bool d_LoadImage(IntPtr tex, IntPtr data, bool markNonReadable);
|
|
||||||
|
|
||||||
public static bool LoadImage(this Texture2D tex, byte[] data, bool markNonReadable)
|
|
||||||
{
|
|
||||||
var il2cppArray = (Il2CppStructArray<byte>)data;
|
|
||||||
|
|
||||||
var iCall = ICallHelper.GetICall<d_LoadImage>("UnityEngine.ImageConversion::LoadImage");
|
|
||||||
|
|
||||||
return iCall.Invoke(tex.Pointer, il2cppArray.Pointer, markNonReadable);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sprite Sprite.Create
|
|
||||||
|
|
||||||
internal delegate IntPtr d_CreateSprite(IntPtr texture, ref Rect rect, ref Vector2 pivot, float pixelsPerUnit,
|
|
||||||
uint extrude, int meshType, ref Vector4 border, bool generateFallbackPhysicsShape);
|
|
||||||
|
|
||||||
public static Sprite CreateSprite(Texture texture, Rect rect, Vector2 pivot, float pixelsPerUnit, uint extrude, Vector4 border)
|
|
||||||
{
|
|
||||||
var iCall = ICallHelper.GetICall<d_CreateSprite>("UnityEngine.Sprite::CreateSprite_Injected");
|
|
||||||
|
|
||||||
var ptr = iCall.Invoke(texture.Pointer, ref rect, ref pivot, pixelsPerUnit, extrude, 1, ref border, false);
|
|
||||||
|
|
||||||
if (ptr == IntPtr.Zero)
|
|
||||||
return null;
|
|
||||||
else
|
|
||||||
return new Sprite(ptr);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Simpler CreateSprite helper
|
|
||||||
|
|
||||||
public static Sprite CreateSprite(Texture2D texture)
|
|
||||||
{
|
|
||||||
#if CPP
|
|
||||||
return CreateSprite(texture, new Rect(0, 0, texture.width, texture.height), Vector2.zero, 100f, 0u, Vector4.zero);
|
|
||||||
#else
|
|
||||||
return Sprite.Create(texture, new Rect(0, 0, texture.width, texture.height), Vector2.zero);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,24 +0,0 @@
|
|||||||
using System;
|
|
||||||
using UnityExplorer.Helpers;
|
|
||||||
using UnityEngine;
|
|
||||||
#if CPP
|
|
||||||
using UnhollowerBaseLib;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace UnityExplorer.Unstrip
|
|
||||||
{
|
|
||||||
public static class LayerMaskUnstrip
|
|
||||||
{
|
|
||||||
#if CPP
|
|
||||||
internal delegate IntPtr d_LayerToName(int layer);
|
|
||||||
|
|
||||||
public static string LayerToName(int layer)
|
|
||||||
{
|
|
||||||
var iCall = ICallHelper.GetICall<d_LayerToName>("UnityEngine.LayerMask::LayerToName");
|
|
||||||
return IL2CPP.Il2CppStringToManaged(iCall.Invoke(layer));
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
public static string LayerToName(int layer) => LayerMask.LayerToName(layer);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,29 +0,0 @@
|
|||||||
using System;
|
|
||||||
using Mono.CSharp;
|
|
||||||
using UnityExplorer.Helpers;
|
|
||||||
#if CPP
|
|
||||||
using UnhollowerBaseLib;
|
|
||||||
using UnhollowerRuntimeLib;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace UnityExplorer.Unstrip
|
|
||||||
{
|
|
||||||
public class ResourcesUnstrip
|
|
||||||
{
|
|
||||||
public static UnityEngine.Object[] FindObjectsOfTypeAll(Type type)
|
|
||||||
{
|
|
||||||
#if MONO
|
|
||||||
return UnityEngine.Resources.FindObjectsOfTypeAll(type);
|
|
||||||
#else
|
|
||||||
var iCall = ICallHelper.GetICall<d_FindObjectsOfTypeAll>("UnityEngine.Resources::FindObjectsOfTypeAll");
|
|
||||||
var cppType = Il2CppType.From(type);
|
|
||||||
|
|
||||||
return new Il2CppReferenceArray<UnityEngine.Object>(iCall.Invoke(cppType.Pointer));
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
#if CPP
|
|
||||||
internal delegate IntPtr d_FindObjectsOfTypeAll(IntPtr type);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,64 +0,0 @@
|
|||||||
using System;
|
|
||||||
using UnityExplorer.Helpers;
|
|
||||||
using UnityEngine;
|
|
||||||
using UnityEngine.SceneManagement;
|
|
||||||
using UnityExplorer.Inspectors;
|
|
||||||
using System.Reflection;
|
|
||||||
|
|
||||||
namespace UnityExplorer.Unstrip
|
|
||||||
{
|
|
||||||
public static class SceneUnstrip
|
|
||||||
{
|
|
||||||
#if MONO
|
|
||||||
private static readonly FieldInfo fi_Scene_handle = typeof(Scene).GetField("m_Handle", ReflectionHelpers.CommonFlags);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
public static int GetHandle(this Scene scene)
|
|
||||||
{
|
|
||||||
#if CPP
|
|
||||||
return scene.handle;
|
|
||||||
#else
|
|
||||||
return (int)fi_Scene_handle.GetValue(scene);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
#if CPP
|
|
||||||
//Scene.GetRootGameObjects();
|
|
||||||
|
|
||||||
internal delegate void d_GetRootGameObjects(int handle, IntPtr list);
|
|
||||||
|
|
||||||
public static GameObject[] GetRootGameObjects(Scene scene) => GetRootGameObjects(scene.handle);
|
|
||||||
|
|
||||||
public static GameObject[] GetRootGameObjects(int handle)
|
|
||||||
{
|
|
||||||
if (handle == -1)
|
|
||||||
return new GameObject[0];
|
|
||||||
|
|
||||||
int count = GetRootCount(handle);
|
|
||||||
|
|
||||||
if (count < 1)
|
|
||||||
return new GameObject[0];
|
|
||||||
|
|
||||||
var list = new Il2CppSystem.Collections.Generic.List<GameObject>(count);
|
|
||||||
|
|
||||||
var iCall = ICallHelper.GetICall<d_GetRootGameObjects>("UnityEngine.SceneManagement.Scene::GetRootGameObjectsInternal");
|
|
||||||
|
|
||||||
iCall.Invoke(handle, list.Pointer);
|
|
||||||
|
|
||||||
return list.ToArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
//Scene.rootCount;
|
|
||||||
|
|
||||||
internal delegate int d_GetRootCountInternal(int handle);
|
|
||||||
|
|
||||||
public static int GetRootCount(Scene scene) => GetRootCount(scene.handle);
|
|
||||||
|
|
||||||
public static int GetRootCount(int handle)
|
|
||||||
{
|
|
||||||
return ICallHelper.GetICall<d_GetRootCountInternal>("UnityEngine.SceneManagement.Scene::GetRootCountInternal")
|
|
||||||
.Invoke(handle);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
Reference in New Issue
Block a user