mirror of
https://github.com/GrahamKracker/UnityExplorer.git
synced 2025-01-09 18:48:46 +08:00
More progress, cleanups and fixes
This commit is contained in:
parent
302ff29e36
commit
a89d66cf81
@ -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)
|
||||
|
@ -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;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//}
|
@ -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.
|
||||
|
@ -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
|
@ -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;
|
||||
|
@ -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");
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -21,7 +21,7 @@ namespace UnityExplorer.UI.Inspectors.CacheObject.Views
|
||||
|
||||
protected virtual void EvaluateClicked()
|
||||
{
|
||||
// TODO
|
||||
this.MemberOccupant.OnEvaluateClicked();
|
||||
}
|
||||
|
||||
protected override void ConstructEvaluateHolder(GameObject parent)
|
||||
|
257
src/UI/Inspectors/CacheObject/Views/EvaluateWidget.cs
Normal file
257
src/UI/Inspectors/CacheObject/Views/EvaluateWidget.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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];
|
||||
|
@ -8,7 +8,7 @@ namespace UnityExplorer.UI.Inspectors
|
||||
{
|
||||
public interface ICacheObjectController
|
||||
{
|
||||
CacheObjectBase ParentCacheObject { get; } // TODO
|
||||
CacheObjectBase ParentCacheObject { get; }
|
||||
|
||||
object Target { get; }
|
||||
Type TargetType { get; }
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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());
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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;
|
||||
|
@ -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()
|
||||
|
@ -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);
|
||||
|
@ -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>();
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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" />
|
||||
|
Loading…
x
Reference in New Issue
Block a user