Compare commits

..

8 Commits
3.0.1 ... 3.0.4

Author SHA1 Message Date
cfa4b12039 3.0.4
see release notes
2020-11-23 18:23:25 +11:00
c7ccdf387c update version 2020-11-22 18:23:07 +11:00
bb46d77a02 3.0.3
* Fixed not being able to set values on Enums
* [MONO] Fixed an issue where GameObjects in no scene (a Resource/Asset) would display nothing for their scene name, instead of "None (Resource/Asset)".
* Some UI layout cleanups and fixes, the Child/Component lists on the GameObject inspector should now expand to fill available height.
2020-11-22 18:22:57 +11:00
c38155ab04 Fix for InputSystem in 3.0.0 (temp fix for il2cpp) 2020-11-20 17:12:40 +11:00
97dbecaa2a Made instance inspector helper (owner gameobject/name), force loading unhollowed Assembly-CSharp on game start 2020-11-19 16:47:18 +11:00
e77e4cce07 fix release links 2020-11-19 01:41:11 +11:00
dcf0bdce48 disabling EventSystem.current patch for bepinex il2cpp as its causing a crash in some games 2020-11-19 00:55:17 +11:00
2a3df5de9d cleanup CacheMembers a bit 2020-11-17 23:26:22 +11:00
32 changed files with 763 additions and 462 deletions

View File

@ -25,8 +25,8 @@
| Mod Loader | IL2CPP | Mono | | Mod Loader | IL2CPP | Mono |
| ----------- | ------ | ---- | | ----------- | ------ | ---- |
| [MelonLoader](https://github.com/HerpDerpinstine/MelonLoader) | ✔️ [link](https://github.com/sinai-dev/Explorer/releases/latest/download/Explorer.MelonLoader.Il2Cpp.zip) | ✔️ [link](https://github.com/sinai-dev/Explorer/releases/latest/download/Explorer.MelonLoader.Mono.zip) | | [MelonLoader](https://github.com/HerpDerpinstine/MelonLoader) | ✔️ [link](https://github.com/sinai-dev/UnityExplorer/releases/latest/download/UnityExplorer.MelonLoader.Il2Cpp.zip) | ✔️ [link](https://github.com/sinai-dev/UnityExplorer/releases/latest/download/UnityExplorer.MelonLoader.Mono.zip) |
| [BepInEx](https://github.com/BepInEx/BepInEx) | ✔️ [link](https://github.com/sinai-dev/Explorer/releases/latest/download/Explorer.BepInEx.Il2Cpp.zip) | ✔️ [link](https://github.com/sinai-dev/Explorer/releases/latest/download/Explorer.BepInEx.Mono.zip) | | [BepInEx](https://github.com/BepInEx/BepInEx) | ✔️ [link](https://github.com/sinai-dev/UnityExplorer/releases/latest/download/UnityExplorer.BepInEx.Il2Cpp.zip) | ✔️ [link](https://github.com/sinai-dev/UnityExplorer/releases/latest/download/UnityExplorer.BepInEx.Mono.zip) |
<b>IL2CPP Issues:</b> <b>IL2CPP Issues:</b>
* Some methods may still fail with a `MissingMethodException`, please let me know if you experience this (with full debug log please). * Some methods may still fail with a `MissingMethodException`, please let me know if you experience this (with full debug log please).

View File

@ -1,20 +1,22 @@
using System; using System;
using System.IO;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityExplorer.Config; using UnityExplorer.Config;
using UnityExplorer.Input; using UnityExplorer.Input;
using UnityExplorer.Inspectors;
using UnityExplorer.UI; using UnityExplorer.UI;
using UnityExplorer.UI.Modules; using UnityExplorer.UI.Modules;
using UnityEngine; #if CPP
using UnityExplorer.Inspectors; using UnityExplorer.Helpers;
using System.IO; #endif
using UnityExplorer.Unstrip;
using UnityEngine.SceneManagement;
namespace UnityExplorer namespace UnityExplorer
{ {
public class ExplorerCore public class ExplorerCore
{ {
public const string NAME = "UnityExplorer"; public const string NAME = "UnityExplorer";
public const string VERSION = "3.0.1"; public const string VERSION = "3.0.4";
public const string AUTHOR = "Sinai"; public const string AUTHOR = "Sinai";
public const string GUID = "com.sinai.unityexplorer"; public const string GUID = "com.sinai.unityexplorer";
public const string EXPLORER_FOLDER = @"Mods\UnityExplorer"; public const string EXPLORER_FOLDER = @"Mods\UnityExplorer";
@ -41,6 +43,10 @@ namespace UnityExplorer
Instance = this; Instance = this;
#if CPP
ReflectionHelpers.TryLoadGameModules();
#endif
if (!Directory.Exists(EXPLORER_FOLDER)) if (!Directory.Exists(EXPLORER_FOLDER))
Directory.CreateDirectory(EXPLORER_FOLDER); Directory.CreateDirectory(EXPLORER_FOLDER);

View File

@ -105,21 +105,19 @@ namespace UnityExplorer.Helpers
return getType; return getType;
} }
private static readonly Dictionary<Type, IntPtr> ClassPointers = new Dictionary<Type, IntPtr>(); private static readonly Dictionary<Type, IntPtr> CppClassPointers = new Dictionary<Type, IntPtr>();
public static object Il2CppCast(this object obj, Type castTo) public static object Il2CppCast(this object obj, Type castTo)
{ {
if (!(obj is Il2CppSystem.Object ilObj)) if (!(obj is Il2CppSystem.Object ilObj))
{
return obj; return obj;
}
if (!Il2CppTypeNotNull(castTo, out IntPtr castToPtr)) if (!Il2CppTypeNotNull(castTo, out IntPtr castToPtr))
return obj; return obj;
IntPtr classPtr = il2cpp_object_get_class(ilObj.Pointer); IntPtr castFromPtr = il2cpp_object_get_class(ilObj.Pointer);
if (!il2cpp_class_is_assignable_from(castToPtr, classPtr)) if (!il2cpp_class_is_assignable_from(castToPtr, castFromPtr))
return obj; return obj;
if (RuntimeSpecificsStore.IsInjected(castToPtr)) if (RuntimeSpecificsStore.IsInjected(castToPtr))
@ -128,24 +126,21 @@ namespace UnityExplorer.Helpers
return Activator.CreateInstance(castTo, ilObj.Pointer); return Activator.CreateInstance(castTo, ilObj.Pointer);
} }
public static bool Il2CppTypeNotNull(Type type) public static bool Il2CppTypeNotNull(Type type) => Il2CppTypeNotNull(type, out _);
{
return Il2CppTypeNotNull(type, out _);
}
public static bool Il2CppTypeNotNull(Type type, out IntPtr il2cppPtr) public static bool Il2CppTypeNotNull(Type type, out IntPtr il2cppPtr)
{ {
if (!ClassPointers.ContainsKey(type)) if (!CppClassPointers.ContainsKey(type))
{ {
il2cppPtr = (IntPtr)typeof(Il2CppClassPointerStore<>) il2cppPtr = (IntPtr)typeof(Il2CppClassPointerStore<>)
.MakeGenericType(new Type[] { type }) .MakeGenericType(new Type[] { type })
.GetField("NativeClassPtr", BF.Public | BF.Static) .GetField("NativeClassPtr", BF.Public | BF.Static)
.GetValue(null); .GetValue(null);
ClassPointers.Add(type, il2cppPtr); CppClassPointers.Add(type, il2cppPtr);
} }
else else
il2cppPtr = ClassPointers[type]; il2cppPtr = CppClassPointers[type];
return il2cppPtr != IntPtr.Zero; return il2cppPtr != IntPtr.Zero;
} }
@ -181,31 +176,44 @@ namespace UnityExplorer.Helpers
} }
} }
#if CPP
internal static void TryLoadGameModules()
{
LoadModule("Assembly-CSharp");
LoadModule("Assembly-CSharp-firstpass");
}
public static bool LoadModule(string module) public static bool LoadModule(string module)
{ {
#if CPP
#if ML #if ML
string path = $@"MelonLoader\Managed\{module}.dll"; var path = $@"MelonLoader\Managed\{module}.dll";
#else #else
var path = $@"BepInEx\unhollowed\{module}.dll"; var path = $@"BepInEx\unhollowed\{module}.dll";
#endif #endif
if (!File.Exists(path))
{ return LoadModuleInternal(path);
}
internal static bool LoadModuleInternal(string fullPath)
{
if (!File.Exists(fullPath))
return false; return false;
}
try try
{ {
Assembly.Load(File.ReadAllBytes(path)); Assembly.Load(File.ReadAllBytes(fullPath));
return true; return true;
} }
catch (Exception e) catch (Exception e)
{ {
ExplorerCore.Log(e.GetType() + ", " + e.Message); Console.WriteLine(e.GetType() + ", " + e.Message);
} }
#endif
return false; return false;
} }
#else
public static bool LoadModule(string module) => true;
#endif
public static bool IsEnumerable(Type t) public static bool IsEnumerable(Type t)
{ {

View File

@ -35,7 +35,6 @@ namespace UnityExplorer.Helpers
} }
#endif #endif
public static bool IsReadable(this Texture2D tex) public static bool IsReadable(this Texture2D tex)
{ {
try try
@ -68,6 +67,10 @@ namespace UnityExplorer.Helpers
return _newTex; 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
@ -78,7 +81,13 @@ namespace UnityExplorer.Helpers
var rt = RenderTexture.GetTemporary(tex.width, tex.height, 0, RenderTextureFormat.ARGB32); var rt = RenderTexture.GetTemporary(tex.width, tex.height, 0, RenderTextureFormat.ARGB32);
rt.filterMode = FilterMode.Point; rt.filterMode = FilterMode.Point;
RenderTexture.active = rt; RenderTexture.active = rt;
#if MONO
Graphics.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);

View File

@ -1,4 +1,5 @@
using UnityEngine; using UnityEngine;
using UnityEngine.EventSystems;
namespace UnityExplorer.Input namespace UnityExplorer.Input
{ {
@ -11,5 +12,12 @@ namespace UnityExplorer.Input
bool GetMouseButtonDown(int btn); bool GetMouseButtonDown(int btn);
bool GetMouseButton(int btn); bool GetMouseButton(int btn);
BaseInputModule UIModule { get; }
PointerEventData InputPointerEvent { get; }
void AddUIInputModule();
void ActivateModule();
} }
} }

View File

@ -2,34 +2,26 @@
using UnityEngine; using UnityEngine;
using UnityExplorer.Helpers; using UnityExplorer.Helpers;
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using UnityEngine.EventSystems;
#if CPP #if CPP
using UnhollowerBaseLib; using UnhollowerBaseLib;
#endif #endif
namespace UnityExplorer.Input namespace UnityExplorer.Input
{ {
public enum InputType
{
InputSystem,
Legacy,
None
}
public static class InputManager public static class InputManager
{ {
public static InputType CurrentType { get; private set; }
private static IHandleInput m_inputModule; private static IHandleInput m_inputModule;
public static void Init()
{
if (InputSystem.TKeyboard != null || (ReflectionHelpers.LoadModule("Unity.InputSystem") && InputSystem.TKeyboard != null))
{
m_inputModule = new InputSystem();
}
else if (LegacyInput.TInput != null || (ReflectionHelpers.LoadModule("UnityEngine.InputLegacyModule") && LegacyInput.TInput != null))
{
m_inputModule = new LegacyInput();
}
if (m_inputModule == null)
{
ExplorerCore.LogWarning("Could not find any Input module!");
m_inputModule = new NoInput();
}
}
public static Vector3 MousePosition => m_inputModule.MousePosition; public static Vector3 MousePosition => m_inputModule.MousePosition;
public static bool GetKeyDown(KeyCode key) => m_inputModule.GetKeyDown(key); public static bool GetKeyDown(KeyCode key) => m_inputModule.GetKeyDown(key);
@ -37,5 +29,37 @@ namespace UnityExplorer.Input
public static bool GetMouseButtonDown(int btn) => m_inputModule.GetMouseButtonDown(btn); public static bool GetMouseButtonDown(int btn) => m_inputModule.GetMouseButtonDown(btn);
public static bool GetMouseButton(int btn) => m_inputModule.GetMouseButton(btn); public static bool GetMouseButton(int btn) => m_inputModule.GetMouseButton(btn);
public static BaseInputModule UIInput => m_inputModule.UIModule;
public static PointerEventData InputPointerEvent => m_inputModule.InputPointerEvent;
public static void ActivateUIModule() => m_inputModule.ActivateModule();
public static void AddUIModule()
{
m_inputModule.AddUIInputModule();
ActivateUIModule();
}
public static void Init()
{
if (InputSystem.TKeyboard != null || (ReflectionHelpers.LoadModule("Unity.InputSystem") && InputSystem.TKeyboard != null))
{
m_inputModule = new InputSystem();
CurrentType = InputType.InputSystem;
}
else if (LegacyInput.TInput != null || (ReflectionHelpers.LoadModule("UnityEngine.InputLegacyModule") && LegacyInput.TInput != null))
{
m_inputModule = new LegacyInput();
CurrentType = InputType.Legacy;
}
if (m_inputModule == null)
{
ExplorerCore.LogWarning("Could not find any Input module!");
m_inputModule = new NoInput();
CurrentType = InputType.None;
}
}
} }
} }

View File

@ -2,6 +2,9 @@
using System.Reflection; using System.Reflection;
using UnityExplorer.Helpers; using UnityExplorer.Helpers;
using UnityEngine; using UnityEngine;
using UnityEngine.EventSystems;
using UnityExplorer.UI;
using System.Collections.Generic;
namespace UnityExplorer.Input namespace UnityExplorer.Input
{ {
@ -64,24 +67,46 @@ namespace UnityExplorer.Input
private static PropertyInfo m_positionProp; private static PropertyInfo m_positionProp;
private static MethodInfo m_readVector2InputMethod; private static MethodInfo m_readVector2InputMethod;
public Vector2 MousePosition => (Vector2)m_readVector2InputMethod.Invoke(MousePositionInfo, new object[0]); public Vector2 MousePosition
public bool GetKeyDown(KeyCode key)
{ {
var parsedKey = Enum.Parse(TKey, key.ToString()); get
var actualKey = m_kbIndexer.GetValue(CurrentKeyboard, new object[] { parsedKey }); {
try
return (bool)m_btnWasPressedProp.GetValue(actualKey, null); {
return (Vector2)m_readVector2InputMethod.Invoke(MousePositionInfo, new object[0]);
}
catch
{
return Vector2.zero;
}
}
} }
public bool GetKey(KeyCode key) internal static Dictionary<KeyCode, object> ActualKeyDict = new Dictionary<KeyCode, object>();
{
var parsed = Enum.Parse(TKey, key.ToString());
var actualKey = m_kbIndexer.GetValue(CurrentKeyboard, new object[] { parsed });
return (bool)m_btnIsPressedProp.GetValue(actualKey, null); internal object GetActualKey(KeyCode key)
{
if (!ActualKeyDict.ContainsKey(key))
{
var s = key.ToString();
if (s.Contains("Control"))
s = s.Replace("Control", "Ctrl");
else if (s.Contains("Return"))
s = "Enter";
var parsed = Enum.Parse(TKey, s);
var actualKey = m_kbIndexer.GetValue(CurrentKeyboard, new object[] { parsed });
ActualKeyDict.Add(key, actualKey);
}
return ActualKeyDict[key];
} }
public bool GetKeyDown(KeyCode key) => (bool)m_btnWasPressedProp.GetValue(GetActualKey(key), null);
public bool GetKey(KeyCode key) => (bool)m_btnIsPressedProp.GetValue(GetActualKey(key), null);
public bool GetMouseButtonDown(int btn) public bool GetMouseButtonDown(int btn)
{ {
switch (btn) switch (btn)
@ -103,5 +128,44 @@ namespace UnityExplorer.Input
default: throw new NotImplementedException(); default: throw new NotImplementedException();
} }
} }
// UI Input
//public Type TInputSystemUIInputModule
// => m_tUIInputModule
// ?? (m_tUIInputModule = ReflectionHelpers.GetTypeByName("UnityEngine.InputSystem.UI.InputSystemUIInputModule"));
//internal Type m_tUIInputModule;
public BaseInputModule UIModule => null; // m_newInputModule;
//internal BaseInputModule m_newInputModule;
public PointerEventData InputPointerEvent => null;
public void AddUIInputModule()
{
// if (TInputSystemUIInputModule != null)
// {
//#if CPP
// // m_newInputModule = UIManager.CanvasRoot.AddComponent(Il2CppType.From(TInputSystemUIInputModule)).TryCast<BaseInputModule>();
//#else
// m_newInputModule = (BaseInputModule)UIManager.CanvasRoot.AddComponent(TInputSystemUIInputModule);
//#endif
// }
// else
// {
// ExplorerCore.LogWarning("New input system: Could not find type by name 'UnityEngine.InputSystem.UI.InputSystemUIInputModule'");
// }
}
public void ActivateModule()
{
//#if CPP
// // m_newInputModule.ActivateModule();
//#else
// m_newInputModule.ActivateModule();
//#endif
}
} }
} }

View File

@ -2,6 +2,8 @@
using System.Reflection; using System.Reflection;
using UnityExplorer.Helpers; using UnityExplorer.Helpers;
using UnityEngine; using UnityEngine;
using UnityEngine.EventSystems;
using UnityExplorer.UI;
namespace UnityExplorer.Input namespace UnityExplorer.Input
{ {
@ -36,5 +38,27 @@ namespace UnityExplorer.Input
public bool GetMouseButton(int btn) => (bool)m_getMouseButtonMethod.Invoke(null, new object[] { btn }); public bool GetMouseButton(int btn) => (bool)m_getMouseButtonMethod.Invoke(null, new object[] { btn });
public bool GetMouseButtonDown(int btn) => (bool)m_getMouseButtonDownMethod.Invoke(null, new object[] { btn }); public bool GetMouseButtonDown(int btn) => (bool)m_getMouseButtonDownMethod.Invoke(null, new object[] { btn });
// UI Input module
public BaseInputModule UIModule => m_inputModule;
internal StandaloneInputModule m_inputModule;
public PointerEventData InputPointerEvent =>
#if CPP
m_inputModule.m_InputPointerEvent;
#else
null;
#endif
public void AddUIInputModule()
{
m_inputModule = UIManager.CanvasRoot.gameObject.AddComponent<StandaloneInputModule>();
}
public void ActivateModule()
{
m_inputModule.ActivateModule();
}
} }
} }

View File

@ -1,4 +1,5 @@
using UnityEngine; using UnityEngine;
using UnityEngine.EventSystems;
namespace UnityExplorer.Input namespace UnityExplorer.Input
{ {
@ -13,5 +14,10 @@ namespace UnityExplorer.Input
public bool GetMouseButton(int btn) => false; public bool GetMouseButton(int btn) => false;
public bool GetMouseButtonDown(int btn) => false; public bool GetMouseButtonDown(int btn) => false;
public BaseInputModule UIModule => null;
public PointerEventData InputPointerEvent => null;
public void ActivateModule() { }
public void AddUIInputModule() { }
} }
} }

View File

@ -140,7 +140,7 @@ namespace UnityExplorer.Inspectors.GameObjects
{ {
var vertGroupObj = UIFactory.CreateVerticalGroup(parent, new Color(1, 1, 1, 0)); var vertGroupObj = UIFactory.CreateVerticalGroup(parent, new Color(1, 1, 1, 0));
var vertGroup = vertGroupObj.GetComponent<VerticalLayoutGroup>(); var vertGroup = vertGroupObj.GetComponent<VerticalLayoutGroup>();
vertGroup.childForceExpandHeight = false; vertGroup.childForceExpandHeight = true;
vertGroup.childForceExpandWidth = false; vertGroup.childForceExpandWidth = false;
vertGroup.childControlWidth = true; vertGroup.childControlWidth = true;
vertGroup.spacing = 5; vertGroup.spacing = 5;

View File

@ -136,7 +136,7 @@ namespace UnityExplorer.Inspectors.GameObjects
{ {
var vertGroupObj = UIFactory.CreateVerticalGroup(parent, new Color(1, 1, 1, 0)); var vertGroupObj = UIFactory.CreateVerticalGroup(parent, new Color(1, 1, 1, 0));
var vertGroup = vertGroupObj.GetComponent<VerticalLayoutGroup>(); var vertGroup = vertGroupObj.GetComponent<VerticalLayoutGroup>();
vertGroup.childForceExpandHeight = false; vertGroup.childForceExpandHeight = true;
vertGroup.childForceExpandWidth = false; vertGroup.childForceExpandWidth = false;
vertGroup.childControlWidth = true; vertGroup.childControlWidth = true;
vertGroup.spacing = 5; vertGroup.spacing = 5;
@ -157,6 +157,7 @@ namespace UnityExplorer.Inspectors.GameObjects
var compScrollObj = UIFactory.CreateScrollView(vertGroupObj, out s_compListContent, out SliderScrollbar scroller, new Color(0.07f, 0.07f, 0.07f)); var compScrollObj = UIFactory.CreateScrollView(vertGroupObj, out s_compListContent, out SliderScrollbar scroller, new Color(0.07f, 0.07f, 0.07f));
var contentLayout = compScrollObj.AddComponent<LayoutElement>(); var contentLayout = compScrollObj.AddComponent<LayoutElement>();
contentLayout.minHeight = 50; contentLayout.minHeight = 50;
contentLayout.flexibleHeight = 5000;
s_compListPageHandler = new PageHandler(scroller); s_compListPageHandler = new PageHandler(scroller);
s_compListPageHandler.ConstructUI(vertGroupObj); s_compListPageHandler.ConstructUI(vertGroupObj);

View File

@ -164,7 +164,7 @@ namespace UnityExplorer.Inspectors
m_layerDropdown.value = TargetGO.layer; m_layerDropdown.value = TargetGO.layer;
} }
if (m_lastScene != TargetGO.scene.name) if (string.IsNullOrEmpty(m_lastScene) || m_lastScene != TargetGO.scene.name)
{ {
m_lastScene = TargetGO.scene.name; m_lastScene = TargetGO.scene.name;
@ -217,10 +217,20 @@ namespace UnityExplorer.Inspectors
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));
var parentLayout = scrollContent.transform.parent.gameObject.AddComponent<VerticalLayoutGroup>();
parentLayout.childForceExpandWidth = true;
parentLayout.childControlWidth = true;
parentLayout.childForceExpandHeight = true;
parentLayout.childControlHeight = true;
var scrollGroup = scrollContent.GetComponent<VerticalLayoutGroup>(); var scrollGroup = scrollContent.GetComponent<VerticalLayoutGroup>();
scrollGroup.childForceExpandHeight = true; scrollGroup.childForceExpandHeight = true;
scrollGroup.childControlHeight = true; scrollGroup.childControlHeight = true;
scrollGroup.childForceExpandWidth = true;
scrollGroup.childControlWidth = true;
scrollGroup.spacing = 5; scrollGroup.spacing = 5;
var contentFitter = scrollContent.GetComponent<ContentSizeFitter>();
contentFitter.verticalFit = ContentSizeFitter.FitMode.Unconstrained;
ConstructTopArea(scrollContent); ConstructTopArea(scrollContent);
@ -230,6 +240,9 @@ namespace UnityExplorer.Inspectors
s_childList.ConstructChildList(midGroupObj); s_childList.ConstructChildList(midGroupObj);
s_compList.ConstructCompList(midGroupObj); s_compList.ConstructCompList(midGroupObj);
LayoutRebuilder.ForceRebuildLayoutImmediate(s_content.GetComponent<RectTransform>());
Canvas.ForceUpdateCanvases();
} }
private void ConstructTopArea(GameObject scrollContent) private void ConstructTopArea(GameObject scrollContent)
@ -431,11 +444,10 @@ namespace UnityExplorer.Inspectors
midGroup.childControlWidth = true; midGroup.childControlWidth = true;
midGroup.childForceExpandHeight = true; midGroup.childForceExpandHeight = true;
midGroup.childControlHeight = true; midGroup.childControlHeight = true;
var midlayout = midGroupObj.AddComponent<LayoutElement>();
midlayout.minHeight = 350; var midLayout = midGroupObj.AddComponent<LayoutElement>();
midlayout.flexibleHeight = 10000; midLayout.minHeight = 300;
midlayout.minWidth = 200; midLayout.flexibleHeight = 5000;
midlayout.flexibleWidth = 25000;
return midGroupObj; return midGroupObj;
} }

View File

@ -230,102 +230,35 @@ namespace UnityExplorer.Inspectors
invisGroup.padding.right = 2; invisGroup.padding.right = 2;
invisGroup.spacing = 10; invisGroup.spacing = 10;
// // time scale group
// var timeGroupObj = UIFactory.CreateHorizontalGroup(invisObj, new Color(1, 1, 1, 0));
// var timeGroup = timeGroupObj.GetComponent<HorizontalLayoutGroup>();
// timeGroup.childForceExpandWidth = false;
// timeGroup.childControlWidth = true;
// timeGroup.childForceExpandHeight = false;
// timeGroup.childControlHeight = true;
// timeGroup.padding.top = 2;
// timeGroup.padding.left = 5;
// timeGroup.padding.right = 2;
// timeGroup.padding.bottom = 2;
// timeGroup.spacing = 5;
// timeGroup.childAlignment = TextAnchor.MiddleCenter;
// var timeGroupLayout = timeGroupObj.AddComponent<LayoutElement>();
// timeGroupLayout.minWidth = 100;
// timeGroupLayout.flexibleWidth = 300;
// timeGroupLayout.minHeight = 25;
// timeGroupLayout.flexibleHeight = 0;
// // time scale title
// var timeTitleObj = UIFactory.CreateLabel(timeGroupObj, TextAnchor.MiddleLeft);
// var timeTitle = timeTitleObj.GetComponent<Text>();
// timeTitle.text = "Time Scale:";
// timeTitle.color = new Color(21f / 255f, 192f / 255f, 235f / 255f);
// var titleLayout = timeTitleObj.AddComponent<LayoutElement>();
// titleLayout.minHeight = 25;
// titleLayout.minWidth = 80;
// titleLayout.flexibleHeight = 0;
// timeTitle.horizontalOverflow = HorizontalWrapMode.Overflow;
// // actual active time label
// var timeLabelObj = UIFactory.CreateLabel(timeGroupObj, TextAnchor.MiddleLeft);
// var timeLabelLayout = timeLabelObj.AddComponent<LayoutElement>();
// timeLabelLayout.minWidth = 40;
// timeLabelLayout.minHeight = 25;
// timeLabelLayout.flexibleHeight = 0;
// // todo make static and update
// var s_timeText = timeLabelObj.GetComponent<Text>();
// s_timeText.text = Time.timeScale.ToString("F1");
// // time scale input
// var timeInputObj = UIFactory.CreateInputField(timeGroupObj);
// var timeInput = timeInputObj.GetComponent<InputField>();
// timeInput.characterValidation = InputField.CharacterValidation.Decimal;
// var timeInputLayout = timeInputObj.AddComponent<LayoutElement>();
// timeInputLayout.minWidth = 90;
// timeInputLayout.flexibleWidth = 0;
// timeInputLayout.minHeight = 25;
// timeInputLayout.flexibleHeight = 0;
// // time scale apply button
// var applyBtnObj = UIFactory.CreateButton(timeGroupObj);
// var applyBtn = applyBtnObj.GetComponent<Button>();
// applyBtn.onClick.AddListener(SetTimeScale);
// var applyText = applyBtnObj.GetComponentInChildren<Text>();
// applyText.text = "Apply";
// applyText.fontSize = 14;
// var applyLayout = applyBtnObj.AddComponent<LayoutElement>();
// applyLayout.minWidth = 50;
// applyLayout.minHeight = 25;
// applyLayout.flexibleHeight = 0;
// void SetTimeScale()
// {
// var scale = float.Parse(timeInput.text);
// Time.timeScale = scale;
// s_timeText.text = Time.timeScale.ToString("F1");
// }
// inspect under mouse button // inspect under mouse button
AddMouseInspectButton(topRowObj, MouseInspector.MouseInspectMode.UI);
AddMouseInspectButton(topRowObj, MouseInspector.MouseInspectMode.World);
}
private static void AddMouseInspectButton(GameObject topRowObj, MouseInspector.MouseInspectMode mode)
{
var inspectObj = UIFactory.CreateButton(topRowObj); var inspectObj = UIFactory.CreateButton(topRowObj);
var inspectLayout = inspectObj.AddComponent<LayoutElement>(); var inspectLayout = inspectObj.AddComponent<LayoutElement>();
inspectLayout.minWidth = 120; inspectLayout.minWidth = 120;
inspectLayout.flexibleWidth = 0; inspectLayout.flexibleWidth = 0;
var inspectText = inspectObj.GetComponentInChildren<Text>();
inspectText.text = "Mouse Inspect";
inspectText.fontSize = 13;
if (mode == MouseInspector.MouseInspectMode.UI)
inspectText.text += " (UI)";
var inspectBtn = inspectObj.GetComponent<Button>(); var inspectBtn = inspectObj.GetComponent<Button>();
var inspectColors = inspectBtn.colors; var inspectColors = inspectBtn.colors;
inspectColors.normalColor = new Color(0.2f, 0.2f, 0.2f); inspectColors.normalColor = new Color(0.2f, 0.2f, 0.2f);
inspectBtn.colors = inspectColors; inspectBtn.colors = inspectColors;
var inspectText = inspectObj.GetComponentInChildren<Text>();
inspectText.text = "Mouse Inspect";
inspectText.fontSize = 13;
inspectBtn.onClick.AddListener(OnInspectMouseClicked); inspectBtn.onClick.AddListener(OnInspectMouseClicked);
void OnInspectMouseClicked() void OnInspectMouseClicked()
{ {
MouseInspector.Mode = mode;
MouseInspector.StartInspect(); MouseInspector.StartInspect();
} }
} }

View File

@ -3,18 +3,27 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using UnityEngine; using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI; using UnityEngine.UI;
using UnityExplorer.Helpers; using UnityExplorer.Helpers;
using UnityExplorer.Input; using UnityExplorer.Input;
using UnityExplorer.UI; using UnityExplorer.UI;
using UnityExplorer.Unstrip;
namespace UnityExplorer.Inspectors namespace UnityExplorer.Inspectors
{ {
public class MouseInspector public class MouseInspector
{ {
public enum MouseInspectMode
{
World,
UI
}
public static bool Enabled { get; set; } public static bool Enabled { get; set; }
//internal static Text s_objUnderMouseName; public static MouseInspectMode Mode { get; set; }
internal static Text s_objNameLabel; internal static Text s_objNameLabel;
internal static Text s_objPathLabel; internal static Text s_objPathLabel;
internal static Text s_mousePosLabel; internal static Text s_mousePosLabel;
@ -29,6 +38,18 @@ namespace UnityExplorer.Inspectors
Enabled = true; Enabled = true;
MainMenu.Instance.MainPanel.SetActive(false); MainMenu.Instance.MainPanel.SetActive(false);
s_UIContent.SetActive(true); s_UIContent.SetActive(true);
// recache Graphic Raycasters each time we start
var casters = ResourcesUnstrip.FindObjectsOfTypeAll(typeof(GraphicRaycaster));
m_gCasters = new GraphicRaycaster[casters.Length];
for (int i = 0; i < casters.Length; i++)
{
#if CPP
m_gCasters[i] = casters[i].TryCast<GraphicRaycaster>();
#else
m_gCasters[i] = casters[i] as GraphicRaycaster;
#endif
}
} }
public static void StopInspect() public static void StopInspect()
@ -40,49 +61,68 @@ namespace UnityExplorer.Inspectors
ClearHitData(); ClearHitData();
} }
internal static GraphicRaycaster[] m_gCasters;
public static void UpdateInspect() public static void UpdateInspect()
{ {
if (InputManager.GetKeyDown(KeyCode.Escape)) if (InputManager.GetKeyDown(KeyCode.Escape))
{ {
StopInspect(); StopInspect();
return;
} }
var mousePos = InputManager.MousePosition; var mousePos = InputManager.MousePosition;
if (mousePos != s_lastMousePos) if (mousePos != s_lastMousePos)
{ UpdatePosition(mousePos);
s_lastMousePos = mousePos;
var inversePos = UIManager.CanvasRoot.transform.InverseTransformPoint(mousePos);
s_mousePosLabel.text = $"<color=grey>Mouse Position:</color> {((Vector2)InputManager.MousePosition).ToString()}";
float yFix = mousePos.y < 120 ? 80 : -80;
s_UIContent.transform.localPosition = new Vector3(inversePos.x, inversePos.y + yFix, 0);
}
if (!UnityHelpers.MainCamera) if (!UnityHelpers.MainCamera)
return; return;
// actual inspect raycast // actual inspect raycast
var ray = UnityHelpers.MainCamera.ScreenPointToRay(mousePos);
if (Physics.Raycast(ray, out RaycastHit hit, 1000f)) switch (Mode)
{ {
var obj = hit.transform.gameObject; case MouseInspectMode.UI:
RaycastUI(mousePos); break;
case MouseInspectMode.World:
RaycastWorld(mousePos); break;
}
}
if (obj != s_lastHit) internal static void OnHitGameObject(GameObject obj)
{ {
s_lastHit = obj; if (obj != s_lastHit)
s_objNameLabel.text = $"<b>Click to Inspect:</b> <color=cyan>{obj.name}</color>"; {
s_objPathLabel.text = $"Path: {obj.transform.GetTransformPath(true)}"; s_lastHit = obj;
} s_objNameLabel.text = $"<b>Click to Inspect:</b> <color=cyan>{obj.name}</color>";
s_objPathLabel.text = $"Path: {obj.transform.GetTransformPath(true)}";
}
if (InputManager.GetMouseButtonDown(0)) if (InputManager.GetMouseButtonDown(0))
{
StopInspect();
InspectorManager.Instance.Inspect(obj);
}
}
internal static void RaycastWorld(Vector2 mousePos)
{
var ray = UnityHelpers.MainCamera.ScreenPointToRay(mousePos);
var casts = Physics.RaycastAll(ray, 1000f);
if (casts.Length > 0)
{
foreach (var cast in casts)
{ {
StopInspect(); if (cast.transform)
InspectorManager.Instance.Inspect(obj); {
var obj = cast.transform.gameObject;
OnHitGameObject(obj);
break;
}
} }
} }
else else
@ -92,6 +132,56 @@ namespace UnityExplorer.Inspectors
} }
} }
internal static void RaycastUI(Vector2 mousePos)
{
var ped = new PointerEventData(null)
{
position = mousePos
};
#if MONO
var list = new List<RaycastResult>();
#else
var list = new Il2CppSystem.Collections.Generic.List<RaycastResult>();
#endif
foreach (var gr in m_gCasters)
{
gr.Raycast(ped, list);
if (list.Count > 0)
{
foreach (var hit in list)
{
if (hit.gameObject)
{
var obj = hit.gameObject;
OnHitGameObject(obj);
break;
}
}
}
else
{
if (s_lastHit)
ClearHitData();
}
}
}
internal static void UpdatePosition(Vector2 mousePos)
{
s_lastMousePos = mousePos;
var inversePos = UIManager.CanvasRoot.transform.InverseTransformPoint(mousePos);
s_mousePosLabel.text = $"<color=grey>Mouse Position:</color> {mousePos.ToString()}";
float yFix = mousePos.y < 120 ? 80 : -80;
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;
@ -99,7 +189,7 @@ namespace UnityExplorer.Inspectors
s_objPathLabel.text = ""; s_objPathLabel.text = "";
} }
#region UI Construction #region UI Construction
internal static void ConstructUI() internal static void ConstructUI()
{ {
@ -112,7 +202,10 @@ namespace UnityExplorer.Inspectors
baseRect.anchorMin = half; baseRect.anchorMin = half;
baseRect.anchorMax = half; baseRect.anchorMax = half;
baseRect.pivot = half; baseRect.pivot = half;
baseRect.sizeDelta = new Vector2(700, 100); baseRect.sizeDelta = new Vector2(700, 150);
var group = content.GetComponent<VerticalLayoutGroup>();
group.childForceExpandHeight = true;
// Title text // Title text
@ -131,13 +224,16 @@ namespace UnityExplorer.Inspectors
var pathLabelObj = UIFactory.CreateLabel(content, TextAnchor.MiddleLeft); var pathLabelObj = UIFactory.CreateLabel(content, TextAnchor.MiddleLeft);
s_objPathLabel = pathLabelObj.GetComponent<Text>(); s_objPathLabel = pathLabelObj.GetComponent<Text>();
s_objPathLabel.color = Color.grey;
s_objPathLabel.fontStyle = FontStyle.Italic; s_objPathLabel.fontStyle = FontStyle.Italic;
s_objPathLabel.horizontalOverflow = HorizontalWrapMode.Overflow; s_objPathLabel.horizontalOverflow = HorizontalWrapMode.Wrap;
var pathLayout = pathLabelObj.AddComponent<LayoutElement>();
pathLayout.minHeight = 75;
pathLayout.flexibleHeight = 0;
s_UIContent.SetActive(false); s_UIContent.SetActive(false);
} }
#endregion #endregion
} }
} }

View File

@ -5,6 +5,7 @@ using System.Text;
using System.Reflection; using System.Reflection;
using UnityExplorer.UI; using UnityExplorer.UI;
using UnityExplorer.Helpers; using UnityExplorer.Helpers;
using UnityEngine;
namespace UnityExplorer.Inspectors.Reflection namespace UnityExplorer.Inspectors.Reflection
{ {
@ -14,7 +15,7 @@ namespace UnityExplorer.Inspectors.Reflection
public override Type FallbackType => (MemInfo as FieldInfo).FieldType; public override Type FallbackType => (MemInfo as FieldInfo).FieldType;
public CacheField(FieldInfo fieldInfo, object declaringInstance) : base(fieldInfo, declaringInstance) public CacheField(FieldInfo fieldInfo, object declaringInstance, GameObject parent) : base(fieldInfo, declaringInstance, parent)
{ {
CreateIValue(null, fieldInfo.FieldType); CreateIValue(null, fieldInfo.FieldType);
} }

View File

@ -43,11 +43,12 @@ namespace UnityExplorer.Inspectors.Reflection
public string RichTextName => m_richTextName ?? GetRichTextName(); public string RichTextName => m_richTextName ?? GetRichTextName();
private string m_richTextName; private string m_richTextName;
public CacheMember(MemberInfo memberInfo, object declaringInstance) public CacheMember(MemberInfo memberInfo, object declaringInstance, GameObject parentContent)
{ {
MemInfo = memberInfo; MemInfo = memberInfo;
DeclaringType = memberInfo.DeclaringType; DeclaringType = memberInfo.DeclaringType;
DeclaringInstance = declaringInstance; DeclaringInstance = declaringInstance;
this.m_parentContent = parentContent;
#if CPP #if CPP
if (DeclaringInstance != null) if (DeclaringInstance != null)
DeclaringInstance = DeclaringInstance.Il2CppCast(DeclaringType); DeclaringInstance = DeclaringInstance.Il2CppCast(DeclaringType);

View File

@ -26,7 +26,7 @@ namespace UnityExplorer.Inspectors.Reflection
public string[] m_genericArgInput = new string[0]; public string[] m_genericArgInput = new string[0];
public CacheMethod(MethodInfo methodInfo, object declaringInstance) : base(methodInfo, declaringInstance) public CacheMethod(MethodInfo methodInfo, object declaringInstance, GameObject parent) : base(methodInfo, declaringInstance, parent)
{ {
GenericArgs = methodInfo.GetGenericArguments(); GenericArgs = methodInfo.GetGenericArguments();

View File

@ -5,6 +5,7 @@ using System.Text;
using System.Reflection; using System.Reflection;
using UnityExplorer.UI; using UnityExplorer.UI;
using UnityExplorer.Helpers; using UnityExplorer.Helpers;
using UnityEngine;
namespace UnityExplorer.Inspectors.Reflection namespace UnityExplorer.Inspectors.Reflection
{ {
@ -14,7 +15,7 @@ namespace UnityExplorer.Inspectors.Reflection
public override bool IsStatic => (MemInfo as PropertyInfo).GetAccessors(true)[0].IsStatic; public override bool IsStatic => (MemInfo as PropertyInfo).GetAccessors(true)[0].IsStatic;
public CacheProperty(PropertyInfo propertyInfo, object declaringInstance) : base(propertyInfo, declaringInstance) public CacheProperty(PropertyInfo propertyInfo, object declaringInstance, GameObject parent) : base(propertyInfo, declaringInstance, parent)
{ {
this.m_arguments = propertyInfo.GetIndexParameters(); this.m_arguments = propertyInfo.GetIndexParameters();
this.m_argumentInput = new string[m_arguments.Length]; this.m_argumentInput = new string[m_arguments.Length];

View File

@ -45,19 +45,95 @@ namespace UnityExplorer.Inspectors.Reflection
public void ConstructInstanceHelpers() public void ConstructInstanceHelpers()
{ {
if (!typeof(Component).IsAssignableFrom(m_targetType) && !typeof(UnityEngine.Object).IsAssignableFrom(m_targetType))
return;
var rowObj = UIFactory.CreateHorizontalGroup(Content, new Color(0.1f, 0.1f, 0.1f));
var rowGroup = rowObj.GetComponent<HorizontalLayoutGroup>();
rowGroup.childForceExpandWidth = true;
rowGroup.childControlWidth = true;
rowGroup.spacing = 5;
rowGroup.padding.top = 2;
rowGroup.padding.bottom = 2;
rowGroup.padding.right = 2;
rowGroup.padding.left = 2;
var rowLayout = rowObj.AddComponent<LayoutElement>();
rowLayout.minHeight = 25;
rowLayout.flexibleWidth = 5000;
if (typeof(Component).IsAssignableFrom(m_targetType))
{
ConstructCompHelper(rowObj);
}
ConstructUObjHelper(rowObj);
// WIP // WIP
//if (m_targetType == typeof(Texture2D)) //if (m_targetType == typeof(Texture2D))
// ConstructTextureHelper(); // ConstructTextureHelper();
}
// todo other helpers internal void ConstructCompHelper(GameObject rowObj)
{
var labelObj = UIFactory.CreateLabel(rowObj, TextAnchor.MiddleLeft);
var labelLayout = labelObj.AddComponent<LayoutElement>();
labelLayout.minWidth = 90;
labelLayout.minHeight = 25;
labelLayout.flexibleWidth = 0;
var labelText = labelObj.GetComponent<Text>();
labelText.text = "GameObject:";
//if (typeof(Component).IsAssignableFrom(m_targetType)) #if MONO
//{ var comp = Target as Component;
//} #else
//else if (typeof(UnityEngine.Object).IsAssignableFrom(m_targetType)) var comp = (Target as Il2CppSystem.Object).TryCast<Component>();
//{ #endif
//}
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 void ConstructUObjHelper(GameObject rowObj)
{
var labelObj = UIFactory.CreateLabel(rowObj, TextAnchor.MiddleLeft);
var labelLayout = labelObj.AddComponent<LayoutElement>();
labelLayout.minWidth = 60;
labelLayout.minHeight = 25;
labelLayout.flexibleWidth = 0;
var labelText = labelObj.GetComponent<Text>();
labelText.text = "Name:";
#if MONO
var uObj = Target as UnityEngine.Object;
#else
var uObj = (Target as Il2CppSystem.Object).TryCast<UnityEngine.Object>();
#endif
var inputObj = UIFactory.CreateInputField(rowObj, 14, 3, 1);
var inputLayout = inputObj.AddComponent<LayoutElement>();
inputLayout.minHeight = 25;
inputLayout.flexibleWidth = 2000;
var inputField = inputObj.GetComponent<InputField>();
inputField.readOnly = true;
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;

View File

@ -37,14 +37,7 @@ namespace UnityExplorer.Inspectors.Reflection
if (m_subContentConstructed) if (m_subContentConstructed)
{ {
// changing types, destroy subcontent DestroySubContent();
for (int i = 0; i < m_subContentParent.transform.childCount; i++)
{
var child = m_subContentParent.transform.GetChild(i);
GameObject.Destroy(child.gameObject);
}
m_subContentConstructed = false;
} }
if (!s_enumNamesCache.ContainsKey(type)) if (!s_enumNamesCache.ContainsKey(type))
@ -96,7 +89,10 @@ namespace UnityExplorer.Inspectors.Reflection
private void SetValueFromDropdown() private void SetValueFromDropdown()
{ {
var type = Value?.GetType() ?? FallbackType; var type = Value?.GetType() ?? FallbackType;
var value = Enum.Parse(type, m_dropdownText.text); var index = m_dropdown.value;
var value = Enum.Parse(type, s_enumNamesCache[type][index].Value);
if (value != null) if (value != null)
{ {
Value = value; Value = value;

View File

@ -14,8 +14,9 @@ namespace UnityExplorer.Inspectors.Reflection
{ {
public InteractiveString(object value, Type valueType) : base(value, valueType) { } public InteractiveString(object value, Type valueType) : base(value, valueType) { }
public override bool HasSubContent => false; public override bool HasSubContent => true;
public override bool SubContentWanted => false; public override bool SubContentWanted => true;
public override bool WantInspectBtn => false; public override bool WantInspectBtn => false;
public override void OnValueUpdated() public override void OnValueUpdated()
@ -27,10 +28,9 @@ namespace UnityExplorer.Inspectors.Reflection
{ {
base.OnException(member); base.OnException(member);
if (m_hiddenObj.gameObject.activeSelf) if (m_subContentConstructed && m_hiddenObj.gameObject.activeSelf)
m_hiddenObj.gameObject.SetActive(false); m_hiddenObj.gameObject.SetActive(false);
// m_baseLabel.text = DefaultLabel;
m_labelLayout.minWidth = 200; m_labelLayout.minWidth = 200;
m_labelLayout.flexibleWidth = 5000; m_labelLayout.flexibleWidth = 5000;
} }
@ -45,39 +45,62 @@ namespace UnityExplorer.Inspectors.Reflection
return; return;
} }
if (!m_hiddenObj.gameObject.activeSelf)
m_hiddenObj.gameObject.SetActive(true);
m_baseLabel.text = m_richValueType; m_baseLabel.text = m_richValueType;
if (Value != null) if (m_subContentConstructed)
{ {
var toString = Value.ToString(); if (!m_hiddenObj.gameObject.activeSelf)
m_hiddenObj.gameObject.SetActive(true);
}
if (!string.IsNullOrEmpty((string)Value))
{
var toString = (string)Value;
if (toString.Length > 15000) if (toString.Length > 15000)
toString = toString.Substring(0, 15000); toString = toString.Substring(0, 15000);
m_valueInput.text = toString; m_readonlyInput.text = toString;
m_placeholderText.text = toString;
if (m_subContentConstructed)
{
m_valueInput.text = toString;
m_placeholderText.text = toString;
}
} }
else else
{ {
m_valueInput.text = ""; string s = Value == null
m_placeholderText.text = "null"; ? "null"
: "empty";
m_readonlyInput.text = $"<i><color=grey>{s}</color></i>";
if (m_subContentConstructed)
{
m_valueInput.text = "";
m_placeholderText.text = s;
}
} }
m_labelLayout.minWidth = 50; m_labelLayout.minWidth = 50;
m_labelLayout.flexibleWidth = 0; m_labelLayout.flexibleWidth = 0;
} }
internal void OnApplyClicked() internal void OnApplyClicked()
{ {
Value = m_valueInput.text; Value = m_valueInput.text;
Owner.SetValue(); Owner.SetValue();
RefreshUIForValue();
} }
internal InputField m_valueInput; // for the default label
internal LayoutElement m_labelLayout; internal LayoutElement m_labelLayout;
//internal InputField m_readonlyInput;
internal Text m_readonlyInput;
// for input
internal InputField m_valueInput;
internal GameObject m_hiddenObj; internal GameObject m_hiddenObj;
internal Text m_placeholderText; internal Text m_placeholderText;
@ -90,12 +113,38 @@ namespace UnityExplorer.Inspectors.Reflection
m_labelLayout = m_baseLabel.gameObject.GetComponent<LayoutElement>(); m_labelLayout = m_baseLabel.gameObject.GetComponent<LayoutElement>();
m_hiddenObj = UIFactory.CreateLabel(m_valueContent, TextAnchor.MiddleLeft); var readonlyInputObj = UIFactory.CreateLabel(m_valueContent, TextAnchor.MiddleLeft);
m_readonlyInput = readonlyInputObj.GetComponent<Text>();
m_readonlyInput.horizontalOverflow = HorizontalWrapMode.Overflow;
var testFitter = readonlyInputObj.AddComponent<ContentSizeFitter>();
testFitter.verticalFit = ContentSizeFitter.FitMode.MinSize;
var labelLayout = readonlyInputObj.AddComponent<LayoutElement>();
labelLayout.minHeight = 25;
labelLayout.preferredHeight = 25;
labelLayout.flexibleHeight = 0;
}
public override void ConstructSubcontent()
{
base.ConstructSubcontent();
var groupObj = UIFactory.CreateVerticalGroup(m_subContentParent, new Color(1, 1, 1, 0));
var group = groupObj.GetComponent<VerticalLayoutGroup>();
group.spacing = 4;
group.padding.top = 3;
group.padding.left = 3;
group.padding.right = 3;
group.padding.bottom = 3;
m_hiddenObj = UIFactory.CreateLabel(groupObj, TextAnchor.MiddleLeft);
m_hiddenObj.SetActive(false); m_hiddenObj.SetActive(false);
var hiddenText = m_hiddenObj.GetComponent<Text>(); var hiddenText = m_hiddenObj.GetComponent<Text>();
hiddenText.color = Color.clear; hiddenText.color = Color.clear;
hiddenText.fontSize = 14; hiddenText.fontSize = 14;
hiddenText.raycastTarget = false; hiddenText.raycastTarget = false;
hiddenText.supportRichText = false;
var hiddenFitter = m_hiddenObj.AddComponent<ContentSizeFitter>(); var hiddenFitter = m_hiddenObj.AddComponent<ContentSizeFitter>();
hiddenFitter.verticalFit = ContentSizeFitter.FitMode.PreferredSize; hiddenFitter.verticalFit = ContentSizeFitter.FitMode.PreferredSize;
var hiddenLayout = m_hiddenObj.AddComponent<LayoutElement>(); var hiddenLayout = m_hiddenObj.AddComponent<LayoutElement>();
@ -121,19 +170,23 @@ namespace UnityExplorer.Inspectors.Reflection
m_placeholderText = m_valueInput.placeholder.GetComponent<Text>(); m_placeholderText = m_valueInput.placeholder.GetComponent<Text>();
m_valueInput.onValueChanged.AddListener((string val) => m_placeholderText.supportRichText = false;
m_valueInput.textComponent.supportRichText = false;
m_valueInput.onValueChanged.AddListener((string val) =>
{ {
hiddenText.text = val; hiddenText.text = val ?? "";
LayoutRebuilder.ForceRebuildLayoutImmediate(Owner.m_mainRect); LayoutRebuilder.ForceRebuildLayoutImmediate(Owner.m_mainRect);
}); });
if (Owner.CanWrite) if (Owner.CanWrite)
{ {
var applyBtnObj = UIFactory.CreateButton(m_valueContent, new Color(0.2f, 0.2f, 0.2f)); var applyBtnObj = UIFactory.CreateButton(groupObj, new Color(0.2f, 0.2f, 0.2f));
var applyLayout = applyBtnObj.AddComponent<LayoutElement>(); var applyLayout = applyBtnObj.AddComponent<LayoutElement>();
applyLayout.minWidth = 50; applyLayout.minWidth = 50;
applyLayout.minHeight = 25; applyLayout.minHeight = 25;
applyLayout.flexibleWidth = 0; applyLayout.flexibleWidth = 0;
var applyBtn = applyBtnObj.GetComponent<Button>(); var applyBtn = applyBtnObj.GetComponent<Button>();
applyBtn.onClick.AddListener(OnApplyClicked); applyBtn.onClick.AddListener(OnApplyClicked);
@ -144,6 +197,8 @@ namespace UnityExplorer.Inspectors.Reflection
{ {
m_valueInput.readOnly = true; m_valueInput.readOnly = true;
} }
RefreshUIForValue();
} }
} }
} }

View File

@ -226,14 +226,15 @@ namespace UnityExplorer.Inspectors.Reflection
if (StructInfo != null) if (StructInfo != null)
{ {
// changing types, destroy subcontent DestroySubContent();
for (int i = 0; i < m_subContentParent.transform.childCount; i++) //// changing types, destroy subcontent
{ //for (int i = 0; i < m_subContentParent.transform.childCount; i++)
var child = m_subContentParent.transform.GetChild(i); //{
GameObject.Destroy(child.gameObject); // var child = m_subContentParent.transform.GetChild(i);
} // GameObject.Destroy(child.gameObject);
//}
m_UIConstructed = false; //m_UIConstructed = false;
} }
m_lastStructType = type; m_lastStructType = type;

View File

@ -78,7 +78,13 @@ namespace UnityExplorer.Inspectors.Reflection
m_valueContent.SetActive(false); m_valueContent.SetActive(false);
GameObject.Destroy(this.m_valueContent.gameObject); GameObject.Destroy(this.m_valueContent.gameObject);
} }
if (this.m_subContentParent && SubContentWanted)
DestroySubContent();
}
public virtual void DestroySubContent()
{
if (this.m_subContentParent && HasSubContent)
{ {
for (int i = 0; i < this.m_subContentParent.transform.childCount; i++) for (int i = 0; i < this.m_subContentParent.transform.childCount; i++)
{ {
@ -87,6 +93,8 @@ namespace UnityExplorer.Inspectors.Reflection
GameObject.Destroy(child.gameObject); GameObject.Destroy(child.gameObject);
} }
} }
m_subContentConstructed = false;
} }
public virtual void OnValueUpdated() public virtual void OnValueUpdated()
@ -95,18 +103,16 @@ namespace UnityExplorer.Inspectors.Reflection
ConstructUI(m_mainContentParent, m_subContentParent); ConstructUI(m_mainContentParent, m_subContentParent);
if (Owner is CacheMember ownerMember && !string.IsNullOrEmpty(ownerMember.ReflectionException)) if (Owner is CacheMember ownerMember && !string.IsNullOrEmpty(ownerMember.ReflectionException))
{
OnException(ownerMember); OnException(ownerMember);
}
else else
{
RefreshUIForValue(); RefreshUIForValue();
}
} }
public virtual void OnException(CacheMember member) public virtual void OnException(CacheMember member)
{ {
m_baseLabel.text = "<color=red>" + member.ReflectionException + "</color>"; if (m_UIConstructed)
m_baseLabel.text = "<color=red>" + member.ReflectionException + "</color>";
Value = null; Value = null;
} }

View File

@ -34,7 +34,7 @@ namespace UnityExplorer.Inspectors
} }
// Blacklists // Blacklists
private static readonly HashSet<string> s_typeAndMemberBlacklist = new HashSet<string> private static readonly HashSet<string> bl_typeAndMember = new HashSet<string>
{ {
#if CPP #if CPP
// these cause a crash in IL2CPP // these cause a crash in IL2CPP
@ -45,14 +45,14 @@ namespace UnityExplorer.Inspectors
"Texture2D.SetPixelDataImpl", "Texture2D.SetPixelDataImpl",
#endif #endif
}; };
private static readonly HashSet<string> s_methodStartsWithBlacklist = new HashSet<string> private static readonly HashSet<string> bl_memberNameStartsWith = new HashSet<string>
{ {
// these are redundant // these are redundant
"get_", "get_",
"set_", "set_",
}; };
#endregion #endregion
#region INSTANCE #region INSTANCE
@ -132,24 +132,99 @@ namespace UnityExplorer.Inspectors
RefreshDisplay(); RefreshDisplay();
} }
private void OnMemberFilterClicked(MemberTypes type, Button button) 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)
{ {
if (m_lastActiveMemButton) 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 lastColors = m_lastActiveMemButton.colors; var target = Target;
lastColors.normalColor = new Color(0.2f, 0.2f, 0.2f); #if CPP
m_lastActiveMemButton.colors = lastColors; 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
{
//ExplorerCore.Log($"Trying to cache member {sig}...");
//ExplorerCore.Log(member.DeclaringType.FullName + "." + member.Name);
var sig = GetSig(member);
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));
}
catch (Exception e)
{
ExplorerCore.LogWarning($"Exception caching member {member.DeclaringType.FullName}.{member.Name}!");
ExplorerCore.Log(e.ToString());
}
}
} }
m_memberFilter = type; var typeList = types.ToList();
m_lastActiveMemButton = button;
var colors = m_lastActiveMemButton.colors; var sorted = new List<CacheMember>();
colors.normalColor = new Color(0.2f, 0.6f, 0.2f); sorted.AddRange(list.Where(it => it is CacheMethod)
m_lastActiveMemButton.colors = colors; .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));
FilterMembers(null, true); m_allMembers = sorted.ToArray();
m_sliderScroller.m_slider.value = 1f;
} }
public override void Update() public override void Update()
@ -178,6 +253,26 @@ namespace UnityExplorer.Inspectors
} }
} }
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) public void FilterMembers(string nameFilter = null, bool force = false)
{ {
int lastCount = m_membersFiltered.Count; int lastCount = m_membersFiltered.Count;
@ -200,7 +295,7 @@ namespace UnityExplorer.Inspectors
} }
// name filter // name filter
if (!string.IsNullOrEmpty(nameFilter) && !mem.NameForFiltering.Contains(nameFilter)) if (!string.IsNullOrEmpty(nameFilter) && !mem.NameForFiltering.Contains(nameFilter))
continue; continue;
m_membersFiltered.Add(mem); m_membersFiltered.Add(mem);
@ -266,137 +361,6 @@ namespace UnityExplorer.Inspectors
} }
} }
public void CacheMembers(Type type)
{
var list = new List<CacheMember>();
var cachedSigs = new HashSet<string>();
var types = ReflectionHelpers.GetAllBaseTypes(type);
foreach (var declaringType in types)
{
MemberInfo[] infos;
try
{
infos = declaringType.GetMembers(ReflectionHelpers.CommonFlags);
}
catch
{
ExplorerCore.Log($"Exception getting members for type: {declaringType.FullName}");
continue;
}
var target = Target;
#if CPP
try
{
target = target.Il2CppCast(declaringType);
}
catch //(Exception e)
{
//ExplorerCore.LogWarning("Excepting casting " + target.GetType().FullName + " to " + declaringType.FullName);
}
#endif
foreach (var member in infos)
{
try
{
// make sure member type is Field, Method or Property (4 / 8 / 16)
int m = (int)member.MemberType;
if (m < 4 || m > 16)
continue;
//ExplorerCore.Log($"Trying to cache member {sig}...");
//ExplorerCore.Log(member.DeclaringType.FullName + "." + member.Name);
var pi = member as PropertyInfo;
var mi = member as MethodInfo;
if (this is StaticInspector)
{
if (member is FieldInfo fi && !fi.IsStatic) continue;
else if (pi != null && !pi.GetAccessors(true)[0].IsStatic) continue;
else if (mi != null && !mi.IsStatic) continue;
}
// check blacklisted members
var sig = $"{member.DeclaringType.Name}.{member.Name}";
if (s_typeAndMemberBlacklist.Any(it => sig.Contains(it)))
continue;
if (s_methodStartsWithBlacklist.Any(it => member.Name.StartsWith(it)))
continue;
if (mi != null)
AppendParams(mi.GetParameters());
else if (pi != null)
AppendParams(pi.GetIndexParameters());
void AppendParams(ParameterInfo[] _args)
{
sig += " (";
foreach (var param in _args)
sig += $"{param.ParameterType.Name} {param.Name}, ";
sig += ")";
}
if (cachedSigs.Contains(sig))
continue;
try
{
CacheMember cached;
if (mi != null && CacheMember.CanProcessArgs(mi.GetParameters()))
cached = new CacheMethod(mi, target);
else if (pi != null && CacheMember.CanProcessArgs(pi.GetIndexParameters()))
cached = new CacheProperty(pi, target);
else if (member is FieldInfo fi)
cached = new CacheField(fi, target);
else
continue;
cached.m_parentContent = m_scrollContent;
if (cached != null)
{
cachedSigs.Add(sig);
list.Add(cached);
}
}
catch (Exception e)
{
ExplorerCore.LogWarning($"Exception caching member {sig}!");
ExplorerCore.Log(e.ToString());
}
}
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();
// ExplorerCore.Log("Cached " + m_allMembers.Length + " members");
}
#region UI CONSTRUCTION #region UI CONSTRUCTION
internal void ConstructUI() internal void ConstructUI()
@ -578,7 +542,7 @@ namespace UnityExplorer.Inspectors
internal void ConstructOptionsArea() internal void ConstructOptionsArea()
{ {
var optionsRowObj = UIFactory.CreateHorizontalGroup(Content, new Color(1,1,1,0)); var optionsRowObj = UIFactory.CreateHorizontalGroup(Content, new Color(1, 1, 1, 0));
var optionsLayout = optionsRowObj.AddComponent<LayoutElement>(); var optionsLayout = optionsRowObj.AddComponent<LayoutElement>();
optionsLayout.minHeight = 25; optionsLayout.minHeight = 25;
var optionsGroup = optionsRowObj.GetComponent<HorizontalLayoutGroup>(); var optionsGroup = optionsRowObj.GetComponent<HorizontalLayoutGroup>();
@ -596,7 +560,7 @@ namespace UnityExplorer.Inspectors
var updateText = updateButtonObj.GetComponentInChildren<Text>(); var updateText = updateButtonObj.GetComponentInChildren<Text>();
updateText.text = "Update Values"; updateText.text = "Update Values";
var updateBtn = updateButtonObj.GetComponent<Button>(); var updateBtn = updateButtonObj.GetComponent<Button>();
updateBtn.onClick.AddListener(() => updateBtn.onClick.AddListener(() =>
{ {
bool orig = m_autoUpdate; bool orig = m_autoUpdate;
m_autoUpdate = true; m_autoUpdate = true;
@ -617,7 +581,7 @@ namespace UnityExplorer.Inspectors
internal void ConstructMemberList() internal void ConstructMemberList()
{ {
var scrollobj = UIFactory.CreateScrollView(Content, out m_scrollContent, out m_sliderScroller, new Color(0.08f, 0.08f, 0.08f)); var scrollobj = UIFactory.CreateScrollView(Content, out m_scrollContent, out m_sliderScroller, new Color(0.05f, 0.05f, 0.05f));
m_scrollContentRect = m_scrollContent.GetComponent<RectTransform>(); m_scrollContentRect = m_scrollContent.GetComponent<RectTransform>();

View File

@ -24,6 +24,12 @@ namespace UnityExplorer.Tests
public class TestClass public class TestClass
{ {
public string AAALongString = @"1
2
3
4
5";
public Vector2 AATestVector2 = new Vector2(1, 2); public Vector2 AATestVector2 = new Vector2(1, 2);
public Vector3 AATestVector3 = new Vector3(1, 2, 3); public Vector3 AATestVector3 = new Vector3(1, 2, 3);
public Vector4 AATestVector4 = new Vector4(1, 2, 3, 4); public Vector4 AATestVector4 = new Vector4(1, 2, 3, 4);

View File

@ -77,11 +77,6 @@ namespace UnityExplorer.UI
catch { } catch { }
// Setup Harmony Patches // Setup Harmony Patches
TryPatch(typeof(EventSystem),
"current",
new HarmonyMethod(typeof(ForceUnlockCursor).GetMethod(nameof(Prefix_EventSystem_set_current))),
true);
TryPatch(typeof(Cursor), TryPatch(typeof(Cursor),
"lockState", "lockState",
new HarmonyMethod(typeof(ForceUnlockCursor).GetMethod(nameof(Prefix_set_lockState))), new HarmonyMethod(typeof(ForceUnlockCursor).GetMethod(nameof(Prefix_set_lockState))),
@ -91,10 +86,21 @@ namespace UnityExplorer.UI
"visible", "visible",
new HarmonyMethod(typeof(ForceUnlockCursor).GetMethod(nameof(Prefix_set_visible))), new HarmonyMethod(typeof(ForceUnlockCursor).GetMethod(nameof(Prefix_set_visible))),
true); true);
#if BIE
#if CPP
// temporarily disabling this patch in BepInEx il2cpp as it's causing a crash in some games.
return;
#endif
#endif
TryPatch(typeof(EventSystem),
"current",
new HarmonyMethod(typeof(ForceUnlockCursor).GetMethod(nameof(Prefix_EventSystem_set_current))),
true);
} }
catch (Exception e) catch (Exception e)
{ {
ExplorerCore.Log($"Exception on CursorControl.Init! {e.GetType()}, {e.Message}"); ExplorerCore.Log($"Exception on ForceUnlockCursor.Init! {e.GetType()}, {e.Message}");
} }
} }
@ -120,10 +126,10 @@ namespace UnityExplorer.UI
harmony.Patch(prop.GetGetMethod(), postfix: patch); harmony.Patch(prop.GetGetMethod(), postfix: patch);
} }
} }
catch // (Exception e) catch (Exception e)
{ {
//string suf = setter ? "set_" : "get_"; string suf = setter ? "set_" : "get_";
//ExplorerCore.Log($"Unable to patch {type.Name}.{suf}{property}: {e.Message}"); ExplorerCore.Log($"Unable to patch {type.Name}.{suf}{property}: {e.Message}");
} }
} }
@ -158,13 +164,20 @@ namespace UnityExplorer.UI
public static void SetEventSystem() public static void SetEventSystem()
{ {
if (InputManager.CurrentType == InputType.InputSystem)
return;
m_settingEventSystem = true; m_settingEventSystem = true;
UIManager.SetEventSystem(); EventSystem.current = UIManager.EventSys;
InputManager.ActivateUIModule();
m_settingEventSystem = false; m_settingEventSystem = false;
} }
public static void ReleaseEventSystem() public static void ReleaseEventSystem()
{ {
if (InputManager.CurrentType == InputType.InputSystem)
return;
if (m_lastEventSystem) if (m_lastEventSystem)
{ {
m_settingEventSystem = true; m_settingEventSystem = true;

View File

@ -260,11 +260,8 @@ namespace UnityExplorer.UI.Modules
if (searchType == null) if (searchType == null)
return; return;
#if MONO
var allObjects = ResourcesUnstrip.FindObjectsOfTypeAll(searchType); var allObjects = ResourcesUnstrip.FindObjectsOfTypeAll(searchType);
#else
var allObjects = ResourcesUnstrip.FindObjectsOfTypeAll(Il2CppType.From(searchType));
#endif
var results = new List<object>(); var results = new List<object>();
// perform filter comparers // perform filter comparers

View File

@ -178,13 +178,9 @@ namespace UnityExplorer.UI
Image image = groupObj.AddComponent<Image>(); Image image = groupObj.AddComponent<Image>();
if (color != default) if (color != default)
{
image.color = color; image.color = color;
}
else else
{
image.color = new Color(44f / 255f, 44f / 255f, 44f / 255f); image.color = new Color(44f / 255f, 44f / 255f, 44f / 255f);
}
return groupObj; return groupObj;
} }
@ -657,16 +653,16 @@ namespace UnityExplorer.UI
contentFitter.horizontalFit = ContentSizeFitter.FitMode.Unconstrained; contentFitter.horizontalFit = ContentSizeFitter.FitMode.Unconstrained;
contentFitter.verticalFit = ContentSizeFitter.FitMode.PreferredSize; contentFitter.verticalFit = ContentSizeFitter.FitMode.PreferredSize;
var contentLayout = content.AddComponent<VerticalLayoutGroup>(); var contentGroup = content.AddComponent<VerticalLayoutGroup>();
contentLayout.childForceExpandHeight = true; contentGroup.childForceExpandHeight = true;
contentLayout.childControlHeight = true; contentGroup.childControlHeight = true;
contentLayout.childForceExpandWidth = true; contentGroup.childForceExpandWidth = true;
contentLayout.childControlWidth = true; contentGroup.childControlWidth = true;
contentLayout.padding.left = 5; contentGroup.padding.left = 5;
contentLayout.padding.right = 5; contentGroup.padding.right = 5;
contentLayout.padding.top = 5; contentGroup.padding.top = 5;
contentLayout.padding.bottom = 5; contentGroup.padding.bottom = 5;
contentLayout.spacing = 5; contentGroup.spacing = 5;
GameObject scrollBarObj = CreateUIObject("DynamicScrollbar", mainObj); GameObject scrollBarObj = CreateUIObject("DynamicScrollbar", mainObj);

View File

@ -8,6 +8,7 @@ using System.IO;
using System.Reflection; using System.Reflection;
using UnityExplorer.Helpers; using UnityExplorer.Helpers;
using UnityExplorer.UI.Shared; using UnityExplorer.UI.Shared;
using UnityExplorer.Input;
#if CPP #if CPP
using UnityExplorer.Unstrip; using UnityExplorer.Unstrip;
#endif #endif
@ -18,37 +19,13 @@ namespace UnityExplorer.UI
{ {
public static GameObject CanvasRoot { get; private set; } public static GameObject CanvasRoot { get; private set; }
public static EventSystem EventSys { get; private set; } public static EventSystem EventSys { get; private set; }
public static StandaloneInputModule InputModule { get; private set; }
//internal static Material UIMaterial { get; private set; }
internal static Sprite ResizeCursor { get; private set; } internal static Sprite ResizeCursor { get; private set; }
internal static Font ConsoleFont { get; private set; } internal static Font ConsoleFont { get; private set; }
public static void Init() public static void Init()
{ {
var bundlePath = ExplorerCore.EXPLORER_FOLDER + @"\explorerui.bundle"; LoadBundle();
if (File.Exists(bundlePath))
{
var bundle = AssetBundle.LoadFromFile(bundlePath);
// Fix for games which don't ship with 'UI/Default' shader.
if (Graphic.defaultGraphicMaterial.shader?.name != "UI/Default")
{
ExplorerCore.Log("This game does not ship with the 'UI/Default' shader, using manual Default Shader...");
Graphic.defaultGraphicMaterial.shader = bundle.LoadAsset<Shader>("DefaultUI");
}
ResizeCursor = bundle.LoadAsset<Sprite>("cursor");
ConsoleFont = bundle.LoadAsset<Font>("CONSOLA");
ExplorerCore.Log("Loaded UI bundle");
}
else
{
ExplorerCore.LogWarning("Could not find the ExplorerUI Bundle! It should exist at '" + bundlePath + "'");
return;
}
// Create core UI Canvas and Event System handler // Create core UI Canvas and Event System handler
CreateRootCanvas(); CreateRootCanvas();
@ -62,12 +39,6 @@ namespace UnityExplorer.UI
Canvas.ForceUpdateCanvases(); Canvas.ForceUpdateCanvases();
} }
public static void SetEventSystem()
{
EventSystem.current = EventSys;
InputModule.ActivateModule();
}
public static void OnSceneChange() public static void OnSceneChange()
{ {
SceneExplorer.Instance?.OnSceneChange(); SceneExplorer.Instance?.OnSceneChange();
@ -78,23 +49,20 @@ namespace UnityExplorer.UI
{ {
MainMenu.Instance?.Update(); MainMenu.Instance?.Update();
if (EventSys && InputModule) if (EventSys)
{ {
if (EventSystem.current != EventSys) if (EventSystem.current != EventSys)
{ {
ForceUnlockCursor.SetEventSystem(); ForceUnlockCursor.SetEventSystem();
//ForceUnlockCursor.Unlock = true;
} }
// Fix for games which override the InputModule pointer events (eg, VRChat)
#if CPP #if CPP
if (InputModule.m_InputPointerEvent != null) // Fix for games which override the InputModule pointer events (eg, VRChat)
var evt = InputManager.InputPointerEvent;
if (evt != null)
{ {
PointerEventData evt = InputModule.m_InputPointerEvent;
if (!evt.eligibleForClick && evt.selectedObject) if (!evt.eligibleForClick && evt.selectedObject)
{
evt.eligibleForClick = true; evt.eligibleForClick = true;
}
} }
#endif #endif
} }
@ -125,6 +93,33 @@ namespace UnityExplorer.UI
} }
} }
private static void LoadBundle()
{
var bundlePath = ExplorerCore.EXPLORER_FOLDER + @"\explorerui.bundle";
if (File.Exists(bundlePath))
{
var bundle = AssetBundle.LoadFromFile(bundlePath);
// Fix for games which don't ship with 'UI/Default' shader.
if (Graphic.defaultGraphicMaterial.shader?.name != "UI/Default")
{
ExplorerCore.Log("This game does not ship with the 'UI/Default' shader, using manual Default Shader...");
Graphic.defaultGraphicMaterial.shader = bundle.LoadAsset<Shader>("DefaultUI");
}
ResizeCursor = bundle.LoadAsset<Sprite>("cursor");
ConsoleFont = bundle.LoadAsset<Font>("CONSOLA");
ExplorerCore.Log("Loaded UI bundle");
}
else
{
ExplorerCore.LogWarning("Could not find the ExplorerUI Bundle! It should exist at '" + bundlePath + "'");
return;
}
}
private static GameObject CreateRootCanvas() private static GameObject CreateRootCanvas()
{ {
GameObject rootObj = new GameObject("ExplorerCanvas"); GameObject rootObj = new GameObject("ExplorerCanvas");
@ -135,8 +130,7 @@ namespace UnityExplorer.UI
CanvasRoot.transform.position = new Vector3(0f, 0f, 1f); CanvasRoot.transform.position = new Vector3(0f, 0f, 1f);
EventSys = rootObj.AddComponent<EventSystem>(); EventSys = rootObj.AddComponent<EventSystem>();
InputModule = rootObj.AddComponent<StandaloneInputModule>(); InputManager.AddUIModule();
InputModule.ActivateModule();
Canvas canvas = rootObj.AddComponent<Canvas>(); Canvas canvas = rootObj.AddComponent<Canvas>();
canvas.renderMode = RenderMode.ScreenSpaceCamera; canvas.renderMode = RenderMode.ScreenSpaceCamera;

View File

@ -42,10 +42,10 @@ namespace UnityExplorer.UI
public static string ParseFullSyntax(Type type, bool includeNamespace, MemberInfo memberInfo = null) public static string ParseFullSyntax(Type type, bool includeNamespace, MemberInfo memberInfo = null)
{ {
string ret = "";
if (type == null) if (type == null)
return "????????????"; throw new ArgumentNullException("type");
string ret = "";
if (type.IsGenericParameter || (type.HasElementType && type.GetElementType().IsGenericParameter)) if (type.IsGenericParameter || (type.HasElementType && type.GetElementType().IsGenericParameter))
{ {

View File

@ -25,13 +25,13 @@
<Prefer32Bit>false</Prefer32Bit> <Prefer32Bit>false</Prefer32Bit>
<RootNamespace>UnityExplorer</RootNamespace> <RootNamespace>UnityExplorer</RootNamespace>
<!-- Set this to the BepInEx Il2Cpp Game folder, without the ending '\' character. --> <!-- Set this to the BepInEx Il2Cpp Game folder, without the ending '\' character. -->
<BIECppGameFolder>D:\Steam\steamapps\common\Outward</BIECppGameFolder> <BIECppGameFolder>D:\source\Unity Projects\Test\_BUILD</BIECppGameFolder>
<!-- Set this to the BepInEx Mono Game folder, without the ending '\' character. --> <!-- Set this to the BepInEx Mono Game folder, without the ending '\' character. -->
<BIEMonoGameFolder>D:\source\Unity Projects\Test\_BUILD_MONO</BIEMonoGameFolder> <BIEMonoGameFolder>D:\source\Unity Projects\Test\_BUILD_MONO</BIEMonoGameFolder>
<!-- Set this to the BepInEx Mono Managed folder, without the ending '\' character. --> <!-- Set this to the BepInEx Mono Managed folder, without the ending '\' character. -->
<BIEMonoManagedFolder>D:\source\Unity Projects\Test\_BUILD_MONO\Test_Data\Managed</BIEMonoManagedFolder> <BIEMonoManagedFolder>D:\source\Unity Projects\Test\_BUILD_MONO\Test_Data\Managed</BIEMonoManagedFolder>
<!-- Set this to the MelonLoader Il2Cpp Game folder, without the ending '\' character. --> <!-- Set this to the MelonLoader Il2Cpp Game folder, without the ending '\' character. -->
<MLCppGameFolder>D:\Steam\steamapps\common\VRChat</MLCppGameFolder> <MLCppGameFolder>D:\source\Unity Projects\Test\_BUILD</MLCppGameFolder>
<!-- Set this to the MelonLoader Mono Game folder, without the ending '\' character. --> <!-- Set this to the MelonLoader Mono Game folder, without the ending '\' character. -->
<MLMonoGameFolder>D:\source\Unity Projects\Test\_BUILD_MONO</MLMonoGameFolder> <MLMonoGameFolder>D:\source\Unity Projects\Test\_BUILD_MONO</MLMonoGameFolder>
<!-- Set this to the MelonLoader Mono Managed folder, without the ending '\' character. --> <!-- Set this to the MelonLoader Mono Managed folder, without the ending '\' character. -->

View File

@ -3,24 +3,27 @@ using Mono.CSharp;
using UnityExplorer.Helpers; using UnityExplorer.Helpers;
#if CPP #if CPP
using UnhollowerBaseLib; using UnhollowerBaseLib;
using UnhollowerRuntimeLib;
#endif #endif
namespace UnityExplorer.Unstrip namespace UnityExplorer.Unstrip
{ {
public class ResourcesUnstrip 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 #if CPP
internal delegate IntPtr d_FindObjectsOfTypeAll(IntPtr type); internal delegate IntPtr d_FindObjectsOfTypeAll(IntPtr type);
public static UnityEngine.Object[] FindObjectsOfTypeAll(Il2CppSystem.Type type)
{
var iCall = ICallHelper.GetICall<d_FindObjectsOfTypeAll>("UnityEngine.Resources::FindObjectsOfTypeAll");
return new Il2CppReferenceArray<UnityEngine.Object>(iCall.Invoke(type.Pointer));
}
#else
public static UnityEngine.Object[] FindObjectsOfTypeAll(Type type) => UnityEngine.Resources.FindObjectsOfTypeAll(type);
#endif #endif
} }
} }