Compare commits

...

4 Commits
1.5.1 ... 1.5.3

Author SHA1 Message Date
5de771389e 1.5.3
* Added exception handling for scrollview when unstripping fails
* Added some better logging in some places
2020-09-04 01:27:44 +10:00
51cfbe524e Update README.md 2020-09-03 20:59:54 +10:00
217b93ef4f 1.5.2
* Added ability to force Reflection Inspector for GameObjects and Transforms if you hold Left Shift while clicking the Inspect button
* Fixed a bug causing duplicate windows to open when you inspect Transforms, the current active window will now be focused. Note: does not apply if you hold Left Shift for forced reflection.
2020-09-03 20:58:04 +10:00
42156e1160 1.5.2
* Added page view to GameObject Children/Component lists
* Made a generic Page Handler helper class, replaced all page view implementations with the helper (no real change for users but should make things easier to maintain in the future, and they were basically all copy+pastes).
2020-09-03 19:48:50 +10:00
13 changed files with 389 additions and 255 deletions

View File

@ -51,7 +51,9 @@ Requires [MelonLoader](https://github.com/HerpDerpinstine/MelonLoader) to be ins
CppExplorer has two main inspector modes: <b>GameObject Inspector</b>, and <b>Reflection Inspector</b>.
<b>Tip:</b> when in Tab View, GameObjects are denoted by a [G] prefix, and Reflection objects are denoted by a [R] prefix.
<b>Tips:</b>
* When in Tab View, GameObjects are denoted by a [G] prefix, and Reflection objects are denoted by a [R] prefix.
* Hold <b>Left Shift</b> when you click the Inspect button to force Reflection mode for GameObjects and Transforms.
### GameObject Inspector

View File

@ -10,32 +10,9 @@ namespace Explorer
{
public class CacheGameObject : CacheObjectBase
{
private GameObject GameObj
{
get
{
if (m_gameObject == null)
{
if (Value is Il2CppSystem.Object ilObj)
{
var ilType = ilObj.GetIl2CppType();
if (ilType == ReflectionHelpers.GameObjectType || ilType == ReflectionHelpers.TransformType)
{
m_gameObject = ilObj.TryCast<GameObject>() ?? ilObj.TryCast<Transform>()?.gameObject;
}
}
}
return m_gameObject;
}
}
private GameObject m_gameObject;
public override void DrawValue(Rect window, float width)
{
UIHelpers.GameobjButton(GameObj, null, false, width);
UIHelpers.GameobjButton(Value, null, false, width);
}
public override void UpdateValue()

View File

@ -11,8 +11,7 @@ namespace Explorer
public class CacheList : CacheObjectBase
{
public bool IsExpanded { get; set; }
public int ArrayOffset { get; set; }
public int ArrayLimit { get; set; } = 20;
public PageHelper Pages = new PageHelper();
public float WhiteSpace = 215f;
public float ButtonWidthOffset = 290f;
@ -230,18 +229,6 @@ namespace Explorer
{
list.Add(null);
}
//var type = ReflectionHelpers.GetActualType(obj);
//if (obj is Il2CppSystem.Object iObj)
//{
// obj = iObj.Il2CppCast(type);
//}
//var cached = GetCacheObject(obj, null, null, type);
//cached.UpdateValue();
//list.Add(cached);
}
m_cachedEntries = list.ToArray();
@ -286,51 +273,51 @@ namespace Explorer
if (IsExpanded)
{
float whitespace = WhiteSpace;
float whitespace = WhiteSpace;
if (whitespace > 0)
{
ClampLabelWidth(window, ref whitespace);
}
if (count > ArrayLimit)
Pages.Count = count;
if (count > Pages.PageLimit)
{
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal(null);
GUILayout.Space(whitespace);
int maxOffset = (int)Mathf.Ceil((float)(count / (decimal)ArrayLimit)) - 1;
GUILayout.Label($"Page {ArrayOffset + 1}/{maxOffset + 1}", new GUILayoutOption[] { GUILayout.Width(80) });
//int maxOffset = (int)Mathf.Ceil((float)(count / (decimal)ArrayLimit)) - 1;
Pages.CalculateMaxOffset();
//GUILayout.Label($"Page {PH.ArrayOffset + 1}/{maxOffset + 1}", new GUILayoutOption[] { GUILayout.Width(80) });
Pages.CurrentPageLabel();
// prev/next page buttons
if (GUILayout.Button("< Prev", new GUILayoutOption[] { GUILayout.Width(60) }))
{
if (ArrayOffset > 0) ArrayOffset--;
Pages.TurnPage(Turn.Left);
}
if (GUILayout.Button("Next >", new GUILayoutOption[] { GUILayout.Width(60) }))
{
if (ArrayOffset < maxOffset) ArrayOffset++;
}
GUILayout.Label("Limit: ", new GUILayoutOption[] { GUILayout.Width(50) });
var limit = this.ArrayLimit.ToString();
limit = GUILayout.TextField(limit, new GUILayoutOption[] { GUILayout.Width(50) });
if (limit != ArrayLimit.ToString() && int.TryParse(limit, out int i))
{
ArrayLimit = i;
Pages.TurnPage(Turn.Right);
}
Pages.DrawLimitInputArea();
GUILayout.Space(5);
}
int offset = ArrayOffset * ArrayLimit;
//int offset = ArrayOffset * ArrayLimit;
//if (offset >= count)
//{
// offset = 0;
// ArrayOffset = 0;
//}
int offset = Pages.CalculateOffsetIndex();
if (offset >= count)
{
offset = 0;
ArrayOffset = 0;
}
for (int i = offset; i < offset + ArrayLimit && i < count; i++)
for (int i = offset; i < offset + Pages.PageLimit && i < count; i++)
{
var entry = m_cachedEntries[i];

View File

@ -12,7 +12,7 @@ namespace Explorer
public class CppExplorer : MelonMod
{
public const string GUID = "com.sinai.cppexplorer";
public const string VERSION = "1.5.1";
public const string VERSION = "1.5.3";
public const string AUTHOR = "Sinai";
public const string NAME = "CppExplorer"
@ -99,6 +99,8 @@ namespace Explorer
public override void OnGUI()
{
if (!ShowMenu) return;
MainMenu.Instance.OnGUI();
WindowManager.Instance.OnGUI();
InspectUnderMouse.OnGUI();

View File

@ -60,9 +60,7 @@
<HintPath>..\..\..\..\..\Steam\steamapps\common\Hellpoint\MelonLoader\Managed\UnhollowerBaseLib.dll</HintPath>
<Private>False</Private>
</Reference>
<!-- Unity 2019 build (InputLegacyModule.dll) -->
<Reference Include="UnityEngine" Condition="'$(Configuration)'=='Debug'">
<HintPath>..\..\..\Steam\steamapps\common\Hellpoint\MelonLoader\Managed\UnityEngine.dll</HintPath>
<Private>False</Private>
@ -91,9 +89,7 @@
<HintPath>..\..\..\Steam\steamapps\common\Hellpoint\MelonLoader\Managed\UnityEngine.UI.dll</HintPath>
<Private>False</Private>
</Reference>
<!-- Unity 2018 build (InputModule.dll) -->
<Reference Include="UnityEngine" Condition="'$(Configuration)'=='Release_Unity2018'">
<HintPath>..\..\..\Steam\steamapps\common\VRChat\MelonLoader\Managed\UnityEngine.dll</HintPath>
<Private>False</Private>
@ -122,7 +118,6 @@
<HintPath>..\..\..\Steam\steamapps\common\VRChat\MelonLoader\Managed\UnityEngine.UI.dll</HintPath>
<Private>False</Private>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="CachedObjects\CacheDictionary.cs" />
@ -135,6 +130,7 @@
<Compile Include="CppExplorer.cs" />
<Compile Include="Extensions\ReflectionExtensions.cs" />
<Compile Include="Extensions\UnityExtensions.cs" />
<Compile Include="Helpers\PageHelper.cs" />
<Compile Include="Helpers\ReflectionHelpers.cs" />
<Compile Include="Helpers\UIHelpers.cs" />
<Compile Include="Helpers\UnityHelpers.cs" />

88
src/Helpers/PageHelper.cs Normal file
View File

@ -0,0 +1,88 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
namespace Explorer
{
public enum Turn
{
Left,
Right
}
public class PageHelper
{
public int PageOffset { get; set; }
public int PageLimit { get; set; } = 20;
public int Count { get; set; }
public int MaxOffset { get; set; } = -1;
public int CalculateMaxOffset()
{
return MaxOffset = (int)Mathf.Ceil((float)(Count / (decimal)PageLimit)) - 1;
}
public void CurrentPageLabel()
{
var orig = GUI.skin.label.alignment;
GUI.skin.label.alignment = TextAnchor.MiddleCenter;
GUILayout.Label($"Page {PageOffset + 1}/{MaxOffset + 1}", new GUILayoutOption[] { GUILayout.Width(80) });
GUI.skin.label.alignment = orig;
}
public void TurnPage(Turn direction)
{
var _ = Vector2.zero;
TurnPage(direction, ref _);
}
public void TurnPage(Turn direction, ref Vector2 scroll)
{
if (direction == Turn.Left)
{
if (PageOffset > 0)
{
PageOffset--;
scroll = Vector2.zero;
}
}
else
{
if (PageOffset < MaxOffset)
{
PageOffset++;
scroll = Vector2.zero;
}
}
}
public int CalculateOffsetIndex()
{
int offset = PageOffset * PageLimit;
if (offset >= Count)
{
offset = 0;
PageOffset = 0;
}
return offset;
}
public void DrawLimitInputArea()
{
GUILayout.Label("Limit: ", new GUILayoutOption[] { GUILayout.Width(50) });
var limit = this.PageLimit.ToString();
limit = GUILayout.TextField(limit, new GUILayoutOption[] { GUILayout.Width(50) });
if (limit != PageLimit.ToString() && int.TryParse(limit, out int i))
{
PageLimit = i;
}
}
}
}

View File

@ -10,6 +10,35 @@ namespace Explorer
{
public class UIHelpers
{
private static bool ScrollUnstrippingFailed = false;
public static Vector2 BeginScrollView(Vector2 scroll) => BeginScrollView(scroll, null);
public static Vector2 BeginScrollView(Vector2 scroll, GUIStyle style, params GUILayoutOption[] layoutOptions)
{
if (ScrollUnstrippingFailed) return scroll;
try
{
if (style != null)
return GUILayout.BeginScrollView(scroll, style, layoutOptions);
else
return GUILayout.BeginScrollView(scroll, layoutOptions);
}
catch
{
ScrollUnstrippingFailed = true;
return scroll;
}
}
public static void EndScrollView()
{
if (ScrollUnstrippingFailed) return;
GUILayout.EndScrollView();
}
// helper for "Instantiate" button on UnityEngine.Objects
public static void InstantiateButton(Object obj, float width = 100)
{
@ -22,8 +51,10 @@ namespace Explorer
}
// helper for drawing a styled button for a GameObject or Transform
public static void GameobjButton(GameObject obj, Action<Transform> specialInspectMethod = null, bool showSmallInspectBtn = true, float width = 380)
public static void GameobjButton(object _obj, Action<Transform> specialInspectMethod = null, bool showSmallInspectBtn = true, float width = 380)
{
var obj = (_obj as GameObject) ?? (_obj as Transform).gameObject;
bool children = obj.transform.childCount > 0;
string label = children ? "[" + obj.transform.childCount + " children] " : "";
@ -49,11 +80,13 @@ namespace Explorer
color = Color.red;
}
FastGameobjButton(obj, color, label, obj.activeSelf, specialInspectMethod, showSmallInspectBtn, width);
FastGameobjButton(_obj, color, label, obj.activeSelf, specialInspectMethod, showSmallInspectBtn, width);
}
public static void FastGameobjButton(GameObject obj, Color activeColor, string label, bool enabled, Action<Transform> specialInspectMethod = null, bool showSmallInspectBtn = true, float width = 380)
public static void FastGameobjButton(object _obj, Color activeColor, string label, bool enabled, Action<Transform> specialInspectMethod = null, bool showSmallInspectBtn = true, float width = 380)
{
var obj = _obj as GameObject ?? (_obj as Transform).gameObject;
if (!obj)
{
GUILayout.Label("<i><color=red>null</color></i>", null);
@ -83,7 +116,7 @@ namespace Explorer
}
else
{
WindowManager.InspectObject(obj, out bool _);
WindowManager.InspectObject(_obj, out bool _);
}
}
@ -94,7 +127,7 @@ namespace Explorer
if (showSmallInspectBtn)
{
SmallInspectButton(obj);
SmallInspectButton(_obj);
}
GUILayout.EndHorizontal();

View File

@ -51,15 +51,12 @@ namespace Explorer
public void OnGUI()
{
if (CppExplorer.ShowMenu)
{
var origSkin = GUI.skin;
GUI.skin = UIStyles.WindowSkin;
var origSkin = GUI.skin;
GUI.skin = UIStyles.WindowSkin;
MainRect = GUI.Window(MainWindowID, MainRect, (GUI.WindowFunction)MainWindow, CppExplorer.NAME);
MainRect = GUI.Window(MainWindowID, MainRect, (GUI.WindowFunction)MainWindow, CppExplorer.NAME);
GUI.skin = origSkin;
}
GUI.skin = origSkin;
}
private void MainWindow(int id)
@ -77,9 +74,12 @@ namespace Explorer
MainHeader();
var page = Pages[m_currentPage];
page.scroll = GUILayout.BeginScrollView(page.scroll, GUI.skin.scrollView);
page.scroll = UIHelpers.BeginScrollView(page.scroll);
page.DrawWindow();
GUILayout.EndScrollView();
UIHelpers.EndScrollView();
MainRect = ResizeDrag.ResizeWindow(MainRect, MainWindowID);

View File

@ -14,9 +14,7 @@ namespace Explorer
public override string Name { get => "Scene Explorer"; set => base.Name = value; }
private int m_pageOffset = 0;
private int m_limit = 20;
private int m_currentTotalCount = 0;
public PageHelper Pages = new PageHelper();
private float m_timeOfLastUpdate = -1f;
@ -46,14 +44,14 @@ namespace Explorer
SetTransformTarget(null);
}
public void CheckOffset(ref int offset, int childCount)
{
if (offset >= childCount)
{
offset = 0;
m_pageOffset = 0;
}
}
//public void CheckOffset(ref int offset, int childCount)
//{
// if (offset >= childCount)
// {
// offset = 0;
// m_pageOffset = 0;
// }
//}
public override void Update()
{
@ -63,7 +61,6 @@ namespace Explorer
m_timeOfLastUpdate = Time.time;
m_objectList = new List<GameObjectCache>();
int offset = m_pageOffset * m_limit;
var allTransforms = new List<Transform>();
@ -86,15 +83,14 @@ namespace Explorer
}
}
m_currentTotalCount = allTransforms.Count;
Pages.Count = allTransforms.Count;
// make sure offset doesn't exceed count
CheckOffset(ref offset, m_currentTotalCount);
int offset = Pages.CalculateOffsetIndex();
// sort by childcount
allTransforms.Sort((a, b) => b.childCount.CompareTo(a.childCount));
for (int i = offset; i < offset + m_limit && i < m_currentTotalCount; i++)
for (int i = offset; i < offset + Pages.PageLimit && i < Pages.Count; i++)
{
var child = allTransforms[i];
m_objectList.Add(new GameObjectCache(child.gameObject));
@ -128,7 +124,7 @@ namespace Explorer
{
m_searchResults = SearchSceneObjects(m_searchInput);
m_searching = true;
m_currentTotalCount = m_searchResults.Count;
Pages.Count = m_searchResults.Count;
}
public void CancelSearch()
@ -242,33 +238,21 @@ namespace Explorer
{
GUILayout.BeginHorizontal(null);
GUILayout.Label("Limit per page: ", new GUILayoutOption[] { GUILayout.Width(100) });
var limit = m_limit.ToString();
limit = GUILayout.TextField(limit, new GUILayoutOption[] { GUILayout.Width(30) });
if (int.TryParse(limit, out int lim))
{
m_limit = lim;
}
Pages.DrawLimitInputArea();
// prev/next page buttons
if (m_currentTotalCount > m_limit)
if (Pages.Count > Pages.PageLimit)
{
int count = m_currentTotalCount;
int maxOffset = (int)Mathf.Ceil((float)(count / (decimal)m_limit)) - 1;
if (GUILayout.Button("< Prev", null))
if (GUILayout.Button("< Prev", new GUILayoutOption[] { GUILayout.Width(80) }))
{
if (m_pageOffset > 0) m_pageOffset--;
m_timeOfLastUpdate = -1f;
Pages.TurnPage(Turn.Left, ref this.scroll);
Update();
}
GUI.skin.label.alignment = TextAnchor.MiddleCenter;
GUILayout.Label($"Page {m_pageOffset + 1}/{maxOffset + 1}", new GUILayoutOption[] { GUILayout.Width(80) });
Pages.CurrentPageLabel();
if (GUILayout.Button("Next >", null))
if (GUILayout.Button("Next >", new GUILayoutOption[] { GUILayout.Width(80) }))
{
if (m_pageOffset < maxOffset) m_pageOffset++;
m_timeOfLastUpdate = -1f;
Pages.TurnPage(Turn.Right, ref this.scroll);
Update();
}
}
@ -342,15 +326,9 @@ namespace Explorer
if (m_searchResults.Count > 0)
{
int offset = m_pageOffset * m_limit;
int offset = Pages.CalculateOffsetIndex();
if (offset >= m_searchResults.Count)
{
offset = 0;
m_pageOffset = 0;
}
for (int i = offset; i < offset + m_limit && i < m_searchResults.Count; i++)
for (int i = offset; i < offset + Pages.PageLimit && i < m_searchResults.Count; i++)
{
var obj = m_searchResults[i];

View File

@ -5,11 +5,7 @@ using System.Linq;
using System.Text;
using UnityEngine;
using System.Reflection;
using UnityEngine.SceneManagement;
using Object = UnityEngine.Object;
using UnhollowerRuntimeLib;
using MelonLoader;
using UnhollowerBaseLib;
namespace Explorer
{
@ -21,11 +17,11 @@ namespace Explorer
private string m_searchInput = "";
private string m_typeInput = "";
private int m_limit = 20;
private int m_pageOffset = 0;
//private List<object> m_searchResults = new List<object>();
private Vector2 resultsScroll = Vector2.zero;
public PageHelper Pages = new PageHelper();
private List<CacheObjectBase> m_searchResults = new List<CacheObjectBase>();
public SceneFilter SceneMode = SceneFilter.Any;
@ -55,7 +51,7 @@ namespace Explorer
public void OnSceneChange()
{
m_searchResults.Clear();
m_pageOffset = 0;
Pages.PageOffset = 0;
}
public override void Update()
@ -78,6 +74,9 @@ namespace Explorer
var cache = CacheObjectBase.GetCacheObject(toCache);
m_searchResults.Add(cache);
}
Pages.Count = m_searchResults.Count;
Pages.PageOffset = 0;
}
public override void DrawWindow()
@ -90,8 +89,7 @@ namespace Explorer
if (GUILayout.Button("Find Static Instances", new GUILayoutOption[] { GUILayout.Width(180) }))
{
//m_searchResults = GetInstanceClassScanner().ToList();
CacheResults(GetInstanceClassScanner());
m_pageOffset = 0;
CacheResults(GetInstanceClassScanner());
}
GUILayout.EndHorizontal();
@ -106,36 +104,45 @@ namespace Explorer
GUI.skin.label.alignment = TextAnchor.UpperLeft;
int count = m_searchResults.Count;
Pages.CalculateMaxOffset();
if (count > this.m_limit)
GUILayout.BeginHorizontal(null);
Pages.DrawLimitInputArea();
if (count > Pages.PageLimit)
{
// prev/next page buttons
GUILayout.BeginHorizontal(null);
int maxOffset = (int)Mathf.Ceil((float)(count / (decimal)m_limit)) - 1;
if (GUILayout.Button("< Prev", null))
{
if (m_pageOffset > 0) m_pageOffset--;
}
GUILayout.Label($"Page {m_pageOffset + 1}/{maxOffset + 1}", new GUILayoutOption[] { GUILayout.Width(80) });
if (GUILayout.Button("Next >", null))
if (Pages.Count > Pages.PageLimit)
{
if (m_pageOffset < maxOffset) m_pageOffset++;
if (GUILayout.Button("< Prev", new GUILayoutOption[] { GUILayout.Width(80) }))
{
Pages.TurnPage(Turn.Left, ref this.resultsScroll);
}
Pages.CurrentPageLabel();
if (GUILayout.Button("Next >", new GUILayoutOption[] { GUILayout.Width(80) }))
{
Pages.TurnPage(Turn.Right, ref this.resultsScroll);
}
}
GUILayout.EndHorizontal();
}
resultsScroll = GUILayout.BeginScrollView(resultsScroll, GUI.skin.scrollView);
GUILayout.EndHorizontal();
resultsScroll = UIHelpers.BeginScrollView(resultsScroll);
var _temprect = new Rect(MainMenu.MainRect.x, MainMenu.MainRect.y, MainMenu.MainRect.width + 160, MainMenu.MainRect.height);
if (m_searchResults.Count > 0)
{
int offset = m_pageOffset * this.m_limit;
if (offset >= count) m_pageOffset = 0;
//int offset = m_pageOffset * this.m_limit;
//if (offset >= count) m_pageOffset = 0;
int offset = Pages.CalculateOffsetIndex();
for (int i = offset; i < offset + m_limit && i < count; i++)
for (int i = offset; i < offset + Pages.PageLimit && i < count; i++)
{
m_searchResults[i].Draw(MainMenu.MainRect, 0f);
//m_searchResults[i].DrawValue(MainMenu.MainRect);
@ -146,7 +153,7 @@ namespace Explorer
GUILayout.Label("<color=red><i>No results found!</i></color>", null);
}
GUILayout.EndScrollView();
UIHelpers.EndScrollView();
GUILayout.EndVertical();
}
catch
@ -169,15 +176,15 @@ namespace Explorer
GUILayout.Label("Name Contains:", new GUILayoutOption[] { GUILayout.Width(100) });
m_searchInput = GUILayout.TextField(m_searchInput, new GUILayoutOption[] { GUILayout.Width(200) });
GUI.skin.label.alignment = TextAnchor.MiddleRight;
GUILayout.Label("Results per page:", new GUILayoutOption[] { GUILayout.Width(120) });
var resultinput = m_limit.ToString();
resultinput = GUILayout.TextField(resultinput, new GUILayoutOption[] { GUILayout.Width(55) });
if (int.TryParse(resultinput, out int _i) && _i > 0)
{
m_limit = _i;
}
GUI.skin.label.alignment = TextAnchor.UpperLeft;
//GUI.skin.label.alignment = TextAnchor.MiddleRight;
//GUILayout.Label("Results per page:", new GUILayoutOption[] { GUILayout.Width(120) });
//var resultinput = m_limit.ToString();
//resultinput = GUILayout.TextField(resultinput, new GUILayoutOption[] { GUILayout.Width(55) });
//if (int.TryParse(resultinput, out int _i) && _i > 0)
//{
// m_limit = _i;
//}
//GUI.skin.label.alignment = TextAnchor.UpperLeft;
GUILayout.EndHorizontal();
@ -256,7 +263,7 @@ namespace Explorer
private void Search()
{
m_pageOffset = 0;
Pages.PageOffset = 0;
CacheResults(FindAllObjectsOfType(m_searchInput, m_typeInput));
}

View File

@ -21,11 +21,13 @@ namespace Explorer
private string m_name;
private string m_scene;
private Vector2 m_transformScroll = Vector2.zero;
private Transform[] m_children;
private Component[] m_components;
private Vector2 m_transformScroll = Vector2.zero;
private PageHelper ChildPages = new PageHelper();
private Component[] m_components;
private Vector2 m_compScroll = Vector2.zero;
private PageHelper CompPages = new PageHelper();
private float m_translateAmount = 0.3f;
private float m_rotateAmount = 50f;
@ -71,15 +73,10 @@ namespace Explorer
m_name = m_object.name;
m_scene = string.IsNullOrEmpty(m_object.scene.name)
? "None"
: m_object.scene.name;
? "None"
: m_object.scene.name;
var list = new List<Transform>();
for (int i = 0; i < m_object.transform.childCount; i++)
{
list.Add(m_object.transform.GetChild(i));
}
m_children = list.ToArray();
Update();
}
public override void Update()
@ -91,12 +88,30 @@ namespace Explorer
throw new Exception("Object is null!");
}
var list = new List<Component>();
var list = new List<Transform>();
for (int i = 0; i < m_object.transform.childCount; i++)
{
list.Add(m_object.transform.GetChild(i));
}
list.Sort((a, b) => b.childCount.CompareTo(a.childCount));
m_children = list.ToArray();
ChildPages.Count = m_children.Length;
var list2 = new List<Component>();
foreach (var comp in m_object.GetComponents(ReflectionHelpers.ComponentType))
{
list.Add(comp);
var ilType = comp.GetIl2CppType();
if (ilType == ReflectionHelpers.TransformType)
{
continue;
}
list2.Add(comp);
}
m_components = list.ToArray();
m_components = list2.ToArray();
CompPages.Count = m_components.Length;
}
catch (Exception e)
{
@ -106,7 +121,7 @@ namespace Explorer
private void DestroyOnException(Exception e)
{
MelonLogger.Log($"{e.GetType()}, {e.Message}");
MelonLogger.Log($"Exception drawing GameObject Window: {e.GetType()}, {e.Message}");
DestroyWindow();
}
@ -154,18 +169,22 @@ namespace Explorer
GUILayout.BeginArea(new Rect(5, 25, rect.width - 10, rect.height - 35), GUI.skin.box);
}
scroll = GUILayout.BeginScrollView(scroll, GUI.skin.scrollView);
scroll = UIHelpers.BeginScrollView(scroll);
GUILayout.BeginHorizontal(null);
GUILayout.Label("Scene: <color=cyan>" + (m_scene == "" ? "n/a" : m_scene) + "</color>", null);
if (m_scene == UnityHelpers.ActiveSceneName)
{
if (GUILayout.Button("<color=#00FF00>< View in Scene Explorer</color>", new GUILayoutOption[] { GUILayout.Width(230) }))
if (GUILayout.Button("<color=#00FF00>Send to Scene View</color>", new GUILayoutOption[] { GUILayout.Width(150) }))
{
ScenePage.Instance.SetTransformTarget(m_object.transform);
MainMenu.SetCurrentPage(0);
}
}
if (GUILayout.Button("Reflection Inspect", new GUILayoutOption[] { GUILayout.Width(150) }))
{
WindowManager.InspectObject(Target, out _, true);
}
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal(null);
@ -201,7 +220,7 @@ namespace Explorer
GameObjectControls();
GUILayout.EndScrollView();
UIHelpers.EndScrollView();
if (!WindowManager.TabView)
{
@ -218,29 +237,49 @@ namespace Explorer
private void TransformList(Rect m_rect)
{
GUILayout.BeginVertical(GUI.skin.box, null); // new GUILayoutOption[] { GUILayout.Height(250) });
m_transformScroll = GUILayout.BeginScrollView(m_transformScroll, GUI.skin.scrollView);
GUILayout.BeginVertical(GUI.skin.box, null);
m_transformScroll = UIHelpers.BeginScrollView(m_transformScroll);
GUILayout.Label("<b><size=15>Children</size></b>", null);
GUILayout.BeginHorizontal(null);
ChildPages.DrawLimitInputArea();
if (ChildPages.Count > ChildPages.PageLimit)
{
ChildPages.CalculateMaxOffset();
ChildPages.CurrentPageLabel();
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal(null);
if (GUILayout.Button("< Prev", new GUILayoutOption[] { GUILayout.Width(80) }))
{
ChildPages.TurnPage(Turn.Left, ref this.m_transformScroll);
}
if (GUILayout.Button("Next >", new GUILayoutOption[] { GUILayout.Width(80) }))
{
ChildPages.TurnPage(Turn.Right, ref this.m_transformScroll);
}
}
GUILayout.EndHorizontal();
GUILayout.Label("<b>Children:</b>", null);
if (m_children != null && m_children.Length > 0)
{
foreach (var obj in m_children.Where(x => x.childCount > 0))
int start = ChildPages.CalculateOffsetIndex();
for (int j = start; (j < start + ChildPages.PageLimit && j < ChildPages.Count); j++)
{
var obj = m_children[j];
if (!obj)
{
GUILayout.Label("null", null);
continue;
}
UIHelpers.GameobjButton(obj.gameObject, InspectGameObject, false, m_rect.width / 2 - 60);
}
foreach (var obj in m_children.Where(x => x.childCount == 0))
{
if (!obj)
{
GUILayout.Label("null", null);
continue;
}
UIHelpers.GameobjButton(obj.gameObject, InspectGameObject, false, m_rect.width / 2 - 60);
UIHelpers.GameobjButton(obj.gameObject, InspectGameObject, false, m_rect.width / 2 - 80);
}
}
else
@ -248,17 +287,39 @@ namespace Explorer
GUILayout.Label("<i>None</i>", null);
}
GUILayout.EndScrollView();
UIHelpers.EndScrollView();
GUILayout.EndVertical();
}
private void ComponentList(Rect m_rect)
{
GUILayout.BeginVertical(GUI.skin.box, null); // new GUILayoutOption[] { GUILayout.Height(250) });
m_compScroll = GUILayout.BeginScrollView(m_compScroll, GUI.skin.scrollView);
GUILayout.BeginVertical(GUI.skin.box, null);
m_compScroll = UIHelpers.BeginScrollView(m_compScroll);
GUILayout.Label("<b><size=15>Components</size></b>", null);
GUILayout.BeginHorizontal(null);
CompPages.DrawLimitInputArea();
if (CompPages.Count > CompPages.PageLimit)
{
CompPages.CalculateMaxOffset();
CompPages.CurrentPageLabel();
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal(null);
if (GUILayout.Button("< Prev", new GUILayoutOption[] { GUILayout.Width(80) }))
{
CompPages.TurnPage(Turn.Left, ref this.m_compScroll);
}
if (GUILayout.Button("Next >", new GUILayoutOption[] { GUILayout.Width(80) }))
{
CompPages.TurnPage(Turn.Right, ref this.m_compScroll);
}
}
GUILayout.EndHorizontal();
GUI.skin.button.alignment = TextAnchor.MiddleLeft;
if (m_cachedDestroyList.Count > 0)
{
@ -267,15 +328,15 @@ namespace Explorer
if (m_components != null)
{
foreach (var component in m_components)
int start = CompPages.CalculateOffsetIndex();
for (int j = start; (j < start + CompPages.PageLimit && j < CompPages.Count); j++)
{
var component = m_components[j];
if (!component) continue;
var ilType = component.GetIl2CppType();
if (ilType == ReflectionHelpers.TransformType)
{
continue;
}
GUILayout.BeginHorizontal(null);
if (ReflectionHelpers.BehaviourType.IsAssignableFrom(ilType))
@ -286,7 +347,7 @@ namespace Explorer
{
GUILayout.Space(26);
}
if (GUILayout.Button("<color=cyan>" + ilType.Name + "</color>", new GUILayoutOption[] { GUILayout.Width(m_rect.width / 2 - 90) }))
if (GUILayout.Button("<color=cyan>" + ilType.Name + "</color>", new GUILayoutOption[] { GUILayout.Width(m_rect.width / 2 - 100) }))
{
ReflectObject(component);
}
@ -308,7 +369,7 @@ namespace Explorer
}
}
GUILayout.EndScrollView();
UIHelpers.EndScrollView();
GUILayout.EndVertical();
}

View File

@ -20,8 +20,10 @@ namespace Explorer
private CacheObjectBase[] m_allCachedMembers;
private CacheObjectBase[] m_cachedMembersFiltered;
private int m_pageOffset;
private int m_limitPerPage = 20;
public PageHelper Pages = new PageHelper();
//private int m_pageOffset;
//private int m_limitPerPage = 20;
private bool m_autoUpdate = false;
private string m_search = "";
@ -138,7 +140,7 @@ namespace Explorer
var name = $"{member.DeclaringType.Name}.{member.Name}";
// blacklist (should probably make a proper implementation)
if (name == "Type.DeclaringMethod" || member.Name.Contains("Il2CppType") || member.Name.StartsWith("get_") || member.Name.StartsWith("set_"))
if (name == "Type.DeclaringMethod" || member.Name.StartsWith("get_") || member.Name.StartsWith("set_")) //|| member.Name.Contains("Il2CppType")
{
continue;
}
@ -254,41 +256,34 @@ namespace Explorer
GUILayout.Space(10);
Pages.Count = m_cachedMembersFiltered.Length;
// prev/next page buttons
GUILayout.BeginHorizontal(null);
GUILayout.Label("<b>Limit per page:</b>", new GUILayoutOption[] { GUILayout.Width(125) });
var limitString = m_limitPerPage.ToString();
limitString = GUILayout.TextField(limitString, new GUILayoutOption[] { GUILayout.Width(60) });
if (int.TryParse(limitString, out int lim))
{
m_limitPerPage = lim;
}
int count = m_cachedMembersFiltered.Length;
if (count > m_limitPerPage)
Pages.DrawLimitInputArea();
if (Pages.Count > Pages.PageLimit)
{
int maxOffset = (int)Mathf.Ceil((float)(count / (decimal)m_limitPerPage)) - 1;
Pages.CalculateMaxOffset();
if (GUILayout.Button("< Prev", new GUILayoutOption[] { GUILayout.Width(80) }))
{
if (m_pageOffset > 0) m_pageOffset--;
scroll = Vector2.zero;
Pages.TurnPage(Turn.Left, ref this.scroll);
}
GUI.skin.label.alignment = TextAnchor.MiddleCenter;
GUILayout.Label($"Page {m_pageOffset + 1}/{maxOffset + 1}", new GUILayoutOption[] { GUILayout.Width(80) });
GUI.skin.label.alignment = TextAnchor.UpperLeft;
Pages.CurrentPageLabel();
if (GUILayout.Button("Next >", new GUILayoutOption[] { GUILayout.Width(80) }))
{
if (m_pageOffset < maxOffset) m_pageOffset++;
scroll = Vector2.zero;
Pages.TurnPage(Turn.Right, ref this.scroll);
}
}
GUILayout.EndHorizontal();
// ====== BODY ======
scroll = GUILayout.BeginScrollView(scroll, GUI.skin.scrollView);
scroll = UIHelpers.BeginScrollView(scroll);
GUILayout.Space(10);
@ -297,18 +292,9 @@ namespace Explorer
GUILayout.BeginVertical(GUI.skin.box, null);
var members = this.m_cachedMembersFiltered;
int start = m_pageOffset * m_limitPerPage;
int start = Pages.CalculateOffsetIndex();
if (start >= count)
{
int maxOffset = (int)Mathf.Ceil((float)(m_cachedMembersFiltered.Length / (decimal)m_limitPerPage)) - 1;
if (m_pageOffset > maxOffset)
{
m_pageOffset = 0;
}
}
for (int j = start; (j < start + m_limitPerPage && j < members.Length); j++)
for (int j = start; (j < start + Pages.PageLimit && j < members.Length); j++)
{
var holder = members[j];
@ -325,12 +311,12 @@ namespace Explorer
GUILayout.EndHorizontal();
// if not last element
if (!(j == (start + m_limitPerPage - 1) || j == (members.Length - 1)))
if (!(j == (start + Pages.PageLimit - 1) || j == (members.Length - 1)))
UIStyles.HorizontalLine(new Color(0.07f, 0.07f, 0.07f), true);
}
GUILayout.EndVertical();
GUILayout.EndScrollView();
UIHelpers.EndScrollView();
if (!WindowManager.TabView)
{
@ -367,7 +353,8 @@ namespace Explorer
if (GUILayout.Button(label, new GUILayoutOption[] { GUILayout.Width(100) }))
{
m_filter = mode;
m_pageOffset = 0;
Pages.PageOffset = 0;
scroll = Vector2.zero;
}
GUI.color = Color.white;
}

View File

@ -86,34 +86,50 @@ namespace Explorer
// ========= Public Helpers =========
public static UIWindow InspectObject(object obj, out bool createdNew)
public static UIWindow InspectObject(object obj, out bool createdNew, bool forceReflection = false)
{
createdNew = false;
UnityEngine.Object uObj = null;
if (obj is UnityEngine.Object)
if (Input.GetKey(KeyCode.LeftShift))
{
uObj = obj as UnityEngine.Object;
forceReflection = true;
}
Il2CppSystem.Object iObj = null;
if (obj is Il2CppSystem.Object isObj)
{
iObj = isObj;
}
foreach (var window in Windows)
if (!forceReflection)
{
bool equals = ReferenceEquals(obj, window.Target);
if (!equals && uObj != null && window.Target is UnityEngine.Object uTarget)
foreach (var window in Windows)
{
equals = uObj.m_CachedPtr == uTarget.m_CachedPtr;
}
bool equals = ReferenceEquals(obj, window.Target);
if (equals)
{
FocusWindow(window);
return window;
if (!equals && iObj is Il2CppSystem.Object iCurrent && window.Target is Il2CppSystem.Object iTarget)
{
if (iCurrent.GetIl2CppType() != iTarget.GetIl2CppType())
{
if (iCurrent is Transform transform)
{
iCurrent = transform.gameObject;
}
}
equals = iCurrent.Pointer == iTarget.Pointer;
}
if (equals)
{
FocusWindow(window);
return window;
}
}
}
createdNew = true;
if (obj is GameObject || obj is Transform)
if (!forceReflection && (obj is GameObject || obj is Transform))
{
return InspectGameObject(obj as GameObject ?? (obj as Transform).gameObject);
}
@ -144,7 +160,7 @@ namespace Explorer
return new_window;
}
public static UIWindow InspectReflection(object obj)
private static UIWindow InspectReflection(object obj)
{
var new_window = UIWindow.CreateWindow<ReflectionWindow>(obj);
FocusWindow(new_window);