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 try
{ {
ExplorerCore.Log("Loading internal data");
if (!File.Exists(INI_PATH)) if (!File.Exists(INI_PATH))
return false; return false;
@ -67,8 +65,6 @@ namespace UnityExplorer.Core.Config
configElement.BoxedValue = StringToConfigValue(config.Value, configElement.ElementType); configElement.BoxedValue = StringToConfigValue(config.Value, configElement.ElementType);
} }
ExplorerCore.Log("Loaded");
return true; return true;
} }
catch (Exception ex) 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() public static void UpdateCursorControl()
{ {
try try
@ -143,9 +136,6 @@ namespace UnityExplorer.Core.Input
public static void ReleaseEventSystem() public static void ReleaseEventSystem()
{ {
if (EventSystem.current != UIManager.EventSys)
return;
if (InputManager.CurrentType == InputType.InputSystem) if (InputManager.CurrentType == InputType.InputSystem)
return; 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> /// <param name="obj">The object to cast</param>
/// <returns>The object, cast to the underlying Type if possible, otherwise the original object.</returns> /// <returns>The object, cast to the underlying Type if possible, otherwise the original object.</returns>
public static object TryCast(this object obj) 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> /// <summary>
/// Cast an object to a Type, if possible. /// Cast an object to a Type, if possible.
@ -66,10 +72,19 @@ namespace UnityExplorer
/// <param name="castTo">The Type to cast to </param> /// <param name="castTo">The Type to cast to </param>
/// <returns>The object, cast to the Type provided if possible, otherwise the original object.</returns> /// <returns>The object, cast to the Type provided if possible, otherwise the original object.</returns>
public static object TryCast(this object obj, Type castTo) 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) 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> /// <summary>
/// Check if the provided Type is assignable to IEnumerable. /// Check if the provided Type is assignable to IEnumerable.

View File

@ -19,9 +19,7 @@ namespace UnityExplorer
public static AssetBundle LoadFromFile(string path) public static AssetBundle LoadFromFile(string path)
{ {
var iCall = ICallManager.GetICall<d_LoadFromFile>("UnityEngine.AssetBundle::LoadFromFile_Internal"); var iCall = ICallManager.GetICall<d_LoadFromFile>("UnityEngine.AssetBundle::LoadFromFile_Internal");
var ptr = iCall.Invoke(IL2CPP.ManagedStringToIl2Cpp(path), 0u, 0UL); var ptr = iCall.Invoke(IL2CPP.ManagedStringToIl2Cpp(path), 0u, 0UL);
return new AssetBundle(ptr); return new AssetBundle(ptr);
} }
@ -30,12 +28,20 @@ namespace UnityExplorer
public static AssetBundle LoadFromMemory(byte[] binary, uint crc = 0) public static AssetBundle LoadFromMemory(byte[] binary, uint crc = 0)
{ {
var iCall = ICallManager.GetICall<d_LoadFromMemory>("UnityEngine.AssetBundle::LoadFromMemory_Internal"); var iCall = ICallManager.GetICall<d_LoadFromMemory>("UnityEngine.AssetBundle::LoadFromMemory_Internal");
var ptr = iCall(((Il2CppStructArray<byte>) binary).Pointer, crc); var ptr = iCall(((Il2CppStructArray<byte>) binary).Pointer, crc);
return new AssetBundle(ptr); 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 ~~~~~~~~~~~~ // ~~~~~~~~~~~~ Instance ~~~~~~~~~~~~
private readonly IntPtr m_bundlePtr = IntPtr.Zero; private readonly IntPtr m_bundlePtr = IntPtr.Zero;
@ -71,6 +77,15 @@ namespace UnityExplorer
return new UnityEngine.Object(ptr).TryCast<T>(); 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 #endif

View File

@ -133,35 +133,37 @@ namespace UnityExplorer.Core.Runtime.Il2Cpp
var type = obj.GetType(); 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 ((Il2CppSystem.Object)obj is Il2CppSystem.Object cppObject)
if (cppObject is CppType)
return typeof(CppType);
if (!string.IsNullOrEmpty(type.Namespace))
{ {
// Il2CppSystem-namespace objects should just return GetType, // weird specific case - if the object is an Il2CppSystem.Type, then return so manually.
// because using GetIl2CppType returns the System namespace type instead. if (cppObject is CppType)
if (type.Namespace.StartsWith("System.") || type.Namespace.StartsWith("Il2CppSystem.")) return typeof(CppType);
return cppObject.GetType();
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(); catch // (Exception ex)
{
// check if type is injected // ExplorerCore.LogWarning("Exception in GetActualType: " + ex);
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;
} }
return type; return type;

View File

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

View File

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

View File

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

View File

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

View File

@ -19,18 +19,35 @@ namespace UnityExplorer.UI.Inspectors.CacheObject
base.SetInspectorOwner(inspector, member); base.SetInspectorOwner(inspector, member);
Arguments = MethodInfo.GetParameters(); Arguments = MethodInfo.GetParameters();
if (MethodInfo.IsGenericMethod)
GenericArguments = MethodInfo.GetGenericArguments();
} }
protected override void TryEvaluate() protected override object TryEvaluate()
{ {
try 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) catch (Exception ex)
{ {
HadException = true; HadException = true;
LastException = ex; LastException = ex;
return null;
} }
} }

View File

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

View File

@ -21,16 +21,26 @@ namespace UnityExplorer.UI.Inspectors.CacheObject
Arguments = PropertyInfo.GetIndexParameters(); Arguments = PropertyInfo.GetIndexParameters();
} }
protected override void TryEvaluate() protected override object TryEvaluate()
{ {
try 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) catch (Exception ex)
{ {
HadException = true; HadException = true;
LastException = ex; LastException = ex;
return null;
} }
} }
@ -41,9 +51,13 @@ namespace UnityExplorer.UI.Inspectors.CacheObject
try 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) catch (Exception ex)
{ {

View File

@ -21,7 +21,7 @@ namespace UnityExplorer.UI.Inspectors.CacheObject.Views
protected virtual void EvaluateClicked() protected virtual void EvaluateClicked()
{ {
// TODO this.MemberOccupant.OnEvaluateClicked();
} }
protected override void ConstructEvaluateHolder(GameObject parent) 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)) 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]; cell.Button.ButtonText.text = compToStringCache[type.AssemblyQualifiedName];

View File

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

View File

@ -39,6 +39,8 @@ namespace UnityExplorer.UI.Inspectors.IValues
public override void OnBorrowed(CacheObjectBase owner) public override void OnBorrowed(CacheObjectBase owner)
{ {
base.OnBorrowed(owner); base.OnBorrowed(owner);
DictScrollPool.Refresh(true, true);
} }
public override void ReleaseFromOwner() public override void ReleaseFromOwner()
@ -83,7 +85,7 @@ namespace UnityExplorer.UI.Inspectors.IValues
CacheEntries(value); 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) if (cell.Occupant != null)
{ {
cell.Occupant.HideIValue(); cell.Occupant.HidePooledObjects();
cell.Occupant.CellView = null; cell.Occupant.CellView = null;
cell.Occupant = null; cell.Occupant = null;
} }

View File

@ -35,6 +35,8 @@ namespace UnityExplorer.UI.Inspectors.IValues
public override void OnBorrowed(CacheObjectBase owner) public override void OnBorrowed(CacheObjectBase owner)
{ {
base.OnBorrowed(owner); base.OnBorrowed(owner);
ListScrollPool.Refresh(true, true);
} }
public override void ReleaseFromOwner() public override void ReleaseFromOwner()
@ -72,7 +74,7 @@ namespace UnityExplorer.UI.Inspectors.IValues
CacheEntries(value); 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); //this.ScrollPoolLayout.minHeight = Math.Min(400f, 35f * values.Count);
@ -169,7 +171,7 @@ namespace UnityExplorer.UI.Inspectors.IValues
{ {
if (cell.Occupant != null) if (cell.Occupant != null)
{ {
cell.Occupant.HideIValue(); cell.Occupant.HidePooledObjects();
cell.Occupant.CellView = null; cell.Occupant.CellView = null;
cell.Occupant = null; cell.Occupant = null;
} }

View File

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

View File

@ -97,7 +97,7 @@ namespace UnityExplorer.UI.Panels
{ {
string text; string text;
if (m_context == SearchContext.StaticClass) if (m_context == SearchContext.StaticClass)
text = SignatureHighlighter.ParseFullType(currentResults[index] as Type, true, true); text = SignatureHighlighter.ParseType(currentResults[index] as Type, true, true);
else else
text = ToStringUtility.ToStringWithType(currentResults[index], currentResults[index]?.GetActualType()); 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 readonly Dictionary<int, Dropdown.OptionData> sceneToDropdownOption = new Dictionary<int, Dropdown.OptionData>();
private IEnumerable<GameObject> GetRootEntries() => SceneHandler.CurrentRootObjects; private IEnumerable<GameObject> GetRootEntries() => SceneHandler.CurrentRootObjects;
public void Update() public void Update()
{ {
if (AutoUpdate && Time.realtimeSinceStartup - timeOfLastUpdate >= 1f) if ((AutoUpdate || !SceneHandler.InspectingAssetScene) && Time.realtimeSinceStartup - timeOfLastUpdate >= 1f)
{ {
timeOfLastUpdate = Time.realtimeSinceStartup; timeOfLastUpdate = Time.realtimeSinceStartup;
UpdateTree(); UpdateTree();
@ -65,7 +65,7 @@ namespace UnityExplorer.UI.Panels
SceneHandler.SelectedScene = SceneHandler.LoadedScenes[value]; SceneHandler.SelectedScene = SceneHandler.LoadedScenes[value];
SceneHandler.Update(); SceneHandler.Update();
Tree.RefreshData(true); Tree.RefreshData(true);
//OnSelectedSceneChanged(SceneHandler.SelectedScene.Value); OnSelectedSceneChanged(SceneHandler.SelectedScene.Value);
} }
private void SceneHandler_OnInspectedSceneChanged(Scene scene) private void SceneHandler_OnInspectedSceneChanged(Scene scene)
@ -83,14 +83,14 @@ namespace UnityExplorer.UI.Panels
sceneDropdown.captionText.text = opt.text; sceneDropdown.captionText.text = opt.text;
} }
//OnSelectedSceneChanged(scene); OnSelectedSceneChanged(scene);
} }
//private void OnSelectedSceneChanged(Scene scene) private void OnSelectedSceneChanged(Scene scene)
//{ {
// if (refreshRow) if (refreshRow)
// refreshRow.SetActive(!scene.IsValid()); refreshRow.SetActive(!scene.IsValid());
//} }
private void SceneHandler_OnLoadedScenesChanged(ReadOnlyCollection<Scene> loadedScenes) private void SceneHandler_OnLoadedScenesChanged(ReadOnlyCollection<Scene> loadedScenes)
{ {

View File

@ -40,7 +40,7 @@ namespace UnityExplorer.UI.Panels
content.SetActive(true); content.SetActive(true);
var button = tabButtons[tabIndex]; 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; SelectedTab = tabIndex;
SaveToConfigManager(); SaveToConfigManager();
@ -49,7 +49,7 @@ namespace UnityExplorer.UI.Panels
private void DisableTab(int tabIndex) private void DisableTab(int tabIndex)
{ {
tabPages[tabIndex].SetActive(false); 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() public override void Update()
@ -97,10 +97,11 @@ namespace UnityExplorer.UI.Panels
public override void SetDefaultPosAndAnchors() public override void SetDefaultPosAndAnchors()
{ {
// todo proper default size
mainPanelRect.localPosition = Vector2.zero; mainPanelRect.localPosition = Vector2.zero;
mainPanelRect.pivot = new Vector2(0f, 1f); mainPanelRect.pivot = new Vector2(0f, 1f);
mainPanelRect.anchorMin = new Vector2(0.1f, 0.2f); mainPanelRect.anchorMin = new Vector2(0.1f, 0.25f);
mainPanelRect.anchorMax = new Vector2(0.25f, 0.9f); mainPanelRect.anchorMax = new Vector2(0.25f, 0.8f);
//mainPanelRect.anchorMin = Vector3.zero; //mainPanelRect.anchorMin = Vector3.zero;

View File

@ -227,19 +227,6 @@ namespace UnityExplorer.UI.Panels
Vector3 pos = Panel.localPosition; Vector3 pos = Panel.localPosition;
pos += (Vector3)diff; pos += (Vector3)diff;
Panel.localPosition = pos; 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() public void OnEndDrag()

View File

@ -114,9 +114,9 @@ namespace UnityExplorer.UI.Panels
if (NavButtonWanted) if (NavButtonWanted)
{ {
if (active) 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 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); NavButton = UIFactory.CreateButton(UIManager.NavbarButtonHolder, $"Button_{PanelType}", Name);
UIFactory.SetLayoutElement(NavButton.Button.gameObject, minWidth: 118, flexibleWidth: 0); 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 += () => NavButton.OnClick += () =>
{ {
UIManager.TogglePanel(PanelType); UIManager.TogglePanel(PanelType);

View File

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

View File

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

View File

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

View File

@ -24,7 +24,7 @@ namespace UnityExplorer.UI
public static float MinY(this RectTransform rect) => rect.position.y; 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; 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\CacheListEntryCell.cs" />
<Compile Include="UI\Inspectors\CacheObject\Views\CacheMemberCell.cs" /> <Compile Include="UI\Inspectors\CacheObject\Views\CacheMemberCell.cs" />
<Compile Include="UI\Inspectors\CacheObject\Views\CacheObjectCell.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\GameObjectInspector.cs" />
<Compile Include="UI\Inspectors\ICacheObjectController.cs" /> <Compile Include="UI\Inspectors\ICacheObjectController.cs" />
<Compile Include="UI\Inspectors\InspectorManager.cs" /> <Compile Include="UI\Inspectors\InspectorManager.cs" />