Skip to content
This repository has been archived by the owner on May 9, 2023. It is now read-only.

Commit

Permalink
1.6.6
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
sinai-dev committed Sep 9, 2020
1 parent 94f7493 commit 6ea435d
Show file tree
Hide file tree
Showing 15 changed files with 337 additions and 216 deletions.
Binary file modified img.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
205 changes: 160 additions & 45 deletions src/CachedObjects/CacheObjectBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,12 @@ public abstract class CacheObjectBase
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; }

Expand All @@ -43,7 +47,6 @@ public bool CanWrite
// ===== Abstract/Virtual Methods ===== //

public virtual void Init() { }

public abstract void DrawValue(Rect window, float width);

// ===== Static Methods ===== //
Expand Down Expand Up @@ -114,12 +117,21 @@ private static CacheObjectBase GetCacheObjectImpl(object obj, MemberInfo memberI
{
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))
{
Expand Down Expand Up @@ -181,7 +193,21 @@ private static CacheObjectBase GetCacheObjectImpl(object obj, MemberInfo memberI
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();
}

Expand All @@ -190,11 +216,57 @@ private static CacheObjectBase GetCacheObjectImpl(object obj, MemberInfo memberI
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;
}
Expand All @@ -209,13 +281,11 @@ public virtual void UpdateValue()
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
{
Expand All @@ -224,6 +294,8 @@ public virtual void UpdateValue()
}

ReflectionException = null;
m_evaluated = true;
m_isEvaluating = false;
}
catch (Exception e)
{
Expand All @@ -244,10 +316,9 @@ public void SetValue()
{
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
{
Expand All @@ -264,6 +335,7 @@ public void SetValue()
// ========= 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)
{
Expand All @@ -282,53 +354,96 @@ public void Draw(Rect window, float labelWidth = 215f)

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);
}

if (!string.IsNullOrEmpty(ReflectionException))
{
GUILayout.Label("<color=red>Reflection failed!</color> (" + ReflectionException + ")", null);
}
else if (Value == null && MemInfo?.MemberType != MemberTypes.Method)
{
GUILayout.Label("<i>null (" + ValueTypeName + ")</i>", null);
}
else
var cm = this as CacheMethod;

if (HasParameters)
{
if (MemInfo is PropertyInfo pi && pi.GetIndexParameters().Length > 0)
GUILayout.BeginVertical(null);

if (m_isEvaluating)
{
GUILayout.Label("index:", new GUILayoutOption[] { GUILayout.Width(50) });
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();
}

m_propertyIndexInput = GUILayout.TextField(m_propertyIndexInput, new GUILayoutOption[] { GUILayout.Width(100) });
if (GUILayout.Button("Set", new GUILayoutOption[] { GUILayout.Width(60) }))
GUILayout.BeginHorizontal(null);
if (cm != null)
{
if (int.TryParse(m_propertyIndexInput, out int i))
if (GUILayout.Button(EVALUATE_LABEL, new GUILayoutOption[] { GUILayout.Width(70) }))
{
PropertyIndex = i;
UpdateValue();
cm.Evaluate();
}
else
}
else
{
if (GUILayout.Button(EVALUATE_LABEL, new GUILayoutOption[] { GUILayout.Width(70) }))
{
MelonLogger.Log($"Could not parse '{m_propertyIndexInput}' to an int!");
UpdateValue();
}
}

// new line and space

if (GUILayout.Button("Cancel", new GUILayoutOption[] { GUILayout.Width(70) }))
{
m_isEvaluating = false;
}
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal(null);
GUILayout.Space(labelWidth);
}
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);
}
else if (Value == null && MemInfo?.MemberType != MemberTypes.Method)
{
GUILayout.Label("<i>null (" + ValueTypeName + ")</i>", null);
}
else
{
DrawValue(window, window.width - labelWidth - 90);
}
}
Expand All @@ -348,15 +463,15 @@ private string GetRichTextName()

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 += ")";
Expand Down
27 changes: 16 additions & 11 deletions src/CachedObjects/Object/CacheDictionary.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public class CacheDictionary : CacheObjectBase, IExpandHeight
{
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();

Expand Down Expand Up @@ -152,15 +152,13 @@ public override void UpdateValue()
foreach (var key in IDict.Keys)
{
var cache = GetCacheObject(key, TypeOfKeys);
cache.UpdateValue();
keys.Add(cache);
}

var values = new List<CacheObjectBase>();
foreach (var val in IDict.Values)
{
var cache = GetCacheObject(val, TypeOfValues);
cache.UpdateValue();
values.Add(cache);
}

Expand All @@ -170,6 +168,11 @@ public override void UpdateValue()

private bool EnsureDictionaryIsSupported()
{
if (typeof(IDictionary).IsAssignableFrom(ValueType))
{
return true;
}

try
{
return Check(TypeOfKeys) && Check(TypeOfValues);
Expand Down Expand Up @@ -200,6 +203,12 @@ public override void DrawValue(Rect window, float width)
return;
}

float whitespace = WhiteSpace;
if (whitespace > 0)
{
ClampLabelWidth(window, ref whitespace);
}

int count = m_cachedKeys.Length;

if (!IsExpanded)
Expand All @@ -217,9 +226,11 @@ public override void DrawValue(Rect window, float width)
}
}

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 _);
}
Expand All @@ -229,12 +240,6 @@ public override void DrawValue(Rect window, float width)

if (IsExpanded)
{
float whitespace = WhiteSpace;
if (whitespace > 0)
{
ClampLabelWidth(window, ref whitespace);
}

Pages.ItemCount = count;

if (count > Pages.ItemsPerPage)
Expand Down
Loading

0 comments on commit 6ea435d

Please sign in to comment.