mirror of
https://github.com/GrahamKracker/UnityExplorer.git
synced 2025-01-09 18:48:46 +08:00
More progress
This commit is contained in:
parent
961ff80c6d
commit
e4ff86259b
@ -6,11 +6,48 @@ using System.Linq;
|
||||
using System.Reflection;
|
||||
using BF = System.Reflection.BindingFlags;
|
||||
using UnityExplorer.Core.Runtime;
|
||||
using System.Text;
|
||||
|
||||
namespace UnityExplorer
|
||||
{
|
||||
public static class ReflectionUtility
|
||||
{
|
||||
static ReflectionUtility()
|
||||
{
|
||||
foreach (var asm in AppDomain.CurrentDomain.GetAssemblies())
|
||||
CacheTypes(asm);
|
||||
|
||||
AppDomain.CurrentDomain.AssemblyLoad += AssemblyLoaded;
|
||||
}
|
||||
|
||||
private static readonly Dictionary<string, Type> allCachedTypes = new Dictionary<string, Type>();
|
||||
|
||||
private static void CacheTypes(Assembly asm)
|
||||
{
|
||||
foreach (var type in asm.TryGetTypes())
|
||||
{
|
||||
if (allCachedTypes.ContainsKey(type.FullName))
|
||||
continue;
|
||||
|
||||
if (type.FullName.ContainsIgnoreCase("PrivateImplementationDetails"))
|
||||
continue;
|
||||
|
||||
allCachedTypes.Add(type.FullName, type);
|
||||
}
|
||||
}
|
||||
|
||||
private static void AssemblyLoaded(object sender, AssemblyLoadEventArgs args)
|
||||
{
|
||||
if (args.LoadedAssembly == null)
|
||||
return;
|
||||
|
||||
s_cachedTypeInheritance.Clear();
|
||||
s_cachedGenericParameterInheritance.Clear();
|
||||
|
||||
CacheTypes(args.LoadedAssembly);
|
||||
}
|
||||
|
||||
|
||||
public const BF AllFlags = BF.Public | BF.Instance | BF.NonPublic | BF.Static;
|
||||
|
||||
public static bool ValueEqual<T>(this T objA, T objB)
|
||||
@ -119,28 +156,8 @@ namespace UnityExplorer
|
||||
/// <returns>The Type if found, otherwise null.</returns>
|
||||
public static Type GetTypeByName(string fullName)
|
||||
{
|
||||
s_typesByName.TryGetValue(fullName, out Type ret);
|
||||
|
||||
if (ret != null)
|
||||
return ret;
|
||||
|
||||
foreach (var type in from asm in AppDomain.CurrentDomain.GetAssemblies()
|
||||
from type in asm.TryGetTypes()
|
||||
select type)
|
||||
{
|
||||
if (type.FullName == fullName)
|
||||
{
|
||||
ret = type;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (s_typesByName.ContainsKey(fullName))
|
||||
s_typesByName[fullName] = ret;
|
||||
else
|
||||
s_typesByName.Add(fullName, ret);
|
||||
|
||||
return ret;
|
||||
allCachedTypes.TryGetValue(fullName, out Type type);
|
||||
return type;
|
||||
}
|
||||
|
||||
// cache for GetBaseTypes
|
||||
@ -180,49 +197,47 @@ namespace UnityExplorer
|
||||
}
|
||||
|
||||
// cache for GetImplementationsOf
|
||||
internal static readonly Dictionary<Type, HashSet<Type>> s_cachedTypeInheritance = new Dictionary<Type, HashSet<Type>>();
|
||||
internal static int s_lastAssemblyCount;
|
||||
internal static readonly Dictionary<string, HashSet<Type>> s_cachedTypeInheritance = new Dictionary<string, HashSet<Type>>();
|
||||
internal static readonly Dictionary<string, HashSet<Type>> s_cachedGenericParameterInheritance = new Dictionary<string, HashSet<Type>>();
|
||||
|
||||
/// <summary>
|
||||
/// Get all non-abstract implementations of the provided type (include itself, if not abstract) in the current AppDomain.
|
||||
/// Also works for generic parameters by analyzing the constraints.
|
||||
/// </summary>
|
||||
/// <param name="baseType">The base type, which can optionally be abstract / interface.</param>
|
||||
/// <returns>All implementations of the type in the current AppDomain.</returns>
|
||||
public static HashSet<Type> GetImplementationsOf(this Type baseType, bool allowAbstract, bool allowGeneric)
|
||||
{
|
||||
var assemblies = AppDomain.CurrentDomain.GetAssemblies();
|
||||
var key = baseType.AssemblyQualifiedName;
|
||||
|
||||
if (!s_cachedTypeInheritance.ContainsKey(baseType) || assemblies.Length != s_lastAssemblyCount)
|
||||
if (!s_cachedTypeInheritance.ContainsKey(key))
|
||||
{
|
||||
if (assemblies.Length != s_lastAssemblyCount)
|
||||
{
|
||||
s_cachedTypeInheritance.Clear();
|
||||
s_lastAssemblyCount = assemblies.Length;
|
||||
}
|
||||
|
||||
var set = new HashSet<Type>();
|
||||
|
||||
if (!baseType.IsAbstract && !baseType.IsInterface)
|
||||
set.Add(baseType);
|
||||
|
||||
foreach (var asm in assemblies)
|
||||
var keys = allCachedTypes.Keys.ToArray();
|
||||
for (int i = 0; i < keys.Length; i++)
|
||||
{
|
||||
foreach (var t in asm.TryGetTypes().Where(t => (allowAbstract || (!t.IsAbstract && !t.IsInterface))
|
||||
&& (allowGeneric || !t.IsGenericType)))
|
||||
var type = allCachedTypes[keys[i]];
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
if (baseType.IsAssignableFrom(t) && !set.Contains(t))
|
||||
set.Add(t);
|
||||
}
|
||||
catch { }
|
||||
if ((type.IsAbstract && type.IsSealed) // ignore static classes
|
||||
|| (!allowAbstract && type.IsAbstract)
|
||||
|| (!allowGeneric && (type.IsGenericType || type.IsGenericTypeDefinition)))
|
||||
continue;
|
||||
|
||||
if (baseType.IsAssignableFrom(type) && !set.Contains(type))
|
||||
set.Add(type);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
s_cachedTypeInheritance.Add(baseType, set);
|
||||
s_cachedTypeInheritance.Add(key, set);
|
||||
}
|
||||
|
||||
return s_cachedTypeInheritance[baseType];
|
||||
return s_cachedTypeInheritance[key];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -25,6 +25,15 @@ namespace UnityExplorer.Core.Runtime.Il2Cpp
|
||||
Instance = this;
|
||||
|
||||
TryLoadGameModules();
|
||||
|
||||
BuildDeobfuscationCache();
|
||||
AppDomain.CurrentDomain.AssemblyLoad += OnAssemblyLoaded;
|
||||
}
|
||||
|
||||
private void OnAssemblyLoaded(object sender, AssemblyLoadEventArgs args)
|
||||
{
|
||||
foreach (var type in args.LoadedAssembly.TryGetTypes())
|
||||
TryCacheDeobfuscatedType(type);
|
||||
}
|
||||
|
||||
public override object Cast(object obj, Type castTo)
|
||||
@ -71,10 +80,6 @@ namespace UnityExplorer.Core.Runtime.Il2Cpp
|
||||
|
||||
public override Type GetDeobfuscatedType(Type type)
|
||||
{
|
||||
if (!builtDeobCache)
|
||||
BuildDeobfuscationCache();
|
||||
|
||||
Type ret = type;
|
||||
try
|
||||
{
|
||||
var cppType = Il2CppType.From(type);
|
||||
@ -84,14 +89,11 @@ namespace UnityExplorer.Core.Runtime.Il2Cpp
|
||||
}
|
||||
catch { }
|
||||
|
||||
return ret;
|
||||
return type;
|
||||
}
|
||||
|
||||
public override string ProcessTypeFullNameInString(Type type, string theString, ref string typeName)
|
||||
{
|
||||
if (!builtDeobCache)
|
||||
BuildDeobfuscationCache();
|
||||
|
||||
if (!Il2CppTypeNotNull(type))
|
||||
return theString;
|
||||
|
||||
@ -105,27 +107,6 @@ namespace UnityExplorer.Core.Runtime.Il2Cpp
|
||||
return theString;
|
||||
}
|
||||
|
||||
//public override string ProcessTypeFullNameInString(Type type, string theString, ref string typeName)
|
||||
//{
|
||||
// if (!builtDeobCache)
|
||||
// BuildDeobfuscationCache();
|
||||
|
||||
// try
|
||||
// {
|
||||
// var cppType = Il2CppType.From(type);
|
||||
// if (s_deobfuscatedTypeNames.ContainsKey(cppType.FullName))
|
||||
// {
|
||||
// typeName = s_deobfuscatedTypeNames[cppType.FullName];
|
||||
// theString = theString.Replace(cppType.FullName, typeName);
|
||||
// }
|
||||
// }
|
||||
// catch
|
||||
// {
|
||||
// }
|
||||
|
||||
// return theString;
|
||||
//}
|
||||
|
||||
public override Type GetActualType(object obj)
|
||||
{
|
||||
if (obj == null)
|
||||
@ -161,9 +142,9 @@ namespace UnityExplorer.Core.Runtime.Il2Cpp
|
||||
return getType;
|
||||
}
|
||||
}
|
||||
catch // (Exception ex)
|
||||
catch (Exception ex)
|
||||
{
|
||||
// ExplorerCore.LogWarning("Exception in GetActualType: " + ex);
|
||||
ExplorerCore.LogWarning("Exception in GetActualType: " + ex);
|
||||
}
|
||||
|
||||
return type;
|
||||
@ -175,37 +156,36 @@ namespace UnityExplorer.Core.Runtime.Il2Cpp
|
||||
// keep deobfuscated type name cache, used to display proper name.
|
||||
internal static Dictionary<string, string> s_deobfuscatedTypeNames = new Dictionary<string, string>();
|
||||
|
||||
private static bool builtDeobCache = false;
|
||||
|
||||
private static void BuildDeobfuscationCache()
|
||||
{
|
||||
foreach (var asm in AppDomain.CurrentDomain.GetAssemblies())
|
||||
{
|
||||
foreach (var type in asm.TryGetTypes())
|
||||
{
|
||||
try
|
||||
{
|
||||
if (type.CustomAttributes.Any(it => it.AttributeType.Name == "ObfuscatedNameAttribute"))
|
||||
{
|
||||
var cppType = Il2CppType.From(type);
|
||||
|
||||
if (!Il2CppToMonoType.ContainsKey(cppType.FullName))
|
||||
{
|
||||
Il2CppToMonoType.Add(cppType.AssemblyQualifiedName, type);
|
||||
s_deobfuscatedTypeNames.Add(cppType.FullName, type.FullName);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
TryCacheDeobfuscatedType(type);
|
||||
}
|
||||
|
||||
builtDeobCache = true;
|
||||
|
||||
if (s_deobfuscatedTypeNames.Count > 0)
|
||||
ExplorerCore.Log($"Built deobfuscation cache, count: {s_deobfuscatedTypeNames.Count}");
|
||||
}
|
||||
|
||||
private static void TryCacheDeobfuscatedType(Type type)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (type.CustomAttributes.Any(it => it.AttributeType.Name == "ObfuscatedNameAttribute"))
|
||||
{
|
||||
var cppType = Il2CppType.From(type);
|
||||
|
||||
if (!Il2CppToMonoType.ContainsKey(cppType.FullName))
|
||||
{
|
||||
Il2CppToMonoType.Add(cppType.AssemblyQualifiedName, type);
|
||||
s_deobfuscatedTypeNames.Add(cppType.FullName, type.FullName);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Try to get the Mono (Unhollowed) Type representation of the provided <see cref="Il2CppSystem.Type"/>.
|
||||
/// </summary>
|
||||
@ -213,9 +193,6 @@ namespace UnityExplorer.Core.Runtime.Il2Cpp
|
||||
/// <returns>The Mono Type if found, otherwise null.</returns>
|
||||
public static Type GetMonoType(CppType cppType)
|
||||
{
|
||||
if (!builtDeobCache)
|
||||
BuildDeobfuscationCache();
|
||||
|
||||
string name = cppType.AssemblyQualifiedName;
|
||||
|
||||
if (Il2CppToMonoType.ContainsKey(name))
|
||||
@ -344,6 +321,7 @@ namespace UnityExplorer.Core.Runtime.Il2Cpp
|
||||
return false;
|
||||
}
|
||||
|
||||
// Not currently using, not sure if its necessary anymore, was necessary to prevent crashes at one point.
|
||||
public override bool IsReflectionSupported(Type type)
|
||||
{
|
||||
try
|
||||
@ -467,7 +445,6 @@ namespace UnityExplorer.Core.Runtime.Il2Cpp
|
||||
var valueList = new List<object>();
|
||||
|
||||
var hashtable = value.TryCast(typeof(Il2CppSystem.Collections.Hashtable)) as Il2CppSystem.Collections.Hashtable;
|
||||
|
||||
if (hashtable != null)
|
||||
{
|
||||
EnumerateCppHashtable(hashtable, keyList, valueList);
|
||||
|
@ -9,8 +9,8 @@ namespace UnityExplorer.Core.Search
|
||||
{
|
||||
UnityObject,
|
||||
GameObject,
|
||||
Component,
|
||||
Custom,
|
||||
//Component,
|
||||
//Custom,
|
||||
Singleton,
|
||||
StaticClass
|
||||
}
|
||||
|
@ -11,6 +11,114 @@ namespace UnityExplorer.Core.Search
|
||||
{
|
||||
public static class SearchProvider
|
||||
{
|
||||
|
||||
private static bool Filter(Scene scene, SceneFilter filter)
|
||||
{
|
||||
switch (filter)
|
||||
{
|
||||
case SceneFilter.Any:
|
||||
return true;
|
||||
case SceneFilter.DontDestroyOnLoad:
|
||||
return scene == SceneHandler.DontDestroyScene;
|
||||
case SceneFilter.HideAndDontSave:
|
||||
return scene == SceneHandler.AssetScene;
|
||||
case SceneFilter.ActivelyLoaded:
|
||||
return scene != SceneHandler.DontDestroyScene && scene != SceneHandler.AssetScene;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
internal static List<object> UnityObjectSearch(string input, string customTypeInput, SearchContext context,
|
||||
ChildFilter childFilter, SceneFilter sceneFilter)
|
||||
{
|
||||
var results = new List<object>();
|
||||
|
||||
Type searchType;
|
||||
switch (context)
|
||||
{
|
||||
case SearchContext.GameObject:
|
||||
searchType = typeof(GameObject);
|
||||
break;
|
||||
|
||||
case SearchContext.UnityObject:
|
||||
default:
|
||||
|
||||
if (!string.IsNullOrEmpty(customTypeInput))
|
||||
{
|
||||
if (ReflectionUtility.GetTypeByName(customTypeInput) is Type customType)
|
||||
{
|
||||
if (typeof(UnityEngine.Object).IsAssignableFrom(customType))
|
||||
{
|
||||
searchType = customType;
|
||||
break;
|
||||
}
|
||||
else
|
||||
ExplorerCore.LogWarning($"Custom type '{customType.FullName}' is not assignable from UnityEngine.Object!");
|
||||
}
|
||||
else
|
||||
ExplorerCore.LogWarning($"Could not find any type by name '{customTypeInput}'!");
|
||||
}
|
||||
|
||||
searchType = typeof(UnityEngine.Object);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if (searchType == null)
|
||||
return results;
|
||||
|
||||
var allObjects = RuntimeProvider.Instance.FindObjectsOfTypeAll(searchType);
|
||||
|
||||
// perform filter comparers
|
||||
|
||||
string nameFilter = null;
|
||||
if (!string.IsNullOrEmpty(input))
|
||||
nameFilter = input;
|
||||
|
||||
bool canGetGameObject = context == SearchContext.GameObject || typeof(Component).IsAssignableFrom(searchType);
|
||||
|
||||
foreach (var obj in allObjects)
|
||||
{
|
||||
// name check
|
||||
if (!string.IsNullOrEmpty(nameFilter) && !obj.name.ContainsIgnoreCase(nameFilter))
|
||||
continue;
|
||||
|
||||
if (canGetGameObject)
|
||||
{
|
||||
var go = context == SearchContext.GameObject
|
||||
? obj.TryCast<GameObject>()
|
||||
: obj.TryCast<Component>().gameObject;
|
||||
|
||||
if (go)
|
||||
{
|
||||
// scene check
|
||||
if (sceneFilter != SceneFilter.Any)
|
||||
{
|
||||
if (!Filter(go.scene, sceneFilter))
|
||||
continue;
|
||||
}
|
||||
|
||||
if (childFilter != ChildFilter.Any)
|
||||
{
|
||||
if (!go)
|
||||
continue;
|
||||
|
||||
// root object check (no parent)
|
||||
if (childFilter == ChildFilter.HasParent && !go.transform.parent)
|
||||
continue;
|
||||
else if (childFilter == ChildFilter.RootObject && go.transform.parent)
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
results.Add(obj);
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
internal static List<object> StaticClassSearch(string input)
|
||||
{
|
||||
var list = new List<object>();
|
||||
@ -76,125 +184,5 @@ namespace UnityExplorer.Core.Search
|
||||
return instances;
|
||||
}
|
||||
|
||||
private static bool Filter(Scene scene, SceneFilter filter)
|
||||
{
|
||||
switch (filter)
|
||||
{
|
||||
case SceneFilter.Any:
|
||||
return true;
|
||||
case SceneFilter.DontDestroyOnLoad:
|
||||
return scene == SceneHandler.DontDestroyScene;
|
||||
case SceneFilter.HideAndDontSave:
|
||||
return scene == SceneHandler.AssetScene;
|
||||
case SceneFilter.ActivelyLoaded:
|
||||
return scene != SceneHandler.DontDestroyScene && scene != SceneHandler.AssetScene;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
internal static List<object> UnityObjectSearch(string input, string customTypeInput, SearchContext context,
|
||||
ChildFilter childFilter, SceneFilter sceneFilter)
|
||||
{
|
||||
var results = new List<object>();
|
||||
|
||||
Type searchType = null;
|
||||
switch (context)
|
||||
{
|
||||
case SearchContext.GameObject:
|
||||
searchType = typeof(GameObject); break;
|
||||
|
||||
case SearchContext.Component:
|
||||
searchType = typeof(Component); break;
|
||||
|
||||
case SearchContext.Custom:
|
||||
if (string.IsNullOrEmpty(customTypeInput))
|
||||
{
|
||||
ExplorerCore.LogWarning("Custom Type input must not be empty!");
|
||||
return results;
|
||||
}
|
||||
if (ReflectionUtility.GetTypeByName(customTypeInput) is Type customType)
|
||||
{
|
||||
if (typeof(UnityEngine.Object).IsAssignableFrom(customType))
|
||||
searchType = customType;
|
||||
else
|
||||
ExplorerCore.LogWarning($"Custom type '{customType.FullName}' is not assignable from UnityEngine.Object!");
|
||||
}
|
||||
else
|
||||
ExplorerCore.LogWarning($"Could not find a type by the name '{customTypeInput}'!");
|
||||
break;
|
||||
|
||||
default:
|
||||
searchType = typeof(UnityEngine.Object); break;
|
||||
}
|
||||
|
||||
|
||||
if (searchType == null)
|
||||
return results;
|
||||
|
||||
var allObjects = RuntimeProvider.Instance.FindObjectsOfTypeAll(searchType);
|
||||
|
||||
// perform filter comparers
|
||||
|
||||
string nameFilter = null;
|
||||
if (!string.IsNullOrEmpty(input))
|
||||
nameFilter = input;
|
||||
|
||||
bool canGetGameObject = (sceneFilter != SceneFilter.Any || childFilter != ChildFilter.Any)
|
||||
&& (context == SearchContext.GameObject || typeof(Component).IsAssignableFrom(searchType));
|
||||
|
||||
if (!canGetGameObject)
|
||||
{
|
||||
if (context != SearchContext.UnityObject && (sceneFilter != SceneFilter.Any || childFilter != ChildFilter.Any))
|
||||
ExplorerCore.LogWarning($"Type '{searchType}' cannot have Scene or Child filters applied to it");
|
||||
}
|
||||
|
||||
foreach (var obj in allObjects)
|
||||
{
|
||||
// name check
|
||||
if (!string.IsNullOrEmpty(nameFilter) && !obj.name.ContainsIgnoreCase(nameFilter))
|
||||
continue;
|
||||
|
||||
if (canGetGameObject)
|
||||
{
|
||||
var go = context == SearchContext.GameObject
|
||||
? obj.TryCast<GameObject>()
|
||||
: obj.TryCast<Component>().gameObject;
|
||||
|
||||
// scene check
|
||||
if (sceneFilter != SceneFilter.Any)
|
||||
{
|
||||
if (!go)
|
||||
continue;
|
||||
|
||||
switch (context)
|
||||
{
|
||||
case SearchContext.GameObject:
|
||||
case SearchContext.Custom:
|
||||
case SearchContext.Component:
|
||||
if (!Filter(go.scene, sceneFilter))
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (childFilter != ChildFilter.Any)
|
||||
{
|
||||
if (!go)
|
||||
continue;
|
||||
|
||||
// root object check (no parent)
|
||||
if (childFilter == ChildFilter.HasParent && !go.transform.parent)
|
||||
continue;
|
||||
else if (childFilter == ChildFilter.RootObject && go.transform.parent)
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
results.Add(obj);
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -76,6 +76,31 @@ namespace UnityExplorer.Tests
|
||||
}
|
||||
}
|
||||
|
||||
private static void TestGeneric<T>()
|
||||
{
|
||||
ExplorerCore.Log("Test1 " + typeof(T).FullName);
|
||||
}
|
||||
|
||||
private static void TestGenericClass<T>() where T : class
|
||||
{
|
||||
ExplorerCore.Log("Test2 " + typeof(T).FullName);
|
||||
}
|
||||
|
||||
//private static void TestGenericMultiInterface<T>() where T : IEnumerable, IList, ICollection
|
||||
//{
|
||||
// ExplorerCore.Log("Test3 " + typeof(T).FullName);
|
||||
//}
|
||||
|
||||
private static void TestComponent<T>() where T : Component
|
||||
{
|
||||
ExplorerCore.Log("Test3 " + typeof(T).FullName);
|
||||
}
|
||||
|
||||
private static void TestStruct<T>() where T : struct
|
||||
{
|
||||
ExplorerCore.Log("Test3 " + typeof(T).FullName);
|
||||
}
|
||||
|
||||
private static object GetRandomObject()
|
||||
{
|
||||
object ret = null;
|
||||
|
@ -10,9 +10,21 @@ namespace UnityExplorer
|
||||
{
|
||||
private static CultureInfo _enCulture = new CultureInfo("en-US");
|
||||
|
||||
/// <summary>
|
||||
/// Check if a string contains another string, case-insensitive.
|
||||
/// </summary>
|
||||
public static bool ContainsIgnoreCase(this string _this, string s)
|
||||
{
|
||||
return _enCulture.CompareInfo.IndexOf(_this, s, CompareOptions.IgnoreCase) >= 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Just to allow Enum to do .HasFlag() in NET 3.5
|
||||
/// </summary>
|
||||
public static bool HasFlag(this Enum flags, Enum value)
|
||||
{
|
||||
ulong num = Convert.ToUInt64(value);
|
||||
return (Convert.ToUInt64(flags) & num) == num;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -81,11 +81,17 @@ namespace UnityExplorer
|
||||
}
|
||||
}
|
||||
|
||||
// long name object
|
||||
new GameObject(new string('#', 500));
|
||||
|
||||
// END
|
||||
|
||||
InspectorManager.Inspect(UIManager.CanvasRoot.gameObject.GetComponent<GraphicRaycaster>());
|
||||
//InspectorManager.Inspect(UIManager.CanvasRoot.gameObject.GetComponent<GraphicRaycaster>());
|
||||
InspectorManager.Inspect(typeof(TestClass));
|
||||
//InspectorManager.InspectType(typeof(ReflectionUtility));
|
||||
|
||||
//var tex = Resources.FindObjectsOfTypeAll<Texture2D>()[0];
|
||||
//InspectorManager.Inspect(tex);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -3,13 +3,15 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using UnityExplorer.UI.Inspectors;
|
||||
|
||||
namespace UnityExplorer.UI.Inspectors.CacheObject
|
||||
namespace UnityExplorer.UI.CacheObject
|
||||
{
|
||||
public class CacheField : CacheMember
|
||||
{
|
||||
public FieldInfo FieldInfo { get; internal set; }
|
||||
public override Type DeclaringType => FieldInfo.DeclaringType;
|
||||
public override bool IsStatic => FieldInfo.IsStatic;
|
||||
public override bool CanWrite => m_canWrite ?? (bool)(m_canWrite = !(FieldInfo.IsLiteral && !FieldInfo.IsInitOnly));
|
||||
private bool? m_canWrite;
|
||||
|
@ -2,11 +2,11 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityExplorer.UI.Inspectors.CacheObject.Views;
|
||||
using UnityExplorer.UI.Inspectors.IValues;
|
||||
using UnityExplorer.UI.CacheObject.Views;
|
||||
using UnityExplorer.UI.IValues;
|
||||
using UnityExplorer.UI.Utility;
|
||||
|
||||
namespace UnityExplorer.UI.Inspectors.CacheObject
|
||||
namespace UnityExplorer.UI.CacheObject
|
||||
{
|
||||
public class CacheKeyValuePair : CacheObjectBase
|
||||
{
|
||||
@ -52,9 +52,9 @@ namespace UnityExplorer.UI.Inspectors.CacheObject
|
||||
}
|
||||
}
|
||||
|
||||
public override void SetCell(CacheObjectCell cell)
|
||||
public override void SetDataToCell(CacheObjectCell cell)
|
||||
{
|
||||
base.SetCell(cell);
|
||||
base.SetDataToCell(cell);
|
||||
|
||||
var kvpCell = cell as CacheKeyValuePairCell;
|
||||
|
@ -2,10 +2,10 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityExplorer.UI.Inspectors.CacheObject.Views;
|
||||
using UnityExplorer.UI.Inspectors.IValues;
|
||||
using UnityExplorer.UI.CacheObject.Views;
|
||||
using UnityExplorer.UI.IValues;
|
||||
|
||||
namespace UnityExplorer.UI.Inspectors.CacheObject
|
||||
namespace UnityExplorer.UI.CacheObject
|
||||
{
|
||||
public class CacheListEntry : CacheObjectBase
|
||||
{
|
||||
@ -21,9 +21,9 @@ namespace UnityExplorer.UI.Inspectors.CacheObject
|
||||
this.ListIndex = listIndex;
|
||||
}
|
||||
|
||||
public override void SetCell(CacheObjectCell cell)
|
||||
public override void SetDataToCell(CacheObjectCell cell)
|
||||
{
|
||||
base.SetCell(cell);
|
||||
base.SetDataToCell(cell);
|
||||
|
||||
var listCell = cell as CacheListEntryCell;
|
||||
|
@ -4,11 +4,12 @@ using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityExplorer.UI.Inspectors.CacheObject.Views;
|
||||
using UnityExplorer.UI.CacheObject.Views;
|
||||
using UnityExplorer.UI.Inspectors;
|
||||
using UnityExplorer.UI.ObjectPool;
|
||||
using UnityExplorer.UI.Utility;
|
||||
|
||||
namespace UnityExplorer.UI.Inspectors.CacheObject
|
||||
namespace UnityExplorer.UI.CacheObject
|
||||
{
|
||||
public abstract class CacheMember : CacheObjectBase
|
||||
{
|
||||
@ -18,6 +19,7 @@ namespace UnityExplorer.UI.Inspectors.CacheObject
|
||||
public abstract Type DeclaringType { get; }
|
||||
public string NameForFiltering { get; protected set; }
|
||||
|
||||
public abstract bool IsStatic { get; }
|
||||
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];
|
||||
@ -43,12 +45,12 @@ namespace UnityExplorer.UI.Inspectors.CacheObject
|
||||
}
|
||||
}
|
||||
|
||||
internal override void HidePooledObjects()
|
||||
public override void UnlinkFromView()
|
||||
{
|
||||
base.HidePooledObjects();
|
||||
|
||||
if (this.Evaluator != null)
|
||||
this.Evaluator.UIRoot.transform.SetParent(Pool<EvaluateWidget>.Instance.InactiveHolder.transform, false);
|
||||
|
||||
base.UnlinkFromView();
|
||||
}
|
||||
|
||||
protected abstract object TryEvaluate();
|
||||
@ -59,7 +61,7 @@ namespace UnityExplorer.UI.Inspectors.CacheObject
|
||||
{
|
||||
Evaluate();
|
||||
if (CellView != null)
|
||||
SetCell(CellView);
|
||||
SetDataToCell(CellView);
|
||||
}
|
||||
|
||||
/// <summary>
|
@ -3,14 +3,16 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using UnityExplorer.UI.Inspectors;
|
||||
|
||||
namespace UnityExplorer.UI.Inspectors.CacheObject
|
||||
namespace UnityExplorer.UI.CacheObject
|
||||
{
|
||||
public class CacheMethod : CacheMember
|
||||
{
|
||||
public MethodInfo MethodInfo { get; internal set; }
|
||||
public override Type DeclaringType => MethodInfo.DeclaringType;
|
||||
public override bool CanWrite => false;
|
||||
public override bool IsStatic => MethodInfo.IsStatic;
|
||||
|
||||
public override bool ShouldAutoEvaluate => false;
|
||||
|
@ -5,12 +5,12 @@ using System.Reflection;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.UI.Inspectors.CacheObject.Views;
|
||||
using UnityExplorer.UI.Inspectors.IValues;
|
||||
using UnityExplorer.UI.CacheObject.Views;
|
||||
using UnityExplorer.UI.IValues;
|
||||
using UnityExplorer.UI.ObjectPool;
|
||||
using UnityExplorer.UI.Utility;
|
||||
|
||||
namespace UnityExplorer.UI.Inspectors.CacheObject
|
||||
namespace UnityExplorer.UI.CacheObject
|
||||
{
|
||||
public enum ValueState
|
||||
{
|
||||
@ -64,38 +64,32 @@ namespace UnityExplorer.UI.Inspectors.CacheObject
|
||||
|
||||
protected const string NOT_YET_EVAL = "<color=grey>Not yet evaluated</color>";
|
||||
|
||||
internal static GameObject InactiveIValueHolder
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!inactiveIValueHolder)
|
||||
{
|
||||
inactiveIValueHolder = new GameObject("InactiveIValueHolder");
|
||||
GameObject.DontDestroyOnLoad(inactiveIValueHolder);
|
||||
inactiveIValueHolder.transform.parent = UIManager.PoolHolder.transform;
|
||||
inactiveIValueHolder.SetActive(false);
|
||||
}
|
||||
return inactiveIValueHolder;
|
||||
}
|
||||
}
|
||||
private static GameObject inactiveIValueHolder;
|
||||
|
||||
// On parent destroying this
|
||||
|
||||
public virtual void ReleasePooledObjects()
|
||||
{
|
||||
if (this.IValue != null)
|
||||
ReleaseIValue();
|
||||
|
||||
// TODO release Evaluate
|
||||
|
||||
if (this.CellView != null)
|
||||
{
|
||||
this.CellView.Occupant = null;
|
||||
this.CellView.SubContentHolder.SetActive(false);
|
||||
this.CellView = null;
|
||||
}
|
||||
|
||||
UnlinkFromView();
|
||||
}
|
||||
|
||||
public virtual void SetView(CacheObjectCell cellView)
|
||||
{
|
||||
this.CellView = cellView;
|
||||
cellView.Occupant = this;
|
||||
}
|
||||
|
||||
public virtual void UnlinkFromView()
|
||||
{
|
||||
if (this.CellView == null)
|
||||
return;
|
||||
|
||||
this.CellView.Occupant = null;
|
||||
this.CellView = null;
|
||||
|
||||
if (this.IValue != null)
|
||||
this.IValue.UIRoot.transform.SetParent(InactiveIValueHolder.transform, false);
|
||||
}
|
||||
|
||||
// Updating and applying values
|
||||
@ -112,13 +106,16 @@ namespace UnityExplorer.UI.Inspectors.CacheObject
|
||||
|
||||
if (State != prevState)
|
||||
{
|
||||
// TODO handle if subcontent / evaluate shown, check type change, etc
|
||||
if (this.IValue != null)
|
||||
{
|
||||
// State has changed, need to return IValue
|
||||
ReleaseIValue();
|
||||
SubContentShowWanted = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.IValue != null)
|
||||
{
|
||||
this.IValue.SetValue(Value);
|
||||
}
|
||||
}
|
||||
|
||||
public abstract void SetUserValue(object value);
|
||||
@ -190,10 +187,12 @@ namespace UnityExplorer.UI.Inspectors.CacheObject
|
||||
this.ValueLabelText = label;
|
||||
}
|
||||
|
||||
// Setting cell state from our model
|
||||
|
||||
/// <summary>Return true if SetCell should abort, false if it should continue.</summary>
|
||||
protected abstract bool SetCellEvaluateState(CacheObjectCell cell);
|
||||
|
||||
public virtual void SetCell(CacheObjectCell cell)
|
||||
public virtual void SetDataToCell(CacheObjectCell cell)
|
||||
{
|
||||
cell.NameLabel.text = NameLabelText;
|
||||
cell.ValueLabel.gameObject.SetActive(true);
|
||||
@ -212,7 +211,6 @@ namespace UnityExplorer.UI.Inspectors.CacheObject
|
||||
{
|
||||
case ValueState.Exception:
|
||||
case ValueState.NullValue:
|
||||
ReleaseIValue();
|
||||
SetValueState(cell, ValueStateArgs.Default);
|
||||
break;
|
||||
case ValueState.Boolean:
|
||||
@ -222,18 +220,15 @@ namespace UnityExplorer.UI.Inspectors.CacheObject
|
||||
SetValueState(cell, new ValueStateArgs(false, typeLabelActive: true, inputActive: true, applyActive: CanWrite));
|
||||
break;
|
||||
case ValueState.String:
|
||||
SetIValueState();
|
||||
SetValueState(cell, new ValueStateArgs(true, false, SignatureHighlighter.StringOrange, subContentButtonActive: true));
|
||||
break;
|
||||
case ValueState.Enum:
|
||||
SetIValueState();
|
||||
SetValueState(cell, new ValueStateArgs(true, subContentButtonActive: CanWrite));
|
||||
break;
|
||||
case ValueState.Collection:
|
||||
case ValueState.Dictionary:
|
||||
case ValueState.ValueStruct:
|
||||
case ValueState.Color:
|
||||
SetIValueState();
|
||||
SetValueState(cell, new ValueStateArgs(true, inspectActive: true, subContentButtonActive: true));
|
||||
break;
|
||||
case ValueState.Unsupported:
|
||||
@ -281,16 +276,22 @@ namespace UnityExplorer.UI.Inspectors.CacheObject
|
||||
|
||||
// IValues
|
||||
|
||||
/// <summary>Called from SetCellState if SubContent button is wanted.</summary>
|
||||
public void SetIValueState()
|
||||
internal static GameObject InactiveIValueHolder
|
||||
{
|
||||
if (this.IValue == null)
|
||||
return;
|
||||
|
||||
// TODO ?
|
||||
get
|
||||
{
|
||||
if (!inactiveIValueHolder)
|
||||
{
|
||||
inactiveIValueHolder = new GameObject("Temp_IValue_Holder");
|
||||
GameObject.DontDestroyOnLoad(inactiveIValueHolder);
|
||||
inactiveIValueHolder.transform.parent = UIManager.PoolHolder.transform;
|
||||
inactiveIValueHolder.SetActive(false);
|
||||
}
|
||||
return inactiveIValueHolder;
|
||||
}
|
||||
}
|
||||
private static GameObject inactiveIValueHolder;
|
||||
|
||||
// temp for testing
|
||||
public virtual void OnCellSubContentToggle()
|
||||
{
|
||||
if (this.IValue == null)
|
||||
@ -307,7 +308,7 @@ namespace UnityExplorer.UI.Inspectors.CacheObject
|
||||
|
||||
// update our cell after creating the ivalue (the value may have updated, make sure its consistent)
|
||||
this.ProcessOnEvaluate();
|
||||
this.SetCell(this.CellView);
|
||||
this.SetDataToCell(this.CellView);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -329,14 +330,6 @@ namespace UnityExplorer.UI.Inspectors.CacheObject
|
||||
IValue = null;
|
||||
}
|
||||
|
||||
internal virtual void HidePooledObjects()
|
||||
{
|
||||
if (this.IValue == null)
|
||||
return;
|
||||
|
||||
this.IValue.UIRoot.transform.SetParent(InactiveIValueHolder.transform, false);
|
||||
}
|
||||
|
||||
// CacheObjectCell Apply
|
||||
|
||||
public virtual void OnCellApplyClicked()
|
||||
@ -363,7 +356,7 @@ namespace UnityExplorer.UI.Inspectors.CacheObject
|
||||
SetUserValue(val);
|
||||
}
|
||||
|
||||
SetCell(this.CellView);
|
||||
SetDataToCell(this.CellView);
|
||||
}
|
||||
|
||||
public struct ValueStateArgs
|
@ -3,14 +3,17 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using UnityExplorer.UI.Inspectors;
|
||||
|
||||
namespace UnityExplorer.UI.Inspectors.CacheObject
|
||||
namespace UnityExplorer.UI.CacheObject
|
||||
{
|
||||
public class CacheProperty : CacheMember
|
||||
{
|
||||
public PropertyInfo PropertyInfo { get; internal set; }
|
||||
public override Type DeclaringType => PropertyInfo.DeclaringType;
|
||||
public override bool CanWrite => PropertyInfo.CanWrite;
|
||||
public override bool IsStatic => m_isStatic ?? (bool)(m_isStatic = PropertyInfo.GetAccessors(true)[0].IsStatic);
|
||||
private bool? m_isStatic;
|
||||
|
||||
public override bool ShouldAutoEvaluate => !HasArguments;
|
||||
|
||||
@ -25,8 +28,7 @@ namespace UnityExplorer.UI.Inspectors.CacheObject
|
||||
{
|
||||
try
|
||||
{
|
||||
bool _static = PropertyInfo.GetAccessors(true)[0].IsStatic;
|
||||
var target = _static ? null : Owner.Target.TryCast(DeclaringType);
|
||||
var target = IsStatic ? null : Owner.Target.TryCast(DeclaringType);
|
||||
|
||||
if (HasArguments)
|
||||
return PropertyInfo.GetValue(target, this.Evaluator.TryParseArguments());
|
@ -2,9 +2,9 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityExplorer.UI.Inspectors.CacheObject;
|
||||
using UnityExplorer.UI.CacheObject;
|
||||
|
||||
namespace UnityExplorer.UI.Inspectors
|
||||
namespace UnityExplorer.UI.CacheObject
|
||||
{
|
||||
public interface ICacheObjectController
|
||||
{
|
@ -4,10 +4,11 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.UI.Inspectors.IValues;
|
||||
using UnityExplorer.UI.Inspectors;
|
||||
using UnityExplorer.UI.IValues;
|
||||
using UnityExplorer.UI.Widgets;
|
||||
|
||||
namespace UnityExplorer.UI.Inspectors.CacheObject.Views
|
||||
namespace UnityExplorer.UI.CacheObject.Views
|
||||
{
|
||||
public class CacheKeyValuePairCell : CacheObjectCell
|
||||
{
|
||||
@ -23,8 +24,8 @@ namespace UnityExplorer.UI.Inspectors.CacheObject.Views
|
||||
public static Color EvenColor = new Color(0.07f, 0.07f, 0.07f);
|
||||
public static Color OddColor = new Color(0.063f, 0.063f, 0.063f);
|
||||
|
||||
public int HalfWidth => (int)(0.5f * Rect.rect.width);
|
||||
public int AdjustedKeyWidth => HalfWidth - 50;
|
||||
public int HalfWidth => (int)(0.5f * Rect.rect.width) + 50;
|
||||
public int AdjustedKeyWidth => HalfWidth - 100;
|
||||
|
||||
private void KeyInspectClicked()
|
||||
{
|
||||
@ -40,6 +41,7 @@ namespace UnityExplorer.UI.Inspectors.CacheObject.Views
|
||||
this.NameLayout.minWidth = 40;
|
||||
this.NameLayout.flexibleWidth = 50;
|
||||
this.NameLayout.minHeight = 30;
|
||||
this.NameLayout.flexibleHeight = 0;
|
||||
this.NameLabel.alignment = TextAnchor.MiddleRight;
|
||||
|
||||
this.RightGroupLayout.minWidth = HalfWidth;
|
||||
@ -47,8 +49,7 @@ namespace UnityExplorer.UI.Inspectors.CacheObject.Views
|
||||
// Key area
|
||||
var keyGroup = UIFactory.CreateUIObject("KeyHolder", root.transform.Find("HoriGroup").gameObject);
|
||||
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(keyGroup, false, false, true, true, 2, 0, 0, 4, 4, childAlignment: TextAnchor.MiddleLeft);
|
||||
UIFactory.SetLayoutElement(keyGroup, minHeight: 30, minWidth: AdjustedKeyWidth, flexibleWidth: 0);
|
||||
KeyGroupLayout = keyGroup.GetComponent<LayoutElement>();
|
||||
KeyGroupLayout = UIFactory.SetLayoutElement(keyGroup, minHeight: 30, minWidth: AdjustedKeyWidth, flexibleWidth: 0);
|
||||
|
||||
// set to be after the NameLabel (our index label), and before the main horizontal group.
|
||||
keyGroup.transform.SetSiblingIndex(1);
|
||||
@ -62,17 +63,17 @@ namespace UnityExplorer.UI.Inspectors.CacheObject.Views
|
||||
// label
|
||||
|
||||
KeyLabel = UIFactory.CreateLabel(keyGroup, "KeyLabel", "<i>empty</i>", TextAnchor.MiddleLeft);
|
||||
UIFactory.SetLayoutElement(KeyLabel.gameObject, minWidth: 50, flexibleWidth: 999, minHeight: 30);
|
||||
UIFactory.SetLayoutElement(KeyLabel.gameObject, minWidth: 50, flexibleWidth: 999, minHeight: 25);
|
||||
|
||||
// Type label for input field
|
||||
|
||||
KeyInputTypeLabel = UIFactory.CreateLabel(keyGroup, "InputTypeLabel", "<i>null</i>", TextAnchor.MiddleLeft);
|
||||
UIFactory.SetLayoutElement(KeyInputTypeLabel.gameObject, minWidth: 55, flexibleWidth: 0, minHeight: 30);
|
||||
UIFactory.SetLayoutElement(KeyInputTypeLabel.gameObject, minWidth: 55, flexibleWidth: 0, minHeight: 25, flexibleHeight: 0);
|
||||
|
||||
// input field
|
||||
|
||||
var keyInputObj = UIFactory.CreateInputField(keyGroup, "KeyInput", "empty", out KeyInputField);
|
||||
UIFactory.SetLayoutElement(keyInputObj, minHeight: 30, flexibleHeight: 0, flexibleWidth: 200);
|
||||
UIFactory.SetLayoutElement(keyInputObj, minHeight: 25, flexibleHeight: 0, flexibleWidth: 200);
|
||||
//KeyInputField.lineType = InputField.LineType.MultiLineNewline;
|
||||
KeyInputField.readOnly = true;
|
||||
|
@ -4,9 +4,9 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.UI.Inspectors.IValues;
|
||||
using UnityExplorer.UI.IValues;
|
||||
|
||||
namespace UnityExplorer.UI.Inspectors.CacheObject.Views
|
||||
namespace UnityExplorer.UI.CacheObject.Views
|
||||
{
|
||||
public class CacheListEntryCell : CacheObjectCell
|
||||
{
|
||||
@ -24,7 +24,8 @@ namespace UnityExplorer.UI.Inspectors.CacheObject.Views
|
||||
|
||||
this.NameLayout.minWidth = 40;
|
||||
this.NameLayout.flexibleWidth = 50;
|
||||
this.NameLayout.minHeight = 30;
|
||||
this.NameLayout.minHeight = 25;
|
||||
this.NameLayout.flexibleHeight = 0;
|
||||
this.NameLabel.alignment = TextAnchor.MiddleRight;
|
||||
|
||||
return root;
|
@ -6,11 +6,11 @@ using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.UI.Widgets;
|
||||
|
||||
namespace UnityExplorer.UI.Inspectors.CacheObject.Views
|
||||
namespace UnityExplorer.UI.CacheObject.Views
|
||||
{
|
||||
public class CacheMemberCell : CacheObjectCell
|
||||
{
|
||||
public ReflectionInspector Owner { get; set; }
|
||||
//public ReflectionInspector Owner { get; set; }
|
||||
|
||||
public CacheMember MemberOccupant => Occupant as CacheMember;
|
||||
|
@ -4,12 +4,13 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.UI.Inspectors.IValues;
|
||||
using UnityExplorer.UI.Inspectors;
|
||||
using UnityExplorer.UI.IValues;
|
||||
using UnityExplorer.UI.ObjectPool;
|
||||
using UnityExplorer.UI.Utility;
|
||||
using UnityExplorer.UI.Widgets;
|
||||
|
||||
namespace UnityExplorer.UI.Inspectors.CacheObject.Views
|
||||
namespace UnityExplorer.UI.CacheObject.Views
|
||||
{
|
||||
public abstract class CacheObjectCell : ICell
|
||||
{
|
||||
@ -106,7 +107,7 @@ namespace UnityExplorer.UI.Inspectors.CacheObject.Views
|
||||
|
||||
UIRoot = UIFactory.CreateUIObject(this.GetType().Name, parent, new Vector2(100, 30));
|
||||
Rect = UIRoot.GetComponent<RectTransform>();
|
||||
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(UIRoot, false, false, true, true, 0, 0);
|
||||
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(UIRoot, false, false, true, true, childAlignment: TextAnchor.UpperLeft);
|
||||
UIFactory.SetLayoutElement(UIRoot, minWidth: 100, flexibleWidth: 9999, minHeight: 30, flexibleHeight: 600);
|
||||
UIRoot.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize;
|
||||
|
@ -7,8 +7,9 @@ using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.UI.ObjectPool;
|
||||
using UnityExplorer.UI.Utility;
|
||||
using UnityExplorer.UI.Widgets.AutoComplete;
|
||||
|
||||
namespace UnityExplorer.UI.Inspectors.CacheObject.Views
|
||||
namespace UnityExplorer.UI.CacheObject.Views
|
||||
{
|
||||
public class EvaluateWidget : IPooledObject
|
||||
{
|
||||
@ -117,7 +118,7 @@ namespace UnityExplorer.UI.Inspectors.CacheObject.Views
|
||||
if (genericArguments.Any())
|
||||
{
|
||||
genericArgHolder.SetActive(true);
|
||||
SetupGenericArgs();
|
||||
SetGenericRows();
|
||||
}
|
||||
else
|
||||
genericArgHolder.SetActive(false);
|
||||
@ -125,13 +126,13 @@ namespace UnityExplorer.UI.Inspectors.CacheObject.Views
|
||||
if (arguments.Any())
|
||||
{
|
||||
argHolder.SetActive(true);
|
||||
SetupArgs();
|
||||
SetNormalArgRows();
|
||||
}
|
||||
else
|
||||
argHolder.SetActive(false);
|
||||
}
|
||||
|
||||
private void SetupGenericArgs()
|
||||
private void SetGenericRows()
|
||||
{
|
||||
for (int i = 0; i < genericArguments.Length || i < genericArgRows.Count; i++)
|
||||
{
|
||||
@ -152,15 +153,18 @@ namespace UnityExplorer.UI.Inspectors.CacheObject.Views
|
||||
|
||||
genericArgRows[i].SetActive(true);
|
||||
|
||||
var constraints = arg.GetGenericParameterConstraints();
|
||||
|
||||
// TODO show "class" constraints as they dont show up, "struct" does effectively.
|
||||
|
||||
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]));
|
||||
sb.Append(SignatureHighlighter.ParseType(constraints[j]));
|
||||
|
||||
if (j + 1 == constraints.Length)
|
||||
sb.Append(')');
|
||||
@ -170,7 +174,7 @@ namespace UnityExplorer.UI.Inspectors.CacheObject.Views
|
||||
}
|
||||
}
|
||||
|
||||
private void SetupArgs()
|
||||
private void SetNormalArgRows()
|
||||
{
|
||||
for (int i = 0; i < arguments.Length || i < argRows.Count; i++)
|
||||
{
|
||||
@ -197,16 +201,17 @@ namespace UnityExplorer.UI.Inspectors.CacheObject.Views
|
||||
private void AddArgRow(int index, bool generic)
|
||||
{
|
||||
if (!generic)
|
||||
AddArgRow(index, argHolder, argRows, argLabels, argumentInput);
|
||||
AddArgRow(index, argHolder, argRows, argLabels, argumentInput);//, false);
|
||||
else
|
||||
AddArgRow(index, genericArgHolder, genericArgRows, genericArgLabels, genericInput);
|
||||
AddArgRow(index, genericArgHolder, genericArgRows, genericArgLabels, genericInput);//, true);
|
||||
}
|
||||
|
||||
private void AddArgRow(int index, GameObject parent, List<GameObject> objectList, List<Text> labelList, string[] inputArray)
|
||||
private void AddArgRow(int index, GameObject parent, List<GameObject> objectList, List<Text> labelList, string[] inputArray)//, bool autocomplete)
|
||||
{
|
||||
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);
|
||||
horiGroup.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize;
|
||||
objectList.Add(horiGroup);
|
||||
|
||||
var label = UIFactory.CreateLabel(horiGroup, "ArgLabel", "not set", TextAnchor.MiddleLeft);
|
||||
@ -215,8 +220,9 @@ namespace UnityExplorer.UI.Inspectors.CacheObject.Views
|
||||
label.horizontalOverflow = HorizontalWrapMode.Wrap;
|
||||
|
||||
var inputObj = UIFactory.CreateInputField(horiGroup, "InputField", "...", out InputField inputField);
|
||||
UIFactory.SetLayoutElement(inputObj, minHeight: 25, flexibleHeight: 0, minWidth: 100, flexibleWidth: 1000);
|
||||
UIFactory.SetLayoutElement(inputObj, minHeight: 25, flexibleHeight: 50, minWidth: 100, flexibleWidth: 1000);
|
||||
inputField.lineType = InputField.LineType.MultiLineNewline;
|
||||
inputObj.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize;
|
||||
inputField.onValueChanged.AddListener((string val) => { inputArray[index] = val; });
|
||||
inputFieldCache.Add(inputField);
|
||||
}
|
||||
@ -226,6 +232,7 @@ namespace UnityExplorer.UI.Inspectors.CacheObject.Views
|
||||
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);
|
||||
//UIRoot.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize;
|
||||
|
||||
// generic args
|
||||
this.genericArgHolder = UIFactory.CreateUIObject("GenericHolder", UIRoot);
|
||||
@ -234,6 +241,7 @@ namespace UnityExplorer.UI.Inspectors.CacheObject.Views
|
||||
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);
|
||||
//genericArgHolder.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize;
|
||||
|
||||
// args
|
||||
this.argHolder = UIFactory.CreateUIObject("ArgHolder", UIRoot);
|
||||
@ -242,6 +250,7 @@ namespace UnityExplorer.UI.Inspectors.CacheObject.Views
|
||||
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);
|
||||
//argHolder.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize;
|
||||
|
||||
// evaluate button
|
||||
var evalButton = UIFactory.CreateButton(UIRoot, "EvaluateButton", "Evaluate", new Color(0.2f, 0.2f, 0.2f));
|
@ -4,13 +4,14 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.UI.Inspectors.CacheObject;
|
||||
using UnityExplorer.UI.Inspectors.CacheObject.Views;
|
||||
using UnityExplorer.UI.CacheObject;
|
||||
using UnityExplorer.UI.CacheObject.Views;
|
||||
using UnityExplorer.UI.Inspectors;
|
||||
using UnityExplorer.UI.Panels;
|
||||
using UnityExplorer.UI.Utility;
|
||||
using UnityExplorer.UI.Widgets;
|
||||
|
||||
namespace UnityExplorer.UI.Inspectors.IValues
|
||||
namespace UnityExplorer.UI.IValues
|
||||
{
|
||||
public class InteractiveDictionary : InteractiveValue, IPoolDataSource<CacheKeyValuePairCell>, ICacheObjectController
|
||||
{
|
||||
@ -137,10 +138,8 @@ namespace UnityExplorer.UI.Inspectors.IValues
|
||||
{
|
||||
var cache = cachedEntries[i];
|
||||
if (cache.CellView != null)
|
||||
{
|
||||
cache.CellView.Occupant = null;
|
||||
cache.CellView = null;
|
||||
}
|
||||
cache.UnlinkFromView();
|
||||
|
||||
cache.ReleasePooledObjects();
|
||||
cachedEntries.RemoveAt(i);
|
||||
}
|
||||
@ -159,10 +158,7 @@ namespace UnityExplorer.UI.Inspectors.IValues
|
||||
if (index < 0 || index >= cachedEntries.Count)
|
||||
{
|
||||
if (cell.Occupant != null)
|
||||
{
|
||||
cell.Occupant.CellView = null;
|
||||
cell.Occupant = null;
|
||||
}
|
||||
cell.Occupant.UnlinkFromView();
|
||||
|
||||
cell.Disable();
|
||||
return;
|
||||
@ -170,20 +166,11 @@ namespace UnityExplorer.UI.Inspectors.IValues
|
||||
|
||||
var entry = cachedEntries[index];
|
||||
|
||||
if (entry != cell.Occupant)
|
||||
{
|
||||
if (cell.Occupant != null)
|
||||
{
|
||||
cell.Occupant.HidePooledObjects();
|
||||
cell.Occupant.CellView = null;
|
||||
cell.Occupant = null;
|
||||
}
|
||||
if (cell.Occupant != null && entry != cell.Occupant)
|
||||
cell.Occupant.UnlinkFromView();
|
||||
|
||||
cell.Occupant = entry;
|
||||
entry.CellView = cell;
|
||||
}
|
||||
|
||||
entry.SetCell(cell);
|
||||
entry.SetView(cell);
|
||||
entry.SetDataToCell(cell);
|
||||
|
||||
SetCellLayout(cell);
|
||||
}
|
@ -4,13 +4,14 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.UI.Inspectors.CacheObject;
|
||||
using UnityExplorer.UI.Inspectors.CacheObject.Views;
|
||||
using UnityExplorer.UI.CacheObject;
|
||||
using UnityExplorer.UI.CacheObject.Views;
|
||||
using UnityExplorer.UI.Inspectors;
|
||||
using UnityExplorer.UI.Panels;
|
||||
using UnityExplorer.UI.Utility;
|
||||
using UnityExplorer.UI.Widgets;
|
||||
|
||||
namespace UnityExplorer.UI.Inspectors.IValues
|
||||
namespace UnityExplorer.UI.IValues
|
||||
{
|
||||
public class InteractiveList : InteractiveValue, IPoolDataSource<CacheListEntryCell>, ICacheObjectController
|
||||
{
|
||||
@ -51,7 +52,10 @@ namespace UnityExplorer.UI.Inspectors.IValues
|
||||
values.Clear();
|
||||
|
||||
foreach (var entry in cachedEntries)
|
||||
{
|
||||
entry.UnlinkFromView();
|
||||
entry.ReleasePooledObjects();
|
||||
}
|
||||
|
||||
cachedEntries.Clear();
|
||||
}
|
||||
@ -121,10 +125,8 @@ namespace UnityExplorer.UI.Inspectors.IValues
|
||||
{
|
||||
var cache = cachedEntries[i];
|
||||
if (cache.CellView != null)
|
||||
{
|
||||
cache.CellView.Occupant = null;
|
||||
cache.CellView = null;
|
||||
}
|
||||
cache.UnlinkFromView();
|
||||
|
||||
cache.ReleasePooledObjects();
|
||||
cachedEntries.RemoveAt(i);
|
||||
}
|
||||
@ -146,20 +148,14 @@ namespace UnityExplorer.UI.Inspectors.IValues
|
||||
this.scrollLayout.minHeight = Math.Min(InspectorPanel.CurrentPanelHeight - 400f, minHeight);
|
||||
}
|
||||
|
||||
public void OnCellBorrowed(CacheListEntryCell cell)
|
||||
{
|
||||
|
||||
}
|
||||
public void OnCellBorrowed(CacheListEntryCell cell) { } // not needed
|
||||
|
||||
public void SetCell(CacheListEntryCell cell, int index)
|
||||
{
|
||||
if (index < 0 || index >= cachedEntries.Count)
|
||||
{
|
||||
if (cell.Occupant != null)
|
||||
{
|
||||
cell.Occupant.CellView = null;
|
||||
cell.Occupant = null;
|
||||
}
|
||||
cell.Occupant.UnlinkFromView();
|
||||
|
||||
cell.Disable();
|
||||
return;
|
||||
@ -167,20 +163,11 @@ namespace UnityExplorer.UI.Inspectors.IValues
|
||||
|
||||
var entry = cachedEntries[index];
|
||||
|
||||
if (entry != cell.Occupant)
|
||||
{
|
||||
if (cell.Occupant != null)
|
||||
{
|
||||
cell.Occupant.HidePooledObjects();
|
||||
cell.Occupant.CellView = null;
|
||||
cell.Occupant = null;
|
||||
}
|
||||
if (cell.Occupant != null && entry != cell.Occupant)
|
||||
cell.Occupant.UnlinkFromView();
|
||||
|
||||
cell.Occupant = entry;
|
||||
entry.CellView = cell;
|
||||
}
|
||||
|
||||
entry.SetCell(cell);
|
||||
entry.SetView(cell);
|
||||
entry.SetDataToCell(cell);
|
||||
}
|
||||
|
||||
private LayoutElement scrollLayout;
|
@ -4,10 +4,10 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.UI.Inspectors.CacheObject;
|
||||
using UnityExplorer.UI.CacheObject;
|
||||
using UnityExplorer.UI.ObjectPool;
|
||||
|
||||
namespace UnityExplorer.UI.Inspectors.IValues
|
||||
namespace UnityExplorer.UI.IValues
|
||||
{
|
||||
public class InteractiveValue : IPooledObject
|
||||
{
|
@ -37,6 +37,8 @@ namespace UnityExplorer.UI.Inspectors
|
||||
{
|
||||
Pool<InspectorTab>.Return(Tab);
|
||||
|
||||
this.Target = null;
|
||||
|
||||
Tab.TabButton.OnClick -= OnTabButtonClicked;
|
||||
Tab.CloseButton.OnClick -= OnCloseClicked;
|
||||
}
|
||||
|
@ -4,7 +4,7 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.UI.Inspectors.CacheObject;
|
||||
using UnityExplorer.UI.CacheObject;
|
||||
using UnityExplorer.UI.ObjectPool;
|
||||
using UnityExplorer.UI.Panels;
|
||||
|
||||
|
@ -5,8 +5,8 @@
|
||||
//using System.Text;
|
||||
//using UnityEngine;
|
||||
//using UnityEngine.UI;
|
||||
//using UnityExplorer.UI.Inspectors.CacheObject;
|
||||
//using UnityExplorer.UI.Inspectors.CacheObject.Views;
|
||||
//using UnityExplorer.UI.CacheObject;
|
||||
//using UnityExplorer.UI.CacheObject.Views;
|
||||
//using UnityExplorer.UI.Utility;
|
||||
//using UnityExplorer.UI.Widgets;
|
||||
|
||||
|
@ -7,8 +7,10 @@ using System.Reflection;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.UI.Inspectors.CacheObject;
|
||||
using UnityExplorer.UI.Inspectors.CacheObject.Views;
|
||||
using UnityExplorer.Core.Config;
|
||||
using UnityExplorer.Core.Runtime;
|
||||
using UnityExplorer.UI.CacheObject;
|
||||
using UnityExplorer.UI.CacheObject.Views;
|
||||
using UnityExplorer.UI.ObjectPool;
|
||||
using UnityExplorer.UI.Panels;
|
||||
using UnityExplorer.UI.Utility;
|
||||
@ -20,34 +22,57 @@ namespace UnityExplorer.UI.Inspectors
|
||||
{
|
||||
public CacheObjectBase ParentCacheObject { get; set; }
|
||||
|
||||
public bool StaticOnly { get; internal set; }
|
||||
|
||||
//public object Target { get; private set; }
|
||||
public Type TargetType { get; private set; }
|
||||
public bool CanWrite => true;
|
||||
|
||||
public ScrollPool<CacheMemberCell> MemberScrollPool { get; private set; }
|
||||
// Instance state
|
||||
|
||||
public bool StaticOnly { get; internal set; }
|
||||
|
||||
public BindingFlags FlagsFilter { get; private set; }
|
||||
public string NameFilter { get; private set; }
|
||||
|
||||
public bool AutoUpdateWanted { get; set; }
|
||||
|
||||
private List<CacheMember> members = new List<CacheMember>();
|
||||
private readonly List<CacheMember> filteredMembers = new List<CacheMember>();
|
||||
// private readonly HashSet<CacheMember> displayedMembers = new HashSet<CacheMember>();
|
||||
|
||||
|
||||
// UI
|
||||
|
||||
public ScrollPool<CacheMemberCell> MemberScrollPool { get; private set; }
|
||||
|
||||
public Text NameText;
|
||||
public Text AssemblyText;
|
||||
|
||||
private LayoutElement memberTitleLayout;
|
||||
// Unity object helpers
|
||||
private UnityEngine.Object ObjectRef;
|
||||
private Component ComponentRef;
|
||||
private Texture2D TextureRef;
|
||||
private bool TextureViewerWanted;
|
||||
private GameObject unityObjectRow;
|
||||
private ButtonRef gameObjectButton;
|
||||
private InputField nameInput;
|
||||
private InputField instanceIdInput;
|
||||
private ButtonRef textureButton;
|
||||
private GameObject textureViewer;
|
||||
|
||||
private readonly Color disabledButtonColor = new Color(0.24f, 0.24f, 0.24f);
|
||||
private readonly Color enabledButtonColor = new Color(0.2f, 0.27f, 0.2f);
|
||||
private readonly Dictionary<BindingFlags, ButtonRef> scopeFilterButtons = new Dictionary<BindingFlags, ButtonRef>();
|
||||
private InputField filterInputField;
|
||||
|
||||
//private LayoutElement memberTitleLayout;
|
||||
|
||||
public bool AutoUpdateWanted { get; set; }
|
||||
private Toggle autoUpdateToggle;
|
||||
|
||||
public override void OnBorrowedFromPool(object target)
|
||||
{
|
||||
base.OnBorrowedFromPool(target);
|
||||
CalculateLayouts();
|
||||
|
||||
SetTitleLayouts();
|
||||
SetTarget(target);
|
||||
|
||||
MemberScrollPool.Refresh(true, true);
|
||||
RuntimeProvider.Instance.StartCoroutine(InitCoroutine());
|
||||
}
|
||||
|
||||
@ -58,10 +83,18 @@ namespace UnityExplorer.UI.Inspectors
|
||||
LayoutRebuilder.ForceRebuildLayoutImmediate(InspectorPanel.Instance.ContentRect);
|
||||
}
|
||||
|
||||
protected override void OnCloseClicked()
|
||||
{
|
||||
InspectorManager.ReleaseInspector(this);
|
||||
}
|
||||
|
||||
public override void OnReturnToPool()
|
||||
{
|
||||
foreach (var member in members)
|
||||
{
|
||||
member.UnlinkFromView();
|
||||
member.ReleasePooledObjects();
|
||||
}
|
||||
|
||||
members.Clear();
|
||||
filteredMembers.Clear();
|
||||
@ -69,9 +102,16 @@ namespace UnityExplorer.UI.Inspectors
|
||||
autoUpdateToggle.isOn = false;
|
||||
AutoUpdateWanted = false;
|
||||
|
||||
ObjectRef = null;
|
||||
ComponentRef = null;
|
||||
TextureRef = null;
|
||||
CleanupTextureViewer();
|
||||
|
||||
base.OnReturnToPool();
|
||||
}
|
||||
|
||||
// Setting target
|
||||
|
||||
private void SetTarget(object target)
|
||||
{
|
||||
string prefix;
|
||||
@ -87,50 +127,33 @@ namespace UnityExplorer.UI.Inspectors
|
||||
prefix = "[R]";
|
||||
}
|
||||
|
||||
// Setup main labels and tab text
|
||||
Tab.TabText.text = $"{prefix} {SignatureHighlighter.ParseType(TargetType)}";
|
||||
|
||||
NameText.text = SignatureHighlighter.ParseFullSyntax(TargetType, true);
|
||||
|
||||
string asmText;
|
||||
if (TargetType.Assembly != null && !string.IsNullOrEmpty(TargetType.Assembly.Location))
|
||||
asmText = Path.GetFileName(TargetType.Assembly.Location);
|
||||
asmText = Path.GetFileName(TargetType.Assembly.Location);
|
||||
else
|
||||
asmText = $"{TargetType.Assembly.GetName().Name} <color=grey><i>(in memory)</i></color>";
|
||||
AssemblyText.text = $"<color=grey>Assembly:</color> {asmText}";
|
||||
|
||||
// unity helpers
|
||||
SetUnityTargets();
|
||||
|
||||
// Get cache members, and set filter to default
|
||||
this.members = CacheMember.GetCacheMembers(Target, TargetType, this);
|
||||
FilterMembers();
|
||||
this.filterInputField.text = "";
|
||||
SetFilter("", StaticOnly ? BindingFlags.Static : BindingFlags.Instance);
|
||||
refreshWanted = true;
|
||||
}
|
||||
|
||||
public void FilterMembers()
|
||||
{
|
||||
// todo
|
||||
for (int i = 0; i < members.Count; i++)
|
||||
{
|
||||
var member = members[i];
|
||||
filteredMembers.Add(member);
|
||||
}
|
||||
// Updating
|
||||
|
||||
//MemberScrollPool.Refresh
|
||||
}
|
||||
|
||||
public override void OnSetActive()
|
||||
{
|
||||
base.OnSetActive();
|
||||
}
|
||||
|
||||
public override void OnSetInactive()
|
||||
{
|
||||
base.OnSetInactive();
|
||||
}
|
||||
|
||||
protected override void OnCloseClicked()
|
||||
{
|
||||
InspectorManager.ReleaseInspector(this);
|
||||
}
|
||||
|
||||
private float timeOfLastUpdate;
|
||||
private bool refreshWanted;
|
||||
private string lastNameFilter;
|
||||
private BindingFlags lastFlagsFilter;
|
||||
private float timeOfLastAutoUpdate;
|
||||
|
||||
public override void Update()
|
||||
{
|
||||
@ -143,15 +166,68 @@ namespace UnityExplorer.UI.Inspectors
|
||||
return;
|
||||
}
|
||||
|
||||
if (timeOfLastUpdate.OccuredEarlierThan(1))
|
||||
if (refreshWanted || NameFilter != lastNameFilter || FlagsFilter != lastFlagsFilter)
|
||||
{
|
||||
timeOfLastUpdate = Time.realtimeSinceStartup;
|
||||
lastNameFilter = NameFilter;
|
||||
lastFlagsFilter = FlagsFilter;
|
||||
|
||||
FilterMembers();
|
||||
MemberScrollPool.Refresh(true, true);
|
||||
refreshWanted = false;
|
||||
}
|
||||
|
||||
if (timeOfLastAutoUpdate.OccuredEarlierThan(1))
|
||||
{
|
||||
timeOfLastAutoUpdate = Time.realtimeSinceStartup;
|
||||
|
||||
if (AutoUpdateWanted)
|
||||
UpdateDisplayedMembers();// true);
|
||||
}
|
||||
}
|
||||
|
||||
// Filtering
|
||||
|
||||
public void SetFilter(string filter) => SetFilter(filter, FlagsFilter);
|
||||
|
||||
public void SetFilter(BindingFlags flagsFilter) => SetFilter(NameFilter, flagsFilter);
|
||||
|
||||
public void SetFilter(string nameFilter, BindingFlags flagsFilter)
|
||||
{
|
||||
this.NameFilter = nameFilter;
|
||||
|
||||
if (flagsFilter != FlagsFilter)
|
||||
{
|
||||
var btn = scopeFilterButtons[FlagsFilter].Button;
|
||||
RuntimeProvider.Instance.SetColorBlock(btn, disabledButtonColor, disabledButtonColor * 1.3f);
|
||||
|
||||
this.FlagsFilter = flagsFilter;
|
||||
btn = scopeFilterButtons[FlagsFilter].Button;
|
||||
RuntimeProvider.Instance.SetColorBlock(btn, enabledButtonColor, enabledButtonColor * 1.3f);
|
||||
}
|
||||
}
|
||||
|
||||
private void FilterMembers()
|
||||
{
|
||||
filteredMembers.Clear();
|
||||
|
||||
for (int i = 0; i < members.Count; i++)
|
||||
{
|
||||
var member = members[i];
|
||||
|
||||
if (!string.IsNullOrEmpty(NameFilter) && !member.NameForFiltering.ContainsIgnoreCase(NameFilter))
|
||||
continue;
|
||||
|
||||
if (FlagsFilter != BindingFlags.Default)
|
||||
{
|
||||
if (FlagsFilter == BindingFlags.Instance && member.IsStatic
|
||||
|| FlagsFilter == BindingFlags.Static && !member.IsStatic)
|
||||
continue;
|
||||
}
|
||||
|
||||
filteredMembers.Add(member);
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateDisplayedMembers()// bool onlyAutoUpdate)
|
||||
{
|
||||
bool shouldRefresh = false;
|
||||
@ -164,7 +240,7 @@ namespace UnityExplorer.UI.Inspectors
|
||||
{
|
||||
shouldRefresh = true;
|
||||
member.Evaluate();
|
||||
member.SetCell(member.CellView);
|
||||
member.SetDataToCell(member.CellView);
|
||||
}
|
||||
}
|
||||
|
||||
@ -176,20 +252,14 @@ namespace UnityExplorer.UI.Inspectors
|
||||
|
||||
public int ItemCount => filteredMembers.Count;
|
||||
|
||||
public void OnCellBorrowed(CacheMemberCell cell)
|
||||
{
|
||||
cell.Owner = this;
|
||||
}
|
||||
public void OnCellBorrowed(CacheMemberCell cell) { } // not needed
|
||||
|
||||
public void SetCell(CacheMemberCell cell, int index)
|
||||
{
|
||||
if (index < 0 || index >= filteredMembers.Count)
|
||||
{
|
||||
if (cell.Occupant != null)
|
||||
{
|
||||
cell.Occupant.CellView = null;
|
||||
cell.Occupant = null;
|
||||
}
|
||||
cell.Occupant.UnlinkFromView();
|
||||
|
||||
cell.Disable();
|
||||
return;
|
||||
@ -197,20 +267,11 @@ namespace UnityExplorer.UI.Inspectors
|
||||
|
||||
var member = filteredMembers[index];
|
||||
|
||||
if (member != cell.Occupant)
|
||||
{
|
||||
if (cell.Occupant != null)
|
||||
{
|
||||
cell.Occupant.HidePooledObjects();
|
||||
cell.Occupant.CellView = null;
|
||||
cell.Occupant = null;
|
||||
}
|
||||
if (cell.Occupant != null && member != cell.Occupant)
|
||||
cell.Occupant.UnlinkFromView();
|
||||
|
||||
cell.Occupant = member;
|
||||
member.CellView = cell;
|
||||
}
|
||||
|
||||
member.SetCell(cell);
|
||||
member.SetView(cell);
|
||||
member.SetDataToCell(cell);
|
||||
|
||||
SetCellLayout(cell);
|
||||
}
|
||||
@ -220,13 +281,21 @@ namespace UnityExplorer.UI.Inspectors
|
||||
private static int LeftGroupWidth { get; set; }
|
||||
private static int RightGroupWidth { get; set; }
|
||||
|
||||
private void SetTitleLayouts()
|
||||
internal void SetLayouts()
|
||||
{
|
||||
CalculateLayouts();
|
||||
|
||||
foreach (var cell in MemberScrollPool.CellPool)
|
||||
SetCellLayout(cell);
|
||||
}
|
||||
|
||||
private void CalculateLayouts()
|
||||
{
|
||||
// Calculate sizes
|
||||
LeftGroupWidth = (int)Math.Max(200, (0.45f * InspectorManager.PanelWidth) - 5);// Math.Min(450f, 0.4f * InspectorManager.PanelWidth - 5));
|
||||
RightGroupWidth = (int)Math.Max(200, InspectorManager.PanelWidth - LeftGroupWidth - 55);
|
||||
LeftGroupWidth = (int)Math.Max(200, (0.4f * InspectorManager.PanelWidth) - 5);// Math.Min(450f, 0.4f * InspectorManager.PanelWidth - 5));
|
||||
RightGroupWidth = (int)Math.Max(200, InspectorManager.PanelWidth - LeftGroupWidth - 65);
|
||||
|
||||
memberTitleLayout.minWidth = LeftGroupWidth;
|
||||
//memberTitleLayout.minWidth = LeftGroupWidth;
|
||||
}
|
||||
|
||||
private void SetCellLayout(CacheObjectCell cell)
|
||||
@ -238,57 +307,40 @@ namespace UnityExplorer.UI.Inspectors
|
||||
cell.Occupant.IValue.SetLayout();
|
||||
}
|
||||
|
||||
internal void SetLayouts()
|
||||
{
|
||||
SetTitleLayouts();
|
||||
// UI Construction
|
||||
|
||||
foreach (var cell in MemberScrollPool.CellPool)
|
||||
SetCellLayout(cell);
|
||||
}
|
||||
private GameObject mainContentHolder;
|
||||
|
||||
public override GameObject CreateContent(GameObject parent)
|
||||
{
|
||||
UIRoot = UIFactory.CreateVerticalGroup(parent, "ReflectionInspector", true, true, true, true, 5,
|
||||
new Vector4(4, 4, 4, 4), new Color(0.12f, 0.12f, 0.12f));
|
||||
UIRoot = UIFactory.CreateVerticalGroup(parent, "ReflectionInspector", true, true, true, true, 5,
|
||||
new Vector4(4, 4, 4, 4), new Color(0.065f, 0.065f, 0.065f));
|
||||
|
||||
// Class name, assembly. TODO more details
|
||||
// Class name, assembly
|
||||
|
||||
NameText = UIFactory.CreateLabel(UIRoot, "Title", "not set", TextAnchor.MiddleLeft, fontSize: 20);
|
||||
NameText = UIFactory.CreateLabel(UIRoot, "Title", "not set", TextAnchor.MiddleLeft, fontSize: 17);
|
||||
UIFactory.SetLayoutElement(NameText.gameObject, minHeight: 25, flexibleHeight: 0);
|
||||
|
||||
AssemblyText = UIFactory.CreateLabel(UIRoot, "AssemblyLabel", "not set", TextAnchor.MiddleLeft);
|
||||
UIFactory.SetLayoutElement(AssemblyText.gameObject, minHeight: 25, flexibleWidth: 9999);
|
||||
|
||||
// TODO filter row
|
||||
ConstructUnityObjectRow();
|
||||
|
||||
mainContentHolder = UIFactory.CreateVerticalGroup(UIRoot, "MemberHolder", false, false, true, true, 5, new Vector4(2,2,2,2),
|
||||
new Color(0.12f, 0.12f, 0.12f));
|
||||
UIFactory.SetLayoutElement(mainContentHolder, flexibleWidth: 9999, flexibleHeight: 9999);
|
||||
|
||||
ConstructFilterRow(mainContentHolder);
|
||||
|
||||
// Member list titles
|
||||
|
||||
var listTitles = UIFactory.CreateUIObject("ListTitles", UIRoot);
|
||||
UIFactory.SetLayoutElement(listTitles, minHeight: 25);
|
||||
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(listTitles, true, true, true, true, 5, 1, 1, 1, 1);
|
||||
|
||||
var memberTitle = UIFactory.CreateLabel(listTitles, "MemberTitle", "Member Name", TextAnchor.LowerLeft, Color.grey, fontSize: 15);
|
||||
memberTitleLayout = memberTitle.gameObject.AddComponent<LayoutElement>();
|
||||
|
||||
var valueTitle = UIFactory.CreateLabel(listTitles, "ValueTitle", "Value", TextAnchor.LowerLeft, Color.grey, fontSize: 15);
|
||||
UIFactory.SetLayoutElement(valueTitle.gameObject, minWidth: 50, flexibleWidth: 9999);
|
||||
|
||||
var updateButton = UIFactory.CreateButton(listTitles, "UpdateButton", "Update displayed values", new Color(0.22f, 0.28f, 0.22f));
|
||||
UIFactory.SetLayoutElement(updateButton.Button.gameObject, minHeight: 25, minWidth: 160, flexibleWidth: 0);
|
||||
updateButton.OnClick += UpdateDisplayedMembers;
|
||||
|
||||
var toggleObj = UIFactory.CreateToggle(listTitles, "AutoUpdateToggle", out autoUpdateToggle, out Text toggleText);
|
||||
//GameObject.DestroyImmediate(toggleText);
|
||||
UIFactory.SetLayoutElement(toggleObj, minWidth: 185, minHeight: 25);
|
||||
autoUpdateToggle.isOn = false;
|
||||
autoUpdateToggle.onValueChanged.AddListener((bool val) => { AutoUpdateWanted = val; });
|
||||
toggleText.text = "Auto-update displayed";
|
||||
ConstructUpdateRow(mainContentHolder);
|
||||
|
||||
// Member scroll pool
|
||||
|
||||
MemberScrollPool = UIFactory.CreateScrollPool<CacheMemberCell>(UIRoot, "MemberList", out GameObject scrollObj,
|
||||
var memberBorder = UIFactory.CreateVerticalGroup(mainContentHolder, "ScrollPoolHolder", false, false, true, true, padding: new Vector4(2,2,2,2),
|
||||
bgColor: new Color(0.05f, 0.05f, 0.05f));
|
||||
UIFactory.SetLayoutElement(memberBorder, flexibleWidth: 9999, flexibleHeight: 9999);
|
||||
|
||||
MemberScrollPool = UIFactory.CreateScrollPool<CacheMemberCell>(memberBorder, "MemberList", out GameObject scrollObj,
|
||||
out GameObject _, new Color(0.09f, 0.09f, 0.09f));
|
||||
UIFactory.SetLayoutElement(scrollObj, flexibleHeight: 9999);
|
||||
MemberScrollPool.Initialize(this);
|
||||
@ -299,5 +351,278 @@ namespace UnityExplorer.UI.Inspectors
|
||||
|
||||
return UIRoot;
|
||||
}
|
||||
|
||||
// Filter row
|
||||
|
||||
private void ConstructFilterRow(GameObject parent)
|
||||
{
|
||||
var filterRow = UIFactory.CreateUIObject("FilterRow", parent);
|
||||
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(filterRow, true, true, true, true, 5, 2, 2, 2, 2);
|
||||
UIFactory.SetLayoutElement(filterRow, minHeight: 25, flexibleHeight: 0, flexibleWidth: 9999);
|
||||
|
||||
var nameLabel = UIFactory.CreateLabel(filterRow, "NameFilterLabel", "Filter names:", TextAnchor.MiddleLeft, Color.grey);
|
||||
UIFactory.SetLayoutElement(nameLabel.gameObject, minHeight: 25, minWidth: 90, flexibleWidth: 0);
|
||||
var nameFilterObj = UIFactory.CreateInputField(filterRow, "NameFilterInput", "...", out filterInputField);
|
||||
UIFactory.SetLayoutElement(nameFilterObj, minHeight: 25, flexibleWidth: 300);
|
||||
filterInputField.onValueChanged.AddListener((string val) => { SetFilter(val); });
|
||||
|
||||
var spacer = UIFactory.CreateUIObject("Spacer", filterRow);
|
||||
UIFactory.SetLayoutElement(spacer, minWidth: 25);
|
||||
|
||||
var scopeLabel = UIFactory.CreateLabel(filterRow, "ScopeLabel", "Scope:", TextAnchor.MiddleLeft, Color.grey);
|
||||
UIFactory.SetLayoutElement(scopeLabel.gameObject, minHeight: 25, minWidth: 60, flexibleWidth: 0);
|
||||
AddFilterButton(filterRow, BindingFlags.Default, true);
|
||||
AddFilterButton(filterRow, BindingFlags.Instance);
|
||||
AddFilterButton(filterRow, BindingFlags.Static);
|
||||
}
|
||||
|
||||
private void AddFilterButton(GameObject parent, BindingFlags flags, bool setAsActive = false)
|
||||
{
|
||||
string lbl = flags == BindingFlags.Default ? "All" : flags.ToString();
|
||||
var color = setAsActive ? enabledButtonColor : disabledButtonColor;
|
||||
|
||||
var button = UIFactory.CreateButton(parent, "Filter_" + flags, lbl, color);
|
||||
UIFactory.SetLayoutElement(button.Button.gameObject, minHeight: 25, flexibleHeight: 0, minWidth: 100, flexibleWidth: 0);
|
||||
scopeFilterButtons.Add(flags, button);
|
||||
|
||||
button.OnClick += () => { SetFilter(flags); };
|
||||
}
|
||||
|
||||
// Update row
|
||||
|
||||
private void ConstructUpdateRow(GameObject parent)
|
||||
{
|
||||
var updateRow = UIFactory.CreateUIObject("UpdateRow", parent);
|
||||
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(updateRow, false, false, true, true, 4);
|
||||
UIFactory.SetLayoutElement(updateRow, minHeight: 25, flexibleHeight: 0, flexibleWidth: 9999);
|
||||
|
||||
var updateButton = UIFactory.CreateButton(updateRow, "UpdateButton", "Update displayed values", new Color(0.22f, 0.28f, 0.22f));
|
||||
UIFactory.SetLayoutElement(updateButton.Button.gameObject, minHeight: 25, minWidth: 175, flexibleWidth: 0);
|
||||
updateButton.OnClick += UpdateDisplayedMembers;
|
||||
|
||||
var toggleObj = UIFactory.CreateToggle(updateRow, "AutoUpdateToggle", out autoUpdateToggle, out Text toggleText);
|
||||
//GameObject.DestroyImmediate(toggleText);
|
||||
UIFactory.SetLayoutElement(toggleObj, minWidth: 185, minHeight: 25);
|
||||
autoUpdateToggle.isOn = false;
|
||||
autoUpdateToggle.onValueChanged.AddListener((bool val) => { AutoUpdateWanted = val; });
|
||||
toggleText.text = "Auto-update displayed";
|
||||
}
|
||||
|
||||
#region UNITY OBJECT SPECIFIC
|
||||
|
||||
// Unity object helpers
|
||||
|
||||
private void SetUnityTargets()
|
||||
{
|
||||
if (!typeof(UnityEngine.Object).IsAssignableFrom(TargetType))
|
||||
{
|
||||
unityObjectRow.SetActive(false);
|
||||
textureViewer.SetActive(false);
|
||||
return;
|
||||
}
|
||||
|
||||
ObjectRef = (UnityEngine.Object)Target.TryCast(typeof(UnityEngine.Object));
|
||||
unityObjectRow.SetActive(true);
|
||||
|
||||
nameInput.text = ObjectRef.name;
|
||||
instanceIdInput.text = ObjectRef.GetInstanceID().ToString();
|
||||
|
||||
if (typeof(Component).IsAssignableFrom(TargetType))
|
||||
{
|
||||
ComponentRef = (Component)Target.TryCast(typeof(Component));
|
||||
gameObjectButton.Button.gameObject.SetActive(true);
|
||||
}
|
||||
else
|
||||
gameObjectButton.Button.gameObject.SetActive(false);
|
||||
|
||||
if (typeof(Texture2D).IsAssignableFrom(TargetType))
|
||||
{
|
||||
TextureRef = (Texture2D)Target.TryCast(typeof(Texture2D));
|
||||
textureButton.Button.gameObject.SetActive(true);
|
||||
}
|
||||
else
|
||||
textureButton.Button.gameObject.SetActive(false);
|
||||
}
|
||||
|
||||
private void OnGameObjectButtonClicked()
|
||||
{
|
||||
if (!ComponentRef)
|
||||
{
|
||||
ExplorerCore.LogWarning("Component reference is null or destroyed!");
|
||||
return;
|
||||
}
|
||||
|
||||
InspectorManager.Inspect(ComponentRef.gameObject);
|
||||
}
|
||||
|
||||
private void ToggleTextureViewer()
|
||||
{
|
||||
if (TextureViewerWanted)
|
||||
{
|
||||
// disable
|
||||
TextureViewerWanted = false;
|
||||
textureViewer.gameObject.SetActive(false);
|
||||
mainContentHolder.SetActive(true);
|
||||
textureButton.ButtonText.text = "View Texture";
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!textureImage.sprite)
|
||||
{
|
||||
// First show, need to create sprite for displaying texture
|
||||
SetTextureViewer();
|
||||
}
|
||||
|
||||
// enable
|
||||
TextureViewerWanted = true;
|
||||
textureViewer.gameObject.SetActive(true);
|
||||
mainContentHolder.gameObject.SetActive(false);
|
||||
textureButton.ButtonText.text = "Hide Texture";
|
||||
}
|
||||
}
|
||||
|
||||
// UI construction
|
||||
|
||||
private void ConstructUnityObjectRow()
|
||||
{
|
||||
unityObjectRow = UIFactory.CreateUIObject("UnityObjectRow", UIRoot);
|
||||
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(unityObjectRow, false, false, true, true, 5);
|
||||
UIFactory.SetLayoutElement(unityObjectRow, minHeight: 25, flexibleHeight: 0, flexibleWidth: 9999);
|
||||
|
||||
textureButton = UIFactory.CreateButton(unityObjectRow, "TextureButton", "View Texture", new Color(0.2f, 0.2f, 0.2f));
|
||||
UIFactory.SetLayoutElement(textureButton.Button.gameObject, minHeight: 25, minWidth: 150);
|
||||
textureButton.OnClick += ToggleTextureViewer;
|
||||
|
||||
gameObjectButton = UIFactory.CreateButton(unityObjectRow, "GameObjectButton", "Inspect GameObject", new Color(0.2f, 0.2f, 0.2f));
|
||||
UIFactory.SetLayoutElement(gameObjectButton.Button.gameObject, minHeight: 25, minWidth: 170);
|
||||
gameObjectButton.OnClick += OnGameObjectButtonClicked;
|
||||
|
||||
var nameLabel = UIFactory.CreateLabel(unityObjectRow, "NameLabel", "Name:", TextAnchor.MiddleLeft, Color.grey);
|
||||
UIFactory.SetLayoutElement(nameLabel.gameObject, minHeight: 25, minWidth: 45, flexibleWidth: 0);
|
||||
|
||||
var nameInputObj = UIFactory.CreateInputField(unityObjectRow, "NameInput", "untitled", out nameInput);
|
||||
UIFactory.SetLayoutElement(nameInputObj, minHeight: 25, minWidth: 100, flexibleWidth: 1000);
|
||||
nameInput.readOnly = true;
|
||||
|
||||
var instanceLabel = UIFactory.CreateLabel(unityObjectRow, "InstanceLabel", "Instance ID:", TextAnchor.MiddleRight, Color.grey);
|
||||
UIFactory.SetLayoutElement(instanceLabel.gameObject, minHeight: 25, minWidth: 100, flexibleWidth: 0);
|
||||
|
||||
var instanceInputObj = UIFactory.CreateInputField(unityObjectRow, "InstanceIDInput", "ERROR", out instanceIdInput);
|
||||
UIFactory.SetLayoutElement(instanceInputObj, minHeight: 25, minWidth: 100, flexibleWidth: 0);
|
||||
instanceIdInput.readOnly = true;
|
||||
|
||||
unityObjectRow.SetActive(false);
|
||||
|
||||
ConstructTextureHelper();
|
||||
}
|
||||
|
||||
// Texture viewer helper
|
||||
|
||||
private InputField textureSavePathInput;
|
||||
private Image textureImage;
|
||||
private LayoutElement textureImageLayout;
|
||||
|
||||
private void CleanupTextureViewer()
|
||||
{
|
||||
if (textureImage.sprite)
|
||||
GameObject.Destroy(textureImage.sprite);
|
||||
|
||||
if (TextureViewerWanted)
|
||||
ToggleTextureViewer();
|
||||
}
|
||||
|
||||
private void ConstructTextureHelper()
|
||||
{
|
||||
textureViewer = UIFactory.CreateVerticalGroup(UIRoot, "TextureViewer", false, false, true, true, 2, new Vector4(5, 5, 5, 5),
|
||||
new Color(0.1f, 0.1f, 0.1f));
|
||||
UIFactory.SetLayoutElement(textureViewer, flexibleWidth: 9999, flexibleHeight: 9999);
|
||||
|
||||
// Save helper
|
||||
|
||||
var saveRowObj = UIFactory.CreateHorizontalGroup(textureViewer, "SaveRow", false, false, true, true, 2, new Vector4(2, 2, 2, 2),
|
||||
new Color(0.1f, 0.1f, 0.1f));
|
||||
|
||||
var saveBtn = UIFactory.CreateButton(saveRowObj, "SaveButton", "Save .PNG", new Color(0.2f, 0.25f, 0.2f));
|
||||
UIFactory.SetLayoutElement(saveBtn.Button.gameObject, minHeight: 25, minWidth: 100, flexibleWidth: 0);
|
||||
saveBtn.OnClick += OnSaveTextureClicked;
|
||||
|
||||
var inputObj = UIFactory.CreateInputField(saveRowObj, "SaveInput", "...", out textureSavePathInput);
|
||||
UIFactory.SetLayoutElement(inputObj, minHeight: 25, minWidth: 100, flexibleWidth: 9999);
|
||||
|
||||
// Actual texture viewer
|
||||
|
||||
var imageObj = UIFactory.CreateUIObject("TextureViewerImage", textureViewer);
|
||||
textureImage = imageObj.AddComponent<Image>();
|
||||
textureImageLayout = textureImage.gameObject.AddComponent<LayoutElement>();
|
||||
|
||||
var fitter = imageObj.AddComponent<ContentSizeFitter>();
|
||||
fitter.verticalFit = ContentSizeFitter.FitMode.PreferredSize;
|
||||
|
||||
textureViewer.SetActive(false);
|
||||
}
|
||||
|
||||
private void SetTextureViewer()
|
||||
{
|
||||
if (!this.TextureRef)
|
||||
return;
|
||||
|
||||
var name = TextureRef.name;
|
||||
if (string.IsNullOrEmpty(name))
|
||||
name = "untitled";
|
||||
|
||||
textureSavePathInput.text = Path.Combine(ConfigManager.Default_Output_Path.Value, $"{name}.png");
|
||||
|
||||
var sprite = TextureUtilProvider.Instance.CreateSprite(TextureRef);
|
||||
textureImage.sprite = sprite;
|
||||
|
||||
textureImageLayout.preferredHeight = sprite.rect.height;
|
||||
textureImageLayout.preferredWidth = sprite.rect.width;
|
||||
}
|
||||
|
||||
private void OnSaveTextureClicked()
|
||||
{
|
||||
if (!TextureRef)
|
||||
{
|
||||
ExplorerCore.LogWarning("Ref Texture is null, maybe it was destroyed?");
|
||||
return;
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(textureSavePathInput.text))
|
||||
{
|
||||
ExplorerCore.LogWarning("Save path cannot be empty!");
|
||||
return;
|
||||
}
|
||||
|
||||
var path = textureSavePathInput.text;
|
||||
if (!path.EndsWith(".png", StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
ExplorerCore.LogWarning("Desired save path must end with '.png'!");
|
||||
return;
|
||||
}
|
||||
|
||||
var dir = Path.GetDirectoryName(path);
|
||||
if (!Directory.Exists(dir))
|
||||
Directory.CreateDirectory(dir);
|
||||
|
||||
if (File.Exists(path))
|
||||
File.Delete(path);
|
||||
|
||||
var tex = TextureRef;
|
||||
|
||||
if (!TextureUtilProvider.IsReadable(tex))
|
||||
tex = TextureUtilProvider.ForceReadTexture(tex);
|
||||
|
||||
byte[] data = TextureUtilProvider.Instance.EncodeToPNG(tex);
|
||||
|
||||
File.WriteAllBytes(path, data);
|
||||
|
||||
if (tex != TextureRef)
|
||||
{
|
||||
// cleanup temp texture if we had to force-read it.
|
||||
GameObject.Destroy(tex);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
@ -26,45 +26,29 @@ namespace UnityExplorer.UI.Panels
|
||||
private SearchContext m_context = SearchContext.UnityObject;
|
||||
private SceneFilter m_sceneFilter = SceneFilter.Any;
|
||||
private ChildFilter m_childFilter = ChildFilter.Any;
|
||||
private string desiredTypeInput;
|
||||
private string lastCheckedTypeInput;
|
||||
private bool lastTypeCanHaveGO;
|
||||
|
||||
public ButtonListSource<object> dataHandler;
|
||||
|
||||
private ScrollPool<ButtonCell> resultsScrollPool;
|
||||
private List<object> currentResults = new List<object>();
|
||||
|
||||
public TypeCompleter typeAutocompleter;
|
||||
|
||||
public override GameObject UIRoot => uiRoot;
|
||||
private GameObject uiRoot;
|
||||
|
||||
private GameObject sceneFilterRow;
|
||||
private GameObject childFilterRow;
|
||||
private GameObject unityObjectClassRow;
|
||||
|
||||
private InputField nameInputField;
|
||||
private InputField classInputField;
|
||||
|
||||
private Text resultsLabel;
|
||||
|
||||
public List<object> GetEntries() => currentResults;
|
||||
|
||||
private void OnContextDropdownChanged(int value)
|
||||
{
|
||||
m_context = (SearchContext)value;
|
||||
|
||||
// show/hide other filters depending on what we just selected.
|
||||
bool shouldShowGoFilters = m_context == SearchContext.GameObject
|
||||
|| m_context == SearchContext.Component
|
||||
|| m_context == SearchContext.Custom;
|
||||
|
||||
sceneFilterRow.SetActive(shouldShowGoFilters);
|
||||
childFilterRow.SetActive(shouldShowGoFilters);
|
||||
|
||||
unityObjectClassRow.SetActive(m_context == SearchContext.Custom);
|
||||
}
|
||||
|
||||
private void OnSceneFilterDropChanged(int value) => m_sceneFilter = (SceneFilter)value;
|
||||
|
||||
private void OnChildFilterDropChanged(int value) => m_childFilter = (ChildFilter)value;
|
||||
|
||||
public void DoSearch()
|
||||
{
|
||||
cachedCellTexts.Clear();
|
||||
@ -76,8 +60,8 @@ namespace UnityExplorer.UI.Panels
|
||||
else
|
||||
{
|
||||
string compType = "";
|
||||
if (m_context == SearchContext.Custom)
|
||||
compType = classInputField.text;
|
||||
if (m_context == SearchContext.UnityObject)
|
||||
compType = this.desiredTypeInput;
|
||||
|
||||
currentResults = SearchProvider.UnityObjectSearch(nameInputField.text, compType, m_context, m_childFilter, m_sceneFilter);
|
||||
}
|
||||
@ -88,6 +72,59 @@ namespace UnityExplorer.UI.Panels
|
||||
resultsLabel.text = $"{currentResults.Count} results";
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
if (lastCheckedTypeInput != desiredTypeInput)
|
||||
{
|
||||
lastCheckedTypeInput = desiredTypeInput;
|
||||
|
||||
//var type = ReflectionUtility.GetTypeByName(desiredTypeInput);
|
||||
if (typeAutocompleter.AllTypes.TryGetValue(desiredTypeInput, out var cachedType))
|
||||
{
|
||||
var type = cachedType.Type;
|
||||
lastTypeCanHaveGO = typeof(Component).IsAssignableFrom(type) || type == typeof(GameObject);
|
||||
sceneFilterRow.SetActive(lastTypeCanHaveGO);
|
||||
childFilterRow.SetActive(lastTypeCanHaveGO);
|
||||
}
|
||||
else
|
||||
{
|
||||
sceneFilterRow.SetActive(false);
|
||||
childFilterRow.SetActive(false);
|
||||
lastTypeCanHaveGO = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// UI Callbacks
|
||||
|
||||
private void OnContextDropdownChanged(int value)
|
||||
{
|
||||
m_context = (SearchContext)value;
|
||||
|
||||
bool shouldShowGoFilters = m_context == SearchContext.GameObject || m_context == SearchContext.UnityObject;
|
||||
|
||||
sceneFilterRow.SetActive(shouldShowGoFilters);
|
||||
childFilterRow.SetActive(shouldShowGoFilters);
|
||||
|
||||
unityObjectClassRow.SetActive(m_context == SearchContext.UnityObject);
|
||||
}
|
||||
|
||||
private void OnSceneFilterDropChanged(int value) => m_sceneFilter = (SceneFilter)value;
|
||||
|
||||
private void OnChildFilterDropChanged(int value) => m_childFilter = (ChildFilter)value;
|
||||
|
||||
private void OnTypeInputChanged(string val)
|
||||
{
|
||||
desiredTypeInput = val;
|
||||
|
||||
if (string.IsNullOrEmpty(val))
|
||||
{
|
||||
sceneFilterRow.SetActive(false);
|
||||
childFilterRow.SetActive(false);
|
||||
lastCheckedTypeInput = val;
|
||||
}
|
||||
}
|
||||
|
||||
// Cache the syntax-highlighted text for each search result to reduce allocs.
|
||||
private static readonly Dictionary<int, string> cachedCellTexts = new Dictionary<int, string>();
|
||||
|
||||
@ -143,12 +180,13 @@ namespace UnityExplorer.UI.Panels
|
||||
var unityClassLbl = UIFactory.CreateLabel(unityObjectClassRow, "UnityClassLabel", "Custom Type:", TextAnchor.MiddleLeft);
|
||||
UIFactory.SetLayoutElement(unityClassLbl.gameObject, minWidth: 110, flexibleWidth: 0);
|
||||
|
||||
var classInputObj = UIFactory.CreateInputField(unityObjectClassRow, "ClassInput", "...", out this.classInputField);
|
||||
var classInputObj = UIFactory.CreateInputField(unityObjectClassRow, "ClassInput", "...", out var classInputField);
|
||||
UIFactory.SetLayoutElement(classInputObj, minHeight: 25, flexibleHeight: 0, flexibleWidth: 9999);
|
||||
|
||||
new TypeCompleter(typeof(UnityEngine.Object), classInputField);
|
||||
typeAutocompleter = new TypeCompleter(typeof(UnityEngine.Object), classInputField);
|
||||
classInputField.onValueChanged.AddListener(OnTypeInputChanged);
|
||||
|
||||
unityObjectClassRow.SetActive(false);
|
||||
//unityObjectClassRow.SetActive(false);
|
||||
|
||||
// Child filter row
|
||||
|
||||
|
@ -197,7 +197,7 @@ namespace UnityExplorer.UI.Panels
|
||||
toggle.isOn = false;
|
||||
toggle.onValueChanged.AddListener((bool val) => AutoUpdate = val);
|
||||
|
||||
//refreshRow.SetActive(false);
|
||||
refreshRow.SetActive(false);
|
||||
|
||||
// Transform Tree
|
||||
|
||||
|
@ -15,6 +15,8 @@ namespace UnityExplorer.UI.Panels
|
||||
{
|
||||
public override string Name => "C# Console";
|
||||
public override UIManager.Panels PanelType => UIManager.Panels.CSConsole;
|
||||
public override int MinWidth => 400;
|
||||
public override int MinHeight => 300;
|
||||
|
||||
public static CSConsolePanel Instance { get; private set; }
|
||||
|
||||
@ -95,25 +97,18 @@ namespace UnityExplorer.UI.Panels
|
||||
ConfigManager.CSConsoleData.Value = this.ToSaveData();
|
||||
}
|
||||
|
||||
public override void LoadSaveData()
|
||||
{
|
||||
this.ApplySaveData(ConfigManager.CSConsoleData.Value);
|
||||
}
|
||||
public override string GetSaveData() => ConfigManager.CSConsoleData.Value;
|
||||
|
||||
public override void SetDefaultPosAndAnchors()
|
||||
// UI Construction
|
||||
|
||||
protected internal override void DoSetDefaultPosAndAnchors()
|
||||
{
|
||||
mainPanelRect.localPosition = Vector2.zero;
|
||||
mainPanelRect.pivot = new Vector2(0f, 1f);
|
||||
mainPanelRect.anchorMin = new Vector2(0.5f, 0);
|
||||
mainPanelRect.anchorMax = new Vector2(0.5f, 1);
|
||||
mainPanelRect.offsetMin = new Vector2(mainPanelRect.offsetMin.x, 100); // bottom
|
||||
mainPanelRect.offsetMax = new Vector2(mainPanelRect.offsetMax.x, -50); // top
|
||||
mainPanelRect.sizeDelta = new Vector2(700f, mainPanelRect.sizeDelta.y);
|
||||
mainPanelRect.anchoredPosition = new Vector2(-150, 0);
|
||||
mainPanelRect.anchorMin = new Vector2(0.4f, 0.1f);
|
||||
mainPanelRect.anchorMax = new Vector2(0.9f, 0.85f);
|
||||
}
|
||||
|
||||
// UI Construction
|
||||
|
||||
public override void ConstructPanelContent()
|
||||
{
|
||||
//Content = UIFactory.CreateVerticalGroup(MainMenu.Instance.PageViewport, "CSharpConsole", true, true, true, true);
|
||||
|
@ -6,11 +6,7 @@ using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.Core.Config;
|
||||
using UnityExplorer.Core.Runtime;
|
||||
using UnityExplorer.UI.Inspectors;
|
||||
using UnityExplorer.UI.Models;
|
||||
using UnityExplorer.UI.Utility;
|
||||
using UnityExplorer.UI.Widgets;
|
||||
|
||||
namespace UnityExplorer.UI.Panels
|
||||
{
|
||||
@ -23,6 +19,8 @@ namespace UnityExplorer.UI.Panels
|
||||
public override string Name => "Inspector";
|
||||
public override UIManager.Panels PanelType => UIManager.Panels.Inspector;
|
||||
public override bool ShouldSaveActiveState => false;
|
||||
public override int MinWidth => 550;
|
||||
public override int MinHeight => 350;
|
||||
|
||||
public GameObject NavbarHolder;
|
||||
public GameObject ContentHolder;
|
||||
@ -40,41 +38,40 @@ namespace UnityExplorer.UI.Panels
|
||||
{
|
||||
base.OnFinishResize(panel);
|
||||
|
||||
InspectorManager.PanelWidth = this.mainPanelRect.rect.width;
|
||||
InspectorManager.OnPanelResized(panel.rect.width);
|
||||
}
|
||||
|
||||
public override void LoadSaveData()
|
||||
{
|
||||
ApplySaveData(ConfigManager.InspectorData.Value);
|
||||
public override string GetSaveData() => ConfigManager.InspectorData.Value;
|
||||
|
||||
InspectorManager.PanelWidth = this.mainPanelRect.rect.width;
|
||||
}
|
||||
//public override void LoadSaveData()
|
||||
//{
|
||||
// ApplySaveData(ConfigManager.InspectorData.Value);
|
||||
//
|
||||
// InspectorManager.PanelWidth = this.mainPanelRect.rect.width;
|
||||
//}
|
||||
|
||||
public override void DoSaveToConfigElement()
|
||||
{
|
||||
ConfigManager.InspectorData.Value = this.ToSaveData();
|
||||
}
|
||||
|
||||
public override void SetDefaultPosAndAnchors()
|
||||
protected internal override void DoSetDefaultPosAndAnchors()
|
||||
{
|
||||
mainPanelRect.localPosition = Vector2.zero;
|
||||
mainPanelRect.pivot = new Vector2(0f, 1f);
|
||||
mainPanelRect.anchorMin = new Vector2(0.1f, 0.15f);
|
||||
mainPanelRect.anchorMax = new Vector2(0.1f, 0.95f);
|
||||
mainPanelRect.offsetMin = new Vector2(mainPanelRect.offsetMin.x, 100); // bottom
|
||||
mainPanelRect.offsetMax = new Vector2(mainPanelRect.offsetMax.x, -50); // top
|
||||
mainPanelRect.sizeDelta = new Vector2(700f, mainPanelRect.sizeDelta.y);
|
||||
mainPanelRect.anchoredPosition = new Vector2(-150, 0);
|
||||
mainPanelRect.anchorMin = new Vector2(0.35f, 0.175f);
|
||||
mainPanelRect.anchorMax = new Vector2(0.8f, 0.925f);
|
||||
}
|
||||
|
||||
public override void ConstructPanelContent()
|
||||
{
|
||||
// this.UIRoot.GetComponent<Mask>().enabled = false;
|
||||
|
||||
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(this.content, forceHeight: true, spacing: 4, padLeft: 5, padRight: 5);
|
||||
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(this.content, true, true, true, true, 4, padLeft: 5, padRight: 5);
|
||||
|
||||
this.NavbarHolder = UIFactory.CreateGridGroup(this.content, "Navbar", new Vector2(200, 22), new Vector2(4, 4),
|
||||
new Color(0.12f, 0.12f, 0.12f));
|
||||
new Color(0.05f, 0.05f, 0.05f));
|
||||
//UIFactory.SetLayoutElement(NavbarHolder, flexibleWidth: 9999, minHeight: 0, preferredHeight: 0, flexibleHeight: 9999);
|
||||
NavbarHolder.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize;
|
||||
|
||||
|
@ -20,6 +20,8 @@ namespace UnityExplorer.UI.Panels
|
||||
{
|
||||
public override string Name => "Object Explorer";
|
||||
public override UIManager.Panels PanelType => UIManager.Panels.ObjectExplorer;
|
||||
public override int MinWidth => 350;
|
||||
public override int MinHeight => 200;
|
||||
|
||||
public SceneExplorer SceneExplorer;
|
||||
public ObjectSearch ObjectSearch;
|
||||
@ -56,18 +58,17 @@ namespace UnityExplorer.UI.Panels
|
||||
{
|
||||
if (SelectedTab == 0)
|
||||
SceneExplorer.Update();
|
||||
else
|
||||
ObjectSearch.Update();
|
||||
}
|
||||
|
||||
public override string GetSaveData() => ConfigManager.ObjectExplorerData.Value;
|
||||
|
||||
public override void DoSaveToConfigElement()
|
||||
{
|
||||
ConfigManager.ObjectExplorerData.Value = this.ToSaveData();
|
||||
}
|
||||
|
||||
public override void LoadSaveData()
|
||||
{
|
||||
ApplySaveData(ConfigManager.ObjectExplorerData.Value);
|
||||
}
|
||||
|
||||
public override string ToSaveData()
|
||||
{
|
||||
string ret = base.ToSaveData();
|
||||
@ -95,21 +96,13 @@ namespace UnityExplorer.UI.Panels
|
||||
SetTab(SelectedTab);
|
||||
}
|
||||
|
||||
public override void SetDefaultPosAndAnchors()
|
||||
protected internal override void DoSetDefaultPosAndAnchors()
|
||||
{
|
||||
// todo proper default size
|
||||
mainPanelRect.localPosition = Vector2.zero;
|
||||
mainPanelRect.pivot = new Vector2(0f, 1f);
|
||||
mainPanelRect.anchorMin = new Vector2(0.1f, 0.25f);
|
||||
mainPanelRect.anchorMax = new Vector2(0.25f, 0.8f);
|
||||
|
||||
|
||||
//mainPanelRect.anchorMin = Vector3.zero;
|
||||
//mainPanelRect.anchorMax = new Vector2(0, 1);
|
||||
//mainPanelRect.sizeDelta = new Vector2(320f, mainPanelRect.sizeDelta.y);
|
||||
//mainPanelRect.anchoredPosition = new Vector2(200, 0);
|
||||
//mainPanelRect.offsetMin = new Vector2(mainPanelRect.offsetMin.x, 100); // bottom
|
||||
//mainPanelRect.offsetMax = new Vector2(mainPanelRect.offsetMax.x, -50); // top
|
||||
mainPanelRect.anchorMin = new Vector2(0.125f, 0.175f);
|
||||
mainPanelRect.anchorMax = new Vector2(0.325f, 0.925f);
|
||||
//mainPanelRect.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, 350);
|
||||
}
|
||||
|
||||
public override void ConstructPanelContent()
|
||||
|
@ -77,7 +77,8 @@ namespace UnityExplorer.UI.Panels
|
||||
|
||||
// Instance
|
||||
|
||||
public bool AllowDragAndResize { get; set; }
|
||||
public UIPanel UIPanel { get; private set; }
|
||||
public bool AllowDragAndResize => UIPanel.CanDragAndResize;
|
||||
|
||||
public RectTransform Panel { get; set; }
|
||||
public event Action<RectTransform> OnFinishResize;
|
||||
@ -95,7 +96,7 @@ namespace UnityExplorer.UI.Panels
|
||||
|
||||
public static GameObject s_resizeCursorObj;
|
||||
|
||||
internal readonly Vector2 minResize = new Vector2(200, 50);
|
||||
//internal readonly Vector2 minResize = new Vector2(200, 50);
|
||||
|
||||
private bool WasResizing { get; set; }
|
||||
private ResizeTypes m_currentResizeType = ResizeTypes.NONE;
|
||||
@ -109,8 +110,9 @@ namespace UnityExplorer.UI.Panels
|
||||
|
||||
private Rect m_totalResizeRect;
|
||||
|
||||
public PanelDragger(RectTransform dragArea, RectTransform panelToDrag)
|
||||
public PanelDragger(RectTransform dragArea, RectTransform panelToDrag, UIPanel panel)
|
||||
{
|
||||
this.UIPanel = panel;
|
||||
Instances.Add(this);
|
||||
DragableArea = dragArea;
|
||||
Panel = panelToDrag;
|
||||
@ -417,12 +419,12 @@ namespace UnityExplorer.UI.Panels
|
||||
Panel.anchorMin = new Vector2(anchorMin.x, anchorMin.y);
|
||||
Panel.anchorMax = new Vector2(anchorMax.x, anchorMax.y);
|
||||
|
||||
if (Panel.rect.width < minResize.x)
|
||||
if (Panel.rect.width < UIPanel.MinWidth)
|
||||
{
|
||||
Panel.anchorMin = new Vector2(prevMin.x, Panel.anchorMin.y);
|
||||
Panel.anchorMax = new Vector2(prevMax.x, Panel.anchorMax.y);
|
||||
}
|
||||
if (Panel.rect.height < minResize.y)
|
||||
if (Panel.rect.height < UIPanel.MinHeight)
|
||||
{
|
||||
Panel.anchorMin = new Vector2(Panel.anchorMin.x, prevMin.y);
|
||||
Panel.anchorMax = new Vector2(Panel.anchorMax.x, prevMax.y);
|
||||
@ -459,14 +461,4 @@ namespace UnityExplorer.UI.Panels
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
// Just to allow Enum to do .HasFlag() in NET 3.5
|
||||
public static class Net35FlagsEx
|
||||
{
|
||||
public static bool HasFlag(this Enum flags, Enum value)
|
||||
{
|
||||
ulong num = Convert.ToUInt64(value);
|
||||
return (Convert.ToUInt64(flags) & num) == num;
|
||||
}
|
||||
}
|
||||
}
|
@ -75,6 +75,8 @@ namespace UnityExplorer.UI.Panels
|
||||
|
||||
public abstract UIManager.Panels PanelType { get; }
|
||||
public abstract string Name { get; }
|
||||
public abstract int MinWidth { get; }
|
||||
public abstract int MinHeight { get; }
|
||||
|
||||
public virtual bool ShowByDefault => false;
|
||||
public virtual bool ShouldSaveActiveState => true;
|
||||
@ -126,6 +128,18 @@ namespace UnityExplorer.UI.Panels
|
||||
base.Destroy();
|
||||
}
|
||||
|
||||
protected internal abstract void DoSetDefaultPosAndAnchors();
|
||||
|
||||
public void SetTransformDefaults()
|
||||
{
|
||||
DoSetDefaultPosAndAnchors();
|
||||
|
||||
if (mainPanelRect.rect.width < MinWidth)
|
||||
mainPanelRect.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, MinWidth);
|
||||
if (mainPanelRect.rect.height < MinHeight)
|
||||
mainPanelRect.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, MinHeight);
|
||||
}
|
||||
|
||||
public void ConstructUI()
|
||||
{
|
||||
//this.Enabled = true;
|
||||
@ -146,16 +160,16 @@ namespace UnityExplorer.UI.Panels
|
||||
// create core canvas
|
||||
uiRoot = UIFactory.CreatePanel(Name, out GameObject panelContent);
|
||||
mainPanelRect = this.uiRoot.GetComponent<RectTransform>();
|
||||
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(this.uiRoot, true, true, true, true, 0, 2, 2, 2, 2, TextAnchor.UpperLeft);
|
||||
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(this.uiRoot, false, false, true, true, 0, 2, 2, 2, 2, TextAnchor.UpperLeft);
|
||||
|
||||
int id = this.uiRoot.transform.GetInstanceID();
|
||||
transformToPanelDict.Add(id, this);
|
||||
|
||||
content = panelContent;
|
||||
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(this.content, true, true, true, true, 2, 2, 2, 2, 2, TextAnchor.UpperLeft);
|
||||
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(this.content, false, false, true, true, 2, 2, 2, 2, 2, TextAnchor.UpperLeft);
|
||||
|
||||
// always apply default pos and anchors (save data may only be partial)
|
||||
SetDefaultPosAndAnchors();
|
||||
SetTransformDefaults();
|
||||
|
||||
// Title bar
|
||||
var titleGroup = UIFactory.CreateHorizontalGroup(content, "TitleBar", false, true, true, true, 2,
|
||||
@ -165,11 +179,14 @@ namespace UnityExplorer.UI.Panels
|
||||
// Title text
|
||||
|
||||
var titleTxt = UIFactory.CreateLabel(titleGroup, "TitleBar", Name, TextAnchor.MiddleLeft);
|
||||
UIFactory.SetLayoutElement(titleTxt.gameObject, minHeight: 25, flexibleHeight: 0, flexibleWidth: 9999);
|
||||
UIFactory.SetLayoutElement(titleTxt.gameObject, minWidth: 250, minHeight: 25, flexibleHeight: 0, flexibleWidth: 0);
|
||||
|
||||
// close button
|
||||
|
||||
var closeBtn = UIFactory.CreateButton(titleGroup, "CloseButton", "—");
|
||||
var closeHolder = UIFactory.CreateUIObject("CloseHolder", titleGroup);
|
||||
UIFactory.SetLayoutElement(closeHolder, minHeight: 25, flexibleHeight: 0, minWidth: 30, flexibleWidth: 9999);
|
||||
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(closeHolder, false, false, true, true, 0, childAlignment: TextAnchor.MiddleRight);
|
||||
var closeBtn = UIFactory.CreateButton(closeHolder, "CloseButton", "—");
|
||||
UIFactory.SetLayoutElement(closeBtn.Button.gameObject, minHeight: 25, minWidth: 25, flexibleWidth: 0);
|
||||
RuntimeProvider.Instance.SetColorBlock(closeBtn.Button, new Color(0.33f, 0.32f, 0.31f));
|
||||
|
||||
@ -184,15 +201,15 @@ namespace UnityExplorer.UI.Panels
|
||||
|
||||
// Panel dragger
|
||||
|
||||
Dragger = new PanelDragger(titleTxt.GetComponent<RectTransform>(), mainPanelRect);
|
||||
Dragger = new PanelDragger(titleGroup.GetComponent<RectTransform>(), mainPanelRect, this);
|
||||
Dragger.OnFinishResize += OnFinishResize;
|
||||
Dragger.OnFinishDrag += OnFinishDrag;
|
||||
Dragger.AllowDragAndResize = this.CanDragAndResize;
|
||||
|
||||
// content (abstract)
|
||||
|
||||
ConstructPanelContent();
|
||||
|
||||
UIManager.SetPanelActive(this.PanelType, true);
|
||||
UIManager.SetPanelActive(this.PanelType, false);
|
||||
UIManager.SetPanelActive(this.PanelType, ShowByDefault);
|
||||
|
||||
@ -200,15 +217,16 @@ namespace UnityExplorer.UI.Panels
|
||||
// apply panel save data or revert to default
|
||||
try
|
||||
{
|
||||
LoadSaveData();
|
||||
Dragger.OnEndResize();
|
||||
ApplySaveData(GetSaveData());
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ExplorerCore.Log($"Exception loading panel save data: {ex}");
|
||||
SetDefaultPosAndAnchors();
|
||||
SetTransformDefaults();
|
||||
}
|
||||
|
||||
Dragger.OnEndResize();
|
||||
|
||||
// simple listener for saving enabled state
|
||||
this.OnToggleEnabled += (bool val) =>
|
||||
{
|
||||
@ -221,6 +239,8 @@ namespace UnityExplorer.UI.Panels
|
||||
|
||||
// SAVE DATA
|
||||
|
||||
public abstract void DoSaveToConfigElement();
|
||||
|
||||
public void SaveToConfigManager()
|
||||
{
|
||||
if (UIManager.Initializing)
|
||||
@ -229,11 +249,7 @@ namespace UnityExplorer.UI.Panels
|
||||
DoSaveToConfigElement();
|
||||
}
|
||||
|
||||
public abstract void DoSaveToConfigElement();
|
||||
|
||||
public abstract void SetDefaultPosAndAnchors();
|
||||
|
||||
public abstract void LoadSaveData();
|
||||
public abstract string GetSaveData();
|
||||
|
||||
public bool ApplyingSaveData { get; set; }
|
||||
|
||||
@ -268,7 +284,7 @@ namespace UnityExplorer.UI.Panels
|
||||
catch
|
||||
{
|
||||
ExplorerCore.LogWarning("Invalid or corrupt panel save data! Restoring to default.");
|
||||
SetDefaultPosAndAnchors();
|
||||
SetTransformDefaults();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -490,7 +490,7 @@ namespace UnityExplorer.UI
|
||||
|
||||
Image mainImage = mainObj.AddComponent<Image>();
|
||||
mainImage.type = Image.Type.Sliced;
|
||||
mainImage.color = new Color(0.12f, 0.12f, 0.12f);
|
||||
mainImage.color = new Color(0.04f, 0.04f, 0.04f, 0.75f);
|
||||
|
||||
inputField = mainObj.AddComponent<InputField>();
|
||||
Navigation nav = inputField.navigation;
|
||||
|
@ -21,6 +21,8 @@ namespace UnityExplorer.UI.Utility
|
||||
private const string destroyedString = "<color=red>Destroyed</color>";
|
||||
private const string untitledString = "<i><color=grey>untitled</color></i>";
|
||||
|
||||
private const string eventSystemNamespace = "UnityEngine.EventSystem";
|
||||
|
||||
public static string ToStringWithType(object value, Type fallbackType, bool includeNamespace = true)
|
||||
{
|
||||
if (value == null && fallbackType == null)
|
||||
@ -49,10 +51,21 @@ namespace UnityExplorer.UI.Utility
|
||||
}
|
||||
|
||||
if (value is UnityEngine.Object obj)
|
||||
{
|
||||
_stringBuilder.Append(string.IsNullOrEmpty(obj.name) ? untitledString : obj.name);
|
||||
{
|
||||
var name = obj.name;
|
||||
if (string.IsNullOrEmpty(name))
|
||||
name = untitledString;
|
||||
else if (name.Length > 50)
|
||||
name = $"{name.Substring(0, 50)}...";
|
||||
|
||||
_stringBuilder.Append($"\"{name}\"");
|
||||
AppendRichType(_stringBuilder, richType);
|
||||
}
|
||||
else if (type.FullName.StartsWith(eventSystemNamespace))
|
||||
{
|
||||
// UnityEngine.EventSystem classes can have some obnoxious ToString results with rich text.
|
||||
_stringBuilder.Append(richType);
|
||||
}
|
||||
else
|
||||
{
|
||||
var toString = ToString(value);
|
||||
@ -84,8 +97,10 @@ namespace UnityExplorer.UI.Utility
|
||||
}
|
||||
else // the ToString contains some actual implementation, use that value.
|
||||
{
|
||||
if (toString.Length > 200)
|
||||
_stringBuilder.Append(toString.Substring(0, 200));
|
||||
// prune long strings unless they're unity structs
|
||||
// (Matrix4x4 and Rect can have some longs ones that we want to display fully)
|
||||
if (toString.Length > 100 && !(type.IsValueType && type.FullName.StartsWith("UnityEngine")))
|
||||
_stringBuilder.Append(toString.Substring(0, 100));
|
||||
else
|
||||
_stringBuilder.Append(toString);
|
||||
|
||||
@ -154,6 +169,15 @@ namespace UnityExplorer.UI.Utility
|
||||
string _ = null;
|
||||
toString = ReflectionProvider.Instance.ProcessTypeFullNameInString(type, toString, ref _);
|
||||
|
||||
#if CPP
|
||||
if (value is Il2CppSystem.Type cppType)
|
||||
{
|
||||
var monoType = Core.Runtime.Il2Cpp.Il2CppReflection.GetMonoType(cppType);
|
||||
if (monoType != null)
|
||||
toString = ReflectionProvider.Instance.ProcessTypeFullNameInString(monoType, toString, ref _);
|
||||
}
|
||||
#endif
|
||||
|
||||
return toString;
|
||||
}
|
||||
}
|
||||
|
@ -22,6 +22,8 @@ namespace UnityExplorer.UI.Widgets.AutoComplete
|
||||
|
||||
public override string Name => "AutoCompleter";
|
||||
public override UIManager.Panels PanelType => UIManager.Panels.AutoCompleter;
|
||||
public override int MinWidth => -1;
|
||||
public override int MinHeight => -1;
|
||||
|
||||
public override bool CanDragAndResize => false;
|
||||
public override bool ShouldSaveActiveState => false;
|
||||
@ -164,7 +166,7 @@ namespace UnityExplorer.UI.Widgets.AutoComplete
|
||||
this.Dragger.OnEndResize();
|
||||
}
|
||||
|
||||
public override void SetDefaultPosAndAnchors()
|
||||
protected internal override void DoSetDefaultPosAndAnchors()
|
||||
{
|
||||
var mainRect = uiRoot.GetComponent<RectTransform>();
|
||||
mainRect.pivot = new Vector2(0f, 1f);
|
||||
@ -190,9 +192,6 @@ namespace UnityExplorer.UI.Widgets.AutoComplete
|
||||
// not savable
|
||||
}
|
||||
|
||||
public override void LoadSaveData()
|
||||
{
|
||||
// not savable
|
||||
}
|
||||
public override string GetSaveData() => null;
|
||||
}
|
||||
}
|
||||
|
@ -11,16 +11,17 @@ namespace UnityExplorer.UI.Widgets.AutoComplete
|
||||
{
|
||||
public readonly string DisplayText;
|
||||
public readonly string UnderlyingValue;
|
||||
public readonly string Prefix;
|
||||
public readonly string Addition;
|
||||
//public int InsertIndex;
|
||||
//public readonly string Prefix;
|
||||
//public readonly string Addition;
|
||||
|
||||
public string Full => Prefix + Addition;
|
||||
//public string Full => Prefix + Addition;
|
||||
|
||||
public Suggestion(string displayText, string prefix, string addition, string underlyingValue)
|
||||
public Suggestion(string displayText, /* string prefix, string addition, */ string underlyingValue)
|
||||
{
|
||||
DisplayText = displayText;
|
||||
Addition = addition;
|
||||
Prefix = prefix;
|
||||
//Addition = addition;
|
||||
//Prefix = prefix;
|
||||
UnderlyingValue = underlyingValue;
|
||||
}
|
||||
}
|
||||
|
@ -1,47 +1,40 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.Core.Runtime;
|
||||
using UnityExplorer.UI.Models;
|
||||
using UnityExplorer.UI.Panels;
|
||||
|
||||
namespace UnityExplorer.UI.Widgets.AutoComplete
|
||||
{
|
||||
public class TypeCompleter : ISuggestionProvider
|
||||
{
|
||||
private class CachedType
|
||||
public class CachedType
|
||||
{
|
||||
public string FullNameForFilter;
|
||||
public Type Type;
|
||||
public string FullNameValue;
|
||||
public string DisplayName;
|
||||
}
|
||||
|
||||
public Type BaseType { get; }
|
||||
public event Action<Suggestion> SuggestionClicked;
|
||||
|
||||
public Type BaseType { get; set; }
|
||||
public Type[] GenericConstraints { get; set; }
|
||||
|
||||
public InputField InputField { get; }
|
||||
public bool AnchorToCaretPosition => false;
|
||||
|
||||
public event Action<Suggestion> SuggestionClicked;
|
||||
public void OnSuggestionClicked(Suggestion suggestion)
|
||||
{
|
||||
SuggestionClicked?.Invoke(suggestion);
|
||||
suggestions.Clear();
|
||||
AutoCompleter.Instance.SetSuggestions(suggestions);
|
||||
|
||||
timeOfLastCheck = Time.realtimeSinceStartup;
|
||||
InputField.text = suggestion.UnderlyingValue;
|
||||
}
|
||||
|
||||
private readonly List<Suggestion> suggestions = new List<Suggestion>();
|
||||
private float timeOfLastCheck;
|
||||
|
||||
private readonly Dictionary<string, CachedType> typeCache = new Dictionary<string, CachedType>();
|
||||
public Dictionary<string, CachedType> AllTypes = new Dictionary<string, CachedType>();
|
||||
|
||||
//// cached list of names for displaying (with proper case)
|
||||
//private readonly List<string> cachedTypesNames = new List<string>();
|
||||
//// cached list of lookup by index (lowercase)
|
||||
//private readonly List<string> cachedTypesFilter = new List<string>();
|
||||
//// cached hashset of names (lower case)
|
||||
//private readonly HashSet<string> cachedTypesSet = new HashSet<string>();
|
||||
// cached type trees from all autocompleters
|
||||
private static readonly Dictionary<string, Dictionary<string, CachedType>> typeCache = new Dictionary<string, Dictionary<string, CachedType>>();
|
||||
|
||||
public TypeCompleter(Type baseType, InputField inputField)
|
||||
{
|
||||
@ -50,37 +43,20 @@ namespace UnityExplorer.UI.Widgets.AutoComplete
|
||||
|
||||
inputField.onValueChanged.AddListener(OnInputFieldChanged);
|
||||
|
||||
var types = ReflectionUtility.GetImplementationsOf(this.BaseType, true, false);
|
||||
|
||||
var list = new List<CachedType>();
|
||||
|
||||
foreach (var type in types)
|
||||
{
|
||||
string displayName = Utility.SignatureHighlighter.ParseFullSyntax(type, true);
|
||||
string fullName = RuntimeProvider.Instance.Reflection.GetDeobfuscatedType(type).FullName;
|
||||
|
||||
string filteredName = fullName;
|
||||
|
||||
list.Add(new CachedType
|
||||
{
|
||||
FullNameValue = fullName,
|
||||
FullNameForFilter = filteredName,
|
||||
DisplayName = displayName,
|
||||
});
|
||||
}
|
||||
|
||||
list.Sort((CachedType a, CachedType b) => a.FullNameForFilter.CompareTo(b.FullNameForFilter));
|
||||
|
||||
foreach (var cache in list)
|
||||
{
|
||||
if (typeCache.ContainsKey(cache.FullNameForFilter))
|
||||
continue;
|
||||
typeCache.Add(cache.FullNameForFilter, cache);
|
||||
}
|
||||
|
||||
if (BaseType != null)
|
||||
CacheTypes();
|
||||
}
|
||||
|
||||
private float timeOfLastCheck;
|
||||
public void OnSuggestionClicked(Suggestion suggestion)
|
||||
{
|
||||
timeOfLastCheck = Time.realtimeSinceStartup;
|
||||
|
||||
InputField.text = suggestion.UnderlyingValue;
|
||||
SuggestionClicked?.Invoke(suggestion);
|
||||
|
||||
suggestions.Clear();
|
||||
AutoCompleter.Instance.SetSuggestions(suggestions);
|
||||
}
|
||||
|
||||
private void OnInputFieldChanged(string value)
|
||||
{
|
||||
@ -110,29 +86,59 @@ namespace UnityExplorer.UI.Widgets.AutoComplete
|
||||
|
||||
var added = new HashSet<string>();
|
||||
|
||||
if (typeCache.TryGetValue(value, out CachedType cache))
|
||||
AddToDict(cache);
|
||||
// Check for exact match first
|
||||
if (AllTypes.TryGetValue(value, out CachedType cache))
|
||||
AddSuggestion(cache);
|
||||
|
||||
foreach (var entry in typeCache.Values)
|
||||
foreach (var entry in AllTypes.Values)
|
||||
AddSuggestion(entry);
|
||||
|
||||
void AddSuggestion(CachedType entry)
|
||||
{
|
||||
if (entry.FullNameValue == null)
|
||||
entry.FullNameValue = ReflectionProvider.Instance.GetDeobfuscatedType(entry.Type).FullName;
|
||||
|
||||
if (added.Contains(entry.FullNameValue))
|
||||
continue;
|
||||
|
||||
if (entry.FullNameForFilter.ContainsIgnoreCase(value))
|
||||
AddToDict(entry);
|
||||
|
||||
return;
|
||||
added.Add(entry.FullNameValue);
|
||||
}
|
||||
|
||||
void AddToDict(CachedType entry)
|
||||
if (entry.DisplayName == null)
|
||||
entry.DisplayName = Utility.SignatureHighlighter.ParseFullSyntax(entry.Type, true);
|
||||
|
||||
suggestions.Add(new Suggestion(entry.DisplayName, entry.FullNameValue));
|
||||
}
|
||||
}
|
||||
|
||||
public void CacheTypes()
|
||||
{
|
||||
var key = BaseType.AssemblyQualifiedName;
|
||||
|
||||
if (typeCache.ContainsKey(key))
|
||||
{
|
||||
added.Add(entry.FullNameValue);
|
||||
|
||||
suggestions.Add(new Suggestion(entry.DisplayName,
|
||||
value,
|
||||
entry.FullNameForFilter.Substring(value.Length, entry.FullNameForFilter.Length - value.Length),
|
||||
entry.FullNameValue));
|
||||
AllTypes = typeCache[key];
|
||||
return;
|
||||
}
|
||||
|
||||
AllTypes = new Dictionary<string, CachedType>();
|
||||
|
||||
var list = ReflectionUtility.GetImplementationsOf(BaseType, true, false)
|
||||
.Select(it => new CachedType()
|
||||
{
|
||||
Type = it,
|
||||
FullNameValue = ReflectionProvider.Instance.GetDeobfuscatedType(it).FullName
|
||||
})
|
||||
.ToList();
|
||||
|
||||
list.Sort((CachedType a, CachedType b) => a.FullNameValue.CompareTo(b.FullNameValue));
|
||||
|
||||
foreach (var cache in list)
|
||||
{
|
||||
if (AllTypes.ContainsKey(cache.FullNameValue))
|
||||
continue;
|
||||
AllTypes.Add(cache.FullNameValue, cache);
|
||||
}
|
||||
|
||||
typeCache.Add(key, AllTypes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -111,15 +111,12 @@ namespace UnityExplorer.UI.Widgets
|
||||
|
||||
if (!writingLocked)
|
||||
{
|
||||
if (prevContentHeight <= 1f && Content.rect.height > 1f)
|
||||
bool viewChange = CheckRecycleViewBounds(true);
|
||||
|
||||
if (viewChange || Content.rect.height != prevContentHeight)
|
||||
{
|
||||
prevContentHeight = Content.rect.height;
|
||||
}
|
||||
else if (Content.rect.height != prevContentHeight)
|
||||
{
|
||||
prevContentHeight = Content.rect.height;
|
||||
if (!writingLocked)
|
||||
OnValueChangedListener(Vector2.zero);
|
||||
OnValueChangedListener(Vector2.zero);
|
||||
|
||||
OnHeightChanged?.Invoke();
|
||||
}
|
||||
@ -176,7 +173,7 @@ namespace UnityExplorer.UI.Widgets
|
||||
|
||||
// set intial bounds
|
||||
prevAnchoredPos = Content.anchoredPosition;
|
||||
SetRecycleViewBounds(false);
|
||||
CheckRecycleViewBounds(false);
|
||||
|
||||
// create initial cell pool and set cells
|
||||
CreateCellPool();
|
||||
@ -186,7 +183,7 @@ namespace UnityExplorer.UI.Widgets
|
||||
SetCell(CellPool[enumerator.Current.cellIndex], enumerator.Current.dataIndex);
|
||||
|
||||
LayoutRebuilder.ForceRebuildLayoutImmediate(Content);
|
||||
|
||||
prevContentHeight = Content.rect.height;
|
||||
// update slider
|
||||
SetScrollBounds();
|
||||
UpdateSliderHandle();
|
||||
@ -203,14 +200,19 @@ namespace UnityExplorer.UI.Widgets
|
||||
NormalizedScrollBounds = new Vector2(Viewport.rect.height * 0.5f, TotalDataHeight - (Viewport.rect.height * 0.5f));
|
||||
}
|
||||
|
||||
private void SetRecycleViewBounds(bool extendPoolIfGrown)
|
||||
/// <summary>
|
||||
/// return value = viewport changed height
|
||||
/// </summary>
|
||||
private bool CheckRecycleViewBounds(bool extendPoolIfGrown)
|
||||
{
|
||||
RecycleViewBounds = new Vector2(Viewport.MinY() + HalfThreshold, Viewport.MaxY() - HalfThreshold);
|
||||
|
||||
if (extendPoolIfGrown && prevViewportHeight < Viewport.rect.height && prevViewportHeight != 0.0f)
|
||||
CheckExtendCellPool();
|
||||
|
||||
bool ret = prevViewportHeight == Viewport.rect.height;
|
||||
prevViewportHeight = Viewport.rect.height;
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Cell pool
|
||||
@ -361,7 +363,7 @@ namespace UnityExplorer.UI.Widgets
|
||||
{
|
||||
if (!CellPool.Any()) return;
|
||||
|
||||
SetRecycleViewBounds(true);
|
||||
CheckRecycleViewBounds(true);
|
||||
|
||||
CheckDataSourceCountChange(out bool jumpToBottom);
|
||||
|
||||
@ -432,7 +434,7 @@ namespace UnityExplorer.UI.Widgets
|
||||
|
||||
RefreshCellHeightsFast();
|
||||
|
||||
SetRecycleViewBounds(true);
|
||||
CheckRecycleViewBounds(true);
|
||||
|
||||
float yChange = ((Vector2)ScrollRect.content.localPosition - prevAnchoredPos).y;
|
||||
float adjust = 0f;
|
||||
@ -544,7 +546,7 @@ namespace UnityExplorer.UI.Widgets
|
||||
// Prevent spam invokes unless value is 0 or 1 (so we dont skip over the start/end)
|
||||
if (DataSource == null || (WritingLocked && val != 0 && val != 1))
|
||||
return;
|
||||
this.WritingLocked = true;
|
||||
//this.WritingLocked = true;
|
||||
|
||||
ScrollRect.StopMovement();
|
||||
RefreshCellHeightsFast();
|
||||
@ -626,7 +628,7 @@ namespace UnityExplorer.UI.Widgets
|
||||
}
|
||||
}
|
||||
|
||||
SetRecycleViewBounds(true);
|
||||
CheckRecycleViewBounds(true);
|
||||
|
||||
SetScrollBounds();
|
||||
ScrollRect.UpdatePrevData();
|
||||
|
@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
@ -14,6 +15,21 @@ namespace UnityExplorer.UI.Widgets
|
||||
{
|
||||
public Func<IEnumerable<GameObject>> GetRootEntriesMethod;
|
||||
|
||||
internal ScrollPool<TransformCell> ScrollPool;
|
||||
|
||||
// Using an OrderedDictionary because we need constant-time lookup of both key and index.
|
||||
/// <summary>
|
||||
/// Key: UnityEngine.Transform instance ID<br/>
|
||||
/// Value: CachedTransform
|
||||
/// </summary>
|
||||
private readonly OrderedDictionary displayedObjects = new OrderedDictionary();
|
||||
|
||||
// for keeping track of which actual transforms are expanded or not, outside of the cache data.
|
||||
private readonly HashSet<int> expandedInstanceIDs = new HashSet<int>();
|
||||
private readonly HashSet<int> autoExpandedIDs = new HashSet<int>();
|
||||
|
||||
public int ItemCount => displayedObjects.Count;
|
||||
|
||||
public bool Filtering => !string.IsNullOrEmpty(currentFilter);
|
||||
private bool wasFiltering;
|
||||
|
||||
@ -34,17 +50,6 @@ namespace UnityExplorer.UI.Widgets
|
||||
}
|
||||
private string currentFilter;
|
||||
|
||||
internal ScrollPool<TransformCell> ScrollPool;
|
||||
|
||||
internal readonly List<CachedTransform> displayedObjects = new List<CachedTransform>();
|
||||
|
||||
private readonly Dictionary<int, CachedTransform> objectCache = new Dictionary<int, CachedTransform>();
|
||||
|
||||
private readonly HashSet<int> expandedInstanceIDs = new HashSet<int>();
|
||||
private readonly HashSet<int> autoExpandedIDs = new HashSet<int>();
|
||||
|
||||
public int ItemCount => displayedObjects.Count;
|
||||
|
||||
public TransformTree(ScrollPool<TransformCell> scrollPool)
|
||||
{
|
||||
ScrollPool = scrollPool;
|
||||
@ -72,18 +77,38 @@ namespace UnityExplorer.UI.Widgets
|
||||
RefreshData(true, true);
|
||||
}
|
||||
|
||||
private readonly HashSet<int> visited = new HashSet<int>();
|
||||
private bool needRefresh;
|
||||
private int displayIndex;
|
||||
|
||||
public void RefreshData(bool andReload = false, bool jumpToTop = false)
|
||||
{
|
||||
displayedObjects.Clear();
|
||||
visited.Clear();
|
||||
displayIndex = 0;
|
||||
needRefresh = false;
|
||||
|
||||
var rootObjects = GetRootEntriesMethod.Invoke();
|
||||
|
||||
//int displayIndex = 0;
|
||||
foreach (var obj in rootObjects)
|
||||
if (obj) Traverse(obj.transform);
|
||||
|
||||
// Prune displayed transforms that we didnt visit in that traverse
|
||||
for (int i = displayedObjects.Count - 1; i >= 0; i--)
|
||||
{
|
||||
if (obj)
|
||||
Traverse(obj.transform);
|
||||
var obj = (CachedTransform)displayedObjects[i];
|
||||
if (!visited.Contains(obj.InstanceID))
|
||||
{
|
||||
displayedObjects.Remove(obj.InstanceID);
|
||||
needRefresh = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!needRefresh)
|
||||
return;
|
||||
|
||||
//displayedObjects.Clear();
|
||||
|
||||
if (andReload)
|
||||
{
|
||||
if (!jumpToTop)
|
||||
@ -97,32 +122,36 @@ namespace UnityExplorer.UI.Widgets
|
||||
{
|
||||
int instanceID = transform.GetInstanceID();
|
||||
|
||||
if (visited.Contains(instanceID))
|
||||
return;
|
||||
visited.Add(instanceID);
|
||||
|
||||
if (Filtering)
|
||||
{
|
||||
//auto - expand to show results: works, but then we need to collapse after the search ends.
|
||||
|
||||
if (FilterHierarchy(transform))
|
||||
{
|
||||
if (!autoExpandedIDs.Contains(instanceID))
|
||||
autoExpandedIDs.Add(instanceID);
|
||||
}
|
||||
else
|
||||
if (!FilterHierarchy(transform))
|
||||
return;
|
||||
|
||||
if (!autoExpandedIDs.Contains(instanceID))
|
||||
autoExpandedIDs.Add(instanceID);
|
||||
}
|
||||
|
||||
CachedTransform cached;
|
||||
if (objectCache.ContainsKey(instanceID))
|
||||
if (displayedObjects.Contains(instanceID))
|
||||
{
|
||||
cached = objectCache[instanceID];
|
||||
cached = (CachedTransform)displayedObjects[(object)instanceID];
|
||||
cached.Update(transform, depth);
|
||||
}
|
||||
else
|
||||
{
|
||||
needRefresh = true;
|
||||
cached = new CachedTransform(this, transform, depth, parent);
|
||||
objectCache.Add(instanceID, cached);
|
||||
if (displayedObjects.Count <= displayIndex)
|
||||
displayedObjects.Add(instanceID, cached);
|
||||
else
|
||||
displayedObjects.Insert(displayIndex, instanceID, cached);
|
||||
}
|
||||
|
||||
displayedObjects.Add(cached);
|
||||
displayIndex++;
|
||||
|
||||
if (IsCellExpanded(instanceID) && cached.Value.childCount > 0)
|
||||
{
|
||||
@ -149,7 +178,7 @@ namespace UnityExplorer.UI.Widgets
|
||||
public void SetCell(TransformCell cell, int index)
|
||||
{
|
||||
if (index < displayedObjects.Count)
|
||||
cell.ConfigureCell(displayedObjects[index], index);
|
||||
cell.ConfigureCell((CachedTransform)displayedObjects[index], index);
|
||||
else
|
||||
cell.Disable();
|
||||
}
|
||||
|
@ -235,26 +235,26 @@
|
||||
<Compile Include="Inspectors_OLD\Reflection\ReflectionInspector.cs" />
|
||||
<Compile Include="Inspectors_OLD\Reflection\StaticInspector.cs" />
|
||||
<Compile Include="UI\CSConsole\CSConsoleManager.cs" />
|
||||
<Compile Include="UI\Inspectors\CacheObject\CacheField.cs" />
|
||||
<Compile Include="UI\Inspectors\CacheObject\CacheKeyValuePair.cs" />
|
||||
<Compile Include="UI\Inspectors\CacheObject\CacheListEntry.cs" />
|
||||
<Compile Include="UI\Inspectors\CacheObject\CacheMember.cs" />
|
||||
<Compile Include="UI\Inspectors\CacheObject\CacheMethod.cs" />
|
||||
<Compile Include="UI\Inspectors\CacheObject\CacheObjectBase.cs" />
|
||||
<Compile Include="UI\Inspectors\CacheObject\CacheProperty.cs" />
|
||||
<Compile Include="UI\Inspectors\CacheObject\Views\CacheKeyValuePairCell.cs" />
|
||||
<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\CacheObject\CacheField.cs" />
|
||||
<Compile Include="UI\CacheObject\CacheKeyValuePair.cs" />
|
||||
<Compile Include="UI\CacheObject\CacheListEntry.cs" />
|
||||
<Compile Include="UI\CacheObject\CacheMember.cs" />
|
||||
<Compile Include="UI\CacheObject\CacheMethod.cs" />
|
||||
<Compile Include="UI\CacheObject\CacheObjectBase.cs" />
|
||||
<Compile Include="UI\CacheObject\CacheProperty.cs" />
|
||||
<Compile Include="UI\CacheObject\Views\CacheKeyValuePairCell.cs" />
|
||||
<Compile Include="UI\CacheObject\Views\CacheListEntryCell.cs" />
|
||||
<Compile Include="UI\CacheObject\Views\CacheMemberCell.cs" />
|
||||
<Compile Include="UI\CacheObject\Views\CacheObjectCell.cs" />
|
||||
<Compile Include="UI\CacheObject\Views\EvaluateWidget.cs" />
|
||||
<Compile Include="UI\Inspectors\GameObjectInspector.cs" />
|
||||
<Compile Include="UI\Inspectors\ICacheObjectController.cs" />
|
||||
<Compile Include="UI\CacheObject\ICacheObjectController.cs" />
|
||||
<Compile Include="UI\Inspectors\InspectorManager.cs" />
|
||||
<Compile Include="UI\Inspectors\InspectorTab.cs" />
|
||||
<Compile Include="UI\Inspectors\InspectorBase.cs" />
|
||||
<Compile Include="UI\Inspectors\IValues\InteractiveDictionary.cs" />
|
||||
<Compile Include="UI\Inspectors\IValues\InteractiveList.cs" />
|
||||
<Compile Include="UI\Inspectors\IValues\InteractiveValue.cs" />
|
||||
<Compile Include="UI\IValues\InteractiveDictionary.cs" />
|
||||
<Compile Include="UI\IValues\InteractiveList.cs" />
|
||||
<Compile Include="UI\IValues\InteractiveValue.cs" />
|
||||
<Compile Include="UI\Inspectors\ListInspector.cs" />
|
||||
<Compile Include="UI\Inspectors\ReflectionInspector.cs" />
|
||||
<Compile Include="UI\ObjectPool\IPooledObject.cs" />
|
||||
|
Loading…
x
Reference in New Issue
Block a user