mirror of
https://github.com/sinai-dev/UnityExplorer.git
synced 2025-06-16 22:27:45 +08:00
1.4.5 (pre-release)
* Added support for MethodInfos with only primitive arguments on reflection window * Added backup resize mode incase resizing experiences an exception
This commit is contained in:
parent
68eeee353e
commit
7dc58ea02c
@ -16,6 +16,10 @@ namespace Explorer
|
|||||||
private bool m_evaluated = false;
|
private bool m_evaluated = false;
|
||||||
private CacheObjectBase m_cachedReturnValue;
|
private CacheObjectBase m_cachedReturnValue;
|
||||||
|
|
||||||
|
private bool m_isEvaluating;
|
||||||
|
private ParameterInfo[] m_arguments;
|
||||||
|
private string[] m_argumentInput;
|
||||||
|
|
||||||
public bool HasParameters
|
public bool HasParameters
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
@ -29,13 +33,6 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
private bool? m_hasParams;
|
private bool? m_hasParams;
|
||||||
|
|
||||||
// ======= TODO =======
|
|
||||||
private bool m_isEvaluating;
|
|
||||||
private string[] m_argumentNames;
|
|
||||||
private Type[] m_argumentTypes;
|
|
||||||
private string[] m_argumentInput;
|
|
||||||
// =====================
|
|
||||||
|
|
||||||
public static bool CanEvaluate(MethodInfo mi)
|
public static bool CanEvaluate(MethodInfo mi)
|
||||||
{
|
{
|
||||||
// generic type args not supported yet
|
// generic type args not supported yet
|
||||||
@ -44,21 +41,15 @@ namespace Explorer
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO primitive params (commented out impl below)
|
// only primitive and string args supported
|
||||||
if (mi.GetParameters().Length > 0)
|
foreach (var param in mi.GetParameters())
|
||||||
{
|
{
|
||||||
return false;
|
if (!param.ParameterType.IsPrimitive && param.ParameterType != typeof(string))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//// only primitive and string args supported
|
|
||||||
//foreach (var param in mi.GetParameters())
|
|
||||||
//{
|
|
||||||
// if (!param.ParameterType.IsPrimitive && param.ParameterType != typeof(string))
|
|
||||||
// {
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,69 +57,68 @@ namespace Explorer
|
|||||||
{
|
{
|
||||||
base.Init();
|
base.Init();
|
||||||
|
|
||||||
// TODO cache params
|
var mi = MemberInfo as MethodInfo;
|
||||||
|
|
||||||
|
m_arguments = mi.GetParameters();
|
||||||
|
m_argumentInput = new string[m_arguments.Length];
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void UpdateValue()
|
public override void UpdateValue()
|
||||||
{
|
{
|
||||||
base.UpdateValue();
|
base.UpdateValue();
|
||||||
|
|
||||||
// TODO update params (?)
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Evaluate()
|
|
||||||
{
|
|
||||||
m_evaluated = true;
|
|
||||||
|
|
||||||
var mi = MemberInfo as MethodInfo;
|
|
||||||
|
|
||||||
object ret;
|
|
||||||
|
|
||||||
if (!HasParameters)
|
|
||||||
{
|
|
||||||
ret = mi.Invoke(mi.IsStatic ? null : DeclaringInstance, new object[0]);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// TODO parse params, invoke if valid
|
|
||||||
throw new NotImplementedException("TODO");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ret != null)
|
|
||||||
{
|
|
||||||
m_cachedReturnValue = GetCacheObject(ret);
|
|
||||||
if (m_cachedReturnValue is CacheList cacheList)
|
|
||||||
{
|
|
||||||
cacheList.WhiteSpace = 0f;
|
|
||||||
cacheList.ButtonWidthOffset += 70f;
|
|
||||||
}
|
|
||||||
m_cachedReturnValue.UpdateValue();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_cachedReturnValue = null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void DrawValue(Rect window, float width)
|
public override void DrawValue(Rect window, float width)
|
||||||
{
|
{
|
||||||
GUILayout.BeginVertical(null);
|
GUILayout.BeginVertical(null);
|
||||||
|
|
||||||
GUILayout.BeginHorizontal(null);
|
string evaluateLabel = "<color=lime>Evaluate</color>";
|
||||||
if (GUILayout.Button("Evaluate", new GUILayoutOption[] { GUILayout.Width(70) }))
|
if (HasParameters)
|
||||||
{
|
{
|
||||||
if (HasParameters)
|
if (m_isEvaluating)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException("TODO");
|
for (int i = 0; i < m_arguments.Length; i++)
|
||||||
|
{
|
||||||
|
var name = m_arguments[i].Name;
|
||||||
|
var input = m_argumentInput[i];
|
||||||
|
var type = m_arguments[i].ParameterType.Name;
|
||||||
|
|
||||||
|
GUILayout.BeginHorizontal(null);
|
||||||
|
m_argumentInput[i] = GUILayout.TextField(input, new GUILayoutOption[] { GUILayout.Width(150) });
|
||||||
|
GUILayout.Label(i + ": <color=cyan>" + name + "</color> <color=yellow>(" + type + ")</color>", null);
|
||||||
|
|
||||||
|
GUILayout.EndHorizontal();
|
||||||
|
}
|
||||||
|
|
||||||
|
GUILayout.BeginHorizontal(null);
|
||||||
|
if (GUILayout.Button(evaluateLabel, new GUILayoutOption[] { GUILayout.Width(70) }))
|
||||||
|
{
|
||||||
|
Evaluate();
|
||||||
|
m_isEvaluating = false;
|
||||||
|
}
|
||||||
|
if (GUILayout.Button("Cancel", new GUILayoutOption[] { GUILayout.Width(70) }))
|
||||||
|
{
|
||||||
|
m_isEvaluating = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
GUILayout.BeginHorizontal(null);
|
||||||
|
if (GUILayout.Button($"Evaluate ({m_arguments.Length} params)", new GUILayoutOption[] { GUILayout.Width(150) }))
|
||||||
|
{
|
||||||
|
m_isEvaluating = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GUILayout.BeginHorizontal(null);
|
||||||
|
if (GUILayout.Button(evaluateLabel, new GUILayoutOption[] { GUILayout.Width(70) }))
|
||||||
{
|
{
|
||||||
Evaluate();
|
Evaluate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
GUI.skin.label.wordWrap = false;
|
|
||||||
GUILayout.Label($"<color=yellow>{ValueType}</color>", null);
|
|
||||||
GUI.skin.label.wordWrap = true;
|
|
||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
|
|
||||||
GUILayout.BeginHorizontal(null);
|
GUILayout.BeginHorizontal(null);
|
||||||
@ -148,16 +138,88 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
GUILayout.Label($"null", null);
|
GUILayout.Label($"null (<color=yellow>{ValueType}</color>)", null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
GUILayout.Label($"<color=grey><i>Not yet evaluated</i></color>", null);
|
GUILayout.Label($"<color=grey><i>Not yet evaluated</i></color> (<color=yellow>{ValueType}</color>)", null);
|
||||||
}
|
}
|
||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
|
|
||||||
GUILayout.EndVertical();
|
GUILayout.EndVertical();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void Evaluate()
|
||||||
|
{
|
||||||
|
m_evaluated = true;
|
||||||
|
|
||||||
|
var mi = MemberInfo as MethodInfo;
|
||||||
|
|
||||||
|
object ret = null;
|
||||||
|
|
||||||
|
if (!HasParameters)
|
||||||
|
{
|
||||||
|
ret = mi.Invoke(mi.IsStatic ? null : DeclaringInstance, new object[0]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var arguments = new List<object>();
|
||||||
|
for (int i = 0; i < m_arguments.Length; i++)
|
||||||
|
{
|
||||||
|
var input = m_argumentInput[i];
|
||||||
|
var type = m_arguments[i].ParameterType;
|
||||||
|
|
||||||
|
if (type == typeof(string))
|
||||||
|
{
|
||||||
|
arguments.Add(input);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (type.GetMethod("Parse", new Type[] { typeof(string) }).Invoke(null, new object[] { input }) is object parsed)
|
||||||
|
{
|
||||||
|
arguments.Add(parsed);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new Exception();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
MelonLogger.Log($"Unable to parse '{input}' to type '{type.Name}'");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (arguments.Count == m_arguments.Length)
|
||||||
|
{
|
||||||
|
ret = mi.Invoke(mi.IsStatic ? null : DeclaringInstance, arguments.ToArray());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MelonLogger.Log($"Did not invoke because {m_arguments.Length - arguments.Count} arguments could not be parsed!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret != null)
|
||||||
|
{
|
||||||
|
m_cachedReturnValue = GetCacheObject(ret);
|
||||||
|
if (m_cachedReturnValue is CacheList cacheList)
|
||||||
|
{
|
||||||
|
cacheList.WhiteSpace = 0f;
|
||||||
|
cacheList.ButtonWidthOffset += 70f;
|
||||||
|
}
|
||||||
|
m_cachedReturnValue.UpdateValue();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_cachedReturnValue = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -69,8 +69,8 @@ namespace Explorer
|
|||||||
var newSkin = Object.Instantiate(GUI.skin);
|
var newSkin = Object.Instantiate(GUI.skin);
|
||||||
Object.DontDestroyOnLoad(newSkin);
|
Object.DontDestroyOnLoad(newSkin);
|
||||||
|
|
||||||
m_nofocusTex = MakeTex(550, 700, new Color(0.1f, 0.1f, 0.1f, 0.7f));
|
m_nofocusTex = MakeTex(1, 1, new Color(0.1f, 0.1f, 0.1f, 0.7f));
|
||||||
m_focusTex = MakeTex(550, 700, new Color(0.3f, 0.3f, 0.3f, 1f));
|
m_focusTex = MakeTex(1, 1, new Color(0.3f, 0.3f, 0.3f, 1f));
|
||||||
|
|
||||||
newSkin.window.normal.background = m_nofocusTex;
|
newSkin.window.normal.background = m_nofocusTex;
|
||||||
newSkin.window.onNormal.background = m_focusTex;
|
newSkin.window.onNormal.background = m_focusTex;
|
||||||
|
@ -12,8 +12,8 @@ namespace Explorer
|
|||||||
public class GameObjectWindow : UIWindow
|
public class GameObjectWindow : UIWindow
|
||||||
{
|
{
|
||||||
public override string Title => WindowManager.TabView
|
public override string Title => WindowManager.TabView
|
||||||
? m_object.name
|
? $"<color=cyan>[G]</color> {m_object.name}"
|
||||||
: $"GameObject Inspector ({m_object.name})";
|
: $"GameObject Inspector ({m_object.name})";
|
||||||
|
|
||||||
public GameObject m_object;
|
public GameObject m_object;
|
||||||
|
|
||||||
|
@ -13,13 +13,13 @@ namespace Explorer
|
|||||||
public class ReflectionWindow : UIWindow
|
public class ReflectionWindow : UIWindow
|
||||||
{
|
{
|
||||||
public override string Title => WindowManager.TabView
|
public override string Title => WindowManager.TabView
|
||||||
? ObjectType.Name
|
? $"<color=cyan>[R]</color> {ObjectType.Name}"
|
||||||
: $"Reflection Inspector ({ObjectType.Name})";
|
: $"Reflection Inspector ({ObjectType.Name})";
|
||||||
|
|
||||||
public Type ObjectType;
|
public Type ObjectType;
|
||||||
|
|
||||||
private CacheObjectBase[] m_cachedMembers;
|
private CacheObjectBase[] m_allCachedMembers;
|
||||||
private CacheObjectBase[] m_cachedMemberFiltered;
|
private CacheObjectBase[] m_cachedMembersFiltered;
|
||||||
private int m_pageOffset;
|
private int m_pageOffset;
|
||||||
private int m_limitPerPage = 20;
|
private int m_limitPerPage = 20;
|
||||||
|
|
||||||
@ -72,7 +72,7 @@ namespace Explorer
|
|||||||
|
|
||||||
public override void Update()
|
public override void Update()
|
||||||
{
|
{
|
||||||
m_cachedMemberFiltered = m_cachedMembers.Where(x => ShouldProcessMember(x)).ToArray();
|
m_cachedMembersFiltered = m_allCachedMembers.Where(x => ShouldProcessMember(x)).ToArray();
|
||||||
|
|
||||||
if (m_autoUpdate)
|
if (m_autoUpdate)
|
||||||
{
|
{
|
||||||
@ -82,7 +82,7 @@ namespace Explorer
|
|||||||
|
|
||||||
private void UpdateValues()
|
private void UpdateValues()
|
||||||
{
|
{
|
||||||
foreach (var member in m_cachedMemberFiltered)
|
foreach (var member in m_cachedMembersFiltered)
|
||||||
{
|
{
|
||||||
member.UpdateValue();
|
member.UpdateValue();
|
||||||
}
|
}
|
||||||
@ -140,7 +140,7 @@ namespace Explorer
|
|||||||
{
|
{
|
||||||
if (member.MemberType == MemberTypes.Field || member.MemberType == MemberTypes.Property || member.MemberType == MemberTypes.Method)
|
if (member.MemberType == MemberTypes.Field || member.MemberType == MemberTypes.Property || member.MemberType == MemberTypes.Method)
|
||||||
{
|
{
|
||||||
if (member.Name.Contains("Il2CppType") || member.Name.StartsWith("get_"))
|
if (member.Name.Contains("Il2CppType") || member.Name.StartsWith("get_") || member.Name.StartsWith("set_"))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
try
|
try
|
||||||
@ -165,7 +165,7 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_cachedMembers = list.ToArray();
|
m_allCachedMembers = list.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
// =========== GUI DRAW =========== //
|
// =========== GUI DRAW =========== //
|
||||||
@ -174,6 +174,8 @@ namespace Explorer
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
// ====== HEADER ======
|
||||||
|
|
||||||
var rect = WindowManager.TabView ? TabViewWindow.Instance.m_rect : this.m_rect;
|
var rect = WindowManager.TabView ? TabViewWindow.Instance.m_rect : this.m_rect;
|
||||||
|
|
||||||
if (!WindowManager.TabView)
|
if (!WindowManager.TabView)
|
||||||
@ -241,18 +243,17 @@ namespace Explorer
|
|||||||
|
|
||||||
GUILayout.Space(10);
|
GUILayout.Space(10);
|
||||||
|
|
||||||
|
|
||||||
// prev/next page buttons
|
// prev/next page buttons
|
||||||
GUILayout.BeginHorizontal(null);
|
GUILayout.BeginHorizontal(null);
|
||||||
GUILayout.Label("<b>Limit per page:</b>", new GUILayoutOption[] { GUILayout.Width(125) });
|
GUILayout.Label("<b>Limit per page:</b>", new GUILayoutOption[] { GUILayout.Width(125) });
|
||||||
var limitString = m_limitPerPage.ToString();
|
var limitString = m_limitPerPage.ToString();
|
||||||
limitString = GUILayout.TextField(limitString, new GUILayoutOption[] { GUILayout.Width(60) });
|
limitString = GUILayout.TextField(limitString, new GUILayoutOption[] { GUILayout.Width(60) });
|
||||||
if (int.TryParse(limitString, out int i))
|
if (int.TryParse(limitString, out int lim))
|
||||||
{
|
{
|
||||||
m_limitPerPage = i;
|
m_limitPerPage = lim;
|
||||||
}
|
}
|
||||||
|
|
||||||
int count = m_cachedMemberFiltered.Length;
|
int count = m_cachedMembersFiltered.Length;
|
||||||
if (count > m_limitPerPage)
|
if (count > m_limitPerPage)
|
||||||
{
|
{
|
||||||
int maxOffset = (int)Mathf.Ceil((float)(count / (decimal)m_limitPerPage)) - 1;
|
int maxOffset = (int)Mathf.Ceil((float)(count / (decimal)m_limitPerPage)) - 1;
|
||||||
@ -274,12 +275,47 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
|
|
||||||
|
// ====== BODY ======
|
||||||
|
|
||||||
scroll = GUILayout.BeginScrollView(scroll, GUI.skin.scrollView);
|
scroll = GUILayout.BeginScrollView(scroll, GUI.skin.scrollView);
|
||||||
|
|
||||||
GUILayout.Space(10);
|
GUILayout.Space(10);
|
||||||
|
|
||||||
DrawMembers(this.m_cachedMemberFiltered);
|
UIStyles.HorizontalLine(Color.grey);
|
||||||
|
|
||||||
|
GUILayout.BeginVertical(GUI.skin.box, null);
|
||||||
|
|
||||||
|
int index = 0;
|
||||||
|
var members = this.m_cachedMembersFiltered;
|
||||||
|
int offsetIndex = (m_pageOffset * m_limitPerPage) + index;
|
||||||
|
|
||||||
|
if (offsetIndex >= count)
|
||||||
|
{
|
||||||
|
int maxOffset = (int)Mathf.Ceil((float)(m_cachedMembersFiltered.Length / (decimal)m_limitPerPage)) - 1;
|
||||||
|
if (m_pageOffset > maxOffset)
|
||||||
|
{
|
||||||
|
m_pageOffset = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int j = offsetIndex; (j < offsetIndex + m_limitPerPage && j < members.Length); j++)
|
||||||
|
{
|
||||||
|
var holder = members[j];
|
||||||
|
|
||||||
|
GUILayout.BeginHorizontal(new GUILayoutOption[] { GUILayout.Height(25) });
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
holder.Draw(rect, 180f);
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
|
|
||||||
|
GUILayout.EndHorizontal();
|
||||||
|
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
GUILayout.EndVertical();
|
||||||
GUILayout.EndScrollView();
|
GUILayout.EndScrollView();
|
||||||
|
|
||||||
if (!WindowManager.TabView)
|
if (!WindowManager.TabView)
|
||||||
@ -289,69 +325,21 @@ namespace Explorer
|
|||||||
GUILayout.EndArea();
|
GUILayout.EndArea();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
catch (Il2CppException e)
|
||||||
|
{
|
||||||
|
if (!e.Message.Contains("in a group with only"))
|
||||||
|
{
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
MelonLogger.LogWarning("Exception on window draw. Message: " + e.Message);
|
MelonLogger.LogWarning("Exception drawing ReflectionWindow: " + e.GetType() + ", " + e.Message);
|
||||||
DestroyWindow();
|
DestroyWindow();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DrawMembers(CacheObjectBase[] members)
|
|
||||||
{
|
|
||||||
// todo pre-cache list based on current search, otherwise this doesnt work.
|
|
||||||
|
|
||||||
int i = 0;
|
|
||||||
DrawMembersInternal("Properties", MemberTypes.Property, members, ref i);
|
|
||||||
DrawMembersInternal("Fields", MemberTypes.Field, members, ref i);
|
|
||||||
DrawMembersInternal("Methods", MemberTypes.Method, members, ref i);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DrawMembersInternal(string title, MemberTypes filter, CacheObjectBase[] members, ref int index)
|
|
||||||
{
|
|
||||||
if (m_filter != filter && m_filter != MemberTypes.All)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var rect = WindowManager.TabView ? TabViewWindow.Instance.m_rect : this.m_rect;
|
|
||||||
|
|
||||||
UIStyles.HorizontalLine(Color.grey);
|
|
||||||
|
|
||||||
GUILayout.Label($"<size=18><b><color=gold>{title}</color></b></size>", null);
|
|
||||||
|
|
||||||
int offset = (m_pageOffset * m_limitPerPage) + index;
|
|
||||||
|
|
||||||
if (offset >= m_cachedMemberFiltered.Length)
|
|
||||||
{
|
|
||||||
m_pageOffset = 0;
|
|
||||||
offset = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int j = offset; j < offset + m_limitPerPage && j < members.Length; j++)
|
|
||||||
{
|
|
||||||
var holder = members[j];
|
|
||||||
|
|
||||||
if (holder.MemberInfoType != filter || !ShouldProcessMember(holder)) continue;
|
|
||||||
|
|
||||||
GUILayout.BeginHorizontal(new GUILayoutOption[] { GUILayout.Height(25) });
|
|
||||||
try
|
|
||||||
{
|
|
||||||
holder.Draw(rect, 180f);
|
|
||||||
}
|
|
||||||
catch // (Exception e)
|
|
||||||
{
|
|
||||||
//MelonLogger.Log("Exception drawing member " + holder.MemberInfo.Name);
|
|
||||||
//MelonLogger.Log(e.GetType() + ", " + e.Message);
|
|
||||||
//MelonLogger.Log(e.StackTrace);
|
|
||||||
}
|
|
||||||
GUILayout.EndHorizontal();
|
|
||||||
|
|
||||||
index++;
|
|
||||||
if (index >= m_limitPerPage) break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void FilterToggle(MemberTypes mode, string label)
|
private void FilterToggle(MemberTypes mode, string label)
|
||||||
{
|
{
|
||||||
if (m_filter == mode)
|
if (m_filter == mode)
|
||||||
@ -365,6 +353,7 @@ namespace Explorer
|
|||||||
if (GUILayout.Button(label, new GUILayoutOption[] { GUILayout.Width(100) }))
|
if (GUILayout.Button(label, new GUILayoutOption[] { GUILayout.Width(100) }))
|
||||||
{
|
{
|
||||||
m_filter = mode;
|
m_filter = mode;
|
||||||
|
m_pageOffset = 0;
|
||||||
}
|
}
|
||||||
GUI.color = Color.white;
|
GUI.color = Color.white;
|
||||||
}
|
}
|
||||||
|
@ -20,55 +20,85 @@ namespace Explorer
|
|||||||
|
|
||||||
public static Rect ResizeWindow(Rect _rect, int ID)
|
public static Rect ResizeWindow(Rect _rect, int ID)
|
||||||
{
|
{
|
||||||
if (RESIZE_FAILED) return _rect;
|
if (!RESIZE_FAILED)
|
||||||
|
{
|
||||||
|
var origRect = _rect;
|
||||||
|
|
||||||
var origRect = _rect;
|
try
|
||||||
|
{
|
||||||
|
GUILayout.BeginHorizontal(GUI.skin.box, null);
|
||||||
|
|
||||||
try
|
GUI.skin.label.alignment = TextAnchor.MiddleCenter;
|
||||||
|
GUILayout.Button(gcDrag, GUI.skin.label, new GUILayoutOption[] { GUILayout.Height(15) });
|
||||||
|
|
||||||
|
var r = GUILayoutUtility.GetLastRect();
|
||||||
|
|
||||||
|
Vector2 mouse = GUIUtility.ScreenToGUIPoint(new Vector2(Input.mousePosition.x, Screen.height - Input.mousePosition.y));
|
||||||
|
|
||||||
|
if (r.Contains(mouse) && Input.GetMouseButtonDown(0))
|
||||||
|
{
|
||||||
|
isResizing = true;
|
||||||
|
m_currentWindow = ID;
|
||||||
|
m_currentResize = new Rect(mouse.x, mouse.y, _rect.width, _rect.height);
|
||||||
|
}
|
||||||
|
else if (!Input.GetMouseButton(0))
|
||||||
|
{
|
||||||
|
isResizing = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isResizing && ID == m_currentWindow)
|
||||||
|
{
|
||||||
|
_rect.width = Mathf.Max(100, m_currentResize.width + (mouse.x - m_currentResize.x));
|
||||||
|
_rect.height = Mathf.Max(100, m_currentResize.height + (mouse.y - m_currentResize.y));
|
||||||
|
_rect.xMax = Mathf.Min(Screen.width, _rect.xMax); // modifying xMax affects width, not x
|
||||||
|
_rect.yMax = Mathf.Min(Screen.height, _rect.yMax); // modifying yMax affects height, not y
|
||||||
|
}
|
||||||
|
|
||||||
|
GUILayout.EndHorizontal();
|
||||||
|
}
|
||||||
|
catch (Il2CppException e) when (e.Message.StartsWith("System.ArgumentException"))
|
||||||
|
{
|
||||||
|
// suppress
|
||||||
|
return origRect;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
RESIZE_FAILED = true;
|
||||||
|
MelonLogger.Log("Exception on GuiResize: " + e.GetType() + ", " + e.Message);
|
||||||
|
return origRect;
|
||||||
|
}
|
||||||
|
|
||||||
|
GUI.skin.label.alignment = TextAnchor.UpperLeft;
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
GUILayout.BeginHorizontal(GUI.skin.box, null);
|
GUILayout.BeginHorizontal(GUI.skin.box, null);
|
||||||
|
|
||||||
GUI.skin.label.alignment = TextAnchor.MiddleCenter;
|
GUILayout.Label("Resize window:", new GUILayoutOption[] { GUILayout.Width(100) });
|
||||||
GUILayout.Button(gcDrag, GUI.skin.label, new GUILayoutOption[] { GUILayout.Height(15) });
|
|
||||||
|
|
||||||
var r = GUILayoutUtility.GetLastRect();
|
GUI.skin.label.alignment = TextAnchor.MiddleRight;
|
||||||
|
GUILayout.Label("<color=cyan>Width:</color>", new GUILayoutOption[] { GUILayout.Width(60) });
|
||||||
Vector2 mouse = GUIUtility.ScreenToGUIPoint(new Vector2(Input.mousePosition.x, Screen.height - Input.mousePosition.y));
|
if (GUILayout.RepeatButton("-", new GUILayoutOption[] { GUILayout.Width(20) }))
|
||||||
|
|
||||||
if (r.Contains(mouse) && Input.GetMouseButtonDown(0))
|
|
||||||
{
|
{
|
||||||
isResizing = true;
|
_rect.width -= 5f;
|
||||||
m_currentWindow = ID;
|
|
||||||
m_currentResize = new Rect(mouse.x, mouse.y, _rect.width, _rect.height);
|
|
||||||
}
|
}
|
||||||
else if (!Input.GetMouseButton(0))
|
if (GUILayout.RepeatButton("+", new GUILayoutOption[] { GUILayout.Width(20) }))
|
||||||
{
|
{
|
||||||
isResizing = false;
|
_rect.width += 5f;
|
||||||
}
|
}
|
||||||
|
GUILayout.Label("<color=cyan>Height:</color>", new GUILayoutOption[] { GUILayout.Width(60) });
|
||||||
if (isResizing && ID == m_currentWindow)
|
if (GUILayout.RepeatButton("-", new GUILayoutOption[] { GUILayout.Width(20) }))
|
||||||
{
|
{
|
||||||
_rect.width = Mathf.Max(100, m_currentResize.width + (mouse.x - m_currentResize.x));
|
_rect.height -= 5f;
|
||||||
_rect.height = Mathf.Max(100, m_currentResize.height + (mouse.y - m_currentResize.y));
|
}
|
||||||
_rect.xMax = Mathf.Min(Screen.width, _rect.xMax); // modifying xMax affects width, not x
|
if (GUILayout.RepeatButton("+", new GUILayoutOption[] { GUILayout.Width(20) }))
|
||||||
_rect.yMax = Mathf.Min(Screen.height, _rect.yMax); // modifying yMax affects height, not y
|
{
|
||||||
|
_rect.height += 5f;
|
||||||
}
|
}
|
||||||
|
|
||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
|
GUI.skin.label.alignment = TextAnchor.UpperLeft;
|
||||||
}
|
}
|
||||||
catch (Il2CppException e) when (e.Message.StartsWith("System.ArgumentException"))
|
|
||||||
{
|
|
||||||
// suppress
|
|
||||||
return origRect;
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
RESIZE_FAILED = true;
|
|
||||||
MelonLogger.Log("Exception on GuiResize: " + e.GetType() + ", " + e.Message);
|
|
||||||
return origRect;
|
|
||||||
}
|
|
||||||
|
|
||||||
GUI.skin.label.alignment = TextAnchor.UpperLeft;
|
|
||||||
|
|
||||||
return _rect;
|
return _rect;
|
||||||
}
|
}
|
||||||
|
@ -3,17 +3,19 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using MelonLoader;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace Explorer
|
namespace Explorer
|
||||||
{
|
{
|
||||||
public class TabViewWindow : UIWindow
|
public class TabViewWindow : UIWindow
|
||||||
{
|
{
|
||||||
public override string Title => "Tab View";
|
public override string Title => $"Tabs ({WindowManager.Windows.Count})";
|
||||||
|
|
||||||
public static TabViewWindow Instance => m_instance ?? (m_instance = new TabViewWindow());
|
public static TabViewWindow Instance => m_instance ?? (m_instance = new TabViewWindow());
|
||||||
private static TabViewWindow m_instance;
|
private static TabViewWindow m_instance;
|
||||||
|
|
||||||
|
private UIWindow m_targetWindow;
|
||||||
public int TargetTabID = 0;
|
public int TargetTabID = 0;
|
||||||
|
|
||||||
public override bool IsTabViewWindow => true;
|
public override bool IsTabViewWindow => true;
|
||||||
@ -24,13 +26,43 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
|
|
||||||
public override void Init() { }
|
public override void Init() { }
|
||||||
public override void Update() { }
|
public override void Update()
|
||||||
|
{
|
||||||
|
while (TargetTabID >= WindowManager.Windows.Count)
|
||||||
|
{
|
||||||
|
TargetTabID--;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TargetTabID == -1 && WindowManager.Windows.Count > 0)
|
||||||
|
{
|
||||||
|
TargetTabID = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TargetTabID >= 0)
|
||||||
|
{
|
||||||
|
m_targetWindow = WindowManager.Windows[TargetTabID];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_targetWindow = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_targetWindow?.Update();
|
||||||
|
}
|
||||||
|
|
||||||
public override void WindowFunction(int windowID)
|
public override void WindowFunction(int windowID)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Header();
|
GUI.DragWindow(new Rect(0, 0, m_rect.width - 90, 20));
|
||||||
|
if (GUI.Button(new Rect(m_rect.width - 90, 2, 80, 20), "<color=red>Close All</color>"))
|
||||||
|
{
|
||||||
|
foreach (var window in WindowManager.Windows)
|
||||||
|
{
|
||||||
|
window.DestroyWindow();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
GUILayout.BeginArea(new Rect(5, 25, m_rect.width - 10, m_rect.height - 35), GUI.skin.box);
|
GUILayout.BeginArea(new Rect(5, 25, m_rect.width - 10, m_rect.height - 35), GUI.skin.box);
|
||||||
|
|
||||||
@ -51,6 +83,7 @@ namespace Explorer
|
|||||||
|
|
||||||
bool focused = i == TargetTabID;
|
bool focused = i == TargetTabID;
|
||||||
string color = focused ? "<color=lime>" : "<color=orange>";
|
string color = focused ? "<color=lime>" : "<color=orange>";
|
||||||
|
GUI.color = focused ? Color.green : Color.white;
|
||||||
|
|
||||||
var window = WindowManager.Windows[i];
|
var window = WindowManager.Windows[i];
|
||||||
if (GUILayout.Button(color + window.Title + "</color>", new GUILayoutOption[] { GUILayout.Width(200) }))
|
if (GUILayout.Button(color + window.Title + "</color>", new GUILayoutOption[] { GUILayout.Width(200) }))
|
||||||
@ -62,20 +95,12 @@ namespace Explorer
|
|||||||
window.DestroyWindow();
|
window.DestroyWindow();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
GUI.color = Color.white;
|
||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
GUILayout.EndVertical();
|
GUILayout.EndVertical();
|
||||||
GUI.skin.button.alignment = TextAnchor.MiddleCenter;
|
GUI.skin.button.alignment = TextAnchor.MiddleCenter;
|
||||||
|
|
||||||
while (TargetTabID >= WindowManager.Windows.Count)
|
m_targetWindow.WindowFunction(m_targetWindow.windowID);
|
||||||
{
|
|
||||||
TargetTabID--;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (TargetTabID >= 0)
|
|
||||||
{
|
|
||||||
var window = WindowManager.Windows[TargetTabID];
|
|
||||||
window.WindowFunction(window.windowID);
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -7,8 +7,6 @@ using MelonLoader;
|
|||||||
using UnhollowerBaseLib;
|
using UnhollowerBaseLib;
|
||||||
using UnhollowerRuntimeLib;
|
using UnhollowerRuntimeLib;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.Events;
|
|
||||||
using UnityEngine.EventSystems;
|
|
||||||
|
|
||||||
namespace Explorer
|
namespace Explorer
|
||||||
{
|
{
|
||||||
@ -46,15 +44,7 @@ namespace Explorer
|
|||||||
|
|
||||||
public void DestroyWindow()
|
public void DestroyWindow()
|
||||||
{
|
{
|
||||||
try
|
WindowManager.DestroyWindow(this);
|
||||||
{
|
|
||||||
WindowManager.Windows.Remove(this);
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
MelonLogger.Log("Exception removing Window from WindowManager.Windows list!");
|
|
||||||
MelonLogger.Log($"{e.GetType()} : {e.Message}\r\n{e.StackTrace}");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnGUI()
|
public void OnGUI()
|
||||||
@ -72,12 +62,10 @@ namespace Explorer
|
|||||||
|
|
||||||
public void Header()
|
public void Header()
|
||||||
{
|
{
|
||||||
if (!WindowManager.TabView || IsTabViewWindow)
|
|
||||||
{
|
|
||||||
GUI.DragWindow(new Rect(0, 0, m_rect.width - 90, 20));
|
|
||||||
}
|
|
||||||
if (!WindowManager.TabView)
|
if (!WindowManager.TabView)
|
||||||
{
|
{
|
||||||
|
GUI.DragWindow(new Rect(0, 0, m_rect.width - 90, 20));
|
||||||
|
|
||||||
if (GUI.Button(new Rect(m_rect.width - 90, 2, 80, 20), "<color=red><b>X</b></color>"))
|
if (GUI.Button(new Rect(m_rect.width - 90, 2, 80, 20), "<color=red><b>X</b></color>"))
|
||||||
{
|
{
|
||||||
DestroyWindow();
|
DestroyWindow();
|
||||||
|
@ -22,19 +22,46 @@ namespace Explorer
|
|||||||
public static int CurrentWindowID { get; set; } = 500000;
|
public static int CurrentWindowID { get; set; } = 500000;
|
||||||
private static Rect m_lastWindowRect;
|
private static Rect m_lastWindowRect;
|
||||||
|
|
||||||
|
private static readonly List<UIWindow> m_windowsToDestroy = new List<UIWindow>();
|
||||||
|
|
||||||
public WindowManager()
|
public WindowManager()
|
||||||
{
|
{
|
||||||
Instance = this;
|
Instance = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void DestroyWindow(UIWindow window)
|
||||||
|
{
|
||||||
|
m_windowsToDestroy.Add(window);
|
||||||
|
}
|
||||||
|
|
||||||
public void Update()
|
public void Update()
|
||||||
{
|
{
|
||||||
for (int i = 0; i < Windows.Count; i++)
|
if (m_windowsToDestroy.Count > 0)
|
||||||
{
|
{
|
||||||
var window = Windows[i];
|
foreach (var window in m_windowsToDestroy)
|
||||||
if (window != null)
|
|
||||||
{
|
{
|
||||||
window.Update();
|
if (Windows.Contains(window))
|
||||||
|
{
|
||||||
|
Windows.Remove(window);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_windowsToDestroy.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TabView)
|
||||||
|
{
|
||||||
|
TabViewWindow.Instance.Update();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (int i = 0; i < Windows.Count; i++)
|
||||||
|
{
|
||||||
|
var window = Windows[i];
|
||||||
|
if (window != null)
|
||||||
|
{
|
||||||
|
window.Update();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user