Compare commits

...

2 Commits
1.6.5 ... 1.6.6

Author SHA1 Message Date
6ea435deee 1.6.6
* Added better support for Properties with index parameters, can now support multiple parameters and non-int parameters.
* Parameters are now formatted in a more expected fashion (in the `(Type arg0, Type arg1)` format).
* Got rid of all the ugly yellow text.
* Cleaned up some minor GUI display / layout issues.
* Refactored some of CacheMethod into CacheObjectBase
2020-09-09 19:15:47 +10:00
94f749342d Update .gitignore 2020-09-09 00:53:31 +10:00
17 changed files with 346 additions and 225 deletions

1
.gitignore vendored
View File

@ -9,6 +9,7 @@
*.user
*.userosscache
*.sln.docstates
*/mcs-unity*
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs

View File

@ -97,12 +97,11 @@ CppExplorer can force the mouse to be visible and unlocked when the menu is open
If you'd like to build this yourself, everything you need (other than MelonLoader) is included with this repository, there is no need for recursive cloning etc.
1. Install MelonLoader for your game.
2. Download this repository and open the `CppExplorer.sln` file in the `src` folder.
3. In Visual Studio, right-click the CppExplorer C# Project in the solution browser and click "Unload Project".
4. Right-click the "CppExplorer (unloaded)" and select "Edit Project File".
5. Scroll down until you see the `<ItemGroup>` containing the References.
6. Fix all of the paths in the `..\Steam\` directory for your game (use the full path if you need to).
7. Reload the project and everything should be working, you can now build and run it.
2. Open the `src\CppExplorer.csproj` file in a text editor.
3. Scroll down until you see the `<ItemGroup>` containing the References.
4. Fix all of the paths in the `..\Steam\` directory for your game (use the full path if you need to).
5. Open the `src\CppExplorer.sln` project and build it.
6. The dll is built to the `Release\` folder in the root of the repository.
## Credits
@ -110,4 +109,4 @@ Written by Sinai.
Thanks to:
* [ManlyMarco](https://github.com/ManlyMarco) for their [Runtime Unity Editor](https://github.com/ManlyMarco/RuntimeUnityEditor), which I used for the REPL Console and the "Find instances" snippet, and the UI style.
* [denikson](https://github.com/denikson) for [mcs-unity](https://github.com/denikson/mcs-unity). I commented out the `SkipVisibilityExt` constructor in `mcs.dll` since it was causing an exception with the Hook it attempted.
* [denikson](https://github.com/denikson) for [mcs-unity](https://github.com/denikson/mcs-unity). I commented out the `SkipVisibilityExt` constructor since it was causing an exception with the Hook it attempted.

BIN
img.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 449 KiB

After

Width:  |  Height:  |  Size: 524 KiB

View File

@ -19,8 +19,12 @@ namespace Explorer
public MemberInfo MemInfo { get; set; }
public Type DeclaringType { get; set; }
public object DeclaringInstance { get; set; }
public int PropertyIndex { get; private set; }
private string m_propertyIndexInput = "0";
public bool HasParameters => m_arguments != null && m_arguments.Length > 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 string ReflectionException { get; set; }
@ -43,7 +47,6 @@ namespace Explorer
// ===== Abstract/Virtual Methods ===== //
public virtual void Init() { }
public abstract void DrawValue(Rect window, float width);
// ===== Static Methods ===== //
@ -114,12 +117,21 @@ namespace Explorer
{
CacheObjectBase holder;
var pi = memberInfo as PropertyInfo;
var mi = memberInfo as MethodInfo;
// if PropertyInfo, check if can process args
if (pi != null && !CanProcessArgs(pi.GetIndexParameters()))
{
return null;
}
// This is pretty ugly, could probably make a cleaner implementation.
// However, the only cleaner ways I can think of are slower and probably not worth it.
// Note: the order is somewhat important.
if (memberInfo is MethodInfo mi)
if (mi != null)
{
if (CacheMethod.CanEvaluate(mi))
{
@ -181,7 +193,21 @@ namespace Explorer
holder.MemInfo = memberInfo;
holder.DeclaringType = memberInfo.DeclaringType;
holder.DeclaringInstance = declaringInstance;
}
if (pi != null)
{
holder.m_arguments = pi.GetIndexParameters();
}
else if (mi != null)
{
holder.m_arguments = mi.GetParameters();
}
holder.m_argumentInput = new string[holder.m_arguments.Length];
if (!holder.HasParameters)
{
holder.UpdateValue();
}
@ -190,11 +216,57 @@ namespace Explorer
return holder;
}
public static bool CanProcessArgs(ParameterInfo[] parameters)
{
foreach (var param in parameters)
{
if (!param.ParameterType.IsPrimitive && param.ParameterType != typeof(string))
{
return false;
}
}
return true;
}
// ======== Instance Methods =========
public object[] ParseArguments()
{
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 == typeof(string))
{
parsedArgs.Add(input);
}
else
{
try
{
parsedArgs.Add(type.GetMethod("Parse", new Type[] { typeof(string) }).Invoke(null, new object[] { input }));
}
catch
{
//MelonLogger.Log($"Unable to parse '{input}' to type '{type.Name}'");
// try add a null arg i guess
parsedArgs.Add(null);
//break;
}
}
}
return parsedArgs.ToArray();
}
public virtual void UpdateValue()
{
if (MemInfo == null || !string.IsNullOrEmpty(ReflectionException))
if (MemInfo == null)
{
return;
}
@ -209,13 +281,11 @@ namespace Explorer
else if (MemInfo.MemberType == MemberTypes.Property)
{
var pi = MemInfo as PropertyInfo;
bool isStatic = pi.GetAccessors()[0].IsStatic;
var target = isStatic ? null : DeclaringInstance;
var target = pi.GetAccessors()[0].IsStatic ? null : DeclaringInstance;
if (pi.GetIndexParameters().Length > 0)
if (HasParameters)
{
var indexes = new object[] { PropertyIndex };
Value = pi.GetValue(target, indexes);
Value = pi.GetValue(target, ParseArguments());
}
else
{
@ -224,6 +294,8 @@ namespace Explorer
}
ReflectionException = null;
m_evaluated = true;
m_isEvaluating = false;
}
catch (Exception e)
{
@ -244,10 +316,9 @@ namespace Explorer
{
var pi = MemInfo as PropertyInfo;
if (pi.GetIndexParameters().Length > 0)
if (HasParameters)
{
var indexes = new object[] { PropertyIndex };
pi.SetValue(pi.GetAccessors()[0].IsStatic ? null : DeclaringInstance, Value, indexes);
pi.SetValue(pi.GetAccessors()[0].IsStatic ? null : DeclaringInstance, Value, ParseArguments());
}
else
{
@ -264,6 +335,7 @@ namespace Explorer
// ========= Instance Gui Draw ==========
public const float MAX_LABEL_WIDTH = 400f;
public const string EVALUATE_LABEL = "<color=lime>Evaluate</color>";
public static void ClampLabelWidth(Rect window, ref float labelWidth)
{
@ -282,19 +354,86 @@ namespace Explorer
if (MemInfo != null)
{
var name = RichTextName;
if (MemInfo is PropertyInfo pi && pi.GetIndexParameters().Length > 0)
{
name += $"[{PropertyIndex}]";
}
GUILayout.Label(name, new GUILayoutOption[] { GUILayout.Width(labelWidth) });
GUILayout.Label(RichTextName, new GUILayoutOption[] { GUILayout.Width(labelWidth) });
}
else
{
GUILayout.Space(labelWidth);
}
var cm = this as CacheMethod;
if (HasParameters)
{
GUILayout.BeginVertical(null);
if (m_isEvaluating)
{
for (int i = 0; i < m_arguments.Length; i++)
{
var name = m_arguments[i].Name;
var input = m_argumentInput[i];
var type = m_arguments[i].ParameterType.Name;
GUILayout.BeginHorizontal(null);
GUILayout.Label(i.ToString(), new GUILayoutOption[] { GUILayout.Width(30) });
m_argumentInput[i] = GUILayout.TextField(input, new GUILayoutOption[] { GUILayout.Width(150) });
GUILayout.Label("<color=#2df7b2>" + type + "</color> <color=cyan>" + name + "</color>", null);
GUILayout.EndHorizontal();
}
GUILayout.BeginHorizontal(null);
if (cm != null)
{
if (GUILayout.Button(EVALUATE_LABEL, new GUILayoutOption[] { GUILayout.Width(70) }))
{
cm.Evaluate();
}
}
else
{
if (GUILayout.Button(EVALUATE_LABEL, new GUILayoutOption[] { GUILayout.Width(70) }))
{
UpdateValue();
}
}
if (GUILayout.Button("Cancel", new GUILayoutOption[] { GUILayout.Width(70) }))
{
m_isEvaluating = false;
}
GUILayout.EndHorizontal();
}
else
{
if (GUILayout.Button($"Evaluate ({m_arguments.Length} params)", new GUILayoutOption[] { GUILayout.Width(150) }))
{
m_isEvaluating = true;
}
}
GUILayout.EndVertical();
// new line and space
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal(null);
GUILayout.Space(labelWidth);
}
else if (cm != null)
{
//GUILayout.BeginHorizontal(null);
if (GUILayout.Button(EVALUATE_LABEL, new GUILayoutOption[] { GUILayout.Width(70) }))
{
cm.Evaluate();
}
// new line and space
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal(null);
GUILayout.Space(labelWidth);
}
if (!string.IsNullOrEmpty(ReflectionException))
{
GUILayout.Label("<color=red>Reflection failed!</color> (" + ReflectionException + ")", null);
@ -305,30 +444,6 @@ namespace Explorer
}
else
{
if (MemInfo is PropertyInfo pi && pi.GetIndexParameters().Length > 0)
{
GUILayout.Label("index:", new GUILayoutOption[] { GUILayout.Width(50) });
m_propertyIndexInput = GUILayout.TextField(m_propertyIndexInput, new GUILayoutOption[] { GUILayout.Width(100) });
if (GUILayout.Button("Set", new GUILayoutOption[] { GUILayout.Width(60) }))
{
if (int.TryParse(m_propertyIndexInput, out int i))
{
PropertyIndex = i;
UpdateValue();
}
else
{
MelonLogger.Log($"Could not parse '{m_propertyIndexInput}' to an int!");
}
}
// new line and space
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal(null);
GUILayout.Space(labelWidth);
}
DrawValue(window, window.width - labelWidth - 90);
}
}
@ -348,15 +463,15 @@ namespace Explorer
m_richTextName = $"<color=#2df7b2>{MemInfo.DeclaringType.Name}</color>.<color={memberColor}>{MemInfo.Name}</color>";
if (MemInfo is MethodInfo mi)
if (m_arguments.Length > 0)
{
m_richTextName += "(";
var _params = "";
foreach (var param in mi.GetParameters())
foreach (var param in m_arguments)
{
if (_params != "") _params += ", ";
_params += $"<color=#a6e9e9>{param.Name}</color>";
_params += $"<color=#2df7b2>{param.ParameterType.Name}</color> <color=#a6e9e9>{param.Name}</color>";
}
m_richTextName += _params;
m_richTextName += ")";

View File

@ -15,7 +15,7 @@ namespace Explorer
{
public bool IsExpanded { get; set; }
public float WhiteSpace { get; set; } = 215f;
public float ButtonWidthOffset { get; set; } = 290f;
public float ButtonWidthOffset { get; set; } = 350f;
public PageHelper Pages = new PageHelper();
@ -152,7 +152,6 @@ namespace Explorer
foreach (var key in IDict.Keys)
{
var cache = GetCacheObject(key, TypeOfKeys);
cache.UpdateValue();
keys.Add(cache);
}
@ -160,7 +159,6 @@ namespace Explorer
foreach (var val in IDict.Values)
{
var cache = GetCacheObject(val, TypeOfValues);
cache.UpdateValue();
values.Add(cache);
}
@ -170,6 +168,11 @@ namespace Explorer
private bool EnsureDictionaryIsSupported()
{
if (typeof(IDictionary).IsAssignableFrom(ValueType))
{
return true;
}
try
{
return Check(TypeOfKeys) && Check(TypeOfValues);
@ -200,6 +203,12 @@ namespace Explorer
return;
}
float whitespace = WhiteSpace;
if (whitespace > 0)
{
ClampLabelWidth(window, ref whitespace);
}
int count = m_cachedKeys.Length;
if (!IsExpanded)
@ -217,9 +226,11 @@ namespace Explorer
}
}
var negativeWhitespace = window.width - (whitespace + 100f);
GUI.skin.button.alignment = TextAnchor.MiddleLeft;
string btnLabel = $"<color=yellow>[{count}] Dictionary<{TypeOfKeys.FullName}, {TypeOfValues.FullName}></color>";
if (GUILayout.Button(btnLabel, new GUILayoutOption[] { GUILayout.MaxWidth(window.width - ButtonWidthOffset) }))
string btnLabel = $"<color=#2df7b2>[{count}] Dictionary<{TypeOfKeys.FullName}, {TypeOfValues.FullName}></color>";
if (GUILayout.Button(btnLabel, new GUILayoutOption[] { GUILayout.Width(negativeWhitespace) }))
{
WindowManager.InspectObject(Value, out bool _);
}
@ -229,12 +240,6 @@ namespace Explorer
if (IsExpanded)
{
float whitespace = WhiteSpace;
if (whitespace > 0)
{
ClampLabelWidth(window, ref whitespace);
}
Pages.ItemCount = count;
if (count > Pages.ItemsPerPage)

View File

@ -219,7 +219,6 @@ namespace Explorer
if (GetCacheObject(obj, t) is CacheObjectBase cached)
{
cached.UpdateValue();
list.Add(cached);
}
else
@ -246,6 +245,12 @@ namespace Explorer
return;
}
float whitespace = WhiteSpace;
if (whitespace > 0)
{
ClampLabelWidth(window, ref whitespace);
}
int count = m_cachedEntries.Length;
if (!IsExpanded)
@ -263,9 +268,11 @@ namespace Explorer
}
}
var negativeWhitespace = window.width - (whitespace + 100f);
GUI.skin.button.alignment = TextAnchor.MiddleLeft;
string btnLabel = "<color=yellow>[" + count + "] " + EntryType.FullName + "</color>";
if (GUILayout.Button(btnLabel, new GUILayoutOption[] { GUILayout.MaxWidth(window.width - ButtonWidthOffset) }))
string btnLabel = $"[{count}] <color=#2df7b2>{EntryType.FullName}</color>";
if (GUILayout.Button(btnLabel, new GUILayoutOption[] { GUILayout.MaxWidth(negativeWhitespace) }))
{
WindowManager.InspectObject(Value, out bool _);
}
@ -275,12 +282,6 @@ namespace Explorer
if (IsExpanded)
{
float whitespace = WhiteSpace;
if (whitespace > 0)
{
ClampLabelWidth(window, ref whitespace);
}
Pages.ItemCount = count;
if (count > Pages.ItemsPerPage)

View File

@ -11,15 +11,8 @@ namespace Explorer
{
public class CacheMethod : CacheObjectBase
{
private bool m_evaluated = false;
private CacheObjectBase m_cachedReturnValue;
private bool m_isEvaluating;
private ParameterInfo[] m_arguments;
private string[] m_argumentInput;
public bool HasParameters => m_arguments != null && m_arguments.Length > 0;
public static bool CanEvaluate(MethodInfo mi)
{
// TODO generic args
@ -29,25 +22,7 @@ namespace Explorer
}
// primitive and string args supported
foreach (var param in mi.GetParameters())
{
if (!param.ParameterType.IsPrimitive && param.ParameterType != typeof(string))
{
return false;
}
}
return true;
}
public override void Init()
{
base.Init();
var mi = MemInfo as MethodInfo;
m_arguments = mi.GetParameters();
m_argumentInput = new string[m_arguments.Length];
return CanProcessArgs(mi.GetParameters());
}
public override void UpdateValue()
@ -55,10 +30,11 @@ namespace Explorer
//base.UpdateValue();
}
private void Evaluate()
public void Evaluate()
{
var mi = MemInfo as MethodInfo;
m_isEvaluating = false;
var mi = MemInfo as MethodInfo;
object ret = null;
if (!HasParameters)
@ -68,38 +44,7 @@ namespace Explorer
}
else
{
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 == typeof(string))
{
parsedArgs.Add(input);
}
else
{
try
{
if (type.GetMethod("Parse", new Type[] { typeof(string) }).Invoke(null, new object[] { input }) is object parsed)
{
parsedArgs.Add(parsed);
}
else
{
// try add a null arg i guess
parsedArgs.Add(null);
}
}
catch
{
MelonLogger.Log($"Unable to parse '{input}' to type '{type.Name}'");
break;
}
}
}
var parsedArgs = ParseArguments();
try
{
@ -115,13 +60,6 @@ namespace Explorer
if (ret != null)
{
m_cachedReturnValue = GetCacheObject(ret);
if (m_cachedReturnValue is IExpandHeight expander)
{
expander.WhiteSpace = 0f;
expander.ButtonWidthOffset += 70f;
}
m_cachedReturnValue.UpdateValue();
}
else
@ -134,58 +72,6 @@ namespace Explorer
public override void DrawValue(Rect window, float width)
{
GUILayout.BeginVertical(null);
string evaluateLabel = "<color=lime>Evaluate</color>";
if (HasParameters)
{
if (m_isEvaluating)
{
for (int i = 0; i < m_arguments.Length; i++)
{
var name = m_arguments[i].Name;
var input = m_argumentInput[i];
var type = m_arguments[i].ParameterType.Name;
GUILayout.BeginHorizontal(null);
m_argumentInput[i] = GUILayout.TextField(input, new GUILayoutOption[] { GUILayout.Width(150) });
GUILayout.Label(i + ": <color=cyan>" + name + "</color> <color=yellow>(" + type + ")</color>", null);
GUILayout.EndHorizontal();
}
GUILayout.BeginHorizontal(null);
if (GUILayout.Button(evaluateLabel, new GUILayoutOption[] { GUILayout.Width(70) }))
{
Evaluate();
m_isEvaluating = false;
}
if (GUILayout.Button("Cancel", new GUILayoutOption[] { GUILayout.Width(70) }))
{
m_isEvaluating = false;
}
}
else
{
GUILayout.BeginHorizontal(null);
if (GUILayout.Button($"Evaluate ({m_arguments.Length} params)", new GUILayoutOption[] { GUILayout.Width(150) }))
{
m_isEvaluating = true;
}
}
}
else
{
GUILayout.BeginHorizontal(null);
if (GUILayout.Button(evaluateLabel, new GUILayoutOption[] { GUILayout.Width(70) }))
{
Evaluate();
}
}
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal(null);
if (m_evaluated)
{
if (m_cachedReturnValue != null)
@ -194,16 +80,13 @@ namespace Explorer
}
else
{
GUILayout.Label($"null (<color=yellow>{ValueTypeName}</color>)", null);
GUILayout.Label($"null (<color=#2df7b2>{ValueTypeName}</color>)", null);
}
}
else
{
GUILayout.Label($"<color=grey><i>Not yet evaluated</i></color> (<color=yellow>{ValueTypeName}</color>)", null);
GUILayout.Label($"<color=grey><i>Not yet evaluated</i></color> (<color=#2df7b2>{ValueTypeName}</color>)", null);
}
GUILayout.EndHorizontal();
GUILayout.EndVertical();
}
}
}

View File

@ -42,15 +42,20 @@ namespace Explorer
if (!label.Contains(ValueTypeName))
{
label += $" ({ValueTypeName})";
label += $" (<color=#2df7b2>{ValueTypeName}</color>)";
}
else
{
label = label.Replace(ValueTypeName, $"<color=#2df7b2>{ValueTypeName}</color>");
}
if (Value is UnityEngine.Object unityObj && !label.Contains(unityObj.name))
{
label = unityObj.name + " | " + label;
}
GUI.skin.button.alignment = TextAnchor.MiddleLeft;
if (GUILayout.Button("<color=yellow>" + label + "</color>", new GUILayoutOption[] { GUILayout.Width(width - 15) }))
if (GUILayout.Button(label, new GUILayoutOption[] { GUILayout.Width(width - 15) }))
{
WindowManager.InspectObject(Value, out bool _);
}

View File

@ -7,15 +7,17 @@ using UnityEngine;
namespace Explorer
{
public class CacheColor : CacheObjectBase
public class CacheColor : CacheObjectBase, IExpandHeight
{
private bool IsExpanded;
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 float ButtonWidthOffset { get; set; } = 290f;
public override void UpdateValue()
{
base.UpdateValue();
@ -50,13 +52,18 @@ namespace Explorer
var c = (Color)Value;
GUI.color = c;
GUILayout.Label($"<color=yellow>Color:</color> {c.ToString()}", null);
GUILayout.Label($"<color=#2df7b2>Color:</color> {c.ToString()}", null);
GUI.color = Color.white;
if (CanWrite && IsExpanded)
{
GUILayout.EndHorizontal();
var whitespace = window.width - width - 90;
float whitespace = WhiteSpace;
if (whitespace > 0)
{
ClampLabelWidth(window, ref whitespace);
}
GUILayout.BeginHorizontal(null);
GUILayout.Space(whitespace);

View File

@ -51,7 +51,7 @@ namespace Explorer
}
}
GUILayout.Label(Value.ToString() + "<color=yellow><i> (" + ValueType + ")</i></color>", null);
GUILayout.Label(Value.ToString() + "<color=#2df7b2><i> (" + ValueType + ")</i></color>", null);
}
public void SetEnum(ref object value, int change)

View File

@ -69,10 +69,10 @@ namespace Explorer
else
{
// using ValueType.Name instead of ValueTypeName, because we only want the short name.
GUILayout.Label("<color=yellow><i>" + ValueType.Name + "</i></color>", new GUILayoutOption[] { GUILayout.Width(50) });
GUILayout.Label("<color=#2df7b2><i>" + ValueType.Name + "</i></color>", new GUILayoutOption[] { GUILayout.Width(50) });
int dynSize = 25 + (m_valueToString.Length * 15);
var maxwidth = window.width - 300f;
var maxwidth = window.width - 310f;
if (CanWrite) maxwidth -= 60;
if (dynSize > maxwidth)
@ -92,7 +92,7 @@ namespace Explorer
}
}
GUILayout.Space(5);
GUILayout.Space(10);
}
}

View File

@ -7,14 +7,16 @@ using UnityEngine;
namespace Explorer
{
public class CacheQuaternion : CacheObjectBase
public class CacheQuaternion : CacheObjectBase, IExpandHeight
{
private bool IsExpanded;
private string x = "0";
private string y = "0";
private string z = "0";
public bool IsExpanded { get; set; }
public float WhiteSpace { get; set; } = 215f;
public float ButtonWidthOffset { get; set; } = 290f;
public override void UpdateValue()
{
base.UpdateValue();
@ -46,12 +48,17 @@ namespace Explorer
}
}
GUILayout.Label($"<color=yellow>Quaternion</color>: {((Quaternion)Value).eulerAngles.ToString()}", null);
GUILayout.Label($"<color=#2df7b2>Quaternion</color>: {((Quaternion)Value).eulerAngles.ToString()}", null);
if (CanWrite && IsExpanded)
{
GUILayout.EndHorizontal();
var whitespace = window.width - width - 90;
float whitespace = WhiteSpace;
if (whitespace > 0)
{
ClampLabelWidth(window, ref whitespace);
}
GUILayout.BeginHorizontal(null);
GUILayout.Space(whitespace);

View File

@ -7,15 +7,17 @@ using UnityEngine;
namespace Explorer
{
public class CacheRect : CacheObjectBase
public class CacheRect : CacheObjectBase, IExpandHeight
{
private bool IsExpanded;
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 float ButtonWidthOffset { get; set; } = 290f;
public override void UpdateValue()
{
base.UpdateValue();
@ -48,12 +50,17 @@ namespace Explorer
}
}
GUILayout.Label($"<color=yellow>Rect</color>: {((Rect)Value).ToString()}", null);
GUILayout.Label($"<color=#2df7b2>Rect</color>: {((Rect)Value).ToString()}", null);
if (CanWrite && IsExpanded)
{
GUILayout.EndHorizontal();
var whitespace = window.width - width - 90;
float whitespace = WhiteSpace;
if (whitespace > 0)
{
ClampLabelWidth(window, ref whitespace);
}
GUILayout.BeginHorizontal(null);
GUILayout.Space(whitespace);

View File

@ -8,10 +8,8 @@ using UnityEngine;
namespace Explorer
{
public class CacheVector : CacheObjectBase
public class CacheVector : CacheObjectBase, IExpandHeight
{
private bool IsExpanded;
public int VectorSize = 2;
private string x = "0";
@ -21,6 +19,10 @@ namespace Explorer
private MethodInfo m_toStringMethod;
public bool IsExpanded { get; set; }
public float WhiteSpace { get; set; } = 215f;
public float ButtonWidthOffset { get; set; } = 290f;
public override void Init()
{
if (Value is Vector2)
@ -83,12 +85,16 @@ namespace Explorer
}
}
GUILayout.Label($"<color=yellow>Vector{VectorSize}</color>: {(string)m_toStringMethod.Invoke(Value, new object[0])}", null);
GUILayout.Label($"<color=#2df7b2>Vector{VectorSize}</color>: {(string)m_toStringMethod.Invoke(Value, new object[0])}", null);
if (CanWrite && IsExpanded)
{
GUILayout.EndHorizontal();
var whitespace = window.width - width - 90;
float whitespace = WhiteSpace;
if (whitespace > 0)
{
ClampLabelWidth(window, ref whitespace);
}
// always draw x and y
GUILayout.BeginHorizontal(null);

View File

@ -88,6 +88,7 @@
<Compile Include="CppExplorer.cs" />
<Compile Include="Extensions\ReflectionExtensions.cs" />
<Compile Include="Helpers\InputHelper.cs" />
<Compile Include="Tests\TestClass.cs" />
<Compile Include="UnstripFixes\GUIUnstrip.cs" />
<Compile Include="UnstripFixes\ScrollViewStateUnstrip.cs" />
<Compile Include="Extensions\UnityExtensions.cs" />

74
src/Tests/TestClass.cs Normal file
View File

@ -0,0 +1,74 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MelonLoader;
using UnityEngine;
namespace Explorer.Tests
{
public class TestClass
{
public static TestClass Instance => m_instance ?? (m_instance = new TestClass());
private static TestClass m_instance;
public string this[int index]
{
get
{
return $"int indexer: {index}";
}
}
public string this[string stringIndex]
{
get
{
return $"string indexer: {stringIndex}";
}
}
public string this[int arg0, string arg1]
{
get
{
return $"arg0: {arg0}, arg1: {arg1}";
}
}
public static List<string> TestList = new List<string>
{
"1",
"2",
"3",
"etc..."
};
public static Dictionary<int, List<string>> NestedDictionary = new Dictionary<int, List<string>>
{
{
123,
new List<string>
{
"One",
"Two"
}
},
{
567,
new List<string>
{
"One",
"Two"
}
},
};
public static Color TestMethod(float r, float g, float b, float a)
{
return new Color(r, g, b, a);
}
}
}

View File

@ -162,10 +162,20 @@ namespace Explorer
name += " (";
foreach (var param in mi.GetParameters())
{
name += param.ParameterType.Name + ", ";
name += $"{param.ParameterType.Name} {param.Name}, ";
}
name += ")";
}
else if (member is PropertyInfo pi)
{
name += " (";
foreach (var param in pi.GetIndexParameters())
{
name += $"{param.ParameterType.Name} {param.Name}, ";
}
name += ")";
}
if (names.Contains(name))
{
continue;