some early steps remaking the GUI with UnityEngine.UI, working in all tested game so far

This commit is contained in:
sinaioutlander 2020-10-23 01:48:00 +11:00
parent 48ed78ec36
commit 4280a071f6
79 changed files with 2206 additions and 10276 deletions

BIN
resources/cursor.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -1,26 +1,26 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Explorer.UI;
//using System;
//using System.Collections;
//using System.Collections.Generic;
//using System.Linq;
//using System.Text;
//using Explorer.UI;
namespace Explorer.CacheObject
{
public class CacheEnumerated : CacheObjectBase
{
public int Index { get; set; }
public IList RefIList { get; set; }
public InteractiveEnumerable ParentEnumeration { get; set; }
//namespace Explorer.CacheObject
//{
// public class CacheEnumerated : CacheObjectBase
// {
// public int Index { get; set; }
// public IList RefIList { get; set; }
// public InteractiveEnumerable ParentEnumeration { get; set; }
public override bool CanWrite => RefIList != null && ParentEnumeration.OwnerCacheObject.CanWrite;
// public override bool CanWrite => RefIList != null && ParentEnumeration.OwnerCacheObject.CanWrite;
public override void SetValue()
{
RefIList[Index] = IValue.Value;
ParentEnumeration.Value = RefIList;
// public override void SetValue()
// {
// RefIList[Index] = IValue.Value;
// ParentEnumeration.Value = RefIList;
ParentEnumeration.OwnerCacheObject.SetValue();
}
}
}
// ParentEnumeration.OwnerCacheObject.SetValue();
// }
// }
//}

View File

@ -1,76 +1,76 @@
using System;
using System.Reflection;
using Explorer.CacheObject;
using UnityEngine;
using Explorer.Helpers;
//using System;
//using System.Reflection;
//using Explorer.CacheObject;
//using UnityEngine;
//using Explorer.Helpers;
namespace Explorer
{
public static class CacheFactory
{
public static CacheObjectBase GetCacheObject(object obj)
{
if (obj == null) return null;
//namespace Explorer
//{
// public static class CacheFactory
// {
// public static CacheObjectBase GetCacheObject(object obj)
// {
// if (obj == null) return null;
return GetCacheObject(obj, ReflectionHelpers.GetActualType(obj));
}
// return GetCacheObject(obj, ReflectionHelpers.GetActualType(obj));
// }
public static CacheObjectBase GetCacheObject(object obj, Type type)
{
var ret = new CacheObjectBase();
ret.Init(obj, type);
return ret;
}
// public static CacheObjectBase GetCacheObject(object obj, Type type)
// {
// var ret = new CacheObjectBase();
// ret.Init(obj, type);
// return ret;
// }
public static CacheMember GetCacheObject(MemberInfo member, object declaringInstance)
{
CacheMember ret;
// public static CacheMember GetCacheObject(MemberInfo member, object declaringInstance)
// {
// CacheMember ret;
if (member is MethodInfo mi && CanProcessArgs(mi.GetParameters()))
{
ret = new CacheMethod();
ret.InitMember(mi, declaringInstance);
}
else if (member is PropertyInfo pi && CanProcessArgs(pi.GetIndexParameters()))
{
ret = new CacheProperty();
ret.InitMember(pi, declaringInstance);
}
else if (member is FieldInfo fi)
{
ret = new CacheField();
ret.InitMember(fi, declaringInstance);
}
else
{
return null;
}
// if (member is MethodInfo mi && CanProcessArgs(mi.GetParameters()))
// {
// ret = new CacheMethod();
// ret.InitMember(mi, declaringInstance);
// }
// else if (member is PropertyInfo pi && CanProcessArgs(pi.GetIndexParameters()))
// {
// ret = new CacheProperty();
// ret.InitMember(pi, declaringInstance);
// }
// else if (member is FieldInfo fi)
// {
// ret = new CacheField();
// ret.InitMember(fi, declaringInstance);
// }
// else
// {
// return null;
// }
return ret;
}
// return ret;
// }
public static bool CanProcessArgs(ParameterInfo[] parameters)
{
foreach (var param in parameters)
{
var pType = param.ParameterType;
// public static bool CanProcessArgs(ParameterInfo[] parameters)
// {
// foreach (var param in parameters)
// {
// var pType = param.ParameterType;
if (pType.IsByRef && pType.HasElementType)
{
pType = pType.GetElementType();
}
// if (pType.IsByRef && pType.HasElementType)
// {
// pType = pType.GetElementType();
// }
if (pType.IsPrimitive || pType == typeof(string))
{
continue;
}
else
{
return false;
}
}
// if (pType.IsPrimitive || pType == typeof(string))
// {
// continue;
// }
// else
// {
// return false;
// }
// }
return true;
}
}
}
// return true;
// }
// }
//}

View File

@ -1,54 +1,54 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using Explorer.UI;
using Explorer.Helpers;
//using System;
//using System.Collections.Generic;
//using System.Linq;
//using System.Text;
//using System.Reflection;
//using Explorer.UI;
//using Explorer.Helpers;
namespace Explorer.CacheObject
{
public class CacheField : CacheMember
{
public override bool IsStatic => (MemInfo as FieldInfo).IsStatic;
//namespace Explorer.CacheObject
//{
// public class CacheField : CacheMember
// {
// public override bool IsStatic => (MemInfo as FieldInfo).IsStatic;
public override void InitMember(MemberInfo member, object declaringInstance)
{
base.InitMember(member, declaringInstance);
// public override void InitMember(MemberInfo member, object declaringInstance)
// {
// base.InitMember(member, declaringInstance);
base.Init(null, (member as FieldInfo).FieldType);
// base.Init(null, (member as FieldInfo).FieldType);
UpdateValue();
}
// UpdateValue();
// }
public override void UpdateValue()
{
if (IValue is InteractiveDictionary iDict)
{
if (!iDict.EnsureDictionaryIsSupported())
{
ReflectionException = "Not supported due to TypeInitializationException";
return;
}
}
// public override void UpdateValue()
// {
// if (IValue is InteractiveDictionary iDict)
// {
// if (!iDict.EnsureDictionaryIsSupported())
// {
// ReflectionException = "Not supported due to TypeInitializationException";
// return;
// }
// }
try
{
var fi = MemInfo as FieldInfo;
IValue.Value = fi.GetValue(fi.IsStatic ? null : DeclaringInstance);
// try
// {
// var fi = MemInfo as FieldInfo;
// IValue.Value = fi.GetValue(fi.IsStatic ? null : DeclaringInstance);
base.UpdateValue();
}
catch (Exception e)
{
ReflectionException = ReflectionHelpers.ExceptionToString(e);
}
}
// base.UpdateValue();
// }
// catch (Exception e)
// {
// ReflectionException = ReflectionHelpers.ExceptionToString(e);
// }
// }
public override void SetValue()
{
var fi = MemInfo as FieldInfo;
fi.SetValue(fi.IsStatic ? null : DeclaringInstance, IValue.Value);
}
}
}
// public override void SetValue()
// {
// var fi = MemInfo as FieldInfo;
// fi.SetValue(fi.IsStatic ? null : DeclaringInstance, IValue.Value);
// }
// }
//}

View File

@ -1,226 +1,226 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using UnityEngine;
using Explorer.UI;
using Explorer.UI.Shared;
//using System;
//using System.Collections.Generic;
//using System.Linq;
//using System.Reflection;
//using UnityEngine;
//using Explorer.UI;
//using Explorer.UI.Shared;
namespace Explorer.CacheObject
{
public class CacheMember : CacheObjectBase
{
public MemberInfo MemInfo { get; set; }
public Type DeclaringType { get; set; }
public object DeclaringInstance { get; set; }
//namespace Explorer.CacheObject
//{
// public class CacheMember : CacheObjectBase
// {
// public MemberInfo MemInfo { get; set; }
// public Type DeclaringType { get; set; }
// public object DeclaringInstance { get; set; }
public virtual bool IsStatic { get; private set; }
// public virtual bool IsStatic { get; private set; }
public override bool HasParameters => m_arguments != null && m_arguments.Length > 0;
public override bool IsMember => true;
// public override bool HasParameters => m_arguments != null && m_arguments.Length > 0;
// public override bool IsMember => true;
public string RichTextName => m_richTextName ?? GetRichTextName();
private string m_richTextName;
// public string RichTextName => m_richTextName ?? GetRichTextName();
// private string m_richTextName;
public override bool CanWrite => m_canWrite ?? GetCanWrite();
private bool? m_canWrite;
// public override bool CanWrite => m_canWrite ?? GetCanWrite();
// private bool? m_canWrite;
public string ReflectionException { get; set; }
// public string ReflectionException { get; set; }
public bool m_evaluated = false;
public bool m_isEvaluating;
public ParameterInfo[] m_arguments = new ParameterInfo[0];
public string[] m_argumentInput = new string[0];
// public bool m_evaluated = false;
// public bool m_isEvaluating;
// public ParameterInfo[] m_arguments = new ParameterInfo[0];
// public string[] m_argumentInput = new string[0];
public virtual void InitMember(MemberInfo member, object declaringInstance)
{
MemInfo = member;
DeclaringInstance = declaringInstance;
DeclaringType = member.DeclaringType;
}
// public virtual void InitMember(MemberInfo member, object declaringInstance)
// {
// MemInfo = member;
// DeclaringInstance = declaringInstance;
// DeclaringType = member.DeclaringType;
// }
public override void UpdateValue()
{
base.UpdateValue();
}
// public override void UpdateValue()
// {
// base.UpdateValue();
// }
public override void SetValue()
{
// ...
}
// public override void SetValue()
// {
// // ...
// }
public object[] ParseArguments()
{
if (m_arguments.Length < 1)
{
return new object[0];
}
// public object[] ParseArguments()
// {
// if (m_arguments.Length < 1)
// {
// return new object[0];
// }
var parsedArgs = new List<object>();
for (int i = 0; i < m_arguments.Length; i++)
{
var input = m_argumentInput[i];
var type = m_arguments[i].ParameterType;
// var parsedArgs = 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.IsByRef)
{
type = type.GetElementType();
}
// if (type.IsByRef)
// {
// type = type.GetElementType();
// }
if (!string.IsNullOrEmpty(input))
{
if (type == typeof(string))
{
parsedArgs.Add(input);
continue;
}
else
{
try
{
var arg = type.GetMethod("Parse", new Type[] { typeof(string) })
.Invoke(null, new object[] { input });
// if (!string.IsNullOrEmpty(input))
// {
// if (type == typeof(string))
// {
// parsedArgs.Add(input);
// continue;
// }
// else
// {
// try
// {
// var arg = type.GetMethod("Parse", new Type[] { typeof(string) })
// .Invoke(null, new object[] { input });
parsedArgs.Add(arg);
continue;
}
catch
{
ExplorerCore.Log($"Argument #{i} '{m_arguments[i].Name}' ({type.Name}), could not parse input '{input}'.");
}
}
}
// parsedArgs.Add(arg);
// continue;
// }
// catch
// {
// ExplorerCore.Log($"Argument #{i} '{m_arguments[i].Name}' ({type.Name}), could not parse input '{input}'.");
// }
// }
// }
// No input, see if there is a default value.
if (HasDefaultValue(m_arguments[i]))
{
parsedArgs.Add(m_arguments[i].DefaultValue);
continue;
}
// // No input, see if there is a default value.
// if (HasDefaultValue(m_arguments[i]))
// {
// parsedArgs.Add(m_arguments[i].DefaultValue);
// continue;
// }
// Try add a null arg I guess
parsedArgs.Add(null);
}
// // Try add a null arg I guess
// parsedArgs.Add(null);
// }
return parsedArgs.ToArray();
}
// return parsedArgs.ToArray();
// }
public static bool HasDefaultValue(ParameterInfo arg) => arg.DefaultValue != DBNull.Value;
// public static bool HasDefaultValue(ParameterInfo arg) => arg.DefaultValue != DBNull.Value;
public void DrawArgsInput()
{
GUILayout.Label($"<b><color=orange>Arguments:</color></b>", new GUILayoutOption[0]);
for (int i = 0; i < this.m_arguments.Length; i++)
{
var name = this.m_arguments[i].Name;
var input = this.m_argumentInput[i];
var type = this.m_arguments[i].ParameterType.Name;
// public void DrawArgsInput()
// {
// GUILayout.Label($"<b><color=orange>Arguments:</color></b>", new GUILayoutOption[0]);
// for (int i = 0; i < this.m_arguments.Length; i++)
// {
// var name = this.m_arguments[i].Name;
// var input = this.m_argumentInput[i];
// var type = this.m_arguments[i].ParameterType.Name;
var label = $"<color={Syntax.Class_Instance}>{type}</color> ";
label += $"<color={Syntax.Local}>{name}</color>";
if (HasDefaultValue(this.m_arguments[i]))
{
label = $"<i>[{label} = {this.m_arguments[i].DefaultValue ?? "null"}]</i>";
}
// var label = $"<color={Syntax.Class_Instance}>{type}</color> ";
// label += $"<color={Syntax.Local}>{name}</color>";
// if (HasDefaultValue(this.m_arguments[i]))
// {
// label = $"<i>[{label} = {this.m_arguments[i].DefaultValue ?? "null"}]</i>";
// }
GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
// GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUI.skin.label.alignment = TextAnchor.MiddleCenter;
// GUI.skin.label.alignment = TextAnchor.MiddleCenter;
GUILayout.Label(i.ToString(), new GUILayoutOption[] { GUILayout.Width(15) });
GUILayout.Label(label, new GUILayoutOption[] { GUIHelper.ExpandWidth(false) });
this.m_argumentInput[i] = GUIHelper.TextField(input, new GUILayoutOption[] { GUIHelper.ExpandWidth(true) });
// GUILayout.Label(i.ToString(), new GUILayoutOption[] { GUILayout.Width(15) });
// GUILayout.Label(label, new GUILayoutOption[] { GUILayout.ExpandWidth(false) });
// this.m_argumentInput[i] = GUIHelper.TextField(input, new GUILayoutOption[] { GUILayout.ExpandWidth(true) });
GUI.skin.label.alignment = TextAnchor.MiddleLeft;
// GUI.skin.label.alignment = TextAnchor.MiddleLeft;
GUILayout.EndHorizontal();
}
}
// GUILayout.EndHorizontal();
// }
// }
private bool GetCanWrite()
{
if (MemInfo is FieldInfo fi)
m_canWrite = !(fi.IsLiteral && !fi.IsInitOnly);
else if (MemInfo is PropertyInfo pi)
m_canWrite = pi.CanWrite;
else
m_canWrite = false;
// private bool GetCanWrite()
// {
// if (MemInfo is FieldInfo fi)
// m_canWrite = !(fi.IsLiteral && !fi.IsInitOnly);
// else if (MemInfo is PropertyInfo pi)
// m_canWrite = pi.CanWrite;
// else
// m_canWrite = false;
return (bool)m_canWrite;
}
// return (bool)m_canWrite;
// }
private string GetRichTextName()
{
string memberColor = "";
bool isStatic = false;
// private string GetRichTextName()
// {
// string memberColor = "";
// bool isStatic = false;
if (MemInfo is FieldInfo fi)
{
if (fi.IsStatic)
{
isStatic = true;
memberColor = Syntax.Field_Static;
}
else
memberColor = Syntax.Field_Instance;
}
else if (MemInfo is MethodInfo mi)
{
if (mi.IsStatic)
{
isStatic = true;
memberColor = Syntax.Method_Static;
}
else
memberColor = Syntax.Method_Instance;
}
else if (MemInfo is PropertyInfo pi)
{
if (pi.GetAccessors()[0].IsStatic)
{
isStatic = true;
memberColor = Syntax.Prop_Static;
}
else
memberColor = Syntax.Prop_Instance;
}
// if (MemInfo is FieldInfo fi)
// {
// if (fi.IsStatic)
// {
// isStatic = true;
// memberColor = Syntax.Field_Static;
// }
// else
// memberColor = Syntax.Field_Instance;
// }
// else if (MemInfo is MethodInfo mi)
// {
// if (mi.IsStatic)
// {
// isStatic = true;
// memberColor = Syntax.Method_Static;
// }
// else
// memberColor = Syntax.Method_Instance;
// }
// else if (MemInfo is PropertyInfo pi)
// {
// if (pi.GetAccessors()[0].IsStatic)
// {
// isStatic = true;
// memberColor = Syntax.Prop_Static;
// }
// else
// memberColor = Syntax.Prop_Instance;
// }
string classColor;
if (MemInfo.DeclaringType.IsValueType)
{
classColor = Syntax.StructGreen;
}
else if (MemInfo.DeclaringType.IsAbstract && MemInfo.DeclaringType.IsSealed)
{
classColor = Syntax.Class_Static;
}
else
{
classColor = Syntax.Class_Instance;
}
// string classColor;
// if (MemInfo.DeclaringType.IsValueType)
// {
// classColor = Syntax.StructGreen;
// }
// else if (MemInfo.DeclaringType.IsAbstract && MemInfo.DeclaringType.IsSealed)
// {
// classColor = Syntax.Class_Static;
// }
// else
// {
// classColor = Syntax.Class_Instance;
// }
m_richTextName = $"<color={classColor}>{MemInfo.DeclaringType.Name}</color>.";
if (isStatic) m_richTextName += "<i>";
m_richTextName += $"<color={memberColor}>{MemInfo.Name}</color>";
if (isStatic) m_richTextName += "</i>";
// m_richTextName = $"<color={classColor}>{MemInfo.DeclaringType.Name}</color>.";
// if (isStatic) m_richTextName += "<i>";
// m_richTextName += $"<color={memberColor}>{MemInfo.Name}</color>";
// if (isStatic) m_richTextName += "</i>";
// generic method args
if (this is CacheMethod cm && cm.GenericArgs.Length > 0)
{
m_richTextName += "<";
// // generic method args
// if (this is CacheMethod cm && cm.GenericArgs.Length > 0)
// {
// m_richTextName += "<";
var args = "";
for (int i = 0; i < cm.GenericArgs.Length; i++)
{
if (args != "") args += ", ";
args += $"<color={Syntax.StructGreen}>{cm.GenericArgs[i].Name}</color>";
}
m_richTextName += args;
// var args = "";
// for (int i = 0; i < cm.GenericArgs.Length; i++)
// {
// if (args != "") args += ", ";
// args += $"<color={Syntax.StructGreen}>{cm.GenericArgs[i].Name}</color>";
// }
// m_richTextName += args;
m_richTextName += ">";
}
// m_richTextName += ">";
// }
return m_richTextName;
}
}
}
// return m_richTextName;
// }
// }
//}

View File

@ -1,200 +1,200 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using UnityEngine;
using Explorer.UI.Shared;
using Explorer.Helpers;
//using System;
//using System.Collections.Generic;
//using System.Linq;
//using System.Reflection;
//using UnityEngine;
//using Explorer.UI.Shared;
//using Explorer.Helpers;
namespace Explorer.CacheObject
{
public class CacheMethod : CacheMember
{
private CacheObjectBase m_cachedReturnValue;
//namespace Explorer.CacheObject
//{
// public class CacheMethod : CacheMember
// {
// private CacheObjectBase m_cachedReturnValue;
public override bool HasParameters => base.HasParameters || GenericArgs.Length > 0;
// public override bool HasParameters => base.HasParameters || GenericArgs.Length > 0;
public override bool IsStatic => (MemInfo as MethodInfo).IsStatic;
// public override bool IsStatic => (MemInfo as MethodInfo).IsStatic;
public Type[] GenericArgs { get; private set; }
public Type[][] GenericConstraints { get; private set; }
// public Type[] GenericArgs { get; private set; }
// public Type[][] GenericConstraints { get; private set; }
public string[] GenericArgInput = new string[0];
// public string[] GenericArgInput = new string[0];
public override void InitMember(MemberInfo member, object declaringInstance)
{
base.InitMember(member, declaringInstance);
// public override void InitMember(MemberInfo member, object declaringInstance)
// {
// base.InitMember(member, declaringInstance);
var mi = MemInfo as MethodInfo;
GenericArgs = mi.GetGenericArguments();
// var mi = MemInfo as MethodInfo;
// GenericArgs = mi.GetGenericArguments();
GenericConstraints = GenericArgs.Select(x => x.GetGenericParameterConstraints())
.ToArray();
// GenericConstraints = GenericArgs.Select(x => x.GetGenericParameterConstraints())
// .ToArray();
GenericArgInput = new string[GenericArgs.Length];
// GenericArgInput = new string[GenericArgs.Length];
m_arguments = mi.GetParameters();
m_argumentInput = new string[m_arguments.Length];
// m_arguments = mi.GetParameters();
// m_argumentInput = new string[m_arguments.Length];
base.Init(null, mi.ReturnType);
}
// base.Init(null, mi.ReturnType);
// }
public override void UpdateValue()
{
// CacheMethod cannot UpdateValue directly. Need to Evaluate.
}
// public override void UpdateValue()
// {
// // CacheMethod cannot UpdateValue directly. Need to Evaluate.
// }
public void Evaluate()
{
MethodInfo mi;
if (GenericArgs.Length > 0)
{
mi = MakeGenericMethodFromInput();
if (mi == null) return;
}
else
{
mi = MemInfo as MethodInfo;
}
// public void Evaluate()
// {
// MethodInfo mi;
// if (GenericArgs.Length > 0)
// {
// mi = MakeGenericMethodFromInput();
// if (mi == null) return;
// }
// else
// {
// mi = MemInfo as MethodInfo;
// }
object ret = null;
// object ret = null;
try
{
ret = mi.Invoke(mi.IsStatic ? null : DeclaringInstance, ParseArguments());
m_evaluated = true;
m_isEvaluating = false;
}
catch (Exception e)
{
ExplorerCore.LogWarning($"Exception evaluating: {e.GetType()}, {e.Message}");
ReflectionException = ReflectionHelpers.ExceptionToString(e);
}
// try
// {
// ret = mi.Invoke(mi.IsStatic ? null : DeclaringInstance, ParseArguments());
// m_evaluated = true;
// m_isEvaluating = false;
// }
// catch (Exception e)
// {
// ExplorerCore.LogWarning($"Exception evaluating: {e.GetType()}, {e.Message}");
// ReflectionException = ReflectionHelpers.ExceptionToString(e);
// }
if (ret != null)
{
//m_cachedReturnValue = CacheFactory.GetTypeAndCacheObject(ret);
m_cachedReturnValue = CacheFactory.GetCacheObject(ret);
m_cachedReturnValue.UpdateValue();
}
else
{
m_cachedReturnValue = null;
}
}
// if (ret != null)
// {
// //m_cachedReturnValue = CacheFactory.GetTypeAndCacheObject(ret);
// m_cachedReturnValue = CacheFactory.GetCacheObject(ret);
// m_cachedReturnValue.UpdateValue();
// }
// else
// {
// m_cachedReturnValue = null;
// }
// }
private MethodInfo MakeGenericMethodFromInput()
{
var mi = MemInfo as MethodInfo;
// private MethodInfo MakeGenericMethodFromInput()
// {
// var mi = MemInfo as MethodInfo;
var list = new List<Type>();
for (int i = 0; i < GenericArgs.Length; i++)
{
var input = GenericArgInput[i];
if (ReflectionHelpers.GetTypeByName(input) is Type t)
{
if (GenericConstraints[i].Length == 0)
{
list.Add(t);
}
else
{
foreach (var constraint in GenericConstraints[i].Where(x => x != null))
{
if (!constraint.IsAssignableFrom(t))
{
ExplorerCore.LogWarning($"Generic argument #{i}, '{input}' is not assignable from the constraint '{constraint}'!");
return null;
}
}
// var list = new List<Type>();
// for (int i = 0; i < GenericArgs.Length; i++)
// {
// var input = GenericArgInput[i];
// if (ReflectionHelpers.GetTypeByName(input) is Type t)
// {
// if (GenericConstraints[i].Length == 0)
// {
// list.Add(t);
// }
// else
// {
// foreach (var constraint in GenericConstraints[i].Where(x => x != null))
// {
// if (!constraint.IsAssignableFrom(t))
// {
// ExplorerCore.LogWarning($"Generic argument #{i}, '{input}' is not assignable from the constraint '{constraint}'!");
// return null;
// }
// }
list.Add(t);
}
}
else
{
ExplorerCore.LogWarning($"Generic argument #{i}, could not get any type by the name of '{input}'!" +
$" Make sure you use the full name, including the NameSpace.");
return null;
}
}
// list.Add(t);
// }
// }
// else
// {
// ExplorerCore.LogWarning($"Generic argument #{i}, could not get any type by the name of '{input}'!" +
// $" Make sure you use the full name, including the NameSpace.");
// return null;
// }
// }
// make into a generic with type list
mi = mi.MakeGenericMethod(list.ToArray());
// // make into a generic with type list
// mi = mi.MakeGenericMethod(list.ToArray());
return mi;
}
// return mi;
// }
// ==== GUI DRAW ====
// // ==== GUI DRAW ====
//public override void Draw(Rect window, float width)
//{
// base.Draw(window, width);
//}
// //public override void Draw(Rect window, float width)
// //{
// // base.Draw(window, width);
// //}
public void DrawValue(Rect window, float width)
{
string typeLabel = $"<color={Syntax.Class_Instance}>{IValue.ValueType.FullName}</color>";
// public void DrawValue(Rect window, float width)
// {
// string typeLabel = $"<color={Syntax.Class_Instance}>{IValue.ValueType.FullName}</color>";
if (m_evaluated)
{
if (m_cachedReturnValue != null)
{
m_cachedReturnValue.IValue.DrawValue(window, width);
}
else
{
GUILayout.Label($"null ({typeLabel})", new GUILayoutOption[0]);
}
}
else
{
GUILayout.Label($"<color=grey><i>Not yet evaluated</i></color> ({typeLabel})", new GUILayoutOption[0]);
}
}
// if (m_evaluated)
// {
// if (m_cachedReturnValue != null)
// {
// m_cachedReturnValue.IValue.DrawValue(window, width);
// }
// else
// {
// GUILayout.Label($"null ({typeLabel})", new GUILayoutOption[0]);
// }
// }
// else
// {
// GUILayout.Label($"<color=grey><i>Not yet evaluated</i></color> ({typeLabel})", new GUILayoutOption[0]);
// }
// }
public void DrawGenericArgsInput()
{
GUILayout.Label($"<b><color=orange>Generic Arguments:</color></b>", new GUILayoutOption[0]);
// public void DrawGenericArgsInput()
// {
// GUILayout.Label($"<b><color=orange>Generic Arguments:</color></b>", new GUILayoutOption[0]);
for (int i = 0; i < this.GenericArgs.Length; i++)
{
string types = "";
if (this.GenericConstraints[i].Length > 0)
{
foreach (var constraint in this.GenericConstraints[i])
{
if (types != "") types += ", ";
// for (int i = 0; i < this.GenericArgs.Length; i++)
// {
// string types = "";
// if (this.GenericConstraints[i].Length > 0)
// {
// foreach (var constraint in this.GenericConstraints[i])
// {
// if (types != "") types += ", ";
string type;
// string type;
if (constraint == null)
type = "Any";
else
type = constraint.ToString();
// if (constraint == null)
// type = "Any";
// else
// type = constraint.ToString();
types += $"<color={Syntax.Class_Instance}>{type}</color>";
}
}
else
{
types = $"<color={Syntax.Class_Instance}>Any</color>";
}
var input = this.GenericArgInput[i];
// types += $"<color={Syntax.Class_Instance}>{type}</color>";
// }
// }
// else
// {
// types = $"<color={Syntax.Class_Instance}>Any</color>";
// }
// var input = this.GenericArgInput[i];
GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
// GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUI.skin.label.alignment = TextAnchor.MiddleCenter;
GUILayout.Label(
$"<color={Syntax.StructGreen}>{this.GenericArgs[i].Name}</color>",
new GUILayoutOption[] { GUILayout.Width(15) }
);
this.GenericArgInput[i] = GUIHelper.TextField(input, new GUILayoutOption[] { GUILayout.Width(150) });
GUI.skin.label.alignment = TextAnchor.MiddleLeft;
GUILayout.Label(types, new GUILayoutOption[0]);
// GUI.skin.label.alignment = TextAnchor.MiddleCenter;
// GUILayout.Label(
// $"<color={Syntax.StructGreen}>{this.GenericArgs[i].Name}</color>",
// new GUILayoutOption[] { GUILayout.Width(15) }
// );
// this.GenericArgInput[i] = GUIHelper.TextField(input, new GUILayoutOption[] { GUILayout.Width(150) });
// GUI.skin.label.alignment = TextAnchor.MiddleLeft;
// GUILayout.Label(types, new GUILayoutOption[0]);
GUILayout.EndHorizontal();
}
}
}
}
// GUILayout.EndHorizontal();
// }
// }
// }
//}

View File

@ -1,117 +1,117 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using UnityEngine;
using Explorer.UI;
using Explorer.UI.Shared;
using Explorer.Helpers;
//using System;
//using System.Collections.Generic;
//using System.Linq;
//using System.Reflection;
//using UnityEngine;
//using Explorer.UI;
//using Explorer.UI.Shared;
//using Explorer.Helpers;
namespace Explorer.CacheObject
{
public class CacheObjectBase
{
public InteractiveValue IValue;
//namespace Explorer.CacheObject
//{
// public class CacheObjectBase
// {
// public InteractiveValue IValue;
public virtual bool CanWrite => false;
public virtual bool HasParameters => false;
public virtual bool IsMember => false;
// public virtual bool CanWrite => false;
// public virtual bool HasParameters => false;
// public virtual bool IsMember => false;
public bool IsStaticClassSearchResult { get; set; }
// public bool IsStaticClassSearchResult { get; set; }
public virtual void Init(object obj, Type valueType)
{
if (valueType == null && obj == null)
{
return;
}
// public virtual void Init(object obj, Type valueType)
// {
// if (valueType == null && obj == null)
// {
// return;
// }
//ExplorerCore.Log("Initializing InteractiveValue of type " + valueType.FullName);
// //ExplorerCore.Log("Initializing InteractiveValue of type " + valueType.FullName);
InteractiveValue interactive;
// InteractiveValue interactive;
if (valueType == typeof(GameObject) || valueType == typeof(Transform))
{
interactive = new InteractiveGameObject();
}
else if (valueType == typeof(Texture2D))
{
interactive = new InteractiveTexture2D();
}
else if (valueType == typeof(Texture))
{
interactive = new InteractiveTexture();
}
else if (valueType == typeof(Sprite))
{
interactive = new InteractiveSprite();
}
else if (valueType.IsPrimitive || valueType == typeof(string))
{
interactive = new InteractivePrimitive();
}
else if (valueType.IsEnum)
{
if (valueType.GetCustomAttributes(typeof(FlagsAttribute), true) is object[] attributes && attributes.Length > 0)
{
interactive = new InteractiveFlags();
}
else
{
interactive = new InteractiveEnum();
}
}
else if (valueType == typeof(Vector2) || valueType == typeof(Vector3) || valueType == typeof(Vector4))
{
interactive = new InteractiveVector();
}
else if (valueType == typeof(Quaternion))
{
interactive = new InteractiveQuaternion();
}
else if (valueType == typeof(Color))
{
interactive = new InteractiveColor();
}
else if (valueType == typeof(Rect))
{
interactive = new InteractiveRect();
}
// must check this before IsEnumerable
else if (ReflectionHelpers.IsDictionary(valueType))
{
interactive = new InteractiveDictionary();
}
else if (ReflectionHelpers.IsEnumerable(valueType))
{
interactive = new InteractiveEnumerable();
}
else
{
interactive = new InteractiveValue();
}
// if (valueType == typeof(GameObject) || valueType == typeof(Transform))
// {
// interactive = new InteractiveGameObject();
// }
// else if (valueType == typeof(Texture2D))
// {
// interactive = new InteractiveTexture2D();
// }
// else if (valueType == typeof(Texture))
// {
// interactive = new InteractiveTexture();
// }
// else if (valueType == typeof(Sprite))
// {
// interactive = new InteractiveSprite();
// }
// else if (valueType.IsPrimitive || valueType == typeof(string))
// {
// interactive = new InteractivePrimitive();
// }
// else if (valueType.IsEnum)
// {
// if (valueType.GetCustomAttributes(typeof(FlagsAttribute), true) is object[] attributes && attributes.Length > 0)
// {
// interactive = new InteractiveFlags();
// }
// else
// {
// interactive = new InteractiveEnum();
// }
// }
// else if (valueType == typeof(Vector2) || valueType == typeof(Vector3) || valueType == typeof(Vector4))
// {
// interactive = new InteractiveVector();
// }
// else if (valueType == typeof(Quaternion))
// {
// interactive = new InteractiveQuaternion();
// }
// else if (valueType == typeof(Color))
// {
// interactive = new InteractiveColor();
// }
// else if (valueType == typeof(Rect))
// {
// interactive = new InteractiveRect();
// }
// // must check this before IsEnumerable
// else if (ReflectionHelpers.IsDictionary(valueType))
// {
// interactive = new InteractiveDictionary();
// }
// else if (ReflectionHelpers.IsEnumerable(valueType))
// {
// interactive = new InteractiveEnumerable();
// }
// else
// {
// interactive = new InteractiveValue();
// }
interactive.Value = obj;
interactive.ValueType = valueType;
// interactive.Value = obj;
// interactive.ValueType = valueType;
this.IValue = interactive;
this.IValue.OwnerCacheObject = this;
// this.IValue = interactive;
// this.IValue.OwnerCacheObject = this;
UpdateValue();
// UpdateValue();
this.IValue.Init();
}
// this.IValue.Init();
// }
public virtual void Draw(Rect window, float width)
{
IValue.Draw(window, width);
}
// public virtual void Draw(Rect window, float width)
// {
// IValue.Draw(window, width);
// }
public virtual void UpdateValue()
{
IValue.UpdateValue();
}
// public virtual void UpdateValue()
// {
// IValue.UpdateValue();
// }
public virtual void SetValue() => throw new NotImplementedException();
}
}
// public virtual void SetValue() => throw new NotImplementedException();
// }
//}

View File

@ -1,84 +1,84 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using Explorer.UI;
using Explorer.Helpers;
//using System;
//using System.Collections.Generic;
//using System.Linq;
//using System.Text;
//using System.Reflection;
//using Explorer.UI;
//using Explorer.Helpers;
namespace Explorer.CacheObject
{
public class CacheProperty : CacheMember
{
public override bool IsStatic => (MemInfo as PropertyInfo).GetAccessors()[0].IsStatic;
//namespace Explorer.CacheObject
//{
// public class CacheProperty : CacheMember
// {
// public override bool IsStatic => (MemInfo as PropertyInfo).GetAccessors()[0].IsStatic;
public override void InitMember(MemberInfo member, object declaringInstance)
{
base.InitMember(member, declaringInstance);
// public override void InitMember(MemberInfo member, object declaringInstance)
// {
// base.InitMember(member, declaringInstance);
var pi = member as PropertyInfo;
// var pi = member as PropertyInfo;
this.m_arguments = pi.GetIndexParameters();
this.m_argumentInput = new string[m_arguments.Length];
// this.m_arguments = pi.GetIndexParameters();
// this.m_argumentInput = new string[m_arguments.Length];
base.Init(null, pi.PropertyType);
// base.Init(null, pi.PropertyType);
UpdateValue();
}
// UpdateValue();
// }
public override void UpdateValue()
{
if (HasParameters && !m_isEvaluating)
{
// Need to enter parameters first.
return;
}
// public override void UpdateValue()
// {
// if (HasParameters && !m_isEvaluating)
// {
// // Need to enter parameters first.
// return;
// }
if (IValue is InteractiveDictionary iDict)
{
if (!iDict.EnsureDictionaryIsSupported())
{
ReflectionException = "Not supported due to TypeInitializationException";
return;
}
}
// if (IValue is InteractiveDictionary iDict)
// {
// if (!iDict.EnsureDictionaryIsSupported())
// {
// ReflectionException = "Not supported due to TypeInitializationException";
// return;
// }
// }
try
{
var pi = MemInfo as PropertyInfo;
// try
// {
// var pi = MemInfo as PropertyInfo;
if (pi.CanRead)
{
var target = pi.GetAccessors()[0].IsStatic ? null : DeclaringInstance;
// if (pi.CanRead)
// {
// var target = pi.GetAccessors()[0].IsStatic ? null : DeclaringInstance;
IValue.Value = pi.GetValue(target, ParseArguments());
// IValue.Value = pi.GetValue(target, ParseArguments());
base.UpdateValue();
}
else // create a dummy value for Write-Only properties.
{
if (IValue.ValueType == typeof(string))
{
IValue.Value = "";
}
else
{
IValue.Value = Activator.CreateInstance(IValue.ValueType);
}
}
}
catch (Exception e)
{
ReflectionException = ReflectionHelpers.ExceptionToString(e);
}
}
// base.UpdateValue();
// }
// else // create a dummy value for Write-Only properties.
// {
// if (IValue.ValueType == typeof(string))
// {
// IValue.Value = "";
// }
// else
// {
// IValue.Value = Activator.CreateInstance(IValue.ValueType);
// }
// }
// }
// catch (Exception e)
// {
// ReflectionException = ReflectionHelpers.ExceptionToString(e);
// }
// }
public override void SetValue()
{
var pi = MemInfo as PropertyInfo;
var target = pi.GetAccessors()[0].IsStatic ? null : DeclaringInstance;
// public override void SetValue()
// {
// var pi = MemInfo as PropertyInfo;
// var target = pi.GetAccessors()[0].IsStatic ? null : DeclaringInstance;
pi.SetValue(target, IValue.Value, ParseArguments());
}
}
}
// pi.SetValue(target, IValue.Value, ParseArguments());
// }
// }
//}

View File

@ -2,7 +2,7 @@
using System.Xml.Serialization;
using UnityEngine;
namespace Explorer.Config
namespace ExplorerBeta.Config
{
public class ModConfig
{

View File

@ -23,7 +23,7 @@
<PlatformTarget>x64</PlatformTarget>
<Prefer32Bit>false</Prefer32Bit>
<RootNamespace>Explorer</RootNamespace>
<AssemblyName>Explorer</AssemblyName>
<AssemblyName>ExplorerBeta</AssemblyName>
<!-- Set this to the MelonLoader Il2Cpp Game folder, without the ending '\' character. -->
<MLCppGameFolder>D:\Steam\steamapps\common\Hellpoint</MLCppGameFolder>
<!-- Set this to the MelonLoader Mono Game folder, without the ending '\' character. -->
@ -132,10 +132,6 @@
<HintPath>$(MLCppGameFolder)\MelonLoader\Managed\UnityEngine.CoreModule.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="UnityEngine.IMGUIModule">
<HintPath>$(MLCppGameFolder)\MelonLoader\Managed\UnityEngine.IMGUIModule.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="UnityEngine.PhysicsModule">
<HintPath>$(MLCppGameFolder)\MelonLoader\Managed\UnityEngine.PhysicsModule.dll</HintPath>
<Private>False</Private>
@ -148,6 +144,14 @@
<HintPath>$(MLCppGameFolder)\MelonLoader\Managed\UnityEngine.UI.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="UnityEngine.UIModule">
<HintPath>$(MLCppGameFolder)\MelonLoader\Managed\UnityEngine.UIModule.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="UnityEngine.IMGUIModule">
<HintPath>$(MLCppGameFolder)\MelonLoader\Managed\UnityEngine.IMGUIModule.dll</HintPath>
<Private>False</Private>
</Reference>
</ItemGroup>
<!-- BepInEx Il2Cpp refs -->
<ItemGroup Condition="'$(IsMelonLoader)|$(IsCpp)'=='false|true'">
@ -183,10 +187,6 @@
<HintPath>$(BIECppGameFolder)\BepInEx\unhollowed\UnityEngine.CoreModule.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="UnityEngine.IMGUIModule">
<HintPath>$(BIECppGameFolder)\BepInEx\unhollowed\UnityEngine.IMGUIModule.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="UnityEngine.PhysicsModule">
<HintPath>$(BIECppGameFolder)\BepInEx\unhollowed\UnityEngine.PhysicsModule.dll</HintPath>
<Private>False</Private>
@ -199,6 +199,14 @@
<HintPath>$(BIECppGameFolder)\BepInEx\unhollowed\UnityEngine.UI.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="UnityEngine.UIModule">
<HintPath>$(BIECppGameFolder)\BepInEx\unhollowed\UnityEngine.UIModule.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="UnityEngine.IMGUIModule">
<HintPath>$(BIECppGameFolder)\BepInEx\unhollowed\UnityEngine.IMGUIModule.dll</HintPath>
<Private>False</Private>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="CacheObject\CacheEnumerated.cs" />
@ -209,20 +217,6 @@
<Compile Include="CacheObject\CacheProperty.cs" />
<Compile Include="CacheObject\CacheObjectBase.cs" />
<Compile Include="Helpers\Texture2DHelpers.cs" />
<Compile Include="UI\InteractiveValue\InteractiveValue.cs" />
<Compile Include="UI\InteractiveValue\Object\InteractiveDictionary.cs" />
<Compile Include="UI\InteractiveValue\Object\InteractiveEnumerable.cs" />
<Compile Include="UI\InteractiveValue\Object\InteractiveGameObject.cs" />
<Compile Include="UI\InteractiveValue\Object\InteractiveSprite.cs" />
<Compile Include="UI\InteractiveValue\Object\InteractiveTexture.cs" />
<Compile Include="UI\InteractiveValue\Object\InteractiveTexture2D.cs" />
<Compile Include="UI\InteractiveValue\Struct\InteractiveQuaternion.cs" />
<Compile Include="UI\InteractiveValue\Struct\InteractiveRect.cs" />
<Compile Include="UI\InteractiveValue\Struct\InteractiveVector.cs" />
<Compile Include="UI\InteractiveValue\Struct\InteractiveColor.cs" />
<Compile Include="UI\InteractiveValue\Struct\InteractiveEnum.cs" />
<Compile Include="UI\InteractiveValue\Struct\InteractiveFlags.cs" />
<Compile Include="UI\InteractiveValue\Struct\InteractivePrimitive.cs" />
<Compile Include="Config\ModConfig.cs" />
<Compile Include="ExplorerCore.cs" />
<Compile Include="ExplorerBepInPlugin.cs" />
@ -231,50 +225,25 @@
<Compile Include="Extensions\UnityExtensions.cs" />
<Compile Include="Helpers\ReflectionHelpers.cs" />
<Compile Include="Helpers\UnityHelpers.cs" />
<Compile Include="UI\ForceUnlockCursor.cs" />
<Compile Include="Input\IAbstractInput.cs" />
<Compile Include="Tests\TestClass.cs" />
<Compile Include="UI\ForceUnlockCursor.cs" />
<Compile Include="Input\InputManager.cs" />
<Compile Include="Input\InputSystem.cs" />
<Compile Include="Input\LegacyInput.cs" />
<Compile Include="Input\NoInput.cs" />
<Compile Include="UI\Inspectors\InspectUnderMouse.cs" />
<Compile Include="UI\Inspectors\Reflection\InstanceInspector.cs" />
<Compile Include="UI\Inspectors\ReflectionInspector.cs" />
<Compile Include="UI\Inspectors\Reflection\StaticInspector.cs" />
<Compile Include="UI\MainMenu.cs" />
<Compile Include="UI\Main\ConsolePage.cs" />
<Compile Include="UI\Main\Console\AutoComplete.cs" />
<Compile Include="UI\Main\Console\ScriptInteraction.cs" />
<Compile Include="UI\Main\Console\ScriptEvaluator.cs" />
<Compile Include="UI\Main\OptionsPage.cs" />
<Compile Include="UI\Main\ScenePage.cs" />
<Compile Include="UI\Main\SearchPage.cs" />
<Compile Include="UI\Main\BaseMainMenuPage.cs" />
<Compile Include="UI\Shared\Buttons.cs" />
<Compile Include="UI\Shared\IExpandHeight.cs" />
<Compile Include="UI\Shared\PageHelper.cs" />
<Compile Include="UI\Shared\ResizeDrag.cs" />
<Compile Include="UI\Main\MainMenu.cs" />
<Compile Include="UI\Main\PanelDragger.cs" />
<Compile Include="UI\InteractiveValue\InteractiveValue.cs" />
<Compile Include="UI\Shared\Syntax.cs" />
<Compile Include="UI\Shared\UIStyles.cs" />
<Compile Include="UI\Inspectors\GameObjectInspector.cs" />
<Compile Include="UI\TabViewWindow.cs" />
<Compile Include="UI\WindowBase.cs" />
<Compile Include="UI\WindowManager.cs" />
<Compile Include="UI\UIManager.cs" />
<Compile Include="Unstrip\ImageConversion\ImageConversionUnstrip.cs" />
<Compile Include="Unstrip\IMGUI\GUIUtilityUnstrip.cs" />
<Compile Include="Unstrip\IMGUI\TextEditorUnstrip.cs" />
<Compile Include="Helpers\ICallHelper.cs" />
<Compile Include="Unstrip\LayerMask\LayerMaskUnstrip.cs" />
<Compile Include="Unstrip\Resources\ResourcesUnstrip.cs" />
<Compile Include="Unstrip\Scene\SceneUnstrip.cs" />
<Compile Include="Unstrip\IMGUI\GUIHelper.cs" />
<Compile Include="Unstrip\IMGUI\LayoutUtilityUnstrip.cs" />
<Compile Include="Unstrip\IMGUI\ScrollViewStateUnstrip.cs" />
<Compile Include="Unstrip\IMGUI\SliderHandlerUnstrip.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Unstrip\IMGUI\GUIUnstrip.cs" />
<Compile Include="Unstrip\IMGUI\SliderStateUnstrip.cs" />
<Compile Include="UI\UIFactory.cs" />
</ItemGroup>
<ItemGroup>
<None Include="ILRepack.targets" />

View File

@ -1,18 +1,17 @@
using System.Collections;
using System.Linq;
using Explorer.Config;
using Explorer.UI;
using Explorer.UI.Inspectors;
using Explorer.UI.Main;
using Explorer.UI.Shared;
using ExplorerBeta.Config;
using ExplorerBeta.Input;
using ExplorerBeta.UI;
using UnityEngine;
using UnityEngine.EventSystems;
namespace Explorer
namespace ExplorerBeta
{
public class ExplorerCore
{
public const string NAME = "Explorer " + VERSION + " (" + PLATFORM + ", " + MODLOADER + ")";
public const string VERSION = "2.0.7";
public const string VERSION = "3.0.0b";
public const string AUTHOR = "Sinai";
public const string GUID = "com.sinai.explorer";
@ -31,6 +30,16 @@ namespace Explorer
public static ExplorerCore Instance { get; private set; }
public static bool ShowMenu
{
get => m_showMenu;
set => SetShowMenu(value);
}
public static bool m_showMenu;
private static bool m_doneUIInit;
private static float m_startupTime;
public ExplorerCore()
{
if (Instance != null)
@ -43,8 +52,9 @@ namespace Explorer
ModConfig.OnLoad();
new MainMenu();
new WindowManager();
// Temporary? Need a small delay after OnApplicationStart before we can safely make our GameObject.
// Can't use Threads (crash), can't use Coroutine (no BepInEx support yet).
m_startupTime = Time.realtimeSinceStartup;
InputManager.Init();
ForceUnlockCursor.Init();
@ -52,23 +62,40 @@ namespace Explorer
ShowMenu = true;
Log($"{NAME} initialized.");
}
public static bool ShowMenu
{
get => m_showMenu;
set => SetShowMenu(value);
}
public static bool m_showMenu;
}
private static void SetShowMenu(bool show)
{
m_showMenu = show;
if (UIManager.CanvasRoot)
{
UIManager.CanvasRoot.SetActive(show);
if (show)
{
ForceUnlockCursor.SetEventSystem();
}
else
{
ForceUnlockCursor.ReleaseEventSystem();
}
}
ForceUnlockCursor.UpdateCursorControl();
}
public static void Update()
{
// Temporary delay before UIManager.Init
if (!m_doneUIInit && Time.realtimeSinceStartup - m_startupTime > 1f)
{
UIManager.Init();
Log("Initialized Explorer UI.");
m_doneUIInit = true;
}
if (InputManager.GetKeyDown(ModConfig.Instance.Main_Menu_Toggle))
{
ShowMenu = !ShowMenu;
@ -77,36 +104,17 @@ namespace Explorer
if (ShowMenu)
{
ForceUnlockCursor.Update();
InspectUnderMouse.Update();
MainMenu.Instance.Update();
WindowManager.Instance.Update();
UIManager.Update();
//// TODO:
//InspectUnderMouse.Update();
}
}
public static void OnGUI()
{
if (!ShowMenu) return;
var origSkin = GUI.skin;
GUI.skin = UIStyles.WindowSkin;
MainMenu.Instance.OnGUI();
WindowManager.Instance.OnGUI();
InspectUnderMouse.OnGUI();
if (!ResizeDrag.IsMouseInResizeArea && WindowManager.IsMouseInWindow)
{
InputManager.ResetInputAxes();
}
GUI.skin = origSkin;
}
public static void OnSceneChange()
{
ScenePage.Instance?.OnSceneChange();
SearchPage.Instance?.OnSceneChange();
UIManager.OnSceneChange();
}
public static void Log(object message)

View File

@ -5,7 +5,7 @@ using System.Linq;
using System.Text;
using MelonLoader;
namespace Explorer
namespace ExplorerBeta
{
public class ExplorerMelonMod : MelonMod
{
@ -28,10 +28,10 @@ namespace Explorer
ExplorerCore.Update();
}
public override void OnGUI()
{
ExplorerCore.OnGUI();
}
//public override void OnGUI()
//{
// ExplorerCore.OnGUI();
//}
}
}
#endif

View File

@ -2,9 +2,9 @@
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Explorer.Helpers;
using ExplorerBeta.Helpers;
namespace Explorer
namespace ExplorerBeta
{
public static class ReflectionExtensions
{

View File

@ -1,6 +1,6 @@
using UnityEngine;
namespace Explorer
namespace ExplorerBeta
{
public static class UnityExtensions
{

View File

@ -7,7 +7,7 @@ using System.Text;
using System.Reflection;
using System.Diagnostics.CodeAnalysis;
namespace Explorer.Helpers
namespace ExplorerBeta.Helpers
{
[SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "External methods")]
public static class ICallHelper

View File

@ -13,7 +13,7 @@ using UnhollowerRuntimeLib;
using System.Runtime.InteropServices;
#endif
namespace Explorer.Helpers
namespace ExplorerBeta.Helpers
{
[SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "External methods")]
public class ReflectionHelpers

View File

@ -6,10 +6,10 @@ using UnityEngine;
using System.IO;
using System.Reflection;
#if CPP
using Explorer.Unstrip.ImageConversion;
using ExplorerBeta.Unstrip.ImageConversion;
#endif
namespace Explorer.Helpers
namespace ExplorerBeta.Helpers
{
public static class Texture2DHelpers
{

View File

@ -1,6 +1,6 @@
using UnityEngine;
namespace Explorer.Helpers
namespace ExplorerBeta.Helpers
{
public class UnityHelpers
{

View File

@ -4,7 +4,7 @@ using System.Linq;
using System.Text;
using UnityEngine;
namespace Explorer.Input
namespace ExplorerBeta.Input
{
public interface IAbstractInput
{

View File

@ -1,14 +1,14 @@
using System;
using System.Reflection;
using UnityEngine;
using Explorer.Input;
using Explorer.Helpers;
using ExplorerBeta.Input;
using ExplorerBeta.Helpers;
using System.Diagnostics.CodeAnalysis;
#if CPP
using UnhollowerBaseLib;
#endif
namespace Explorer
namespace ExplorerBeta.Input
{
[SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "Unity style")]
public static class InputManager

View File

@ -4,9 +4,9 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using Explorer.Helpers;
using ExplorerBeta.Helpers;
namespace Explorer.Input
namespace ExplorerBeta.Input
{
public class InputSystem : IAbstractInput
{

View File

@ -4,9 +4,9 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using Explorer.Helpers;
using ExplorerBeta.Helpers;
namespace Explorer.Input
namespace ExplorerBeta.Input
{
public class LegacyInput : IAbstractInput
{

View File

@ -4,7 +4,7 @@ using System.Linq;
using System.Text;
using UnityEngine;
namespace Explorer.Input
namespace ExplorerBeta.Input
{
// Just a stub for games where no Input module was able to load at all.

View File

@ -1,12 +1,12 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using Explorer;
using ExplorerBeta;
#if ML
using MelonLoader;
[assembly: MelonInfo(typeof(ExplorerMelonMod), "Explorer", ExplorerCore.VERSION, ExplorerCore.AUTHOR)]
[assembly: MelonInfo(typeof(ExplorerMelonMod), "ExplorerBeta", ExplorerCore.VERSION, ExplorerCore.AUTHOR)]
[assembly: MelonGame(null, null)]
#endif

View File

@ -4,14 +4,15 @@ using System;
using UnityEngine;
using System.Reflection;
using System.Runtime.InteropServices;
using Explorer.UI.Shared;
using ExplorerBeta.UI.Shared;
using ExplorerBeta.UI;
#if CPP
using UnhollowerBaseLib;
using UnityEngine.SceneManagement;
using Explorer.Unstrip.ImageConversion;
using ExplorerBeta.Unstrip.ImageConversion;
#endif
namespace Explorer.Tests
namespace ExplorerBeta.Tests
{
public static class StaticTestClass
{
@ -40,7 +41,7 @@ namespace Explorer.Tests
}
private static bool m_setOnlyProperty;
public Texture2D TestTexture = UIStyles.MakeTex(200, 200, Color.white);
public Texture2D TestTexture = UIManager.MakeSolidTexture(Color.white, 200, 200);
public static Sprite TestSprite;
public static int StaticProperty => 5;

View File

@ -1,13 +1,16 @@
using System;
using UnityEngine;
using Explorer.Helpers;
using ExplorerBeta.Helpers;
using UnityEngine.EventSystems;
using ExplorerBeta.UI;
using ExplorerBeta.Input;
#if ML
using Harmony;
#else
using HarmonyLib;
#endif
namespace Explorer.UI
namespace ExplorerBeta.UI
{
public class ForceUnlockCursor
{
@ -18,6 +21,12 @@ namespace Explorer.UI
}
private static bool m_forceUnlock;
private static void SetForceUnlock(bool unlock)
{
m_forceUnlock = unlock;
UpdateCursorControl();
}
public static bool ShouldForceMouse => ExplorerCore.ShowMenu && Unlock;
private static CursorLockMode m_lastLockMode;
@ -25,8 +34,8 @@ namespace Explorer.UI
private static bool m_currentlySettingCursor = false;
private static Type CursorType
=> m_cursorType
private static Type CursorType
=> m_cursorType
?? (m_cursorType = ReflectionHelpers.GetTypeByName("UnityEngine.Cursor"));
private static Type m_cursorType;
@ -44,11 +53,13 @@ namespace Explorer.UI
m_lastVisibleState = Cursor.visible;
// Setup Harmony Patches
TryPatch("lockState", new HarmonyMethod(typeof(ForceUnlockCursor).GetMethod(nameof(Prefix_set_lockState))), true);
TryPatch("lockState", new HarmonyMethod(typeof(ForceUnlockCursor).GetMethod(nameof(Postfix_get_lockState))), false);
TryPatch(typeof(EventSystem), "current", new HarmonyMethod(typeof(ForceUnlockCursor).GetMethod(nameof(Prefix_EventSystem_set_current))), true);
TryPatch("visible", new HarmonyMethod(typeof(ForceUnlockCursor).GetMethod(nameof(Prefix_set_visible))), true);
TryPatch("visible", new HarmonyMethod(typeof(ForceUnlockCursor).GetMethod(nameof(Postfix_get_visible))), false);
TryPatch(typeof(Cursor), "lockState", new HarmonyMethod(typeof(ForceUnlockCursor).GetMethod(nameof(Prefix_set_lockState))), true);
//TryPatch(typeof(Cursor), "lockState", new HarmonyMethod(typeof(ForceUnlockCursor).GetMethod(nameof(Postfix_get_lockState))), false);
TryPatch(typeof(Cursor), "visible", new HarmonyMethod(typeof(ForceUnlockCursor).GetMethod(nameof(Prefix_set_visible))), true);
//TryPatch(typeof(Cursor), "visible", new HarmonyMethod(typeof(ForceUnlockCursor).GetMethod(nameof(Postfix_get_visible))), false);
}
catch (Exception e)
{
@ -58,7 +69,7 @@ namespace Explorer.UI
Unlock = true;
}
private static void TryPatch(string property, HarmonyMethod patch, bool setter)
private static void TryPatch(Type type, string property, HarmonyMethod patch, bool setter)
{
try
{
@ -70,7 +81,7 @@ namespace Explorer.UI
#endif
;
var prop = typeof(Cursor).GetProperty(property);
var prop = type.GetProperty(property);
if (setter)
{
@ -85,17 +96,11 @@ namespace Explorer.UI
}
catch (Exception e)
{
string s = setter ? "set_" : "get_" ;
ExplorerCore.Log($"Unable to patch Cursor.{s}{property}: {e.Message}");
string suf = setter ? "set_" : "get_";
ExplorerCore.Log($"Unable to patch {type.Name}.{suf}{property}: {e.Message}");
}
}
private static void SetForceUnlock(bool unlock)
{
m_forceUnlock = unlock;
UpdateCursorControl();
}
public static void Update()
{
// Check Force-Unlock input
@ -128,6 +133,45 @@ namespace Explorer.UI
}
}
// Event system
private static bool m_settingEventSystem;
private static EventSystem m_lastEventSystem;
private static BaseInputModule m_lastInputModule;
public static void SetEventSystem()
{
m_settingEventSystem = true;
UIManager.SetEventSystem();
m_settingEventSystem = false;
}
public static void ReleaseEventSystem()
{
if (m_lastEventSystem)
{
m_settingEventSystem = true;
EventSystem.current = m_lastEventSystem;
m_lastInputModule?.ActivateModule();
m_settingEventSystem = false;
}
}
[HarmonyPrefix]
public static void Prefix_EventSystem_set_current(ref EventSystem value)
{
if (!m_settingEventSystem)
{
m_lastEventSystem = value;
m_lastInputModule = value?.currentInputModule;
if (ExplorerCore.ShowMenu)
{
value = UIManager.EventSys;
}
}
}
// Force mouse to stay unlocked and visible while UnlockMouse and ShowMenu are true.
// Also keep track of when anything else tries to set Cursor state, this will be the
// value that we set back to when we close the menu or disable force-unlock.
@ -160,22 +204,22 @@ namespace Explorer.UI
}
}
[HarmonyPrefix]
public static void Postfix_get_lockState(ref CursorLockMode __result)
{
if (ShouldForceMouse)
{
__result = m_lastLockMode;
}
}
//[HarmonyPrefix]
//public static void Postfix_get_lockState(ref CursorLockMode __result)
//{
// if (ShouldForceMouse)
// {
// __result = m_lastLockMode;
// }
//}
[HarmonyPrefix]
public static void Postfix_get_visible(ref bool __result)
{
if (ShouldForceMouse)
{
__result = m_lastVisibleState;
}
}
//[HarmonyPrefix]
//public static void Postfix_get_visible(ref bool __result)
//{
// if (ShouldForceMouse)
// {
// __result = m_lastVisibleState;
// }
//}
}
}

View File

@ -1,751 +0,0 @@
using System;
using System.Collections.Generic;
using UnityEngine;
using Explorer.UI.Shared;
using Explorer.UI.Main;
using Explorer.Unstrip.LayerMasks;
using Explorer.Helpers;
#if CPP
using UnhollowerRuntimeLib;
#endif
namespace Explorer.UI.Inspectors
{
public class GameObjectInspector : WindowBase
{
public override string Title => WindowManager.TabView
? $"<color=cyan>[G]</color> {TargetGO.name}"
: $"GameObject Inspector ({TargetGO.name})";
public GameObject TargetGO;
public bool pendingDestroy;
private static bool m_hideControls;
// gui element holders
private string m_name;
private string m_scene;
private Transform[] m_children;
private Vector2 m_transformScroll = Vector2.zero;
private readonly PageHelper ChildPages = new PageHelper();
private Component[] m_components;
private Vector2 m_compScroll = Vector2.zero;
private readonly PageHelper CompPages = new PageHelper();
private readonly Vector3[] m_cachedInput = new Vector3[3];
private float m_translateAmount = 0.3f;
private float m_rotateAmount = 50f;
private float m_scaleAmount = 0.1f;
private bool m_freeze;
private Vector3 m_frozenPosition;
private Quaternion m_frozenRotation;
private Vector3 m_frozenScale;
private bool m_autoApplyTransform;
private bool m_autoUpdateTransform;
private bool m_localContext;
private int m_layer;
private readonly List<Component> m_cachedDestroyList = new List<Component>();
private string m_addComponentInput = "";
private string m_setParentInput = "Enter a GameObject name or path";
public bool GetObjectAsGameObject()
{
var targetType = Target?.GetType();
if (targetType == typeof(GameObject))
{
TargetGO = Target as GameObject;
return true;
}
else if (targetType == typeof(Transform))
{
TargetGO = (Target as Transform).gameObject;
return true;
}
ExplorerCore.Log("Error: Target is null or not a GameObject/Transform!");
DestroyWindow();
return false;
}
public override void Init()
{
if (!GetObjectAsGameObject())
{
return;
}
m_name = TargetGO.name;
m_scene = string.IsNullOrEmpty(TargetGO.scene.name)
? "None (Asset/Resource)"
: TargetGO.scene.name;
CacheTransformValues();
Update();
}
private void CacheTransformValues()
{
if (m_localContext)
{
m_cachedInput[0] = TargetGO.transform.localPosition;
m_cachedInput[1] = TargetGO.transform.localEulerAngles;
}
else
{
m_cachedInput[0] = TargetGO.transform.position;
m_cachedInput[1] = TargetGO.transform.eulerAngles;
}
m_cachedInput[2] = TargetGO.transform.localScale;
}
public override void Update()
{
try
{
if (pendingDestroy) return;
if (Target == null)
{
DestroyOnException(new Exception("Target was destroyed."));
return;
}
if (!TargetGO && !GetObjectAsGameObject())
{
DestroyOnException(new Exception("Target was destroyed."));
return;
}
if (m_freeze)
{
if (m_localContext)
{
TargetGO.transform.localPosition = m_frozenPosition;
TargetGO.transform.localRotation = m_frozenRotation;
}
else
{
TargetGO.transform.position = m_frozenPosition;
TargetGO.transform.rotation = m_frozenRotation;
}
TargetGO.transform.localScale = m_frozenScale;
}
m_layer = TargetGO.layer;
// update child objects
var childList = new List<Transform>();
for (int i = 0; i < TargetGO.transform.childCount; i++)
{
childList.Add(TargetGO.transform.GetChild(i));
}
childList.Sort((a, b) => b.childCount.CompareTo(a.childCount));
m_children = childList.ToArray();
ChildPages.ItemCount = m_children.Length;
// update components
#if CPP
var compList = new Il2CppSystem.Collections.Generic.List<Component>();
TargetGO.GetComponentsInternal(ReflectionHelpers.ComponentType, true, false, true, false, compList);
m_components = compList.ToArray();
#else
m_components = TargetGO.GetComponents<Component>();
#endif
CompPages.ItemCount = m_components.Length;
}
catch (Exception e)
{
DestroyOnException(e);
}
}
private void DestroyOnException(Exception e)
{
if (pendingDestroy) return;
ExplorerCore.Log($"Exception drawing GameObject Window: {e.GetType()}, {e.Message}");
pendingDestroy = true;
DestroyWindow();
}
private void InspectGameObject(Transform obj)
{
var window = WindowManager.InspectObject(obj, out bool created);
if (created)
{
window.m_rect = new Rect(this.m_rect.x, this.m_rect.y, this.m_rect.width, this.m_rect.height);
DestroyWindow();
}
}
#if CPP
private void ReflectObject(Il2CppSystem.Object obj)
#else
private void ReflectObject(object obj)
#endif
{
var window = WindowManager.InspectObject(obj, out bool created, true);
if (created)
{
if (this.m_rect.x <= (Screen.width - this.m_rect.width - 100))
{
window.m_rect = new Rect(
this.m_rect.x + this.m_rect.width + 20,
this.m_rect.y,
550,
700);
}
else
{
window.m_rect = new Rect(this.m_rect.x + 50, this.m_rect.y + 50, 550, 700);
}
}
}
public override void WindowFunction(int windowID)
{
if (pendingDestroy) return;
try
{
var rect = WindowManager.TabView ? TabViewWindow.Instance.m_rect : this.m_rect;
if (!WindowManager.TabView)
{
Header();
GUIHelper.BeginArea(new Rect(5, 25, rect.width - 10, rect.height - 35), GUI.skin.box);
}
scroll = GUIHelper.BeginScrollView(scroll);
GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUILayout.Label("Scene: <color=cyan>" + (m_scene == "" ? "n/a" : m_scene) + "</color>", new GUILayoutOption[0]);
if (m_scene == UnityHelpers.ActiveSceneName)
{
if (GUILayout.Button("<color=#00FF00>Send to Scene View</color>", new GUILayoutOption[] { GUILayout.Width(150) }))
{
ScenePage.Instance.SetTransformTarget(TargetGO.transform);
MainMenu.SetCurrentPage(0);
}
}
if (GUILayout.Button("Reflection Inspect", new GUILayoutOption[] { GUILayout.Width(150) }))
{
WindowManager.InspectObject(Target, out _, true);
}
GUILayout.EndHorizontal();
GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUILayout.Label("Path:", new GUILayoutOption[] { GUILayout.Width(50) });
string pathlabel = TargetGO.transform.GetGameObjectPath();
if (TargetGO.transform.parent != null)
{
if (GUILayout.Button("<-", new GUILayoutOption[] { GUILayout.Width(35) }))
{
InspectGameObject(TargetGO.transform.parent);
}
}
GUIHelper.TextArea(pathlabel, new GUILayoutOption[0]);
GUILayout.EndHorizontal();
GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUILayout.Label("Name:", new GUILayoutOption[] { GUILayout.Width(50) });
GUIHelper.TextArea(m_name, new GUILayoutOption[0]);
GUILayout.EndHorizontal();
LayerControls();
// --- Horizontal Columns section ---
GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUIHelper.BeginVertical(new GUILayoutOption[] { GUILayout.Width(rect.width / 2 - 17) });
TransformList(rect);
GUILayout.EndVertical();
GUIHelper.BeginVertical(new GUILayoutOption[] { GUILayout.Width(rect.width / 2 - 17) });
ComponentList(rect);
GUILayout.EndVertical();
GUILayout.EndHorizontal(); // end horiz columns
GameObjectControls();
GUIHelper.EndScrollView();
if (!WindowManager.TabView)
{
m_rect = ResizeDrag.ResizeWindow(rect, windowID);
GUIHelper.EndArea();
}
}
catch (Exception e)
{
DestroyOnException(e);
}
}
private void LayerControls()
{
GUIHelper.BeginHorizontal();
GUILayout.Label("Layer:", new GUILayoutOption[] { GUILayout.Width(50) });
if (GUILayout.Button("<", new GUILayoutOption[] { GUILayout.Width(30) }))
{
if (m_layer > 0)
{
m_layer--;
if (TargetGO) TargetGO.layer = m_layer;
}
}
if (GUILayout.Button(">", new GUILayoutOption[] { GUILayout.Width(30) }))
{
if (m_layer < 32)
{
m_layer++;
if (TargetGO) TargetGO.layer = m_layer;
}
}
GUILayout.Label($"{m_layer} (<color=cyan>{LayerMaskUnstrip.LayerToName(m_layer)}</color>)",
new GUILayoutOption[] { GUILayout.Width(200) });
GUILayout.EndHorizontal();
}
private void TransformList(Rect m_rect)
{
GUIHelper.BeginVertical(GUIContent.none, GUI.skin.box, null);
m_transformScroll = GUIHelper.BeginScrollView(m_transformScroll);
GUILayout.Label("<b><size=15>Children</size></b>", new GUILayoutOption[0]);
GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
ChildPages.DrawLimitInputArea();
if (ChildPages.ItemCount > ChildPages.ItemsPerPage)
{
ChildPages.CurrentPageLabel();
GUILayout.EndHorizontal();
GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
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();
if (m_children != null && m_children.Length > 0)
{
int start = ChildPages.CalculateOffsetIndex();
for (int j = start; (j < start + ChildPages.ItemsPerPage && j < ChildPages.ItemCount); j++)
{
var obj = m_children[j];
if (!obj)
{
GUILayout.Label("null", new GUILayoutOption[0]);
continue;
}
Buttons.GameObjectButton(obj.gameObject, InspectGameObject, false, m_rect.width / 2 - 80);
}
}
else
{
GUILayout.Label("<i>None</i>", new GUILayoutOption[0]);
}
GUIHelper.EndScrollView();
GUILayout.EndVertical();
}
private void ComponentList(Rect m_rect)
{
GUIHelper.BeginVertical(GUIContent.none, GUI.skin.box, null);
m_compScroll = GUIHelper.BeginScrollView(m_compScroll);
GUILayout.Label("<b><size=15>Components</size></b>", new GUILayoutOption[0]);
GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
CompPages.DrawLimitInputArea();
if (CompPages.ItemCount > CompPages.ItemsPerPage)
{
CompPages.CurrentPageLabel();
GUILayout.EndHorizontal();
GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
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();
GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
var width = m_rect.width / 2 - 135f;
m_addComponentInput = GUIHelper.TextField(m_addComponentInput, new GUILayoutOption[] { GUILayout.Width(width) });
if (GUILayout.Button("Add Comp", new GUILayoutOption[0]))
{
if (ReflectionHelpers.GetTypeByName(m_addComponentInput) is Type compType)
{
if (typeof(Component).IsAssignableFrom(compType))
{
#if CPP
TargetGO.AddComponent(Il2CppType.From(compType));
#else
TargetGO.AddComponent(compType);
#endif
}
else
{
ExplorerCore.LogWarning($"Type '{compType.Name}' is not assignable from Component!");
}
}
else
{
ExplorerCore.LogWarning($"Could not find a type by the name of '{m_addComponentInput}'!");
}
}
GUILayout.EndHorizontal();
GUI.skin.button.alignment = TextAnchor.MiddleLeft;
if (m_cachedDestroyList.Count > 0)
{
m_cachedDestroyList.Clear();
}
if (m_components != null)
{
int start = CompPages.CalculateOffsetIndex();
for (int j = start; (j < start + CompPages.ItemsPerPage && j < CompPages.ItemCount); j++)
{
var component = m_components[j];
if (!component) continue;
var type =
#if CPP
component.GetIl2CppType();
#else
component.GetType();
#endif
GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
if (ReflectionHelpers.BehaviourType.IsAssignableFrom(type))
{
#if CPP
BehaviourEnabledBtn(component.TryCast<Behaviour>());
#else
BehaviourEnabledBtn(component as Behaviour);
#endif
}
else
{
GUIHelper.Space(26);
}
if (GUILayout.Button("<color=cyan>" + type.Name + "</color>", new GUILayoutOption[] { GUILayout.Width(m_rect.width / 2 - 100) }))
{
ReflectObject(component);
}
if (GUILayout.Button("<color=red>-</color>", new GUILayoutOption[] { GUILayout.Width(20) }))
{
m_cachedDestroyList.Add(component);
}
GUILayout.EndHorizontal();
}
}
GUI.skin.button.alignment = TextAnchor.MiddleCenter;
if (m_cachedDestroyList.Count > 0)
{
for (int i = m_cachedDestroyList.Count - 1; i >= 0; i--)
{
var comp = m_cachedDestroyList[i];
GameObject.Destroy(comp);
}
}
GUIHelper.EndScrollView();
GUILayout.EndVertical();
}
private void BehaviourEnabledBtn(Behaviour obj)
{
var _col = GUI.color;
bool _enabled = obj.enabled;
if (_enabled)
{
GUI.color = Color.green;
}
else
{
GUI.color = Color.red;
}
// ------ toggle active button ------
_enabled = GUILayout.Toggle(_enabled, "", new GUILayoutOption[] { GUILayout.Width(18) });
if (obj.enabled != _enabled)
{
obj.enabled = _enabled;
}
GUI.color = _col;
}
private void GameObjectControls()
{
if (m_hideControls)
{
GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUILayout.Label("<b><size=15>GameObject Controls</size></b>", new GUILayoutOption[] { GUILayout.Width(200) });
if (GUILayout.Button("^ Show ^", new GUILayoutOption[] { GUILayout.Width(75) }))
{
m_hideControls = false;
}
GUILayout.EndHorizontal();
return;
}
GUIHelper.BeginVertical(GUIContent.none, GUI.skin.box, new GUILayoutOption[] { GUILayout.Width(520) });
GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUILayout.Label("<b><size=15>GameObject Controls</size></b>", new GUILayoutOption[] { GUILayout.Width(200) });
if (GUILayout.Button("v Hide v", new GUILayoutOption[] { GUILayout.Width(75) }))
{
m_hideControls = true;
}
GUILayout.EndHorizontal();
GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
bool m_active = TargetGO.activeSelf;
m_active = GUILayout.Toggle(m_active, (m_active ? "<color=lime>Enabled " : "<color=red>Disabled") + "</color>",
new GUILayoutOption[] { GUILayout.Width(80) });
if (TargetGO.activeSelf != m_active) { TargetGO.SetActive(m_active); }
Buttons.InstantiateButton(TargetGO, 100);
if (GUILayout.Button("Set DontDestroyOnLoad", new GUILayoutOption[] { GUILayout.Width(170) }))
{
GameObject.DontDestroyOnLoad(TargetGO);
TargetGO.hideFlags |= HideFlags.DontUnloadUnusedAsset;
}
var lbl = m_freeze ? "<color=lime>Unfreeze</color>" : "<color=orange>Freeze Pos/Rot</color>";
if (GUILayout.Button(lbl, new GUILayoutOption[] { GUILayout.Width(110) }))
{
m_freeze = !m_freeze;
if (m_freeze)
{
UpdateFreeze();
}
}
GUILayout.EndHorizontal();
GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
m_setParentInput = GUIHelper.TextField(m_setParentInput, new GUILayoutOption[0]);
if (GUILayout.Button("Set Parent", new GUILayoutOption[] { GUILayout.Width(80) }))
{
if (GameObject.Find(m_setParentInput) is GameObject newparent)
{
TargetGO.transform.parent = newparent.transform;
}
else
{
ExplorerCore.LogWarning($"Could not find gameobject '{m_setParentInput}'");
}
}
if (GUILayout.Button("Detach from parent", new GUILayoutOption[] { GUILayout.Width(160) }))
{
TargetGO.transform.parent = null;
}
GUILayout.EndHorizontal();
GUIHelper.BeginVertical(GUIContent.none, GUI.skin.box, null);
m_cachedInput[0] = TranslateControl(TranslateType.Position, ref m_translateAmount, false);
m_cachedInput[1] = TranslateControl(TranslateType.Rotation, ref m_rotateAmount, true);
m_cachedInput[2] = TranslateControl(TranslateType.Scale, ref m_scaleAmount, false);
GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
if (GUILayout.Button("<color=lime>Apply to Transform</color>", new GUILayoutOption[0]) || m_autoApplyTransform)
{
if (m_localContext)
{
TargetGO.transform.localPosition = m_cachedInput[0];
TargetGO.transform.localEulerAngles = m_cachedInput[1];
}
else
{
TargetGO.transform.position = m_cachedInput[0];
TargetGO.transform.eulerAngles = m_cachedInput[1];
}
TargetGO.transform.localScale = m_cachedInput[2];
if (m_freeze)
{
UpdateFreeze();
}
}
if (GUILayout.Button("<color=lime>Update from Transform</color>", new GUILayoutOption[0]) || m_autoUpdateTransform)
{
CacheTransformValues();
}
GUILayout.EndHorizontal();
GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
BoolToggle(ref m_autoApplyTransform, "Auto-apply to Transform?");
BoolToggle(ref m_autoUpdateTransform, "Auto-update from transform?");
GUILayout.EndHorizontal();
bool b = m_localContext;
b = GUILayout.Toggle(b, "<color=" + (b ? "lime" : "orange") + ">Use local transform values?</color>", new GUILayoutOption[0]);
if (b != m_localContext)
{
m_localContext = b;
CacheTransformValues();
if (m_freeze)
{
UpdateFreeze();
}
}
GUILayout.EndVertical();
if (GUILayout.Button("<color=red><b>Destroy</b></color>", new GUILayoutOption[] { GUILayout.Width(120) }))
{
GameObject.Destroy(TargetGO);
DestroyWindow();
return;
}
GUILayout.EndVertical();
}
private void UpdateFreeze()
{
if (m_localContext)
{
m_frozenPosition = TargetGO.transform.localPosition;
m_frozenRotation = TargetGO.transform.localRotation;
}
else
{
m_frozenPosition = TargetGO.transform.position;
m_frozenRotation = TargetGO.transform.rotation;
}
m_frozenScale = TargetGO.transform.localScale;
}
private void BoolToggle(ref bool value, string message)
{
string lbl = "<color=";
lbl += value ? "lime" : "orange";
lbl += $">{message}</color>";
value = GUILayout.Toggle(value, lbl, new GUILayoutOption[0]);
}
public enum TranslateType
{
Position,
Rotation,
Scale
}
private Vector3 TranslateControl(TranslateType mode, ref float amount, bool multByTime)
{
GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUILayout.Label($"<color=cyan><b>{(m_localContext ? "Local " : "")}{mode}</b></color>:",
new GUILayoutOption[] { GUILayout.Width(m_localContext ? 110 : 65) });
var transform = TargetGO.transform;
switch (mode)
{
case TranslateType.Position:
var pos = m_localContext ? transform.localPosition : transform.position;
GUILayout.Label(pos.ToString(), new GUILayoutOption[] { GUILayout.Width(250) });
break;
case TranslateType.Rotation:
var rot = m_localContext ? transform.localEulerAngles : transform.eulerAngles;
GUILayout.Label(rot.ToString(), new GUILayoutOption[] { GUILayout.Width(250) });
break;
case TranslateType.Scale:
GUILayout.Label(transform.localScale.ToString(), new GUILayoutOption[] { GUILayout.Width(250) });
break;
}
GUILayout.EndHorizontal();
Vector3 input = m_cachedInput[(int)mode];
GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUI.skin.label.alignment = TextAnchor.MiddleRight;
GUILayout.Label("<color=cyan>X:</color>", new GUILayoutOption[] { GUILayout.Width(20) });
PlusMinusFloat(ref input.x, amount, multByTime);
GUILayout.Label("<color=cyan>Y:</color>", new GUILayoutOption[] { GUILayout.Width(20) });
PlusMinusFloat(ref input.y, amount, multByTime);
GUILayout.Label("<color=cyan>Z:</color>", new GUILayoutOption[] { GUILayout.Width(20) });
PlusMinusFloat(ref input.z, amount, multByTime);
GUILayout.Label("+/-:", new GUILayoutOption[] { GUILayout.Width(30) });
var amountInput = amount.ToString("F3");
amountInput = GUIHelper.TextField(amountInput, new GUILayoutOption[] { GUILayout.Width(60) });
if (float.TryParse(amountInput, out float f))
{
amount = f;
}
GUI.skin.label.alignment = TextAnchor.UpperLeft;
GUILayout.EndHorizontal();
return input;
}
private void PlusMinusFloat(ref float f, float amount, bool multByTime)
{
string s = f.ToString("F3");
s = GUIHelper.TextField(s, new GUILayoutOption[] { GUILayout.Width(60) });
if (float.TryParse(s, out float f2))
{
f = f2;
}
if (GUIHelper.RepeatButton("-", new GUILayoutOption[] { GUILayout.Width(20) }))
{
f -= multByTime ? amount * Time.deltaTime : amount;
}
if (GUIHelper.RepeatButton("+", new GUILayoutOption[] { GUILayout.Width(20) }))
{
f += multByTime ? amount * Time.deltaTime : amount;
}
}
}
}

View File

@ -1,86 +0,0 @@
using UnityEngine;
using Explorer.Helpers;
namespace Explorer.UI.Inspectors
{
public class InspectUnderMouse
{
public static bool EnableInspect { get; set; } = false;
private static string m_objUnderMouseName = "";
public static void Update()
{
if (ExplorerCore.ShowMenu)
{
if (InputManager.GetKey(KeyCode.LeftShift) && InputManager.GetMouseButtonDown(1))
{
EnableInspect = !EnableInspect;
}
if (EnableInspect)
{
InspectRaycast();
}
}
else if (EnableInspect)
{
EnableInspect = false;
}
}
public static void InspectRaycast()
{
if (!UnityHelpers.MainCamera)
return;
var ray = UnityHelpers.MainCamera.ScreenPointToRay(InputManager.MousePosition);
if (Physics.Raycast(ray, out RaycastHit hit, 1000f))
{
var obj = hit.transform.gameObject;
m_objUnderMouseName = obj.transform.GetGameObjectPath();
if (InputManager.GetMouseButtonDown(0))
{
EnableInspect = false;
m_objUnderMouseName = "";
WindowManager.InspectObject(obj, out _);
}
}
else
{
m_objUnderMouseName = "";
}
}
public static void OnGUI()
{
if (EnableInspect)
{
if (m_objUnderMouseName != "")
{
var pos = InputManager.MousePosition;
var rect = new Rect(
pos.x - (Screen.width / 2), // x
Screen.height - pos.y - 50, // y
Screen.width, // w
50 // h
);
var origAlign = GUI.skin.label.alignment;
GUI.skin.label.alignment = TextAnchor.MiddleCenter;
//shadow text
GUI.Label(rect, $"<color=black>{m_objUnderMouseName}</color>");
//white text
GUI.Label(new Rect(rect.x - 1, rect.y + 1, rect.width, rect.height), m_objUnderMouseName);
GUI.skin.label.alignment = origAlign;
}
}
}
}
}

View File

@ -1,107 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using UnityEngine;
using Explorer.UI;
using Explorer.UI.Shared;
using Explorer.CacheObject;
#if CPP
using UnhollowerBaseLib;
#endif
namespace Explorer.UI.Inspectors
{
public class InstanceInspector : ReflectionInspector
{
public override bool IsStaticInspector => false;
// some extra cast-caching
public UnityEngine.Object m_uObj;
private Component m_component;
public override void Init()
{
// cache the extra cast-caching
#if CPP
if (!IsStaticInspector && Target is Il2CppSystem.Object ilObject)
{
var unityObj = ilObject.TryCast<UnityEngine.Object>();
if (unityObj)
{
m_uObj = unityObj;
var component = ilObject.TryCast<Component>();
if (component)
{
m_component = component;
}
}
}
#else
if (!IsStaticInspector)
{
m_uObj = Target as UnityEngine.Object;
m_component = Target as Component;
}
#endif
base.Init();
}
public override void Update()
{
if (Target == null)
{
ExplorerCore.Log("Target is null!");
DestroyWindow();
return;
}
if (Target is UnityEngine.Object uObj)
{
if (!uObj)
{
ExplorerCore.Log("Target was destroyed!");
DestroyWindow();
return;
}
}
base.Update();
}
public void DrawInstanceControls(Rect rect)
{
//if (m_uObj)
//{
// GUILayout.Label("Name: " + m_uObj.name, new GUILayoutOption[0]);
//}
//GUILayout.EndHorizontal();
if (m_uObj)
{
GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUILayout.Label("<b>Tools:</b>", new GUILayoutOption[] { GUILayout.Width(80) });
Buttons.InstantiateButton(m_uObj);
if (m_component && m_component.gameObject is GameObject obj)
{
GUI.skin.label.alignment = TextAnchor.MiddleRight;
GUILayout.Label("GameObject:", new GUILayoutOption[] { GUILayout.Width(135) });
var charWidth = obj.name.Length * 15;
var maxWidth = rect.width - 350;
var btnWidth = charWidth < maxWidth ? charWidth : maxWidth;
if (GUILayout.Button("<color=#00FF00>" + obj.name + "</color>", new GUILayoutOption[] { GUILayout.Width(btnWidth) }))
{
WindowManager.InspectObject(obj, out bool _);
}
GUI.skin.label.alignment = TextAnchor.UpperLeft;
}
else
{
GUILayout.Label("Name: " + m_uObj.name, new GUILayoutOption[0]);
}
GUILayout.EndHorizontal();
}
}
}
}

View File

@ -1,28 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Explorer.CacheObject;
namespace Explorer.UI.Inspectors
{
public class StaticInspector : ReflectionInspector
{
public override bool IsStaticInspector => true;
public override void Init()
{
base.Init();
}
public override bool ShouldProcessMember(CacheMember holder)
{
return base.ShouldProcessMember(holder);
}
public override void WindowFunction(int windowID)
{
base.WindowFunction(windowID);
}
}
}

View File

@ -1,431 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using UnityEngine;
using Explorer.UI;
using Explorer.UI.Shared;
using Explorer.CacheObject;
using Explorer.UI.Inspectors;
using Explorer.Helpers;
#if CPP
using UnhollowerBaseLib;
#endif
namespace Explorer.UI.Inspectors
{
public abstract class ReflectionInspector : WindowBase
{
public override string Title => WindowManager.TabView
? $"<color=cyan>[R]</color> {TargetType.Name}"
: $"Reflection Inspector ({TargetType.Name})";
public virtual bool IsStaticInspector { get; }
public Type TargetType;
private CacheMember[] m_allCachedMembers;
private CacheMember[] m_cachedMembersFiltered;
public PageHelper Pages = new PageHelper();
private bool m_autoUpdate = false;
private string m_search = "";
public MemberTypes m_typeFilter = MemberTypes.Property;
private bool m_hideFailedReflection = false;
private MemberScopes m_scopeFilter;
private enum MemberScopes
{
Both,
Instance,
Static
}
private static readonly HashSet<string> _typeAndMemberBlacklist = new HashSet<string>
{
// Causes a crash
"Type.DeclaringMethod",
// Causes a crash
"Rigidbody2D.Cast",
};
private static readonly HashSet<string> _methodStartsWithBlacklist = new HashSet<string>
{
// Pointless (handled by Properties)
"get_",
"set_",
};
public override void Init()
{
if (!IsStaticInspector)
{
TargetType = ReflectionHelpers.GetActualType(Target);
CacheMembers(ReflectionHelpers.GetAllBaseTypes(Target));
}
else
{
CacheMembers(new Type[] { TargetType });
}
}
public override void Update()
{
if (m_allCachedMembers == null)
{
return;
}
m_cachedMembersFiltered = m_allCachedMembers.Where(x => ShouldProcessMember(x)).ToArray();
if (m_autoUpdate)
{
UpdateValues();
}
}
private void UpdateValues()
{
foreach (var member in m_cachedMembersFiltered)
{
member.UpdateValue();
}
}
public virtual bool ShouldProcessMember(CacheMember holder)
{
// check MemberTypes filter
if (m_typeFilter != MemberTypes.All && m_typeFilter != holder.MemInfo?.MemberType)
return false;
// check scope filter
if (m_scopeFilter == MemberScopes.Instance)
{
return !holder.IsStatic;
}
else if (m_scopeFilter == MemberScopes.Static)
{
return holder.IsStatic;
}
// hide failed reflection
if (!string.IsNullOrEmpty(holder.ReflectionException) && m_hideFailedReflection)
return false;
// see if we should do name search
if (m_search == "" || holder.MemInfo == null)
return true;
// ok do name search
return (holder.MemInfo.DeclaringType.Name + "." + holder.MemInfo.Name)
.ToLower()
.Contains(m_search.ToLower());
}
private void CacheMembers(Type[] types)
{
var list = new List<CacheMember>();
var cachedSigs = new HashSet<string>();
foreach (var declaringType in types)
{
MemberInfo[] infos;
try
{
infos = declaringType.GetMembers(ReflectionHelpers.CommonFlags);
}
catch
{
ExplorerCore.Log($"Exception getting members for type: {declaringType.FullName}");
continue;
}
object target = Target;
string exception = null;
#if CPP
if (!IsStaticInspector && target is Il2CppSystem.Object ilObject)
{
try
{
target = ilObject.Il2CppCast(declaringType);
}
catch (Exception e)
{
exception = ReflectionHelpers.ExceptionToString(e);
}
}
#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;
var fi = member as FieldInfo;
var pi = member as PropertyInfo;
var mi = member as MethodInfo;
if (IsStaticInspector)
{
if (fi != null && !fi.IsStatic) continue;
else if (pi != null && !pi.GetAccessors()[0].IsStatic) continue;
else if (mi != null && !mi.IsStatic) continue;
}
// check blacklisted members
var sig = $"{member.DeclaringType.Name}.{member.Name}";
if (_typeAndMemberBlacklist.Any(it => it == sig))
continue;
if (_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
{
var cached = CacheFactory.GetCacheObject(member, target);
if (cached != null)
{
cachedSigs.Add(sig);
list.Add(cached);
if (string.IsNullOrEmpty(cached.ReflectionException))
{
cached.ReflectionException = exception;
}
}
}
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());
}
}
}
m_allCachedMembers = list.ToArray();
}
// =========== GUI DRAW =========== //
public override void WindowFunction(int windowID)
{
try
{
// ====== HEADER ======
var rect = WindowManager.TabView ? TabViewWindow.Instance.m_rect : this.m_rect;
if (!WindowManager.TabView)
{
Header();
GUIHelper.BeginArea(new Rect(5, 25, rect.width - 10, rect.height - 35), GUI.skin.box);
}
var asInstance = this as InstanceInspector;
GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
var labelWidth = (asInstance != null && asInstance.m_uObj)
? new GUILayoutOption[] { GUILayout.Width(245f) }
: new GUILayoutOption[0];
GUILayout.Label("<b>Type:</b> <color=cyan>" + TargetType.FullName + "</color>", labelWidth);
GUILayout.EndHorizontal();
if (asInstance != null)
{
asInstance.DrawInstanceControls(rect);
}
UIStyles.HorizontalLine(Color.grey);
GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUILayout.Label("<b>Search:</b>", new GUILayoutOption[] { GUILayout.Width(75) });
m_search = GUIHelper.TextField(m_search, new GUILayoutOption[0]);
GUILayout.EndHorizontal();
GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUILayout.Label("<b>Filter:</b>", new GUILayoutOption[] { GUILayout.Width(75) });
FilterTypeToggle(MemberTypes.All, "All");
FilterTypeToggle(MemberTypes.Property, "Properties");
FilterTypeToggle(MemberTypes.Field, "Fields");
FilterTypeToggle(MemberTypes.Method, "Methods");
GUILayout.EndHorizontal();
if (this is InstanceInspector)
{
GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUILayout.Label("<b>Scope:</b>", new GUILayoutOption[] { GUILayout.Width(75) });
FilterScopeToggle(MemberScopes.Both, "Both");
FilterScopeToggle(MemberScopes.Instance, "Instance");
FilterScopeToggle(MemberScopes.Static, "Static");
GUILayout.EndHorizontal();
}
GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUILayout.Label("<b>Values:</b>", new GUILayoutOption[] { GUILayout.Width(75) });
if (GUILayout.Button("Update", new GUILayoutOption[] { GUILayout.Width(100) }))
{
UpdateValues();
}
GUI.color = m_autoUpdate ? Color.green : Color.red;
m_autoUpdate = GUILayout.Toggle(m_autoUpdate, "Auto-update?", new GUILayoutOption[] { GUILayout.Width(100) });
GUI.color = m_hideFailedReflection ? Color.green : Color.red;
m_hideFailedReflection = GUILayout.Toggle(m_hideFailedReflection, "Hide failed Reflection?", new GUILayoutOption[] { GUILayout.Width(150) });
GUI.color = Color.white;
GUILayout.EndHorizontal();
GUIHelper.Space(10);
Pages.ItemCount = m_cachedMembersFiltered.Length;
// prev/next page buttons
GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
Pages.DrawLimitInputArea();
if (Pages.ItemCount > Pages.ItemsPerPage)
{
if (GUILayout.Button("< Prev", new GUILayoutOption[] { GUILayout.Width(80) }))
{
Pages.TurnPage(Turn.Left, ref this.scroll);
}
Pages.CurrentPageLabel();
if (GUILayout.Button("Next >", new GUILayoutOption[] { GUILayout.Width(80) }))
{
Pages.TurnPage(Turn.Right, ref this.scroll);
}
}
GUILayout.EndHorizontal();
// ====== BODY ======
scroll = GUIHelper.BeginScrollView(scroll);
GUIHelper.Space(10);
UIStyles.HorizontalLine(Color.grey);
GUIHelper.BeginVertical(GUIContent.none, GUI.skin.box, null);
var members = this.m_cachedMembersFiltered;
int start = Pages.CalculateOffsetIndex();
for (int j = start; (j < start + Pages.ItemsPerPage && j < members.Length); j++)
{
var holder = members[j];
GUIHelper.BeginHorizontal(new GUILayoutOption[] { GUILayout.Height(25) });
try
{
holder.Draw(rect, 180f);
}
catch
{
GUILayout.EndHorizontal();
continue;
}
GUILayout.EndHorizontal();
// if not last element
if (!(j == (start + Pages.ItemsPerPage - 1) || j == (members.Length - 1)))
UIStyles.HorizontalLine(new Color(0.07f, 0.07f, 0.07f), true);
}
GUILayout.EndVertical();
GUIHelper.EndScrollView();
if (!WindowManager.TabView)
{
m_rect = ResizeDrag.ResizeWindow(rect, windowID);
GUIHelper.EndArea();
}
}
catch (Exception e) when (e.Message.Contains("in a group with only"))
{
// suppress
}
catch (Exception e)
{
ExplorerCore.LogWarning("Exception drawing ReflectionWindow: " + e.GetType() + ", " + e.Message);
DestroyWindow();
return;
}
}
private void FilterTypeToggle(MemberTypes mode, string label)
{
if (m_typeFilter == mode)
{
GUI.color = Color.green;
}
else
{
GUI.color = Color.white;
}
if (GUILayout.Button(label, new GUILayoutOption[] { GUILayout.Width(100) }))
{
m_typeFilter = mode;
Pages.PageOffset = 0;
scroll = Vector2.zero;
}
GUI.color = Color.white;
}
private void FilterScopeToggle(MemberScopes mode, string label)
{
if (m_scopeFilter == mode)
{
GUI.color = Color.green;
}
else
{
GUI.color = Color.white;
}
if (GUILayout.Button(label, new GUILayoutOption[] { GUILayout.Width(100) }))
{
m_scopeFilter = mode;
Pages.PageOffset = 0;
scroll = Vector2.zero;
}
GUI.color = Color.white;
}
}
}

View File

@ -1,258 +1,108 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using UnityEngine;
using Explorer.UI.Shared;
using Explorer.CacheObject;
using Explorer.Helpers;
//using System;
//using System.Collections.Generic;
//using System.Linq;
//using System.Reflection;
//using UnityEngine;
//using Explorer.CacheObject;
//using Explorer.Helpers;
//using Explorer.UI.Shared;
namespace Explorer.UI
{
public class InteractiveValue
{
public const float MAX_LABEL_WIDTH = 400f;
public const string EVALUATE_LABEL = "<color=lime>Evaluate</color>";
//namespace Explorer.UI
//{
// public class InteractiveValue
// {
// //public const float MAX_LABEL_WIDTH = 400f;
// //public const string EVALUATE_LABEL = "<color=lime>Evaluate</color>";
public CacheObjectBase OwnerCacheObject;
// public CacheObjectBase OwnerCacheObject;
public object Value { get; set; }
public Type ValueType;
// public object Value { get; set; }
// public Type ValueType;
public string ButtonLabel => m_btnLabel ?? GetButtonLabel();
private string m_btnLabel;
// public string ButtonLabel => m_btnLabel ?? GetButtonLabel();
// private string m_btnLabel;
public MethodInfo ToStringMethod => m_toStringMethod ?? GetToStringMethod();
private MethodInfo m_toStringMethod;
// public MethodInfo ToStringMethod => m_toStringMethod ?? GetToStringMethod();
// private MethodInfo m_toStringMethod;
public virtual void Init()
{
UpdateValue();
}
// public virtual void Init()
// {
// UpdateValue();
// }
public virtual void UpdateValue()
{
GetButtonLabel();
}
// public virtual void UpdateValue()
// {
// GetButtonLabel();
// }
public float CalcWhitespace(Rect window)
{
if (!(this is IExpandHeight)) return 0f;
float whitespace = (this as IExpandHeight).WhiteSpace;
if (whitespace > 0)
{
ClampLabelWidth(window, ref whitespace);
}
// private MethodInfo GetToStringMethod()
// {
// try
// {
// m_toStringMethod = ReflectionHelpers.GetActualType(Value).GetMethod("ToString", new Type[0])
// ?? typeof(object).GetMethod("ToString", new Type[0]);
return whitespace;
}
// // test invoke
// m_toStringMethod.Invoke(Value, null);
// }
// catch
// {
// m_toStringMethod = typeof(object).GetMethod("ToString", new Type[0]);
// }
// return m_toStringMethod;
// }
public static void ClampLabelWidth(Rect window, ref float labelWidth)
{
float min = window.width * 0.37f;
if (min > MAX_LABEL_WIDTH) min = MAX_LABEL_WIDTH;
// public string GetButtonLabel()
// {
// if (Value == null) return null;
labelWidth = Mathf.Clamp(labelWidth, min, MAX_LABEL_WIDTH);
}
// var valueType = ReflectionHelpers.GetActualType(Value);
public void Draw(Rect window, float labelWidth = 215f)
{
if (labelWidth > 0)
{
ClampLabelWidth(window, ref labelWidth);
}
// string label;
var cacheMember = OwnerCacheObject as CacheMember;
// if (valueType == typeof(TextAsset))
// {
// var textAsset = Value as TextAsset;
if (cacheMember != null && cacheMember.MemInfo != null)
{
GUILayout.Label(cacheMember.RichTextName, new GUILayoutOption[] { GUILayout.Width(labelWidth) });
}
else
{
GUIHelper.Space(labelWidth);
}
// label = textAsset.text;
var cacheMethod = OwnerCacheObject as CacheMethod;
// if (label.Length > 10)
// {
// label = $"{label.Substring(0, 10)}...";
// }
if (cacheMember != null && cacheMember.HasParameters)
{
GUIHelper.BeginVertical(new GUILayoutOption[] { GUILayout.ExpandHeight(true) } );
// label = $"\"{label}\" {textAsset.name} (<color={Syntax.Class_Instance}>UnityEngine.TextAsset</color>)";
// }
// else
// {
// label = (string)ToStringMethod?.Invoke(Value, null) ?? Value.ToString();
if (cacheMember.m_isEvaluating)
{
if (cacheMethod != null && cacheMethod.GenericArgs.Length > 0)
{
cacheMethod.DrawGenericArgsInput();
}
// var classColor = valueType.IsAbstract && valueType.IsSealed
// ? Syntax.Class_Static
// : Syntax.Class_Instance;
if (cacheMember.m_arguments.Length > 0)
{
cacheMember.DrawArgsInput();
}
// string typeLabel = $"<color={classColor}>{valueType.FullName}</color>";
GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
if (GUILayout.Button(EVALUATE_LABEL, new GUILayoutOption[] { GUILayout.Width(70) }))
{
if (cacheMethod != null)
cacheMethod.Evaluate();
else
cacheMember.UpdateValue();
}
if (GUILayout.Button("Cancel", new GUILayoutOption[] { GUILayout.Width(70) }))
{
cacheMember.m_isEvaluating = false;
}
GUILayout.EndHorizontal();
}
else
{
var lbl = $"Evaluate (";
int len = cacheMember.m_arguments.Length;
if (cacheMethod != null) len += cacheMethod.GenericArgs.Length;
lbl += len + " params)";
// if (Value is UnityEngine.Object)
// {
// label = label.Replace($"({valueType.FullName})", $"({typeLabel})");
// }
// else
// {
// if (!label.Contains(valueType.FullName))
// {
// label += $" ({typeLabel})";
// }
// else
// {
// label = label.Replace(valueType.FullName, typeLabel);
// }
// }
// }
if (GUILayout.Button(lbl, new GUILayoutOption[] { GUILayout.Width(150) }))
{
cacheMember.m_isEvaluating = true;
}
}
GUILayout.EndVertical();
GUILayout.EndHorizontal();
GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUIHelper.Space(labelWidth);
}
else if (cacheMethod != null)
{
if (GUILayout.Button(EVALUATE_LABEL, new GUILayoutOption[] { GUILayout.Width(70) }))
{
cacheMethod.Evaluate();
}
GUILayout.EndHorizontal();
GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUIHelper.Space(labelWidth);
}
string typeName = $"<color={Syntax.Class_Instance}>{ValueType.FullName}</color>";
if (cacheMember != null && !string.IsNullOrEmpty(cacheMember.ReflectionException))
{
GUILayout.Label("<color=red>Reflection failed!</color> (" + cacheMember.ReflectionException + ")", new GUILayoutOption[0]);
}
else if (cacheMember != null && (cacheMember.HasParameters || cacheMember is CacheMethod) && !cacheMember.m_evaluated)
{
GUILayout.Label($"<color=grey><i>Not yet evaluated</i></color> ({typeName})", new GUILayoutOption[0]);
}
else if ((Value == null || Value is UnityEngine.Object uObj && !uObj) && !(cacheMember is CacheMethod))
{
GUILayout.Label($"<i>null ({typeName})</i>", new GUILayoutOption[0]);
}
else
{
float _width = window.width - labelWidth - 90;
if (OwnerCacheObject is CacheMethod cm)
{
cm.DrawValue(window, _width);
}
else
{
DrawValue(window, _width);
}
}
}
public virtual void DrawValue(Rect window, float width)
{
GUI.skin.button.alignment = TextAnchor.MiddleLeft;
if (GUILayout.Button(ButtonLabel, new GUILayoutOption[] { GUILayout.Width(width - 15) }))
{
if (OwnerCacheObject.IsStaticClassSearchResult)
{
WindowManager.InspectStaticReflection(Value as Type);
}
else
{
WindowManager.InspectObject(Value, out bool _);
}
}
GUI.skin.button.alignment = TextAnchor.MiddleCenter;
}
private MethodInfo GetToStringMethod()
{
try
{
m_toStringMethod = ReflectionHelpers.GetActualType(Value).GetMethod("ToString", new Type[0])
?? typeof(object).GetMethod("ToString", new Type[0]);
// test invoke
m_toStringMethod.Invoke(Value, null);
}
catch
{
m_toStringMethod = typeof(object).GetMethod("ToString", new Type[0]);
}
return m_toStringMethod;
}
public string GetButtonLabel()
{
if (Value == null) return null;
var valueType = ReflectionHelpers.GetActualType(Value);
string label;
if (valueType == typeof(TextAsset))
{
var textAsset = Value as TextAsset;
label = textAsset.text;
if (label.Length > 10)
{
label = $"{label.Substring(0, 10)}...";
}
label = $"\"{label}\" {textAsset.name} (<color={Syntax.Class_Instance}>UnityEngine.TextAsset</color>)";
}
else
{
label = (string)ToStringMethod?.Invoke(Value, null) ?? Value.ToString();
if (label.Length > 100)
{
label = label.Substring(0, 99);
}
var classColor = valueType.IsAbstract && valueType.IsSealed
? Syntax.Class_Static
: Syntax.Class_Instance;
string typeLabel = $"<color={classColor}>{valueType.FullName}</color>";
if (Value is UnityEngine.Object)
{
label = label.Replace($"({valueType.FullName})", $"({typeLabel})");
}
else
{
if (!label.Contains(valueType.FullName))
{
label += $" ({typeLabel})";
}
else
{
label = label.Replace(valueType.FullName, typeLabel);
}
}
}
return m_btnLabel = label;
}
}
}
// return m_btnLabel = label;
// }
// }
//}

View File

@ -1,312 +0,0 @@
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Explorer.UI.Shared;
using Explorer.CacheObject;
using Explorer.Helpers;
#if CPP
using UnhollowerBaseLib;
#endif
namespace Explorer.UI
{
// TODO: Re-work class using InteractiveEnumerable or maybe InteractiveCollection for the Keys/Value lists.
// Make the keys and values editable.
public class InteractiveDictionary : InteractiveValue, IExpandHeight
{
public bool IsExpanded { get; set; }
public float WhiteSpace { get; set; } = 215f;
public PageHelper Pages = new PageHelper();
private CacheObjectBase[] m_cachedKeys = new CacheObjectBase[0];
private CacheObjectBase[] m_cachedValues = new CacheObjectBase[0];
public Type TypeOfKeys
{
get
{
if (m_keysType == null) GetGenericArguments();
return m_keysType;
}
}
private Type m_keysType;
public Type TypeOfValues
{
get
{
if (m_valuesType == null) GetGenericArguments();
return m_valuesType;
}
}
private Type m_valuesType;
public IDictionary IDict
{
get => m_iDictionary ?? (m_iDictionary = Value as IDictionary) ?? Il2CppDictionaryToMono();
set => m_iDictionary = value;
}
private IDictionary m_iDictionary;
// ========== Methods ==========
// This is a bit janky due to Il2Cpp Dictionary not implementing IDictionary.
private IDictionary Il2CppDictionaryToMono()
{
// note: "ValueType" is the Dictionary itself, TypeOfValues is the 'Dictionary.Values' type.
// get keys and values
var keys = ValueType.GetProperty("Keys").GetValue(Value, null);
var values = ValueType.GetProperty("Values").GetValue(Value, null);
// create lists to hold them
var keyList = new List<object>();
var valueList = new List<object>();
// store entries with reflection
EnumerateWithReflection(keys, keyList);
EnumerateWithReflection(values, valueList);
// make actual mono dictionary
var dict = (IDictionary)Activator.CreateInstance(typeof(Dictionary<,>)
.MakeGenericType(TypeOfKeys, TypeOfValues));
// finally iterate into dictionary
for (int i = 0; i < keyList.Count; i++)
{
dict.Add(keyList[i], valueList[i]);
}
return dict;
}
private void EnumerateWithReflection(object collection, List<object> list)
{
// invoke GetEnumerator
var enumerator = collection.GetType().GetMethod("GetEnumerator").Invoke(collection, null);
// get the type of it
var enumeratorType = enumerator.GetType();
// reflect MoveNext and Current
var moveNext = enumeratorType.GetMethod("MoveNext");
var current = enumeratorType.GetProperty("Current");
// iterate
while ((bool)moveNext.Invoke(enumerator, null))
{
list.Add(current.GetValue(enumerator, null));
}
}
private void GetGenericArguments()
{
if (ValueType.IsGenericType)
{
var generics = ValueType.GetGenericArguments();
m_keysType = generics[0];
m_valuesType = generics[1];
}
else
{
// It's non-generic, just use System.Object to allow for anything.
m_keysType = typeof(object);
m_valuesType = typeof(object);
}
}
public override void UpdateValue()
{
// first make sure we won't run into a TypeInitializationException.
if (!EnsureDictionaryIsSupported())
{
if (OwnerCacheObject is CacheMember cacheMember)
{
cacheMember.ReflectionException = "Dictionary Type not supported with Reflection!";
}
return;
}
base.UpdateValue();
CacheEntries();
}
public void CacheEntries()
{
// reset
IDict = null;
if (Value == null || IDict == null)
{
return;
}
var keys = new List<CacheObjectBase>();
foreach (var key in IDict.Keys)
{
Type t = ReflectionHelpers.GetActualType(key) ?? TypeOfKeys;
var cache = CacheFactory.GetCacheObject(key, t);
keys.Add(cache);
}
var values = new List<CacheObjectBase>();
foreach (var val in IDict.Values)
{
Type t = ReflectionHelpers.GetActualType(val) ?? TypeOfValues;
var cache = CacheFactory.GetCacheObject(val, t);
values.Add(cache);
}
m_cachedKeys = keys.ToArray();
m_cachedValues = values.ToArray();
}
public bool EnsureDictionaryIsSupported()
{
if (typeof(IDictionary).IsAssignableFrom(ValueType))
{
return true;
}
#if CPP
try
{
return Check(TypeOfKeys) && Check(TypeOfValues);
bool Check(Type type)
{
var ptr = (IntPtr)typeof(Il2CppClassPointerStore<>)
.MakeGenericType(type)
.GetField("NativeClassPtr")
.GetValue(null);
if (ptr == IntPtr.Zero)
{
return false;
}
return Il2CppSystem.Type.internal_from_handle(IL2CPP.il2cpp_class_get_type(ptr)) is Il2CppSystem.Type;
}
}
catch
{
return false;
}
#else
return false;
#endif
}
// ============= GUI Draw =============
public override void DrawValue(Rect window, float width)
{
if (m_cachedKeys == null || m_cachedValues == null)
{
GUILayout.Label("Cached keys or values is null!", new GUILayoutOption[0]);
return;
}
var whitespace = CalcWhitespace(window);
if (!IsExpanded)
{
if (GUILayout.Button("v", new GUILayoutOption[] { GUILayout.Width(25) }))
{
IsExpanded = true;
}
}
else
{
if (GUILayout.Button("^", new GUILayoutOption[] { GUILayout.Width(25) }))
{
IsExpanded = false;
}
}
var negativeWhitespace = window.width - (whitespace + 100f);
int count = m_cachedKeys.Length;
GUI.skin.button.alignment = TextAnchor.MiddleLeft;
string btnLabel = $"[{count}] <color=#2df7b2>Dictionary<{TypeOfKeys.FullName}, {TypeOfValues.FullName}></color>";
if (GUILayout.Button(btnLabel, new GUILayoutOption[] { GUILayout.Width(negativeWhitespace) }))
{
WindowManager.InspectObject(Value, out bool _);
}
GUI.skin.button.alignment = TextAnchor.MiddleCenter;
GUIHelper.Space(5);
if (IsExpanded)
{
Pages.ItemCount = count;
if (count > Pages.ItemsPerPage)
{
GUILayout.EndHorizontal();
GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUIHelper.Space(whitespace);
Pages.CurrentPageLabel();
// prev/next page buttons
if (GUILayout.Button("< Prev", new GUILayoutOption[] { GUILayout.Width(60) }))
{
Pages.TurnPage(Turn.Left);
}
if (GUILayout.Button("Next >", new GUILayoutOption[] { GUILayout.Width(60) }))
{
Pages.TurnPage(Turn.Right);
}
Pages.DrawLimitInputArea();
GUIHelper.Space(5);
}
int offset = Pages.CalculateOffsetIndex();
for (int i = offset; i < offset + Pages.ItemsPerPage && i < count; i++)
{
var key = m_cachedKeys[i];
var val = m_cachedValues[i];
//collapsing the BeginHorizontal called from ReflectionWindow.WindowFunction or previous array entry
GUILayout.EndHorizontal();
GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
//GUIUnstrip.Space(whitespace);
if (key == null && val == null)
{
GUILayout.Label($"[{i}] <i><color=grey>(null)</color></i>", new GUILayoutOption[0]);
}
else
{
GUI.skin.label.alignment = TextAnchor.MiddleCenter;
GUILayout.Label($"[{i}]", new GUILayoutOption[] { GUILayout.Width(40) });
GUI.skin.label.alignment = TextAnchor.MiddleLeft;
GUILayout.Label("Key:", new GUILayoutOption[] { GUILayout.Width(40) });
if (key != null)
key.IValue.DrawValue(window, (window.width / 2) - 80f);
else
GUILayout.Label("<i>null</i>", new GUILayoutOption[0]);
GUILayout.Label("Value:", new GUILayoutOption[] { GUILayout.Width(40) });
if (val != null)
val.IValue.DrawValue(window, (window.width / 2) - 80f);
else
GUILayout.Label("<i>null</i>", new GUILayoutOption[0]);
}
}
GUI.skin.label.alignment = TextAnchor.UpperLeft;
}
}
}
}

View File

@ -1,362 +0,0 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading;
using System.Reflection;
using UnityEngine;
using Explorer.UI.Shared;
using Explorer.CacheObject;
using System.Linq;
using Explorer.Helpers;
#if CPP
using UnhollowerBaseLib;
#endif
namespace Explorer.UI
{
public class InteractiveEnumerable : InteractiveValue, IExpandHeight
{
public bool IsExpanded { get; set; }
public float WhiteSpace { get; set; } = 215f;
public PageHelper Pages = new PageHelper();
private CacheEnumerated[] m_cachedEntries = new CacheEnumerated[0];
// Type of Entries in the Array
public Type EntryType
{
get => GetEntryType();
set => m_entryType = value;
}
private Type m_entryType;
// Cached IEnumerable object
public IEnumerable Enumerable
{
get => GetEnumerable();
}
private IEnumerable m_enumerable;
// Generic Type Definition for Lists
public Type GenericTypeDef
{
get => GetGenericTypeDef();
}
private Type m_genericTypeDef;
// Cached ToArray method for Lists
public MethodInfo CppListToArrayMethod
{
get => GetGenericToArrayMethod();
}
private MethodInfo m_genericToArray;
// Cached Item Property for ILists
public PropertyInfo ItemProperty
{
get => GetItemProperty();
}
private PropertyInfo m_itemProperty;
// ========== Methods ==========
private IEnumerable GetEnumerable()
{
if (m_enumerable == null && Value != null)
{
m_enumerable = Value as IEnumerable ?? EnumerateWithReflection();
}
return m_enumerable;
}
private Type GetGenericTypeDef()
{
if (m_genericTypeDef == null && Value != null)
{
var type = Value.GetType();
if (type.IsGenericType)
{
m_genericTypeDef = type.GetGenericTypeDefinition();
}
}
return m_genericTypeDef;
}
private MethodInfo GetGenericToArrayMethod()
{
if (GenericTypeDef == null) return null;
if (m_genericToArray == null)
{
m_genericToArray = GenericTypeDef
.MakeGenericType(new Type[] { this.EntryType })
.GetMethod("ToArray");
}
return m_genericToArray;
}
private PropertyInfo GetItemProperty()
{
if (m_itemProperty == null)
{
m_itemProperty = Value?.GetType().GetProperty("Item");
}
return m_itemProperty;
}
private IEnumerable EnumerateWithReflection()
{
if (Value == null) return null;
#if CPP
if (GenericTypeDef == typeof(Il2CppSystem.Collections.Generic.List<>))
{
return (IEnumerable)CppListToArrayMethod?.Invoke(Value, new object[0]);
}
else if (GenericTypeDef == typeof(Il2CppSystem.Collections.Generic.HashSet<>))
{
return CppHashSetToMono();
}
else
{
return CppIListToMono();
}
#else
return Value as IEnumerable;
#endif
}
#if CPP
private IEnumerable CppHashSetToMono()
{
var set = new HashSet<object>();
// invoke GetEnumerator
var enumerator = Value.GetType().GetMethod("GetEnumerator").Invoke(Value, null);
// get the type of it
var enumeratorType = enumerator.GetType();
// reflect MoveNext and Current
var moveNext = enumeratorType.GetMethod("MoveNext");
var current = enumeratorType.GetProperty("Current");
// iterate
while ((bool)moveNext.Invoke(enumerator, null))
{
set.Add(current.GetValue(enumerator));
}
return set;
}
private IList CppIListToMono()
{
try
{
var genericType = typeof(List<>).MakeGenericType(new Type[] { this.EntryType });
var list = (IList)Activator.CreateInstance(genericType);
for (int i = 0; ; i++)
{
try
{
var itm = ItemProperty.GetValue(Value, new object[] { i });
list.Add(itm);
}
catch { break; }
}
return list;
}
catch (Exception e)
{
ExplorerCore.Log("Exception converting Il2Cpp IList to Mono IList: " + e.GetType() + ", " + e.Message);
return null;
}
}
#endif
private Type GetEntryType()
{
if (ValueType.IsGenericType)
{
var gArgs = ValueType.GetGenericArguments();
if (ValueType.FullName.Contains("ValueCollection"))
{
m_entryType = gArgs[gArgs.Length - 1];
}
else
{
m_entryType = gArgs[0];
}
}
else
{
m_entryType = typeof(object);
}
return m_entryType;
}
public override void UpdateValue()
{
base.UpdateValue();
if (Value == null || Enumerable == null)
{
return;
}
CacheEntries();
}
public void CacheEntries()
{
var enumerator = Enumerable.GetEnumerator();
if (enumerator == null)
{
return;
}
var list = new List<CacheEnumerated>();
int index = 0;
while (enumerator.MoveNext())
{
var obj = enumerator.Current;
if (obj != null && ReflectionHelpers.GetActualType(obj) is Type t)
{
#if CPP
if (obj is Il2CppSystem.Object iObj)
{
try
{
var cast = iObj.Il2CppCast(t);
if (cast != null)
{
obj = cast;
}
}
catch { }
}
#endif
//ExplorerCore.Log("Caching enumeration entry " + obj.ToString() + " as " + EntryType.FullName);
var cached = new CacheEnumerated() { Index = index, RefIList = Value as IList, ParentEnumeration = this };
cached.Init(obj, EntryType);
list.Add(cached);
}
else
{
list.Add(null);
}
index++;
}
m_cachedEntries = list.ToArray();
}
// ============= GUI Draw =============
public override void DrawValue(Rect window, float width)
{
if (m_cachedEntries == null)
{
GUILayout.Label("m_cachedEntries is null!", new GUILayoutOption[0]);
return;
}
var whitespace = CalcWhitespace(window);
if (!IsExpanded)
{
if (GUILayout.Button("v", new GUILayoutOption[] { GUILayout.Width(25) }))
{
IsExpanded = true;
}
}
else
{
if (GUILayout.Button("^", new GUILayoutOption[] { GUILayout.Width(25) }))
{
IsExpanded = false;
}
}
var negativeWhitespace = window.width - (whitespace + 100f);
int count = m_cachedEntries.Length;
GUI.skin.button.alignment = TextAnchor.MiddleLeft;
string btnLabel = $"[{count}] <color=#2df7b2>{EntryType.FullName}</color>";
if (GUILayout.Button(btnLabel, new GUILayoutOption[] { GUILayout.Width(negativeWhitespace) }))
{
WindowManager.InspectObject(Value, out bool _);
}
GUI.skin.button.alignment = TextAnchor.MiddleCenter;
GUIHelper.Space(5);
if (IsExpanded)
{
Pages.ItemCount = count;
if (count > Pages.ItemsPerPage)
{
GUILayout.EndHorizontal();
GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUIHelper.Space(whitespace);
Pages.CurrentPageLabel();
// prev/next page buttons
if (GUILayout.Button("< Prev", new GUILayoutOption[] { GUILayout.Width(60) }))
{
Pages.TurnPage(Turn.Left);
}
if (GUILayout.Button("Next >", new GUILayoutOption[] { GUILayout.Width(60) }))
{
Pages.TurnPage(Turn.Right);
}
Pages.DrawLimitInputArea();
GUIHelper.Space(5);
}
int offset = Pages.CalculateOffsetIndex();
for (int i = offset; i < offset + Pages.ItemsPerPage && i < count; i++)
{
var entry = m_cachedEntries[i];
//collapsing the BeginHorizontal called from ReflectionWindow.WindowFunction or previous array entry
GUILayout.EndHorizontal();
GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUIHelper.Space(whitespace);
if (entry == null || entry.IValue == null)
{
GUILayout.Label($"[{i}] <i><color=grey>(null)</color></i>", new GUILayoutOption[0]);
}
else
{
GUI.skin.label.alignment = TextAnchor.MiddleCenter;
GUILayout.Label($"[{i}]", new GUILayoutOption[] { GUILayout.Width(30) });
GUI.skin.label.alignment = TextAnchor.MiddleLeft;
entry.IValue.DrawValue(window, window.width - (whitespace + 85));
}
}
GUI.skin.label.alignment = TextAnchor.UpperLeft;
}
}
}
}

View File

@ -1,25 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using Explorer.UI.Shared;
using Explorer.CacheObject;
namespace Explorer.UI
{
public class InteractiveGameObject : InteractiveValue
{
public override void DrawValue(Rect window, float width)
{
Buttons.GameObjectButton(Value, null, false, width);
}
public override void UpdateValue()
{
base.UpdateValue();
}
}
}

View File

@ -1,51 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Explorer.Helpers;
using UnityEngine;
namespace Explorer.UI
{
public class InteractiveSprite : InteractiveTexture2D
{
private Sprite refSprite;
public override void UpdateValue()
{
#if CPP
if (Value != null && Value.Il2CppCast(typeof(Sprite)) is Sprite sprite)
{
refSprite = sprite;
}
#else
if (Value is Sprite sprite)
{
refSprite = sprite;
}
#endif
base.UpdateValue();
}
public override void GetTexture2D()
{
if (refSprite)
{
currentTex = refSprite.texture;
}
}
public override void GetGUIContent()
{
// Check if the Sprite.textureRect is just the entire texture
if (refSprite.textureRect != new Rect(0, 0, currentTex.width, currentTex.height))
{
// It's not, do a sub-copy.
currentTex = Texture2DHelpers.Copy(refSprite.texture, refSprite.textureRect);
}
base.GetGUIContent();
}
}
}

View File

@ -1,30 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
namespace Explorer.UI
{
// This class is possibly unnecessary.
// It's just for CacheMembers that have 'Texture' as the value type, but is actually a Texture2D.
public class InteractiveTexture : InteractiveTexture2D
{
public override void GetTexture2D()
{
#if CPP
if (Value != null && Value.Il2CppCast(typeof(Texture2D)) is Texture2D tex)
#else
if (Value is Texture2D tex)
#endif
{
currentTex = tex;
texContent = new GUIContent
{
image = currentTex
};
}
}
}
}

View File

@ -1,149 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Explorer.CacheObject;
using Explorer.Config;
using UnityEngine;
using System.IO;
using Explorer.Helpers;
#if CPP
using Explorer.Unstrip.ImageConversion;
#endif
namespace Explorer.UI
{
public class InteractiveTexture2D : InteractiveValue, IExpandHeight
{
public bool IsExpanded { get; set; }
public float WhiteSpace { get; set; } = 215f;
public Texture2D currentTex;
public GUIContent texContent;
private string saveFolder = ModConfig.Instance.Default_Output_Path;
public override void Init()
{
base.Init();
}
public override void UpdateValue()
{
base.UpdateValue();
GetTexture2D();
}
public virtual void GetTexture2D()
{
#if CPP
if (Value != null && Value.Il2CppCast(typeof(Texture2D)) is Texture2D tex)
#else
if (Value is Texture2D tex)
#endif
{
currentTex = tex;
}
}
public virtual void GetGUIContent()
{
texContent = new GUIContent
{
image = currentTex
};
}
public override void DrawValue(Rect window, float width)
{
GUIHelper.BeginVertical();
GUIHelper.BeginHorizontal();
if (currentTex && !IsExpanded)
{
if (GUILayout.Button("v", new GUILayoutOption[] { GUILayout.Width(25) }))
{
IsExpanded = true;
GetGUIContent();
}
}
else if (currentTex)
{
if (GUILayout.Button("^", new GUILayoutOption[] { GUILayout.Width(25) }))
{
IsExpanded = false;
}
}
base.DrawValue(window, width);
GUILayout.EndHorizontal();
if (currentTex && IsExpanded)
{
DrawTextureControls();
DrawTexture();
}
GUILayout.EndVertical();
}
// Temporarily disabled in BepInEx IL2CPP.
private void DrawTexture()
{
#if CPP
#if BIE
#else
GUILayout.Label(texContent, new GUILayoutOption[0]);
#endif
#else
GUILayout.Label(texContent, new GUILayoutOption[0]);
#endif
}
private void DrawTextureControls()
{
GUIHelper.BeginHorizontal();
GUILayout.Label("Save folder:", new GUILayoutOption[] { GUILayout.Width(80f) });
saveFolder = GUIHelper.TextField(saveFolder, new GUILayoutOption[0]);
GUIHelper.Space(10f);
GUILayout.EndHorizontal();
if (GUILayout.Button("Save to PNG", new GUILayoutOption[] { GUILayout.Width(100f) }))
{
var name = RemoveInvalidFilenameChars(currentTex.name ?? "");
if (string.IsNullOrEmpty(name))
{
if (OwnerCacheObject is CacheMember cacheMember)
{
name = cacheMember.MemInfo.Name;
}
else
{
name = "UNTITLED";
}
}
Texture2DHelpers.SaveTextureAsPNG(currentTex, saveFolder, name, false);
ExplorerCore.Log($@"Saved to {saveFolder}\{name}.png!");
}
}
private string RemoveInvalidFilenameChars(string s)
{
var invalid = System.IO.Path.GetInvalidFileNameChars();
foreach (var c in invalid)
{
s = s.Replace(c.ToString(), "");
}
return s;
}
}
}

View File

@ -1,115 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using Explorer.UI.Shared;
using Explorer.CacheObject;
namespace Explorer.UI
{
public class InteractiveColor : InteractiveValue, IExpandHeight
{
private string r = "0";
private string g = "0";
private string b = "0";
private string a = "0";
public bool IsExpanded { get; set; }
public float WhiteSpace { get; set; } = 215f;
public override void UpdateValue()
{
base.UpdateValue();
if (Value == null) return;
var color = (Color)Value;
r = color.r.ToString();
g = color.g.ToString();
b = color.b.ToString();
a = color.a.ToString();
}
public override void DrawValue(Rect window, float width)
{
if (OwnerCacheObject.CanWrite)
{
if (!IsExpanded)
{
if (GUILayout.Button("v", new GUILayoutOption[] { GUILayout.Width(25) }))
{
IsExpanded = true;
}
}
else
{
if (GUILayout.Button("^", new GUILayoutOption[] { GUILayout.Width(25) }))
{
IsExpanded = false;
}
}
}
//var c = (Color)Value;
//GUI.color = c;
GUILayout.Label($"<color=#2df7b2>Color:</color> {((Color)Value).ToString()}", new GUILayoutOption[0]);
//GUI.color = Color.white;
if (OwnerCacheObject.CanWrite && IsExpanded)
{
GUILayout.EndHorizontal();
var whitespace = CalcWhitespace(window);
GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUIHelper.Space(whitespace);
GUILayout.Label("R:", new GUILayoutOption[] { GUILayout.Width(30) });
r = GUIHelper.TextField(r, new GUILayoutOption[] { GUILayout.Width(120) });
GUILayout.EndHorizontal();
GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUIHelper.Space(whitespace);
GUILayout.Label("G:", new GUILayoutOption[] { GUILayout.Width(30) });
g = GUIHelper.TextField(g, new GUILayoutOption[] { GUILayout.Width(120) });
GUILayout.EndHorizontal();
GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUIHelper.Space(whitespace);
GUILayout.Label("B:", new GUILayoutOption[] { GUILayout.Width(30) });
b = GUIHelper.TextField(b, new GUILayoutOption[] { GUILayout.Width(120) });
GUILayout.EndHorizontal();
GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUIHelper.Space(whitespace);
GUILayout.Label("A:", new GUILayoutOption[] { GUILayout.Width(30) });
a = GUIHelper.TextField(a, new GUILayoutOption[] { GUILayout.Width(120) });
GUILayout.EndHorizontal();
// draw set value button
GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUIHelper.Space(whitespace);
if (GUILayout.Button("<color=lime>Apply</color>", new GUILayoutOption[] { GUILayout.Width(155) }))
{
SetValueFromInput();
}
GUILayout.EndHorizontal();
GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
}
}
private void SetValueFromInput()
{
if (float.TryParse(r, out float fR)
&& float.TryParse(g, out float fG)
&& float.TryParse(b, out float fB)
&& float.TryParse(a, out float fA))
{
Value = new Color(fR, fG, fB, fA);
OwnerCacheObject.SetValue();
}
}
}
}

View File

@ -1,91 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using UnityEngine;
using Explorer.UI.Shared;
using Explorer.CacheObject;
namespace Explorer.UI
{
public class InteractiveEnum : InteractiveValue
{
internal static Dictionary<Type, string[]> EnumNamesInternalCache = new Dictionary<Type, string[]>();
// public Type EnumType;
public string[] EnumNames = new string[0];
public override void Init()
{
if (ValueType == null && Value != null)
{
ValueType = Value.GetType();
}
if (ValueType != null)
{
GetNames();
}
else
{
if (OwnerCacheObject is CacheMember cacheMember)
{
cacheMember.ReflectionException = "Unknown, could not get Enum names.";
}
}
}
internal void GetNames()
{
if (!EnumNamesInternalCache.ContainsKey(ValueType))
{
// using GetValues not GetNames, to catch instances of weird enums (eg CameraClearFlags)
var values = Enum.GetValues(ValueType);
var set = new HashSet<string>();
foreach (var value in values)
{
var v = value.ToString();
if (set.Contains(v)) continue;
set.Add(v);
}
EnumNamesInternalCache.Add(ValueType, set.ToArray());
}
EnumNames = EnumNamesInternalCache[ValueType];
}
public override void DrawValue(Rect window, float width)
{
if (OwnerCacheObject.CanWrite)
{
if (GUILayout.Button("<", new GUILayoutOption[] { GUILayout.Width(25) }))
{
SetEnum(-1);
OwnerCacheObject.SetValue();
}
if (GUILayout.Button(">", new GUILayoutOption[] { GUILayout.Width(25) }))
{
SetEnum(1);
OwnerCacheObject.SetValue();
}
}
GUILayout.Label(Value.ToString() + $"<color={Syntax.StructGreen}><i> ({ValueType})</i></color>", new GUILayoutOption[0]);
}
public void SetEnum(int change)
{
var names = EnumNames.ToList();
int newindex = names.IndexOf(Value.ToString()) + change;
if (newindex >= 0 && newindex < names.Count)
{
Value = Enum.Parse(ValueType, EnumNames[newindex]);
}
}
}
}

View File

@ -1,113 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using Explorer.UI.Shared;
using Explorer.CacheObject;
namespace Explorer.UI
{
public class InteractiveFlags : InteractiveEnum, IExpandHeight
{
public bool[] m_enabledFlags = new bool[0];
public bool IsExpanded { get; set; }
public float WhiteSpace { get; set; } = 215f;
public override void Init()
{
base.Init();
UpdateValue();
}
public override void UpdateValue()
{
base.UpdateValue();
if (Value == null) return;
try
{
var enabledNames = Value.ToString().Split(',').Select(it => it.Trim());
m_enabledFlags = new bool[EnumNames.Length];
for (int i = 0; i < EnumNames.Length; i++)
{
m_enabledFlags[i] = enabledNames.Contains(EnumNames[i]);
}
}
catch (Exception e)
{
ExplorerCore.Log(e.ToString());
}
}
public override void DrawValue(Rect window, float width)
{
if (OwnerCacheObject.CanWrite)
{
if (!IsExpanded)
{
if (GUILayout.Button("v", new GUILayoutOption[] { GUILayout.Width(25) }))
{
IsExpanded = true;
}
}
else
{
if (GUILayout.Button("^", new GUILayoutOption[] { GUILayout.Width(25) }))
{
IsExpanded = false;
}
}
}
GUILayout.Label(Value.ToString() + "<color=#2df7b2><i> (" + ValueType + ")</i></color>", new GUILayoutOption[0]);
if (IsExpanded)
{
GUILayout.EndHorizontal();
var whitespace = CalcWhitespace(window);
for (int i = 0; i < EnumNames.Length; i++)
{
GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUIHelper.Space(whitespace);
m_enabledFlags[i] = GUILayout.Toggle(m_enabledFlags[i], EnumNames[i], new GUILayoutOption[0]);
GUILayout.EndHorizontal();
}
GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUIHelper.Space(whitespace);
if (GUILayout.Button("<color=lime>Apply</color>", new GUILayoutOption[] { GUILayout.Width(155) }))
{
SetFlagsFromInput();
}
GUILayout.EndHorizontal();
GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
}
}
public void SetFlagsFromInput()
{
string val = "";
for (int i = 0; i < EnumNames.Length; i++)
{
if (m_enabledFlags[i])
{
if (val != "") val += ", ";
val += EnumNames[i];
}
}
Value = Enum.Parse(ValueType, val);
OwnerCacheObject.SetValue();
}
}
}

View File

@ -1,262 +0,0 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using UnityEngine;
#if CPP
using UnhollowerRuntimeLib;
#endif
using Explorer.UI.Shared;
using Explorer.CacheObject;
using Explorer.Config;
namespace Explorer.UI
{
public class InteractivePrimitive : InteractiveValue
{
private string m_valueToString;
private bool m_isBool;
private bool m_isString;
public MethodInfo ParseMethod => m_parseMethod ?? (m_parseMethod = Value.GetType().GetMethod("Parse", new Type[] { typeof(string) }));
private MethodInfo m_parseMethod;
private bool m_canBitwiseOperate;
private bool m_inBitwiseMode;
private string m_bitwiseOperatorInput = "0";
private string m_binaryInput;
public override void Init()
{
if (ValueType == null)
{
ValueType = Value?.GetType();
// has to be a string at this point
if (ValueType == null)
{
ValueType = typeof(string);
}
}
if (ValueType == typeof(string))
{
m_isString = true;
}
else if (ValueType == typeof(bool))
{
m_isBool = true;
}
m_canBitwiseOperate = typeof(int).IsAssignableFrom(ValueType);
UpdateValue();
}
public override void UpdateValue()
{
base.UpdateValue();
RefreshToString();
}
private void RefreshToString()
{
m_valueToString = Value?.ToString();
if (m_canBitwiseOperate && Value != null)
{
var _int = (int)Value;
m_binaryInput = Convert.ToString(_int, toBase: 2);
}
}
public override void DrawValue(Rect window, float width)
{
if (m_isBool)
{
var b = (bool)Value;
var label = $"<color={(b ? "lime" : "red")}>{b}</color>";
if (OwnerCacheObject.CanWrite)
{
Value = GUILayout.Toggle(b, label, new GUILayoutOption[] { GUILayout.Width(60) });
DrawApplyButton();
//if (b != (bool)Value)
//{
// Value = b;
// OwnerCacheObject.SetValue();
//}
}
else
{
GUILayout.Label(label, new GUILayoutOption[0]);
}
return;
}
// all other non-bool values use TextField
GUIHelper.BeginVertical(new GUILayoutOption[0]);
GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUILayout.Label("<color=#2df7b2><i>" + ValueType.Name + "</i></color>", new GUILayoutOption[] { GUILayout.Width(50) });
m_valueToString = GUIHelper.TextArea(m_valueToString, new GUILayoutOption[] { GUIHelper.ExpandWidth(true) });
DrawApplyButton();
if (ModConfig.Instance.Bitwise_Support && m_canBitwiseOperate)
{
m_inBitwiseMode = GUILayout.Toggle(m_inBitwiseMode, "Bitwise?", new GUILayoutOption[0]);
}
GUIHelper.Space(10);
GUILayout.EndHorizontal();
if (ModConfig.Instance.Bitwise_Support && m_inBitwiseMode)
{
DrawBitwise();
}
GUILayout.EndVertical();
}
private void DrawApplyButton()
{
if (OwnerCacheObject.CanWrite)
{
if (GUILayout.Button("<color=#00FF00>Apply</color>", new GUILayoutOption[] { GUILayout.Width(60) }))
{
if (m_isBool)
{
OwnerCacheObject.SetValue();
}
else
{
SetValueFromInput();
}
}
}
}
private void DrawBitwise()
{
if (OwnerCacheObject.CanWrite)
{
GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUI.skin.label.alignment = TextAnchor.MiddleRight;
GUILayout.Label("RHS:", new GUILayoutOption[] { GUILayout.Width(35) });
GUI.skin.label.alignment = TextAnchor.UpperLeft;
if (GUILayout.Button("~", new GUILayoutOption[] { GUILayout.Width(25) }))
{
if (int.TryParse(m_bitwiseOperatorInput, out int bit))
{
Value = ~bit;
RefreshToString();
}
}
if (GUILayout.Button("<<", new GUILayoutOption[] { GUILayout.Width(25) }))
{
if (int.TryParse(m_bitwiseOperatorInput, out int bit))
{
Value = (int)Value << bit;
RefreshToString();
}
}
if (GUILayout.Button(">>", new GUILayoutOption[] { GUILayout.Width(25) }))
{
if (int.TryParse(m_bitwiseOperatorInput, out int bit))
{
Value = (int)Value >> bit;
RefreshToString();
}
}
if (GUILayout.Button("|", new GUILayoutOption[] { GUILayout.Width(25) }))
{
if (int.TryParse(m_bitwiseOperatorInput, out int bit))
{
Value = (int)Value | bit;
RefreshToString();
}
}
if (GUILayout.Button("&", new GUILayoutOption[] { GUILayout.Width(25) }))
{
if (int.TryParse(m_bitwiseOperatorInput, out int bit))
{
Value = (int)Value & bit;
RefreshToString();
}
}
if (GUILayout.Button("^", new GUILayoutOption[] { GUILayout.Width(25) }))
{
if (int.TryParse(m_bitwiseOperatorInput, out int bit))
{
Value = (int)Value ^ bit;
RefreshToString();
}
}
m_bitwiseOperatorInput = GUIHelper.TextField(m_bitwiseOperatorInput, new GUILayoutOption[] { GUILayout.Width(55) });
GUILayout.EndHorizontal();
}
GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUILayout.Label($"<color=cyan>Binary:</color>", new GUILayoutOption[] { GUILayout.Width(60) });
m_binaryInput = GUIHelper.TextField(m_binaryInput, new GUILayoutOption[0]);
if (OwnerCacheObject.CanWrite)
{
if (GUILayout.Button("Apply", new GUILayoutOption[0]))
{
SetValueFromBinaryInput();
}
}
GUILayout.EndHorizontal();
}
public void SetValueFromInput()
{
if (m_isString)
{
Value = m_valueToString;
}
else
{
try
{
Value = ParseMethod.Invoke(null, new object[] { m_valueToString });
}
catch (Exception e)
{
ExplorerCore.Log("Exception parsing value: " + e.GetType() + ", " + e.Message);
}
}
OwnerCacheObject.SetValue();
RefreshToString();
}
private void SetValueFromBinaryInput()
{
try
{
var method = typeof(Convert).GetMethod($"To{ValueType.Name}", new Type[] { typeof(string), typeof(int) });
Value = method.Invoke(null, new object[] { m_binaryInput, 2 });
OwnerCacheObject.SetValue();
RefreshToString();
}
catch (Exception e)
{
ExplorerCore.Log("Exception setting value: " + e.GetType() + ", " + e.Message);
}
}
}
}

View File

@ -1,103 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using Explorer.UI.Shared;
using Explorer.CacheObject;
namespace Explorer.UI
{
public class InteractiveQuaternion : InteractiveValue, IExpandHeight
{
private string x = "0";
private string y = "0";
private string z = "0";
public bool IsExpanded { get; set; }
public float WhiteSpace { get; set; } = 215f;
public override void UpdateValue()
{
base.UpdateValue();
if (Value == null) return;
var euler = ((Quaternion)Value).eulerAngles;
x = euler.x.ToString();
y = euler.y.ToString();
z = euler.z.ToString();
}
public override void DrawValue(Rect window, float width)
{
if (OwnerCacheObject.CanWrite)
{
if (!IsExpanded)
{
if (GUILayout.Button("v", new GUILayoutOption[] { GUILayout.Width(25) }))
{
IsExpanded = true;
}
}
else
{
if (GUILayout.Button("^", new GUILayoutOption[] { GUILayout.Width(25) }))
{
IsExpanded = false;
}
}
}
GUILayout.Label($"<color=#2df7b2>Quaternion</color>: {((Quaternion)Value).eulerAngles.ToString()}", new GUILayoutOption[0]);
if (OwnerCacheObject.CanWrite && IsExpanded)
{
GUILayout.EndHorizontal();
var whitespace = CalcWhitespace(window);
GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUIHelper.Space(whitespace);
GUILayout.Label("X:", new GUILayoutOption[] { GUILayout.Width(30) });
x = GUIHelper.TextField(x, new GUILayoutOption[] { GUILayout.Width(120) });
GUILayout.EndHorizontal();
GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUIHelper.Space(whitespace);
GUILayout.Label("Y:", new GUILayoutOption[] { GUILayout.Width(30) });
y = GUIHelper.TextField(y, new GUILayoutOption[] { GUILayout.Width(120) });
GUILayout.EndHorizontal();
GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUIHelper.Space(whitespace);
GUILayout.Label("Z:", new GUILayoutOption[] { GUILayout.Width(30) });
z = GUIHelper.TextField(z, new GUILayoutOption[] { GUILayout.Width(120) });
GUILayout.EndHorizontal();
// draw set value button
GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUIHelper.Space(whitespace);
if (GUILayout.Button("<color=lime>Apply</color>", new GUILayoutOption[] { GUILayout.Width(155) }))
{
SetValueFromInput();
}
GUILayout.EndHorizontal();
GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
}
}
private void SetValueFromInput()
{
if (float.TryParse(x, out float fX)
&& float.TryParse(y, out float fY)
&& float.TryParse(z, out float fZ))
{
Value = Quaternion.Euler(new Vector3(fX, fY, fZ));
OwnerCacheObject.SetValue();
}
}
}
}

View File

@ -1,112 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using Explorer.UI.Shared;
using Explorer.CacheObject;
namespace Explorer.UI
{
public class InteractiveRect : InteractiveValue, IExpandHeight
{
private string x = "0";
private string y = "0";
private string w = "0";
private string h = "0";
public bool IsExpanded { get; set; }
public float WhiteSpace { get; set; } = 215f;
public override void UpdateValue()
{
base.UpdateValue();
if (Value == null) return;
var rect = (Rect)Value;
x = rect.x.ToString();
y = rect.y.ToString();
w = rect.width.ToString();
h = rect.height.ToString();
}
public override void DrawValue(Rect window, float width)
{
if (OwnerCacheObject.CanWrite)
{
if (!IsExpanded)
{
if (GUILayout.Button("v", new GUILayoutOption[] { GUILayout.Width(25) }))
{
IsExpanded = true;
}
}
else
{
if (GUILayout.Button("^", new GUILayoutOption[] { GUILayout.Width(25) }))
{
IsExpanded = false;
}
}
}
GUILayout.Label($"<color=#2df7b2>Rect</color>: {((Rect)Value).ToString()}", new GUILayoutOption[0]);
if (OwnerCacheObject.CanWrite && IsExpanded)
{
GUILayout.EndHorizontal();
var whitespace = CalcWhitespace(window);
GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUIHelper.Space(whitespace);
GUILayout.Label("X:", new GUILayoutOption[] { GUILayout.Width(30) });
x = GUIHelper.TextField(x, new GUILayoutOption[] { GUILayout.Width(120) });
GUILayout.EndHorizontal();
GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUIHelper.Space(whitespace);
GUILayout.Label("Y:", new GUILayoutOption[] { GUILayout.Width(30) });
y = GUIHelper.TextField(y, new GUILayoutOption[] { GUILayout.Width(120) });
GUILayout.EndHorizontal();
GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUIHelper.Space(whitespace);
GUILayout.Label("W:", new GUILayoutOption[] { GUILayout.Width(30) });
w = GUIHelper.TextField(w, new GUILayoutOption[] { GUILayout.Width(120) });
GUILayout.EndHorizontal();
GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUIHelper.Space(whitespace);
GUILayout.Label("H:", new GUILayoutOption[] { GUILayout.Width(30) });
h = GUIHelper.TextField(h, new GUILayoutOption[] { GUILayout.Width(120) });
GUILayout.EndHorizontal();
// draw set value button
GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUIHelper.Space(whitespace);
if (GUILayout.Button("<color=lime>Apply</color>", new GUILayoutOption[] { GUILayout.Width(155) }))
{
SetValueFromInput();
}
GUILayout.EndHorizontal();
GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
}
}
private void SetValueFromInput()
{
if (float.TryParse(x, out float fX)
&& float.TryParse(y, out float fY)
&& float.TryParse(w, out float fW)
&& float.TryParse(h, out float fH))
{
Value = new Rect(fX, fY, fW, fH);
OwnerCacheObject.SetValue();
}
}
}
}

View File

@ -1,171 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using UnityEngine;
namespace Explorer.UI
{
public class InteractiveVector : InteractiveValue, IExpandHeight
{
public int VectorSize = 2;
private string x = "0";
private string y = "0";
private string z = "0";
private string w = "0";
//private MethodInfo m_toStringMethod;
public bool IsExpanded { get; set; }
public float WhiteSpace { get; set; } = 215f;
public override void Init()
{
if (ValueType == null && Value != null)
{
ValueType = Value.GetType();
}
if (ValueType == typeof(Vector2))
{
VectorSize = 2;
//m_toStringMethod = typeof(Vector2).GetMethod("ToString", new Type[0]);
}
else if (ValueType == typeof(Vector3))
{
VectorSize = 3;
//m_toStringMethod = typeof(Vector3).GetMethod("ToString", new Type[0]);
}
else
{
VectorSize = 4;
//m_toStringMethod = typeof(Vector4).GetMethod("ToString", new Type[0]);
}
base.Init();
}
public override void UpdateValue()
{
base.UpdateValue();
if (Value is Vector2 vec2)
{
x = vec2.x.ToString();
y = vec2.y.ToString();
}
else if (Value is Vector3 vec3)
{
x = vec3.x.ToString();
y = vec3.y.ToString();
z = vec3.z.ToString();
}
else if (Value is Vector4 vec4)
{
x = vec4.x.ToString();
y = vec4.y.ToString();
z = vec4.z.ToString();
w = vec4.w.ToString();
}
}
public override void DrawValue(Rect window, float width)
{
if (OwnerCacheObject.CanWrite)
{
if (!IsExpanded)
{
if (GUILayout.Button("v", new GUILayoutOption[] { GUILayout.Width(25) }))
{
IsExpanded = true;
}
}
else
{
if (GUILayout.Button("^", new GUILayoutOption[] { GUILayout.Width(25) }))
{
IsExpanded = false;
}
}
}
GUILayout.Label($"<color=#2df7b2>Vector{VectorSize}</color>: {(string)ToStringMethod.Invoke(Value, new object[0])}", new GUILayoutOption[0]);
if (OwnerCacheObject.CanWrite && IsExpanded)
{
GUILayout.EndHorizontal();
var whitespace = CalcWhitespace(window);
// always draw x and y
GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUIHelper.Space(whitespace);
GUILayout.Label("X:", new GUILayoutOption[] { GUILayout.Width(30) });
x = GUIHelper.TextField(x, new GUILayoutOption[] { GUILayout.Width(120) });
GUILayout.EndHorizontal();
GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUIHelper.Space(whitespace);
GUILayout.Label("Y:", new GUILayoutOption[] { GUILayout.Width(30) });
y = GUIHelper.TextField(y, new GUILayoutOption[] { GUILayout.Width(120) });
GUILayout.EndHorizontal();
if (VectorSize > 2)
{
// draw z
GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUIHelper.Space(whitespace);
GUILayout.Label("Z:", new GUILayoutOption[] { GUILayout.Width(30) });
z = GUIHelper.TextField(z, new GUILayoutOption[] { GUILayout.Width(120) });
GUILayout.EndHorizontal();
}
if (VectorSize > 3)
{
// draw w
GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUIHelper.Space(whitespace);
GUILayout.Label("W:", new GUILayoutOption[] { GUILayout.Width(30) });
w = GUIHelper.TextField(w, new GUILayoutOption[] { GUILayout.Width(120) });
GUILayout.EndHorizontal();
}
// draw set value button
GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUIHelper.Space(whitespace);
if (GUILayout.Button("<color=lime>Apply</color>", new GUILayoutOption[] { GUILayout.Width(155) }))
{
SetValueFromInput();
}
GUILayout.EndHorizontal();
GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
}
}
private void SetValueFromInput()
{
if (float.TryParse(x, out float fX)
&& float.TryParse(y, out float fY)
&& float.TryParse(z, out float fZ)
&& float.TryParse(w, out float fW))
{
object vector = null;
switch (VectorSize)
{
case 2: vector = new Vector2(fX, fY); break;
case 3: vector = new Vector3(fX, fY, fZ); break;
case 4: vector = new Vector4(fX, fY, fZ, fW); break;
}
if (vector != null)
{
Value = vector;
OwnerCacheObject.SetValue();
}
}
}
}
}

View File

@ -1,17 +0,0 @@
using UnityEngine;
namespace Explorer.UI.Main
{
public abstract class BaseMainMenuPage
{
public virtual string Name { get; }
public Vector2 scroll = Vector2.zero;
public abstract void Init();
public abstract void DrawWindow();
public abstract void Update();
}
}

View File

@ -1,56 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using UnityEngine;
// Thanks to ManlyMarco for this
namespace Explorer.UI.Main
{
public struct AutoComplete
{
public string Full => Prefix + Addition;
public readonly string Prefix;
public readonly string Addition;
public readonly Contexts Context;
public Color TextColor => Context == Contexts.Namespace
? Color.gray
: Color.white;
public AutoComplete(string addition, string prefix, Contexts type)
{
Addition = addition;
Prefix = prefix;
Context = type;
}
public enum Contexts
{
Namespace,
Other
}
}
public static class AutoCompleteHelpers
{
public static HashSet<string> Namespaces => _namespaces ?? GetNamespaces();
private static HashSet<string> _namespaces;
private static HashSet<string> GetNamespaces()
{
var set = new HashSet<string>(
AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(GetTypes)
.Where(x => x.IsPublic && !string.IsNullOrEmpty(x.Namespace))
.Select(x => x.Namespace));
return _namespaces = set;
IEnumerable<Type> GetTypes(Assembly asm) => asm.TryGetTypes();
}
}
}

View File

@ -1,70 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using Mono.CSharp;
// Thanks to ManlyMarco for this
namespace Explorer.UI.Main
{
internal class ScriptEvaluator : Evaluator, IDisposable
{
private static readonly HashSet<string> StdLib = new HashSet<string>(StringComparer.InvariantCultureIgnoreCase)
{
"mscorlib", "System.Core", "System", "System.Xml"
};
private readonly TextWriter _logger;
public ScriptEvaluator(TextWriter logger) : base(BuildContext(logger))
{
_logger = logger;
ImportAppdomainAssemblies(ReferenceAssembly);
AppDomain.CurrentDomain.AssemblyLoad += OnAssemblyLoad;
}
public void Dispose()
{
AppDomain.CurrentDomain.AssemblyLoad -= OnAssemblyLoad;
_logger.Dispose();
}
private void OnAssemblyLoad(object sender, AssemblyLoadEventArgs args)
{
string name = args.LoadedAssembly.GetName().Name;
if (StdLib.Contains(name))
return;
ReferenceAssembly(args.LoadedAssembly);
}
private static CompilerContext BuildContext(TextWriter tw)
{
var reporter = new StreamReportPrinter(tw);
var settings = new CompilerSettings
{
Version = LanguageVersion.Experimental,
GenerateDebugInfo = false,
StdLib = true,
Target = Target.Library,
WarningLevel = 0,
EnhancedWarnings = false
};
return new CompilerContext(settings, reporter);
}
private static void ImportAppdomainAssemblies(Action<Assembly> import)
{
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
{
string name = assembly.GetName().Name;
if (StdLib.Contains(name))
continue;
import(assembly);
}
}
}
}

View File

@ -1,79 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Explorer.UI.Inspectors;
using Mono.CSharp;
using UnityEngine;
namespace Explorer.UI.Main
{
public class ScriptInteraction : InteractiveBase
{
public static void Log(object message)
{
ExplorerCore.Log(message);
}
public static object CurrentTarget()
{
if (!WindowManager.TabView)
{
ExplorerCore.Log("CurrentTarget() is only a valid method when in Tab View mode!");
return null;
}
return WindowManager.Windows.ElementAt(TabViewWindow.Instance.TargetTabID).Target;
}
public static object[] AllTargets()
{
var list = new List<object>();
foreach (var window in WindowManager.Windows)
{
if (window.Target != null)
{
list.Add(window.Target);
}
}
return list.ToArray();
}
public static void Inspect(object obj)
{
WindowManager.InspectObject(obj, out bool _);
}
public static void Inspect(Type type)
{
WindowManager.InspectStaticReflection(type);
}
public static void Help()
{
ExplorerCore.Log("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
ExplorerCore.Log(" C# Console Help ");
ExplorerCore.Log("");
ExplorerCore.Log("The following helper methods are available:");
ExplorerCore.Log("");
ExplorerCore.Log("void Log(object message)");
ExplorerCore.Log(" prints a message to the console window and debug log");
ExplorerCore.Log(" usage: Log(\"hello world\");");
ExplorerCore.Log("");
ExplorerCore.Log("object CurrentTarget()");
ExplorerCore.Log(" returns the target object of the current tab (in tab view mode only)");
ExplorerCore.Log(" usage: var target = CurrentTarget();");
ExplorerCore.Log("");
ExplorerCore.Log("object[] AllTargets()");
ExplorerCore.Log(" returns an object[] array containing all currently inspected objects");
ExplorerCore.Log(" usage: var targets = AllTargets();");
ExplorerCore.Log("");
ExplorerCore.Log("void Inspect(object obj)");
ExplorerCore.Log(" inspects the provided object in a new window.");
ExplorerCore.Log(" usage: Inspect(Camera.main);");
ExplorerCore.Log("");
ExplorerCore.Log("void Inspect(Type type)");
ExplorerCore.Log(" attempts to inspect the provided type with static-only reflection.");
ExplorerCore.Log(" usage: Inspect(typeof(Camera));");
}
}
}

View File

@ -1,371 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using Mono.CSharp;
using System.Reflection;
using System.IO;
#if CPP
using UnhollowerRuntimeLib;
using TextEditor = Explorer.Unstrip.IMGUI.TextEditorUnstrip;
using Explorer.Unstrip.IMGUI;
#endif
namespace Explorer.UI.Main
{
public class ConsolePage : BaseMainMenuPage
{
public static ConsolePage Instance { get; private set; }
public override string Name { get => "C# Console"; }
private ScriptEvaluator m_evaluator;
public const string INPUT_CONTROL_NAME = "consoleInput";
private string m_input = "";
private string m_prevInput = "";
private string m_usingInput = "";
public static List<AutoComplete> AutoCompletes = new List<AutoComplete>();
public static List<string> UsingDirectives;
private Vector2 inputAreaScroll;
private Vector2 autocompleteScroll;
public static TextEditor textEditor;
private bool shouldRefocus;
public static GUIStyle AutocompleteStyle => autocompleteStyle ?? GetAutocompleteStyle();
private static GUIStyle autocompleteStyle;
public static readonly string[] DefaultUsing = new string[]
{
"System",
"UnityEngine",
"System.Linq",
"System.Collections",
"System.Collections.Generic",
"System.Reflection"
};
public override void Init()
{
Instance = this;
try
{
m_input = @"// For a list of helper methods, execute the 'Help();' method.
// Enable the Console Window with your Mod Loader to see log output.
Help();";
ResetConsole();
foreach (var use in DefaultUsing)
{
AddUsing(use);
}
}
catch (Exception e)
{
ExplorerCore.LogWarning($"Error setting up console!\r\nMessage: {e.Message}");
MainMenu.SetCurrentPage(0);
MainMenu.Pages.Remove(this);
}
}
public override void Update() { }
public string AsmToUsing(string asm, bool richtext = false)
{
if (richtext)
{
return $"<color=#569cd6>using</color> {asm};";
}
return $"using {asm};";
}
public void AddUsing(string asm)
{
if (!UsingDirectives.Contains(asm))
{
UsingDirectives.Add(asm);
Evaluate(AsmToUsing(asm), true);
}
}
public object Evaluate(string str, bool suppressWarning = false)
{
object ret = VoidType.Value;
m_evaluator.Compile(str, out var compiled);
try
{
if (compiled == null)
{
throw new Exception("Mono.Csharp Service was unable to compile the code provided.");
}
compiled.Invoke(ref ret);
}
catch (Exception e)
{
if (!suppressWarning)
{
ExplorerCore.LogWarning(e.GetType() + ", " + e.Message);
}
}
return ret;
}
public void ResetConsole()
{
if (m_evaluator != null)
{
m_evaluator.Dispose();
}
m_evaluator = new ScriptEvaluator(new StringWriter(new StringBuilder())) { InteractiveBaseClass = typeof(ScriptInteraction) };
UsingDirectives = new List<string>();
}
public override void DrawWindow()
{
GUILayout.Label("<b><size=15><color=cyan>C# Console</color></size></b>", new GUILayoutOption[0]);
GUI.skin.label.alignment = TextAnchor.UpperLeft;
// SCRIPT INPUT
GUILayout.Label("Enter code here as though it is a method body:", new GUILayoutOption[0]);
inputAreaScroll = GUIHelper.BeginScrollView(
inputAreaScroll,
new GUILayoutOption[] { GUILayout.Height(250), GUIHelper.ExpandHeight(true) }
);
GUI.SetNextControlName(INPUT_CONTROL_NAME);
m_input = GUIHelper.TextArea(m_input, new GUILayoutOption[] { GUIHelper.ExpandHeight(true) });
GUIHelper.EndScrollView();
// EXECUTE BUTTON
if (GUILayout.Button("<color=cyan><b>Execute</b></color>", new GUILayoutOption[0]))
{
try
{
m_input = m_input.Trim();
if (!string.IsNullOrEmpty(m_input))
{
Evaluate(m_input);
//var result = Evaluate(m_input);
//if (result != null && !Equals(result, VoidType.Value))
//{
// ExplorerCore.Log("[Console Output]\r\n" + result.ToString());
//}
}
}
catch (Exception e)
{
ExplorerCore.LogError("Exception compiling!\r\nMessage: " + e.Message + "\r\nStack: " + e.StackTrace);
}
}
// SUGGESTIONS
if (AutoCompletes.Count > 0)
{
autocompleteScroll = GUIHelper.BeginScrollView(autocompleteScroll, new GUILayoutOption[] { GUILayout.Height(150) });
var origSkin = GUI.skin.button;
GUI.skin.button = AutocompleteStyle;
foreach (var autocomplete in AutoCompletes)
{
AutocompleteStyle.normal.textColor = autocomplete.TextColor;
if (GUILayout.Button(autocomplete.Full, new GUILayoutOption[] { GUILayout.Width(MainMenu.MainRect.width - 50) }))
{
UseAutocomplete(autocomplete.Addition);
break;
}
}
GUI.skin.button = origSkin;
GUIHelper.EndScrollView();
}
if (shouldRefocus)
{
GUI.FocusControl(INPUT_CONTROL_NAME);
shouldRefocus = false;
}
// USING DIRECTIVES
GUILayout.Label("<b>Using directives:</b>", new GUILayoutOption[0]);
GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUILayout.Label("Add namespace:", new GUILayoutOption[] { GUILayout.Width(105) });
m_usingInput = GUIHelper.TextField(m_usingInput, new GUILayoutOption[] { GUILayout.Width(150) });
if (GUILayout.Button("<b><color=lime>Add</color></b>", new GUILayoutOption[] { GUILayout.Width(120) }))
{
AddUsing(m_usingInput);
}
if (GUILayout.Button("<b><color=red>Clear All</color></b>", new GUILayoutOption[] { GUILayout.Width(120) }))
{
ResetConsole();
}
GUILayout.EndHorizontal();
foreach (var asm in UsingDirectives)
{
GUILayout.Label(AsmToUsing(asm, true), new GUILayoutOption[0]);
}
CheckAutocomplete();
}
private void CheckAutocomplete()
{
// Temporary disabling this check in BepInEx Il2Cpp.
#if BIE
#if CPP
#else
if (GUI.GetNameOfFocusedControl() != INPUT_CONTROL_NAME)
return;
#endif
#else
if (GUI.GetNameOfFocusedControl() != INPUT_CONTROL_NAME)
return;
#endif
#if CPP
//textEditor = GUIUtility.GetStateObject(Il2CppType.Of<TextEditor>(), GUIUtility.keyboardControl).TryCast<TextEditor>();
textEditor = (TextEditor)GUIUtilityUnstrip.GetMonoStateObject(typeof(TextEditor), GUIUtility.keyboardControl);
#else
textEditor = (TextEditor)GUIUtility.GetStateObject(typeof(TextEditor), GUIUtility.keyboardControl);
#endif
var input = m_input;
if (!string.IsNullOrEmpty(input))
{
try
{
var splitChars = new[] { ',', ';', '<', '>', '(', ')', '[', ']', '=', '|', '&' };
// Credit ManlyMarco
// Separate input into parts, grab only the part with cursor in it
var cursorIndex = textEditor.cursorIndex;
var start = cursorIndex <= 0 ? 0 : input.LastIndexOfAny(splitChars, cursorIndex - 1) + 1;
var end = cursorIndex <= 0 ? input.Length : input.IndexOfAny(splitChars, cursorIndex - 1);
if (end < 0 || end < start) end = input.Length;
input = input.Substring(start, end - start);
}
catch (ArgumentException) { }
if (!string.IsNullOrEmpty(input) && input != m_prevInput)
{
GetAutocompletes(input);
}
}
else
{
ClearAutocompletes();
}
m_prevInput = input;
}
private void ClearAutocompletes()
{
if (AutoCompletes.Any())
{
AutoCompletes.Clear();
shouldRefocus = true;
}
}
private void UseAutocomplete(string suggestion)
{
int cursorIndex = textEditor.cursorIndex;
m_input = m_input.Insert(cursorIndex, suggestion);
ClearAutocompletes();
shouldRefocus = true;
}
private void GetAutocompletes(string input)
{
try
{
//ExplorerCore.Log("Fetching suggestions for input " + input);
// Credit ManylMarco
AutoCompletes.Clear();
var completions = m_evaluator.GetCompletions(input, out string prefix);
if (completions != null)
{
if (prefix == null)
prefix = input;
AutoCompletes.AddRange(completions
.Where(x => !string.IsNullOrEmpty(x))
.Select(x => new AutoComplete(x, prefix, AutoComplete.Contexts.Other))
);
}
var trimmed = input.Trim();
if (trimmed.StartsWith("using"))
trimmed = trimmed.Remove(0, 5).Trim();
var namespaces = AutoCompleteHelpers.Namespaces
.Where(x => x.StartsWith(trimmed) && x.Length > trimmed.Length)
.Select(x => new AutoComplete(
x.Substring(trimmed.Length),
x.Substring(0, trimmed.Length),
AutoComplete.Contexts.Namespace));
AutoCompletes.AddRange(namespaces);
shouldRefocus = true;
}
catch (Exception ex)
{
ExplorerCore.Log("C# Console error:\r\n" + ex);
ClearAutocompletes();
}
}
// Credit ManlyMarco
private static GUIStyle GetAutocompleteStyle()
{
var style = new GUIStyle
{
border = new RectOffset(),
margin = new RectOffset(),
padding = new RectOffset(),
hover = { background = Texture2D.whiteTexture, textColor = Color.black },
normal = { background = null },
focused = { background = Texture2D.whiteTexture, textColor = Color.black },
active = { background = Texture2D.whiteTexture, textColor = Color.black },
alignment = TextAnchor.MiddleLeft
};
return autocompleteStyle = style;
}
private class VoidType
{
public static readonly VoidType Value = new VoidType();
private VoidType() { }
}
}
}

180
src/UI/Main/MainMenu.cs Normal file
View File

@ -0,0 +1,180 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ExplorerBeta.UI;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
using ExplorerBeta.UI.Shared;
namespace ExplorerBeta.UI.Main
{
// TODO REMAKE THIS
public class MainMenu
{
public static MainMenu Instance { get; set; }
public PanelDragger Dragger { get; private set; }
public GameObject MainPanel { get; private set; }
public MainMenu()
{
if (Instance != null)
{
ExplorerCore.LogWarning("An instance of MainMenu already exists, cannot create another!");
return;
}
Instance = this;
MainPanel = CreateBasePanel("MainMenu");
CreateTitleBar();
CreateNavbar();
CreateViewArea();
}
public void Update()
{
}
private void TestButtonCallback()
{
//if (EventSystem.current != EventSys)
// return;
var go = EventSystem.current.currentSelectedGameObject;
if (!go)
return;
var name = go.name;
if (go.GetComponentInChildren<Text>() is Text text)
{
name = text.text;
}
ExplorerCore.Log($"{Time.time} | Pressed {name ?? "null"}");
if (name == "X")
{
ExplorerCore.ShowMenu = false;
}
}
#region UI Generator
public virtual GameObject CreateBasePanel(string name)
{
var basePanel = UIFactory.CreatePanel(UIManager.CanvasRoot.gameObject, name);
var panelRect = basePanel.GetComponent<RectTransform>();
panelRect.anchorMin = new Vector2(0.327f, 0.0967f);
panelRect.anchorMax = new Vector2(0.672f, 0.904f);
panelRect.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, 620f);
panelRect.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, 800f);
return basePanel;
}
private void CreateTitleBar()
{
// Make the horizontal group for window title area
var titleGroup = UIFactory.CreateHorizontalGroup(MainPanel);
var titleRect = titleGroup.GetComponent<RectTransform>();
titleRect.anchorMin = new Vector2(0.005f, 0.96f);
titleRect.anchorMax = new Vector2(0.995f, 0.994f);
titleRect.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, 613);
titleRect.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, 30);
var group = titleGroup.GetComponent<HorizontalLayoutGroup>();
group.childControlWidth = true;
//group.childScaleWidth = true;
group.childForceExpandHeight = true;
group.childForceExpandWidth = true;
// Create window title
var titleLabel = UIFactory.CreateLabel(titleGroup, TextAnchor.MiddleCenter);
var labelText = titleLabel.GetComponent<Text>();
labelText.text = ExplorerCore.NAME;
labelText.fontSize = 15;
var labelRect = labelText.GetComponent<RectTransform>();
labelRect.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, 575);
labelRect.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, 25);
// Add drag handler (on Title label)
Dragger = new PanelDragger(titleLabel.transform.TryCast<RectTransform>(),
MainPanel.GetComponent<RectTransform>());
// Create X Button
var exitBtnObj = UIFactory.CreateButton(titleGroup);
var exitBtn = exitBtnObj.GetComponentInChildren<Button>();
exitBtn.onClick.AddListener(new Action(TestButtonCallback));
var exitBtnText = exitBtnObj.GetComponentInChildren<Text>();
exitBtnText.text = "X";
exitBtnText.fontSize = 14;
var exitBtnRect = exitBtnObj.GetComponent<RectTransform>();
exitBtnRect.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, 40f);
exitBtnRect.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, 25f);
}
private void CreateNavbar()
{
// Make the horizontal group for the nav bar
var navArea = UIFactory.CreateHorizontalGroup(MainPanel);
var group = navArea.GetComponent<HorizontalLayoutGroup>();
group.childAlignment = TextAnchor.MiddleLeft;
group.spacing = 5;
group.childForceExpandWidth = true;
group.childForceExpandHeight = true;
group.childControlWidth = true;
group.spacing = 5;
var padding = new RectOffset();
padding.left = 5;
padding.right = 5;
padding.top = 3;
padding.bottom = 3;
group.padding = padding;
var navRect = navArea.GetComponent<RectTransform>();
navRect.anchorMin = new Vector2(0.005f, 0.93f);
navRect.anchorMax = new Vector2(0.995f, 0.97f);
var pos = navRect.localPosition;
pos.y = 348;
navRect.localPosition = pos;
navRect.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, 613);
navRect.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, 30);
// Add the buttons for pages (this should be done programmatically)
var names = new string[] { "Scenes", "Search", "C# Console", "Options" };
for (int i = 0; i < names.Length; i++)
{
var btn = UIFactory.CreateButton(navArea);
var text = btn.GetComponentInChildren<Text>();
text.text = names[i];
btn.GetComponent<Button>().onClick.AddListener(new Action(TestButtonCallback));
if (i == 0)
{
var image = btn.GetComponentInChildren<Image>();
image.color = new Color(0.1f, 0.35f, 0.1f);
}
}
}
private void CreateViewArea()
{
// Make the vertical group for the viewport
var viewGroup = UIFactory.CreateVerticalGroup(MainPanel);
var viewRect = viewGroup.GetComponent<RectTransform>();
viewRect.anchorMin = new Vector2(0.005f, -0.038f);
viewRect.anchorMax = new Vector2(0.995f, 0.954f);
viewRect.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, 613);
viewRect.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, 720f);
viewRect.localPosition = new Vector3(0, -35f, 0);
}
#endregion
}
}

View File

@ -1,145 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using Explorer.UI.Shared;
using Explorer.Config;
using Explorer.CacheObject;
namespace Explorer.UI.Main
{
public class OptionsPage : BaseMainMenuPage
{
public override string Name => "Options";
public string toggleKeyInputString = "";
public Vector2 defaultSizeInputVector;
public int defaultPageLimit;
public bool bitwiseSupport;
public bool tabView;
public string defaultOutputPath;
private CacheObjectBase toggleKeyInput;
private CacheObjectBase defaultSizeInput;
private CacheObjectBase defaultPageLimitInput;
private CacheObjectBase bitwiseSupportInput;
private CacheObjectBase tabViewInput;
private CacheObjectBase defaultOutputPathInput;
public override void Init()
{
toggleKeyInputString = ModConfig.Instance.Main_Menu_Toggle.ToString();
toggleKeyInput = CacheFactory.GetCacheObject(typeof(OptionsPage).GetField("toggleKeyInputString"), this);
defaultSizeInputVector = ModConfig.Instance.Default_Window_Size;
defaultSizeInput = CacheFactory.GetCacheObject(typeof(OptionsPage).GetField("defaultSizeInputVector"), this);
defaultPageLimit = ModConfig.Instance.Default_Page_Limit;
defaultPageLimitInput = CacheFactory.GetCacheObject(typeof(OptionsPage).GetField("defaultPageLimit"), this);
bitwiseSupport = ModConfig.Instance.Bitwise_Support;
bitwiseSupportInput = CacheFactory.GetCacheObject(typeof(OptionsPage).GetField("bitwiseSupport"), this);
tabView = ModConfig.Instance.Tab_View;
tabViewInput = CacheFactory.GetCacheObject(typeof(OptionsPage).GetField("tabView"), this);
defaultOutputPath = ModConfig.Instance.Default_Output_Path;
defaultOutputPathInput = CacheFactory.GetCacheObject(typeof(OptionsPage).GetField("defaultOutputPath"), this);
}
public override void Update() { }
public override void DrawWindow()
{
GUI.skin.label.alignment = TextAnchor.MiddleCenter;
GUILayout.Label("<color=orange><size=16><b>Options</b></size></color>", new GUILayoutOption[0]);
GUI.skin.label.alignment = TextAnchor.MiddleLeft;
GUIHelper.BeginVertical(GUIContent.none, GUI.skin.box, new GUILayoutOption[0]);
GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUILayout.Label($"Menu Toggle Key:", new GUILayoutOption[] { GUILayout.Width(215f) });
toggleKeyInput.IValue.DrawValue(MainMenu.MainRect, MainMenu.MainRect.width - 215f);
GUILayout.EndHorizontal();
UIStyles.HorizontalLine(Color.black, true);
GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUILayout.Label($"Default Window Size:", new GUILayoutOption[] { GUILayout.Width(215f) });
defaultSizeInput.IValue.DrawValue(MainMenu.MainRect, MainMenu.MainRect.width - 215f);
GUILayout.EndHorizontal();
UIStyles.HorizontalLine(Color.black, true);
GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUILayout.Label($"Default Items per Page:", new GUILayoutOption[] { GUILayout.Width(215f) });
defaultPageLimitInput.IValue.DrawValue(MainMenu.MainRect, MainMenu.MainRect.width - 215f);
GUILayout.EndHorizontal();
UIStyles.HorizontalLine(Color.black, true);
GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUILayout.Label($"Enable Bitwise Editing:", new GUILayoutOption[] { GUILayout.Width(215f) });
bitwiseSupportInput.IValue.DrawValue(MainMenu.MainRect, MainMenu.MainRect.width - 215f);
GUILayout.EndHorizontal();
UIStyles.HorizontalLine(Color.black, true);
GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUILayout.Label($"Enable Tab View:", new GUILayoutOption[] { GUILayout.Width(215f) });
tabViewInput.IValue.DrawValue(MainMenu.MainRect, MainMenu.MainRect.width - 215f);
GUILayout.EndHorizontal();
UIStyles.HorizontalLine(Color.black, true);
GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUILayout.Label($"Default Output Path:", new GUILayoutOption[] { GUILayout.Width(215f) });
defaultOutputPathInput.IValue.DrawValue(MainMenu.MainRect, MainMenu.MainRect.width - 215f);
GUILayout.EndHorizontal();
if (GUILayout.Button("<color=lime><b>Apply and Save</b></color>", new GUILayoutOption[0]))
{
ApplyAndSave();
}
GUILayout.EndVertical();
GUIHelper.Space(10f);
GUI.skin.label.alignment = TextAnchor.MiddleCenter;
GUILayout.Label("<color=orange><size=16><b>Other</b></size></color>", new GUILayoutOption[0]);
GUI.skin.label.alignment = TextAnchor.MiddleLeft;
GUIHelper.BeginVertical(GUIContent.none, GUI.skin.box, new GUILayoutOption[0]);
if (GUILayout.Button("Inspect Test Class", new GUILayoutOption[0]))
{
WindowManager.InspectObject(Tests.TestClass.Instance, out bool _);
}
GUILayout.EndVertical();
}
private void ApplyAndSave()
{
if (Enum.Parse(typeof(KeyCode), toggleKeyInputString) is KeyCode key)
{
ModConfig.Instance.Main_Menu_Toggle = key;
}
else
{
ExplorerCore.LogWarning($"Could not parse '{toggleKeyInputString}' to KeyCode!");
}
ModConfig.Instance.Default_Window_Size = defaultSizeInputVector;
ModConfig.Instance.Default_Page_Limit = defaultPageLimit;
ModConfig.Instance.Bitwise_Support = bitwiseSupport;
ModConfig.Instance.Tab_View = tabView;
WindowManager.TabView = tabView;
ModConfig.SaveSettings();
}
}
}

390
src/UI/Main/PanelDragger.cs Normal file
View File

@ -0,0 +1,390 @@
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
using ExplorerBeta.Input;
using ExplorerBeta.Helpers;
using ExplorerBeta.Unstrip.ImageConversion;
using System.IO;
using System.Linq;
namespace ExplorerBeta.UI
{
// Handles dragging and resizing for the main explorer window.
public class PanelDragger
{
public static PanelDragger Instance { get; private set; }
public RectTransform Panel { get; set; }
public PanelDragger(RectTransform dragArea, RectTransform panelToDrag)
{
Instance = this;
DragableArea = dragArea;
Panel = panelToDrag;
UpdateResizeCache();
try
{
var path = @"Mods\Explorer\cursor.png";
var data = File.ReadAllBytes(path);
var tex = new Texture2D(32, 32);
tex.LoadImage(data, false);
UnityEngine.Object.DontDestroyOnLoad(tex);
var size = new Rect();
size.width = 32;
size.height = 32;
var sprite = UIManager.CreateSprite(tex, size);
UnityEngine.Object.DontDestroyOnLoad(sprite);
m_resizeCursorImage = new GameObject("ResizeCursorImage");
m_resizeCursorImage.transform.SetParent(UIManager.CanvasRoot.transform);
var image = m_resizeCursorImage.AddComponent<Image>();
image.sprite = sprite;
var rect = image.transform.TryCast<RectTransform>();
rect.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, 32);
rect.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, 32);
m_resizeCursorImage.SetActive(false);
}
catch (Exception e)
{
ExplorerCore.Log("Exception loading resize cursor: " + e.ToString());
}
}
public void Update()
{
var rawMousePos = InputManager.MousePosition;
var resizePos = Panel.InverseTransformPoint(rawMousePos);
var dragPos = DragableArea.InverseTransformPoint(rawMousePos);
if (m_wasHoveringResize)
{
UpdateHoverImagePos();
}
// If Mouse pressed this frame
if (InputManager.GetMouseButtonDown(0))
{
if (DragableArea.rect.Contains(dragPos))
{
OnBeginDrag();
return;
}
else if (MouseInResizeArea(resizePos))
{
var type = GetResizeType(resizePos);
OnBeginResize(type);
}
}
// If mouse still pressed from last frame
else if (InputManager.GetMouseButton(0))
{
if (WasDragging)
{
OnDrag();
}
else if (WasResizing)
{
OnResize();
}
}
// If mouse not pressed
else
{
if (WasDragging)
{
OnEndDrag();
}
else if (WasResizing)
{
OnEndResize();
}
else if (MouseInResizeArea(resizePos))
{
var type = GetResizeType(resizePos);
OnHoverResize(type);
}
else if (m_wasHoveringResize)
{
OnHoverResizeEnd();
}
}
return;
}
#region DRAGGING
public RectTransform DragableArea { get; set; }
public bool WasDragging { get; set; }
private Vector3 m_lastDragPosition;
public void OnBeginDrag()
{
WasDragging = true;
m_lastDragPosition = InputManager.MousePosition;
}
public void OnDrag()
{
var diff = InputManager.MousePosition - m_lastDragPosition;
m_lastDragPosition = InputManager.MousePosition;
var pos = Panel.localPosition;
var z = pos.z;
pos += diff;
pos.z = z;
Panel.localPosition = pos;
}
public void OnEndDrag()
{
WasDragging = false;
UpdateResizeCache();
}
#endregion
#region RESIZE
private const int RESIZE_THICKNESS = 10;
private bool WasResizing { get; set; }
private ResizeTypes m_currentResizeType = ResizeTypes.NONE;
private Vector2 m_lastMousePos;
private bool m_wasHoveringResize;
private ResizeTypes m_lastResizeHoverType;
private GameObject m_resizeCursorImage;
private Rect m_outerResize;
private Rect m_innerResize;
private readonly Dictionary<ResizeTypes, Rect> m_cachedResizeAreas = new Dictionary<ResizeTypes, Rect>
{
{ ResizeTypes.Top, Rect.zero },
{ ResizeTypes.Left, Rect.zero },
{ ResizeTypes.Right, Rect.zero },
{ ResizeTypes.Bottom, Rect.zero },
{ ResizeTypes.TopLeft, Rect.zero },
{ ResizeTypes.TopRight, Rect.zero },
{ ResizeTypes.BottomLeft, Rect.zero },
{ ResizeTypes.BottomRight, Rect.zero },
};
[Flags]
public enum ResizeTypes
{
NONE = 0,
Top = 1,
Left = 2,
Right = 4,
Bottom = 8,
TopLeft = Top | Left,
TopRight = Top | Right,
BottomLeft = Bottom | Left,
BottomRight = Bottom | Right,
}
private void UpdateHoverImagePos()
{
if (!m_resizeCursorImage)
return;
m_resizeCursorImage.transform.localPosition = UIManager.CanvasRoot.transform.TryCast<RectTransform>()
.InverseTransformPoint(InputManager.MousePosition);
}
private void UpdateResizeCache()
{
int halfThick = RESIZE_THICKNESS / 2;
// calculate main two rects
this.m_outerResize = new Rect();
m_outerResize.x = Panel.rect.x - halfThick;
m_outerResize.y = Panel.rect.y - halfThick;
m_outerResize.width = Panel.rect.width + (RESIZE_THICKNESS * 2);
m_outerResize.height = Panel.rect.height + (RESIZE_THICKNESS * 2);
this.m_innerResize = new Rect();
m_innerResize.x = m_outerResize.x + RESIZE_THICKNESS;
m_innerResize.y = m_outerResize.y + RESIZE_THICKNESS;
m_innerResize.width = Panel.rect.width - RESIZE_THICKNESS;
m_innerResize.height = Panel.rect.height - RESIZE_THICKNESS;
// calculate resize areas
var left = m_cachedResizeAreas[ResizeTypes.Left];
left.x = m_outerResize.x;
left.y = m_outerResize.y + RESIZE_THICKNESS;
left.width = RESIZE_THICKNESS;
left.height = m_innerResize.height - RESIZE_THICKNESS;
m_cachedResizeAreas[ResizeTypes.Left] = left;
var topLeft = m_cachedResizeAreas[ResizeTypes.TopLeft];
topLeft.x = m_outerResize.x;
topLeft.y = m_innerResize.y + m_innerResize.height;
topLeft.width = RESIZE_THICKNESS;
topLeft.height = RESIZE_THICKNESS;
m_cachedResizeAreas[ResizeTypes.TopLeft] = topLeft;
var top = m_cachedResizeAreas[ResizeTypes.Top];
top.x = m_innerResize.x;
top.y = m_innerResize.y + m_innerResize.height;
top.width = m_innerResize.width;
top.height = RESIZE_THICKNESS;
m_cachedResizeAreas[ResizeTypes.Top] = top;
var topRight = m_cachedResizeAreas[ResizeTypes.TopRight];
topRight.x = m_innerResize.x + m_innerResize.width;
topRight.y = m_innerResize.y + m_innerResize.height;
topRight.width = RESIZE_THICKNESS;
topRight.height = RESIZE_THICKNESS;
m_cachedResizeAreas[ResizeTypes.TopRight] = topRight;
var right = m_cachedResizeAreas[ResizeTypes.Right];
right.x = m_innerResize.x + m_innerResize.width;
right.y = m_innerResize.y + halfThick;
right.width = RESIZE_THICKNESS;
right.height = m_innerResize.height - RESIZE_THICKNESS;
m_cachedResizeAreas[ResizeTypes.Right] = right;
var bottomRight = m_cachedResizeAreas[ResizeTypes.BottomRight];
bottomRight.x = m_innerResize.x + m_innerResize.width;
bottomRight.y = m_outerResize.y;
bottomRight.width = RESIZE_THICKNESS;
bottomRight.height = RESIZE_THICKNESS;
m_cachedResizeAreas[ResizeTypes.BottomRight] = bottomRight;
var bottom = m_cachedResizeAreas[ResizeTypes.Bottom];
bottom.x = m_innerResize.x;
bottom.y = m_outerResize.y;
bottom.width = m_innerResize.width;
bottom.height = RESIZE_THICKNESS;
m_cachedResizeAreas[ResizeTypes.Bottom] = bottom;
var bottomLeft = m_cachedResizeAreas[ResizeTypes.BottomLeft];
bottomLeft.x = m_outerResize.x;
bottomLeft.y = m_outerResize.y;
bottomLeft.width = RESIZE_THICKNESS;
bottomLeft.height = RESIZE_THICKNESS;
m_cachedResizeAreas[ResizeTypes.BottomLeft] = bottomLeft;
}
private bool MouseInResizeArea(Vector2 mousePos)
{
return m_outerResize.Contains(mousePos) && !m_innerResize.Contains(mousePos);
}
private ResizeTypes GetResizeType(Vector2 mousePos)
{
foreach (var entry in m_cachedResizeAreas)
{
if (entry.Value.Contains(mousePos))
{
return entry.Key;
}
}
return ResizeTypes.NONE;
}
public void OnHoverResize(ResizeTypes resizeType)
{
if (m_wasHoveringResize && m_lastResizeHoverType == resizeType)
return;
// we are entering resize, or the resize type has changed.
m_wasHoveringResize = true;
m_lastResizeHoverType = resizeType;
m_resizeCursorImage.SetActive(true);
float rotation = 0;
switch (resizeType)
{
case ResizeTypes.TopRight:
case ResizeTypes.BottomLeft:
rotation = 45f; break;
case ResizeTypes.Top:
case ResizeTypes.Bottom:
rotation = 90f; break;
case ResizeTypes.TopLeft:
case ResizeTypes.BottomRight:
rotation = 135f; break;
}
var rot = m_resizeCursorImage.transform.rotation;
rot.eulerAngles = new Vector3(0, 0, rotation);
m_resizeCursorImage.transform.rotation = rot;
UpdateHoverImagePos();
}
public void OnHoverResizeEnd()
{
m_wasHoveringResize = false;
m_resizeCursorImage.SetActive(false);
}
public void OnBeginResize(ResizeTypes resizeType)
{
m_currentResizeType = resizeType;
m_lastMousePos = InputManager.MousePosition;
WasResizing = true;
}
public void OnResize()
{
var mousePos = InputManager.MousePosition;
var diff = m_lastMousePos - (Vector2)mousePos;
m_lastMousePos = mousePos;
var diffX = (float)((decimal)diff.x / Screen.width);
var diffY = (float)((decimal)diff.y / Screen.height);
if (m_currentResizeType.HasFlag(ResizeTypes.Left))
{
var anch = Panel.anchorMin;
anch.x -= diffX;
Panel.anchorMin = anch;
}
else if (m_currentResizeType.HasFlag(ResizeTypes.Right))
{
var anch = Panel.anchorMax;
anch.x -= diffX;
Panel.anchorMax = anch;
}
if (m_currentResizeType.HasFlag(ResizeTypes.Top))
{
var anch = Panel.anchorMax;
anch.y -= diffY;
Panel.anchorMax = anch;
}
else if (m_currentResizeType.HasFlag(ResizeTypes.Bottom))
{
var anch = Panel.anchorMin;
anch.y -= diffY;
Panel.anchorMin = anch;
}
}
public void OnEndResize()
{
WasResizing = false;
UpdateResizeCache();
}
#endregion
}
}

View File

@ -1,374 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.SceneManagement;
using Explorer.UI.Shared;
using Explorer.CacheObject;
using Explorer.Helpers;
using Explorer.Unstrip.Resources;
namespace Explorer.UI.Main
{
public class ScenePage : BaseMainMenuPage
{
public static ScenePage Instance;
public override string Name { get => "Scenes"; }
public PageHelper Pages = new PageHelper();
private float m_timeOfLastUpdate = -1f;
private const int PASSIVE_UPDATE_INTERVAL = 1;
private static string m_currentScene = "";
// gameobject list
private Transform m_currentTransform;
private readonly List<CacheObjectBase> m_objectList = new List<CacheObjectBase>();
// search bar
private bool m_searching = false;
private string m_searchInput = "";
private List<CacheObjectBase> m_searchResults = new List<CacheObjectBase>();
public override void Init()
{
Instance = this;
}
public void OnSceneChange()
{
m_currentScene = UnityHelpers.ActiveSceneName;
SetTransformTarget(null);
}
public void SetTransformTarget(Transform t)
{
m_currentTransform = t;
if (m_searching)
CancelSearch();
Update_Impl();
}
public void TraverseUp()
{
if (m_currentTransform.parent != null)
{
SetTransformTarget(m_currentTransform.parent);
}
else
{
SetTransformTarget(null);
}
}
public void Search()
{
m_searchResults = SearchSceneObjects(m_searchInput);
m_searching = true;
Pages.ItemCount = m_searchResults.Count;
}
public void CancelSearch()
{
m_searching = false;
}
public List<CacheObjectBase> SearchSceneObjects(string _search)
{
var matches = new List<CacheObjectBase>();
foreach (var obj in ResourcesUnstrip.FindObjectsOfTypeAll(ReflectionHelpers.GameObjectType))
{
#if CPP
var go = obj.TryCast<GameObject>();
#else
var go = obj as GameObject;
#endif
if (go.name.ToLower().Contains(_search.ToLower()) && go.scene.name == m_currentScene)
{
matches.Add(CacheFactory.GetCacheObject(go));
}
}
return matches;
}
public override void Update()
{
if (m_searching) return;
if (Time.time - m_timeOfLastUpdate < PASSIVE_UPDATE_INTERVAL) return;
m_timeOfLastUpdate = Time.time;
Update_Impl();
}
private void Update_Impl()
{
List<Transform> allTransforms = new List<Transform>();
// get current list of all transforms (either scene root or our current transform children)
if (m_currentTransform)
{
for (int i = 0; i < m_currentTransform.childCount; i++)
{
allTransforms.Add(m_currentTransform.GetChild(i));
}
}
else
{
for (int i = 0; i < SceneManager.sceneCount; i++)
{
var scene = SceneManager.GetSceneAt(i);
if (scene.name == m_currentScene)
{
var rootObjects =
#if CPP
Unstrip.Scenes.SceneUnstrip.GetRootGameObjects(scene)
.Select(it => it.transform);
#else
scene.GetRootGameObjects().Select(it => it.transform);
#endif
allTransforms.AddRange(rootObjects);
break;
}
}
}
Pages.ItemCount = allTransforms.Count;
int offset = Pages.CalculateOffsetIndex();
// sort by childcount
allTransforms.Sort((a, b) => b.childCount.CompareTo(a.childCount));
m_objectList.Clear();
for (int i = offset; i < offset + Pages.ItemsPerPage && i < Pages.ItemCount; i++)
{
var child = allTransforms[i];
m_objectList.Add(CacheFactory.GetCacheObject(child));
}
}
// --------- GUI Draw Function --------- //
public override void DrawWindow()
{
try
{
DrawHeaderArea();
GUIHelper.BeginVertical(GUIContent.none, GUI.skin.box, null);
DrawPageButtons();
if (!m_searching)
{
DrawGameObjectList();
}
else
{
DrawSearchResultsList();
}
GUILayout.EndVertical();
}
catch (Exception e)
{
if (!e.Message.Contains("in a group with only"))
{
ExplorerCore.Log(e.ToString());
}
}
}
private void DrawHeaderArea()
{
GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
// Current Scene label
GUILayout.Label("Current Scene:", new GUILayoutOption[] { GUILayout.Width(120) });
SceneChangeButtons();
GUILayout.Label("<color=cyan>" + m_currentScene + "</color>", new GUILayoutOption[0]);
GUILayout.EndHorizontal();
// ----- GameObject Search -----
GUIHelper.BeginHorizontal(GUIContent.none, GUI.skin.box, null);
GUILayout.Label("<b>Search Scene:</b>", new GUILayoutOption[] { GUILayout.Width(100) });
m_searchInput = GUIHelper.TextField(m_searchInput, new GUILayoutOption[0]);
if (GUILayout.Button("Search", new GUILayoutOption[] { GUILayout.Width(80) }))
{
Search();
}
GUILayout.EndHorizontal();
GUIHelper.Space(5);
}
private void SceneChangeButtons()
{
var scenes = new List<Scene>();
var names = new List<string>();
for (int i = 0; i < SceneManager.sceneCount; i++)
{
var scene = SceneManager.GetSceneAt(i);
names.Add(scene.name);
scenes.Add(scene);
}
if (scenes.Count > 1)
{
int changeWanted = 0;
if (GUILayout.Button("<", new GUILayoutOption[] { GUILayout.Width(30) }))
{
changeWanted = -1;
}
if (GUILayout.Button(">", new GUILayoutOption[] { GUILayout.Width(30) }))
{
changeWanted = 1;
}
if (changeWanted != 0)
{
int index = names.IndexOf(m_currentScene);
index += changeWanted;
if (index >= 0 && index < SceneManager.sceneCount)
{
m_currentScene = scenes[index].name;
Update_Impl();
}
}
}
}
private void DrawPageButtons()
{
GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
Pages.DrawLimitInputArea();
if (Pages.ItemCount > Pages.ItemsPerPage)
{
if (GUILayout.Button("< Prev", new GUILayoutOption[] { GUILayout.Width(80) }))
{
Pages.TurnPage(Turn.Left, ref this.scroll);
Update_Impl();
}
Pages.CurrentPageLabel();
if (GUILayout.Button("Next >", new GUILayoutOption[] { GUILayout.Width(80) }))
{
Pages.TurnPage(Turn.Right, ref this.scroll);
Update_Impl();
}
}
GUILayout.EndHorizontal();
GUI.skin.label.alignment = TextAnchor.UpperLeft;
}
private void DrawGameObjectList()
{
if (m_currentTransform != null)
{
GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
if (GUILayout.Button("<-", new GUILayoutOption[] { GUILayout.Width(35) }))
{
TraverseUp();
}
else
{
GUILayout.Label("<color=cyan>" + m_currentTransform.GetGameObjectPath() + "</color>",
new GUILayoutOption[] { GUILayout.Width(MainMenu.MainRect.width - 187f) });
}
Buttons.InspectButton(m_currentTransform);
GUILayout.EndHorizontal();
}
else
{
GUILayout.Label("Scene Root GameObjects:", new GUILayoutOption[0]);
}
if (m_objectList.Count > 0)
{
for (int i = 0; i < m_objectList.Count; i++)
{
var obj = m_objectList[i];
if (obj == null) continue;
try
{
var go = obj.IValue.Value as GameObject ?? (obj.IValue.Value as Transform)?.gameObject;
if (!go)
{
string label = "<color=red><i>null";
if (go != null)
{
label += " (Destroyed)";
}
label += "</i></color>";
GUILayout.Label(label, new GUILayoutOption[0]);
}
else
{
Buttons.GameObjectButton(go, SetTransformTarget, true, MainMenu.MainRect.width - 170f);
}
}
catch { }
}
}
}
private void DrawSearchResultsList()
{
if (GUILayout.Button("<- Cancel Search", new GUILayoutOption[] { GUILayout.Width(150) }))
{
CancelSearch();
}
GUILayout.Label("Search Results:", new GUILayoutOption[0]);
if (m_searchResults.Count > 0)
{
int offset = Pages.CalculateOffsetIndex();
for (int i = offset; i < offset + Pages.ItemsPerPage && i < m_searchResults.Count; i++)
{
var obj = m_searchResults[i].IValue.Value as GameObject;
if (obj)
{
Buttons.GameObjectButton(obj, SetTransformTarget, true, MainMenu.MainRect.width - 170);
}
else
{
GUILayout.Label("<i><color=red>Null or destroyed!</color></i>", new GUILayoutOption[0]);
}
}
}
else
{
GUILayout.Label("<color=red><i>No results found!</i></color>", new GUILayoutOption[0]);
}
}
}
}

View File

@ -1,544 +0,0 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using UnityEngine;
using Explorer.UI.Shared;
using Explorer.CacheObject;
using Explorer.Helpers;
using Explorer.Unstrip.Resources;
namespace Explorer.UI.Main
{
public class SearchPage : BaseMainMenuPage
{
public static SearchPage Instance;
public override string Name { get => "Search"; }
private int MaxSearchResults = 5000;
private string m_searchInput = "";
private string m_typeInput = "";
//private bool m_cachingResults;
private Vector2 resultsScroll = Vector2.zero;
public PageHelper Pages = new PageHelper();
private List<CacheObjectBase> m_searchResults = new List<CacheObjectBase>();
public SceneFilter SceneMode = SceneFilter.Any;
public TypeFilter TypeMode = TypeFilter.Object;
public enum SceneFilter
{
Any,
This,
DontDestroy,
None
}
public enum TypeFilter
{
Object,
GameObject,
Component,
Custom
}
public override void Init()
{
Instance = this;
}
public void OnSceneChange()
{
m_searchResults.Clear();
Pages.PageOffset = 0;
}
public override void Update() { }
private void CacheResults(IEnumerable results, bool isStaticClasses = false)
{
//m_cachingResults = true;
m_searchResults = new List<CacheObjectBase>();
foreach (var obj in results)
{
var toCache = obj;
#if CPP
if (toCache is Il2CppSystem.Object ilObject)
{
var type = ReflectionHelpers.GetActualType(ilObject);
ilObject = (Il2CppSystem.Object)ilObject.Il2CppCast(type);
toCache = ilObject.TryCast<GameObject>() ?? ilObject.TryCast<Transform>()?.gameObject ?? ilObject;
}
#else
if (toCache is GameObject || toCache is Transform)
{
toCache = toCache as GameObject ?? (toCache as Transform).gameObject;
}
#endif
if (toCache is TextAsset textAsset)
{
if (string.IsNullOrEmpty(textAsset.text))
{
continue;
}
}
var cache = CacheFactory.GetCacheObject(toCache);
cache.IsStaticClassSearchResult = isStaticClasses;
m_searchResults.Add(cache);
}
Pages.ItemCount = m_searchResults.Count;
Pages.PageOffset = 0;
results = null;
//m_cachingResults = false;
}
private void Search()
{
//if (m_cachingResults)
//{
// ExplorerCore.Log("Cannot search now, we are already caching results...");
// return;
//}
Pages.PageOffset = 0;
#if CPP
Il2CppSystem.Type searchType = null;
#else
Type searchType = null;
#endif
if (TypeMode == TypeFilter.Custom)
{
if (ReflectionHelpers.GetTypeByName(m_typeInput) is Type t)
{
#if CPP
searchType = Il2CppSystem.Type.GetType(t.AssemblyQualifiedName);
#else
searchType = t;
#endif
}
else
{
ExplorerCore.Log($"Could not find a Type by the name of '{m_typeInput}'!");
return;
}
}
else if (TypeMode == TypeFilter.Object)
{
searchType = ReflectionHelpers.ObjectType;
}
else if (TypeMode == TypeFilter.GameObject)
{
searchType = ReflectionHelpers.GameObjectType;
}
else if (TypeMode == TypeFilter.Component)
{
searchType = ReflectionHelpers.ComponentType;
}
if (!ReflectionHelpers.ObjectType.IsAssignableFrom(searchType))
{
if (searchType != null)
{
ExplorerCore.LogWarning("Your Custom Class Type must inherit from UnityEngine.Object!");
}
return;
}
var matches = new List<object>();
var allObjectsOfType = ResourcesUnstrip.FindObjectsOfTypeAll(searchType);
//ExplorerCore.Log("Found count: " + allObjectsOfType.Length);
int i = 0;
foreach (var obj in allObjectsOfType)
{
if (i >= MaxSearchResults) break;
if (m_searchInput != "" && !obj.name.ToLower().Contains(m_searchInput.ToLower()))
{
continue;
}
if (searchType.FullName == ReflectionHelpers.ComponentType.FullName
#if CPP
&& ReflectionHelpers.TransformType.IsAssignableFrom(obj.GetIl2CppType()))
#else
&& ReflectionHelpers.TransformType.IsAssignableFrom(obj.GetType()))
#endif
{
// Transforms shouldn't really be counted as Components, skip them.
// They're more akin to GameObjects.
continue;
}
if (SceneMode != SceneFilter.Any && !FilterScene(obj, this.SceneMode))
{
continue;
}
if (!matches.Contains(obj))
{
matches.Add(obj);
}
i++;
}
CacheResults(matches);
}
public static bool FilterScene(object obj, SceneFilter filter)
{
GameObject go = null;
#if CPP
if (obj is Il2CppSystem.Object ilObject)
{
go = ilObject.TryCast<GameObject>() ?? ilObject.TryCast<Component>().gameObject;
}
#else
if (obj is GameObject || obj is Component)
{
go = (obj as GameObject) ?? (obj as Component).gameObject;
}
#endif
if (!go)
{
// object is not on a GameObject, cannot perform scene filter operation.
return false;
}
if (filter == SceneFilter.None)
{
return string.IsNullOrEmpty(go.scene.name);
}
else if (filter == SceneFilter.This)
{
return go.scene.name == UnityHelpers.ActiveSceneName;
}
else if (filter == SceneFilter.DontDestroy)
{
return go.scene.name == "DontDestroyOnLoad";
}
return false;
}
private static bool FilterName(string name)
{
// Don't really want these instances.
return !name.StartsWith("Mono")
&& !name.StartsWith("System")
&& !name.StartsWith("Il2CppSystem")
&& !name.StartsWith("Iced");
}
// credit: ManlyMarco (RuntimeUnityEditor)
public static IEnumerable<object> GetStaticInstances()
{
var query = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(t => t.TryGetTypes())
.Where(t => t.IsClass && !t.IsAbstract && !t.ContainsGenericParameters);
var flags = BindingFlags.Public | BindingFlags.Static;
var flatFlags = flags | BindingFlags.FlattenHierarchy;
foreach (var type in query)
{
object obj = null;
try
{
var pi = type.GetProperty("Instance", flags);
if (pi == null)
{
pi = type.GetProperty("Instance", flatFlags);
}
if (pi != null)
{
obj = pi.GetValue(null, null);
}
else
{
var fi = type.GetField("Instance", flags);
if (fi == null)
{
fi = type.GetField("Instance", flatFlags);
}
if (fi != null)
{
obj = fi.GetValue(null);
}
}
}
catch { }
if (obj != null)
{
var t = ReflectionHelpers.GetActualType(obj);
if (!FilterName(t.FullName) || ReflectionHelpers.IsEnumerable(t))
{
continue;
}
yield return obj;
}
}
}
private IEnumerable GetStaticClasses()
{
var list = new List<Type>();
var input = m_searchInput?.ToLower() ?? "";
foreach (var asm in AppDomain.CurrentDomain.GetAssemblies())
{
try
{
foreach (var type in asm.TryGetTypes())
{
if (!type.IsAbstract || !type.IsSealed)
{
continue;
}
if (!string.IsNullOrEmpty(input))
{
var typename = type.FullName.ToLower();
if (!typename.Contains(input))
{
continue;
}
}
list.Add(type);
}
}
catch { }
}
return list;
}
// =========== GUI DRAW ============= //
public override void DrawWindow()
{
try
{
// helpers
GUIHelper.BeginHorizontal(GUIContent.none, GUI.skin.box, null);
GUILayout.Label("<b><color=orange>Helpers</color></b>", new GUILayoutOption[] { GUILayout.Width(70) });
if (GUILayout.Button("Find Static Instances", new GUILayoutOption[] { GUILayout.Width(180) }))
{
CacheResults(GetStaticInstances());
}
if (GUILayout.Button("Find Static Classes", new GUILayoutOption[] { GUILayout.Width(180) }))
{
CacheResults(GetStaticClasses(), true);
}
GUILayout.EndHorizontal();
// search box
SearchBox();
// results
GUIHelper.BeginVertical(GUIContent.none, GUI.skin.box, null);
GUI.skin.label.alignment = TextAnchor.MiddleCenter;
GUILayout.Label("<b><color=orange>Results </color></b>" + " (" + m_searchResults.Count + ")", new GUILayoutOption[0]);
GUI.skin.label.alignment = TextAnchor.UpperLeft;
int count = m_searchResults.Count;
GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
Pages.DrawLimitInputArea();
if (count > Pages.ItemsPerPage)
{
// prev/next page buttons
if (Pages.ItemCount > Pages.ItemsPerPage)
{
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 = GUIHelper.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 = Pages.CalculateOffsetIndex();
for (int i = offset; i < offset + Pages.ItemsPerPage && i < count; i++)
{
if (i >= m_searchResults.Count) break;
m_searchResults[i].Draw(MainMenu.MainRect, 0f);
}
}
else
{
GUILayout.Label("<color=red><i>No results found!</i></color>", new GUILayoutOption[0]);
}
GUIHelper.EndScrollView();
GUILayout.EndVertical();
}
catch (Exception e)
{
if (!e.Message.Contains("in a group with only"))
{
ExplorerCore.Log("Exception drawing search results!");
while (e != null)
{
ExplorerCore.Log(e);
e = e.InnerException;
}
m_searchResults.Clear();
}
}
}
private void SearchBox()
{
GUIHelper.BeginVertical(GUIContent.none, GUI.skin.box, null);
// ----- GameObject Search -----
GUI.skin.label.alignment = TextAnchor.MiddleCenter;
GUILayout.Label("<b><color=orange>Search</color></b>", new GUILayoutOption[0]);
GUI.skin.label.alignment = TextAnchor.UpperLeft;
GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUILayout.Label("Name Contains:", new GUILayoutOption[] { GUILayout.Width(100) });
m_searchInput = GUIHelper.TextField(m_searchInput, new GUILayoutOption[] { GUILayout.Width(200) });
GUILayout.Label("Max Results:", new GUILayoutOption[] { GUILayout.Width(100) });
var s = MaxSearchResults.ToString();
s = GUIHelper.TextField(s, new GUILayoutOption[] { GUILayout.Width(80) });
if (int.TryParse(s, out int i))
{
MaxSearchResults = i;
}
GUILayout.EndHorizontal();
GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUILayout.Label("Class Filter:", new GUILayoutOption[] { GUILayout.Width(100) });
ClassFilterToggle(TypeFilter.Object, "Object");
ClassFilterToggle(TypeFilter.GameObject, "GameObject");
ClassFilterToggle(TypeFilter.Component, "Component");
ClassFilterToggle(TypeFilter.Custom, "Custom");
GUILayout.EndHorizontal();
if (TypeMode == TypeFilter.Custom)
{
GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUI.skin.label.alignment = TextAnchor.MiddleRight;
GUILayout.Label("Custom Class:", new GUILayoutOption[] { GUILayout.Width(250) });
GUI.skin.label.alignment = TextAnchor.UpperLeft;
m_typeInput = GUIHelper.TextField(m_typeInput, new GUILayoutOption[] { GUILayout.Width(250) });
GUILayout.EndHorizontal();
}
GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUILayout.Label("Scene Filter:", new GUILayoutOption[] { GUILayout.Width(100) });
SceneFilterToggle(SceneFilter.Any, "Any", 60);
SceneFilterToggle(SceneFilter.This, "This Scene", 100);
SceneFilterToggle(SceneFilter.DontDestroy, "DontDestroyOnLoad", 140);
SceneFilterToggle(SceneFilter.None, "No Scene", 80);
GUILayout.EndHorizontal();
if (GUILayout.Button("<b><color=cyan>Search</color></b>", new GUILayoutOption[0]))
{
Search();
}
//if (m_cachingResults)
//{
// GUILayout.Label("Searching...", new GUILayoutOption[0]);
//}
//else
//{
// if (GUILayout.Button("<b><color=cyan>Search</color></b>", new GUILayoutOption[0]))
// {
// Search();
// }
//}
GUILayout.EndVertical();
}
private void ClassFilterToggle(TypeFilter mode, string label)
{
if (TypeMode == mode)
{
GUI.color = Color.green;
}
else
{
GUI.color = Color.white;
}
if (GUILayout.Button(label, new GUILayoutOption[] { GUILayout.Width(100) }))
{
TypeMode = mode;
}
GUI.color = Color.white;
}
private void SceneFilterToggle(SceneFilter mode, string label, float width)
{
if (SceneMode == mode)
{
GUI.color = Color.green;
}
else
{
GUI.color = Color.white;
}
if (GUILayout.Button(label, new GUILayoutOption[] { GUILayout.Width(width) }))
{
SceneMode = mode;
}
GUI.color = Color.white;
}
}
}

View File

@ -1,125 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using Explorer.Config;
using Explorer.UI.Main;
using Explorer.UI.Shared;
using Explorer.UI.Inspectors;
namespace Explorer.UI
{
public class MainMenu
{
public static MainMenu Instance;
public MainMenu()
{
Instance = this;
Pages.Add(new ScenePage());
Pages.Add(new SearchPage());
Pages.Add(new ConsolePage());
Pages.Add(new OptionsPage());
for (int i = 0; i < Pages.Count; i++)
{
var page = Pages[i];
page.Init();
// If page failed to init, it will remove itself from the list. Lower the iterate counter.
if (!Pages.Contains(page)) i--;
}
}
public const int MainWindowID = 5000;
public static Rect MainRect = new Rect(5, 5, ModConfig.Instance.Default_Window_Size.x, ModConfig.Instance.Default_Window_Size.y);
public static readonly List<BaseMainMenuPage> Pages = new List<BaseMainMenuPage>();
private static int m_currentPage = 0;
public static void SetCurrentPage(int index)
{
if (index < 0 || Pages.Count <= index)
{
ExplorerCore.Log("cannot set page " + index);
return;
}
m_currentPage = index;
GUIHelper.BringWindowToFront(MainWindowID);
GUI.FocusWindow(MainWindowID);
}
public void Update()
{
Pages[m_currentPage].Update();
}
public void OnGUI()
{
MainRect = GUIHelper.Window(MainWindowID, MainRect, (GUI.WindowFunction)MainWindow, ExplorerCore.NAME);
}
private void MainWindow(int id)
{
GUI.DragWindow(new Rect(0, 0, MainRect.width - 90, 20));
if (GUIHelper.Button(new Rect(MainRect.width - 90, 2, 80, 20), $"Hide ({ModConfig.Instance.Main_Menu_Toggle})"))
{
ExplorerCore.ShowMenu = false;
return;
}
GUIHelper.BeginArea(new Rect(5, 25, MainRect.width - 10, MainRect.height - 35), GUI.skin.box);
MainHeader();
var page = Pages[m_currentPage];
page.scroll = GUIHelper.BeginScrollView(page.scroll);
page.DrawWindow();
GUIHelper.EndScrollView();
MainRect = ResizeDrag.ResizeWindow(MainRect, MainWindowID);
GUIHelper.EndArea();
}
private void MainHeader()
{
GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
for (int i = 0; i < Pages.Count; i++)
{
if (m_currentPage == i)
GUI.color = Color.green;
else
GUI.color = Color.white;
if (GUILayout.Button(Pages[i].Name, new GUILayoutOption[0]))
{
m_currentPage = i;
}
}
GUILayout.EndHorizontal();
GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUI.color = Color.white;
InspectUnderMouse.EnableInspect = GUILayout.Toggle(InspectUnderMouse.EnableInspect, "Inspect Under Mouse (Shift + RMB)", new GUILayoutOption[0]);
bool mouseState = ForceUnlockCursor.Unlock;
bool setMouse = GUILayout.Toggle(mouseState, "Force Unlock Mouse (Left Alt)", new GUILayoutOption[0]);
if (setMouse != mouseState) ForceUnlockCursor.Unlock = setMouse;
//WindowManager.TabView = GUILayout.Toggle(WindowManager.TabView, "Tab View", new GUILayoutOption[0]);
GUILayout.EndHorizontal();
//GUIUnstrip.Space(10);
GUIHelper.Space(10);
GUI.color = Color.white;
}
}
}

View File

@ -1,100 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using Object = UnityEngine.Object;
namespace Explorer.UI.Shared
{
public class Buttons
{
public static void InstantiateButton(Object obj, float width = 100)
{
if (GUILayout.Button("Instantiate", new GUILayoutOption[] { GUILayout.Width(width) }))
{
var newobj = Object.Instantiate(obj);
WindowManager.InspectObject(newobj, out _);
}
}
public static void InspectButton(object obj)
{
if (GUILayout.Button("Inspect", new GUILayoutOption[0]))
{
WindowManager.InspectObject(obj, out bool _);
}
}
public static void GameObjectButton(object _obj, Action<Transform> inspectOverride = null, bool showSmallInspect = true, float width = 380)
{
var go = (_obj as GameObject) ?? (_obj as Transform).gameObject;
if (!go) return;
bool hasChild = go.transform.childCount > 0;
string label = hasChild ? $"[{go.transform.childCount} children] " : "";
label += go.name;
bool enabled = go.activeSelf;
int childCount = go.transform.childCount;
Color color;
if (enabled)
{
if (childCount > 0)
{
color = Color.green;
}
else
{
color = UIStyles.LightGreen;
}
}
else
{
color = Color.red;
}
// ------ toggle active button ------
GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUI.skin.button.alignment = TextAnchor.UpperLeft;
GUI.color = color;
enabled = GUILayout.Toggle(enabled, "", new GUILayoutOption[] { GUILayout.Width(18) });
if (go.activeSelf != enabled)
{
go.SetActive(enabled);
}
// ------- actual button ---------
if (GUILayout.Button(label, new GUILayoutOption[] { GUILayout.Height(22), GUILayout.Width(width) }))
{
if (inspectOverride != null)
{
inspectOverride(go.transform);
}
else
{
WindowManager.InspectObject(_obj, out bool _);
}
}
// ------ small "Inspect" button on the right ------
GUI.skin.button.alignment = TextAnchor.MiddleCenter;
GUI.color = Color.white;
if (showSmallInspect)
{
InspectButton(_obj);
}
GUILayout.EndHorizontal();
}
}
}

View File

@ -1,8 +0,0 @@
namespace Explorer
{
interface IExpandHeight
{
bool IsExpanded { get; set; }
float WhiteSpace { get; set; }
}
}

View File

@ -1,105 +0,0 @@
using System;
using UnityEngine;
namespace Explorer.UI.Shared
{
public enum Turn
{
Left,
Right
}
public class PageHelper
{
public int PageOffset { get; set; }
public int ItemsPerPage
{
get => m_itemsPerPage;
set
{
m_itemsPerPage = value;
CalculateMaxOffset();
}
}
private int m_itemsPerPage = Config.ModConfig.Instance.Default_Page_Limit;
public int ItemCount
{
get => m_count;
set
{
m_count = value;
CalculateMaxOffset();
}
}
private int m_count;
public int MaxPageOffset { get; private set; } = -1;
private int CalculateMaxOffset()
{
return MaxPageOffset = (int)Math.Ceiling((float)(ItemCount / (decimal)ItemsPerPage)) - 1;
}
public void CurrentPageLabel()
{
var orig = GUI.skin.label.alignment;
GUI.skin.label.alignment = TextAnchor.MiddleCenter;
GUILayout.Label($"Page {PageOffset + 1}/{MaxPageOffset + 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 < MaxPageOffset)
{
PageOffset++;
scroll = Vector2.zero;
}
}
}
public int CalculateOffsetIndex()
{
int offset = PageOffset * ItemsPerPage;
if (offset >= ItemCount)
{
offset = 0;
PageOffset = 0;
}
return offset;
}
public void DrawLimitInputArea()
{
GUILayout.Label("Limit: ", new GUILayoutOption[] { GUILayout.Width(50) });
var limit = this.ItemsPerPage.ToString();
limit = GUIHelper.TextField(limit, new GUILayoutOption[] { GUILayout.Width(50) });
if (limit != ItemsPerPage.ToString() && int.TryParse(limit, out int i))
{
ItemsPerPage = i;
}
}
}
}

View File

@ -1,127 +0,0 @@
using System;
#if CPP
using UnhollowerBaseLib;
#endif
using UnityEngine;
namespace Explorer.UI.Shared
{
public class ResizeDrag
{
private static bool RESIZE_FAILED = false;
public static bool IsResizing = false;
public static bool IsMouseInResizeArea = false;
private static readonly GUIContent gcDrag = new GUIContent("<-- Drag to resize -->");
private static Rect m_currentResize;
private static int m_currentWindow;
public static Rect ResizeWindow(Rect _rect, int ID)
{
if (!RESIZE_FAILED)
{
var origRect = _rect;
try
{
GUIHelper.BeginHorizontal(GUIContent.none, GUI.skin.box, null);
GUI.skin.label.alignment = TextAnchor.MiddleCenter;
#if BIE
#if CPP // Temporary for BepInEx IL2CPP
GUILayout.Button("<-- Drag to resize -->", new GUILayoutOption[] { GUILayout.Height(15) });
#else
GUILayout.Button(gcDrag, GUI.skin.label, new GUILayoutOption[] { GUILayout.Height(15) });
#endif
#else
GUILayout.Button(gcDrag, GUI.skin.label, new GUILayoutOption[] { GUILayout.Height(15) });
#endif
var resizeDragArea = GUIHelper.GetLastRect();
var mousePos = InputManager.MousePosition;
try
{
var mouse = GUIHelper.ScreenToGUIPoint(new Vector2(mousePos.x, Screen.height - mousePos.y));
if (resizeDragArea.Contains(mouse))
{
IsMouseInResizeArea = true;
if (InputManager.GetMouseButtonDown(0))
{
IsResizing = true;
m_currentWindow = ID;
m_currentResize = new Rect(mouse.x, mouse.y, _rect.width, _rect.height);
}
}
else if (!InputManager.GetMouseButton(0))
{
IsMouseInResizeArea = false;
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
}
}
catch
{
// throw safe Managed exception
throw new Exception("");
}
GUILayout.EndHorizontal();
}
catch (Exception e) when (e.Message.StartsWith("System.ArgumentException"))
{
// suppress
return origRect;
}
catch (Exception e)
{
RESIZE_FAILED = true;
ExplorerCore.Log("Exception on GuiResize: " + e.GetType() + ", " + e.Message);
//ExplorerCore.Log(e.StackTrace);
return origRect;
}
}
else
{
GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUILayout.Label("Resize window:", new GUILayoutOption[] { GUILayout.Width(100) });
GUI.skin.label.alignment = TextAnchor.MiddleRight;
GUILayout.Label("<color=cyan>Width:</color>", new GUILayoutOption[] { GUILayout.Width(60) });
if (GUIHelper.RepeatButton("-", new GUILayoutOption[] { GUILayout.Width(20) }))
{
_rect.width -= 5f;
}
if (GUIHelper.RepeatButton("+", new GUILayoutOption[] { GUILayout.Width(20) }))
{
_rect.width += 5f;
}
GUILayout.Label("<color=cyan>Height:</color>", new GUILayoutOption[] { GUILayout.Width(60) });
if (GUIHelper.RepeatButton("-", new GUILayoutOption[] { GUILayout.Width(20) }))
{
_rect.height -= 5f;
}
if (GUIHelper.RepeatButton("+", new GUILayoutOption[] { GUILayout.Width(20) }))
{
_rect.height += 5f;
}
GUILayout.EndHorizontal();
}
GUI.skin.label.alignment = TextAnchor.MiddleLeft;
return _rect;
}
}
}

View File

@ -3,7 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Explorer.UI.Shared
namespace ExplorerBeta.UI.Shared
{
public class Syntax
{

View File

@ -1,118 +0,0 @@
using UnityEngine;
using Object = UnityEngine.Object;
namespace Explorer.UI.Shared
{
public class UIStyles
{
public static Color LightGreen = new Color(Color.green.r - 0.3f, Color.green.g - 0.3f, Color.green.b - 0.3f);
public static GUISkin WindowSkin
{
get
{
if (_customSkin == null)
{
try
{
_customSkin = CreateWindowSkin();
}
catch
{
_customSkin = GUI.skin;
}
}
return _customSkin;
}
}
public static void HorizontalLine(Color _color, bool small = false)
{
var orig = GUI.color;
GUI.color = _color;
GUILayout.Box(GUIContent.none, !small ? HorizontalBar : HorizontalBarSmall, null);
GUI.color = orig;
}
private static GUISkin _customSkin;
public static Texture2D m_nofocusTex;
public static Texture2D m_focusTex;
private static GUIStyle HorizontalBar
{
get
{
if (_horizBarStyle == null)
{
_horizBarStyle = new GUIStyle();
_horizBarStyle.normal.background = Texture2D.whiteTexture;
var rectOffset = new RectOffset();
rectOffset.top = 4;
rectOffset.bottom = 4;
_horizBarStyle.margin = rectOffset;
_horizBarStyle.fixedHeight = 2;
}
return _horizBarStyle;
}
}
private static GUIStyle _horizBarStyle;
private static GUIStyle HorizontalBarSmall
{
get
{
if (_horizBarSmallStyle == null)
{
_horizBarSmallStyle = new GUIStyle();
_horizBarSmallStyle.normal.background = Texture2D.whiteTexture;
var rectOffset = new RectOffset();
rectOffset.top = 2;
rectOffset.bottom = 2;
_horizBarSmallStyle.margin = rectOffset;
_horizBarSmallStyle.fixedHeight = 1;
}
return _horizBarSmallStyle;
}
}
private static GUIStyle _horizBarSmallStyle;
private static GUISkin CreateWindowSkin()
{
var newSkin = Object.Instantiate(GUI.skin);
Object.DontDestroyOnLoad(newSkin);
m_nofocusTex = MakeTex(1, 1, new Color(0.1f, 0.1f, 0.1f, 0.7f));
m_focusTex = MakeTex(1, 1, new Color(0.3f, 0.3f, 0.3f, 1f));
newSkin.window.normal.background = m_nofocusTex;
newSkin.window.onNormal.background = m_focusTex;
newSkin.box.normal.textColor = Color.white;
newSkin.window.normal.textColor = Color.white;
newSkin.button.normal.textColor = Color.white;
newSkin.textField.normal.textColor = Color.white;
newSkin.label.normal.textColor = Color.white;
return newSkin;
}
public static Texture2D MakeTex(int width, int height, Color col)
{
Color[] pix = new Color[width * height];
for (int i = 0; i < pix.Length; ++i)
{
pix[i] = col;
}
Texture2D result = new Texture2D(width, height);
result.SetPixels(pix);
result.Apply();
return result;
}
}
}

View File

@ -1,124 +0,0 @@
using System;
using UnityEngine;
using Explorer.UI.Shared;
namespace Explorer.UI
{
public class TabViewWindow : WindowBase
{
public override string Title => $"Tabs ({WindowManager.Windows.Count})";
public static TabViewWindow Instance => m_instance ?? (m_instance = new TabViewWindow());
private static TabViewWindow m_instance;
private WindowBase m_targetWindow;
public int TargetTabID = 0;
public override bool IsTabViewWindow => true;
public TabViewWindow()
{
m_rect = new Rect(570, 0, 550, 700);
}
public override void Init() { }
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)
{
try
{
GUI.DragWindow(new Rect(0, 0, m_rect.width - 90, 20));
if (GUIHelper.Button(new Rect(m_rect.width - 90, 2, 80, 20), "<color=red>Close All</color>"))
{
foreach (var window in WindowManager.Windows)
{
window.DestroyWindow();
}
return;
}
GUIHelper.BeginArea(new Rect(5, 25, m_rect.width - 10, m_rect.height - 35), GUI.skin.box);
GUIHelper.BeginVertical(GUIContent.none, GUI.skin.box, null);
GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
GUI.skin.button.alignment = TextAnchor.MiddleLeft;
int tabPerRow = (int)Math.Floor(m_rect.width / 238);
int rowCount = 0;
for (int i = 0; i < WindowManager.Windows.Count; i++)
{
var window = WindowManager.Windows[i];
// Prevent trying to draw destroyed UnityEngine.Objects
// before the WindowManager removes them.
if (window.Target is UnityEngine.Object uObj && !uObj)
{
continue;
}
if (rowCount >= tabPerRow)
{
rowCount = 0;
GUILayout.EndHorizontal();
GUIHelper.BeginHorizontal(new GUILayoutOption[0]);
}
rowCount++;
bool focused = i == TargetTabID;
string color = focused ? "<color=lime>" : "<color=orange>";
GUI.color = focused ? Color.green : Color.white;
if (GUILayout.Button(color + window.Title + "</color>", new GUILayoutOption[] { GUILayout.Width(200) }))
{
TargetTabID = i;
}
if (GUILayout.Button("<color=red><b>X</b></color>", new GUILayoutOption[] { GUILayout.Width(22) }))
{
window.DestroyWindow();
}
}
GUI.color = Color.white;
GUILayout.EndHorizontal();
GUILayout.EndVertical();
GUI.skin.button.alignment = TextAnchor.MiddleCenter;
m_targetWindow.WindowFunction(m_targetWindow.windowID);
m_rect = ResizeDrag.ResizeWindow(m_rect, windowID);
GUIHelper.EndArea();
}
catch (Exception e)
{
if (!e.Message.Contains("in a group with only"))
{
ExplorerCore.Log("Exception drawing Tab View window: " + e.GetType() + ", " + e.Message);
ExplorerCore.Log(e.StackTrace);
}
}
}
}
}

570
src/UI/UIFactory.cs Normal file
View File

@ -0,0 +1,570 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using UnityEngine.UI;
namespace ExplorerBeta.UI
{
public static class UIFactory
{
//private const float kWidth = 160f;
//private const float kThickHeight = 30f;
//private const float kThinHeight = 20f;
private static Vector2 s_ThickElementSize = new Vector2(160f, 30f);
private static Vector2 s_ThinElementSize = new Vector2(160f, 20f);
//private static Vector2 s_ImageElementSize = new Vector2(100f, 100f);
private static Color s_DefaultSelectableColor = new Color(0.3f, 0.3f, 0.3f, 1f);
private static Color s_PanelColor = new Color(0.1f, 0.1f, 0.1f, 1.0f);
private static Color s_TextColor = new Color(0.95f, 0.95f, 0.95f, 1f);
public static Resources UIResources { get; set; }
public struct Resources
{
public Sprite standard;
public Sprite background;
public Sprite inputField;
public Sprite knob;
public Sprite checkmark;
public Sprite dropdown;
public Sprite mask;
}
private static GameObject CreateUIObject(string name, GameObject parent, Vector2 size = default)
{
GameObject obj = new GameObject(name);
var rect = obj.AddComponent<RectTransform>();
if (size != default)
{
rect.sizeDelta = size;
}
SetParentAndAlign(obj, parent);
return obj;
}
private static void SetDefaultTextValues(Text lbl)
{
lbl.color = s_TextColor;
lbl.AssignDefaultFont();
//lbl.alignment = alignment;
//lbl.resizeTextForBestFit = true;
}
private static void SetDefaultColorTransitionValues(Selectable slider)
{
ColorBlock colors = slider.colors;
colors.highlightedColor = new Color(0.4f, 0.4f, 0.4f);
colors.pressedColor = new Color(0.05f, 0.05f, 0.05f);
colors.disabledColor = new Color(0.7f, 0.7f, 0.7f);
}
private static void SetParentAndAlign(GameObject child, GameObject parent)
{
if (parent == null)
{
return;
}
child.transform.SetParent(parent.transform, false);
SetLayerRecursively(child);
}
private static void SetLayerRecursively(GameObject go)
{
go.layer = 5;
Transform transform = go.transform;
for (int i = 0; i < transform.childCount; i++)
{
DefaultControls.SetLayerRecursively(transform.GetChild(i).gameObject, 5);
}
}
public static GameObject CreatePanel(GameObject parent, string name)
{
GameObject panelObj = CreateUIObject($"Panel_{name}", parent, s_ThickElementSize);
RectTransform rect = panelObj.GetComponent<RectTransform>();
rect.anchorMin = Vector2.zero;
rect.anchorMax = Vector2.one;
rect.anchoredPosition = Vector2.zero;
rect.sizeDelta = Vector2.zero;
Image image = panelObj.AddComponent<Image>();
image.sprite = UIResources.background;
image.type = Image.Type.Sliced;
image.color = s_PanelColor;
return panelObj;
}
public static GameObject CreateVerticalGroup(GameObject parent, Color color = default)
{
var groupObj = CreateUIObject("HorizontalLayout", parent);
var horiGroup = groupObj.AddComponent<VerticalLayoutGroup>();
horiGroup.childAlignment = TextAnchor.UpperLeft;
horiGroup.childControlWidth = false;
var image = groupObj.AddComponent<Image>();
if (color != default)
image.color = color;
else
image.color = new Color(44f / 255f, 44f / 255f, 44f / 255f);
return groupObj;
}
public static GameObject CreateHorizontalGroup(GameObject parent, Color color = default)
{
var groupObj = CreateUIObject("HorizontalLayout", parent);
var horiGroup = groupObj.AddComponent<HorizontalLayoutGroup>();
horiGroup.childAlignment = TextAnchor.UpperLeft;
horiGroup.childControlWidth = false;
var image = groupObj.AddComponent<Image>();
if (color != default)
image.color = color;
else
image.color = new Color(44f / 255f, 44f / 255f, 44f / 255f);
return groupObj;
}
public static GameObject CreateLabel(GameObject parent, TextAnchor alignment)
{
GameObject labelObj = CreateUIObject("Label", parent, s_ThinElementSize);
var text = labelObj.AddComponent<Text>();
SetDefaultTextValues(text);
text.alignment = alignment;
return labelObj;
}
public static GameObject CreateButton(GameObject parent)
{
GameObject buttonObj = CreateUIObject("Button", parent, s_ThinElementSize);
GameObject textObj = new GameObject("Text");
textObj.AddComponent<RectTransform>();
SetParentAndAlign(textObj, buttonObj);
Image image = buttonObj.AddComponent<Image>();
image.sprite = UIResources.standard;
image.type = Image.Type.Sliced;
image.color = s_DefaultSelectableColor;
SetDefaultColorTransitionValues(buttonObj.AddComponent<Button>());
Text text = textObj.AddComponent<Text>();
text.text = "Button";
SetDefaultTextValues(text);
text.alignment = TextAnchor.MiddleCenter;
RectTransform rect = textObj.GetComponent<RectTransform>();
rect.anchorMin = Vector2.zero;
rect.anchorMax = Vector2.one;
rect.sizeDelta = Vector2.zero;
return buttonObj;
}
public static GameObject CreateSlider(GameObject parent)
{
GameObject sliderObj = CreateUIObject("Slider", parent, s_ThinElementSize);
GameObject bgObj = CreateUIObject("Background", sliderObj);
GameObject fillAreaObj = CreateUIObject("Fill Area", sliderObj);
GameObject fillObj = CreateUIObject("Fill", fillAreaObj);
GameObject handleSlideAreaObj = CreateUIObject("Handle Slide Area", sliderObj);
GameObject handleObj = CreateUIObject("Handle", handleSlideAreaObj);
Image bgImage = bgObj.AddComponent<Image>();
bgImage.sprite = UIResources.background;
bgImage.type = Image.Type.Sliced;
bgImage.color = s_DefaultSelectableColor;
RectTransform bgRect = bgObj.GetComponent<RectTransform>();
bgRect.anchorMin = new Vector2(0f, 0.25f);
bgRect.anchorMax = new Vector2(1f, 0.75f);
bgRect.sizeDelta = new Vector2(0f, 0f);
RectTransform fillAreaRect = fillAreaObj.GetComponent<RectTransform>();
fillAreaRect.anchorMin = new Vector2(0f, 0.25f);
fillAreaRect.anchorMax = new Vector2(1f, 0.75f);
fillAreaRect.anchoredPosition = new Vector2(-5f, 0f);
fillAreaRect.sizeDelta = new Vector2(-20f, 0f);
Image fillImage = fillObj.AddComponent<Image>();
fillImage.sprite = UIResources.standard;
fillImage.type = Image.Type.Sliced;
fillImage.color = s_DefaultSelectableColor;
fillObj.GetComponent<RectTransform>().sizeDelta = new Vector2(10f, 0f);
RectTransform handleSlideRect = handleSlideAreaObj.GetComponent<RectTransform>();
handleSlideRect.sizeDelta = new Vector2(-20f, 0f);
handleSlideRect.anchorMin = new Vector2(0f, 0f);
handleSlideRect.anchorMax = new Vector2(1f, 1f);
Image handleImage = handleObj.AddComponent<Image>();
handleImage.sprite = UIResources.knob;
handleImage.color = s_DefaultSelectableColor;
handleObj.GetComponent<RectTransform>().sizeDelta = new Vector2(20f, 0f);
Slider slider = sliderObj.AddComponent<Slider>();
slider.fillRect = fillObj.GetComponent<RectTransform>();
slider.handleRect = handleObj.GetComponent<RectTransform>();
slider.targetGraphic = handleImage;
slider.direction = Slider.Direction.LeftToRight;
SetDefaultColorTransitionValues(slider);
return sliderObj;
}
public static GameObject CreateScrollbar(GameObject parent)
{
GameObject scrollObj = CreateUIObject("Scrollbar", parent, s_ThinElementSize);
GameObject slideAreaObj = CreateUIObject("Sliding Area", scrollObj);
GameObject handleObj = CreateUIObject("Handle", slideAreaObj);
Image scrollImage = scrollObj.AddComponent<Image>();
scrollImage.sprite = UIResources.background;
scrollImage.type = Image.Type.Sliced;
scrollImage.color = s_DefaultSelectableColor;
Image handleImage = handleObj.AddComponent<Image>();
handleImage.sprite = UIResources.standard;
handleImage.type = Image.Type.Sliced;
handleImage.color = s_DefaultSelectableColor;
RectTransform slideAreaRect = slideAreaObj.GetComponent<RectTransform>();
slideAreaRect.sizeDelta = new Vector2(-20f, -20f);
slideAreaRect.anchorMin = Vector2.zero;
slideAreaRect.anchorMax = Vector2.one;
RectTransform handleRect = handleObj.GetComponent<RectTransform>();
handleRect.sizeDelta = new Vector2(20f, 20f);
Scrollbar scrollbar = scrollObj.AddComponent<Scrollbar>();
scrollbar.handleRect = handleRect;
scrollbar.targetGraphic = handleImage;
SetDefaultColorTransitionValues(scrollbar);
return scrollObj;
}
public static GameObject CreateToggle(GameObject parent)
{
GameObject toggleObj = CreateUIObject("Toggle", parent, s_ThinElementSize);
GameObject bgObj = CreateUIObject("Background", toggleObj);
GameObject checkObj = CreateUIObject("Checkmark", bgObj);
GameObject labelObj = CreateUIObject("Label", toggleObj);
Toggle toggle = toggleObj.AddComponent<Toggle>();
toggle.isOn = true;
Image bgImage = bgObj.AddComponent<Image>();
bgImage.sprite = UIResources.standard;
bgImage.type = Image.Type.Sliced;
bgImage.color = s_DefaultSelectableColor;
Image checkImage = checkObj.AddComponent<Image>();
checkImage.sprite = UIResources.checkmark;
Text text = labelObj.AddComponent<Text>();
text.text = "Toggle";
SetDefaultTextValues(text);
toggle.graphic = checkImage;
toggle.targetGraphic = bgImage;
SetDefaultColorTransitionValues(toggle);
RectTransform bgRect = bgObj.GetComponent<RectTransform>();
bgRect.anchorMin = new Vector2(0f, 1f);
bgRect.anchorMax = new Vector2(0f, 1f);
bgRect.anchoredPosition = new Vector2(10f, -10f);
bgRect.sizeDelta = new Vector2(20f, 20f);
RectTransform checkRect = checkObj.GetComponent<RectTransform>();
checkRect.anchorMin = new Vector2(0.5f, 0.5f);
checkRect.anchorMax = new Vector2(0.5f, 0.5f);
checkRect.anchoredPosition = Vector2.zero;
checkRect.sizeDelta = new Vector2(20f, 20f);
RectTransform labelRect = labelObj.GetComponent<RectTransform>();
labelRect.anchorMin = new Vector2(0f, 0f);
labelRect.anchorMax = new Vector2(1f, 1f);
labelRect.offsetMin = new Vector2(23f, 1f);
labelRect.offsetMax = new Vector2(-5f, -2f);
return toggleObj;
}
public static GameObject CreateInputField(GameObject parent)
{
GameObject inputObj = CreateUIObject("InputField", parent, s_ThickElementSize);
GameObject placeholderObj = CreateUIObject("Placeholder", inputObj);
GameObject textObj = CreateUIObject("Text", inputObj);
Image inputImage = inputObj.AddComponent<Image>();
inputImage.sprite = UIResources.inputField;
inputImage.type = Image.Type.Sliced;
inputImage.color = s_DefaultSelectableColor;
InputField inputField = inputObj.AddComponent<InputField>();
SetDefaultColorTransitionValues(inputField);
Text text = textObj.AddComponent<Text>();
text.text = "";
text.supportRichText = false;
SetDefaultTextValues(text);
Text placeholderText = placeholderObj.AddComponent<Text>();
placeholderText.text = "Enter text...";
placeholderText.fontStyle = FontStyle.Italic;
Color color = text.color;
color.a *= 0.5f;
placeholderText.color = color;
RectTransform textRect = textObj.GetComponent<RectTransform>();
textRect.anchorMin = Vector2.zero;
textRect.anchorMax = Vector2.one;
textRect.sizeDelta = Vector2.zero;
textRect.offsetMin = new Vector2(10f, 6f);
textRect.offsetMax = new Vector2(-10f, -7f);
RectTransform placeholderRect = placeholderObj.GetComponent<RectTransform>();
placeholderRect.anchorMin = Vector2.zero;
placeholderRect.anchorMax = Vector2.one;
placeholderRect.sizeDelta = Vector2.zero;
placeholderRect.offsetMin = new Vector2(10f, 6f);
placeholderRect.offsetMax = new Vector2(-10f, -7f);
inputField.textComponent = text;
inputField.placeholder = placeholderText;
return inputObj;
}
public static GameObject CreateDropdown(GameObject parent)
{
GameObject dropdownObj = CreateUIObject("Dropdown", parent, s_ThickElementSize);
GameObject labelObj = CreateUIObject("Label", dropdownObj);
GameObject arrowObj = CreateUIObject("Arrow", dropdownObj);
GameObject templateObj = CreateUIObject("Template", dropdownObj);
GameObject viewportObj = CreateUIObject("Viewport", templateObj);
GameObject contentObj = CreateUIObject("Content", viewportObj);
GameObject itemObj = CreateUIObject("Item", contentObj);
GameObject itemBgObj = CreateUIObject("Item Background", itemObj);
GameObject itemCheckObj = CreateUIObject("Item Checkmark", itemObj);
GameObject itemLabelObj = CreateUIObject("Item Label", itemObj);
GameObject scrollbarObj = CreateScrollbar(templateObj);
scrollbarObj.name = "Scrollbar";
Scrollbar scrollbar = scrollbarObj.GetComponent<Scrollbar>();
scrollbar.SetDirection(Scrollbar.Direction.BottomToTop, true);
RectTransform scrollRectTransform = scrollbarObj.GetComponent<RectTransform>();
scrollRectTransform.anchorMin = Vector2.right;
scrollRectTransform.anchorMax = Vector2.one;
scrollRectTransform.pivot = Vector2.one;
scrollRectTransform.sizeDelta = new Vector2(scrollRectTransform.sizeDelta.x, 0f);
Text itemLabelText = itemLabelObj.AddComponent<Text>();
SetDefaultTextValues(itemLabelText);
itemLabelText.alignment = TextAnchor.MiddleLeft;
Image itemBgImage = itemBgObj.AddComponent<Image>();
itemBgImage.color = new Color32(245, 245, 245, byte.MaxValue);
Image itemCheckImage = itemCheckObj.AddComponent<Image>();
itemCheckImage.sprite = UIResources.checkmark;
Toggle itemToggle = itemObj.AddComponent<Toggle>();
itemToggle.targetGraphic = itemBgImage;
itemToggle.graphic = itemCheckImage;
itemToggle.isOn = true;
Image templateImage = templateObj.AddComponent<Image>();
templateImage.sprite = UIResources.standard;
templateImage.type = Image.Type.Sliced;
ScrollRect scrollRect = templateObj.AddComponent<ScrollRect>();
scrollRect.content = (RectTransform)contentObj.transform;
scrollRect.viewport = (RectTransform)viewportObj.transform;
scrollRect.horizontal = false;
scrollRect.movementType = ScrollRect.MovementType.Clamped;
scrollRect.verticalScrollbar = scrollbar;
scrollRect.verticalScrollbarVisibility = ScrollRect.ScrollbarVisibility.AutoHideAndExpandViewport;
scrollRect.verticalScrollbarSpacing = -3f;
viewportObj.AddComponent<Mask>().showMaskGraphic = false;
Image viewportImage = viewportObj.AddComponent<Image>();
viewportImage.sprite = UIResources.mask;
viewportImage.type = Image.Type.Sliced;
Text labelText = labelObj.AddComponent<Text>();
SetDefaultTextValues(labelText);
labelText.alignment = TextAnchor.MiddleLeft;
arrowObj.AddComponent<Image>().sprite = UIResources.dropdown;
Image dropdownImage = dropdownObj.AddComponent<Image>();
dropdownImage.sprite = UIResources.standard;
dropdownImage.color = s_DefaultSelectableColor;
dropdownImage.type = Image.Type.Sliced;
Dropdown dropdown = dropdownObj.AddComponent<Dropdown>();
dropdown.targetGraphic = dropdownImage;
SetDefaultColorTransitionValues(dropdown);
dropdown.template = templateObj.GetComponent<RectTransform>();
dropdown.captionText = labelText;
dropdown.itemText = itemLabelText;
itemLabelText.text = "Option A";
dropdown.options.Add(new Dropdown.OptionData
{
text = "Option A"
});
//dropdown.options.Add(new Dropdown.OptionData
//{
// text = "Option B"
//});
//dropdown.options.Add(new Dropdown.OptionData
//{
// text = "Option C"
//});
dropdown.RefreshShownValue();
RectTransform labelRect = labelObj.GetComponent<RectTransform>();
labelRect.anchorMin = Vector2.zero;
labelRect.anchorMax = Vector2.one;
labelRect.offsetMin = new Vector2(10f, 6f);
labelRect.offsetMax = new Vector2(-25f, -7f);
RectTransform arrowRect = arrowObj.GetComponent<RectTransform>();
arrowRect.anchorMin = new Vector2(1f, 0.5f);
arrowRect.anchorMax = new Vector2(1f, 0.5f);
arrowRect.sizeDelta = new Vector2(20f, 20f);
arrowRect.anchoredPosition = new Vector2(-15f, 0f);
RectTransform templateRect = templateObj.GetComponent<RectTransform>();
templateRect.anchorMin = new Vector2(0f, 0f);
templateRect.anchorMax = new Vector2(1f, 0f);
templateRect.pivot = new Vector2(0.5f, 1f);
templateRect.anchoredPosition = new Vector2(0f, 2f);
templateRect.sizeDelta = new Vector2(0f, 150f);
RectTransform viewportRect = viewportObj.GetComponent<RectTransform>();
viewportRect.anchorMin = new Vector2(0f, 0f);
viewportRect.anchorMax = new Vector2(1f, 1f);
viewportRect.sizeDelta = new Vector2(-18f, 0f);
viewportRect.pivot = new Vector2(0f, 1f);
RectTransform contentRect = contentObj.GetComponent<RectTransform>();
contentRect.anchorMin = new Vector2(0f, 1f);
contentRect.anchorMax = new Vector2(1f, 1f);
contentRect.pivot = new Vector2(0.5f, 1f);
contentRect.anchoredPosition = new Vector2(0f, 0f);
contentRect.sizeDelta = new Vector2(0f, 28f);
RectTransform itemRect = itemObj.GetComponent<RectTransform>();
itemRect.anchorMin = new Vector2(0f, 0.5f);
itemRect.anchorMax = new Vector2(1f, 0.5f);
itemRect.sizeDelta = new Vector2(0f, 20f);
RectTransform itemBgRect = itemBgObj.GetComponent<RectTransform>();
itemBgRect.anchorMin = Vector2.zero;
itemBgRect.anchorMax = Vector2.one;
itemBgRect.sizeDelta = Vector2.zero;
RectTransform itemCheckRect = itemCheckObj.GetComponent<RectTransform>();
itemCheckRect.anchorMin = new Vector2(0f, 0.5f);
itemCheckRect.anchorMax = new Vector2(0f, 0.5f);
itemCheckRect.sizeDelta = new Vector2(20f, 20f);
itemCheckRect.anchoredPosition = new Vector2(10f, 0f);
RectTransform itemLabelRect = itemLabelObj.GetComponent<RectTransform>();
itemLabelRect.anchorMin = Vector2.zero;
itemLabelRect.anchorMax = Vector2.one;
itemLabelRect.offsetMin = new Vector2(20f, 1f);
itemLabelRect.offsetMax = new Vector2(-10f, -2f);
templateObj.SetActive(false);
return dropdownObj;
}
public static GameObject CreateScrollView(GameObject parent)
{
GameObject scrollObj = CreateUIObject("Scroll View", parent, new Vector2(200f, 200f));
GameObject viewportObj = CreateUIObject("Viewport", scrollObj);
GameObject contentObj = CreateUIObject("Content", viewportObj);
GameObject horiScroll = CreateScrollbar(scrollObj);
horiScroll.name = "Scrollbar Horizontal";
//SetParentAndAlign(scrollbarObj, scrollObj);
RectTransform horiRect = horiScroll.GetComponent<RectTransform>();
horiRect.anchorMin = Vector2.zero;
horiRect.anchorMax = Vector2.right;
horiRect.pivot = Vector2.zero;
horiRect.sizeDelta = new Vector2(0f, horiRect.sizeDelta.y);
GameObject vertScroll = CreateScrollbar(scrollObj);
vertScroll.name = "Scrollbar Vertical";
//SetParentAndAlign(vertScroll, scrollObj);
vertScroll.GetComponent<Scrollbar>().SetDirection(Scrollbar.Direction.BottomToTop, true);
RectTransform vertRect = vertScroll.GetComponent<RectTransform>();
vertRect.anchorMin = Vector2.right;
vertRect.anchorMax = Vector2.one;
vertRect.pivot = Vector2.one;
vertRect.sizeDelta = new Vector2(vertRect.sizeDelta.x, 0f);
RectTransform viewportRect = viewportObj.GetComponent<RectTransform>();
viewportRect.anchorMin = Vector2.zero;
viewportRect.anchorMax = Vector2.one;
viewportRect.sizeDelta = Vector2.zero;
viewportRect.pivot = Vector2.up;
RectTransform contentRect = contentObj.GetComponent<RectTransform>();
contentRect.anchorMin = Vector2.up;
contentRect.anchorMax = Vector2.one;
contentRect.sizeDelta = new Vector2(0f, 300f);
contentRect.pivot = Vector2.up;
ScrollRect scrollRect = scrollObj.AddComponent<ScrollRect>();
scrollRect.content = contentRect;
scrollRect.viewport = viewportRect;
scrollRect.horizontalScrollbar = horiScroll.GetComponent<Scrollbar>();
scrollRect.verticalScrollbar = vertScroll.GetComponent<Scrollbar>();
scrollRect.horizontalScrollbarVisibility = ScrollRect.ScrollbarVisibility.AutoHideAndExpandViewport;
scrollRect.verticalScrollbarVisibility = ScrollRect.ScrollbarVisibility.AutoHideAndExpandViewport;
scrollRect.horizontalScrollbarSpacing = -3f;
scrollRect.verticalScrollbarSpacing = -3f;
Image scrollImage = scrollObj.AddComponent<Image>();
scrollImage.sprite = UIResources.background;
scrollImage.type = Image.Type.Sliced;
scrollImage.color = s_PanelColor;
viewportObj.AddComponent<Mask>().showMaskGraphic = false;
Image viewportImage = viewportObj.AddComponent<Image>();
viewportImage.sprite = UIResources.mask;
viewportImage.type = Image.Type.Sliced;
return scrollObj;
}
}
}

126
src/UI/UIManager.cs Normal file
View File

@ -0,0 +1,126 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ExplorerBeta.Input;
using ExplorerBeta.UI.Main;
using ExplorerBeta.UI.Shared;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
namespace ExplorerBeta.UI
{
// This class itself is fine.
public static class UIManager
{
public static GameObject CanvasRoot { get; private set; }
public static EventSystem EventSys { get; private set; }
public static StandaloneInputModule InputModule { get; private set; }
public static void Init()
{
var res = UIFactory.UIResources = new UIFactory.Resources();
var bg = CreateSprite(MakeSolidTexture(new Color(0.1f, 0.1f, 0.1f), 1, 1), new Rect(0, 0, 1, 1));
res.background = bg;
// Create core UI Canvas and Event System handler
CreateRootCanvas();
// Create submodules
new MainMenu();
}
public static void SetEventSystem()
{
EventSystem.current = EventSys;
InputModule.ActivateModule();
}
private static GameObject CreateRootCanvas()
{
var rootObj = new GameObject("ExplorerCanvas");
UnityEngine.Object.DontDestroyOnLoad(rootObj);
rootObj.layer = 5;
CanvasRoot = rootObj;
CanvasRoot.transform.position = new Vector3(0f, 0f, 1f);
EventSys = rootObj.AddComponent<EventSystem>();
InputModule = rootObj.AddComponent<StandaloneInputModule>();
InputModule.ActivateModule();
var canvas = rootObj.AddComponent<Canvas>();
canvas.renderMode = RenderMode.ScreenSpaceCamera;
canvas.referencePixelsPerUnit = 100;
canvas.sortingOrder = 999;
var scaler = rootObj.AddComponent<CanvasScaler>();
scaler.referenceResolution = new Vector2(1920, 1080);
scaler.screenMatchMode = CanvasScaler.ScreenMatchMode.Expand;
rootObj.AddComponent<GraphicRaycaster>();
return rootObj;
}
public static void Update()
{
if (EventSys && InputModule)
{
if (EventSystem.current != EventSys)
{
ForceUnlockCursor.SetEventSystem();
//ForceUnlockCursor.Unlock = true;
}
// Fix for games which override the InputModule pointer events (eg, VRChat)
if (InputModule.m_InputPointerEvent != null)
{
var evt = InputModule.m_InputPointerEvent;
if (!evt.eligibleForClick && evt.selectedObject)
{
evt.eligibleForClick = true;
}
}
}
if (PanelDragger.Instance != null)
{
PanelDragger.Instance.Update();
}
}
public static void OnSceneChange()
{
// todo
}
public static Sprite CreateSprite(Texture2D tex, Rect size)
{
#if CPP
var pivot = Vector2.zero;
var border = Vector4.zero;
return Sprite.CreateSprite_Injected(tex, ref size, ref pivot, 100f, 0u, SpriteMeshType.Tight, ref border, false);
#else
return Sprite.Create(tex, size, Vector2.zero);
#endif
}
public static Texture2D MakeSolidTexture(Color color, int width, int height)
{
var pixels = new Color[width * height];
for (int i = 0; i < pixels.Length; i++)
{
pixels[i] = color;
}
var tex = new Texture2D(width, height);
tex.SetPixels(pixels);
tex.Apply();
return tex;
}
}
}

View File

@ -1,88 +0,0 @@
using System;
using UnityEngine;
using Explorer.Config;
using Explorer.UI.Inspectors;
namespace Explorer.UI
{
public abstract class WindowBase
{
public abstract string Title { get; }
public object Target;
public int windowID;
public Rect m_rect = new Rect(0, 0, ModConfig.Instance.Default_Window_Size.x, ModConfig.Instance.Default_Window_Size.y);
public Vector2 scroll = Vector2.zero;
public virtual bool IsTabViewWindow => false;
public abstract void Init();
public abstract void WindowFunction(int windowID);
public abstract void Update();
public static WindowBase CreateWindow<T>(object target) where T : WindowBase
{
var window = Activator.CreateInstance<T>();
window.Target = target;
window.windowID = WindowManager.NextWindowID();
window.m_rect = WindowManager.GetNewWindowRect();
WindowManager.Windows.Add(window);
window.Init();
return window;
}
public static StaticInspector CreateWindowStatic(Type type)
{
var window = new StaticInspector
{
TargetType = type,
windowID = WindowManager.NextWindowID(),
m_rect = WindowManager.GetNewWindowRect()
};
WindowManager.Windows.Add(window);
window.Init();
return window;
}
public void DestroyWindow()
{
WindowManager.DestroyWindow(this);
}
public void OnGUI()
{
#if CPP
m_rect = GUI.Window(windowID, m_rect, (GUI.WindowFunction)WindowFunction, GUIContent.Temp(Title), GUI.skin.window);
#else
m_rect = GUI.Window(windowID, m_rect, WindowFunction, Title);
#endif
}
public void Header()
{
if (!WindowManager.TabView)
{
GUI.DragWindow(new Rect(0, 0, m_rect.width - 90, 20));
#if CPP
if (GUI.Button(new Rect(m_rect.width - 90, 2, 80, 20), GUIContent.Temp("<color=red><b>X</b></color>"), GUI.skin.button))
#else
if (GUI.Button(new Rect(m_rect.width - 90, 2, 80, 20), "<color=red><b>X</b></color>", GUI.skin.button))
#endif
{
DestroyWindow();
return;
}
}
}
}
}

View File

@ -1,234 +0,0 @@
using System;
using System.Collections.Generic;
using UnityEngine;
using Explorer.UI.Inspectors;
namespace Explorer.UI
{
public class WindowManager
{
public static WindowManager Instance;
public static bool TabView = Config.ModConfig.Instance.Tab_View;
public static bool IsMouseInWindow
{
get
{
if (!ExplorerCore.ShowMenu)
{
return false;
}
foreach (var window in Windows)
{
if (RectContainsMouse(window.m_rect))
{
return true;
}
}
return RectContainsMouse(MainMenu.MainRect);
}
}
public static List<WindowBase> Windows = new List<WindowBase>();
public static int CurrentWindowID { get; set; } = 500000;
private static Rect m_lastWindowRect;
private static readonly List<WindowBase> m_windowsToDestroy = new List<WindowBase>();
public WindowManager()
{
Instance = this;
}
public static void DestroyWindow(WindowBase window)
{
m_windowsToDestroy.Add(window);
}
public static WindowBase InspectObject(object obj, out bool createdNew, bool forceReflection = false)
{
createdNew = false;
//if (InputManager.GetKey(KeyCode.LeftShift))
//{
// forceReflection = true;
//}
#if CPP
Il2CppSystem.Object iObj = null;
if (obj is Il2CppSystem.Object isObj)
{
iObj = isObj;
}
#else
var iObj = obj;
#endif
if (!forceReflection)
{
foreach (var window in Windows)
{
bool equals = ReferenceEquals(obj, window.Target);
#if CPP
if (!equals && iObj is Il2CppSystem.Object iCurrent && window.Target is Il2CppSystem.Object iTarget)
{
if (iCurrent.GetIl2CppType().FullName != iTarget.GetIl2CppType().FullName)
{
if (iCurrent is Transform transform)
{
iCurrent = transform.gameObject;
}
}
equals = iCurrent.Pointer == iTarget.Pointer;
}
#endif
if (equals)
{
FocusWindow(window);
return window;
}
}
}
createdNew = true;
if (!forceReflection && (obj is GameObject || obj is Transform))
{
return InspectGameObject(obj as GameObject ?? (obj as Transform).gameObject);
}
else
{
return InspectReflection(obj);
}
}
private static void FocusWindow(WindowBase window)
{
if (!TabView)
{
GUIHelper.BringWindowToFront(window.windowID);
GUI.FocusWindow(window.windowID);
}
else
{
TabViewWindow.Instance.TargetTabID = Windows.IndexOf(window);
}
}
private static WindowBase InspectGameObject(GameObject obj)
{
var new_window = WindowBase.CreateWindow<GameObjectInspector>(obj);
FocusWindow(new_window);
return new_window;
}
private static WindowBase InspectReflection(object obj)
{
var new_window = WindowBase.CreateWindow<InstanceInspector>(obj);
FocusWindow(new_window);
return new_window;
}
public static StaticInspector InspectStaticReflection(Type type)
{
var new_window = WindowBase.CreateWindowStatic(type);
FocusWindow(new_window);
return new_window;
}
private static bool RectContainsMouse(Rect rect)
{
var mousePos = InputManager.MousePosition;
return rect.Contains(new Vector2(mousePos.x, Screen.height - mousePos.y));
}
public static int NextWindowID()
{
return CurrentWindowID++;
}
public static Rect GetNewWindowRect()
{
return GetNewWindowRect(ref m_lastWindowRect);
}
public static Rect GetNewWindowRect(ref Rect lastRect)
{
Rect rect = new Rect(0, 0, 550, 700);
var mainrect = MainMenu.MainRect;
if (mainrect.x <= (Screen.width - mainrect.width - 100))
{
rect = new Rect(mainrect.x + mainrect.width + 20, mainrect.y, rect.width, rect.height);
}
if (lastRect.x == rect.x)
{
rect = new Rect(rect.x + 25, rect.y + 25, rect.width, rect.height);
}
lastRect = rect;
return rect;
}
// ============= instance methods ===============
public void Update()
{
if (m_windowsToDestroy.Count > 0)
{
foreach (var window in m_windowsToDestroy)
{
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();
}
}
}
}
public void OnGUI()
{
if (TabView)
{
if (Windows.Count > 0)
{
TabViewWindow.Instance.OnGUI();
}
}
else
{
foreach (var window in Windows)
{
window.OnGUI();
}
}
}
}
}

View File

@ -1,183 +0,0 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using UnityEngine;
#if CPP
using Explorer.Unstrip.IMGUI;
#endif
namespace Explorer
{
// All the pre-processor directive stuff is in this class to keep it separate.
// This is so Mono build can use this class and not have to worry.
public class GUIHelper
{
internal static GUILayoutOption ExpandWidth(bool expand)
{
#if CPP
return GUIUnstrip.ExpandWidth(expand);
#else
return GUIHelper.ExpandWidth(expand);
#endif
}
internal static GUILayoutOption ExpandHeight(bool expand)
{
#if CPP
return GUIUnstrip.ExpandHeight(expand);
#else
return GUILayout.ExpandHeight(expand);
#endif
}
public static void BeginHorizontal(params GUILayoutOption[] options)
=> BeginHorizontal(GUIContent.none, GUIStyle.none, options);
public static void BeginHorizontal(GUIStyle style, params GUILayoutOption[] options)
=> BeginHorizontal(GUIContent.none, style, options);
public static void BeginHorizontal(GUIContent content, GUIStyle style, params GUILayoutOption[] options)
{
#if CPP
GUIUnstrip.BeginLayoutDirection(false, content, style, options);
#else
GUILayout.BeginHorizontal(content, style, options);
#endif
}
public static void BeginVertical(params GUILayoutOption[] options)
=> BeginVertical(GUIContent.none, GUIStyle.none, options);
public static void BeginVertical(GUIStyle style, params GUILayoutOption[] options)
=> BeginVertical(GUIContent.none, style, options);
public static void BeginVertical(GUIContent content, GUIStyle style, params GUILayoutOption[] options)
{
#if CPP
GUIUnstrip.BeginLayoutDirection(true, content, style, options);
#else
GUILayout.BeginVertical(content, style, options);
#endif
}
public static Rect GetLastRect()
{
#if CPP
return LayoutUtilityUnstrip.GetLastRect();
#else
return GUILayoutUtility.GetLastRect();
#endif
}
public static string TextField(string text, GUILayoutOption[] options)
{
#if CPP
return GUIUnstrip.TextField(text, options, false);
#else
return GUILayout.TextField(text, options);
#endif
}
public static string TextArea(string text, params GUILayoutOption[] options)
{
#if CPP
return GUIUnstrip.TextField(text, options, true);
#else
return GUILayout.TextArea(text, options);
#endif
}
public static Rect Window(int id, Rect rect, GUI.WindowFunction windowFunc, string title)
{
#if CPP
return GUI.Window(id, rect, windowFunc, GUIContent.Temp(title), GUI.skin.window);
#else
return GUI.Window(id, rect, windowFunc, title);
#endif
}
public static bool Button(Rect rect, string title)
{
#if CPP
return GUI.Button(rect, GUIContent.Temp(title), GUI.skin.button);
#else
return GUI.Button(rect, title);
#endif
}
public static void BringWindowToFront(int id)
{
#if CPP
GUIUnstrip.BringWindowToFront(id);
#else
GUI.BringWindowToFront(id);
#endif
}
public static Vector2 ScreenToGUIPoint(Vector2 screenPoint)
{
#if CPP
return GUIUnstrip.ScreenToGUIPoint(screenPoint);
#else
return GUIUtility.ScreenToGUIPoint(screenPoint);
#endif
}
public static void Space(float pixels)
{
#if CPP
GUIUnstrip.Space(pixels);
#else
GUILayout.Space(pixels);
#endif
}
public static bool RepeatButton(string text, params GUILayoutOption[] options)
{
#if CPP
return GUIUnstrip.DoRepeatButton(GUIContent.Temp(text), GUI.skin.button, options);
#else
return GUILayout.RepeatButton(text, options);
#endif
}
public static void BeginArea(Rect screenRect, GUIStyle style)
{
#if CPP
GUIUnstrip.BeginArea(screenRect, GUIContent.none, style);
#else
GUILayout.BeginArea(screenRect, style);
#endif
}
static public void EndArea()
{
#if CPP
GUIUnstrip.EndArea();
#else
GUILayout.EndArea();
#endif
}
public static Vector2 BeginScrollView(Vector2 scroll, params GUILayoutOption[] options)
{
#if CPP
return GUIUnstrip.BeginScrollView(scroll, options);
#else
return GUILayout.BeginScrollView(scroll, options);
#endif
}
public static void EndScrollView(bool handleScrollWheel = true)
{
#if CPP
GUIUnstrip.EndScrollView(handleScrollWheel);
#else
GUILayout.EndScrollView();
#endif
}
}
}

View File

@ -1,812 +0,0 @@
#if CPP
using System;
using System.Collections.Generic;
using System.Reflection;
using UnityEngine;
using UnityEngineInternal;
using UnhollowerRuntimeLib;
namespace Explorer.Unstrip.IMGUI
{
public class GUIUnstrip
{
#region Properties
public static int s_ScrollControlId;
public static bool ScrollFailed = false;
public static bool ManualUnstripFailed = false;
public static Stack<object> ScrollStack => m_scrollStack ?? GetScrollStack();
public static Stack<object> m_scrollStack;
//public static PropertyInfo m_scrollViewStatesInfo;
public static GUIStyle SpaceStyle => m_spaceStyle ?? GetSpaceStyle();
public static GUIStyle m_spaceStyle;
public static DateTime nextScrollStepTime;
public static MethodInfo ScreenToGuiPointMethod;
public static bool m_screenToGuiAttemped;
public static MethodInfo m_bringWindowToFrontMethod;
public static bool m_bringWindowFrontAttempted;
private static Stack<object> GetScrollStack()
{
m_scrollStack = new Stack<object>();
return m_scrollStack;
}
private static GUIStyle GetSpaceStyle()
{
try
{
m_spaceStyle = typeof(GUILayoutUtility)
.GetProperty("s_SpaceStyle")
.GetValue(null, null)
.Il2CppCast(typeof(GUIStyle))
as GUIStyle;
if (m_spaceStyle == null) throw new Exception();
}
catch { }
if (m_spaceStyle == null)
{
m_spaceStyle = new GUIStyle();
}
m_spaceStyle.stretchWidth = false;
return m_spaceStyle;
}
#endregion
#region GUILayout Methods
public static GUILayoutOption ExpandWidth(bool expand)
{
var ilValue = new Il2CppSystem.Int32
{
m_value = (!expand) ? 0 : 1
};
var option = new GUILayoutOption(GUILayoutOption.Type.stretchWidth, ilValue.BoxIl2CppObject());
return option;
}
public static GUILayoutOption ExpandHeight(bool expand)
{
var ilValue = new Il2CppSystem.Int32
{
m_value = (!expand) ? 0 : 1
};
var option = new GUILayoutOption(GUILayoutOption.Type.stretchHeight, ilValue.BoxIl2CppObject());
return option;
}
public static void BeginLayoutDirection(bool vertical, GUIContent content, GUIStyle style, GUILayoutOption[] options)
{
var g = BeginLayoutGroup(style, options, Il2CppType.Of<GUILayoutGroup>());
g.isVertical = vertical;
if (style != GUIStyle.none || content != GUIContent.none)
GUI.Box(g.rect, content, style);
}
public static GUILayoutGroup BeginLayoutGroup(GUIStyle style, GUILayoutOption[] options, Il2CppSystem.Type layoutType)
{
EventType type = Event.current.type;
GUILayoutGroup guilayoutGroup;
if (type != EventType.Used && type != EventType.Layout)
{
guilayoutGroup = GUILayoutUtility.current.topLevel.GetNext().TryCast<GUILayoutGroup>();
if (guilayoutGroup == null)
{
throw new ArgumentException("GUILayout: Mismatched LayoutGroup." + Event.current.type);
}
guilayoutGroup.ResetCursor();
}
else
{
guilayoutGroup = GUILayoutUtility.CreateGUILayoutGroupInstanceOfType(layoutType);
guilayoutGroup.style = style;
if (options != null)
{
guilayoutGroup.ApplyOptions(options);
}
GUILayoutUtility.current.topLevel.entries.Add(guilayoutGroup);
}
GUILayoutUtility.current.layoutGroups.Push(guilayoutGroup);
GUILayoutUtility.current.topLevel = guilayoutGroup;
return guilayoutGroup;
}
public static string TextField(string text, GUILayoutOption[] options, bool multiLine)
{
text = text ?? string.Empty;
var skin = multiLine ? GUI.skin.textArea : GUI.skin.textField;
int controlID = GUIUtility.GetControlID(FocusType.Keyboard);
GUIContent guicontent = GUIContent.Temp(text);
bool flag = GUIUtility.keyboardControl != controlID;
if (flag)
{
guicontent = GUIContent.Temp(text);
}
else
{
guicontent = GUIContent.Temp(text);
// guicontent = GUIContent.Temp(text + GUIUtility.compositionString);
}
Rect rect = LayoutUtilityUnstrip.GetRect(guicontent, skin, options);
bool flag2 = GUIUtility.keyboardControl == controlID;
if (flag2)
{
guicontent = GUIContent.Temp(text);
}
DoTextField(rect, controlID, guicontent, multiLine, -1, skin);
return guicontent.text;
}
internal static void DoTextField(Rect position, int id, GUIContent content, bool multiline, int maxLength, GUIStyle style)
{
if (GUIUtilityUnstrip.GetMonoStateObject(typeof(TextEditorUnstrip), id) is TextEditorUnstrip textEditor)
{
if (maxLength >= 0 && content.text.Length > maxLength)
{
content.text = content.text.Substring(0, maxLength);
}
textEditor.m_Content.text = content.text;
textEditor.SaveBackup();
textEditor.position = position;
textEditor.style = style;
textEditor.multiline = multiline;
textEditor.controlID = id;
textEditor.DetectFocusChange();
HandleTextFieldEventForDesktop(position, id, content, multiline, maxLength, style, textEditor);
textEditor.UpdateScrollOffsetIfNeeded(Event.current);
}
}
private static void HandleTextFieldEventForDesktop(Rect position, int id, GUIContent content, bool multiline, int maxLength,
GUIStyle style, TextEditorUnstrip editor)
{
var evt = Event.current;
bool change = false;
switch (evt.type)
{
case EventType.MouseDown:
if (position.Contains(evt.mousePosition))
{
GUIUtility.hotControl = id;
GUIUtility.keyboardControl = id;
editor.m_HasFocus = true;
editor.MoveCursorToPosition(Event.current.mousePosition);
if (Event.current.clickCount == 2 && GUI.skin.settings.doubleClickSelectsWord)
{
editor.SelectCurrentWord();
editor.DblClickSnap(TextEditorUnstrip.DblClickSnapping.WORDS);
editor.MouseDragSelectsWholeWords(true);
}
if (Event.current.clickCount == 3 && GUI.skin.settings.tripleClickSelectsLine)
{
editor.SelectCurrentParagraph();
editor.MouseDragSelectsWholeWords(true);
editor.DblClickSnap(TextEditorUnstrip.DblClickSnapping.PARAGRAPHS);
}
evt.Use();
}
break;
case EventType.MouseDrag:
if (GUIUtility.hotControl == id)
{
if (evt.shift)
editor.MoveCursorToPosition(Event.current.mousePosition);
else
editor.SelectToPosition(Event.current.mousePosition);
evt.Use();
}
break;
case EventType.MouseUp:
if (GUIUtility.hotControl == id)
{
editor.MouseDragSelectsWholeWords(false);
GUIUtility.hotControl = 0;
evt.Use();
}
break;
case EventType.KeyDown:
if (GUIUtility.keyboardControl != id)
return;
if (editor.HandleKeyEvent(evt))
{
evt.Use();
change = true;
content.text = editor.text;
break;
}
// Ignore tab & shift-tab in textfields
if (evt.keyCode == KeyCode.Tab || evt.character == '\t')
return;
char c = evt.character;
if (c == '\n' && !multiline && !evt.alt)
return;
// Simplest test: only allow the character if the display font supports it.
Font font = style.font;
if (!font)
font = GUI.skin.font;
if (font.HasCharacter(c) || c == '\n')
{
editor.Insert(c);
change = true;
break;
}
// On windows, keypresses also send events with keycode but no character. Eat them up here.
if (c == 0)
{
// if we have a composition string, make sure we clear the previous selection.
if (InputManager.compositionString.Length > 0)
{
editor.ReplaceSelection("");
change = true;
}
evt.Use();
}
// else {
// REALLY USEFUL:
// Debug.Log ("unhandled " +evt);
// evt.Use ();
// }
break;
case EventType.Repaint:
// If we have keyboard focus, draw the cursor
// TODO: check if this OpenGL view has keyboard focus
if (GUIUtility.keyboardControl != id)
{
style.Draw(position, content, id, false);
}
else
{
editor.DrawCursor(content.text);
}
break;
}
if (GUIUtility.keyboardControl == id)
GUIUtility.textFieldInput = true;
if (change)
{
GUI.changed = true;
content.text = editor.text;
if (maxLength >= 0 && content.text.Length > maxLength)
content.text = content.text.Substring(0, maxLength);
evt.Use();
}
}
public static bool DoRepeatButton(GUIContent content, GUIStyle style, GUILayoutOption[] options)
{
return GUI.DoRepeatButton(LayoutUtilityUnstrip.GetRect(content, style, options), content, style, FocusType.Passive);
}
public static void Space(float pixels)
{
if (GUILayoutUtility.current.topLevel.isVertical)
LayoutUtilityUnstrip.GetRect(0, pixels, SpaceStyle, new GUILayoutOption[] { GUILayout.Height(pixels) });
else
LayoutUtilityUnstrip.GetRect(pixels, 0, SpaceStyle, new GUILayoutOption[] { GUILayout.Width(pixels) });
if (Event.current.type == EventType.Layout)
{
GUILayoutUtility.current.topLevel.entries[GUILayoutUtility.current.topLevel.entries.Count - 1].consideredForMargin = false;
}
}
public static Vector2 ScreenToGUIPoint(Vector2 screenPoint)
{
if (!m_screenToGuiAttemped)
{
m_screenToGuiAttemped = true;
ScreenToGuiPointMethod = typeof(GUIUtility).GetMethod("ScreenToGUIPoint");
}
if (ScreenToGuiPointMethod == null)
{
throw new Exception("Couldn't get method 'GUIUtility.ScreenToGUIPoint'!");
}
return (Vector2)ScreenToGuiPointMethod.Invoke(null, new object[] { screenPoint });
}
public static void BringWindowToFront(int id)
{
if (!m_bringWindowFrontAttempted)
{
m_bringWindowFrontAttempted = true;
m_bringWindowToFrontMethod = typeof(GUI).GetMethod("BringWindowToFront");
}
if (m_bringWindowToFrontMethod == null)
{
throw new Exception("Couldn't get method 'GUIUtility.BringWindowToFront'!");
}
m_bringWindowToFrontMethod.Invoke(null, new object[] { id });
}
public static void BeginArea(Rect screenRect, GUIContent content, GUIStyle style)
{
var g = BeginLayoutArea(style, typeof(GUILayoutGroup));
if (Event.current.type == EventType.Layout)
{
g.resetCoords = true;
g.minWidth = g.maxWidth = screenRect.width;
g.minHeight = g.maxHeight = screenRect.height;
g.rect = Rect.MinMaxRect(screenRect.xMin, screenRect.yMin, g.rect.xMax, g.rect.yMax);
}
BeginGroup(g.rect, content, style);
}
internal static GUILayoutGroup BeginLayoutArea(GUIStyle style, Type layoutType)
{
EventType type = Event.current.type;
GUILayoutGroup guilayoutGroup;
if (type != EventType.Used && type != EventType.Layout)
{
guilayoutGroup = GUILayoutUtility.current.windows.GetNext().TryCast<GUILayoutGroup>();
guilayoutGroup.ResetCursor();
}
else
{
guilayoutGroup = (GUILayoutGroup)Activator.CreateInstance(layoutType);
guilayoutGroup.style = style;
GUILayoutUtility.current.windows.entries.Add(guilayoutGroup);
}
GUILayoutUtility.current.layoutGroups.Push(guilayoutGroup);
GUILayoutUtility.current.topLevel = guilayoutGroup;
return guilayoutGroup;
}
public static void BeginGroup(Rect position, GUIContent content, GUIStyle style)
{
BeginGroup(position, content, style, Vector2.zero);
}
internal static void BeginGroup(Rect position, GUIContent content, GUIStyle style, Vector2 scrollOffset)
{
int id = GUIUtility.GetControlID(GUI.s_BeginGroupHash, FocusType.Passive);
if (content != GUIContent.none || style != GUIStyle.none)
{
switch (Event.current.type)
{
case EventType.Repaint:
style.Draw(position, content, id);
break;
default:
if (position.Contains(Event.current.mousePosition))
GUIUtility.mouseUsed = true;
break;
}
}
GUIClip.Push(position, scrollOffset, Vector2.zero, false);
}
public static void EndArea()
{
if (Event.current.type == EventType.Used)
return;
GUILayoutUtility.current.layoutGroups.Pop();
GUILayoutUtility.current.topLevel = GUILayoutUtility.current.layoutGroups.Peek().TryCast<GUILayoutGroup>();
GUI.EndGroup();
}
#endregion
#region Scrolling
public static Vector2 BeginScrollView(Vector2 scroll, params GUILayoutOption[] options)
{
// First, just try normal way, may not have been stripped or was unstripped successfully.
if (!ScrollFailed)
{
try
{
return GUILayout.BeginScrollView(scroll, options);
}
catch
{
ScrollFailed = true;
}
}
// Try manual implementation.
if (!ManualUnstripFailed)
{
try
{
return BeginScrollView_ImplLayout(scroll,
false,
false,
GUI.skin.horizontalScrollbar,
GUI.skin.verticalScrollbar,
GUI.skin.scrollView,
options);
}
catch (Exception e)
{
ExplorerCore.Log("Exception on manual BeginScrollView: " + e.GetType() + ", " + e.Message + "\r\n" + e.StackTrace);
ManualUnstripFailed = true;
}
}
// Sorry! No scrolling for you.
return scroll;
}
internal static void EndScrollView(bool handleScrollWheel)
{
// Only end the scroll view for the relevant BeginScrollView option, if any.
if (!ScrollFailed)
{
GUILayout.EndScrollView();
}
else if (!ManualUnstripFailed)
{
GUILayoutUtility.EndLayoutGroup();
if (ScrollStack.Count <= 0) return;
var scrollExt = ScrollStack.Peek() as ScrollViewStateUnstrip;
//var state = ScrollStack.Peek().TryCast<ScrollViewState>();
//var scrollExt = Internal_ScrollViewState.FromPointer(state.Pointer);
//if (scrollExt == null) throw new Exception("Could not get scrollExt!");
GUIClip.Pop();
ScrollStack.Pop();
var position = scrollExt.position;
if (handleScrollWheel && Event.current.type == EventType.ScrollWheel && position.Contains(Event.current.mousePosition))
{
var pos = scrollExt.scrollPosition;
pos.x = Mathf.Clamp(scrollExt.scrollPosition.x + Event.current.delta.x * 20f, 0f, scrollExt.viewRect.width - scrollExt.visibleRect.width);
pos.y = Mathf.Clamp(scrollExt.scrollPosition.y + Event.current.delta.y * 20f, 0f, scrollExt.viewRect.height - scrollExt.visibleRect.height);
if (scrollExt.scrollPosition.x < 0f)
{
pos.x = 0f;
}
if (pos.y < 0f)
{
pos.y = 0f;
}
scrollExt.apply = true;
Event.current.Use();
}
}
}
private static Vector2 BeginScrollView_ImplLayout(Vector2 scrollPosition, bool alwaysShowHorizontal, bool alwaysShowVertical,
GUIStyle horizontalScrollbar, GUIStyle verticalScrollbar, GUIStyle background, params GUILayoutOption[] options)
{
var guiscrollGroup = GUILayoutUtility.BeginLayoutGroup(background, null, Il2CppType.Of<GUIScrollGroup>())
.TryCast<GUIScrollGroup>();
EventType type = Event.current.type;
if (type == EventType.Layout)
{
guiscrollGroup.resetCoords = true;
guiscrollGroup.isVertical = true;
guiscrollGroup.stretchWidth = 1;
guiscrollGroup.stretchHeight = 1;
guiscrollGroup.verticalScrollbar = verticalScrollbar;
guiscrollGroup.horizontalScrollbar = horizontalScrollbar;
guiscrollGroup.needsVerticalScrollbar = alwaysShowVertical;
guiscrollGroup.needsHorizontalScrollbar = alwaysShowHorizontal;
guiscrollGroup.ApplyOptions(options);
}
return BeginScrollView_Impl(guiscrollGroup.rect,
scrollPosition,
new Rect(0f, 0f, guiscrollGroup.clientWidth, guiscrollGroup.clientHeight),
alwaysShowHorizontal,
alwaysShowVertical,
horizontalScrollbar,
verticalScrollbar,
background
);
}
private static Vector2 BeginScrollView_Impl(Rect position, Vector2 scrollPosition, Rect viewRect, bool alwaysShowHorizontal,
bool alwaysShowVertical, GUIStyle horizontalScrollbar, GUIStyle verticalScrollbar, GUIStyle background)
{
// GUIUtility.CheckOnGUI();
int controlID = GUIUtility.GetControlID(GUI.s_ScrollviewHash, FocusType.Passive);
ScrollViewStateUnstrip scrollExt;
try
{
scrollExt = (ScrollViewStateUnstrip)GUIUtilityUnstrip.GetMonoStateObject(typeof(ScrollViewStateUnstrip), controlID);
}
catch
{
return Vector2.zero;
}
bool apply = scrollExt.apply;
if (apply)
{
scrollPosition = scrollExt.scrollPosition;
scrollExt.apply = false;
}
scrollExt.position = position;
scrollExt.scrollPosition = scrollPosition;
scrollExt.visibleRect = scrollExt.viewRect = viewRect;
var rect = scrollExt.visibleRect;
rect.width = position.width;
rect.height = position.height;
ScrollStack.Push(scrollExt);
Rect screenRect = new Rect(position.x, position.y, position.width, position.height);
EventType type = Event.current.type;
if (type != EventType.Layout)
{
if (type != EventType.Used)
{
bool flag = alwaysShowVertical;
bool flag2 = alwaysShowHorizontal;
if (flag2 || viewRect.width > screenRect.width)
{
rect.height = position.height - horizontalScrollbar.fixedHeight + (float)horizontalScrollbar.margin.top;
screenRect.height -= horizontalScrollbar.fixedHeight + (float)horizontalScrollbar.margin.top;
flag2 = true;
}
if (flag || viewRect.height > screenRect.height)
{
rect.width = position.width - verticalScrollbar.fixedWidth + (float)verticalScrollbar.margin.left;
screenRect.width -= verticalScrollbar.fixedWidth + (float)verticalScrollbar.margin.left;
flag = true;
if (!flag2 && viewRect.width > screenRect.width)
{
rect.height = position.height - horizontalScrollbar.fixedHeight + (float)horizontalScrollbar.margin.top;
screenRect.height -= horizontalScrollbar.fixedHeight + (float)horizontalScrollbar.margin.top;
flag2 = true;
}
}
if (Event.current.type == EventType.Repaint && background != GUIStyle.none)
{
background.Draw(position, position.Contains(Event.current.mousePosition), false, flag2 && flag, false);
}
if (flag2 && horizontalScrollbar != GUIStyle.none)
{
scrollPosition.x = HorizontalScroll(
new Rect(
position.x,
position.yMax - horizontalScrollbar.fixedHeight,
screenRect.width,
horizontalScrollbar.fixedHeight),
scrollPosition.x,
Mathf.Min(screenRect.width, viewRect.width),
0f,
viewRect.width,
horizontalScrollbar
);
}
else
{
GUIUtility.GetControlID(GUI.s_SliderHash, FocusType.Passive);
GUIUtility.GetControlID(GUI.s_RepeatButtonHash, FocusType.Passive);
GUIUtility.GetControlID(GUI.s_RepeatButtonHash, FocusType.Passive);
scrollPosition.x = ((horizontalScrollbar == GUIStyle.none)
? Mathf.Clamp(scrollPosition.x, 0f, Mathf.Max(viewRect.width - position.width, 0f))
: 0f);
}
if (flag && verticalScrollbar != GUIStyle.none)
{
scrollPosition.y = VerticalScroll(
new Rect(
screenRect.xMax + (float)verticalScrollbar.margin.left,
screenRect.y,
verticalScrollbar.fixedWidth,
screenRect.height),
scrollPosition.y,
Mathf.Min(screenRect.height, viewRect.height),
0f,
viewRect.height,
verticalScrollbar
);
}
else
{
GUIUtility.GetControlID(GUI.s_SliderHash, FocusType.Passive);
GUIUtility.GetControlID(GUI.s_RepeatButtonHash, FocusType.Passive);
GUIUtility.GetControlID(GUI.s_RepeatButtonHash, FocusType.Passive);
scrollPosition.y = ((verticalScrollbar == GUIStyle.none)
? Mathf.Clamp(scrollPosition.y, 0f, Mathf.Max(viewRect.height - position.height, 0f))
: 0f);
}
}
}
else
{
GUIUtility.GetControlID(GUI.s_SliderHash, FocusType.Passive);
GUIUtility.GetControlID(GUI.s_RepeatButtonHash, FocusType.Passive);
GUIUtility.GetControlID(GUI.s_RepeatButtonHash, FocusType.Passive);
GUIUtility.GetControlID(GUI.s_SliderHash, FocusType.Passive);
GUIUtility.GetControlID(GUI.s_RepeatButtonHash, FocusType.Passive);
GUIUtility.GetControlID(GUI.s_RepeatButtonHash, FocusType.Passive);
}
GUIClip.Push(screenRect,
new Vector2(
Mathf.Round(-scrollPosition.x - viewRect.x),
Mathf.Round(-scrollPosition.y - viewRect.y)),
Vector2.zero,
false
);
return scrollPosition;
}
public static float HorizontalScroll(Rect position, float value, float size, float leftValue, float rightValue, GUIStyle style)
{
return Scroller(position, value, size, leftValue, rightValue, style,
GUI.skin.GetStyle(style.name + "thumb"),
GUI.skin.GetStyle(style.name + "leftbutton"),
GUI.skin.GetStyle(style.name + "rightbutton"),
true);
}
public static float VerticalScroll(Rect position, float value, float size, float topValue, float bottomValue, GUIStyle style)
{
return Scroller(position, value, size, topValue, bottomValue, style,
GUI.skin.GetStyle(style.name + "thumb"),
GUI.skin.GetStyle(style.name + "upbutton"),
GUI.skin.GetStyle(style.name + "downbutton"),
false);
}
private static float Scroller(Rect position, float value, float size, float leftValue, float rightValue, GUIStyle slider,
GUIStyle thumb, GUIStyle leftButton, GUIStyle rightButton, bool horiz)
{
GUIUtility.CheckOnGUI();
int controlID = GUIUtility.GetControlID(GUI.s_SliderHash, FocusType.Passive, position);
Rect position2;
Rect rect;
Rect rect2;
if (horiz)
{
position2 = new Rect(position.x + leftButton.fixedWidth,
position.y,
position.width - leftButton.fixedWidth - rightButton.fixedWidth,
position.height);
rect = new Rect(position.x, position.y, leftButton.fixedWidth, position.height);
rect2 = new Rect(position.xMax - rightButton.fixedWidth, position.y, rightButton.fixedWidth, position.height);
}
else
{
position2 = new Rect(position.x,
position.y + leftButton.fixedHeight,
position.width,
position.height - leftButton.fixedHeight - rightButton.fixedHeight);
rect = new Rect(position.x, position.y, position.width, leftButton.fixedHeight);
rect2 = new Rect(position.x, position.yMax - rightButton.fixedHeight, position.width, rightButton.fixedHeight);
}
value = Slider(position2, value, size, leftValue, rightValue, slider, thumb, horiz, controlID);
bool flag = Event.current.type == EventType.MouseUp;
if (ScrollerRepeatButton(controlID, rect, leftButton))
{
value -= 10f * ((leftValue >= rightValue) ? -1f : 1f);
}
if (ScrollerRepeatButton(controlID, rect2, rightButton))
{
value += 10f * ((leftValue >= rightValue) ? -1f : 1f);
}
if (flag && Event.current.type == EventType.Used)
{
s_ScrollControlId = 0;
}
if (leftValue < rightValue)
{
value = Mathf.Clamp(value, leftValue, rightValue - size);
}
else
{
value = Mathf.Clamp(value, rightValue, leftValue - size);
}
return value;
}
public static float Slider(Rect position, float value, float size, float start, float end, GUIStyle slider,
GUIStyle thumb, bool horiz, int id)
{
if (id == 0)
{
id = GUIUtility.GetControlID(GUI.s_SliderHash, FocusType.Passive, position);
}
var sliderHandler = new SliderHandlerUnstrip(position, value, size, start, end, slider, thumb, horiz, id);
return sliderHandler.Handle();
}
private static bool ScrollerRepeatButton(int scrollerID, Rect rect, GUIStyle style)
{
bool result = false;
if (GUI.DoRepeatButton(rect, GUIContent.none, style, FocusType.Passive))
{
bool flag = s_ScrollControlId != scrollerID;
s_ScrollControlId = scrollerID;
if (flag)
{
result = true;
nextScrollStepTime = DateTime.Now.AddMilliseconds(250.0);
}
else if (DateTime.Now >= nextScrollStepTime)
{
result = true;
nextScrollStepTime = DateTime.Now.AddMilliseconds(30.0);
}
if (Event.current.type == EventType.Repaint)
{
GUI.InternalRepaintEditorWindow();
}
}
return result;
}
#endregion
}
#region Extensions
public static class Extensions
{
public static Rect Unstripped_GetLast(this GUILayoutGroup group)
{
Rect result;
if (group.m_Cursor > 0 && group.m_Cursor <= group.entries.Count)
{
GUILayoutEntry guilayoutEntry = group.entries[group.m_Cursor - 1];
result = guilayoutEntry.rect;
}
else
{
result = GUILayoutEntry.kDummyRect;
}
return result;
}
}
#endregion
}
#endif

View File

@ -1,67 +0,0 @@
#if CPP
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using Explorer.Helpers;
namespace Explorer.Unstrip.IMGUI
{
public class GUIUtilityUnstrip
{
public static Dictionary<int, object> MonoStateCache = new Dictionary<int, object>();
public static object GetMonoStateObject(Type type, int controlID)
{
if (!MonoStateCache.ContainsKey(controlID))
{
MonoStateCache.Add(controlID, Activator.CreateInstance(type));
}
return MonoStateCache[controlID];
}
public static Dictionary<int, Il2CppSystem.Object> StateCache => m_stateCacheDict ?? GetStateCacheDict();
public static Dictionary<int, Il2CppSystem.Object> m_stateCacheDict;
public static Il2CppSystem.Object GetStateObject(Il2CppSystem.Type type, int controlID)
{
Il2CppSystem.Object obj;
if (StateCache.ContainsKey(controlID))
{
obj = StateCache[controlID];
}
else
{
obj = Il2CppSystem.Activator.CreateInstance(type);
StateCache.Add(controlID, obj);
}
return obj;
}
private static Dictionary<int, Il2CppSystem.Object> GetStateCacheDict()
{
if (m_stateCacheDict == null)
{
try
{
m_stateCacheDict = ReflectionHelpers.GetTypeByName("UnityEngine.GUIStateObjects")
.GetProperty("s_StateCache")
.GetValue(null, null)
as Dictionary<int, Il2CppSystem.Object>;
if (m_stateCacheDict == null) throw new Exception();
}
catch
{
m_stateCacheDict = new Dictionary<int, Il2CppSystem.Object>();
}
}
return m_stateCacheDict;
}
}
}
#endif

View File

@ -1,91 +0,0 @@
#if CPP
using UnityEngine;
namespace Explorer.Unstrip.IMGUI
{
public class LayoutUtilityUnstrip
{
public static Rect GetRect(float width, float height, GUIStyle style, params GUILayoutOption[] options)
{
switch (Event.current.type)
{
case EventType.Layout:
GUILayoutUtility.current.topLevel.Add(new GUILayoutEntry(width, width, height, height, style, options));
return GUILayoutUtility.kDummyRect;
case EventType.Used:
return GUILayoutUtility.kDummyRect;
default:
return GUILayoutUtility.current.topLevel.GetNext().rect;
}
}
public static Rect GetRect(GUIContent content, GUIStyle style, params GUILayoutOption[] options)
{
return DoGetRect(content, style, options);
}
static Rect DoGetRect(GUIContent content, GUIStyle style, GUILayoutOption[] options)
{
switch (Event.current.type)
{
case EventType.Layout:
if (style.isHeightDependantOnWidth)
{
GUILayoutUtility.current.topLevel.Add(new GUIWordWrapSizer(style, content, options));
}
else
{
Vector2 sizeConstraints = new Vector2(0, 0);
if (options != null)
{
foreach (var option in options)
{
if (float.TryParse(option.value.ToString(), out float f))
{
switch (option.type)
{
case GUILayoutOption.Type.maxHeight:
sizeConstraints.y = f;
break;
case GUILayoutOption.Type.maxWidth:
sizeConstraints.x = f;
break;
}
}
}
}
Vector2 size = style.CalcSizeWithConstraints(content, sizeConstraints);
// This is needed on non-integer scale ratios to avoid errors to accumulate in further layout calculations
size.x = Mathf.Ceil(size.x);
size.y = Mathf.Ceil(size.y);
GUILayoutUtility.current.topLevel.Add(new GUILayoutEntry(size.x, size.x, size.y, size.y, style, options));
}
return GUILayoutUtility.kDummyRect;
case EventType.Used:
return GUILayoutUtility.kDummyRect;
default:
var entry = GUILayoutUtility.current.topLevel.GetNext();
//GUIDebugger.LogLayoutEntry(entry.rect, entry.marginLeft, entry.marginRight, entry.marginTop, entry.marginBottom, entry.style);
return entry.rect;
}
}
public static Rect GetLastRect()
{
EventType type = Event.current.type;
Rect last;
if (type != EventType.Layout && type != EventType.Used)
{
last = GUILayoutUtility.current.topLevel.Unstripped_GetLast();
}
else
{
last = GUILayoutUtility.kDummyRect;
}
return last;
}
}
}
#endif

View File

@ -1,89 +0,0 @@
#if CPP
using System;
using System.Collections.Generic;
using UnityEngine;
namespace Explorer.Unstrip.IMGUI
{
public class ScrollViewStateUnstrip
{
public Rect position;
public Rect visibleRect;
public Rect viewRect;
public Vector2 scrollPosition;
public bool apply;
public void ScrollTo(Rect pos)
{
this.ScrollTowards(pos, float.PositiveInfinity);
}
public bool ScrollTowards(Rect pos, float maxDelta)
{
Vector2 b = this.ScrollNeeded(pos);
bool result;
if (b.sqrMagnitude < 0.0001f)
{
result = false;
}
else if (maxDelta == 0f)
{
result = true;
}
else
{
if (b.magnitude > maxDelta)
{
b = b.normalized * maxDelta;
}
this.scrollPosition += b;
this.apply = true;
result = true;
}
return result;
}
private Vector2 ScrollNeeded(Rect pos)
{
Rect rect = this.visibleRect;
rect.x += this.scrollPosition.x;
rect.y += this.scrollPosition.y;
float num = pos.width - this.visibleRect.width;
if (num > 0f)
{
pos.width -= num;
pos.x += num * 0.5f;
}
num = pos.height - this.visibleRect.height;
if (num > 0f)
{
pos.height -= num;
pos.y += num * 0.5f;
}
Vector2 zero = Vector2.zero;
if (pos.xMax > rect.xMax)
{
zero.x += pos.xMax - rect.xMax;
}
else if (pos.xMin < rect.xMin)
{
zero.x -= rect.xMin - pos.xMin;
}
if (pos.yMax > rect.yMax)
{
zero.y += pos.yMax - rect.yMax;
}
else if (pos.yMin < rect.yMin)
{
zero.y -= rect.yMin - pos.yMin;
}
Rect rect2 = this.viewRect;
rect2.width = Mathf.Max(rect2.width, this.visibleRect.width);
rect2.height = Mathf.Max(rect2.height, this.visibleRect.height);
zero.x = Mathf.Clamp(zero.x, rect2.xMin - this.scrollPosition.x, rect2.xMax - this.visibleRect.width - this.scrollPosition.x);
zero.y = Mathf.Clamp(zero.y, rect2.yMin - this.scrollPosition.y, rect2.yMax - this.visibleRect.height - this.scrollPosition.y);
return zero;
}
}
}
#endif

View File

@ -1,411 +0,0 @@
#if CPP
using System;
using UnhollowerRuntimeLib;
using UnityEngine;
namespace Explorer.Unstrip.IMGUI
{
public struct SliderHandlerUnstrip
{
public static int ScrollTroughSide
{
get
{
if (!m_getScrollTroughSideFailed)
{
try
{
return GUI.scrollTroughSide;
}
catch
{
m_getScrollTroughSideFailed = true;
}
}
return m_manualScrollTrough;
}
set
{
if (!m_setScrollTroughSideFailed)
{
try
{
GUI.scrollTroughSide = value;
return;
}
catch
{
m_setScrollTroughSideFailed = true;
}
}
m_manualScrollTrough = value;
}
}
private static bool m_getScrollTroughSideFailed;
private static bool m_setScrollTroughSideFailed;
private static int m_manualScrollTrough;
private readonly Rect position;
private readonly float currentValue;
private readonly float size;
private readonly float start;
private readonly float end;
private readonly GUIStyle slider;
private readonly GUIStyle thumb;
private readonly bool horiz;
private readonly int id;
public SliderHandlerUnstrip(Rect position, float currentValue, float size, float start,
float end, GUIStyle slider, GUIStyle thumb, bool horiz, int id)
{
this.position = position;
this.currentValue = currentValue;
this.size = size;
this.start = start;
this.end = end;
this.slider = slider;
this.thumb = thumb;
this.horiz = horiz;
this.id = id;
}
public float Handle()
{
float result;
if (this.slider == null || this.thumb == null)
{
result = this.currentValue;
}
else
{
switch (this.CurrentEventType())
{
case EventType.MouseDown:
return this.OnMouseDown();
case EventType.MouseUp:
return this.OnMouseUp();
case EventType.MouseDrag:
return this.OnMouseDrag();
case EventType.Repaint:
return this.OnRepaint();
}
result = this.currentValue;
}
return result;
}
private float OnMouseDown()
{
float result;
if (!this.position.Contains(this.CurrentEvent().mousePosition) || this.IsEmptySlider())
{
result = this.currentValue;
}
else
{
ScrollTroughSide = 0;
GUIUtility.hotControl = this.id;
this.CurrentEvent().Use();
if (this.ThumbSelectionRect().Contains(this.CurrentEvent().mousePosition))
{
this.StartDraggingWithValue(this.ClampedCurrentValue());
result = this.currentValue;
}
else
{
GUI.changed = true;
if (this.SupportsPageMovements())
{
var state = GetSliderState();
state.isDragging = false;
GUIUnstrip.nextScrollStepTime = DateTime.Now.AddMilliseconds(250.0);
ScrollTroughSide = this.CurrentScrollTroughSide();
result = this.PageMovementValue();
}
else
{
float num = this.ValueForCurrentMousePosition();
this.StartDraggingWithValue(num);
result = this.Clamp(num);
}
}
}
return result;
}
private float OnMouseDrag()
{
float result;
if (GUIUtility.hotControl != this.id)
{
result = this.currentValue;
}
else
{
var state = GetSliderState();
if (!state.isDragging)
{
result = this.currentValue;
}
else
{
GUI.changed = true;
this.CurrentEvent().Use();
float num = this.MousePosition() - state.dragStartPos;
float value = state.dragStartValue + num / this.ValuesPerPixel();
result = this.Clamp(value);
}
}
return result;
}
private float OnMouseUp()
{
if (GUIUtility.hotControl == this.id)
{
this.CurrentEvent().Use();
GUIUtility.hotControl = 0;
}
return this.currentValue;
}
private float OnRepaint()
{
this.slider.Draw(this.position, GUIContent.none, this.id);
if (!this.IsEmptySlider() && this.currentValue >= this.MinValue() && this.currentValue <= this.MaxValue())
{
this.thumb.Draw(this.ThumbRect(), GUIContent.none, this.id);
}
float result;
if (GUIUtility.hotControl != this.id || !this.position.Contains(this.CurrentEvent().mousePosition) || this.IsEmptySlider())
{
result = this.currentValue;
}
else if (this.ThumbRect().Contains(this.CurrentEvent().mousePosition))
{
if (ScrollTroughSide != 0)
{
GUIUtility.hotControl = 0;
}
result = this.currentValue;
}
else
{
GUI.InternalRepaintEditorWindow();
if (DateTime.Now < GUIUnstrip.nextScrollStepTime)
{
result = this.currentValue;
}
else if (this.CurrentScrollTroughSide() != ScrollTroughSide)
{
result = this.currentValue;
}
else
{
GUIUnstrip.nextScrollStepTime = DateTime.Now.AddMilliseconds(30.0);
if (this.SupportsPageMovements())
{
GetSliderState().isDragging = false;
GUI.changed = true;
result = this.PageMovementValue();
}
else
{
result = this.ClampedCurrentValue();
}
}
}
return result;
}
private EventType CurrentEventType()
{
return this.CurrentEvent().GetTypeForControl(this.id);
}
private int CurrentScrollTroughSide()
{
float num = (!this.horiz) ? this.CurrentEvent().mousePosition.y : this.CurrentEvent().mousePosition.x;
float num2 = (!this.horiz) ? this.ThumbRect().y : this.ThumbRect().x;
return (num <= num2) ? -1 : 1;
}
private bool IsEmptySlider()
{
return this.start == this.end;
}
private bool SupportsPageMovements()
{
return this.size != 0f && GUI.usePageScrollbars;
}
private float PageMovementValue()
{
float num = this.currentValue;
int num2 = (this.start <= this.end) ? 1 : -1;
if (this.MousePosition() > this.PageUpMovementBound())
{
num += this.size * (float)num2 * 0.9f;
}
else
{
num -= this.size * (float)num2 * 0.9f;
}
return this.Clamp(num);
}
private float PageUpMovementBound()
{
float result;
if (this.horiz)
{
result = this.ThumbRect().xMax - this.position.x;
}
else
{
result = this.ThumbRect().yMax - this.position.y;
}
return result;
}
private Event CurrentEvent()
{
return Event.current;
}
private float ValueForCurrentMousePosition()
{
float result;
if (this.horiz)
{
result = (this.MousePosition() - this.ThumbRect().width * 0.5f) / this.ValuesPerPixel() + this.start - this.size * 0.5f;
}
else
{
result = (this.MousePosition() - this.ThumbRect().height * 0.5f) / this.ValuesPerPixel() + this.start - this.size * 0.5f;
}
return result;
}
private float Clamp(float value)
{
return Mathf.Clamp(value, this.MinValue(), this.MaxValue());
}
private Rect ThumbSelectionRect()
{
return this.ThumbRect();
}
private void StartDraggingWithValue(float dragStartValue)
{
var state = GetSliderState();
state.dragStartPos = this.MousePosition();
state.dragStartValue = dragStartValue;
state.isDragging = true;
}
private SliderStateUnstrip GetSliderState()
{
return (SliderStateUnstrip)GUIUtilityUnstrip.GetMonoStateObject(typeof(SliderStateUnstrip), this.id);
}
private Rect ThumbRect()
{
return (!this.horiz) ? this.VerticalThumbRect() : this.HorizontalThumbRect();
}
private Rect VerticalThumbRect()
{
float num = this.ValuesPerPixel();
Rect result;
if (this.start < this.end)
{
result = new Rect(this.position.x + (float)this.slider.padding.left, (this.ClampedCurrentValue() - this.start) * num + this.position.y + (float)this.slider.padding.top, this.position.width - (float)this.slider.padding.horizontal, this.size * num + this.ThumbSize());
}
else
{
result = new Rect(this.position.x + (float)this.slider.padding.left, (this.ClampedCurrentValue() + this.size - this.start) * num + this.position.y + (float)this.slider.padding.top, this.position.width - (float)this.slider.padding.horizontal, this.size * -num + this.ThumbSize());
}
return result;
}
private Rect HorizontalThumbRect()
{
float num = this.ValuesPerPixel();
Rect result;
if (this.start < this.end)
{
result = new Rect((this.ClampedCurrentValue() - this.start) * num + this.position.x + (float)this.slider.padding.left, this.position.y + (float)this.slider.padding.top, this.size * num + this.ThumbSize(), this.position.height - (float)this.slider.padding.vertical);
}
else
{
result = new Rect((this.ClampedCurrentValue() + this.size - this.start) * num + this.position.x + (float)this.slider.padding.left, this.position.y, this.size * -num + this.ThumbSize(), this.position.height);
}
return result;
}
private float ClampedCurrentValue()
{
return this.Clamp(this.currentValue);
}
private float MousePosition()
{
float result;
if (this.horiz)
{
result = this.CurrentEvent().mousePosition.x - this.position.x;
}
else
{
result = this.CurrentEvent().mousePosition.y - this.position.y;
}
return result;
}
private float ValuesPerPixel()
{
float result;
if (this.horiz)
{
result = (this.position.width - (float)this.slider.padding.horizontal - this.ThumbSize()) / (this.end - this.start);
}
else
{
result = (this.position.height - (float)this.slider.padding.vertical - this.ThumbSize()) / (this.end - this.start);
}
return result;
}
private float ThumbSize()
{
float result;
if (this.horiz)
{
result = ((this.thumb.fixedWidth == 0f) ? ((float)this.thumb.padding.horizontal) : this.thumb.fixedWidth);
}
else
{
result = ((this.thumb.fixedHeight == 0f) ? ((float)this.thumb.padding.vertical) : this.thumb.fixedHeight);
}
return result;
}
private float MaxValue()
{
return Mathf.Max(this.start, this.end) - this.size;
}
private float MinValue()
{
return Mathf.Min(this.start, this.end);
}
}
}
#endif

View File

@ -1,14 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Explorer.Unstrip.IMGUI
{
public class SliderStateUnstrip
{
public float dragStartPos;
public float dragStartValue;
public bool isDragging;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -6,12 +6,12 @@ using System.Text;
using UnhollowerBaseLib;
using UnityEngine;
using System.IO;
using Explorer.Helpers;
using ExplorerBeta.Helpers;
using System.Runtime.InteropServices;
using Unity.Collections;
using Unity.Collections.LowLevel.Unsafe;
namespace Explorer.Unstrip.ImageConversion
namespace ExplorerBeta.Unstrip.ImageConversion
{
public static class ImageConversionUnstrip
{

View File

@ -3,12 +3,12 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using Explorer.Helpers;
using ExplorerBeta.Helpers;
#if CPP
using UnhollowerBaseLib;
#endif
namespace Explorer.Unstrip.LayerMasks
namespace ExplorerBeta.Unstrip.LayerMasks
{
public static class LayerMaskUnstrip
{

View File

@ -2,13 +2,13 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Explorer.Helpers;
using ExplorerBeta.Helpers;
using UnityEngine;
#if CPP
using UnhollowerBaseLib;
#endif
namespace Explorer.Unstrip.Resources
namespace ExplorerBeta.Unstrip.Resources
{
public class ResourcesUnstrip
{

View File

@ -3,12 +3,12 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Explorer.Helpers;
using ExplorerBeta.Helpers;
using UnhollowerBaseLib;
using UnityEngine;
using UnityEngine.SceneManagement;
namespace Explorer.Unstrip.Scenes
namespace ExplorerBeta.Unstrip.Scenes
{
public class SceneUnstrip
{