More progress, cleanups and fixes

This commit is contained in:
Sinai 2021-05-04 20:10:46 +10:00
parent 302ff29e36
commit a89d66cf81
30 changed files with 807 additions and 176 deletions

View File

@ -52,8 +52,6 @@ namespace UnityExplorer.Core.Config
{
try
{
ExplorerCore.Log("Loading internal data");
if (!File.Exists(INI_PATH))
return false;
@ -67,8 +65,6 @@ namespace UnityExplorer.Core.Config
configElement.BoxedValue = StringToConfigValue(config.Value, configElement.ElementType);
}
ExplorerCore.Log("Loaded");
return true;
}
catch (Exception ex)

View File

@ -78,13 +78,6 @@ namespace UnityExplorer.Core.Input
}
}
public static void UpdateIfNeeded()
{
if ((!ShouldActuallyUnlock && (Cursor.visible || Cursor.lockState == CursorLockMode.None))
|| (ShouldActuallyUnlock && (!Cursor.visible || Cursor.lockState != CursorLockMode.None)))
UpdateCursorControl();
}
public static void UpdateCursorControl()
{
try
@ -143,9 +136,6 @@ namespace UnityExplorer.Core.Input
public static void ReleaseEventSystem()
{
if (EventSystem.current != UIManager.EventSys)
return;
if (InputManager.CurrentType == InputType.InputSystem)
return;
@ -225,4 +215,198 @@ namespace UnityExplorer.Core.Input
}
}
}
}
}
// Was rewriting but something broke, not looking into it right now.
//using System;
//using UnityEngine;
//using UnityEngine.EventSystems;
//using UnityExplorer.Core.Input;
//using BF = System.Reflection.BindingFlags;
//using UnityExplorer.Core.Config;
//using UnityExplorer.Core;
//using UnityExplorer.UI;
//using System.Collections;
//#if ML
//using Harmony;
//#else
//using HarmonyLib;
//#endif
//namespace UnityExplorer.Core.Input
//{
// public class CursorUnlocker
// {
// public static bool Unlock
// {
// get => unlock;
// set
// {
// unlock = value;
// UpdateCursorControl();
// }
// }
// private static bool unlock;
// public static bool ShouldActuallyUnlock => UIManager.ShowMenu && Unlock;
// private static CursorLockMode lastLockMode;
// private static bool lastVisibleState;
// private static bool currentlySetting = false;
// private static Type CursorType
// => cursorType
// ?? (cursorType = ReflectionUtility.GetTypeByName("UnityEngine.Cursor"));
// private static Type cursorType;
// public static void Init()
// {
// SetupPatches();
// UpdateCursorControl();
// Unlock = ConfigManager.Force_Unlock_Mouse.Value;
// ConfigManager.Force_Unlock_Mouse.OnValueChanged += (bool val) => { Unlock = val; };
// if (ConfigManager.Aggressive_Force_Unlock.Value)
// RuntimeProvider.Instance.StartCoroutine(ForceUnlockCoroutine());
// }
// private static readonly WaitForEndOfFrame _waitForEndOfFrame = new WaitForEndOfFrame();
// private static IEnumerator ForceUnlockCoroutine()
// {
// while (true)
// {
// yield return _waitForEndOfFrame;
// UpdateCursorControl();
// }
// }
// public static void UpdateCursorControl()
// {
// currentlySetting = true;
// if (ShouldActuallyUnlock)
// {
// if (Cursor.lockState != CursorLockMode.None)
// Cursor.lockState = CursorLockMode.None;
// if (!Cursor.visible)
// Cursor.visible = true;
// SetEventSystem();
// }
// else
// {
// if (Cursor.lockState != lastLockMode)
// Cursor.lockState = lastLockMode;
// if (Cursor.visible != lastVisibleState)
// Cursor.visible = lastVisibleState;
// ReleaseEventSystem();
// }
// currentlySetting = false;
// }
// // Event system overrides
// private static bool m_settingEventSystem;
// private static EventSystem m_lastEventSystem;
// private static BaseInputModule m_lastInputModule;
// public static void SetEventSystem()
// {
// if (InputManager.CurrentType == InputType.InputSystem
// || !UIManager.EventSys
// || EventSystem.current == UIManager.EventSys)
// return;
// if (EventSystem.current && EventSystem.current != UIManager.EventSys)
// {
// m_lastEventSystem = EventSystem.current;
// m_lastEventSystem.enabled = false;
// }
// // Set to our current system
// m_settingEventSystem = true;
// UIManager.EventSys.enabled = true;
// EventSystem.current = UIManager.EventSys;
// InputManager.ActivateUIModule();
// m_settingEventSystem = false;
// }
// public static void ReleaseEventSystem()
// {
// if (InputManager.CurrentType == InputType.InputSystem
// || !UIManager.EventSys
// || EventSystem.current != UIManager.EventSys
// || !m_lastEventSystem)
// return;
// if (m_lastEventSystem.gameObject.activeInHierarchy)
// {
// m_lastEventSystem.enabled = true;
// m_settingEventSystem = true;
// EventSystem.current = m_lastEventSystem;
// m_lastInputModule?.ActivateModule();
// m_settingEventSystem = false;
// }
// }
// // Patches
// private static void SetupPatches()
// {
// if (CursorType == null)
// throw new Exception("Could not load Type 'UnityEngine.Cursor'!");
// lastLockMode = Cursor.lockState;
// lastVisibleState = Cursor.visible;
// // Let mod loader handle actual patching (only necessary until ML 0.3.1)
// ExplorerCore.Loader.SetupCursorPatches();
// }
// public static void Prefix_EventSystem_set_current(ref EventSystem value)
// {
// if (!m_settingEventSystem && value != UIManager.EventSys)
// {
// m_lastEventSystem = value;
// m_lastInputModule = value?.currentInputModule;
// if (ShouldActuallyUnlock)
// {
// value = UIManager.EventSys;
// value.enabled = true;
// }
// }
// }
// public static void Prefix_set_lockState(ref CursorLockMode value)
// {
// if (!currentlySetting)
// {
// lastLockMode = value;
// if (ShouldActuallyUnlock)
// value = CursorLockMode.None;
// }
// }
// public static void Prefix_set_visible(ref bool value)
// {
// if (!currentlySetting)
// {
// lastVisibleState = value;
// if (ShouldActuallyUnlock)
// value = true;
// }
// }
// }
//}

View File

@ -57,7 +57,13 @@ namespace UnityExplorer
/// <param name="obj">The object to cast</param>
/// <returns>The object, cast to the underlying Type if possible, otherwise the original object.</returns>
public static object TryCast(this object obj)
=> ReflectionProvider.Instance.Cast(obj, GetActualType(obj));
{
var type = GetActualType(obj);
if (type.IsValueType)
return obj;
return ReflectionProvider.Instance.Cast(obj, type);
}
/// <summary>
/// Cast an object to a Type, if possible.
@ -66,10 +72,19 @@ namespace UnityExplorer
/// <param name="castTo">The Type to cast to </param>
/// <returns>The object, cast to the Type provided if possible, otherwise the original object.</returns>
public static object TryCast(this object obj, Type castTo)
=> ReflectionProvider.Instance.Cast(obj, castTo);
{
if (castTo.IsValueType)
return obj;
return ReflectionProvider.Instance.Cast(obj, castTo);
}
public static T TryCast<T>(this object obj)
=> ReflectionProvider.Instance.TryCast<T>(obj);
{
var type = typeof(T);
if (type.IsValueType)
return (T)obj;
return ReflectionProvider.Instance.TryCast<T>(obj);
}
/// <summary>
/// Check if the provided Type is assignable to IEnumerable.

View File

@ -19,9 +19,7 @@ namespace UnityExplorer
public static AssetBundle LoadFromFile(string path)
{
var iCall = ICallManager.GetICall<d_LoadFromFile>("UnityEngine.AssetBundle::LoadFromFile_Internal");
var ptr = iCall.Invoke(IL2CPP.ManagedStringToIl2Cpp(path), 0u, 0UL);
return new AssetBundle(ptr);
}
@ -30,12 +28,20 @@ namespace UnityExplorer
public static AssetBundle LoadFromMemory(byte[] binary, uint crc = 0)
{
var iCall = ICallManager.GetICall<d_LoadFromMemory>("UnityEngine.AssetBundle::LoadFromMemory_Internal");
var ptr = iCall(((Il2CppStructArray<byte>) binary).Pointer, crc);
return new AssetBundle(ptr);
}
// static void UnloadAllAssetBundles(bool unloadAllObjects);
internal delegate void d_UnloadAllAssetBundles(bool unloadAllObjects);
public static void UnloadAllAssetBundles(bool unloadAllObjects)
{
var iCall = ICallManager.GetICall<d_UnloadAllAssetBundles>("UnityEngine.AssetBundle::UnloadAllAssetBundles");
iCall.Invoke(unloadAllObjects);
}
// ~~~~~~~~~~~~ Instance ~~~~~~~~~~~~
private readonly IntPtr m_bundlePtr = IntPtr.Zero;
@ -71,6 +77,15 @@ namespace UnityExplorer
return new UnityEngine.Object(ptr).TryCast<T>();
}
// public extern void Unload(bool unloadAllLoadedObjects);
internal delegate void d_Unload(IntPtr _this, bool unloadAllLoadedObjects);
public void Unload(bool unloadAssets = true)
{
var iCall = ICallManager.GetICall<d_Unload>("UnityEngine.AssetBundle::Unload");
iCall.Invoke(this.m_bundlePtr, unloadAssets);
}
}
}
#endif

View File

@ -133,35 +133,37 @@ namespace UnityExplorer.Core.Runtime.Il2Cpp
var type = obj.GetType();
if (obj is Il2CppSystem.Object cppObject)
try
{
// weird specific case - if the object is an Il2CppSystem.Type, then return so manually.
if (cppObject is CppType)
return typeof(CppType);
if (!string.IsNullOrEmpty(type.Namespace))
if ((Il2CppSystem.Object)obj is Il2CppSystem.Object cppObject)
{
// Il2CppSystem-namespace objects should just return GetType,
// because using GetIl2CppType returns the System namespace type instead.
if (type.Namespace.StartsWith("System.") || type.Namespace.StartsWith("Il2CppSystem."))
return cppObject.GetType();
// weird specific case - if the object is an Il2CppSystem.Type, then return so manually.
if (cppObject is CppType)
return typeof(CppType);
if (type.FullName.StartsWith("System.") || type.FullName.StartsWith("Il2CppSystem."))
return type;
var cppType = cppObject.GetIl2CppType();
// check if type is injected
IntPtr classPtr = il2cpp_object_get_class(cppObject.Pointer);
if (RuntimeSpecificsStore.IsInjected(classPtr))
{
var typeByName = ReflectionUtility.GetTypeByName(cppType.FullName);
if (typeByName != null)
return typeByName;
}
// this should be fine for all other il2cpp objects
var getType = GetMonoType(cppType);
if (getType != null)
return getType;
}
var cppType = cppObject.GetIl2CppType();
// check if type is injected
IntPtr classPtr = il2cpp_object_get_class(cppObject.Pointer);
if (RuntimeSpecificsStore.IsInjected(classPtr))
{
var typeByName = ReflectionUtility.GetTypeByName(cppType.FullName);
if (typeByName != null)
return typeByName;
}
// this should be fine for all other il2cpp objects
var getType = GetMonoType(cppType);
if (getType != null)
return getType;
}
catch // (Exception ex)
{
// ExplorerCore.LogWarning("Exception in GetActualType: " + ex);
}
return type;

View File

@ -103,6 +103,11 @@ namespace UnityExplorer.Tests
public static Il2CppSystem.Collections.Hashtable testHashset;
public static Il2CppSystem.Collections.Generic.List<Il2CppSystem.Object> testList;
//public static Il2CppSystem.Nullable<Quaternion> NullableQuaternion;
//public static Il2CppSystem.Nullable<int> NullableInt = new Il2CppSystem.Nullable<int>(5);
//public static Il2CppSystem.Nullable<bool> NullableBool = new Il2CppSystem.Nullable<bool>(false);
#endif
static TestClass()
@ -111,6 +116,9 @@ namespace UnityExplorer.Tests
BigList.Add(i.ToString());
#if CPP
//NullableQuaternion = new Il2CppSystem.Nullable<Quaternion>();
//NullableQuaternion.value = Quaternion.identity;
testHashset = new Il2CppSystem.Collections.Hashtable();
testHashset.Add("key1", "itemOne");
testHashset.Add("key2", "itemTwo");

View File

@ -20,16 +20,20 @@ namespace UnityExplorer.UI.Inspectors.CacheObject
base.SetInspectorOwner(inspector, member);
}
protected override void TryEvaluate()
protected override object TryEvaluate()
{
try
{
Value = FieldInfo.GetValue(this.Owner.Target.TryCast(this.DeclaringType));
var ret = FieldInfo.GetValue(this.Owner.Target.TryCast(this.DeclaringType));
HadException = false;
LastException = null;
return ret;
}
catch (Exception ex)
{
HadException = true;
LastException = ex;
return null;
}
}
@ -37,7 +41,7 @@ namespace UnityExplorer.UI.Inspectors.CacheObject
{
try
{
FieldInfo.SetValue(FieldInfo.IsStatic ? null : Owner.Target, value);
FieldInfo.SetValue(FieldInfo.IsStatic ? null : Owner.Target.TryCast(this.DeclaringType), value);
}
catch (Exception ex)
{

View File

@ -42,7 +42,7 @@ namespace UnityExplorer.UI.Inspectors.CacheObject
{
KeyInputWanted = true;
KeyInputText = key.ToString();
KeyInputTypeText = SignatureHighlighter.ParseFullType(type, false);
KeyInputTypeText = SignatureHighlighter.ParseType(type, false);
}
else
{

View File

@ -5,6 +5,7 @@ using System.Reflection;
using System.Text;
using UnityEngine;
using UnityExplorer.UI.Inspectors.CacheObject.Views;
using UnityExplorer.UI.ObjectPool;
using UnityExplorer.UI.Utility;
namespace UnityExplorer.UI.Inspectors.CacheObject
@ -17,9 +18,11 @@ namespace UnityExplorer.UI.Inspectors.CacheObject
public abstract Type DeclaringType { get; }
public string NameForFiltering { get; protected set; }
public override bool HasArguments => Arguments?.Length > 0;
public ParameterInfo[] Arguments { get; protected set; }
public bool Evaluating { get; protected set; }
public override bool HasArguments => Arguments?.Length > 0 || GenericArguments.Length > 0;
public ParameterInfo[] Arguments { get; protected set; } = new ParameterInfo[0];
public Type[] GenericArguments { get; protected set; } = new Type[0];
public EvaluateWidget Evaluator { get; protected set; }
public bool Evaluating => Evaluator != null && Evaluator.UIRoot.activeSelf;
public virtual void SetInspectorOwner(ReflectionInspector inspector, MemberInfo member)
{
@ -28,17 +31,43 @@ namespace UnityExplorer.UI.Inspectors.CacheObject
this.NameForFiltering = $"{member.DeclaringType.Name}.{member.Name}";
}
protected abstract void TryEvaluate();
public override void ReleasePooledObjects()
{
base.ReleasePooledObjects();
if (this.Evaluator != null)
{
this.Evaluator.OnReturnToPool();
Pool<EvaluateWidget>.Return(this.Evaluator);
this.Evaluator = null;
}
}
internal override void HidePooledObjects()
{
base.HidePooledObjects();
if (this.Evaluator != null)
this.Evaluator.UIRoot.transform.SetParent(Pool<EvaluateWidget>.Instance.InactiveHolder.transform, false);
}
protected abstract object TryEvaluate();
protected abstract void TrySetValue(object value);
public void EvaluateAndSetCell()
{
Evaluate();
if (CellView != null)
SetCell(CellView);
}
/// <summary>
/// Evaluate when first shown (if ShouldAutoEvaluate), or else when Evaluate button is clicked, or auto-updated.
/// </summary>
public void Evaluate()
{
TryEvaluate();
SetValueFromSource(Value);
SetValueFromSource(TryEvaluate());
}
public override void SetUserValue(object value)
@ -58,6 +87,9 @@ namespace UnityExplorer.UI.Inspectors.CacheObject
//memCell.UpdateToggle.gameObject.SetActive(ShouldAutoEvaluate);
}
private static readonly Color evalEnabledColor = new Color(0.15f, 0.25f, 0.15f);
private static readonly Color evalDisabledColor = new Color(0.15f, 0.15f, 0.15f);
protected override bool SetCellEvaluateState(CacheObjectCell objectcell)
{
var cell = objectcell as CacheMemberCell;
@ -68,15 +100,27 @@ namespace UnityExplorer.UI.Inspectors.CacheObject
//cell.UpdateToggle.gameObject.SetActive(false);
cell.EvaluateButton.Button.gameObject.SetActive(true);
if (HasArguments)
cell.EvaluateButton.ButtonText.text = $"Evaluate ({Arguments.Length})";
{
if (!Evaluating)
cell.EvaluateButton.ButtonText.text = $"Evaluate ({Arguments.Length + GenericArguments.Length})";
else
{
cell.EvaluateButton.ButtonText.text = "Hide";
Evaluator.UIRoot.transform.SetParent(cell.EvaluateHolder.transform, false);
RuntimeProvider.Instance.SetColorBlock(cell.EvaluateButton.Button, evalEnabledColor, evalEnabledColor * 1.3f);
}
}
else
cell.EvaluateButton.ButtonText.text = "Evaluate";
if (!Evaluating)
RuntimeProvider.Instance.SetColorBlock(cell.EvaluateButton.Button, evalDisabledColor, evalDisabledColor * 1.3f);
}
else
{
//cell.UpdateToggle.gameObject.SetActive(true);
//cell.UpdateToggle.isOn = AutoUpdateWanted;
}
//else
//{
// cell.UpdateToggle.gameObject.SetActive(true);
// cell.UpdateToggle.isOn = AutoUpdateWanted;
//}
if (State == ValueState.NotEvaluated && !ShouldAutoEvaluate)
{
@ -93,6 +137,35 @@ namespace UnityExplorer.UI.Inspectors.CacheObject
return false;
}
public void OnEvaluateClicked()
{
if (!HasArguments)
{
EvaluateAndSetCell();
}
else
{
if (Evaluator == null)
{
this.Evaluator = Pool<EvaluateWidget>.Borrow();
Evaluator.OnBorrowedFromPool(this);
Evaluator.UIRoot.transform.SetParent((CellView as CacheMemberCell).EvaluateHolder.transform, false);
SetCellEvaluateState(CellView);
}
else
{
if (Evaluator.UIRoot.activeSelf)
Evaluator.UIRoot.SetActive(false);
else
Evaluator.UIRoot.SetActive(true);
SetCellEvaluateState(CellView);
}
}
}
#region Cache Member Util
public static bool CanProcessArgs(ParameterInfo[] parameters)

View File

@ -19,18 +19,35 @@ namespace UnityExplorer.UI.Inspectors.CacheObject
base.SetInspectorOwner(inspector, member);
Arguments = MethodInfo.GetParameters();
if (MethodInfo.IsGenericMethod)
GenericArguments = MethodInfo.GetGenericArguments();
}
protected override void TryEvaluate()
protected override object TryEvaluate()
{
try
{
throw new NotImplementedException("TODO");
var methodInfo = MethodInfo;
if (methodInfo.IsGenericMethod)
methodInfo = MethodInfo.MakeGenericMethod(Evaluator.TryParseGenericArguments());
var target = MethodInfo.IsStatic ? null : Owner.Target.TryCast(DeclaringType);
if (Arguments.Length > 0)
return methodInfo.Invoke(target, Evaluator.TryParseArguments());
var ret = methodInfo.Invoke(target, new object[0]);
HadException = false;
LastException = null;
return ret;
}
catch (Exception ex)
{
HadException = true;
LastException = ex;
return null;
}
}

View File

@ -128,7 +128,6 @@ namespace UnityExplorer.UI.Inspectors.CacheObject
/// </summary>
protected virtual void ProcessOnEvaluate()
{
if (HadException)
State = ValueState.Exception;
else if (Value.IsNullOrDestroyed())
@ -166,7 +165,7 @@ namespace UnityExplorer.UI.Inspectors.CacheObject
switch (State)
{
case ValueState.NotEvaluated:
label = $"<i>{NOT_YET_EVAL} ({SignatureHighlighter.ParseFullType(FallbackType, true)})</i>"; break;
label = $"<i>{NOT_YET_EVAL} ({SignatureHighlighter.ParseType(FallbackType, true)})</i>"; break;
case ValueState.Exception:
label = $"<i><color=red>{ReflectionUtility.ReflectionExToString(LastException)}</color></i>"; break;
case ValueState.Boolean:
@ -228,7 +227,7 @@ namespace UnityExplorer.UI.Inspectors.CacheObject
break;
case ValueState.Enum:
SetIValueState();
SetValueState(cell, new ValueStateArgs(true, subContentButtonActive: true));
SetValueState(cell, new ValueStateArgs(true, subContentButtonActive: CanWrite));
break;
case ValueState.Collection:
case ValueState.Dictionary:
@ -258,11 +257,12 @@ namespace UnityExplorer.UI.Inspectors.CacheObject
cell.TypeLabel.gameObject.SetActive(args.typeLabelActive);
if (args.typeLabelActive)
cell.TypeLabel.text = SignatureHighlighter.ParseFullType(Value.GetActualType(), false);
cell.TypeLabel.text = SignatureHighlighter.ParseType(Value.GetActualType(), false);
cell.Toggle.gameObject.SetActive(args.toggleActive);
if (args.toggleActive)
{
cell.Toggle.interactable = CanWrite;
cell.Toggle.isOn = (bool)Value;
cell.ToggleText.text = Value.ToString();
}
@ -329,7 +329,7 @@ namespace UnityExplorer.UI.Inspectors.CacheObject
IValue = null;
}
internal void HideIValue()
internal virtual void HidePooledObjects()
{
if (this.IValue == null)
return;

View File

@ -21,16 +21,26 @@ namespace UnityExplorer.UI.Inspectors.CacheObject
Arguments = PropertyInfo.GetIndexParameters();
}
protected override void TryEvaluate()
protected override object TryEvaluate()
{
try
{
Value = PropertyInfo.GetValue(Owner.Target.TryCast(DeclaringType), null);
bool _static = PropertyInfo.GetAccessors(true)[0].IsStatic;
var target = _static ? null : Owner.Target.TryCast(DeclaringType);
if (HasArguments)
return PropertyInfo.GetValue(target, this.Evaluator.TryParseArguments());
var ret = PropertyInfo.GetValue(target, null);
HadException = false;
LastException = null;
return ret;
}
catch (Exception ex)
{
HadException = true;
LastException = ex;
return null;
}
}
@ -41,9 +51,13 @@ namespace UnityExplorer.UI.Inspectors.CacheObject
try
{
// TODO property indexers
bool _static = PropertyInfo.GetAccessors(true)[0].IsStatic;
var target = _static ? null : Owner.Target.TryCast(DeclaringType);
PropertyInfo.SetValue(PropertyInfo.GetSetMethod().IsStatic ? null : Owner.Target, value, null);
if (HasArguments)
PropertyInfo.SetValue(target, value, Evaluator.TryParseArguments());
else
PropertyInfo.SetValue(target, value, null);
}
catch (Exception ex)
{

View File

@ -21,7 +21,7 @@ namespace UnityExplorer.UI.Inspectors.CacheObject.Views
protected virtual void EvaluateClicked()
{
// TODO
this.MemberOccupant.OnEvaluateClicked();
}
protected override void ConstructEvaluateHolder(GameObject parent)

View File

@ -0,0 +1,257 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using UnityEngine;
using UnityEngine.UI;
using UnityExplorer.UI.ObjectPool;
using UnityExplorer.UI.Utility;
namespace UnityExplorer.UI.Inspectors.CacheObject.Views
{
public class EvaluateWidget : IPooledObject
{
public CacheMember Owner { get; set; }
public GameObject UIRoot { get; set; }
public float DefaultHeight => -1f;
private ParameterInfo[] arguments;
private string[] argumentInput;
private GameObject argHolder;
private readonly List<GameObject> argRows = new List<GameObject>();
private readonly List<Text> argLabels = new List<Text>();
private Type[] genericArguments;
private string[] genericInput;
private GameObject genericArgHolder;
private readonly List<GameObject> genericArgRows = new List<GameObject>();
private readonly List<Text> genericArgLabels = new List<Text>();
private readonly List<InputField> inputFieldCache = new List<InputField>();
public void OnBorrowedFromPool(CacheMember owner)
{
this.Owner = owner;
arguments = owner.Arguments;
argumentInput = new string[arguments.Length];
genericArguments = owner.GenericArguments;
genericInput = new string[genericArguments.Length];
SetArgRows();
this.UIRoot.SetActive(true);
}
public void OnReturnToPool()
{
foreach (var input in inputFieldCache)
input.text = "";
this.Owner = null;
}
public Type[] TryParseGenericArguments()
{
Type[] outArgs = new Type[genericArguments.Length];
for (int i = 0; i < genericArguments.Length; i++)
{
outArgs[i] = ReflectionUtility.GetTypeByName(genericInput[i])
?? throw new Exception($"Could not find any type by name '{genericInput[i]}'!");
}
return outArgs;
}
public object[] TryParseArguments()
{
object[] outArgs = new object[arguments.Length];
for (int i = 0; i < arguments.Length; i++)
{
var arg = arguments[i];
var input = argumentInput[i];
var type = arg.ParameterType;
if (type.IsByRef)
type = type.GetElementType();
if (type == typeof(string))
{
outArgs[i] = input;
continue;
}
if (string.IsNullOrEmpty(input))
{
if (arg.IsOptional)
outArgs[i] = arg.DefaultValue;
else
outArgs[i] = null;
continue;
}
try
{
var parse = ReflectionUtility.GetMethodInfo(type, "Parse", new Type[] { typeof(string) });
outArgs[i] = parse.Invoke(null, new object[] { input });
}
catch (Exception ex)
{
ExplorerCore.LogWarning($"Cannot parse argument '{arg.Name}' ({arg.ParameterType.Name}), {ex.GetType().Name}: {ex.Message}");
outArgs[i] = null;
}
}
return outArgs;
}
private void SetArgRows()
{
if (genericArguments.Any())
{
genericArgHolder.SetActive(true);
SetupGenericArgs();
}
else
genericArgHolder.SetActive(false);
if (arguments.Any())
{
argHolder.SetActive(true);
SetupArgs();
}
else
argHolder.SetActive(false);
}
private void SetupGenericArgs()
{
for (int i = 0; i < genericArguments.Length || i < genericArgRows.Count; i++)
{
if (i >= genericArguments.Length)
{
if (i >= genericArgRows.Count)
break;
else
// exceeded actual args, but still iterating so there must be views left, disable them
genericArgRows[i].SetActive(false);
continue;
}
var arg = genericArguments[i];
if (i >= genericArgRows.Count)
AddArgRow(i, true);
genericArgRows[i].SetActive(true);
var sb = new StringBuilder($"<color={SignatureHighlighter.CONST}>{arg.Name}</color>");
var constraints = arg.GetGenericParameterConstraints();
for (int j = 0; j < constraints.Length; j++)
{
if (j == 0) sb.Append(' ').Append('(');
else sb.Append(',').Append(' ');
sb.Append(SignatureHighlighter.ParseType(constraints[i]));
if (j + 1 == constraints.Length)
sb.Append(')');
}
genericArgLabels[i].text = sb.ToString();
}
}
private void SetupArgs()
{
for (int i = 0; i < arguments.Length || i < argRows.Count; i++)
{
if (i >= arguments.Length)
{
if (i >= argRows.Count)
break;
else
// exceeded actual args, but still iterating so there must be views left, disable them
argRows[i].SetActive(false);
continue;
}
var arg = arguments[i];
if (i >= argRows.Count)
AddArgRow(i, false);
argRows[i].SetActive(true);
argLabels[i].text = $"{SignatureHighlighter.ParseType(arg.ParameterType)} <color={SignatureHighlighter.LOCAL_ARG}>{arg.Name}</color>";
}
}
private void AddArgRow(int index, bool generic)
{
if (!generic)
AddArgRow(index, argHolder, argRows, argLabels, argumentInput);
else
AddArgRow(index, genericArgHolder, genericArgRows, genericArgLabels, genericInput);
}
private void AddArgRow(int index, GameObject parent, List<GameObject> objectList, List<Text> labelList, string[] inputArray)
{
var horiGroup = UIFactory.CreateUIObject("ArgRow_" + index, parent);
UIFactory.SetLayoutElement(horiGroup, minHeight: 25, flexibleHeight: 50, minWidth: 50, flexibleWidth: 9999);
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(horiGroup, false, false, true, true, 5);
objectList.Add(horiGroup);
var label = UIFactory.CreateLabel(horiGroup, "ArgLabel", "not set", TextAnchor.MiddleLeft);
UIFactory.SetLayoutElement(label.gameObject, minWidth: 40, flexibleWidth: 90, minHeight: 25, flexibleHeight: 50);
labelList.Add(label);
label.horizontalOverflow = HorizontalWrapMode.Wrap;
var inputObj = UIFactory.CreateInputField(horiGroup, "InputField", "...", out InputField inputField);
UIFactory.SetLayoutElement(inputObj, minHeight: 25, flexibleHeight: 0, minWidth: 100, flexibleWidth: 1000);
inputField.lineType = InputField.LineType.MultiLineNewline;
inputField.onValueChanged.AddListener((string val) => { inputArray[index] = val; });
inputFieldCache.Add(inputField);
}
public GameObject CreateContent(GameObject parent)
{
UIRoot = UIFactory.CreateVerticalGroup(parent, "EvaluateWidget", false, false, true, true, 3, new Vector4(2, 2, 2, 2),
new Color(0.15f, 0.15f, 0.15f));
UIFactory.SetLayoutElement(UIRoot, minWidth: 50, flexibleWidth: 9999, minHeight: 50, flexibleHeight: 800);
// generic args
this.genericArgHolder = UIFactory.CreateUIObject("GenericHolder", UIRoot);
UIFactory.SetLayoutElement(genericArgHolder, flexibleWidth: 1000);
var genericsTitle = UIFactory.CreateLabel(genericArgHolder, "GenericsTitle", "Generic Arguments", TextAnchor.MiddleLeft);
UIFactory.SetLayoutElement(genericsTitle.gameObject, minHeight: 25, flexibleWidth: 1000);
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(genericArgHolder, false, false, true, true, 3);
UIFactory.SetLayoutElement(genericArgHolder, minHeight: 25, flexibleHeight: 750, minWidth: 50, flexibleWidth: 9999);
// args
this.argHolder = UIFactory.CreateUIObject("ArgHolder", UIRoot);
UIFactory.SetLayoutElement(argHolder, flexibleWidth: 1000);
var argsTitle = UIFactory.CreateLabel(argHolder, "ArgsTitle", "Arguments", TextAnchor.MiddleLeft);
UIFactory.SetLayoutElement(argsTitle.gameObject, minHeight: 25, flexibleWidth: 1000);
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(argHolder, false, false, true, true, 3);
UIFactory.SetLayoutElement(argHolder, minHeight: 25, flexibleHeight: 750, minWidth: 50, flexibleWidth: 9999);
// evaluate button
var evalButton = UIFactory.CreateButton(UIRoot, "EvaluateButton", "Evaluate", new Color(0.2f, 0.2f, 0.2f));
UIFactory.SetLayoutElement(evalButton.Button.gameObject, minHeight: 25, minWidth: 150, flexibleWidth: 0);
evalButton.OnClick += () =>
{
Owner.EvaluateAndSetCell();
};
return UIRoot;
}
}
}

View File

@ -121,7 +121,7 @@ namespace UnityExplorer.UI.Inspectors
if (!compToStringCache.ContainsKey(type.AssemblyQualifiedName))
{
compToStringCache.Add(type.AssemblyQualifiedName, SignatureHighlighter.ParseFullType(type, true));
compToStringCache.Add(type.AssemblyQualifiedName, SignatureHighlighter.ParseType(type, true));
}
cell.Button.ButtonText.text = compToStringCache[type.AssemblyQualifiedName];

View File

@ -8,7 +8,7 @@ namespace UnityExplorer.UI.Inspectors
{
public interface ICacheObjectController
{
CacheObjectBase ParentCacheObject { get; } // TODO
CacheObjectBase ParentCacheObject { get; }
object Target { get; }
Type TargetType { get; }

View File

@ -39,6 +39,8 @@ namespace UnityExplorer.UI.Inspectors.IValues
public override void OnBorrowed(CacheObjectBase owner)
{
base.OnBorrowed(owner);
DictScrollPool.Refresh(true, true);
}
public override void ReleaseFromOwner()
@ -83,7 +85,7 @@ namespace UnityExplorer.UI.Inspectors.IValues
CacheEntries(value);
TopLabel.text = $"[{cachedEntries.Count}] {SignatureHighlighter.ParseFullType(type, false)}";
TopLabel.text = $"[{cachedEntries.Count}] {SignatureHighlighter.ParseType(type, false)}";
}
@ -172,7 +174,7 @@ namespace UnityExplorer.UI.Inspectors.IValues
{
if (cell.Occupant != null)
{
cell.Occupant.HideIValue();
cell.Occupant.HidePooledObjects();
cell.Occupant.CellView = null;
cell.Occupant = null;
}

View File

@ -35,6 +35,8 @@ namespace UnityExplorer.UI.Inspectors.IValues
public override void OnBorrowed(CacheObjectBase owner)
{
base.OnBorrowed(owner);
ListScrollPool.Refresh(true, true);
}
public override void ReleaseFromOwner()
@ -72,7 +74,7 @@ namespace UnityExplorer.UI.Inspectors.IValues
CacheEntries(value);
TopLabel.text = $"[{cachedEntries.Count}] {SignatureHighlighter.ParseFullType(type, false)}";
TopLabel.text = $"[{cachedEntries.Count}] {SignatureHighlighter.ParseType(type, false)}";
}
//this.ScrollPoolLayout.minHeight = Math.Min(400f, 35f * values.Count);
@ -169,7 +171,7 @@ namespace UnityExplorer.UI.Inspectors.IValues
{
if (cell.Occupant != null)
{
cell.Occupant.HideIValue();
cell.Occupant.HidePooledObjects();
cell.Occupant.CellView = null;
cell.Occupant = null;
}

View File

@ -30,7 +30,7 @@ namespace UnityExplorer.UI.Inspectors
private List<CacheMember> members = new List<CacheMember>();
private readonly List<CacheMember> filteredMembers = new List<CacheMember>();
private readonly HashSet<CacheMember> displayedMembers = new HashSet<CacheMember>();
// private readonly HashSet<CacheMember> displayedMembers = new HashSet<CacheMember>();
public Text NameText;
public Text AssemblyText;
@ -65,7 +65,6 @@ namespace UnityExplorer.UI.Inspectors
members.Clear();
filteredMembers.Clear();
displayedMembers.Clear();
autoUpdateToggle.isOn = false;
AutoUpdateWanted = false;
@ -88,7 +87,7 @@ namespace UnityExplorer.UI.Inspectors
prefix = "[R]";
}
Tab.TabText.text = $"{prefix} {SignatureHighlighter.ParseFullType(TargetType)}";
Tab.TabText.text = $"{prefix} {SignatureHighlighter.ParseType(TargetType)}";
NameText.text = SignatureHighlighter.ParseFullSyntax(TargetType, true);
@ -156,8 +155,11 @@ namespace UnityExplorer.UI.Inspectors
private void UpdateDisplayedMembers()// bool onlyAutoUpdate)
{
bool shouldRefresh = false;
foreach (var member in displayedMembers)
foreach (var cell in MemberScrollPool.CellPool)
{
if (!cell.Enabled || cell.Occupant == null)
continue;
var member = cell.MemberOccupant;
if (member.ShouldAutoEvaluate) // && (!onlyAutoUpdate || member.AutoUpdateWanted))
{
shouldRefresh = true;
@ -185,9 +187,6 @@ namespace UnityExplorer.UI.Inspectors
{
if (cell.Occupant != null)
{
if (displayedMembers.Contains(cell.MemberOccupant))
displayedMembers.Remove(cell.MemberOccupant);
cell.Occupant.CellView = null;
cell.Occupant = null;
}
@ -202,15 +201,13 @@ namespace UnityExplorer.UI.Inspectors
{
if (cell.Occupant != null)
{
cell.Occupant.HideIValue();
displayedMembers.Remove(cell.MemberOccupant);
cell.Occupant.HidePooledObjects();
cell.Occupant.CellView = null;
cell.Occupant = null;
}
cell.Occupant = member;
member.CellView = cell;
displayedMembers.Add(member);
}
member.SetCell(cell);

View File

@ -97,7 +97,7 @@ namespace UnityExplorer.UI.Panels
{
string text;
if (m_context == SearchContext.StaticClass)
text = SignatureHighlighter.ParseFullType(currentResults[index] as Type, true, true);
text = SignatureHighlighter.ParseType(currentResults[index] as Type, true, true);
else
text = ToStringUtility.ToStringWithType(currentResults[index], currentResults[index]?.GetActualType());

View File

@ -41,10 +41,10 @@ namespace UnityExplorer.UI.Panels
private readonly Dictionary<int, Dropdown.OptionData> sceneToDropdownOption = new Dictionary<int, Dropdown.OptionData>();
private IEnumerable<GameObject> GetRootEntries() => SceneHandler.CurrentRootObjects;
public void Update()
{
if (AutoUpdate && Time.realtimeSinceStartup - timeOfLastUpdate >= 1f)
if ((AutoUpdate || !SceneHandler.InspectingAssetScene) && Time.realtimeSinceStartup - timeOfLastUpdate >= 1f)
{
timeOfLastUpdate = Time.realtimeSinceStartup;
UpdateTree();
@ -65,7 +65,7 @@ namespace UnityExplorer.UI.Panels
SceneHandler.SelectedScene = SceneHandler.LoadedScenes[value];
SceneHandler.Update();
Tree.RefreshData(true);
//OnSelectedSceneChanged(SceneHandler.SelectedScene.Value);
OnSelectedSceneChanged(SceneHandler.SelectedScene.Value);
}
private void SceneHandler_OnInspectedSceneChanged(Scene scene)
@ -83,14 +83,14 @@ namespace UnityExplorer.UI.Panels
sceneDropdown.captionText.text = opt.text;
}
//OnSelectedSceneChanged(scene);
OnSelectedSceneChanged(scene);
}
//private void OnSelectedSceneChanged(Scene scene)
//{
// if (refreshRow)
// refreshRow.SetActive(!scene.IsValid());
//}
private void OnSelectedSceneChanged(Scene scene)
{
if (refreshRow)
refreshRow.SetActive(!scene.IsValid());
}
private void SceneHandler_OnLoadedScenesChanged(ReadOnlyCollection<Scene> loadedScenes)
{

View File

@ -40,7 +40,7 @@ namespace UnityExplorer.UI.Panels
content.SetActive(true);
var button = tabButtons[tabIndex];
RuntimeProvider.Instance.SetColorBlock(button.Button, UIManager.navButtonEnabledColor, UIManager.navButtonEnabledColor * 1.2f);
RuntimeProvider.Instance.SetColorBlock(button.Button, UIManager.enabledButtonColor, UIManager.enabledButtonColor * 1.2f);
SelectedTab = tabIndex;
SaveToConfigManager();
@ -49,7 +49,7 @@ namespace UnityExplorer.UI.Panels
private void DisableTab(int tabIndex)
{
tabPages[tabIndex].SetActive(false);
RuntimeProvider.Instance.SetColorBlock(tabButtons[tabIndex].Button, UIManager.navButtonDisabledColor, UIManager.navButtonDisabledColor * 1.2f);
RuntimeProvider.Instance.SetColorBlock(tabButtons[tabIndex].Button, UIManager.disabledButtonColor, UIManager.disabledButtonColor * 1.2f);
}
public override void Update()
@ -97,10 +97,11 @@ namespace UnityExplorer.UI.Panels
public override void SetDefaultPosAndAnchors()
{
// todo proper default size
mainPanelRect.localPosition = Vector2.zero;
mainPanelRect.pivot = new Vector2(0f, 1f);
mainPanelRect.anchorMin = new Vector2(0.1f, 0.2f);
mainPanelRect.anchorMax = new Vector2(0.25f, 0.9f);
mainPanelRect.anchorMin = new Vector2(0.1f, 0.25f);
mainPanelRect.anchorMax = new Vector2(0.25f, 0.8f);
//mainPanelRect.anchorMin = Vector3.zero;

View File

@ -227,19 +227,6 @@ namespace UnityExplorer.UI.Panels
Vector3 pos = Panel.localPosition;
pos += (Vector3)diff;
Panel.localPosition = pos;
// TODO prevent dragging the navbar outside the window completely.
// this was not that, but should do that.
//var halfHeight = Panel.rect.height * 0.5f;
//var halfWidth = Panel.rect.width * 0.5f;
//if (Panel.MinY() - halfHeight + 25 < 0
// || Panel.MinX() - halfWidth + 25 < 0
// || Panel.MaxY() + halfWidth - 25 > Screen.height
// || Panel.MinX() + halfWidth - 25 > Screen.width)
//{
// Panel.localPosition -= (Vector3)diff;
//}
}
public void OnEndDrag()

View File

@ -114,9 +114,9 @@ namespace UnityExplorer.UI.Panels
if (NavButtonWanted)
{
if (active)
RuntimeProvider.Instance.SetColorBlock(NavButton.Button, UIManager.navButtonEnabledColor, UIManager.navButtonEnabledColor * 1.2f);
RuntimeProvider.Instance.SetColorBlock(NavButton.Button, UIManager.enabledButtonColor, UIManager.enabledButtonColor * 1.2f);
else
RuntimeProvider.Instance.SetColorBlock(NavButton.Button, UIManager.navButtonDisabledColor, UIManager.navButtonDisabledColor * 1.2f);
RuntimeProvider.Instance.SetColorBlock(NavButton.Button, UIManager.disabledButtonColor, UIManager.disabledButtonColor * 1.2f);
}
}
@ -136,7 +136,7 @@ namespace UnityExplorer.UI.Panels
NavButton = UIFactory.CreateButton(UIManager.NavbarButtonHolder, $"Button_{PanelType}", Name);
UIFactory.SetLayoutElement(NavButton.Button.gameObject, minWidth: 118, flexibleWidth: 0);
RuntimeProvider.Instance.SetColorBlock(NavButton.Button, UIManager.navButtonDisabledColor, UIManager.navButtonDisabledColor * 1.2f);
RuntimeProvider.Instance.SetColorBlock(NavButton.Button, UIManager.disabledButtonColor, UIManager.disabledButtonColor * 1.2f);
NavButton.OnClick += () =>
{
UIManager.TogglePanel(PanelType);

View File

@ -729,9 +729,7 @@ namespace UnityExplorer.UI
contentRect.pivot = new Vector2(0.5f, 1f);
contentRect.sizeDelta = new Vector2(0f, 0f);
contentRect.offsetMax = new Vector2(0f, 0f);
SetLayoutGroup<VerticalLayoutGroup>(content, true, false, true, true, 0, 2, 2, 2, 2, TextAnchor.UpperCenter);
content.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize;
var scrollRect = mainObj.AddComponent<ScrollRect>();

View File

@ -53,8 +53,8 @@ namespace UnityExplorer.UI
public static RectTransform NavBarRect;
public static GameObject NavbarButtonHolder;
internal static readonly Color navButtonEnabledColor = new Color(0.2f, 0.4f, 0.28f);
internal static readonly Color navButtonDisabledColor = new Color(0.25f, 0.25f, 0.25f);
internal static readonly Color enabledButtonColor = new Color(0.2f, 0.4f, 0.28f);
internal static readonly Color disabledButtonColor = new Color(0.25f, 0.25f, 0.25f);
public const int MAX_INPUTFIELD_CHARS = 16000;

View File

@ -35,6 +35,12 @@ namespace UnityExplorer.UI.Utility
public const string LOCAL_ARG = "#a6e9e9";
internal const string ARRAY_TOKEN = "[]";
internal const string OPEN_COLOR = "<color=";
internal const string CLOSE_COLOR = "</color>";
internal const string OPEN_ITALIC = "<i>";
internal const string CLOSE_ITALIC = "</i>";
public static readonly Color StringOrange = new Color(0.83f, 0.61f, 0.52f);
public static readonly Color EnumGreen = new Color(0.57f, 0.76f, 0.43f);
public static readonly Color KeywordBlue = new Color(0.3f, 0.61f, 0.83f);
@ -73,17 +79,20 @@ namespace UnityExplorer.UI.Utility
bool isGeneric = type.IsGenericParameter || (type.HasElementType && type.GetElementType().IsGenericParameter);
if (!isGeneric && includeNamespace && GetNamespace(type, out string ns))
syntaxBuilder.Append($"<color={NAMESPACE}>{ns}</color>.");
// Declaring type
var declaring = type.DeclaringType;
while (declaring != null)
if (!isGeneric)
{
syntaxBuilder.Append(HighlightType(declaring));
syntaxBuilder.Append('.');
declaring = declaring.DeclaringType;
if (includeNamespace && GetNamespace(type, out string ns))
syntaxBuilder.Append(OPEN_COLOR).Append(NAMESPACE).Append('>').Append(ns).Append(CLOSE_COLOR).Append('.');
// Declaring type
var declaring = type.DeclaringType;
while (declaring != null)
{
syntaxBuilder.Append(HighlightType(declaring));
syntaxBuilder.Append('.');
declaring = declaring.DeclaringType;
}
}
// Highlight the type name
@ -96,68 +105,101 @@ namespace UnityExplorer.UI.Utility
{
syntaxBuilder.Append('.');
string memColor = GetMemberInfoColor(memberInfo, out bool isStatic);
//string memColor = GetMemberInfoColor(memberInfo, out bool isStatic);
//if (isStatic)
// syntaxBuilder.Append(OPEN_ITALIC);
//syntaxBuilder.Append($"<color={memColor}>{memberInfo.Name}{CLOSE_COLOR}");
int start = syntaxBuilder.Length - 1;
syntaxBuilder.Append(OPEN_COLOR)
.Append(GetMemberInfoColor(memberInfo, out bool isStatic))
.Append('>')
.Append(memberInfo.Name)
.Append(CLOSE_COLOR);
if (isStatic)
syntaxBuilder.Append("<i>");
syntaxBuilder.Append($"<color={memColor}>{memberInfo.Name}</color>");
if (isStatic)
syntaxBuilder.Append("</i>");
{
syntaxBuilder.Insert(start, OPEN_ITALIC);
syntaxBuilder.Append(CLOSE_ITALIC);
}
if (memberInfo is MethodInfo method)
{
var args = method.GetGenericArguments();
if (args.Length > 0)
syntaxBuilder.Append($"<{ParseGenericArgs(args, true)}>");
//syntaxBuilder.Append($"<{ParseGenericArgs(args, true)}>");
syntaxBuilder.Append('<').Append(ParseGenericArgs(args, true)).Append('>');
}
}
return syntaxBuilder.ToString();
}
public static string ParseFullType(Type type, bool includeNamespace = false, bool includeDllName = false)
public static string ParseType(Type type, bool includeNamespace = false, bool includeDllName = false)
{
string ret = HighlightType(type);
var sb = new StringBuilder();
bool isGeneric = type.IsGenericParameter || (type.HasElementType && type.GetElementType().IsGenericParameter);
if (!isGeneric && includeNamespace && GetNamespace(type, out string ns))
ret = $"<color={NAMESPACE}>{ns}</color>.{ret}";
//sb.Append($"<color={NAMESPACE}>{ns}{CLOSE_COLOR}.");
sb.Append(OPEN_COLOR).Append(NAMESPACE).Append('>').Append(ns).Append(CLOSE_COLOR).Append('.');
sb.Append(HighlightType(type));
if (includeDllName)
{
if (!string.IsNullOrEmpty(type.Assembly.Location))
ret = $"{ret} ({Path.GetFileName(type.Assembly.Location)})";
//sb.Append($" ({Path.GetFileName(type.Assembly.Location)})");
sb.Append(' ').Append('(').Append(Path.GetFileName(type.Assembly.Location)).Append(')');
else
ret = $"{ret} ({type.Assembly.GetName().Name})";
//sb.Append($" ({type.Assembly.GetName().Name})");
sb.Append(' ').Append('(').Append(type.Assembly.GetName().Name).Append(')');
}
return ret;
return sb.ToString();
}
private static readonly Dictionary<string, string> typeToRichType = new Dictionary<string, string>();
private static bool EndsWith(this StringBuilder sb, string _string)
{
int len = _string.Length;
if (sb.Length < len)
return false;
int stringpos = 0;
for (int i = sb.Length - len; i < sb.Length; i++, stringpos++)
{
if (sb[i] != _string[stringpos])
return false;
}
return true;
}
private static string HighlightType(Type type)
{
string key = type.ToString();
if (typeToRichType.ContainsKey(key))
return typeToRichType[key];
var typeName = type.Name;
var sb = new StringBuilder(type.Name);
bool isArray = false;
if (typeName.EndsWith("[]"))
if (sb.EndsWith(ARRAY_TOKEN))
{
isArray = true;
typeName = typeName.Substring(0, typeName.Length - 2);
sb.Remove(sb.Length - 2, 2);
type = type.GetElementType();
}
if (type.IsGenericParameter || (type.HasElementType && type.GetElementType().IsGenericParameter))
{
typeName = $"<color={CONST}>{typeName}</color>";
//typeName = $"<color={CONST}>{typeName}</color>";
sb.Insert(0, $"<color={CONST}>");
sb.Append(CLOSE_COLOR);
}
else
{
@ -172,27 +214,33 @@ namespace UnityExplorer.UI.Utility
int suffixLen = 1 + args.Length.ToString().Length;
// make sure the typename actually has expected "`N" format.
if (typeName[typeName.Length - suffixLen] == '`')
typeName = typeName.Substring(0, typeName.Length - suffixLen);
if (sb[sb.Length - suffixLen] == '`')
//typeName = typeName.Substring(0, typeName.Length - suffixLen);
sb.Remove(sb.Length - suffixLen, suffixLen);
}
// highlight the base name itself
// do this after removing the `N suffix, so only the name itself is in the color tags.
typeName = $"<color={GetClassColor(type)}>{typeName}</color>";
//typeName = $"<color={GetClassColor(type)}>{typeName}</color>";
sb.Insert(0, $"{OPEN_COLOR}{GetClassColor(type)}>");
sb.Append(CLOSE_COLOR);
// parse the generic args, if any
if (args.Length > 0)
{
typeName += $"<{ParseGenericArgs(args)}>";
//typeName += $"<{ParseGenericArgs(args)}>";
sb.Append('<').Append(ParseGenericArgs(args)).Append('>');
}
}
if (isArray)
typeName += "[]";
//typeName += "[]";
sb.Append('[').Append(']');
typeToRichType.Add(key, typeName);
var ret = sb.ToString();
typeToRichType.Add(key, ret);
return typeName;
return ret;
}
public static string ParseGenericArgs(Type[] args, bool isGenericParams = false)
@ -200,24 +248,27 @@ namespace UnityExplorer.UI.Utility
if (args.Length < 1)
return string.Empty;
string ret = "";
//string ret = "";
var sb = new StringBuilder();
for (int i = 0; i < args.Length; i++)
{
if (i > 0)
ret += ", ";
//ret += ", ";
sb.Append(',').Append(' ');
if (isGenericParams)
{
ret += $"<color={CONST}>{args[i].Name}</color>";
//ret += $"<color={CONST}>{args[i].Name}</color>";
sb.Append(OPEN_COLOR).Append(CONST).Append('>').Append(args[i].Name).Append(CLOSE_COLOR);
continue;
}
// using HighlightTypeName makes it recursive, so we can parse nested generic args.
ret += ParseFullType(args[i]);
//ret += ParseType(args[i]);
sb.Append(ParseType(args[i]));
}
return ret;
return sb.ToString();
}
public static string GetMemberInfoColor(MemberInfo memberInfo, out bool isStatic)

View File

@ -30,9 +30,6 @@ namespace UnityExplorer.UI.Utility
string richType = SignatureHighlighter.ParseFullSyntax(type, includeNamespace);
//if (!includeName)
// return richType;
_stringBuilder.Clear();
if (value.IsNullOrDestroyed())
@ -142,10 +139,20 @@ namespace UnityExplorer.UI.Utility
value = value.TryCast(type);
string toString;
if (toStringFormattedMethods.TryGetValue(type.AssemblyQualifiedName, out MethodInfo f3method))
toString = (string)f3method.Invoke(value, new object[] { "F3" });
else
toString = (string)toStringMethods[type.AssemblyQualifiedName].Invoke(value, new object[0]);
try
{
if (toStringFormattedMethods.TryGetValue(type.AssemblyQualifiedName, out MethodInfo f3method))
toString = (string)f3method.Invoke(value, new object[] { "F3" });
else
toString = (string)toStringMethods[type.AssemblyQualifiedName].Invoke(value, new object[0]);
}
catch (Exception ex)
{
toString = ex.ReflectionExToString();
}
string _ = null;
toString = ReflectionProvider.Instance.ProcessTypeFullNameInString(type, toString, ref _);
return toString;
}

View File

@ -24,7 +24,7 @@ namespace UnityExplorer.UI
public static float MinY(this RectTransform rect) => rect.position.y;
public static float MaxX(this RectTransform rect) => rect.position.x - rect.rect.width;
public static float MaxX(this RectTransform rect) => rect.position.x + rect.rect.width;
public static float MinX(this RectTransform rect) => rect.position.x;
}

View File

@ -246,6 +246,7 @@
<Compile Include="UI\Inspectors\CacheObject\Views\CacheListEntryCell.cs" />
<Compile Include="UI\Inspectors\CacheObject\Views\CacheMemberCell.cs" />
<Compile Include="UI\Inspectors\CacheObject\Views\CacheObjectCell.cs" />
<Compile Include="UI\Inspectors\CacheObject\Views\EvaluateWidget.cs" />
<Compile Include="UI\Inspectors\GameObjectInspector.cs" />
<Compile Include="UI\Inspectors\ICacheObjectController.cs" />
<Compile Include="UI\Inspectors\InspectorManager.cs" />