Rewriting everything from scratch, developed generic ObjectPool system

This commit is contained in:
Sinai 2021-04-26 19:56:21 +10:00
parent 5a0c2390ce
commit 9f8d53f55a
77 changed files with 4399 additions and 4316 deletions

View File

@ -6,6 +6,7 @@ using UnityExplorer.Core;
using UnityExplorer.Core.Config;
using UnityExplorer.Core.Input;
using UnityExplorer.Core.Runtime;
using UnityExplorer.Tests;
using UnityExplorer.UI;
using UnityExplorer.UI.Panels;
@ -68,7 +69,7 @@ namespace UnityExplorer
UIManager.InitUI();
//InspectorManager.Instance.Inspect(typeof(TestClass));
//InspectorManager.Inspect(typeof(TestClass));
}
/// <summary>

View File

@ -0,0 +1,102 @@
//using System;
//using System.Collections.Generic;
//using System.Linq;
//using System.Text;
//using UnityEngine;
//using UnityEngine.UI;
//using UnityExplorer.Core.Config;
//using UnityExplorer.UI.InteractiveValues;
//namespace UnityExplorer.UI.CacheObject
//{
// public class CacheConfigEntry : CacheObjectBase
// {
// public IConfigElement RefConfig { get; }
// public override Type FallbackType => RefConfig.ElementType;
// public override bool HasEvaluated => true;
// public override bool HasParameters => false;
// public override bool IsMember => false;
// public override bool CanWrite => true;
// public CacheConfigEntry(IConfigElement config, GameObject parent)
// {
// RefConfig = config;
// m_parentContent = parent;
// config.OnValueChangedNotify += () => { UpdateValue(); };
// CreateIValue(config.BoxedValue, config.ElementType);
// }
// public override void CreateIValue(object value, Type fallbackType)
// {
// IValue = InteractiveValue.Create(value, fallbackType);
// IValue.Owner = this;
// IValue.m_mainContentParent = m_mainGroup;
// IValue.m_subContentParent = this.SubContentGroup;
// }
// public override void UpdateValue()
// {
// IValue.Value = RefConfig.BoxedValue;
// base.UpdateValue();
// }
// public override void SetValue()
// {
// RefConfig.BoxedValue = IValue.Value;
// }
// internal GameObject m_mainGroup;
// internal override void ConstructUI()
// {
// base.ConstructUI();
// m_mainGroup = UIFactory.CreateVerticalGroup(UIRoot, "ConfigHolder", true, false, true, true, 5, new Vector4(2, 2, 2, 2));
// var horiGroup = UIFactory.CreateHorizontalGroup(m_mainGroup, "ConfigEntryHolder", false, false, true, true, childAlignment: TextAnchor.MiddleLeft);
// UIFactory.SetLayoutElement(horiGroup, minHeight: 30, flexibleHeight: 0);
// // config entry label
// var configLabel = UIFactory.CreateLabel(horiGroup, "ConfigLabel", this.RefConfig.Name, TextAnchor.MiddleLeft);
// var leftRect = configLabel.GetComponent<RectTransform>();
// leftRect.anchorMin = Vector2.zero;
// leftRect.anchorMax = Vector2.one;
// leftRect.offsetMin = Vector2.zero;
// leftRect.offsetMax = Vector2.zero;
// leftRect.sizeDelta = Vector2.zero;
// UIFactory.SetLayoutElement(configLabel.gameObject, minWidth: 250, minHeight: 25, flexibleWidth: 0, flexibleHeight: 0);
// // Default button
// var defaultButton = UIFactory.CreateButton(horiGroup,
// "RevertDefaultButton",
// "Default",
// () => { RefConfig.RevertToDefaultValue(); },
// new Color(0.3f, 0.3f, 0.3f));
// UIFactory.SetLayoutElement(defaultButton.gameObject, minWidth: 80, minHeight: 22, flexibleWidth: 0);
// // Description label
// var desc = UIFactory.CreateLabel(m_mainGroup, "Description", $"<i>{RefConfig.Description}</i>", TextAnchor.MiddleLeft, Color.grey);
// UIFactory.SetLayoutElement(desc.gameObject, minWidth: 250, minHeight: 20, flexibleWidth: 9999, flexibleHeight: 0);
// // IValue
// if (IValue != null)
// {
// IValue.m_mainContentParent = m_mainGroup;
// IValue.m_subContentParent = this.SubContentGroup;
// }
// // makes the subcontent look nicer
// SubContentGroup.transform.SetParent(m_mainGroup.transform, false);
// }
// }
//}

View File

@ -0,0 +1,57 @@
//using System;
//using System.Collections;
//using System.Collections.Generic;
//using System.Linq;
//using System.Text;
//using UnityExplorer.UI;
//using UnityEngine;
//using UnityEngine.UI;
//using UnityExplorer.UI.InteractiveValues;
//namespace UnityExplorer.UI.CacheObject
//{
// public class CacheEnumerated : CacheObjectBase
// {
// public override Type FallbackType => ParentEnumeration.m_baseEntryType;
// public override bool CanWrite => RefIList != null && ParentEnumeration.Owner.CanWrite;
// public int Index { get; set; }
// public IList RefIList { get; set; }
// public InteractiveEnumerable ParentEnumeration { get; set; }
// public CacheEnumerated(int index, InteractiveEnumerable parentEnumeration, IList refIList, GameObject parentContent)
// {
// this.ParentEnumeration = parentEnumeration;
// this.Index = index;
// this.RefIList = refIList;
// this.m_parentContent = parentContent;
// }
// public override void CreateIValue(object value, Type fallbackType)
// {
// IValue = InteractiveValue.Create(value, fallbackType);
// IValue.Owner = this;
// }
// public override void SetValue()
// {
// RefIList[Index] = IValue.Value;
// ParentEnumeration.Value = RefIList;
// ParentEnumeration.Owner.SetValue();
// }
// internal override void ConstructUI()
// {
// base.ConstructUI();
// var rowObj = UIFactory.CreateHorizontalGroup(UIRoot, "CacheEnumeratedGroup", false, true, true, true, 0, new Vector4(0,0,5,2),
// new Color(1, 1, 1, 0));
// var indexLabel = UIFactory.CreateLabel(rowObj, "IndexLabel", $"{this.Index}:", TextAnchor.MiddleLeft);
// UIFactory.SetLayoutElement(indexLabel.gameObject, minWidth: 20, flexibleWidth: 30, minHeight: 25);
// IValue.m_mainContentParent = rowObj;
// }
// }
//}

View File

@ -0,0 +1,40 @@
//using System;
//using System.Collections.Generic;
//using System.Linq;
//using System.Text;
//using System.Reflection;
//using UnityExplorer.UI;
//using UnityEngine;
//namespace UnityExplorer.UI.CacheObject
//{
// public class CacheField : CacheMember
// {
// public override bool IsStatic => (MemInfo as FieldInfo).IsStatic;
// public override Type FallbackType => (MemInfo as FieldInfo).FieldType;
// public CacheField(FieldInfo fieldInfo, object declaringInstance, GameObject parent) : base(fieldInfo, declaringInstance, parent)
// {
// CreateIValue(null, fieldInfo.FieldType);
// }
// public override void UpdateReflection()
// {
// var fi = MemInfo as FieldInfo;
// IValue.Value = fi.GetValue(fi.IsStatic ? null : DeclaringInstance);
// m_evaluated = true;
// ReflectionException = null;
// }
// public override void SetValue()
// {
// var fi = MemInfo as FieldInfo;
// fi.SetValue(fi.IsStatic ? null : DeclaringInstance, IValue.Value);
// if (this.ParentInspector?.ParentMember != null)
// this.ParentInspector.ParentMember.SetValue();
// }
// }
//}

View File

@ -0,0 +1,360 @@
//using System;
//using System.Collections.Generic;
//using System.Linq;
//using System.Reflection;
//using UnityEngine;
//using UnityEngine.UI;
//using UnityExplorer.UI;
//using UnityExplorer.Core.Runtime;
//using UnityExplorer.Core;
//using UnityExplorer.UI.Utility;
//using UnityExplorer.UI.InteractiveValues;
//using UnityExplorer.Inspectors.Reflection;
//using UnityExplorer.UI.Panels;
//namespace UnityExplorer.UI.CacheObject
//{
// public abstract class CacheMember : CacheObjectBase
// {
// public override bool IsMember => true;
// public override Type FallbackType { get; }
// public ReflectionInspector ParentInspector { get; set; }
// public MemberInfo MemInfo { get; set; }
// public Type DeclaringType { get; set; }
// public object DeclaringInstance { get; set; }
// public virtual bool IsStatic { get; private set; }
// public string ReflectionException { get; set; }
// public override bool CanWrite => m_canWrite ?? GetCanWrite();
// private bool? m_canWrite;
// public override bool HasParameters => ParamCount > 0;
// public virtual int ParamCount => m_arguments.Length;
// public override bool HasEvaluated => m_evaluated;
// public bool m_evaluated = false;
// public bool m_isEvaluating;
// public ParameterInfo[] m_arguments = new ParameterInfo[0];
// public string[] m_argumentInput = new string[0];
// public string NameForFiltering => m_nameForFilter ?? (m_nameForFilter = $"{MemInfo.DeclaringType.Name}.{MemInfo.Name}".ToLower());
// private string m_nameForFilter;
// public string RichTextName => m_richTextName ?? GetRichTextName();
// private string m_richTextName;
// public CacheMember(MemberInfo memberInfo, object declaringInstance, GameObject parentContent)
// {
// MemInfo = memberInfo;
// DeclaringType = memberInfo.DeclaringType;
// DeclaringInstance = declaringInstance;
// this.m_parentContent = parentContent;
// DeclaringInstance = ReflectionProvider.Instance.Cast(declaringInstance, DeclaringType);
// }
// public override void Enable()
// {
// base.Enable();
// ParentInspector.displayedMembers.Add(this);
// memberLabelElement.minWidth = 0.4f * InspectorPanel.CurrentPanelWidth;
// }
// public override void Disable()
// {
// base.Disable();
// ParentInspector.displayedMembers.Remove(this);
// }
// public static bool CanProcessArgs(ParameterInfo[] parameters)
// {
// foreach (var param in parameters)
// {
// var pType = param.ParameterType;
// if (pType.IsByRef && pType.HasElementType)
// pType = pType.GetElementType();
// if (pType != null && (pType.IsPrimitive || pType == typeof(string)))
// continue;
// else
// return false;
// }
// return true;
// }
// public override void CreateIValue(object value, Type fallbackType)
// {
// IValue = InteractiveValue.Create(value, fallbackType);
// IValue.Owner = this;
// IValue.m_mainContentParent = this.ContentGroup;
// IValue.m_subContentParent = this.SubContentGroup;
// }
// public override void UpdateValue()
// {
// if (!HasParameters || m_isEvaluating)
// {
// try
// {
// Type baseType = ReflectionUtility.GetActualType(IValue.Value) ?? FallbackType;
// if (!ReflectionProvider.Instance.IsReflectionSupported(baseType))
// throw new Exception("Type not supported with reflection");
// UpdateReflection();
// if (IValue.Value != null)
// IValue.Value = IValue.Value.TryCast(ReflectionUtility.GetActualType(IValue.Value));
// }
// catch (Exception e)
// {
// ReflectionException = e.ReflectionExToString(true);
// }
// }
// base.UpdateValue();
// }
// public abstract void UpdateReflection();
// public override void SetValue()
// {
// // no implementation for base class
// }
// public object[] ParseArguments()
// {
// if (m_arguments.Length < 1)
// return new object[0];
// var parsedArgs = new List<object>();
// for (int i = 0; i < m_arguments.Length; i++)
// {
// var input = m_argumentInput[i];
// var type = m_arguments[i].ParameterType;
// if (type.IsByRef)
// type = type.GetElementType();
// if (!string.IsNullOrEmpty(input))
// {
// if (type == typeof(string))
// {
// parsedArgs.Add(input);
// continue;
// }
// else
// {
// try
// {
// var arg = type.GetMethod("Parse", new Type[] { typeof(string) })
// .Invoke(null, new object[] { input });
// parsedArgs.Add(arg);
// continue;
// }
// catch
// {
// ExplorerCore.Log($"Could not parse input '{input}' for argument #{i} '{m_arguments[i].Name}' ({type.FullName})");
// }
// }
// }
// // No input, see if there is a default value.
// if (m_arguments[i].IsOptional)
// {
// parsedArgs.Add(m_arguments[i].DefaultValue);
// continue;
// }
// // Try add a null arg I guess
// parsedArgs.Add(null);
// }
// return parsedArgs.ToArray();
// }
// private bool GetCanWrite()
// {
// if (MemInfo is FieldInfo fi)
// m_canWrite = !(fi.IsLiteral && !fi.IsInitOnly);
// else if (MemInfo is PropertyInfo pi)
// m_canWrite = pi.CanWrite;
// else
// m_canWrite = false;
// return (bool)m_canWrite;
// }
// private string GetRichTextName()
// {
// return m_richTextName = SignatureHighlighter.ParseFullSyntax(MemInfo.DeclaringType, false, MemInfo);
// }
// #region UI
// internal Text memberLabelText;
// internal GameObject ContentGroup;
// internal LayoutElement memberLabelElement;
// internal override void ConstructUI()
// {
// base.ConstructUI();
// var horiGroup = UIFactory.CreateUIObject("HoriGroup", UIRoot);
// var groupRect = horiGroup.GetComponent<RectTransform>();
// groupRect.pivot = new Vector2(0, 1);
// groupRect.anchorMin = Vector2.zero;
// groupRect.anchorMax = Vector2.one;
// UIFactory.SetLayoutElement(horiGroup, minHeight: 30, flexibleHeight: 9999);
// UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(horiGroup, true, true, true, true, 2, 2, 2, 2, 2, childAlignment: TextAnchor.UpperLeft);
// memberLabelText = UIFactory.CreateLabel(horiGroup, "MemLabelText", RichTextName, TextAnchor.UpperLeft);
// memberLabelText.horizontalOverflow = HorizontalWrapMode.Wrap;
// UIFactory.SetLayoutElement(memberLabelText.gameObject, minHeight: 25, flexibleHeight: 9999, minWidth: 150, flexibleWidth: 0);
// memberLabelElement = memberLabelText.GetComponent<LayoutElement>();
// ContentGroup = UIFactory.CreateUIObject("ContentGroup", horiGroup, default);
// UIFactory.SetLayoutElement(ContentGroup, minHeight: 30, flexibleWidth: 9999);
// var contentRect = ContentGroup.GetComponent<RectTransform>();
// contentRect.pivot = new Vector2(0, 1);
// contentRect.anchorMin = new Vector2(0, 0);
// contentRect.anchorMax = new Vector2(1, 1);
// UIFactory.SetLayoutGroup<VerticalLayoutGroup>(ContentGroup, false, false, true, true, childAlignment: TextAnchor.MiddleLeft);
// ConstructArgInput(out GameObject argsHolder);
// ConstructEvaluateButtons(argsHolder);
// IValue.m_mainContentParent = this.ContentGroup;
// //RightContentGroup.SetActive(false);
// // ParentInspector.CacheObjectContents.Add(this.m_mainContent);
// }
// internal void ConstructArgInput(out GameObject argsHolder)
// {
// argsHolder = null;
// if (HasParameters)
// {
// argsHolder = UIFactory.CreateVerticalGroup(ContentGroup, "ArgsHolder", true, false, true, true, 4, new Color(1, 1, 1, 0));
// if (this is CacheMethod cm && cm.GenericArgs.Length > 0)
// cm.ConstructGenericArgInput(argsHolder);
// if (m_arguments.Length > 0)
// {
// UIFactory.CreateLabel(argsHolder, "ArgumentsLabel", "Arguments:", TextAnchor.MiddleLeft);
// for (int i = 0; i < m_arguments.Length; i++)
// AddArgRow(i, argsHolder);
// }
// argsHolder.SetActive(false);
// }
// }
// internal void AddArgRow(int i, GameObject parent)
// {
// var arg = m_arguments[i];
// var rowObj = UIFactory.CreateHorizontalGroup(parent, "ArgRow", true, false, true, true, 4, default, new Color(1, 1, 1, 0));
// UIFactory.SetLayoutElement(rowObj, minHeight: 25, flexibleWidth: 5000);
// var argTypeTxt = SignatureHighlighter.ParseFullSyntax(arg.ParameterType, false);
// var argLabel = UIFactory.CreateLabel(rowObj, "ArgLabel", $"{argTypeTxt} <color={SignatureHighlighter.LOCAL_ARG}>{arg.Name}</color>",
// TextAnchor.MiddleLeft);
// UIFactory.SetLayoutElement(argLabel.gameObject, minHeight: 25);
// var argInputObj = UIFactory.CreateInputField(rowObj, "ArgInput", "...", out InputField argInput, 14, (int)TextAnchor.MiddleLeft, 1);
// UIFactory.SetLayoutElement(argInputObj, flexibleWidth: 1200, preferredWidth: 150, minWidth: 20, minHeight: 25, flexibleHeight: 0);
// argInput.onValueChanged.AddListener((string val) => { m_argumentInput[i] = val; });
// if (arg.IsOptional)
// {
// var phInput = argInput.placeholder.GetComponent<Text>();
// phInput.text = " = " + arg.DefaultValue?.ToString() ?? "null";
// }
// }
// internal void ConstructEvaluateButtons(GameObject argsHolder)
// {
// if (HasParameters)
// {
// var evalGroupObj = UIFactory.CreateHorizontalGroup(ContentGroup, "EvalGroup", false, false, true, true, 5,
// default, new Color(1, 1, 1, 0));
// UIFactory.SetLayoutElement(evalGroupObj, minHeight: 25, flexibleHeight: 0, flexibleWidth: 5000);
// var evalButton = UIFactory.CreateButton(evalGroupObj,
// "EvalButton",
// $"Evaluate ({ParamCount})",
// null);
// RuntimeProvider.Instance.SetColorBlock(evalButton, new Color(0.4f, 0.4f, 0.4f),
// new Color(0.4f, 0.7f, 0.4f), new Color(0.3f, 0.3f, 0.3f));
// UIFactory.SetLayoutElement(evalButton.gameObject, minWidth: 100, minHeight: 22, flexibleWidth: 0);
// var evalText = evalButton.GetComponentInChildren<Text>();
// var cancelButton = UIFactory.CreateButton(evalGroupObj, "CancelButton", "Close", null, new Color(0.3f, 0.3f, 0.3f));
// UIFactory.SetLayoutElement(cancelButton.gameObject, minWidth: 100, minHeight: 22, flexibleWidth: 0);
// cancelButton.gameObject.SetActive(false);
// evalButton.onClick.AddListener(() =>
// {
// if (!m_isEvaluating)
// {
// argsHolder.SetActive(true);
// m_isEvaluating = true;
// evalText.text = "Evaluate";
// RuntimeProvider.Instance.SetColorBlock(evalButton, new Color(0.3f, 0.6f, 0.3f));
// cancelButton.gameObject.SetActive(true);
// }
// else
// {
// if (this is CacheMethod cm)
// cm.Evaluate();
// else
// UpdateValue();
// }
// });
// cancelButton.onClick.AddListener(() =>
// {
// cancelButton.gameObject.SetActive(false);
// argsHolder.SetActive(false);
// m_isEvaluating = false;
// evalText.text = $"Evaluate ({ParamCount})";
// RuntimeProvider.Instance.SetColorBlock(evalButton, new Color(0.4f, 0.4f, 0.4f));
// });
// }
// else if (this is CacheMethod)
// {
// // simple method evaluate button
// var evalButton = UIFactory.CreateButton(ContentGroup, "EvalButton", "Evaluate", () => { (this as CacheMethod).Evaluate(); });
// RuntimeProvider.Instance.SetColorBlock(evalButton, new Color(0.4f, 0.4f, 0.4f),
// new Color(0.4f, 0.7f, 0.4f), new Color(0.3f, 0.3f, 0.3f));
// UIFactory.SetLayoutElement(evalButton.gameObject, minWidth: 100, minHeight: 22, flexibleWidth: 0);
// }
// }
// #endregion
// }
//}

View File

@ -0,0 +1,170 @@
//using System;
//using System.Collections.Generic;
//using System.Linq;
//using System.Reflection;
//using UnityEngine;
//using UnityEngine.UI;
//using UnityExplorer.UI;
//using UnityExplorer.Core;
//using UnityExplorer.UI.Utility;
//namespace UnityExplorer.UI.CacheObject
//{
// public class CacheMethod : CacheMember
// {
// //private CacheObjectBase m_cachedReturnValue;
// public override Type FallbackType => (MemInfo as MethodInfo).ReturnType;
// public override bool HasParameters => base.HasParameters || GenericArgs.Length > 0;
// public override bool IsStatic => (MemInfo as MethodInfo).IsStatic;
// public override int ParamCount => base.ParamCount + m_genericArgInput.Length;
// public Type[] GenericArgs { get; private set; }
// public Type[][] GenericConstraints { get; private set; }
// public string[] m_genericArgInput = new string[0];
// public CacheMethod(MethodInfo methodInfo, object declaringInstance, GameObject parent) : base(methodInfo, declaringInstance, parent)
// {
// GenericArgs = methodInfo.GetGenericArguments();
// GenericConstraints = GenericArgs.Select(x => x.GetGenericParameterConstraints())
// .Where(x => x != null)
// .ToArray();
// m_genericArgInput = new string[GenericArgs.Length];
// m_arguments = methodInfo.GetParameters();
// m_argumentInput = new string[m_arguments.Length];
// CreateIValue(null, methodInfo.ReturnType);
// }
// public override void UpdateReflection()
// {
// // CacheMethod cannot UpdateValue directly. Need to Evaluate.
// }
// public void Evaluate()
// {
// MethodInfo mi;
// if (GenericArgs.Length > 0)
// {
// mi = MakeGenericMethodFromInput();
// if (mi == null) return;
// }
// else
// {
// mi = MemInfo as MethodInfo;
// }
// object ret = null;
// try
// {
// ret = mi.Invoke(mi.IsStatic ? null : DeclaringInstance, ParseArguments());
// m_evaluated = true;
// m_isEvaluating = false;
// ReflectionException = null;
// }
// catch (Exception e)
// {
// while (e.InnerException != null)
// e = e.InnerException;
// ExplorerCore.LogWarning($"Exception evaluating: {e.GetType()}, {e.Message}");
// ReflectionException = ReflectionUtility.ReflectionExToString(e);
// }
// IValue.Value = ret;
// UpdateValue();
// }
// private MethodInfo MakeGenericMethodFromInput()
// {
// var mi = MemInfo as MethodInfo;
// var list = new List<Type>();
// for (int i = 0; i < GenericArgs.Length; i++)
// {
// var input = m_genericArgInput[i];
// if (ReflectionUtility.GetTypeByName(input) is Type t)
// {
// if (GenericConstraints[i].Length == 0)
// {
// list.Add(t);
// }
// else
// {
// foreach (var constraint in GenericConstraints[i].Where(x => x != null))
// {
// if (!constraint.IsAssignableFrom(t))
// {
// ExplorerCore.LogWarning($"Generic argument #{i}, '{input}' is not assignable from the constraint '{constraint}'!");
// return null;
// }
// }
// list.Add(t);
// }
// }
// else
// {
// ExplorerCore.LogWarning($"Generic argument #{i}, could not get any type by the name of '{input}'!" +
// $" Make sure you use the full name including the namespace.");
// return null;
// }
// }
// // make into a generic with type list
// mi = mi.MakeGenericMethod(list.ToArray());
// return mi;
// }
// #region UI CONSTRUCTION
// internal void ConstructGenericArgInput(GameObject parent)
// {
// UIFactory.CreateLabel(parent, "GenericArgLabel", "Generic Arguments:", TextAnchor.MiddleLeft);
// for (int i = 0; i < GenericArgs.Length; i++)
// AddGenericArgRow(i, parent);
// }
// internal void AddGenericArgRow(int i, GameObject parent)
// {
// var arg = GenericArgs[i];
// string constrainTxt = "";
// if (this.GenericConstraints[i].Length > 0)
// {
// foreach (var constraint in this.GenericConstraints[i])
// {
// if (constrainTxt != "")
// constrainTxt += ", ";
// constrainTxt += $"{SignatureHighlighter.ParseFullSyntax(constraint, false)}";
// }
// }
// else
// constrainTxt = $"Any";
// var rowObj = UIFactory.CreateHorizontalGroup(parent, "ArgRowObj", false, true, true, true, 4, default, new Color(1, 1, 1, 0));
// UIFactory.SetLayoutElement(rowObj, minHeight: 25, flexibleWidth: 5000);
// var argLabelObj = UIFactory.CreateLabel(rowObj, "ArgLabelObj", $"{constrainTxt} <color={SignatureHighlighter.CONST_VAR}>{arg.Name}</color>",
// TextAnchor.MiddleLeft);
// var argInputObj = UIFactory.CreateInputField(rowObj, "ArgInput", "...", out InputField argInput, 14, (int)TextAnchor.MiddleLeft, 1);
// UIFactory.SetLayoutElement(argInputObj, flexibleWidth: 1200);
// argInput.onValueChanged.AddListener((string val) => { m_genericArgInput[i] = val; });
// }
// #endregion
// }
//}

View File

@ -0,0 +1,120 @@
//using System;
//using System.Collections.Generic;
//using System.Linq;
//using System.Reflection;
//using UnityEngine;
//using UnityExplorer.UI;
//using UnityEngine.UI;
//using UnityExplorer.Core;
//using UnityExplorer.UI.InteractiveValues;
//using UnityExplorer.UI.Widgets;
//namespace UnityExplorer.UI.CacheObject
//{
// public abstract class CacheObjectBase
// {
// public InteractiveValue IValue;
// public virtual bool CanWrite => false;
// public virtual bool HasParameters => false;
// public virtual bool IsMember => false;
// public virtual bool HasEvaluated => true;
// public abstract Type FallbackType { get; }
// public abstract void CreateIValue(object value, Type fallbackType);
// public virtual void Enable()
// {
// if (!m_constructedUI)
// {
// ConstructUI();
// UpdateValue();
// }
// }
// public virtual void Disable()
// {
// if (UIRoot)
// UIRoot.SetActive(false);
// }
// public void Destroy()
// {
// if (this.UIRoot)
// GameObject.Destroy(this.UIRoot);
// }
// public virtual void UpdateValue()
// {
// var value = IValue.Value;
// // if the type has changed fundamentally, make a new interactivevalue for it
// var type = value == null
// ? FallbackType
// : ReflectionUtility.GetActualType(value);
// var ivalueType = InteractiveValue.GetIValueForType(type);
// if (ivalueType != IValue.GetType())
// {
// IValue.OnDestroy();
// CreateIValue(value, FallbackType);
// SubContentGroup.SetActive(false);
// }
// IValue.OnValueUpdated();
// IValue.RefreshElementsAfterUpdate();
// }
// public virtual void SetValue() => throw new NotImplementedException();
// #region UI CONSTRUCTION
// internal bool m_constructedUI;
// internal GameObject m_parentContent;
// internal RectTransform m_mainRect;
// internal GameObject UIRoot;
// internal GameObject SubContentGroup;
// internal bool constructedSubcontent;
// // Make base UI holder for CacheObject, this doesnt actually display anything.
// internal virtual void ConstructUI()
// {
// m_constructedUI = true;
// //UIRoot = UIFactory.CreateVerticalGroup(m_parentContent, $"{this.GetType().Name}.MainContent", true, true, true, true, 2,
// // new Vector4(0, 5, 0, 0), new Color(0.1f, 0.1f, 0.1f), TextAnchor.UpperLeft);
// UIRoot = UIFactory.CreateUIObject($"{this.GetType().Name}.MainContent", m_parentContent);
// UIFactory.SetLayoutGroup<VerticalLayoutGroup>(UIRoot, true, true, true, true, 2, 0, 5, 0, 0, TextAnchor.UpperLeft);
// m_mainRect = UIRoot.GetComponent<RectTransform>();
// m_mainRect.pivot = new Vector2(0, 1);
// m_mainRect.anchorMin = Vector2.zero;
// m_mainRect.anchorMax = Vector2.one;
// UIFactory.SetLayoutElement(UIRoot, minHeight: 30, flexibleHeight: 9999, minWidth: 200, flexibleWidth: 5000);
// SubContentGroup = new GameObject("SubContent");
// SubContentGroup.transform.parent = UIRoot.transform;
// UIFactory.SetLayoutElement(SubContentGroup, minHeight: 30, flexibleHeight: 9999, minWidth: 125, flexibleWidth: 9000);
// UIFactory.SetLayoutGroup<VerticalLayoutGroup>(SubContentGroup, true, false, true, true);
// SubContentGroup.SetActive(false);
// IValue.m_subContentParent = SubContentGroup;
// }
// public virtual void CheckSubcontentCreation()
// {
// if (!constructedSubcontent)
// {
// SubContentGroup.AddComponent<Image>().color = new Color(0.08f, 0.08f, 0.08f);
// constructedSubcontent = true;
// }
// }
// #endregion
// }
//}

View File

@ -0,0 +1,72 @@
//using System;
//using System.Collections;
//using System.Collections.Generic;
//using System.Linq;
//using System.Text;
//using UnityExplorer.UI;
//using UnityEngine;
//using UnityEngine.UI;
//using UnityExplorer.UI.InteractiveValues;
//namespace UnityExplorer.UI.CacheObject
//{
// public enum PairTypes
// {
// Key,
// Value
// }
// public class CachePaired : CacheObjectBase
// {
// public override Type FallbackType => PairType == PairTypes.Key
// ? ParentDictionary.m_typeOfKeys
// : ParentDictionary.m_typeofValues;
// public override bool CanWrite => false; // todo?
// public PairTypes PairType;
// public int Index { get; private set; }
// public InteractiveDictionary ParentDictionary { get; private set; }
// internal IDictionary RefIDict;
// public CachePaired(int index, InteractiveDictionary parentDict, IDictionary refIDict, PairTypes pairType, GameObject parentContent)
// {
// Index = index;
// ParentDictionary = parentDict;
// RefIDict = refIDict;
// this.PairType = pairType;
// this.m_parentContent = parentContent;
// }
// public override void CreateIValue(object value, Type fallbackType)
// {
// IValue = InteractiveValue.Create(value, fallbackType);
// IValue.Owner = this;
// }
// #region UI CONSTRUCTION
// internal override void ConstructUI()
// {
// base.ConstructUI();
// Color bgColor = this.PairType == PairTypes.Key
// ? new Color(0.07f, 0.07f, 0.07f)
// : new Color(0.1f, 0.1f, 0.1f);
// var rowObj = UIFactory.CreateHorizontalGroup(UIRoot, "PairedGroup", false, false, true, true, 0, new Vector4(0,0,5,2),
// bgColor);
// string lbl = $"{this.PairType}";
// if (this.PairType == PairTypes.Key)
// lbl = $"[{Index}] {lbl}";
// var indexLabel = UIFactory.CreateLabel(rowObj, "IndexLabel", lbl, TextAnchor.MiddleLeft);
// UIFactory.SetLayoutElement(indexLabel.gameObject, minWidth: 80, flexibleWidth: 30, minHeight: 25);
// IValue.m_mainContentParent = rowObj;
// }
// #endregion
// }
//}

View File

@ -0,0 +1,70 @@
//using System;
//using System.Collections.Generic;
//using System.Linq;
//using System.Text;
//using System.Reflection;
//using UnityExplorer.UI;
//using UnityEngine;
//namespace UnityExplorer.UI.CacheObject
//{
// public class CacheProperty : CacheMember
// {
// public override Type FallbackType => (MemInfo as PropertyInfo).PropertyType;
// public override bool IsStatic => (MemInfo as PropertyInfo).GetAccessors(true)[0].IsStatic;
// public CacheProperty(PropertyInfo propertyInfo, object declaringInstance, GameObject parent) : base(propertyInfo, declaringInstance, parent)
// {
// this.m_arguments = propertyInfo.GetIndexParameters();
// this.m_argumentInput = new string[m_arguments.Length];
// CreateIValue(null, propertyInfo.PropertyType);
// }
// public override void UpdateReflection()
// {
// if (HasParameters && !m_isEvaluating)
// {
// // Need to enter parameters first.
// return;
// }
// var pi = MemInfo as PropertyInfo;
// if (pi.CanRead)
// {
// var target = pi.GetAccessors(true)[0].IsStatic ? null : DeclaringInstance;
// IValue.Value = pi.GetValue(target, ParseArguments());
// m_evaluated = true;
// ReflectionException = null;
// }
// else
// {
// if (FallbackType == typeof(string))
// {
// IValue.Value = "";
// }
// else if (FallbackType.IsPrimitive)
// {
// IValue.Value = Activator.CreateInstance(FallbackType);
// }
// m_evaluated = true;
// ReflectionException = null;
// }
// }
// public override void SetValue()
// {
// var pi = MemInfo as PropertyInfo;
// var target = pi.GetAccessors()[0].IsStatic ? null : DeclaringInstance;
// pi.SetValue(target, IValue.Value, ParseArguments());
// if (this.ParentInspector?.ParentMember != null)
// this.ParentInspector.ParentMember.SetValue();
// }
// }
//}

View File

@ -7,7 +7,7 @@
//using UnityExplorer.Core.Runtime;
//using UnityExplorer.UI.Utility;
//namespace UnityExplorer.UI.Inspectors.GameObjects
//namespace UnityExplorer.Inspectors.GameObjects
//{
// public class ChildList
// {

View File

@ -8,7 +8,7 @@
//using UnityExplorer.Core.Runtime;
//using UnityExplorer.UI.Utility;
//namespace UnityExplorer.UI.Inspectors.GameObjects
//namespace UnityExplorer.Inspectors.GameObjects
//{
// public class ComponentList
// {

View File

@ -7,7 +7,7 @@
//using UnityExplorer.Core.Input;
//using UnityExplorer.Core.Runtime;
//namespace UnityExplorer.UI.Inspectors.GameObjects
//namespace UnityExplorer.Inspectors.GameObjects
//{
// public class GameObjectControls
// {

View File

@ -6,7 +6,7 @@
//using UnityEngine.UI;
//using UnityExplorer.Core.Runtime;
//namespace UnityExplorer.UI.Inspectors.GameObjects
//namespace UnityExplorer.Inspectors.GameObjects
//{
// public class GameObjectInspector : InspectorBase
// {

View File

@ -10,7 +10,7 @@
//using UnityExplorer.Core.Runtime;
//using UnityExplorer.UI;
//using UnityExplorer.UI.Main;
//using UnityExplorer.UI.Inspectors;
//using UnityExplorer.Inspectors;
//namespace UnityExplorer.UI.Main.Home
//{

View File

@ -0,0 +1,122 @@
//using System;
//using UnityEngine;
//using UnityEngine.UI;
//using UnityExplorer.UI.Panels;
//namespace UnityExplorer.Inspectors
//{
// public abstract class InspectorBase
// {
// public object Target;
// public bool IsActive { get; private set; }
// public abstract string TabLabel { get; }
// internal bool m_pendingDestroy;
// public InspectorBase(object target)
// {
// Target = target;
// if (Target.IsNullOrDestroyed(false))
// {
// Destroy();
// return;
// }
// AddInspectorTab(this);
// }
// public virtual void SetActive()
// {
// this.IsActive = true;
// Content?.SetActive(true);
// }
// public virtual void SetInactive()
// {
// this.IsActive = false;
// Content?.SetActive(false);
// }
// public virtual void Update()
// {
// if (Target.IsNullOrDestroyed(false))
// {
// Destroy();
// return;
// }
// m_tabText.text = TabLabel;
// }
// public virtual void Destroy()
// {
// m_pendingDestroy = true;
// GameObject tabGroup = m_tabButton?.transform.parent.gameObject;
// if (tabGroup)
// GameObject.Destroy(tabGroup);
// int thisIndex = -1;
// if (InspectorManager.ActiveInspectors.Contains(this))
// {
// thisIndex = InspectorManager.ActiveInspectors.IndexOf(this);
// InspectorManager.ActiveInspectors.Remove(this);
// }
// if (ReferenceEquals(InspectorManager.m_activeInspector, this))
// {
// InspectorManager.UnsetInspectorTab();
// if (InspectorManager.ActiveInspectors.Count > 0)
// {
// var prevTab = InspectorManager.ActiveInspectors[thisIndex > 0 ? thisIndex - 1 : 0];
// InspectorManager.SetInspectorTab(prevTab);
// }
// }
// }
// #region UI
// public abstract GameObject Content { get; set; }
// public Button m_tabButton;
// public Text m_tabText;
// public void AddInspectorTab(InspectorBase parent)
// {
// var tabContent = InspectorPanel.Instance.NavbarHolder;
// var tabGroupObj = UIFactory.CreateHorizontalGroup(tabContent, "TabObject", true, true, true, true);
// UIFactory.SetLayoutElement(tabGroupObj, minWidth: 185, flexibleWidth: 0);
// tabGroupObj.AddComponent<Mask>();
// m_tabButton = UIFactory.CreateButton(tabGroupObj,
// "TabButton",
// "",
// () => { InspectorManager.SetInspectorTab(parent); });
// UIFactory.SetLayoutElement(m_tabButton.gameObject, minWidth: 165, flexibleWidth: 0);
// m_tabText = m_tabButton.GetComponentInChildren<Text>();
// m_tabText.horizontalOverflow = HorizontalWrapMode.Overflow;
// m_tabText.alignment = TextAnchor.MiddleLeft;
// var closeBtn = UIFactory.CreateButton(tabGroupObj,
// "CloseButton",
// "X",
// () => { InspectorManager.DestroyInspector(parent); },
// new Color(0.2f, 0.2f, 0.2f, 1));
// UIFactory.SetLayoutElement(closeBtn.gameObject, minWidth: 20, flexibleWidth: 0);
// var closeBtnText = closeBtn.GetComponentInChildren<Text>();
// closeBtnText.color = new Color(1, 0, 0, 1);
// }
// public virtual void OnPanelResized() { }
// #endregion
// }
//}

View File

@ -0,0 +1,151 @@
//using System;
//using System.Collections.Generic;
//using System.Linq;
//using UnityExplorer.UI;
//using UnityEngine;
//using UnityEngine.SceneManagement;
//using UnityEngine.UI;
//using UnityExplorer.Core.Runtime;
//using UnityExplorer.UI.CacheObject;
//using UnityExplorer.Inspectors.Reflection;
//using UnityExplorer.UI.Panels;
//namespace UnityExplorer.Inspectors
//{
// public static class InspectorManager
// {
// public static InspectorBase m_activeInspector;
// public static readonly List<InspectorBase> ActiveInspectors = new List<InspectorBase>();
// public static void Update()
// {
// try
// {
// for (int i = 0; i < ActiveInspectors.Count; i++)
// ActiveInspectors[i].Update();
// }
// catch (Exception ex)
// {
// ExplorerCore.LogWarning(ex);
// }
// }
// public static void DestroyInspector(InspectorBase inspector)
// {
// if (inspector is ReflectionInspector ri)
// ri.Destroy();
// else
// inspector.Destroy();
// }
// public static void Inspect(object obj, CacheObjectBase parentMember = null)
// {
// var type = ReflectionProvider.Instance.GetActualType(obj);
// // only need to set parent member for structs
// if (!type.IsValueType)
// parentMember = null;
// obj = ReflectionProvider.Instance.Cast(obj, type);
// if (obj.IsNullOrDestroyed(false))
// return;
// // check if currently inspecting this object
// foreach (InspectorBase tab in ActiveInspectors)
// {
// if (obj.ReferenceEqual(tab.Target))
// {
// SetInspectorTab(tab);
// return;
// }
// }
// InspectorBase inspector;
// if (obj is GameObject go)
// {
// ExplorerCore.Log("TODO");
// return;
// // inspector = new GameObjectInspector(go);
// }
// else
// inspector = new InstanceInspector(obj);
// if (inspector is ReflectionInspector ri)
// ri.ParentMember = parentMember;
// ActiveInspectors.Add(inspector);
// SetInspectorTab(inspector);
// }
// public static void Inspect(Type type)
// {
// if (type == null)
// {
// ExplorerCore.LogWarning("The provided type was null!");
// return;
// }
// foreach (var tab in ActiveInspectors.Where(x => x is StaticInspector))
// {
// if (ReferenceEquals(tab.Target as Type, type))
// {
// SetInspectorTab(tab);
// return;
// }
// }
// var inspector = new StaticInspector(type);
// ActiveInspectors.Add(inspector);
// SetInspectorTab(inspector);
// }
// public static void SetInspectorTab(InspectorBase inspector)
// {
// UIManager.SetPanelActive(UIManager.Panels.Inspector, true);
// if (m_activeInspector == inspector)
// return;
// UnsetInspectorTab();
// m_activeInspector = inspector;
// inspector.SetActive();
// OnSetInspectorTab(inspector);
// }
// public static void UnsetInspectorTab()
// {
// if (m_activeInspector == null)
// return;
// m_activeInspector.SetInactive();
// OnUnsetInspectorTab();
// m_activeInspector = null;
// }
// public static void OnSetInspectorTab(InspectorBase inspector)
// {
// Color activeColor = new Color(0, 0.25f, 0, 1);
// RuntimeProvider.Instance.SetColorBlock(inspector.m_tabButton, activeColor, activeColor);
// }
// public static void OnUnsetInspectorTab()
// {
// RuntimeProvider.Instance.SetColorBlock(m_activeInspector.m_tabButton,
// new Color(0.2f, 0.2f, 0.2f, 1), new Color(0.1f, 0.3f, 0.1f, 1));
// }
// internal static void OnPanelResized()
// {
// foreach (var instance in ActiveInspectors)
// {
// instance.OnPanelResized();
// }
// }
// }
//}

View File

@ -0,0 +1,110 @@
//using System;
//using System.Collections.Generic;
//using System.Linq;
//using System.Text;
//using UnityEngine;
//using UnityEngine.UI;
//using UnityExplorer.UI;
//using UnityExplorer.UI.CacheObject;
//namespace UnityExplorer.UI.InteractiveValues
//{
// public class InteractiveBool : InteractiveValue
// {
// public InteractiveBool(object value, Type valueType) : base(value, valueType) { }
// public override bool HasSubContent => false;
// public override bool SubContentWanted => false;
// public override bool WantInspectBtn => false;
// internal Toggle m_toggle;
// internal Button m_applyBtn;
// public override void OnValueUpdated()
// {
// base.OnValueUpdated();
// }
// public override void RefreshUIForValue()
// {
// GetDefaultLabel();
// if (Owner.HasEvaluated)
// {
// var val = (bool)Value;
// if (!m_toggle.gameObject.activeSelf)
// m_toggle.gameObject.SetActive(true);
// if (val != m_toggle.isOn)
// m_toggle.isOn = val;
// if (Owner.CanWrite)
// {
// if (!m_applyBtn.gameObject.activeSelf)
// m_applyBtn.gameObject.SetActive(true);
// }
// var color = val
// ? "6bc981" // on
// : "c96b6b"; // off
// m_baseLabel.text = $"<color=#{color}>{val}</color>";
// }
// else
// {
// m_baseLabel.text = DefaultLabel;
// }
// }
// public override void OnException(CacheMember member)
// {
// base.OnException(member);
// if (Owner.CanWrite)
// {
// if (m_toggle.gameObject.activeSelf)
// m_toggle.gameObject.SetActive(false);
// if (m_applyBtn.gameObject.activeSelf)
// m_applyBtn.gameObject.SetActive(false);
// }
// }
// internal void OnToggleValueChanged(bool val)
// {
// Value = val;
// RefreshUIForValue();
// }
// public override void ConstructUI(GameObject parent, GameObject subGroup)
// {
// base.ConstructUI(parent, subGroup);
// var baseLayout = m_baseLabel.gameObject.GetComponent<LayoutElement>();
// baseLayout.flexibleWidth = 0;
// baseLayout.minWidth = 50;
// var toggleObj = UIFactory.CreateToggle(m_mainContent, "InteractiveBoolToggle", out m_toggle, out _, new Color(0.1f, 0.1f, 0.1f));
// UIFactory.SetLayoutElement(toggleObj, minWidth: 24);
// m_toggle.onValueChanged.AddListener(OnToggleValueChanged);
// m_baseLabel.transform.SetAsLastSibling();
// m_applyBtn = UIFactory.CreateButton(m_mainContent,
// "ApplyButton",
// "Apply",
// () => { Owner.SetValue(); },
// new Color(0.2f, 0.2f, 0.2f));
// UIFactory.SetLayoutElement(m_applyBtn.gameObject, minWidth: 50, minHeight: 25, flexibleWidth: 0);
// toggleObj.SetActive(false);
// if (!Owner.CanWrite)
// m_toggle.interactable = false;
// m_applyBtn.gameObject.SetActive(false);
// }
// }
//}

View File

@ -0,0 +1,167 @@
//using System;
//using System.Collections.Generic;
//using System.Linq;
//using System.Text;
//using UnityEngine;
//using UnityEngine.UI;
//namespace UnityExplorer.UI.InteractiveValues
//{
// public class InteractiveColor : InteractiveValue
// {
// //~~~~~~~~~ Instance ~~~~~~~~~~
// public InteractiveColor(object value, Type valueType) : base(value, valueType) { }
// public override bool HasSubContent => true;
// public override bool SubContentWanted => true;
// public override bool WantInspectBtn => true;
// public override void RefreshUIForValue()
// {
// base.RefreshUIForValue();
// if (m_subContentConstructed)
// RefreshUI();
// }
// private void RefreshUI()
// {
// var color = (Color)this.Value;
// m_inputs[0].text = color.r.ToString();
// m_inputs[1].text = color.g.ToString();
// m_inputs[2].text = color.b.ToString();
// m_inputs[3].text = color.a.ToString();
// if (m_colorImage)
// m_colorImage.color = color;
// }
// internal override void OnToggleSubcontent(bool toggle)
// {
// base.OnToggleSubcontent(toggle);
// RefreshUI();
// }
// #region UI CONSTRUCTION
// private Image m_colorImage;
// private readonly InputField[] m_inputs = new InputField[4];
// private readonly Slider[] m_sliders = new Slider[4];
// public override void ConstructUI(GameObject parent, GameObject subGroup)
// {
// base.ConstructUI(parent, subGroup);
// //// Limit the label width for colors, they're always about the same so make use of that space.
// //UIFactory.SetLayoutElement(this.m_baseLabel.gameObject, flexibleWidth: 0, minWidth: 250);
// }
// public override void ConstructSubcontent()
// {
// base.ConstructSubcontent();
// var horiGroup = UIFactory.CreateHorizontalGroup(m_subContentParent, "ColorEditor", false, false, true, true, 5,
// default, default, TextAnchor.MiddleLeft);
// var editorContainer = UIFactory.CreateVerticalGroup(horiGroup, "EditorContent", false, true, true, true, 2, new Vector4(4, 4, 4, 4),
// new Color(0.08f, 0.08f, 0.08f));
// UIFactory.SetLayoutElement(editorContainer, minWidth: 300, flexibleWidth: 0);
// for (int i = 0; i < 4; i++)
// AddEditorRow(i, editorContainer);
// if (Owner.CanWrite)
// {
// var applyBtn = UIFactory.CreateButton(editorContainer, "ApplyButton", "Apply", OnSetValue, new Color(0.2f, 0.2f, 0.2f));
// UIFactory.SetLayoutElement(applyBtn.gameObject, minWidth: 175, minHeight: 25, flexibleWidth: 0);
// void OnSetValue()
// {
// Owner.SetValue();
// RefreshUIForValue();
// }
// }
// var imgHolder = UIFactory.CreateVerticalGroup(horiGroup, "ImgHolder", true, true, true, true, 0, new Vector4(1, 1, 1, 1),
// new Color(0.08f, 0.08f, 0.08f));
// UIFactory.SetLayoutElement(imgHolder, minWidth: 128, minHeight: 128, flexibleWidth: 0, flexibleHeight: 0);
// var imgObj = UIFactory.CreateUIObject("ColorImageHelper", imgHolder, new Vector2(100, 25));
// m_colorImage = imgObj.AddComponent<Image>();
// m_colorImage.color = (Color)this.Value;
// }
// private static readonly string[] s_fieldNames = new[] { "R", "G", "B", "A" };
// internal void AddEditorRow(int index, GameObject groupObj)
// {
// var row = UIFactory.CreateHorizontalGroup(groupObj, "EditorRow_" + s_fieldNames[index],
// false, true, true, true, 5, default, new Color(1, 1, 1, 0));
// var label = UIFactory.CreateLabel(row, "RowLabel", $"{s_fieldNames[index]}:", TextAnchor.MiddleRight, Color.cyan);
// UIFactory.SetLayoutElement(label.gameObject, minWidth: 50, flexibleWidth: 0, minHeight: 25);
// var inputFieldObj = UIFactory.CreateInputField(row, "InputField", "...", out InputField inputField, 14, 3, 1);
// UIFactory.SetLayoutElement(inputFieldObj, minWidth: 120, minHeight: 25, flexibleWidth: 0);
// m_inputs[index] = inputField;
// inputField.characterValidation = InputField.CharacterValidation.Decimal;
// inputField.onValueChanged.AddListener((string value) =>
// {
// float val = float.Parse(value);
// SetValueToColor(val);
// m_sliders[index].value = val;
// });
// var sliderObj = UIFactory.CreateSlider(row, "Slider", out Slider slider);
// m_sliders[index] = slider;
// UIFactory.SetLayoutElement(sliderObj, minWidth: 200, minHeight: 25, flexibleWidth: 0, flexibleHeight: 0);
// slider.minValue = 0;
// slider.maxValue = 1;
// slider.value = GetValueFromColor();
// slider.onValueChanged.AddListener((float value) =>
// {
// inputField.text = value.ToString();
// SetValueToColor(value);
// m_inputs[index].text = value.ToString();
// });
// // methods for writing to the color for this field
// void SetValueToColor(float floatValue)
// {
// Color _color = (Color)Value;
// switch (index)
// {
// case 0: _color.r = floatValue; break;
// case 1: _color.g = floatValue; break;
// case 2: _color.b = floatValue; break;
// case 3: _color.a = floatValue; break;
// }
// Value = _color;
// m_colorImage.color = _color;
// }
// float GetValueFromColor()
// {
// Color _color = (Color)Value;
// switch (index)
// {
// case 0: return _color.r;
// case 1: return _color.g;
// case 2: return _color.b;
// case 3: return _color.a;
// default: throw new NotImplementedException();
// }
// }
// }
// #endregion
// }
//}

View File

@ -0,0 +1,246 @@
//using System;
//using System.Collections;
//using System.Collections.Generic;
//using System.Linq;
//using System.Text;
//using UnityEngine;
//using UnityEngine.UI;
//using UnityExplorer.Core.Config;
//using UnityExplorer.UI;
//using System.Reflection;
//using UnityExplorer.UI.CacheObject;
//using UnityExplorer.Core;
//using UnityExplorer.UI.Utility;
//#if CPP
//using AltIDictionary = Il2CppSystem.Collections.IDictionary;
//#else
//using AltIDictionary = System.Collections.IDictionary;
//#endif
//namespace UnityExplorer.UI.InteractiveValues
//{
// public class InteractiveDictionary : InteractiveValue
// {
// public InteractiveDictionary(object value, Type valueType) : base(value, valueType)
// {
// if (valueType.IsGenericType)
// {
// var gArgs = valueType.GetGenericArguments();
// m_typeOfKeys = gArgs[0];
// m_typeofValues = gArgs[1];
// }
// else
// {
// m_typeOfKeys = typeof(object);
// m_typeofValues = typeof(object);
// }
// }
// public override bool WantInspectBtn => false;
// public override bool HasSubContent => true;
// public override bool SubContentWanted
// {
// get
// {
// if (m_recacheWanted && Value != null)
// return true;
// else return m_entries.Count > 0;
// }
// }
// internal IDictionary RefIDictionary;
// internal AltIDictionary RefAltIDictionary;
// internal Type m_typeOfKeys;
// internal Type m_typeofValues;
// internal readonly List<KeyValuePair<CachePaired, CachePaired>> m_entries
// = new List<KeyValuePair<CachePaired, CachePaired>>();
// internal readonly KeyValuePair<CachePaired, CachePaired>[] m_displayedEntries
// = new KeyValuePair<CachePaired, CachePaired>[ConfigManager.Default_Page_Limit.Value];
// internal bool m_recacheWanted = true;
// public override void OnDestroy()
// {
// base.OnDestroy();
// }
// public override void OnValueUpdated()
// {
// RefIDictionary = Value as IDictionary;
// if (RefIDictionary == null)
// {
// try { RefAltIDictionary = Value.TryCast<AltIDictionary>(); }
// catch { }
// }
// if (m_subContentParent.activeSelf)
// {
// GetCacheEntries();
// RefreshDisplay();
// }
// else
// m_recacheWanted = true;
// base.OnValueUpdated();
// }
// internal void OnPageTurned()
// {
// RefreshDisplay();
// }
// public override void RefreshUIForValue()
// {
// GetDefaultLabel();
// if (Value != null)
// {
// string count = "?";
// if (m_recacheWanted && RefIDictionary != null)
// count = RefIDictionary.Count.ToString();
// else if (!m_recacheWanted)
// count = m_entries.Count.ToString();
// m_baseLabel.text = $"[{count}] {m_richValueType}";
// }
// else
// {
// m_baseLabel.text = DefaultLabel;
// }
// }
// public void GetCacheEntries()
// {
// if (m_entries.Any())
// {
// // maybe improve this, probably could be more efficient i guess
// foreach (var pair in m_entries)
// {
// pair.Key.Destroy();
// pair.Value.Destroy();
// }
// m_entries.Clear();
// }
// if (RefIDictionary == null && Value != null)
// RefIDictionary = RuntimeProvider.Instance.Reflection.EnumerateDictionary(Value, m_typeOfKeys, m_typeofValues);
// if (RefIDictionary != null)
// {
// int index = 0;
// foreach (var key in RefIDictionary.Keys)
// {
// var value = RefIDictionary[key];
// var cacheKey = new CachePaired(index, this, this.RefIDictionary, PairTypes.Key, m_listContent);
// cacheKey.CreateIValue(key, this.m_typeOfKeys);
// cacheKey.Disable();
// var cacheValue = new CachePaired(index, this, this.RefIDictionary, PairTypes.Value, m_listContent);
// cacheValue.CreateIValue(value, this.m_typeofValues);
// cacheValue.Disable();
// //holder.SetActive(false);
// m_entries.Add(new KeyValuePair<CachePaired, CachePaired>(cacheKey, cacheValue));
// index++;
// }
// }
// RefreshDisplay();
// }
// public void RefreshDisplay()
// {
// //var entries = m_entries;
// //m_pageHandler.ListCount = entries.Count;
// //
// //for (int i = 0; i < m_displayedEntries.Length; i++)
// //{
// // var entry = m_displayedEntries[i];
// // if (entry.Key != null && entry.Value != null)
// // {
// // //m_rowHolders[i].SetActive(false);
// // entry.Key.Disable();
// // entry.Value.Disable();
// // }
// // else
// // break;
// //}
// //
// //if (entries.Count < 1)
// // return;
// //
// //foreach (var itemIndex in m_pageHandler)
// //{
// // if (itemIndex >= entries.Count)
// // break;
// //
// // var entry = entries[itemIndex];
// // m_displayedEntries[itemIndex - m_pageHandler.StartIndex] = entry;
// //
// // //m_rowHolders[itemIndex].SetActive(true);
// // entry.Key.Enable();
// // entry.Value.Enable();
// //}
// //
// ////UpdateSubcontentHeight();
// }
// internal override void OnToggleSubcontent(bool active)
// {
// base.OnToggleSubcontent(active);
// if (active && m_recacheWanted)
// {
// m_recacheWanted = false;
// GetCacheEntries();
// RefreshUIForValue();
// }
// RefreshDisplay();
// }
// internal GameObject m_listContent;
// internal LayoutElement m_listLayout;
// // internal PageHandler m_pageHandler;
// public override void ConstructUI(GameObject parent, GameObject subGroup)
// {
// base.ConstructUI(parent, subGroup);
// }
// public override void ConstructSubcontent()
// {
// base.ConstructSubcontent();
// //m_pageHandler = new PageHandler(null);
// //m_pageHandler.ConstructUI(m_subContentParent);
// //m_pageHandler.OnPageChanged += OnPageTurned;
// m_listContent = UIFactory.CreateVerticalGroup(m_subContentParent, "DictionaryContent", true, true, true, true, 2, new Vector4(5,5,5,5),
// new Color(0.08f, 0.08f, 0.08f));
// var scrollRect = m_listContent.GetComponent<RectTransform>();
// scrollRect.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, 0);
// m_listLayout = Owner.UIRoot.GetComponent<LayoutElement>();
// m_listLayout.minHeight = 25;
// m_listLayout.flexibleHeight = 0;
// Owner.m_mainRect.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, 25);
// var contentFitter = m_listContent.AddComponent<ContentSizeFitter>();
// contentFitter.horizontalFit = ContentSizeFitter.FitMode.Unconstrained;
// contentFitter.verticalFit = ContentSizeFitter.FitMode.PreferredSize;
// }
// }
//}

View File

@ -0,0 +1,163 @@
//using System;
//using System.Collections.Generic;
//using System.Linq;
//using System.Text;
//using UnityEngine;
//using UnityEngine.UI;
//using UnityExplorer.UI;
//namespace UnityExplorer.UI.InteractiveValues
//{
// public class InteractiveEnum : InteractiveValue
// {
// internal static Dictionary<Type, KeyValuePair<int,string>[]> s_enumNamesCache = new Dictionary<Type, KeyValuePair<int, string>[]>();
// public InteractiveEnum(object value, Type valueType) : base(value, valueType)
// {
// GetNames();
// }
// public override bool HasSubContent => true;
// public override bool SubContentWanted => Owner.CanWrite;
// public override bool WantInspectBtn => false;
// internal KeyValuePair<int,string>[] m_values = new KeyValuePair<int, string>[0];
// internal Type m_lastEnumType;
// internal void GetNames()
// {
// var type = Value?.GetType() ?? FallbackType;
// if (m_lastEnumType == type)
// return;
// m_lastEnumType = type;
// if (m_subContentConstructed)
// {
// DestroySubContent();
// }
// if (!s_enumNamesCache.ContainsKey(type))
// {
// // using GetValues not GetNames, to catch instances of weird enums (eg CameraClearFlags)
// var values = Enum.GetValues(type);
// var list = new List<KeyValuePair<int, string>>();
// var set = new HashSet<string>();
// foreach (var value in values)
// {
// var name = value.ToString();
// if (set.Contains(name))
// continue;
// set.Add(name);
// var backingType = Enum.GetUnderlyingType(type);
// int intValue;
// try
// {
// // this approach is necessary, a simple '(int)value' is not sufficient.
// var unbox = Convert.ChangeType(value, backingType);
// intValue = (int)Convert.ChangeType(unbox, typeof(int));
// }
// catch (Exception ex)
// {
// ExplorerCore.LogWarning("[InteractiveEnum] Could not Unbox underlying type " + backingType.Name + " from " + type.FullName);
// ExplorerCore.Log(ex.ToString());
// continue;
// }
// list.Add(new KeyValuePair<int, string>(intValue, name));
// }
// s_enumNamesCache.Add(type, list.ToArray());
// }
// m_values = s_enumNamesCache[type];
// }
// public override void OnValueUpdated()
// {
// GetNames();
// base.OnValueUpdated();
// }
// public override void RefreshUIForValue()
// {
// base.RefreshUIForValue();
// if (m_subContentConstructed && !(this is InteractiveFlags))
// {
// m_dropdownText.text = Value?.ToString() ?? "<no value set>";
// }
// }
// internal override void OnToggleSubcontent(bool toggle)
// {
// base.OnToggleSubcontent(toggle);
// RefreshUIForValue();
// }
// private void SetValueFromDropdown()
// {
// var type = Value?.GetType() ?? FallbackType;
// var index = m_dropdown.value;
// var value = Enum.Parse(type, s_enumNamesCache[type][index].Value);
// if (value != null)
// {
// Value = value;
// Owner.SetValue();
// RefreshUIForValue();
// }
// }
// internal Dropdown m_dropdown;
// internal Text m_dropdownText;
// public override void ConstructUI(GameObject parent, GameObject subGroup)
// {
// base.ConstructUI(parent, subGroup);
// }
// public override void ConstructSubcontent()
// {
// base.ConstructSubcontent();
// if (Owner.CanWrite)
// {
// var groupObj = UIFactory.CreateHorizontalGroup(m_subContentParent, "InteractiveEnumGroup", false, true, true, true, 5,
// new Vector4(3,3,3,3),new Color(1, 1, 1, 0));
// // apply button
// var apply = UIFactory.CreateButton(groupObj, "ApplyButton", "Apply", SetValueFromDropdown, new Color(0.3f, 0.3f, 0.3f));
// UIFactory.SetLayoutElement(apply.gameObject, minHeight: 25, minWidth: 50);
// // dropdown
// var dropdownObj = UIFactory.CreateDropdown(groupObj, out m_dropdown, "", 14, null);
// UIFactory.SetLayoutElement(dropdownObj, minWidth: 150, minHeight: 25, flexibleWidth: 120);
// foreach (var kvp in m_values)
// {
// m_dropdown.options.Add(new Dropdown.OptionData
// {
// text = $"{kvp.Key}: {kvp.Value}"
// });
// }
// m_dropdownText = m_dropdown.transform.Find("Label").GetComponent<Text>();
// }
// }
// }
//}

View File

@ -0,0 +1,245 @@
//using System;
//using System.Collections;
//using System.Collections.Generic;
//using System.Linq;
//using System.Reflection;
//using System.Text;
//using UnityEngine;
//using UnityEngine.UI;
//using UnityExplorer.Core;
//using UnityExplorer.Core.Config;
//using UnityExplorer.UI;
//using UnityExplorer.UI.CacheObject;
//using UnityExplorer.UI.Utility;
//using UnityExplorer.UI.Widgets;
//namespace UnityExplorer.UI.InteractiveValues
//{
// public class InteractiveEnumerable : InteractiveValue, IPoolDataSource
// {
// // IPoolDataSource
// public ScrollPool ScrollPool;
// public GameObject InactiveHolder;
// internal LayoutElement listLayout;
// public int ItemCount => m_entries?.Count ?? 0;
// public void SetCell(ICell icell, int index)
// {
// var cell = icell as CellViewHolder;
// if (index < 0 || index >= ItemCount)
// {
// var existing = cell.DisableContent();
// if (existing)
// existing.transform.SetParent(InactiveHolder.transform, false);
// return;
// }
// var cache = m_entries[index];
// cache.Enable();
// var prev = cell.SetContent(cache.UIRoot);
// if (prev)
// prev.transform.SetParent(InactiveHolder.transform, false);
// }
// public void DisableCell(ICell cell, int index)
// {
// var content = (cell as CellViewHolder).DisableContent();
// if (content)
// content.transform.SetParent(InactiveHolder.transform, false);
// }
// //public void SetCell(ICell cell, int index)
// //{
// // var root = (cell as CellViewHolder).UIRoot;
// // if (index < 0 || index >= ItemCount)
// // {
// // DisableContent(root);
// // cell.Disable();
// // return;
// // }
// // var cache = m_entries[index];
// // cache.Enable();
// // var content = cache.UIRoot;
// // if (content.transform.parent.ReferenceEqual(root.transform))
// // return;
// // DisableContent(root);
// // content.transform.SetParent(root.transform, false);
// //}
// //public void DisableCell(ICell cell, int index)
// //{
// // var root = (cell as CellViewHolder).UIRoot;
// // DisableContent(root);
// // cell.Disable();
// //}
// //private void DisableContent(GameObject cellRoot)
// //{
// // if (cellRoot.transform.childCount > 0 && cellRoot.transform.GetChild(0) is Transform existing)
// // existing.transform.SetParent(InactiveHolder.transform, false);
// //}
// public ICell CreateCell(RectTransform cellTransform) => new CellViewHolder(cellTransform.gameObject);
// public int GetRealIndexOfTempIndex(int tempIndex) => throw new NotImplementedException("Filtering not supported");
// // InteractiveEnumerable
// public InteractiveEnumerable(object value, Type valueType) : base(value, valueType)
// {
// if (valueType.IsGenericType)
// m_baseEntryType = valueType.GetGenericArguments()[0];
// else
// m_baseEntryType = typeof(object);
// }
// public override bool WantInspectBtn => false;
// public override bool HasSubContent => true;
// public override bool SubContentWanted
// {
// get
// {
// if (m_recacheWanted && Value != null)
// return true;
// else return m_entries.Count > 0;
// }
// }
// internal IEnumerable RefIEnumerable;
// internal IList RefIList;
// internal readonly Type m_baseEntryType;
// internal readonly List<CacheEnumerated> m_entries = new List<CacheEnumerated>();
// internal readonly CacheEnumerated[] m_displayedEntries = new CacheEnumerated[ConfigManager.Default_Page_Limit.Value];
// internal bool m_recacheWanted = true;
// public override void OnValueUpdated()
// {
// RefIEnumerable = Value as IEnumerable;
// RefIList = Value as IList;
// if (m_subContentParent && m_subContentParent.activeSelf)
// {
// ToggleSubcontent();
// //GetCacheEntries();
// //RefreshDisplay();
// }
// m_recacheWanted = true;
// base.OnValueUpdated();
// }
// public override void OnException(CacheMember member)
// {
// base.OnException(member);
// }
// public override void RefreshUIForValue()
// {
// GetDefaultLabel();
// if (Value != null)
// {
// string count = "?";
// if (m_recacheWanted && RefIList != null)
// count = RefIList.Count.ToString();
// else if (!m_recacheWanted)
// count = m_entries.Count.ToString();
// m_baseLabel.text = $"[{count}] {m_richValueType}";
// }
// else
// {
// m_baseLabel.text = DefaultLabel;
// }
// }
// public void GetCacheEntries()
// {
// if (m_entries.Any())
// {
// foreach (var entry in m_entries)
// entry.Destroy();
// m_entries.Clear();
// }
// if (RefIEnumerable == null && Value != null)
// RefIEnumerable = RuntimeProvider.Instance.Reflection.EnumerateEnumerable(Value);
// if (RefIEnumerable != null)
// {
// int index = 0;
// foreach (var entry in RefIEnumerable)
// {
// var cache = new CacheEnumerated(index, this, RefIList, this.InactiveHolder);
// cache.CreateIValue(entry, m_baseEntryType);
// m_entries.Add(cache);
// cache.Disable();
// index++;
// }
// }
// RefreshDisplay();
// }
// public void RefreshDisplay()
// {
// ScrollPool.RefreshCells(true);
// listLayout.minHeight = Math.Min(500f, m_entries.Count * 32f);
// }
// internal override void OnToggleSubcontent(bool active)
// {
// base.OnToggleSubcontent(active);
// if (active && m_recacheWanted)
// {
// m_recacheWanted = false;
// GetCacheEntries();
// RefreshUIForValue();
// }
// RefreshDisplay();
// }
// public override void ConstructUI(GameObject parent, GameObject subGroup)
// {
// base.ConstructUI(parent, subGroup);
// InactiveHolder = new GameObject("InactiveHolder");
// InactiveHolder.transform.SetParent(parent.transform, false);
// InactiveHolder.SetActive(false);
// }
// public override void ConstructSubcontent()
// {
// base.ConstructSubcontent();
// ScrollPool = UIFactory.CreateScrollPool(m_subContentParent, "ListEntries", out GameObject scrollRoot, out GameObject scrollContent,
// new Color(0.05f, 0.05f, 0.05f));
// listLayout = scrollRoot.AddComponent<LayoutElement>();
// var proto = CellViewHolder.CreatePrototypeCell(scrollRoot);
// proto.sizeDelta = new Vector2(100, 30);
// ScrollPool.Initialize(this, proto);
// }
// }
//}

View File

@ -0,0 +1,125 @@
//using System;
//using System.Collections.Generic;
//using System.Linq;
//using System.Text;
//using UnityEngine;
//using UnityEngine.UI;
//using UnityExplorer.UI;
//namespace UnityExplorer.UI.InteractiveValues
//{
// public class InteractiveFlags : InteractiveEnum
// {
// public InteractiveFlags(object value, Type valueType) : base(value, valueType)
// {
// m_toggles = new Toggle[m_values.Length];
// m_enabledFlags = new bool[m_values.Length];
// }
// public override bool HasSubContent => true;
// public override bool SubContentWanted => Owner.CanWrite;
// public override bool WantInspectBtn => false;
// internal bool[] m_enabledFlags;
// internal Toggle[] m_toggles;
// public override void OnValueUpdated()
// {
// if (Owner.CanWrite)
// {
// var enabledNames = new List<string>();
// var enabled = Value?.ToString().Split(',').Select(it => it.Trim());
// if (enabled != null)
// enabledNames.AddRange(enabled);
// for (int i = 0; i < m_values.Length; i++)
// m_enabledFlags[i] = enabledNames.Contains(m_values[i].Value);
// }
// base.OnValueUpdated();
// }
// public override void RefreshUIForValue()
// {
// GetDefaultLabel();
// m_baseLabel.text = DefaultLabel;
// base.RefreshUIForValue();
// if (m_subContentConstructed)
// {
// for (int i = 0; i < m_values.Length; i++)
// {
// var toggle = m_toggles[i];
// if (toggle.isOn != m_enabledFlags[i])
// toggle.isOn = m_enabledFlags[i];
// }
// }
// }
// private void SetValueFromToggles()
// {
// string val = "";
// for (int i = 0; i < m_values.Length; i++)
// {
// if (m_enabledFlags[i])
// {
// if (val != "") val += ", ";
// val += m_values[i].Value;
// }
// }
// var type = Value?.GetType() ?? FallbackType;
// Value = Enum.Parse(type, val);
// RefreshUIForValue();
// Owner.SetValue();
// }
// internal override void OnToggleSubcontent(bool toggle)
// {
// base.OnToggleSubcontent(toggle);
// RefreshUIForValue();
// }
// public override void ConstructUI(GameObject parent, GameObject subGroup)
// {
// base.ConstructUI(parent, subGroup);
// }
// public override void ConstructSubcontent()
// {
// m_subContentConstructed = true;
// if (Owner.CanWrite)
// {
// var groupObj = UIFactory.CreateVerticalGroup(m_subContentParent, "InteractiveFlagsContent", false, true, true, true, 5,
// new Vector4(3,3,3,3), new Color(1, 1, 1, 0));
// // apply button
// var apply = UIFactory.CreateButton(groupObj, "ApplyButton", "Apply", SetValueFromToggles, new Color(0.3f, 0.3f, 0.3f));
// UIFactory.SetLayoutElement(apply.gameObject, minWidth: 50, minHeight: 25);
// // toggles
// for (int i = 0; i < m_values.Length; i++)
// AddToggle(i, groupObj);
// }
// }
// internal void AddToggle(int index, GameObject groupObj)
// {
// var value = m_values[index];
// var toggleObj = UIFactory.CreateToggle(groupObj, "FlagToggle", out Toggle toggle, out Text text, new Color(0.1f, 0.1f, 0.1f));
// UIFactory.SetLayoutElement(toggleObj, minWidth: 100, flexibleWidth: 2000, minHeight: 25);
// m_toggles[index] = toggle;
// toggle.onValueChanged.AddListener((bool val) => { m_enabledFlags[index] = val; });
// text.text = $"{value.Key}: {value.Value}";
// }
// }
//}

View File

@ -0,0 +1,203 @@
//using System;
//using System.Collections.Generic;
//using System.Linq;
//using System.Text;
//using UnityEngine;
//using UnityEngine.UI;
//using System.Reflection;
//namespace UnityExplorer.UI.InteractiveValues
//{
// // Class for supporting any "float struct" (ie Vector, Rect, etc).
// // Supports any struct where all the public instance fields are floats (or types assignable to float)
// public class StructInfo
// {
// public string[] FieldNames { get; }
// private readonly FieldInfo[] m_fields;
// public StructInfo(Type type)
// {
// m_fields = type.GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public)
// .Where(it => !it.IsLiteral)
// .ToArray();
// FieldNames = m_fields.Select(it => it.Name)
// .ToArray();
// }
// public object SetValue(ref object instance, int fieldIndex, float val)
// {
// m_fields[fieldIndex].SetValue(instance, val);
// return instance;
// }
// public float GetValue(object instance, int fieldIndex)
// => (float)m_fields[fieldIndex].GetValue(instance);
// public void RefreshUI(InputField[] inputs, object instance)
// {
// try
// {
// for (int i = 0; i < m_fields.Length; i++)
// {
// var field = m_fields[i];
// float val = (float)field.GetValue(instance);
// inputs[i].text = val.ToString();
// }
// }
// catch (Exception ex)
// {
// ExplorerCore.Log(ex);
// }
// }
// }
// public class InteractiveFloatStruct : InteractiveValue
// {
// private static readonly Dictionary<string, bool> _typeSupportCache = new Dictionary<string, bool>();
// public static bool IsTypeSupported(Type type)
// {
// if (!type.IsValueType)
// return false;
// if (string.IsNullOrEmpty(type.AssemblyQualifiedName))
// return false;
// if (_typeSupportCache.TryGetValue(type.AssemblyQualifiedName, out bool ret))
// return ret;
// if (type.FullName == "System.Void")
// return false;
// ret = true;
// var fields = type.GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
// foreach (var field in fields)
// {
// if (field.IsLiteral)
// continue;
// if (!typeof(float).IsAssignableFrom(field.FieldType))
// {
// ret = false;
// break;
// }
// }
// _typeSupportCache.Add(type.AssemblyQualifiedName, ret);
// return ret;
// }
// //~~~~~~~~~ Instance ~~~~~~~~~~
// public InteractiveFloatStruct(object value, Type valueType) : base(value, valueType) { }
// public override bool HasSubContent => true;
// public override bool SubContentWanted => true;
// public StructInfo StructInfo;
// public override void RefreshUIForValue()
// {
// InitializeStructInfo();
// base.RefreshUIForValue();
// if (m_subContentConstructed)
// StructInfo.RefreshUI(m_inputs, this.Value);
// }
// internal override void OnToggleSubcontent(bool toggle)
// {
// InitializeStructInfo();
// base.OnToggleSubcontent(toggle);
// StructInfo.RefreshUI(m_inputs, this.Value);
// }
// internal Type m_lastStructType;
// internal void InitializeStructInfo()
// {
// var type = Value?.GetType() ?? FallbackType;
// if (StructInfo != null && type == m_lastStructType)
// return;
// if (StructInfo != null && m_subContentConstructed)
// DestroySubContent();
// m_lastStructType = type;
// StructInfo = new StructInfo(type);
// if (m_subContentParent.activeSelf)
// ConstructSubcontent();
// }
// #region UI CONSTRUCTION
// internal InputField[] m_inputs;
// public override void ConstructUI(GameObject parent, GameObject subGroup)
// {
// base.ConstructUI(parent, subGroup);
// }
// public override void ConstructSubcontent()
// {
// base.ConstructSubcontent();
// if (StructInfo == null)
// {
// ExplorerCore.LogWarning("Setting up subcontent but structinfo is null");
// return;
// }
// var editorContainer = UIFactory.CreateVerticalGroup(m_subContentParent, "EditorContent", false, true, true, true, 2, new Vector4(4, 4, 4, 4),
// new Color(0.08f, 0.08f, 0.08f));
// m_inputs = new InputField[StructInfo.FieldNames.Length];
// for (int i = 0; i < StructInfo.FieldNames.Length; i++)
// AddEditorRow(i, editorContainer);
// RefreshUIForValue();
// }
// internal void AddEditorRow(int index, GameObject groupObj)
// {
// try
// {
// var row = UIFactory.CreateHorizontalGroup(groupObj, "EditorRow", false, true, true, true, 5, default, new Color(1, 1, 1, 0));
// string name = StructInfo.FieldNames[index];
// var label = UIFactory.CreateLabel(row, "RowLabel", $"{name}:", TextAnchor.MiddleRight, Color.cyan);
// UIFactory.SetLayoutElement(label.gameObject, minWidth: 30, flexibleWidth: 0, minHeight: 25);
// var inputFieldObj = UIFactory.CreateInputField(row, "InputField", "...", out InputField inputField, 14, 3, 1);
// UIFactory.SetLayoutElement(inputFieldObj, minWidth: 120, minHeight: 25, flexibleWidth: 0);
// m_inputs[index] = inputField;
// inputField.onValueChanged.AddListener((string val) =>
// {
// try
// {
// float f = float.Parse(val);
// Value = StructInfo.SetValue(ref this.Value, index, f);
// Owner.SetValue();
// }
// catch { }
// });
// }
// catch (Exception ex)
// {
// ExplorerCore.Log(ex);
// }
// }
// #endregion
// }
//}

View File

@ -0,0 +1,115 @@
//using System;
//using System.Collections.Generic;
//using System.Linq;
//using System.Text;
//using System.Reflection;
//using UnityEngine;
//using UnityEngine.UI;
//using UnityExplorer.UI;
//using UnityExplorer.Core;
//using UnityExplorer.UI.Utility;
//using UnityExplorer.UI.CacheObject;
//namespace UnityExplorer.UI.InteractiveValues
//{
// public class InteractiveNumber : InteractiveValue
// {
// public InteractiveNumber(object value, Type valueType) : base(value, valueType) { }
// public override bool HasSubContent => false;
// public override bool SubContentWanted => false;
// public override bool WantInspectBtn => false;
// public override void OnValueUpdated()
// {
// base.OnValueUpdated();
// }
// public override void OnException(CacheMember member)
// {
// base.OnException(member);
// if (m_valueInput.gameObject.activeSelf)
// m_valueInput.gameObject.SetActive(false);
// if (Owner.CanWrite)
// {
// if (m_applyBtn.gameObject.activeSelf)
// m_applyBtn.gameObject.SetActive(false);
// }
// }
// public override void RefreshUIForValue()
// {
// if (!Owner.HasEvaluated)
// {
// GetDefaultLabel();
// m_baseLabel.text = DefaultLabel;
// return;
// }
// m_baseLabel.text = SignatureHighlighter.ParseFullSyntax(FallbackType, false);
// m_valueInput.text = Value.ToString();
// var type = Value.GetType();
// if (type == typeof(float)
// || type == typeof(double)
// || type == typeof(decimal))
// {
// m_valueInput.characterValidation = InputField.CharacterValidation.Decimal;
// }
// else
// {
// m_valueInput.characterValidation = InputField.CharacterValidation.Integer;
// }
// if (Owner.CanWrite)
// {
// if (!m_applyBtn.gameObject.activeSelf)
// m_applyBtn.gameObject.SetActive(true);
// }
// if (!m_valueInput.gameObject.activeSelf)
// m_valueInput.gameObject.SetActive(true);
// }
// public MethodInfo ParseMethod => m_parseMethod ?? (m_parseMethod = Value.GetType().GetMethod("Parse", new Type[] { typeof(string) }));
// private MethodInfo m_parseMethod;
// internal void OnApplyClicked()
// {
// try
// {
// Value = ParseMethod.Invoke(null, new object[] { m_valueInput.text });
// Owner.SetValue();
// RefreshUIForValue();
// }
// catch (Exception e)
// {
// ExplorerCore.LogWarning("Could not parse input! " + ReflectionUtility.ReflectionExToString(e, true));
// }
// }
// internal InputField m_valueInput;
// internal Button m_applyBtn;
// public override void ConstructUI(GameObject parent, GameObject subGroup)
// {
// base.ConstructUI(parent, subGroup);
// var labelLayout = m_baseLabel.gameObject.GetComponent<LayoutElement>();
// labelLayout.minWidth = 50;
// labelLayout.flexibleWidth = 0;
// var inputObj = UIFactory.CreateInputField(m_mainContent, "InteractiveNumberInput", "...", out m_valueInput);
// UIFactory.SetLayoutElement(inputObj, minWidth: 120, minHeight: 25, flexibleWidth: 0);
// m_valueInput.gameObject.SetActive(false);
// if (Owner.CanWrite)
// {
// m_applyBtn = UIFactory.CreateButton(m_mainContent, "ApplyButton", "Apply", OnApplyClicked, new Color(0.2f, 0.2f, 0.2f));
// UIFactory.SetLayoutElement(m_applyBtn.gameObject, minWidth: 50, minHeight: 25, flexibleWidth: 0);
// }
// }
// }
//}

View File

@ -0,0 +1,186 @@
//using System;
//using System.Collections.Generic;
//using System.Linq;
//using System.Text;
//using System.Reflection;
//using UnityEngine;
//using UnityEngine.UI;
//using UnityExplorer.UI;
//using UnityExplorer.UI.Utility;
//using UnityExplorer.UI.CacheObject;
//using UnityExplorer.Core.Runtime;
//namespace UnityExplorer.UI.InteractiveValues
//{
// public class InteractiveString : InteractiveValue
// {
// public InteractiveString(object value, Type valueType) : base(value, valueType) { }
// public override bool HasSubContent => true;
// public override bool SubContentWanted => true;
// public override bool WantInspectBtn => false;
// public override void OnValueUpdated()
// {
// if (!(Value is string) && Value != null)
// Value = RuntimeProvider.Instance.Reflection.UnboxString(Value);
// base.OnValueUpdated();
// }
// public override void OnException(CacheMember member)
// {
// base.OnException(member);
// if (m_subContentConstructed && m_hiddenObj.gameObject.activeSelf)
// m_hiddenObj.gameObject.SetActive(false);
// m_labelLayout.minWidth = 200;
// m_labelLayout.flexibleWidth = 5000;
// }
// public override void RefreshUIForValue()
// {
// GetDefaultLabel(false);
// if (!Owner.HasEvaluated)
// {
// m_baseLabel.text = DefaultLabel;
// return;
// }
// m_baseLabel.text = m_richValueType;
// if (m_subContentConstructed)
// {
// if (!m_hiddenObj.gameObject.activeSelf)
// m_hiddenObj.gameObject.SetActive(true);
// }
// if (!string.IsNullOrEmpty((string)Value))
// {
// var toString = (string)Value;
// if (toString.Length > 15000)
// toString = toString.Substring(0, 15000);
// m_readonlyInput.text = toString;
// if (m_subContentConstructed)
// {
// m_valueInput.text = toString;
// m_placeholderText.text = toString;
// }
// }
// else
// {
// string s = Value == null
// ? "null"
// : "empty";
// m_readonlyInput.text = $"<i><color=grey>{s}</color></i>";
// if (m_subContentConstructed)
// {
// m_valueInput.text = "";
// m_placeholderText.text = s;
// }
// }
// m_labelLayout.minWidth = 50;
// m_labelLayout.flexibleWidth = 0;
// }
// internal void SetValueFromInput()
// {
// Value = m_valueInput.text;
// if (!typeof(string).IsAssignableFrom(Owner.FallbackType))
// ReflectionProvider.Instance.BoxStringToType(ref Value, Owner.FallbackType);
// Owner.SetValue();
// // revert back to string now
// OnValueUpdated();
// RefreshUIForValue();
// }
// // for the default label
// internal LayoutElement m_labelLayout;
// //internal InputField m_readonlyInput;
// internal Text m_readonlyInput;
// // for input
// internal InputField m_valueInput;
// internal GameObject m_hiddenObj;
// internal Text m_placeholderText;
// public override void ConstructUI(GameObject parent, GameObject subGroup)
// {
// base.ConstructUI(parent, subGroup);
// GetDefaultLabel(false);
// m_richValueType = SignatureHighlighter.ParseFullSyntax(FallbackType, false);
// m_labelLayout = m_baseLabel.gameObject.GetComponent<LayoutElement>();
// m_readonlyInput = UIFactory.CreateLabel(m_mainContent, "ReadonlyLabel", "", TextAnchor.MiddleLeft);
// m_readonlyInput.horizontalOverflow = HorizontalWrapMode.Overflow;
// var testFitter = m_readonlyInput.gameObject.AddComponent<ContentSizeFitter>();
// testFitter.verticalFit = ContentSizeFitter.FitMode.MinSize;
// UIFactory.SetLayoutElement(m_readonlyInput.gameObject, minHeight: 25, preferredHeight: 25, flexibleHeight: 0);
// }
// public override void ConstructSubcontent()
// {
// base.ConstructSubcontent();
// var groupObj = UIFactory.CreateVerticalGroup(m_subContentParent, "SubContent", false, false, true, true, 4, new Vector4(3,3,3,3),
// new Color(1, 1, 1, 0));
// m_hiddenObj = UIFactory.CreateLabel(groupObj, "HiddenLabel", "", TextAnchor.MiddleLeft).gameObject;
// m_hiddenObj.SetActive(false);
// var hiddenText = m_hiddenObj.GetComponent<Text>();
// hiddenText.color = Color.clear;
// hiddenText.fontSize = 14;
// hiddenText.raycastTarget = false;
// hiddenText.supportRichText = false;
// var hiddenFitter = m_hiddenObj.AddComponent<ContentSizeFitter>();
// hiddenFitter.verticalFit = ContentSizeFitter.FitMode.PreferredSize;
// UIFactory.SetLayoutElement(m_hiddenObj, minHeight: 25, flexibleHeight: 500, minWidth: 250, flexibleWidth: 9000);
// UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(m_hiddenObj, true, true, true, true);
// var inputObj = UIFactory.CreateInputField(m_hiddenObj, "StringInputField", "...", out m_valueInput, 14, 3);
// UIFactory.SetLayoutElement(inputObj, minWidth: 120, minHeight: 25, flexibleWidth: 5000, flexibleHeight: 5000);
// m_valueInput.lineType = InputField.LineType.MultiLineNewline;
// m_placeholderText = m_valueInput.placeholder.GetComponent<Text>();
// m_placeholderText.supportRichText = false;
// m_valueInput.textComponent.supportRichText = false;
// m_valueInput.onValueChanged.AddListener((string val) =>
// {
// hiddenText.text = val ?? "";
// LayoutRebuilder.ForceRebuildLayoutImmediate(Owner.m_mainRect);
// });
// if (Owner.CanWrite)
// {
// var apply = UIFactory.CreateButton(groupObj, "ApplyButton", "Apply", SetValueFromInput, new Color(0.2f, 0.2f, 0.2f));
// UIFactory.SetLayoutElement(apply.gameObject, minWidth: 50, minHeight: 25, flexibleWidth: 0);
// }
// else
// {
// m_valueInput.readOnly = true;
// }
// RefreshUIForValue();
// }
// }
//}

View File

@ -0,0 +1,355 @@
//using System;
//using System.Collections.Generic;
//using System.Linq;
//using System.Reflection;
//using UnityEngine;
//using UnityEngine.EventSystems;
//using UnityEngine.UI;
//using UnityExplorer.Core;
//using UnityExplorer.Core.Runtime;
//using UnityExplorer.UI;
//using UnityExplorer.UI.Utility;
//using UnityExplorer.UI.CacheObject;
//using UnityExplorer.Inspectors;
//namespace UnityExplorer.UI.InteractiveValues
//{
// public class InteractiveValue
// {
// /// <summary>
// /// Get the <see cref="InteractiveValue"/> subclass which supports the provided <paramref name="type"/>.
// /// </summary>
// /// <param name="type">The <see cref="Type"/> which you want the <see cref="InteractiveValue"/> Type for.</param>
// /// <returns>The best subclass of <see cref="InteractiveValue"/> which supports the provided <paramref name="type"/>.</returns>
// public static Type GetIValueForType(Type type)
// {
// // rather ugly but I couldn't think of a cleaner way that was worth it.
// // switch-case doesn't really work here.
// // arbitrarily check some types, fastest methods first.
// if (type == typeof(bool))
// return typeof(InteractiveBool);
// // if type is primitive then it must be a number if its not a bool. Also check for decimal.
// else if (type.IsPrimitive || type == typeof(decimal))
// return typeof(InteractiveNumber);
// // check for strings
// else if (type == typeof(string))
// return typeof(InteractiveString);
// // check for enum/flags
// else if (typeof(Enum).IsAssignableFrom(type))
// {
// // NET 3.5 doesn't have "GetCustomAttribute", gotta use the multiple version.
// if (type.GetCustomAttributes(typeof(FlagsAttribute), true) is object[] fa && fa.Any())
// return typeof(InteractiveFlags);
// else
// return typeof(InteractiveEnum);
// }
// // check for unity struct types
// else if (typeof(Color).IsAssignableFrom(type))
// return typeof(InteractiveColor);
// else if (InteractiveFloatStruct.IsTypeSupported(type))
// return typeof(InteractiveFloatStruct);
// // check Transform, force InteractiveValue so they dont become InteractiveEnumerables.
// else if (typeof(Transform).IsAssignableFrom(type))
// return typeof(InteractiveValue);
// // check Dictionaries before Enumerables
// else if (ReflectionUtility.IsDictionary(type))
// return typeof(InteractiveDictionary);
// // finally check for Enumerables
// else if (ReflectionUtility.IsEnumerable(type))
// return typeof(InteractiveEnumerable);
// // fallback to default
// else
// return typeof(InteractiveValue);
// }
// public static InteractiveValue Create(object value, Type fallbackType)
// {
// var type = ReflectionUtility.GetActualType(value) ?? fallbackType;
// var iType = GetIValueForType(type);
// return (InteractiveValue)Activator.CreateInstance(iType, new object[] { value, type });
// }
// // ~~~~~~~~~ Instance ~~~~~~~~~
// public InteractiveValue(object value, Type valueType)
// {
// this.Value = value;
// this.FallbackType = valueType;
// }
// public CacheObjectBase Owner;
// public object Value;
// public readonly Type FallbackType;
// public virtual bool HasSubContent => false;
// public virtual bool SubContentWanted => false;
// public virtual bool WantInspectBtn => true;
// public string DefaultLabel => m_defaultLabel ?? GetDefaultLabel();
// internal string m_defaultLabel;
// internal string m_richValueType;
// public bool m_UIConstructed;
// public virtual void OnDestroy()
// {
// if (this.m_mainContent)
// {
// m_mainContent.transform.SetParent(null, false);
// m_mainContent.SetActive(false);
// GameObject.Destroy(this.m_mainContent.gameObject);
// }
// DestroySubContent();
// }
// public virtual void DestroySubContent()
// {
// if (this.m_subContentParent && HasSubContent)
// {
// for (int i = 0; i < this.m_subContentParent.transform.childCount; i++)
// {
// var child = m_subContentParent.transform.GetChild(i);
// if (child)
// GameObject.Destroy(child.gameObject);
// }
// }
// m_subContentConstructed = false;
// }
// public virtual void OnValueUpdated()
// {
// if (!m_UIConstructed)
// ConstructUI(m_mainContentParent, m_subContentParent);
// if (Owner is CacheMember ownerMember && !string.IsNullOrEmpty(ownerMember.ReflectionException))
// OnException(ownerMember);
// else
// RefreshUIForValue();
// }
// public virtual void OnException(CacheMember member)
// {
// if (m_UIConstructed)
// m_baseLabel.text = "<color=red>" + member.ReflectionException + "</color>";
// Value = null;
// }
// public virtual void RefreshUIForValue()
// {
// GetDefaultLabel();
// m_baseLabel.text = DefaultLabel;
// }
// public void RefreshElementsAfterUpdate()
// {
// if (WantInspectBtn)
// {
// bool shouldShowInspect = !Value.IsNullOrDestroyed();
// if (m_inspectButton.activeSelf != shouldShowInspect)
// m_inspectButton.SetActive(shouldShowInspect);
// }
// bool subContentWanted = SubContentWanted;
// if (Owner is CacheMember cm && (!cm.HasEvaluated || !string.IsNullOrEmpty(cm.ReflectionException)))
// subContentWanted = false;
// if (HasSubContent)
// {
// if (m_subExpandBtn.gameObject.activeSelf != subContentWanted)
// m_subExpandBtn.gameObject.SetActive(subContentWanted);
// if (!subContentWanted && m_subContentParent.activeSelf)
// ToggleSubcontent();
// }
// }
// public virtual void ConstructSubcontent()
// {
// Owner.CheckSubcontentCreation();
// m_subContentConstructed = true;
// }
// public void ToggleSubcontent()
// {
// if (!this.m_subContentParent.activeSelf)
// {
// this.m_subContentParent.SetActive(true);
// this.m_subContentParent.transform.SetAsLastSibling();
// m_subExpandBtn.GetComponentInChildren<Text>().text = "▼";
// }
// else
// {
// this.m_subContentParent.SetActive(false);
// m_subExpandBtn.GetComponentInChildren<Text>().text = "▲";
// }
// OnToggleSubcontent(m_subContentParent.activeSelf);
// RefreshElementsAfterUpdate();
// }
// internal virtual void OnToggleSubcontent(bool toggle)
// {
// if (!m_subContentConstructed)
// ConstructSubcontent();
// }
// internal MethodInfo m_toStringMethod;
// internal MethodInfo m_toStringFormatMethod;
// internal bool m_gotToStringMethods;
// public string GetDefaultLabel(bool updateType = true)
// {
// var valueType = Value?.GetType() ?? this.FallbackType;
// if (updateType)
// m_richValueType = SignatureHighlighter.ParseFullSyntax(valueType, true);
// if (!Owner.HasEvaluated)
// return m_defaultLabel = $"<i><color=grey>Not yet evaluated</color> ({m_richValueType})</i>";
// if (Value.IsNullOrDestroyed())
// return m_defaultLabel = $"<color=grey>null</color> ({m_richValueType})";
// string label;
// // Two dirty fixes for TextAsset and EventSystem, which can have very long ToString results.
// if (Value is TextAsset textAsset)
// {
// label = textAsset.text;
// if (label.Length > 10)
// label = $"{label.Substring(0, 10)}...";
// label = $"\"{label}\" {textAsset.name} ({m_richValueType})";
// }
// else if (Value is EventSystem)
// {
// label = m_richValueType;
// }
// else // For everything else...
// {
// if (!m_gotToStringMethods)
// {
// m_gotToStringMethods = true;
// m_toStringMethod = valueType.GetMethod("ToString", new Type[0]);
// m_toStringFormatMethod = valueType.GetMethod("ToString", new Type[] { typeof(string) });
// // test format method actually works
// try
// {
// m_toStringFormatMethod.Invoke(Value, new object[] { "F3" });
// }
// catch
// {
// m_toStringFormatMethod = null;
// }
// }
// string toString;
// if (m_toStringFormatMethod != null)
// toString = (string)m_toStringFormatMethod.Invoke(Value, new object[] { "F3" });
// else
// toString = (string)m_toStringMethod.Invoke(Value, new object[0]);
// toString = toString ?? "";
// string typeName = valueType.FullName;
// if (typeName.StartsWith("Il2CppSystem."))
// typeName = typeName.Substring(6, typeName.Length - 6);
// toString = ReflectionProvider.Instance.ProcessTypeFullNameInString(valueType, toString, ref typeName);
// // If the ToString is just the type name, use our syntax highlighted type name instead.
// if (toString == typeName)
// {
// label = m_richValueType;
// }
// else // Otherwise, parse the result and put our highlighted name in.
// {
// if (toString.Length > 200)
// toString = toString.Substring(0, 200) + "...";
// label = toString;
// var unityType = $"({valueType.FullName})";
// if (Value is UnityEngine.Object && label.Contains(unityType))
// label = label.Replace(unityType, $"({m_richValueType})");
// else
// label += $" ({m_richValueType})";
// }
// }
// return m_defaultLabel = label;
// }
// #region UI CONSTRUCTION
// internal GameObject m_mainContentParent;
// internal GameObject m_subContentParent;
// internal GameObject m_mainContent;
// internal GameObject m_inspectButton;
// internal Text m_baseLabel;
// internal Button m_subExpandBtn;
// internal bool m_subContentConstructed;
// public virtual void ConstructUI(GameObject parent, GameObject subGroup)
// {
// m_UIConstructed = true;
// //m_mainContent = UIFactory.CreateHorizontalGroup(parent, $"InteractiveValue_{this.GetType().Name}", false, false, true, true, 4, default,
// // new Color(1, 1, 1, 0), TextAnchor.UpperLeft);
// m_mainContent = UIFactory.CreateUIObject($"InteractiveValue_{this.GetType().Name}", parent);
// UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(m_mainContent, false, false, true, true, 4, 0, 0, 0, 0, TextAnchor.UpperLeft);
// var mainRect = m_mainContent.GetComponent<RectTransform>();
// mainRect.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, 25);
// UIFactory.SetLayoutElement(m_mainContent, flexibleWidth: 9000, minWidth: 175, minHeight: 25, flexibleHeight: 0);
// // subcontent expand button
// if (HasSubContent)
// {
// m_subExpandBtn = UIFactory.CreateButton(m_mainContent, "ExpandSubcontentButton", "▲", ToggleSubcontent, new Color(1,1,1,0));
// UIFactory.SetLayoutElement(m_subExpandBtn.gameObject, minHeight: 25, minWidth: 25, flexibleWidth: 0, flexibleHeight: 0);
// }
// // inspect button
// var inspectBtn = UIFactory.CreateButton(m_mainContent,
// "InspectButton",
// "Inspect",
// () =>
// {
// if (!Value.IsNullOrDestroyed(false))
// InspectorManager.Inspect(this.Value, this.Owner);
// },
// new Color(0.3f, 0.3f, 0.3f, 0.2f));
// m_inspectButton = inspectBtn.gameObject;
// UIFactory.SetLayoutElement(m_inspectButton, minWidth: 60, minHeight: 25, flexibleWidth: 0, flexibleHeight: 0);
// m_inspectButton.SetActive(false);
// // value label
// m_baseLabel = UIFactory.CreateLabel(m_mainContent, "ValueLabel", "", TextAnchor.MiddleLeft);
// UIFactory.SetLayoutElement(m_baseLabel.gameObject, flexibleWidth: 9000, minHeight: 25);
// m_subContentParent = subGroup;
// }
//#endregion
// }
//}

View File

@ -0,0 +1,61 @@
//using System;
//using System.Collections.Generic;
//using System.Linq;
//using System.Text;
//using UnityEngine;
//using UnityExplorer.UI.Widgets;
//namespace UnityExplorer.Inspectors.Reflection
//{
// public class CacheMemberList : IPoolDataSource
// {
// public ScrollPool ScrollPool { get; }
// public ReflectionInspector Inspector { get; }
// public CacheMemberList(ScrollPool scrollPool, ReflectionInspector inspector)
// {
// this.ScrollPool = scrollPool;
// this.Inspector = inspector;
// }
// public int ItemCount => Inspector.filteredMembers.Count;
// public int GetRealIndexOfTempIndex(int index)
// {
// if (index < 0 || index >= Inspector.filteredToRealIndices.Count)
// return -1;
// return Inspector.filteredToRealIndices[index];
// }
// public ICell CreateCell(RectTransform cellTransform) => new CellViewHolder(cellTransform.gameObject);
// public void SetCell(ICell icell, int index)
// {
// var cell = icell as CellViewHolder;
// if (index < 0 || index >= ItemCount)
// {
// var existing = cell.DisableContent();
// if (existing)
// existing.transform.SetParent(Inspector.InactiveHolder.transform, false);
// return;
// }
// index = GetRealIndexOfTempIndex(index);
// var cache = Inspector.allMembers[index];
// cache.Enable();
// var prev = cell.SetContent(cache.UIRoot);
// if (prev)
// prev.transform.SetParent(Inspector.InactiveHolder.transform, false);
// }
// public void DisableCell(ICell cell, int index)
// {
// var content = (cell as CellViewHolder).DisableContent();
// if (content)
// content.transform.SetParent(Inspector.InactiveHolder.transform, false);
// }
// }
//}

View File

@ -0,0 +1,254 @@
//using System;
//using System.Collections.Generic;
//using System.IO;
//using System.Linq;
//using System.Text;
//using UnityEngine;
//using UnityEngine.UI;
//using UnityExplorer.Core;
//using UnityExplorer.Core.Config;
//using UnityExplorer.Core.Runtime;
//namespace UnityExplorer.Inspectors.Reflection
//{
// public enum MemberScopes
// {
// All,
// Instance,
// Static
// }
// public class InstanceInspector : ReflectionInspector
// {
// public override string TabLabel => $" <color=cyan>[R]</color> {base.TabLabel}";
// internal MemberScopes m_scopeFilter;
// internal Button m_lastActiveScopeButton;
// public InstanceInspector(object target) : base(target) { }
// internal void OnScopeFilterClicked(MemberScopes type, Button button)
// {
// if (m_lastActiveScopeButton)
// RuntimeProvider.Instance.SetColorBlock(m_lastActiveScopeButton, new Color(0.2f, 0.2f, 0.2f));
// m_scopeFilter = type;
// m_lastActiveScopeButton = button;
// RuntimeProvider.Instance.SetColorBlock(m_lastActiveScopeButton, new Color(0.2f, 0.6f, 0.2f));
// FilterMembers(null, true);
// ScrollPool.RecreateHeightCache();
// ScrollPool.RefreshAndJumpToTop();
// //RefreshDisplay();
// //m_sliderScroller.m_slider.value = 1f;
// }
// public void ConstructInstanceScopeFilters(GameObject parent)
// {
// var memberFilterRowObj = UIFactory.CreateHorizontalGroup(parent, "InstanceFilterRow", false, false, true, true, 5, default,
// new Color(1, 1, 1, 0));
// UIFactory.SetLayoutElement(memberFilterRowObj, minHeight: 25, flexibleHeight: 0, flexibleWidth: 5000);
// var memLabel = UIFactory.CreateLabel(memberFilterRowObj, "MemberLabel", "Filter scope:", TextAnchor.MiddleLeft);
// UIFactory.SetLayoutElement(memLabel.gameObject, minWidth: 100, minHeight: 25, flexibleWidth: 0);
// AddFilterButton(memberFilterRowObj, MemberScopes.All, true);
// AddFilterButton(memberFilterRowObj, MemberScopes.Instance);
// AddFilterButton(memberFilterRowObj, MemberScopes.Static);
// }
// private void AddFilterButton(GameObject parent, MemberScopes type, bool setEnabled = false)
// {
// var btn = UIFactory.CreateButton(parent,
// "ScopeFilterButton_" + type,
// type.ToString(),
// null,
// new Color(0.2f, 0.2f, 0.2f));
// UIFactory.SetLayoutElement(btn.gameObject, minHeight: 25, minWidth: 70);
// btn.onClick.AddListener(() => { OnScopeFilterClicked(type, btn); });
// RuntimeProvider.Instance.SetColorBlock(btn, highlighted: new Color(0.3f, 0.7f, 0.3f));
// if (setEnabled)
// {
// RuntimeProvider.Instance.SetColorBlock(btn, new Color(0.2f, 0.6f, 0.2f));
// m_scopeFilter = type;
// m_lastActiveScopeButton = btn;
// }
// }
// public void ConstructUnityInstanceHelpers()
// {
// if (!typeof(UnityEngine.Object).IsAssignableFrom(m_targetType))
// return;
// var rowObj = UIFactory.CreateHorizontalGroup(Content, "InstanceHelperRow", true, true, true, true, 5, new Vector4(2, 2, 2, 2),
// new Color(0.1f, 0.1f, 0.1f));
// UIFactory.SetLayoutElement(rowObj, minHeight: 25, flexibleWidth: 5000);
// if (typeof(Component).IsAssignableFrom(m_targetType))
// ConstructCompHelper(rowObj);
// ConstructUnityObjHelper(rowObj);
// if (m_targetType == typeof(Texture2D))
// ConstructTextureHelper();
// }
// internal void ConstructCompHelper(GameObject rowObj)
// {
// //var gameObjectLabel = UIFactory.CreateLabel(rowObj, "GameObjectLabel", "GameObject:", TextAnchor.MiddleLeft);
// //UIFactory.SetLayoutElement(gameObjectLabel.gameObject, minWidth: 90, minHeight: 25, flexibleWidth: 0);
// var comp = Target.TryCast(typeof(Component)) as Component;
// var btn = UIFactory.CreateButton(rowObj,
// "GameObjectButton",
// "View GameObject",
// () => { InspectorManager.Inspect(comp.gameObject); },
// new Color(0.2f, 0.5f, 0.2f));
// UIFactory.SetLayoutElement(btn.gameObject, minHeight: 25, minWidth: 120, flexibleWidth: 0);
// }
// internal void ConstructUnityObjHelper(GameObject rowObj)
// {
// var label = UIFactory.CreateLabel(rowObj, "NameLabel", "Name:", TextAnchor.MiddleLeft);
// UIFactory.SetLayoutElement(label.gameObject, minWidth: 60, minHeight: 25, flexibleWidth: 0);
// var uObj = Target.TryCast(typeof(UnityEngine.Object)) as UnityEngine.Object;
// var inputObj = UIFactory.CreateInputField(rowObj, "NameInput", "...", out InputField inputField, 14, 3, 1);
// UIFactory.SetLayoutElement(inputObj, minHeight: 25, flexibleWidth: 2000);
// inputField.readOnly = true;
// inputField.text = uObj.name;
// }
// internal bool showingTextureHelper;
// internal bool constructedTextureViewer;
// internal GameObject m_textureViewerObj;
// internal void ConstructTextureHelper()
// {
// var rowObj = UIFactory.CreateHorizontalGroup(Content, "TextureHelper", false, false, true, true, 5, new Vector4(3, 3, 3, 3),
// new Color(0.1f, 0.1f, 0.1f));
// UIFactory.SetLayoutElement(rowObj, minHeight: 25, flexibleHeight: 0);
// var showBtn = UIFactory.CreateButton(rowObj, "ShowButton", "Show", null, new Color(0.2f, 0.3f, 0.2f));
// UIFactory.SetLayoutElement(showBtn.gameObject, minWidth: 50, flexibleWidth: 0, minHeight: 20);
// UIFactory.CreateLabel(rowObj, "TextureViewerLabel", "Texture Viewer", TextAnchor.MiddleLeft);
// m_textureViewerObj = UIFactory.CreateScrollView(Content, "TextureViewerContent", out GameObject scrollContent, out _,
// new Color(0.1f, 0.1f, 0.1f));
// UIFactory.SetLayoutGroup<VerticalLayoutGroup>(scrollContent, false, false, true, true);
// UIFactory.SetLayoutElement(m_textureViewerObj, minHeight: 100, flexibleHeight: 9999, flexibleWidth: 9999);
// m_textureViewerObj.SetActive(false);
// var showText = showBtn.GetComponentInChildren<Text>();
// showBtn.onClick.AddListener(() =>
// {
// showingTextureHelper = !showingTextureHelper;
// if (showingTextureHelper)
// {
// if (!constructedTextureViewer)
// ConstructTextureViewerArea(scrollContent);
// showText.text = "Hide";
// ToggleTextureViewer(true);
// }
// else
// {
// showText.text = "Show";
// ToggleTextureViewer(false);
// }
// });
// }
// internal void ConstructTextureViewerArea(GameObject parent)
// {
// constructedTextureViewer = true;
// var tex = Target.TryCast(typeof(Texture2D)) as Texture2D;
// if (!tex)
// {
// ExplorerCore.LogWarning("Could not cast the target instance to Texture2D! Maybe its null or destroyed?");
// return;
// }
// // Save helper
// var saveRowObj = UIFactory.CreateHorizontalGroup(parent, "SaveRow", true, true, 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", null, new Color(0.2f, 0.2f, 0.2f));
// UIFactory.SetLayoutElement(saveBtn.gameObject, minHeight: 25, minWidth: 100, flexibleWidth: 0);
// var inputObj = UIFactory.CreateInputField(saveRowObj, "SaveInput", "...", out InputField inputField);
// UIFactory.SetLayoutElement(inputObj, minHeight: 25, minWidth: 100, flexibleWidth: 9999);
// var name = tex.name;
// if (string.IsNullOrEmpty(name))
// name = "untitled";
// inputField.text = Path.Combine(ConfigManager.Default_Output_Path.Value, $"{name}.png");
// saveBtn.onClick.AddListener(() =>
// {
// if (tex && !string.IsNullOrEmpty(inputField.text))
// {
// var path = inputField.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);
// if (!TextureUtilProvider.IsReadable(tex))
// tex = TextureUtilProvider.ForceReadTexture(tex);
// byte[] data = TextureUtilProvider.Instance.EncodeToPNG(tex);
// File.WriteAllBytes(path, data);
// }
// });
// // Actual texture viewer
// var imageObj = UIFactory.CreateUIObject("TextureViewerImage", parent);
// var image = imageObj.AddComponent<Image>();
// var sprite = TextureUtilProvider.Instance.CreateSprite(tex);
// image.sprite = sprite;
// var fitter = imageObj.AddComponent<ContentSizeFitter>();
// fitter.verticalFit = ContentSizeFitter.FitMode.PreferredSize;
// var imageLayout = imageObj.AddComponent<LayoutElement>();
// imageLayout.preferredHeight = sprite.rect.height;
// imageLayout.preferredWidth = sprite.rect.width;
// }
// internal void ToggleTextureViewer(bool enabled)
// {
// m_textureViewerObj.SetActive(enabled);
// m_filterAreaObj.SetActive(!enabled);
// this.ScrollPool.UIRoot.SetActive(!enabled);
// m_updateRowObj.SetActive(!enabled);
// }
// }
//}

View File

@ -0,0 +1,173 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using UnityEngine.UI;
using UnityExplorer.UI.ObjectPool;
using UnityExplorer.UI.Utility;
using UnityExplorer.UI.Widgets;
namespace UnityExplorer.UI.Inspectors
{
public class GameObjectInspector : InspectorBase
{
public GameObject Target;
public override GameObject UIRoot => uiRoot;
private GameObject uiRoot;
private Text NameText;
public TransformTree TransformTree;
private ScrollPool<TransformCell> transformScroll;
public ButtonListSource<Component> ComponentList;
private ScrollPool<ButtonCell> componentScroll;
public override GameObject CreateContent(GameObject parent)
{
uiRoot = UIFactory.CreateVerticalGroup(Pool<GameObjectInspector>.Instance.InactiveHolder,
"GameObjectInspector", true, true, true, true, 5, new Vector4(4, 4, 4, 4), new Color(0.12f, 0.12f, 0.12f));
NameText = UIFactory.CreateLabel(uiRoot, "Title", "not set", TextAnchor.MiddleLeft, fontSize: 20);
UIFactory.SetLayoutElement(NameText.gameObject, minHeight: 30, flexibleHeight: 0);
var listHolder = UIFactory.CreateHorizontalGroup(uiRoot, "ListHolder", true, true, true, true, 5, new Vector4(2, 2, 2, 2));
UIFactory.SetLayoutElement(listHolder, flexibleWidth: 9999, flexibleHeight: 9999);
transformScroll = UIFactory.CreateScrollPool<TransformCell>(listHolder, "TransformTree", out GameObject transformObj,
out GameObject transformContent, new Color(0.11f, 0.11f, 0.11f));
UIFactory.SetLayoutElement(transformObj, flexibleHeight: 9999);
UIFactory.SetLayoutElement(transformContent, flexibleHeight: 9999);
componentScroll = UIFactory.CreateScrollPool<ButtonCell>(listHolder, "ComponentList", out GameObject compObj,
out GameObject compContent, new Color(0.11f, 0.11f, 0.11f));
UIFactory.SetLayoutElement(compObj, flexibleHeight: 9999);
UIFactory.SetLayoutElement(compContent, flexibleHeight: 9999);
TransformTree = new TransformTree(transformScroll) { GetRootEntriesMethod = GetTransformEntries };
TransformTree.Init();
ComponentList = new ButtonListSource<Component>(componentScroll, GetComponentEntries, SetComponentCell, ShouldDisplay, OnComponentClicked);
componentScroll.Initialize(ComponentList);
return uiRoot;
}
private readonly List<GameObject> _rootEntries = new List<GameObject>();
private IEnumerable<GameObject> GetTransformEntries()
{
_rootEntries.Clear();
for (int i = 0; i < Target.transform.childCount; i++)
_rootEntries.Add(Target.transform.GetChild(i).gameObject);
return _rootEntries;
}
private readonly List<Component> _componentEntries = new List<Component>();
private List<Component> GetComponentEntries()
{
return _componentEntries;
}
private static readonly Dictionary<Type, string> compToStringCache = new Dictionary<Type, string>();
private void SetComponentCell(ButtonCell cell, int index)
{
if (index < 0 || index >= _componentEntries.Count)
{
cell.Disable();
return;
}
cell.Enable();
var comp = _componentEntries[index];
var type = comp.GetActualType();
if (!compToStringCache.ContainsKey(type))
{
compToStringCache.Add(type,
$"<color={SignatureHighlighter.NAMESPACE}>{type.Namespace}</color>.{SignatureHighlighter.HighlightTypeName(type)}");
}
cell.Button.ButtonText.text = compToStringCache[type];
}
private bool ShouldDisplay(Component comp, string filter) => true;
private void OnComponentClicked(int index)
{
if (index < 0 || index >= _componentEntries.Count)
return;
var comp = _componentEntries[index];
if (comp)
InspectorManager.Inspect(comp);
}
public override void OnBorrowedFromPool(object target)
{
base.OnBorrowedFromPool(target);
Target = target as GameObject;
NameText.text = Target.name;
this.Tab.TabText.text = $"[G] {Target.name}";
TransformTree.Rebuild();
ComponentList.ScrollPool.Rebuild();
UpdateComponents();
}
public override void OnReturnToPool()
{
base.OnReturnToPool();
// release component and transform lists
this.TransformTree.ScrollPool.ReturnCells();
this.TransformTree.ScrollPool.SetUninitialized();
this.ComponentList.ScrollPool.ReturnCells();
this.ComponentList.ScrollPool.SetUninitialized();
}
private float timeOfLastUpdate;
public override void Update()
{
// todo update tab title? or put that in InspectorBase update?
if (!this.IsActive)
return;
if (Time.time - timeOfLastUpdate > 1f)
{
timeOfLastUpdate = Time.time;
// Refresh children and components
TransformTree.RefreshData(true, false);
UpdateComponents();
}
}
private void UpdateComponents()
{
_componentEntries.Clear();
foreach (var comp in Target.GetComponents<Component>())
_componentEntries.Add(comp);
ComponentList.RefreshData();
ComponentList.ScrollPool.RefreshCells(true);
}
protected override void OnCloseClicked()
{
InspectorManager.ReleaseInspector(this);
}
}
}

View File

@ -1,122 +1,64 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using UnityEngine.UI;
using UnityExplorer.UI.ObjectPool;
using UnityExplorer.UI.Panels;
namespace UnityExplorer.UI.Inspectors
{
public abstract class InspectorBase
public abstract class InspectorBase : IPooledObject
{
public object Target;
public bool IsActive { get; private set; }
public InspectorTab Tab { get; internal set; }
public bool IsActive { get; internal set; }
public abstract string TabLabel { get; }
public abstract GameObject UIRoot { get; }
internal bool m_pendingDestroy;
private static readonly Color _enabledTabColor = new Color(0.2f, 0.4f, 0.2f);
private static readonly Color _disabledTabColor = new Color(0.25f, 0.25f, 0.25f);
public InspectorBase(object target)
public float DefaultHeight => -1f;
public abstract GameObject CreateContent(GameObject content);
public abstract void Update();
public virtual void OnBorrowedFromPool(object target)
{
Target = target;
Tab = Pool<InspectorTab>.Borrow();
Tab.UIRoot.transform.SetParent(InspectorPanel.Instance.NavbarHolder.transform, false);
if (Target.IsNullOrDestroyed(false))
{
Destroy();
return;
}
AddInspectorTab(this);
Tab.TabButton.OnClick += OnTabButtonClicked;
Tab.CloseButton.OnClick += OnCloseClicked;
}
public virtual void SetActive()
public virtual void OnReturnToPool()
{
this.IsActive = true;
Content?.SetActive(true);
Pool<InspectorTab>.Return(Tab);
Tab.TabButton.OnClick -= OnTabButtonClicked;
Tab.CloseButton.OnClick -= OnCloseClicked;
}
public virtual void SetInactive()
public virtual void OnSetActive()
{
this.IsActive = false;
Content?.SetActive(false);
RuntimeProvider.Instance.SetColorBlock(Tab.TabButton.Button, _enabledTabColor, _enabledTabColor * 1.2f);
UIRoot.SetActive(true);
IsActive = true;
}
public virtual void Update()
public virtual void OnSetInactive()
{
if (Target.IsNullOrDestroyed(false))
{
Destroy();
return;
}
m_tabText.text = TabLabel;
RuntimeProvider.Instance.SetColorBlock(Tab.TabButton.Button, _disabledTabColor, _disabledTabColor * 1.2f);
UIRoot.SetActive(false);
IsActive = false;
}
public virtual void Destroy()
private void OnTabButtonClicked()
{
m_pendingDestroy = true;
GameObject tabGroup = m_tabButton?.transform.parent.gameObject;
if (tabGroup)
GameObject.Destroy(tabGroup);
int thisIndex = -1;
if (InspectorManager.ActiveInspectors.Contains(this))
{
thisIndex = InspectorManager.ActiveInspectors.IndexOf(this);
InspectorManager.ActiveInspectors.Remove(this);
}
if (ReferenceEquals(InspectorManager.m_activeInspector, this))
{
InspectorManager.UnsetInspectorTab();
if (InspectorManager.ActiveInspectors.Count > 0)
{
var prevTab = InspectorManager.ActiveInspectors[thisIndex > 0 ? thisIndex - 1 : 0];
InspectorManager.SetInspectorTab(prevTab);
}
}
InspectorManager.SetInspectorActive(this);
}
#region UI
public abstract GameObject Content { get; set; }
public Button m_tabButton;
public Text m_tabText;
public void AddInspectorTab(InspectorBase parent)
{
var tabContent = InspectorPanel.Instance.NavbarHolder;
var tabGroupObj = UIFactory.CreateHorizontalGroup(tabContent, "TabObject", true, true, true, true);
UIFactory.SetLayoutElement(tabGroupObj, minWidth: 185, flexibleWidth: 0);
tabGroupObj.AddComponent<Mask>();
m_tabButton = UIFactory.CreateButton(tabGroupObj,
"TabButton",
"",
() => { InspectorManager.SetInspectorTab(parent); });
UIFactory.SetLayoutElement(m_tabButton.gameObject, minWidth: 165, flexibleWidth: 0);
m_tabText = m_tabButton.GetComponentInChildren<Text>();
m_tabText.horizontalOverflow = HorizontalWrapMode.Overflow;
m_tabText.alignment = TextAnchor.MiddleLeft;
var closeBtn = UIFactory.CreateButton(tabGroupObj,
"CloseButton",
"X",
() => { InspectorManager.DestroyInspector(parent); },
new Color(0.2f, 0.2f, 0.2f, 1));
UIFactory.SetLayoutElement(closeBtn.gameObject, minWidth: 20, flexibleWidth: 0);
var closeBtnText = closeBtn.GetComponentInChildren<Text>();
closeBtnText.color = new Color(1, 0, 0, 1);
}
public virtual void OnPanelResized() { }
#endregion
protected abstract void OnCloseClicked();
}
}

View File

@ -1,151 +1,79 @@
using System;
using System.Collections.Generic;
using System.Linq;
using UnityExplorer.UI;
using System.Text;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
using UnityExplorer.Core.Runtime;
using UnityExplorer.UI.CacheObject;
using UnityExplorer.UI.Inspectors.Reflection;
using UnityExplorer.UI.ObjectPool;
using UnityExplorer.UI.Panels;
namespace UnityExplorer.UI.Inspectors
{
public static class InspectorManager
{
public static InspectorBase m_activeInspector;
public static readonly List<InspectorBase> ActiveInspectors = new List<InspectorBase>();
public static readonly List<InspectorBase> Inspectors = new List<InspectorBase>();
public static void Update()
public static InspectorBase ActiveInspector { get; private set; }
public static void Inspect(object obj)
{
try
{
for (int i = 0; i < ActiveInspectors.Count; i++)
ActiveInspectors[i].Update();
}
catch (Exception ex)
{
ExplorerCore.LogWarning(ex);
}
}
public static void DestroyInspector(InspectorBase inspector)
{
if (inspector is ReflectionInspector ri)
ri.Destroy();
obj = obj.TryCast();
if (obj is GameObject)
CreateInspector<GameObjectInspector>(obj);
else
inspector.Destroy();
}
public static void Inspect(object obj, CacheObjectBase parentMember = null)
{
var type = ReflectionProvider.Instance.GetActualType(obj);
// only need to set parent member for structs
if (!type.IsValueType)
parentMember = null;
obj = ReflectionProvider.Instance.Cast(obj, type);
if (obj.IsNullOrDestroyed(false))
return;
// check if currently inspecting this object
foreach (InspectorBase tab in ActiveInspectors)
{
if (obj.ReferenceEqual(tab.Target))
{
SetInspectorTab(tab);
return;
}
}
InspectorBase inspector;
if (obj is GameObject go)
{
ExplorerCore.Log("TODO");
return;
// inspector = new GameObjectInspector(go);
}
else
inspector = new InstanceInspector(obj);
if (inspector is ReflectionInspector ri)
ri.ParentMember = parentMember;
ActiveInspectors.Add(inspector);
SetInspectorTab(inspector);
CreateInspector<InstanceInspector>(obj);
}
public static void Inspect(Type type)
{
if (type == null)
{
ExplorerCore.LogWarning("The provided type was null!");
return;
}
foreach (var tab in ActiveInspectors.Where(x => x is StaticInspector))
{
if (ReferenceEquals(tab.Target as Type, type))
{
SetInspectorTab(tab);
return;
}
}
var inspector = new StaticInspector(type);
ActiveInspectors.Add(inspector);
SetInspectorTab(inspector);
CreateInspector<StaticInspector>(type);
}
public static void SetInspectorTab(InspectorBase inspector)
public static void SetInspectorActive(InspectorBase inspector)
{
UnsetActiveInspector();
ActiveInspector = inspector;
inspector.OnSetActive();
}
public static void UnsetActiveInspector()
{
if (ActiveInspector != null)
ActiveInspector.OnSetInactive();
}
private static void CreateInspector<T>(object target) where T : InspectorBase
{
var inspector = Pool<T>.Borrow();
Inspectors.Add(inspector);
inspector.UIRoot.transform.SetParent(InspectorPanel.Instance.ContentHolder.transform, false);
inspector.OnBorrowedFromPool(target);
SetInspectorActive(inspector);
UIManager.SetPanelActive(UIManager.Panels.Inspector, true);
if (m_activeInspector == inspector)
return;
UnsetInspectorTab();
m_activeInspector = inspector;
inspector.SetActive();
OnSetInspectorTab(inspector);
}
public static void UnsetInspectorTab()
internal static void ReleaseInspector<T>(T inspector) where T : InspectorBase
{
if (m_activeInspector == null)
return;
inspector.OnReturnToPool();
Pool<T>.Return(inspector);
m_activeInspector.SetInactive();
OnUnsetInspectorTab();
m_activeInspector = null;
Inspectors.Remove(inspector);
}
public static void OnSetInspectorTab(InspectorBase inspector)
internal static void Update()
{
Color activeColor = new Color(0, 0.25f, 0, 1);
RuntimeProvider.Instance.SetColorBlock(inspector.m_tabButton, activeColor, activeColor);
}
public static void OnUnsetInspectorTab()
{
RuntimeProvider.Instance.SetColorBlock(m_activeInspector.m_tabButton,
new Color(0.2f, 0.2f, 0.2f, 1), new Color(0.1f, 0.3f, 0.1f, 1));
foreach (var inspector in Inspectors)
{
inspector.Update();
}
}
internal static void OnPanelResized()
{
foreach (var instance in ActiveInspectors)
{
instance.OnPanelResized();
}
}
}
}

View File

@ -0,0 +1,46 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using UnityEngine.UI;
using UnityExplorer.UI.ObjectPool;
using UnityExplorer.UI.Widgets;
namespace UnityExplorer.UI.Inspectors
{
public class InspectorTab : IPooledObject
{
public GameObject UIRoot => uiRoot;
private GameObject uiRoot;
public float DefaultHeight => 25f;
public ButtonRef TabButton;
public Text TabText;
public ButtonRef CloseButton;
public GameObject CreateContent(GameObject parent)
{
uiRoot = UIFactory.CreateHorizontalGroup(parent, "TabObject", true, true, true, true, 0, new Vector4(0, 0, 3, 0));
UIFactory.SetLayoutElement(uiRoot, minWidth: 185, flexibleWidth: 0);
uiRoot.AddComponent<Mask>();
TabButton = UIFactory.CreateButton(uiRoot, "TabButton", "");
UIFactory.SetLayoutElement(TabButton.Button.gameObject, minWidth: 165, flexibleWidth: 0);
TabText = TabButton.Button.GetComponentInChildren<Text>();
TabText.horizontalOverflow = HorizontalWrapMode.Overflow;
TabText.alignment = TextAnchor.MiddleLeft;
CloseButton = UIFactory.CreateButton(uiRoot, "CloseButton", "X", new Color(0.2f, 0.2f, 0.2f, 1));
UIFactory.SetLayoutElement(CloseButton.Button.gameObject, minWidth: 20, flexibleWidth: 0);
var closeBtnText = CloseButton.Button.GetComponentInChildren<Text>();
closeBtnText.color = Color.red;
return uiRoot;
}
}
}

View File

@ -1,61 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using UnityExplorer.UI.Widgets;
namespace UnityExplorer.UI.Inspectors.Reflection
{
public class CacheMemberList : IPoolDataSource
{
public ScrollPool ScrollPool { get; }
public ReflectionInspector Inspector { get; }
public CacheMemberList(ScrollPool scrollPool, ReflectionInspector inspector)
{
this.ScrollPool = scrollPool;
this.Inspector = inspector;
}
public int ItemCount => Inspector.filteredMembers.Count;
public int GetRealIndexOfTempIndex(int index)
{
if (index < 0 || index >= Inspector.filteredToRealIndices.Count)
return -1;
return Inspector.filteredToRealIndices[index];
}
public ICell CreateCell(RectTransform cellTransform) => new CellViewHolder(cellTransform.gameObject);
public void SetCell(ICell icell, int index)
{
var cell = icell as CellViewHolder;
if (index < 0 || index >= ItemCount)
{
var existing = cell.DisableContent();
if (existing)
existing.transform.SetParent(Inspector.InactiveHolder.transform, false);
return;
}
index = GetRealIndexOfTempIndex(index);
var cache = Inspector.allMembers[index];
cache.Enable();
var prev = cell.SetContent(cache.UIRoot);
if (prev)
prev.transform.SetParent(Inspector.InactiveHolder.transform, false);
}
public void DisableCell(ICell cell, int index)
{
var content = (cell as CellViewHolder).DisableContent();
if (content)
content.transform.SetParent(Inspector.InactiveHolder.transform, false);
}
}
}

View File

@ -1,254 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using UnityEngine;
using UnityEngine.UI;
using UnityExplorer.Core;
using UnityExplorer.Core.Config;
using UnityExplorer.Core.Runtime;
namespace UnityExplorer.UI.Inspectors.Reflection
{
public enum MemberScopes
{
All,
Instance,
Static
}
public class InstanceInspector : ReflectionInspector
{
public override string TabLabel => $" <color=cyan>[R]</color> {base.TabLabel}";
internal MemberScopes m_scopeFilter;
internal Button m_lastActiveScopeButton;
public InstanceInspector(object target) : base(target) { }
internal void OnScopeFilterClicked(MemberScopes type, Button button)
{
if (m_lastActiveScopeButton)
RuntimeProvider.Instance.SetColorBlock(m_lastActiveScopeButton, new Color(0.2f, 0.2f, 0.2f));
m_scopeFilter = type;
m_lastActiveScopeButton = button;
RuntimeProvider.Instance.SetColorBlock(m_lastActiveScopeButton, new Color(0.2f, 0.6f, 0.2f));
FilterMembers(null, true);
ScrollPool.RecreateHeightCache();
ScrollPool.RefreshAndJumpToTop();
//RefreshDisplay();
//m_sliderScroller.m_slider.value = 1f;
}
public void ConstructInstanceScopeFilters(GameObject parent)
{
var memberFilterRowObj = UIFactory.CreateHorizontalGroup(parent, "InstanceFilterRow", false, false, true, true, 5, default,
new Color(1, 1, 1, 0));
UIFactory.SetLayoutElement(memberFilterRowObj, minHeight: 25, flexibleHeight: 0, flexibleWidth: 5000);
var memLabel = UIFactory.CreateLabel(memberFilterRowObj, "MemberLabel", "Filter scope:", TextAnchor.MiddleLeft);
UIFactory.SetLayoutElement(memLabel.gameObject, minWidth: 100, minHeight: 25, flexibleWidth: 0);
AddFilterButton(memberFilterRowObj, MemberScopes.All, true);
AddFilterButton(memberFilterRowObj, MemberScopes.Instance);
AddFilterButton(memberFilterRowObj, MemberScopes.Static);
}
private void AddFilterButton(GameObject parent, MemberScopes type, bool setEnabled = false)
{
var btn = UIFactory.CreateButton(parent,
"ScopeFilterButton_" + type,
type.ToString(),
null,
new Color(0.2f, 0.2f, 0.2f));
UIFactory.SetLayoutElement(btn.gameObject, minHeight: 25, minWidth: 70);
btn.onClick.AddListener(() => { OnScopeFilterClicked(type, btn); });
RuntimeProvider.Instance.SetColorBlock(btn, highlighted: new Color(0.3f, 0.7f, 0.3f));
if (setEnabled)
{
RuntimeProvider.Instance.SetColorBlock(btn, new Color(0.2f, 0.6f, 0.2f));
m_scopeFilter = type;
m_lastActiveScopeButton = btn;
}
}
public void ConstructUnityInstanceHelpers()
{
if (!typeof(UnityEngine.Object).IsAssignableFrom(m_targetType))
return;
var rowObj = UIFactory.CreateHorizontalGroup(Content, "InstanceHelperRow", true, true, true, true, 5, new Vector4(2, 2, 2, 2),
new Color(0.1f, 0.1f, 0.1f));
UIFactory.SetLayoutElement(rowObj, minHeight: 25, flexibleWidth: 5000);
if (typeof(Component).IsAssignableFrom(m_targetType))
ConstructCompHelper(rowObj);
ConstructUnityObjHelper(rowObj);
if (m_targetType == typeof(Texture2D))
ConstructTextureHelper();
}
internal void ConstructCompHelper(GameObject rowObj)
{
//var gameObjectLabel = UIFactory.CreateLabel(rowObj, "GameObjectLabel", "GameObject:", TextAnchor.MiddleLeft);
//UIFactory.SetLayoutElement(gameObjectLabel.gameObject, minWidth: 90, minHeight: 25, flexibleWidth: 0);
var comp = Target.TryCast(typeof(Component)) as Component;
var btn = UIFactory.CreateButton(rowObj,
"GameObjectButton",
"View GameObject",
() => { InspectorManager.Inspect(comp.gameObject); },
new Color(0.2f, 0.5f, 0.2f));
UIFactory.SetLayoutElement(btn.gameObject, minHeight: 25, minWidth: 120, flexibleWidth: 0);
}
internal void ConstructUnityObjHelper(GameObject rowObj)
{
var label = UIFactory.CreateLabel(rowObj, "NameLabel", "Name:", TextAnchor.MiddleLeft);
UIFactory.SetLayoutElement(label.gameObject, minWidth: 60, minHeight: 25, flexibleWidth: 0);
var uObj = Target.TryCast(typeof(UnityEngine.Object)) as UnityEngine.Object;
var inputObj = UIFactory.CreateInputField(rowObj, "NameInput", "...", out InputField inputField, 14, 3, 1);
UIFactory.SetLayoutElement(inputObj, minHeight: 25, flexibleWidth: 2000);
inputField.readOnly = true;
inputField.text = uObj.name;
}
internal bool showingTextureHelper;
internal bool constructedTextureViewer;
internal GameObject m_textureViewerObj;
internal void ConstructTextureHelper()
{
var rowObj = UIFactory.CreateHorizontalGroup(Content, "TextureHelper", false, false, true, true, 5, new Vector4(3, 3, 3, 3),
new Color(0.1f, 0.1f, 0.1f));
UIFactory.SetLayoutElement(rowObj, minHeight: 25, flexibleHeight: 0);
var showBtn = UIFactory.CreateButton(rowObj, "ShowButton", "Show", null, new Color(0.2f, 0.3f, 0.2f));
UIFactory.SetLayoutElement(showBtn.gameObject, minWidth: 50, flexibleWidth: 0, minHeight: 20);
UIFactory.CreateLabel(rowObj, "TextureViewerLabel", "Texture Viewer", TextAnchor.MiddleLeft);
m_textureViewerObj = UIFactory.CreateScrollView(Content, "TextureViewerContent", out GameObject scrollContent, out _,
new Color(0.1f, 0.1f, 0.1f));
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(scrollContent, false, false, true, true);
UIFactory.SetLayoutElement(m_textureViewerObj, minHeight: 100, flexibleHeight: 9999, flexibleWidth: 9999);
m_textureViewerObj.SetActive(false);
var showText = showBtn.GetComponentInChildren<Text>();
showBtn.onClick.AddListener(() =>
{
showingTextureHelper = !showingTextureHelper;
if (showingTextureHelper)
{
if (!constructedTextureViewer)
ConstructTextureViewerArea(scrollContent);
showText.text = "Hide";
ToggleTextureViewer(true);
}
else
{
showText.text = "Show";
ToggleTextureViewer(false);
}
});
}
internal void ConstructTextureViewerArea(GameObject parent)
{
constructedTextureViewer = true;
var tex = Target.TryCast(typeof(Texture2D)) as Texture2D;
if (!tex)
{
ExplorerCore.LogWarning("Could not cast the target instance to Texture2D! Maybe its null or destroyed?");
return;
}
// Save helper
var saveRowObj = UIFactory.CreateHorizontalGroup(parent, "SaveRow", true, true, 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", null, new Color(0.2f, 0.2f, 0.2f));
UIFactory.SetLayoutElement(saveBtn.gameObject, minHeight: 25, minWidth: 100, flexibleWidth: 0);
var inputObj = UIFactory.CreateInputField(saveRowObj, "SaveInput", "...", out InputField inputField);
UIFactory.SetLayoutElement(inputObj, minHeight: 25, minWidth: 100, flexibleWidth: 9999);
var name = tex.name;
if (string.IsNullOrEmpty(name))
name = "untitled";
inputField.text = Path.Combine(ConfigManager.Default_Output_Path.Value, $"{name}.png");
saveBtn.onClick.AddListener(() =>
{
if (tex && !string.IsNullOrEmpty(inputField.text))
{
var path = inputField.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);
if (!TextureUtilProvider.IsReadable(tex))
tex = TextureUtilProvider.ForceReadTexture(tex);
byte[] data = TextureUtilProvider.Instance.EncodeToPNG(tex);
File.WriteAllBytes(path, data);
}
});
// Actual texture viewer
var imageObj = UIFactory.CreateUIObject("TextureViewerImage", parent);
var image = imageObj.AddComponent<Image>();
var sprite = TextureUtilProvider.Instance.CreateSprite(tex);
image.sprite = sprite;
var fitter = imageObj.AddComponent<ContentSizeFitter>();
fitter.verticalFit = ContentSizeFitter.FitMode.PreferredSize;
var imageLayout = imageObj.AddComponent<LayoutElement>();
imageLayout.preferredHeight = sprite.rect.height;
imageLayout.preferredWidth = sprite.rect.width;
}
internal void ToggleTextureViewer(bool enabled)
{
m_textureViewerObj.SetActive(enabled);
m_filterAreaObj.SetActive(!enabled);
this.ScrollPool.UIRoot.SetActive(!enabled);
m_updateRowObj.SetActive(!enabled);
}
}
}

View File

@ -1,487 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using UnityEngine;
using UnityEngine.UI;
using UnityExplorer.Core;
using UnityExplorer.Core.Config;
using UnityExplorer.Core.Runtime;
using UnityExplorer.UI.CacheObject;
using UnityExplorer.UI.Panels;
using UnityExplorer.UI.Utility;
using UnityExplorer.UI.Widgets;
namespace UnityExplorer.UI.Inspectors.Reflection
{
public class ReflectionInspector : InspectorBase
{
#region STATIC
public static ReflectionInspector ActiveInstance { get; private set; }
//static ReflectionInspector()
//{
// PanelDragger.OnFinishResize += (RectTransform _) => OnContainerResized();
// SceneExplorer.OnToggleShow += OnContainerResized;
//}
//private static void OnContainerResized(bool _ = false)
//{
// if (ActiveInstance == null)
// return;
// ActiveInstance.m_widthUpdateWanted = true;
//}
// Blacklists
private static readonly HashSet<string> bl_typeAndMember = new HashSet<string>
{
#if CPP
// these cause a crash in IL2CPP
"Type.DeclaringMethod",
"Rigidbody2D.Cast",
"Collider2D.Cast",
"Collider2D.Raycast",
"Texture2D.SetPixelDataImpl",
"Camera.CalculateProjectionMatrixFromPhysicalProperties",
#endif
};
private static readonly HashSet<string> bl_methodNameStartsWith = new HashSet<string>
{
// these are redundant, just adds noise, properties are supported directly
"get_",
"set_",
};
#endregion
#region INSTANCE
public override string TabLabel => m_targetTypeShortName;
public CacheObjectBase ParentMember { get; internal set; }
public ScrollPool ScrollPool { get; private set; }
public CacheMemberList CacheMemberList { get; private set; }
public GameObject InactiveHolder => m_inactiveHolder;
private GameObject m_inactiveHolder;
internal readonly Type m_targetType;
internal readonly string m_targetTypeShortName;
// all cached members of the target
internal CacheMember[] allMembers;
// filtered members based on current filters
internal readonly List<CacheMember> filteredMembers = new List<CacheMember>();
// actual shortlist of displayed members
internal readonly List<CacheMember> displayedMembers = new List<CacheMember>();
// index: Index in filter list, Value: Actual real index in allMembers list.
internal readonly List<int> filteredToRealIndices = new List<int>();
internal bool autoUpdate;
public override void OnPanelResized()
{
foreach (var member in displayedMembers)
{
member.memberLabelElement.minWidth = 0.4f * InspectorPanel.CurrentPanelWidth;
}
}
public ReflectionInspector(object target) : base(target)
{
if (this is StaticInspector)
m_targetType = target as Type;
else
m_targetType = ReflectionUtility.GetActualType(target);
m_targetTypeShortName = SignatureHighlighter.ParseFullSyntax(m_targetType, false);
ConstructUI();
CacheMembers(m_targetType);
FilterMembers();
}
public override void SetActive()
{
base.SetActive();
ActiveInstance = this;
}
public override void SetInactive()
{
base.SetInactive();
ActiveInstance = null;
}
public override void Destroy()
{
base.Destroy();
if (this.Content)
{
GameObject.Destroy(this.InactiveHolder);
GameObject.Destroy(this.Content);
}
}
internal bool IsBlacklisted(string sig) => bl_typeAndMember.Any(it => sig.Contains(it));
internal bool IsBlacklisted(MethodInfo method) => bl_methodNameStartsWith.Any(it => method.Name.StartsWith(it));
internal string GetSig(MemberInfo member) => $"{member.DeclaringType.Name}.{member.Name}";
internal string AppendArgsToSig(ParameterInfo[] args)
{
string ret = " (";
foreach (var param in args)
ret += $"{param.ParameterType.Name} {param.Name}, ";
ret += ")";
return ret;
}
public void CacheMembers(Type type)
{
var list = new List<CacheMember>();
var cachedSigs = new HashSet<string>();
var types = ReflectionUtility.GetAllBaseTypes(type);
var flags = BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static;
if (this is InstanceInspector)
flags |= BindingFlags.Instance;
foreach (var declaringType in types)
{
var target = Target;
target = target.TryCast(declaringType);
IEnumerable<MemberInfo> infos = declaringType.GetMethods(flags);
infos = infos.Concat(declaringType.GetProperties(flags));
infos = infos.Concat(declaringType.GetFields(flags));
foreach (var member in infos)
{
try
{
var sig = GetSig(member);
//ExplorerCore.Log($"Trying to cache member {sig}...");
//ExplorerCore.Log(member.DeclaringType.FullName + "." + member.Name);
var mi = member as MethodInfo;
var pi = member as PropertyInfo;
var fi = member as FieldInfo;
if (IsBlacklisted(sig) || (mi != null && IsBlacklisted(mi)))
continue;
var args = mi?.GetParameters() ?? pi?.GetIndexParameters();
if (args != null)
{
if (!CacheMember.CanProcessArgs(args))
continue;
sig += AppendArgsToSig(args);
}
if (cachedSigs.Contains(sig))
continue;
cachedSigs.Add(sig);
if (mi != null)
list.Add(new CacheMethod(mi, target, InactiveHolder));
else if (pi != null)
list.Add(new CacheProperty(pi, target, InactiveHolder));
else
list.Add(new CacheField(fi, target, InactiveHolder));
var cached = list[list.Count - 1];
cached.ParentInspector = this;
}
catch (Exception e)
{
ExplorerCore.LogWarning($"Exception caching member {member.DeclaringType.FullName}.{member.Name}!");
ExplorerCore.Log(e.ToString());
}
}
}
var typeList = types.ToList();
var sorted = new List<CacheMember>();
sorted.AddRange(list.Where(it => it is CacheProperty)
.OrderBy(it => typeList.IndexOf(it.DeclaringType))
.ThenBy(it => it.NameForFiltering));
sorted.AddRange(list.Where(it => it is CacheField)
.OrderBy(it => typeList.IndexOf(it.DeclaringType))
.ThenBy(it => it.NameForFiltering));
sorted.AddRange(list.Where(it => it is CacheMethod)
.OrderBy(it => typeList.IndexOf(it.DeclaringType))
.ThenBy(it => it.NameForFiltering));
allMembers = sorted.ToArray();
}
public override void Update()
{
base.Update();
if (autoUpdate)
{
foreach (var member in displayedMembers)
{
if (member == null) break;
member.UpdateValue();
}
}
//if (m_widthUpdateWanted)
//{
// if (!m_widthUpdateWaiting)
// m_widthUpdateWaiting = true;
// else
// {
// UpdateWidths();
// m_widthUpdateWaiting = false;
// m_widthUpdateWanted = false;
// }
//}
}
internal void OnMemberFilterClicked(MemberTypes type, Button button)
{
if (m_lastActiveMemButton)
RuntimeProvider.Instance.SetColorBlock(m_lastActiveMemButton, new Color(0.2f, 0.2f, 0.2f));
m_memberFilter = type;
m_lastActiveMemButton = button;
RuntimeProvider.Instance.SetColorBlock(m_lastActiveMemButton, new Color(0.2f, 0.6f, 0.2f));
FilterMembers(null, true);
ScrollPool.RecreateHeightCache();
ScrollPool.Rebuild();
}
public void FilterMembers(string nameFilter = null, bool force = false)
{
int lastCount = filteredMembers.Count;
filteredMembers.Clear();
nameFilter = nameFilter?.ToLower() ?? m_nameFilterText.text.ToLower();
filteredToRealIndices.Clear();
for (int i = 0; i < allMembers.Length; i++)
{
var mem = allMembers[i];
// membertype filter
if (m_memberFilter != MemberTypes.All && mem.MemInfo.MemberType != m_memberFilter)
continue;
if (this is InstanceInspector ii && ii.m_scopeFilter != MemberScopes.All)
{
if (mem.IsStatic && ii.m_scopeFilter != MemberScopes.Static)
continue;
else if (!mem.IsStatic && ii.m_scopeFilter != MemberScopes.Instance)
continue;
}
// name filter
if (!string.IsNullOrEmpty(nameFilter) && !mem.NameForFiltering.Contains(nameFilter))
continue;
filteredMembers.Add(mem);
filteredToRealIndices.Add(i);
}
//if (force || lastCount != filteredMembers.Count)
//{
// ScrollPool.EnableTempCache();
// ScrollPool.Rebuild();
//}
}
#endregion
#region UI
private GameObject m_content;
public override GameObject Content
{
get => m_content;
set => m_content = value;
}
internal Text m_nameFilterText;
internal MemberTypes m_memberFilter;
internal Button m_lastActiveMemButton;
internal GameObject m_filterAreaObj;
internal GameObject m_updateRowObj;
internal void ConstructUI()
{
var parent = InspectorPanel.Instance.ContentHolder;
this.Content = UIFactory.CreateVerticalGroup(parent, "ReflectionInspector", true, false, true, true, 5, new Vector4(4, 4, 4, 4),
new Color(0.15f, 0.15f, 0.15f));
this.m_inactiveHolder = new GameObject("InactiveContentHolder");
m_inactiveHolder.transform.SetParent(Content.transform, false);
m_inactiveHolder.SetActive(false);
ConstructTopArea();
ConstructMemberList();
}
internal void ConstructTopArea()
{
var nameRowObj = UIFactory.CreateHorizontalGroup(Content, "NameRowObj", true, true, true, true, 2, default, new Color(1, 1, 1, 0));
UIFactory.SetLayoutElement(nameRowObj, minHeight: 25, flexibleHeight: 0, minWidth: 200, flexibleWidth: 5000);
var typeLabelText = UIFactory.CreateLabel(nameRowObj, "TypeLabel", "Type:", TextAnchor.MiddleLeft);
typeLabelText.horizontalOverflow = HorizontalWrapMode.Overflow;
UIFactory.SetLayoutElement(typeLabelText.gameObject, minWidth: 40, flexibleWidth: 0, minHeight: 25);
var typeDisplay = UIFactory.CreateLabel(nameRowObj, "TypeDisplayText", SignatureHighlighter.ParseFullSyntax(m_targetType, true),
TextAnchor.MiddleLeft);
UIFactory.SetLayoutElement(typeDisplay.gameObject, minHeight: 25, flexibleWidth: 5000);
// instance helper tools
if (this is InstanceInspector instanceInspector)
{
instanceInspector.ConstructUnityInstanceHelpers();
}
ConstructFilterArea();
ConstructUpdateRow();
}
internal void ConstructFilterArea()
{
// Filters
m_filterAreaObj = UIFactory.CreateVerticalGroup(Content, "FilterGroup", true, true, true, true, 4, new Vector4(4, 4, 4, 4),
new Color(0.1f, 0.1f, 0.1f));
UIFactory.SetLayoutElement(m_filterAreaObj, minHeight: 60);
// name filter
var nameFilterRowObj = UIFactory.CreateHorizontalGroup(m_filterAreaObj, "NameFilterRow", false, false, true, true, 5, default,
new Color(1, 1, 1, 0));
UIFactory.SetLayoutElement(nameFilterRowObj, minHeight: 25, flexibleHeight: 0, flexibleWidth: 5000);
var nameLabel = UIFactory.CreateLabel(nameFilterRowObj, "NameLabel", "Filter names:", TextAnchor.MiddleLeft, Color.grey);
UIFactory.SetLayoutElement(nameLabel.gameObject, minWidth: 100, minHeight: 25, flexibleWidth: 0);
var nameInputObj = UIFactory.CreateInputField(nameFilterRowObj, "NameInput", "...", out InputField nameInput, 14, (int)TextAnchor.MiddleLeft,
(int)HorizontalWrapMode.Overflow);
UIFactory.SetLayoutElement(nameInputObj, flexibleWidth: 5000, minWidth: 100, minHeight: 25);
nameInput.onValueChanged.AddListener((string val) =>
{
FilterMembers(val, true);
ScrollPool.RecreateHeightCache();
ScrollPool.Rebuild();
});
m_nameFilterText = nameInput.textComponent;
// membertype filter
var memberFilterRowObj = UIFactory.CreateHorizontalGroup(m_filterAreaObj, "MemberFilter", false, false, true, true, 5, default,
new Color(1, 1, 1, 0));
UIFactory.SetLayoutElement(memberFilterRowObj, minHeight: 25, flexibleHeight: 0, flexibleWidth: 5000);
var memLabel = UIFactory.CreateLabel(memberFilterRowObj, "MemberFilterLabel", "Filter members:", TextAnchor.MiddleLeft, Color.grey);
UIFactory.SetLayoutElement(memLabel.gameObject, minWidth: 100, minHeight: 25, flexibleWidth: 0);
AddFilterButton(memberFilterRowObj, MemberTypes.All, true);
AddFilterButton(memberFilterRowObj, MemberTypes.Method);
AddFilterButton(memberFilterRowObj, MemberTypes.Property);
AddFilterButton(memberFilterRowObj, MemberTypes.Field);
// Instance filters
if (this is InstanceInspector instanceInspector)
{
instanceInspector.ConstructInstanceScopeFilters(m_filterAreaObj);
}
}
private void AddFilterButton(GameObject parent, MemberTypes type, bool setEnabled = false)
{
var btn = UIFactory.CreateButton(parent,
"FilterButton_" + type,
type.ToString(),
null,
new Color(0.2f, 0.2f, 0.2f));
UIFactory.SetLayoutElement(btn.gameObject, minHeight: 25, minWidth: 70);
btn.onClick.AddListener(() => { OnMemberFilterClicked(type, btn); });
RuntimeProvider.Instance.SetColorBlock(btn, highlighted: new Color(0.3f, 0.7f, 0.3f));
if (setEnabled)
{
RuntimeProvider.Instance.SetColorBlock(btn, new Color(0.2f, 0.6f, 0.2f));
m_memberFilter = type;
m_lastActiveMemButton = btn;
}
}
internal void ConstructUpdateRow()
{
m_updateRowObj = UIFactory.CreateHorizontalGroup(Content, "UpdateRow", false, true, true, true, 10, default, new Color(1, 1, 1, 0));
UIFactory.SetLayoutElement(m_updateRowObj, minHeight: 25);
// update button
var updateBtn = UIFactory.CreateButton(m_updateRowObj, "UpdateButton", "Update Values", null, new Color(0.2f, 0.2f, 0.2f));
UIFactory.SetLayoutElement(updateBtn.gameObject, minWidth: 110, flexibleWidth: 0);
updateBtn.onClick.AddListener(() =>
{
bool orig = autoUpdate;
autoUpdate = true;
Update();
if (!orig)
autoUpdate = orig;
});
// auto update
var autoUpdateObj = UIFactory.CreateToggle(m_updateRowObj, "UpdateToggle", out Toggle autoUpdateToggle, out Text autoUpdateText);
var autoUpdateLayout = autoUpdateObj.AddComponent<LayoutElement>();
autoUpdateLayout.minWidth = 150;
autoUpdateLayout.minHeight = 25;
autoUpdateText.text = "Auto-update?";
autoUpdateToggle.isOn = false;
autoUpdateToggle.onValueChanged.AddListener((bool val) => { autoUpdate = val; });
}
internal void ConstructMemberList()
{
ScrollPool = UIFactory.CreateScrollPool(Content, "MemberList", out GameObject scrollRoot, out GameObject scrollContent,
new Color(0.05f, 0.05f, 0.05f));
UIFactory.SetLayoutElement(scrollRoot, flexibleHeight: 9999);
UIFactory.SetLayoutElement(scrollContent, flexibleHeight: 9999);
CacheMemberList = new CacheMemberList(ScrollPool, this);
ScrollPool.Initialize(CacheMemberList, CellViewHolder.CreatePrototypeCell(scrollRoot));
// ScrollPool.Viewport.GetComponent<Mask>().enabled = false;
}
}
#endregion
}

View File

@ -1,14 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace UnityExplorer.UI.Inspectors.Reflection
{
public class StaticInspector : ReflectionInspector
{
public override string TabLabel => $" <color=cyan>[S]</color> {base.TabLabel}";
public StaticInspector(Type type) : base(type) { }
}
}

View File

@ -0,0 +1,32 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
namespace UnityExplorer.UI.Inspectors
{
public class InstanceInspector : ReflectionInspector { }
public class StaticInspector : ReflectionInspector { }
public class ReflectionInspector : InspectorBase
{
public override GameObject UIRoot => throw new NotImplementedException();
public override GameObject CreateContent(GameObject content)
{
throw new NotImplementedException();
}
public override void Update()
{
throw new NotImplementedException();
}
protected override void OnCloseClicked()
{
throw new NotImplementedException();
}
}
}

View File

@ -127,13 +127,15 @@ namespace UnityExplorer.UI.Models
// close button
var closeBtn = UIFactory.CreateButton(titleGroup, "CloseButton", "X", () =>
var closeBtn = UIFactory.CreateButton(titleGroup, "CloseButton", "X");
UIFactory.SetLayoutElement(closeBtn.Button.gameObject, minHeight: 25, minWidth: 25, flexibleWidth: 0);
RuntimeProvider.Instance.SetColorBlock(closeBtn.Button, new Color(0.63f, 0.32f, 0.31f),
new Color(0.81f, 0.25f, 0.2f), new Color(0.6f, 0.18f, 0.16f));
closeBtn.OnClick += () =>
{
UIManager.SetPanelActive(this.PanelType, false);
});
UIFactory.SetLayoutElement(closeBtn.gameObject, minHeight: 25, minWidth: 25, flexibleWidth: 0);
RuntimeProvider.Instance.SetColorBlock(closeBtn, new Color(0.63f, 0.32f, 0.31f),
new Color(0.81f, 0.25f, 0.2f), new Color(0.6f, 0.18f, 0.16f));
};
if (!CanDrag)
titleGroup.SetActive(false);

View File

@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
namespace UnityExplorer.UI.ObjectPool
{
public interface IPooledObject
{
GameObject UIRoot { get; }
GameObject CreateContent(GameObject parent);
float DefaultHeight { get; }
//GameObject CreatePrototype();
}
}

106
src/UI/ObjectPool/Pool.cs Normal file
View File

@ -0,0 +1,106 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
namespace UnityExplorer.UI.ObjectPool
{
public interface IObjectPool { }
public class Pool<T> : IObjectPool where T : IPooledObject
{
// internal pool management
private static readonly Dictionary<Type, IObjectPool> pools = new Dictionary<Type, IObjectPool>();
public static Pool<T> GetPool()
{
var type = typeof(T);
if (!pools.ContainsKey(type))
CreatePool();
return (Pool<T>)pools[type];
}
private static Pool<T> CreatePool()
{
var pool = new Pool<T>();
pools.Add(typeof(T), pool);
return pool;
}
public static T Borrow()
{
return GetPool().BorrowObject();
}
public static void Return(T obj)
{
GetPool().ReturnObject(obj);
}
// Instance
public static Pool<T> Instance
{
get => s_instance ?? CreatePool();
}
private static Pool<T> s_instance;
public Pool()
{
s_instance = this;
ExplorerCore.LogWarning("Creating Pool<" + typeof(T).Name + ">");
InactiveHolder = new GameObject($"InactiveHolder_{typeof(T).Name}");
InactiveHolder.transform.parent = UIManager.PoolHolder.transform;
InactiveHolder.hideFlags |= HideFlags.HideAndDontSave;
InactiveHolder.SetActive(false);
// Create an instance (not content) to grab the default height.
// Tiny bit wasteful, but not a big deal, only happens once per type
// and its just the C# wrapper class being created.
var obj = (T)Activator.CreateInstance(typeof(T));
DefaultHeight = obj.DefaultHeight;
}
public GameObject InactiveHolder { get; }
public float DefaultHeight { get; }
private readonly HashSet<T> available = new HashSet<T>();
private readonly HashSet<T> borrowed = new HashSet<T>();
public int AvailableObjects => available.Count;
private void IncrementPool()
{
var obj = (T)Activator.CreateInstance(typeof(T));
obj.CreateContent(InactiveHolder);
available.Add(obj);
}
public T BorrowObject()
{
if (available.Count <= 0)
IncrementPool();
var obj = available.First();
available.Remove(obj);
borrowed.Add(obj);
return obj;
}
public void ReturnObject(T obj)
{
if (!borrowed.Contains(obj))
ExplorerCore.LogWarning($"Returning an item to object pool ({typeof(T).Name}) but the item didn't exist in the borrowed list?");
else
borrowed.Remove(obj);
available.Add(obj);
obj.UIRoot.transform.SetParent(InactiveHolder.transform, false);
}
}
}

View File

@ -26,7 +26,7 @@ namespace UnityExplorer.UI.Panels
public int SelectedTab = -1;
private readonly List<UIModel> tabPages = new List<UIModel>();
private readonly List<Button> tabButtons = new List<Button>();
private readonly List<ButtonRef> tabButtons = new List<ButtonRef>();
public void SetTab(int tabIndex)
{
@ -37,7 +37,7 @@ namespace UnityExplorer.UI.Panels
content.SetActive(true);
var button = tabButtons[tabIndex];
RuntimeProvider.Instance.SetColorBlock(button, UIManager.navButtonEnabledColor, UIManager.navButtonEnabledColor * 1.2f);
RuntimeProvider.Instance.SetColorBlock(button.Button, UIManager.navButtonEnabledColor, UIManager.navButtonEnabledColor * 1.2f);
SelectedTab = tabIndex;
SaveToConfigManager();
@ -46,7 +46,7 @@ namespace UnityExplorer.UI.Panels
private void DisableTab(int tabIndex)
{
tabPages[tabIndex].SetActive(false);
RuntimeProvider.Instance.SetColorBlock(tabButtons[tabIndex], UIManager.navButtonDisabledColor, UIManager.navButtonDisabledColor * 1.2f);
RuntimeProvider.Instance.SetColorBlock(tabButtons[tabIndex].Button, UIManager.navButtonDisabledColor, UIManager.navButtonDisabledColor * 1.2f);
}
public override void Update()
@ -130,7 +130,8 @@ namespace UnityExplorer.UI.Panels
var button = UIFactory.CreateButton(tabGroup, $"Button_{label}", label);
int idx = tabButtons.Count;
button.onClick.AddListener(() => { SetTab(idx); });
//button.onClick.AddListener(() => { SetTab(idx); });
button.OnClick += () => { SetTab(idx); };
tabButtons.Add(button);

View File

@ -27,6 +27,7 @@ namespace UnityExplorer.UI
if (!parent)
{
ExplorerCore.LogWarning("Cannot create UI object as the parent is null or destroyed! (" + name + ")");
ExplorerCore.Log(Environment.StackTrace);
return null;
}
@ -56,10 +57,6 @@ namespace UnityExplorer.UI
{
RuntimeProvider.Instance.SetColorBlock(selectable, new Color(0.2f, 0.2f, 0.2f),
new Color(0.3f, 0.3f, 0.3f), new Color(0.15f, 0.15f, 0.15f));
// Deselect all Buttons after they are clicked.
if (selectable is Button button)
button.onClick.AddListener(() => { button.OnDeselect(null); });
}
/// <summary>
@ -258,19 +255,19 @@ namespace UnityExplorer.UI
return textComp;
}
public static Button CreateButton(GameObject parent, string name, string text, Action onClick = null, Color? normalColor = null)
public static ButtonRef CreateButton(GameObject parent, string name, string text, Color? normalColor = null)
{
var colors = new ColorBlock();
normalColor = normalColor ?? new Color(0.25f, 0.25f, 0.25f);
var btn = CreateButton(parent, name, text, onClick, colors);
var btn = CreateButton(parent, name, text, colors);
RuntimeProvider.Instance.SetColorBlock(btn, normalColor, new Color(0.4f, 0.4f, 0.4f), new Color(0.15f, 0.15f, 0.15f));
RuntimeProvider.Instance.SetColorBlock(btn.Button, normalColor, normalColor * 1.2f, normalColor * 0.7f);
return btn;
}
public static Button CreateButton(GameObject parent, string name, string text, Action onClick, ColorBlock colors)
public static ButtonRef CreateButton(GameObject parent, string name, string text, ColorBlock colors)
{
GameObject buttonObj = CreateUIObject(name, parent, _smallElementSize);
@ -296,10 +293,17 @@ namespace UnityExplorer.UI
rect.anchorMax = Vector2.one;
rect.sizeDelta = Vector2.zero;
if (onClick != null)
button.onClick.AddListener(onClick);
SetButtonDeselectListener(button);
return button;
return new ButtonRef(button);
}
public static void SetButtonDeselectListener(Button button)
{
button.onClick.AddListener(() =>
{
button.OnDeselect(null);
});
}
/// <summary>
@ -720,8 +724,8 @@ namespace UnityExplorer.UI
return dropdownObj;
}
public static ScrollPool CreateScrollPool(GameObject parent, string name, out GameObject uiRoot,
out GameObject content, Color? bgColor = null)
public static ScrollPool<T> CreateScrollPool<T>(GameObject parent, string name, out GameObject uiRoot,
out GameObject content, Color? bgColor = null) where T : ICell
{
var mainObj = CreateUIObject(name, parent, new Vector2(1, 1));
mainObj.AddComponent<Image>().color = bgColor ?? new Color(0.12f, 0.12f, 0.12f);
@ -787,7 +791,7 @@ namespace UnityExplorer.UI
// finalize and create ScrollPool
uiRoot = mainObj;
var scrollPool = new ScrollPool(scrollRect);
var scrollPool = new ScrollPool<T>(scrollRect);
//viewportObj.GetComponent<Mask>().enabled = false;

View File

@ -32,6 +32,8 @@ namespace UnityExplorer.UI
public static Canvas Canvas { get; private set; }
public static EventSystem EventSys { get; private set; }
internal static GameObject PoolHolder { get; private set; }
// panels
internal static GameObject PanelHolder { get; private set; }
@ -138,6 +140,11 @@ namespace UnityExplorer.UI
UIFactory.Init();
CreateRootCanvas();
PoolHolder = new GameObject("PoolHolder");
PoolHolder.transform.parent = CanvasRoot.transform;
PoolHolder.SetActive(false);
CreateTopNavBar();
AutoCompleter = new AutoCompleter();
@ -213,22 +220,24 @@ namespace UnityExplorer.UI
// close button
var closeBtn = UIFactory.CreateButton(panel, "CloseButton", "X", () => { ShowMenu = false; });
UIFactory.SetLayoutElement(closeBtn.gameObject, minHeight: 25, minWidth: 25, flexibleWidth: 0);
RuntimeProvider.Instance.SetColorBlock(closeBtn, new Color(0.63f, 0.32f, 0.31f),
var closeBtn = UIFactory.CreateButton(panel, "CloseButton", "X");
UIFactory.SetLayoutElement(closeBtn.Button.gameObject, minHeight: 25, minWidth: 25, flexibleWidth: 0);
RuntimeProvider.Instance.SetColorBlock(closeBtn.Button, new Color(0.63f, 0.32f, 0.31f),
new Color(0.81f, 0.25f, 0.2f), new Color(0.6f, 0.18f, 0.16f));
closeBtn.OnClick += () => { ShowMenu = false; };
}
private static void CreateNavButton(GameObject navbar, Panels panel, string label)
{
var button = UIFactory.CreateButton(navbar, $"Button_{panel}", label);
UIFactory.SetLayoutElement(button.gameObject, minWidth: 118, flexibleWidth: 0);
RuntimeProvider.Instance.SetColorBlock(button, navButtonDisabledColor, navButtonDisabledColor * 1.2f);
button.onClick.AddListener(() =>
UIFactory.SetLayoutElement(button.Button.gameObject, minWidth: 118, flexibleWidth: 0);
RuntimeProvider.Instance.SetColorBlock(button.Button, navButtonDisabledColor, navButtonDisabledColor * 1.2f);
button.OnClick += () =>
{
TogglePanel(panel);
});
navButtonDict.Add(panel, button);
};
navButtonDict.Add(panel, button.Button);
}
// Could be cool, need to investigate properly.

View File

@ -61,7 +61,7 @@ namespace UnityExplorer.UI.Utility
else
{
if (includeNamespace && !string.IsNullOrEmpty(type.Namespace))
syntaxBuilder.Append($"<color=#{NAMESPACE}>{type.Namespace}</color>.");
syntaxBuilder.Append($"<color={NAMESPACE}>{type.Namespace}</color>.");
var declaring = type.DeclaringType;
while (declaring != null)

View File

@ -8,6 +8,7 @@ using UnityExplorer.Core.Input;
using UnityExplorer.Core.Runtime;
using UnityExplorer.UI;
using UnityExplorer.UI.Models;
using UnityExplorer.UI.ObjectPool;
namespace UnityExplorer.UI.Widgets.AutoComplete
{
@ -58,7 +59,7 @@ namespace UnityExplorer.UI.Widgets.AutoComplete
public ISuggestionProvider CurrentHandler { get; private set; }
public ButtonListSource<Suggestion> dataHandler;
public ScrollPool scrollPool;
public ScrollPool<ButtonCell> scrollPool;
private List<Suggestion> suggestions = new List<Suggestion>();
@ -123,7 +124,7 @@ namespace UnityExplorer.UI.Widgets.AutoComplete
CurrentHandler.OnSuggestionClicked(suggestion);
}
private void SetCell(ButtonCell<Suggestion> cell, int index)
private void SetCell(ButtonCell cell, int index)
{
if (index < 0 || index >= suggestions.Count)
{
@ -132,7 +133,7 @@ namespace UnityExplorer.UI.Widgets.AutoComplete
}
var suggestion = suggestions[index];
cell.buttonText.text = suggestion.DisplayText;
cell.Button.ButtonText.text = suggestion.DisplayText;
}
private void UpdatePosition()
@ -173,11 +174,8 @@ namespace UnityExplorer.UI.Widgets.AutoComplete
{
dataHandler = new ButtonListSource<Suggestion>(scrollPool, GetEntries, SetCell, ShouldDisplay, OnCellClicked);
var prototypeCell = ButtonCell<Suggestion>.CreatePrototypeCell(this.content);
prototypeCell.GetComponentInChildren<Text>().supportRichText = true;
scrollPool = UIFactory.CreateScrollPool(this.content, "AutoCompleter", out GameObject scrollObj, out GameObject scrollContent);
scrollPool.Initialize(dataHandler, prototypeCell);
scrollPool = UIFactory.CreateScrollPool<ButtonCell>(this.content, "AutoCompleter", out GameObject scrollObj, out GameObject scrollContent);
scrollPool.Initialize(dataHandler);
UIFactory.SetLayoutElement(scrollObj, flexibleHeight: 9999);
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(scrollContent, true, false, true, false);

View File

@ -4,35 +4,29 @@ using System.Linq;
using System.Text;
using UnityEngine;
using UnityEngine.UI;
using UnityExplorer.UI.ObjectPool;
namespace UnityExplorer.UI.Widgets
{
public class ButtonCell<T> : ICell
public class ButtonCell : ICell
{
public bool Enabled => m_enabled;
private bool m_enabled;
public float DefaultHeight => 25f;
public Action<int> OnClick;
public int CurrentDataIndex;
public ButtonListSource<T> list;
public GameObject UIRoot => uiRoot;
public GameObject uiRoot;
private RectTransform m_rect;
public ButtonRef Button;
#region ICell
public bool Enabled => m_enabled;
private bool m_enabled;
public RectTransform Rect => m_rect;
public Text buttonText;
public Button button;
public ButtonCell(ButtonListSource<T> list, GameObject uiRoot, Button button, Text text)
{
this.list = list;
this.uiRoot = uiRoot;
this.m_rect = uiRoot.GetComponent<RectTransform>();
this.buttonText = text;
this.button = button;
button.onClick.AddListener(() => { OnClick?.Invoke(CurrentDataIndex); });
}
private RectTransform m_rect;
public void Disable()
{
@ -46,33 +40,36 @@ namespace UnityExplorer.UI.Widgets
uiRoot.SetActive(true);
}
public static RectTransform CreatePrototypeCell(GameObject parent)
#endregion
public GameObject CreateContent(GameObject parent)
{
var prototype = UIFactory.CreateHorizontalGroup(parent, "PrototypeCell", true, true, true, true, 2, default,
new Color(0.15f, 0.15f, 0.15f), TextAnchor.MiddleCenter);
//var cell = prototype.AddComponent<TransformCell>();
var rect = prototype.GetComponent<RectTransform>();
rect.anchorMin = new Vector2(0, 1);
rect.anchorMax = new Vector2(0, 1);
rect.pivot = new Vector2(0.5f, 1);
rect.sizeDelta = new Vector2(25, 25);
UIFactory.SetLayoutElement(prototype, minWidth: 100, flexibleWidth: 9999, minHeight: 25, flexibleHeight: 0);
uiRoot = UIFactory.CreateHorizontalGroup(parent, "ButtonCell", true, true, true, true, 2, default,
new Color(0.11f, 0.11f, 0.11f), TextAnchor.MiddleCenter);
m_rect = uiRoot.GetComponent<RectTransform>();
m_rect.anchorMin = new Vector2(0, 1);
m_rect.anchorMax = new Vector2(0, 1);
m_rect.pivot = new Vector2(0.5f, 1);
m_rect.sizeDelta = new Vector2(25, 25);
UIFactory.SetLayoutElement(uiRoot, minWidth: 100, flexibleWidth: 9999, minHeight: 25, flexibleHeight: 0);
var nameButton = UIFactory.CreateButton(prototype, "NameButton", "Name", null);
UIFactory.SetLayoutElement(nameButton.gameObject, flexibleWidth: 9999, minHeight: 25, flexibleHeight: 0);
var nameLabel = nameButton.GetComponentInChildren<Text>();
nameLabel.horizontalOverflow = HorizontalWrapMode.Overflow;
nameLabel.alignment = TextAnchor.MiddleLeft;
uiRoot.SetActive(false);
Color normal = new Color(0.15f, 0.15f, 0.15f);
this.Button = UIFactory.CreateButton(uiRoot, "NameButton", "Name");
UIFactory.SetLayoutElement(Button.Button.gameObject, flexibleWidth: 9999, minHeight: 25, flexibleHeight: 0);
var buttonText = Button.Button.GetComponentInChildren<Text>();
buttonText.horizontalOverflow = HorizontalWrapMode.Overflow;
buttonText.alignment = TextAnchor.MiddleLeft;
Color normal = new Color(0.11f, 0.11f, 0.11f);
Color highlight = new Color(0.25f, 0.25f, 0.25f);
Color pressed = new Color(0.05f, 0.05f, 0.05f);
Color disabled = new Color(1, 1, 1, 0);
RuntimeProvider.Instance.SetColorBlock(nameButton, normal, highlight, pressed, disabled);
RuntimeProvider.Instance.SetColorBlock(Button.Button, normal, highlight, pressed, disabled);
prototype.SetActive(false);
Button.OnClick += () => { OnClick?.Invoke(CurrentDataIndex); };
return rect;
return m_rect.gameObject;
}
}
}

View File

@ -5,21 +5,22 @@ using System.Linq;
using System.Text;
using UnityEngine;
using UnityEngine.UI;
using UnityExplorer.UI.ObjectPool;
using UnityExplorer.UI.Widgets;
namespace UnityExplorer.UI.Widgets
{
public class ButtonListSource<T> : IPoolDataSource
public class ButtonListSource<T> : IPoolDataSource<ButtonCell>
{
public int GetRealIndexOfTempIndex(int index) => throw new NotImplementedException("TODO");
internal ScrollPool Scroller;
internal ScrollPool<ButtonCell> ScrollPool;
public int ItemCount => currentEntries.Count;
public readonly List<T> currentEntries = new List<T>();
public Func<List<T>> GetEntries;
public Action<ButtonCell<T>, int> SetICell;
public Action<ButtonCell, int> SetICell;
public Func<T, string, bool> ShouldDisplay;
public Action<int> OnCellClicked;
@ -30,11 +31,11 @@ namespace UnityExplorer.UI.Widgets
}
private string currentFilter;
public ButtonListSource(ScrollPool scrollPool, Func<List<T>> getEntriesMethod,
Action<ButtonCell<T>, int> setICellMethod, Func<T, string, bool> shouldDisplayMethod,
public ButtonListSource(ScrollPool<ButtonCell> scrollPool, Func<List<T>> getEntriesMethod,
Action<ButtonCell, int> setICellMethod, Func<T, string, bool> shouldDisplayMethod,
Action<int> onCellClickedMethod)
{
Scroller = scrollPool;
ScrollPool = scrollPool;
GetEntries = getEntriesMethod;
SetICell = setICellMethod;
@ -42,15 +43,6 @@ namespace UnityExplorer.UI.Widgets
OnCellClicked = onCellClickedMethod;
}
public void Init()
{
var proto = ButtonCell<T>.CreatePrototypeCell(Scroller.UIRoot);
RefreshData();
Scroller.DataSource = this;
Scroller.Initialize(this, proto);
}
public void RefreshData()
{
var allEntries = GetEntries.Invoke();
@ -70,16 +62,17 @@ namespace UnityExplorer.UI.Widgets
}
}
public ICell CreateCell(RectTransform rect)
public void OnCellBorrowed(ButtonCell cell)
{
var button = rect.GetComponentInChildren<Button>();
var text = button.GetComponentInChildren<Text>();
var cell = new ButtonCell<T>(this, rect.gameObject, button, text);
cell.OnClick += OnCellClicked;
return cell;
}
public void SetCell(ICell cell, int index)
public void OnCellReturned(ButtonCell cell)
{
cell.OnClick -= OnCellClicked;
}
public void SetCell(ButtonCell cell, int index)
{
if (currentEntries == null)
RefreshData();
@ -89,11 +82,11 @@ namespace UnityExplorer.UI.Widgets
else
{
cell.Enable();
(cell as ButtonCell<T>).CurrentDataIndex = index;
SetICell.Invoke((ButtonCell<T>)cell, index);
cell.CurrentDataIndex = index;
SetICell.Invoke(cell, index);
}
}
public void DisableCell(ICell cell, int index) => cell.Disable();
public void DisableCell(ButtonCell cell, int index) => cell.Disable();
}
}

View File

@ -0,0 +1,26 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine.UI;
namespace UnityExplorer.UI.Widgets
{
// A simple helper class to handle a button's OnClick more effectively.
public class ButtonRef
{
public Action OnClick;
public Button Button { get; }
public Text ButtonText { get; }
public ButtonRef(Button button)
{
this.Button = button;
this.ButtonText = button.GetComponentInChildren<Text>();
button.onClick.AddListener(() => { OnClick?.Invoke(); });
}
}
}

View File

@ -1,102 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using UnityEngine.UI;
using UnityExplorer.Core.Config;
using UnityExplorer.UI.InteractiveValues;
namespace UnityExplorer.UI.CacheObject
{
public class CacheConfigEntry : CacheObjectBase
{
public IConfigElement RefConfig { get; }
public override Type FallbackType => RefConfig.ElementType;
public override bool HasEvaluated => true;
public override bool HasParameters => false;
public override bool IsMember => false;
public override bool CanWrite => true;
public CacheConfigEntry(IConfigElement config, GameObject parent)
{
RefConfig = config;
m_parentContent = parent;
config.OnValueChangedNotify += () => { UpdateValue(); };
CreateIValue(config.BoxedValue, config.ElementType);
}
public override void CreateIValue(object value, Type fallbackType)
{
IValue = InteractiveValue.Create(value, fallbackType);
IValue.Owner = this;
IValue.m_mainContentParent = m_mainGroup;
IValue.m_subContentParent = this.SubContentGroup;
}
public override void UpdateValue()
{
IValue.Value = RefConfig.BoxedValue;
base.UpdateValue();
}
public override void SetValue()
{
RefConfig.BoxedValue = IValue.Value;
}
internal GameObject m_mainGroup;
internal override void ConstructUI()
{
base.ConstructUI();
m_mainGroup = UIFactory.CreateVerticalGroup(UIRoot, "ConfigHolder", true, false, true, true, 5, new Vector4(2, 2, 2, 2));
var horiGroup = UIFactory.CreateHorizontalGroup(m_mainGroup, "ConfigEntryHolder", false, false, true, true, childAlignment: TextAnchor.MiddleLeft);
UIFactory.SetLayoutElement(horiGroup, minHeight: 30, flexibleHeight: 0);
// config entry label
var configLabel = UIFactory.CreateLabel(horiGroup, "ConfigLabel", this.RefConfig.Name, TextAnchor.MiddleLeft);
var leftRect = configLabel.GetComponent<RectTransform>();
leftRect.anchorMin = Vector2.zero;
leftRect.anchorMax = Vector2.one;
leftRect.offsetMin = Vector2.zero;
leftRect.offsetMax = Vector2.zero;
leftRect.sizeDelta = Vector2.zero;
UIFactory.SetLayoutElement(configLabel.gameObject, minWidth: 250, minHeight: 25, flexibleWidth: 0, flexibleHeight: 0);
// Default button
var defaultButton = UIFactory.CreateButton(horiGroup,
"RevertDefaultButton",
"Default",
() => { RefConfig.RevertToDefaultValue(); },
new Color(0.3f, 0.3f, 0.3f));
UIFactory.SetLayoutElement(defaultButton.gameObject, minWidth: 80, minHeight: 22, flexibleWidth: 0);
// Description label
var desc = UIFactory.CreateLabel(m_mainGroup, "Description", $"<i>{RefConfig.Description}</i>", TextAnchor.MiddleLeft, Color.grey);
UIFactory.SetLayoutElement(desc.gameObject, minWidth: 250, minHeight: 20, flexibleWidth: 9999, flexibleHeight: 0);
// IValue
if (IValue != null)
{
IValue.m_mainContentParent = m_mainGroup;
IValue.m_subContentParent = this.SubContentGroup;
}
// makes the subcontent look nicer
SubContentGroup.transform.SetParent(m_mainGroup.transform, false);
}
}
}

View File

@ -1,57 +0,0 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityExplorer.UI;
using UnityEngine;
using UnityEngine.UI;
using UnityExplorer.UI.InteractiveValues;
namespace UnityExplorer.UI.CacheObject
{
public class CacheEnumerated : CacheObjectBase
{
public override Type FallbackType => ParentEnumeration.m_baseEntryType;
public override bool CanWrite => RefIList != null && ParentEnumeration.Owner.CanWrite;
public int Index { get; set; }
public IList RefIList { get; set; }
public InteractiveEnumerable ParentEnumeration { get; set; }
public CacheEnumerated(int index, InteractiveEnumerable parentEnumeration, IList refIList, GameObject parentContent)
{
this.ParentEnumeration = parentEnumeration;
this.Index = index;
this.RefIList = refIList;
this.m_parentContent = parentContent;
}
public override void CreateIValue(object value, Type fallbackType)
{
IValue = InteractiveValue.Create(value, fallbackType);
IValue.Owner = this;
}
public override void SetValue()
{
RefIList[Index] = IValue.Value;
ParentEnumeration.Value = RefIList;
ParentEnumeration.Owner.SetValue();
}
internal override void ConstructUI()
{
base.ConstructUI();
var rowObj = UIFactory.CreateHorizontalGroup(UIRoot, "CacheEnumeratedGroup", false, true, true, true, 0, new Vector4(0,0,5,2),
new Color(1, 1, 1, 0));
var indexLabel = UIFactory.CreateLabel(rowObj, "IndexLabel", $"{this.Index}:", TextAnchor.MiddleLeft);
UIFactory.SetLayoutElement(indexLabel.gameObject, minWidth: 20, flexibleWidth: 30, minHeight: 25);
IValue.m_mainContentParent = rowObj;
}
}
}

View File

@ -1,40 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using UnityExplorer.UI;
using UnityEngine;
namespace UnityExplorer.UI.CacheObject
{
public class CacheField : CacheMember
{
public override bool IsStatic => (MemInfo as FieldInfo).IsStatic;
public override Type FallbackType => (MemInfo as FieldInfo).FieldType;
public CacheField(FieldInfo fieldInfo, object declaringInstance, GameObject parent) : base(fieldInfo, declaringInstance, parent)
{
CreateIValue(null, fieldInfo.FieldType);
}
public override void UpdateReflection()
{
var fi = MemInfo as FieldInfo;
IValue.Value = fi.GetValue(fi.IsStatic ? null : DeclaringInstance);
m_evaluated = true;
ReflectionException = null;
}
public override void SetValue()
{
var fi = MemInfo as FieldInfo;
fi.SetValue(fi.IsStatic ? null : DeclaringInstance, IValue.Value);
if (this.ParentInspector?.ParentMember != null)
this.ParentInspector.ParentMember.SetValue();
}
}
}

View File

@ -1,360 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using UnityEngine;
using UnityEngine.UI;
using UnityExplorer.UI;
using UnityExplorer.Core.Runtime;
using UnityExplorer.Core;
using UnityExplorer.UI.Utility;
using UnityExplorer.UI.InteractiveValues;
using UnityExplorer.UI.Inspectors.Reflection;
using UnityExplorer.UI.Panels;
namespace UnityExplorer.UI.CacheObject
{
public abstract class CacheMember : CacheObjectBase
{
public override bool IsMember => true;
public override Type FallbackType { get; }
public ReflectionInspector ParentInspector { get; set; }
public MemberInfo MemInfo { get; set; }
public Type DeclaringType { get; set; }
public object DeclaringInstance { get; set; }
public virtual bool IsStatic { get; private set; }
public string ReflectionException { get; set; }
public override bool CanWrite => m_canWrite ?? GetCanWrite();
private bool? m_canWrite;
public override bool HasParameters => ParamCount > 0;
public virtual int ParamCount => m_arguments.Length;
public override bool HasEvaluated => m_evaluated;
public bool m_evaluated = false;
public bool m_isEvaluating;
public ParameterInfo[] m_arguments = new ParameterInfo[0];
public string[] m_argumentInput = new string[0];
public string NameForFiltering => m_nameForFilter ?? (m_nameForFilter = $"{MemInfo.DeclaringType.Name}.{MemInfo.Name}".ToLower());
private string m_nameForFilter;
public string RichTextName => m_richTextName ?? GetRichTextName();
private string m_richTextName;
public CacheMember(MemberInfo memberInfo, object declaringInstance, GameObject parentContent)
{
MemInfo = memberInfo;
DeclaringType = memberInfo.DeclaringType;
DeclaringInstance = declaringInstance;
this.m_parentContent = parentContent;
DeclaringInstance = ReflectionProvider.Instance.Cast(declaringInstance, DeclaringType);
}
public override void Enable()
{
base.Enable();
ParentInspector.displayedMembers.Add(this);
memberLabelElement.minWidth = 0.4f * InspectorPanel.CurrentPanelWidth;
}
public override void Disable()
{
base.Disable();
ParentInspector.displayedMembers.Remove(this);
}
public static bool CanProcessArgs(ParameterInfo[] parameters)
{
foreach (var param in parameters)
{
var pType = param.ParameterType;
if (pType.IsByRef && pType.HasElementType)
pType = pType.GetElementType();
if (pType != null && (pType.IsPrimitive || pType == typeof(string)))
continue;
else
return false;
}
return true;
}
public override void CreateIValue(object value, Type fallbackType)
{
IValue = InteractiveValue.Create(value, fallbackType);
IValue.Owner = this;
IValue.m_mainContentParent = this.ContentGroup;
IValue.m_subContentParent = this.SubContentGroup;
}
public override void UpdateValue()
{
if (!HasParameters || m_isEvaluating)
{
try
{
Type baseType = ReflectionUtility.GetActualType(IValue.Value) ?? FallbackType;
if (!ReflectionProvider.Instance.IsReflectionSupported(baseType))
throw new Exception("Type not supported with reflection");
UpdateReflection();
if (IValue.Value != null)
IValue.Value = IValue.Value.TryCast(ReflectionUtility.GetActualType(IValue.Value));
}
catch (Exception e)
{
ReflectionException = e.ReflectionExToString(true);
}
}
base.UpdateValue();
}
public abstract void UpdateReflection();
public override void SetValue()
{
// no implementation for base class
}
public object[] ParseArguments()
{
if (m_arguments.Length < 1)
return new object[0];
var parsedArgs = new List<object>();
for (int i = 0; i < m_arguments.Length; i++)
{
var input = m_argumentInput[i];
var type = m_arguments[i].ParameterType;
if (type.IsByRef)
type = type.GetElementType();
if (!string.IsNullOrEmpty(input))
{
if (type == typeof(string))
{
parsedArgs.Add(input);
continue;
}
else
{
try
{
var arg = type.GetMethod("Parse", new Type[] { typeof(string) })
.Invoke(null, new object[] { input });
parsedArgs.Add(arg);
continue;
}
catch
{
ExplorerCore.Log($"Could not parse input '{input}' for argument #{i} '{m_arguments[i].Name}' ({type.FullName})");
}
}
}
// No input, see if there is a default value.
if (m_arguments[i].IsOptional)
{
parsedArgs.Add(m_arguments[i].DefaultValue);
continue;
}
// Try add a null arg I guess
parsedArgs.Add(null);
}
return parsedArgs.ToArray();
}
private bool GetCanWrite()
{
if (MemInfo is FieldInfo fi)
m_canWrite = !(fi.IsLiteral && !fi.IsInitOnly);
else if (MemInfo is PropertyInfo pi)
m_canWrite = pi.CanWrite;
else
m_canWrite = false;
return (bool)m_canWrite;
}
private string GetRichTextName()
{
return m_richTextName = SignatureHighlighter.ParseFullSyntax(MemInfo.DeclaringType, false, MemInfo);
}
#region UI
internal Text memberLabelText;
internal GameObject ContentGroup;
internal LayoutElement memberLabelElement;
internal override void ConstructUI()
{
base.ConstructUI();
var horiGroup = UIFactory.CreateUIObject("HoriGroup", UIRoot);
var groupRect = horiGroup.GetComponent<RectTransform>();
groupRect.pivot = new Vector2(0, 1);
groupRect.anchorMin = Vector2.zero;
groupRect.anchorMax = Vector2.one;
UIFactory.SetLayoutElement(horiGroup, minHeight: 30, flexibleHeight: 9999);
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(horiGroup, true, true, true, true, 2, 2, 2, 2, 2, childAlignment: TextAnchor.UpperLeft);
memberLabelText = UIFactory.CreateLabel(horiGroup, "MemLabelText", RichTextName, TextAnchor.UpperLeft);
memberLabelText.horizontalOverflow = HorizontalWrapMode.Wrap;
UIFactory.SetLayoutElement(memberLabelText.gameObject, minHeight: 25, flexibleHeight: 9999, minWidth: 150, flexibleWidth: 0);
memberLabelElement = memberLabelText.GetComponent<LayoutElement>();
ContentGroup = UIFactory.CreateUIObject("ContentGroup", horiGroup, default);
UIFactory.SetLayoutElement(ContentGroup, minHeight: 30, flexibleWidth: 9999);
var contentRect = ContentGroup.GetComponent<RectTransform>();
contentRect.pivot = new Vector2(0, 1);
contentRect.anchorMin = new Vector2(0, 0);
contentRect.anchorMax = new Vector2(1, 1);
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(ContentGroup, false, false, true, true, childAlignment: TextAnchor.MiddleLeft);
ConstructArgInput(out GameObject argsHolder);
ConstructEvaluateButtons(argsHolder);
IValue.m_mainContentParent = this.ContentGroup;
//RightContentGroup.SetActive(false);
// ParentInspector.CacheObjectContents.Add(this.m_mainContent);
}
internal void ConstructArgInput(out GameObject argsHolder)
{
argsHolder = null;
if (HasParameters)
{
argsHolder = UIFactory.CreateVerticalGroup(ContentGroup, "ArgsHolder", true, false, true, true, 4, new Color(1, 1, 1, 0));
if (this is CacheMethod cm && cm.GenericArgs.Length > 0)
cm.ConstructGenericArgInput(argsHolder);
if (m_arguments.Length > 0)
{
UIFactory.CreateLabel(argsHolder, "ArgumentsLabel", "Arguments:", TextAnchor.MiddleLeft);
for (int i = 0; i < m_arguments.Length; i++)
AddArgRow(i, argsHolder);
}
argsHolder.SetActive(false);
}
}
internal void AddArgRow(int i, GameObject parent)
{
var arg = m_arguments[i];
var rowObj = UIFactory.CreateHorizontalGroup(parent, "ArgRow", true, false, true, true, 4, default, new Color(1, 1, 1, 0));
UIFactory.SetLayoutElement(rowObj, minHeight: 25, flexibleWidth: 5000);
var argTypeTxt = SignatureHighlighter.ParseFullSyntax(arg.ParameterType, false);
var argLabel = UIFactory.CreateLabel(rowObj, "ArgLabel", $"{argTypeTxt} <color={SignatureHighlighter.LOCAL_ARG}>{arg.Name}</color>",
TextAnchor.MiddleLeft);
UIFactory.SetLayoutElement(argLabel.gameObject, minHeight: 25);
var argInputObj = UIFactory.CreateInputField(rowObj, "ArgInput", "...", out InputField argInput, 14, (int)TextAnchor.MiddleLeft, 1);
UIFactory.SetLayoutElement(argInputObj, flexibleWidth: 1200, preferredWidth: 150, minWidth: 20, minHeight: 25, flexibleHeight: 0);
argInput.onValueChanged.AddListener((string val) => { m_argumentInput[i] = val; });
if (arg.IsOptional)
{
var phInput = argInput.placeholder.GetComponent<Text>();
phInput.text = " = " + arg.DefaultValue?.ToString() ?? "null";
}
}
internal void ConstructEvaluateButtons(GameObject argsHolder)
{
if (HasParameters)
{
var evalGroupObj = UIFactory.CreateHorizontalGroup(ContentGroup, "EvalGroup", false, false, true, true, 5,
default, new Color(1, 1, 1, 0));
UIFactory.SetLayoutElement(evalGroupObj, minHeight: 25, flexibleHeight: 0, flexibleWidth: 5000);
var evalButton = UIFactory.CreateButton(evalGroupObj,
"EvalButton",
$"Evaluate ({ParamCount})",
null);
RuntimeProvider.Instance.SetColorBlock(evalButton, new Color(0.4f, 0.4f, 0.4f),
new Color(0.4f, 0.7f, 0.4f), new Color(0.3f, 0.3f, 0.3f));
UIFactory.SetLayoutElement(evalButton.gameObject, minWidth: 100, minHeight: 22, flexibleWidth: 0);
var evalText = evalButton.GetComponentInChildren<Text>();
var cancelButton = UIFactory.CreateButton(evalGroupObj, "CancelButton", "Close", null, new Color(0.3f, 0.3f, 0.3f));
UIFactory.SetLayoutElement(cancelButton.gameObject, minWidth: 100, minHeight: 22, flexibleWidth: 0);
cancelButton.gameObject.SetActive(false);
evalButton.onClick.AddListener(() =>
{
if (!m_isEvaluating)
{
argsHolder.SetActive(true);
m_isEvaluating = true;
evalText.text = "Evaluate";
RuntimeProvider.Instance.SetColorBlock(evalButton, new Color(0.3f, 0.6f, 0.3f));
cancelButton.gameObject.SetActive(true);
}
else
{
if (this is CacheMethod cm)
cm.Evaluate();
else
UpdateValue();
}
});
cancelButton.onClick.AddListener(() =>
{
cancelButton.gameObject.SetActive(false);
argsHolder.SetActive(false);
m_isEvaluating = false;
evalText.text = $"Evaluate ({ParamCount})";
RuntimeProvider.Instance.SetColorBlock(evalButton, new Color(0.4f, 0.4f, 0.4f));
});
}
else if (this is CacheMethod)
{
// simple method evaluate button
var evalButton = UIFactory.CreateButton(ContentGroup, "EvalButton", "Evaluate", () => { (this as CacheMethod).Evaluate(); });
RuntimeProvider.Instance.SetColorBlock(evalButton, new Color(0.4f, 0.4f, 0.4f),
new Color(0.4f, 0.7f, 0.4f), new Color(0.3f, 0.3f, 0.3f));
UIFactory.SetLayoutElement(evalButton.gameObject, minWidth: 100, minHeight: 22, flexibleWidth: 0);
}
}
#endregion
}
}

View File

@ -1,170 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using UnityEngine;
using UnityEngine.UI;
using UnityExplorer.UI;
using UnityExplorer.Core;
using UnityExplorer.UI.Utility;
namespace UnityExplorer.UI.CacheObject
{
public class CacheMethod : CacheMember
{
//private CacheObjectBase m_cachedReturnValue;
public override Type FallbackType => (MemInfo as MethodInfo).ReturnType;
public override bool HasParameters => base.HasParameters || GenericArgs.Length > 0;
public override bool IsStatic => (MemInfo as MethodInfo).IsStatic;
public override int ParamCount => base.ParamCount + m_genericArgInput.Length;
public Type[] GenericArgs { get; private set; }
public Type[][] GenericConstraints { get; private set; }
public string[] m_genericArgInput = new string[0];
public CacheMethod(MethodInfo methodInfo, object declaringInstance, GameObject parent) : base(methodInfo, declaringInstance, parent)
{
GenericArgs = methodInfo.GetGenericArguments();
GenericConstraints = GenericArgs.Select(x => x.GetGenericParameterConstraints())
.Where(x => x != null)
.ToArray();
m_genericArgInput = new string[GenericArgs.Length];
m_arguments = methodInfo.GetParameters();
m_argumentInput = new string[m_arguments.Length];
CreateIValue(null, methodInfo.ReturnType);
}
public override void UpdateReflection()
{
// CacheMethod cannot UpdateValue directly. Need to Evaluate.
}
public void Evaluate()
{
MethodInfo mi;
if (GenericArgs.Length > 0)
{
mi = MakeGenericMethodFromInput();
if (mi == null) return;
}
else
{
mi = MemInfo as MethodInfo;
}
object ret = null;
try
{
ret = mi.Invoke(mi.IsStatic ? null : DeclaringInstance, ParseArguments());
m_evaluated = true;
m_isEvaluating = false;
ReflectionException = null;
}
catch (Exception e)
{
while (e.InnerException != null)
e = e.InnerException;
ExplorerCore.LogWarning($"Exception evaluating: {e.GetType()}, {e.Message}");
ReflectionException = ReflectionUtility.ReflectionExToString(e);
}
IValue.Value = ret;
UpdateValue();
}
private MethodInfo MakeGenericMethodFromInput()
{
var mi = MemInfo as MethodInfo;
var list = new List<Type>();
for (int i = 0; i < GenericArgs.Length; i++)
{
var input = m_genericArgInput[i];
if (ReflectionUtility.GetTypeByName(input) is Type t)
{
if (GenericConstraints[i].Length == 0)
{
list.Add(t);
}
else
{
foreach (var constraint in GenericConstraints[i].Where(x => x != null))
{
if (!constraint.IsAssignableFrom(t))
{
ExplorerCore.LogWarning($"Generic argument #{i}, '{input}' is not assignable from the constraint '{constraint}'!");
return null;
}
}
list.Add(t);
}
}
else
{
ExplorerCore.LogWarning($"Generic argument #{i}, could not get any type by the name of '{input}'!" +
$" Make sure you use the full name including the namespace.");
return null;
}
}
// make into a generic with type list
mi = mi.MakeGenericMethod(list.ToArray());
return mi;
}
#region UI CONSTRUCTION
internal void ConstructGenericArgInput(GameObject parent)
{
UIFactory.CreateLabel(parent, "GenericArgLabel", "Generic Arguments:", TextAnchor.MiddleLeft);
for (int i = 0; i < GenericArgs.Length; i++)
AddGenericArgRow(i, parent);
}
internal void AddGenericArgRow(int i, GameObject parent)
{
var arg = GenericArgs[i];
string constrainTxt = "";
if (this.GenericConstraints[i].Length > 0)
{
foreach (var constraint in this.GenericConstraints[i])
{
if (constrainTxt != "")
constrainTxt += ", ";
constrainTxt += $"{SignatureHighlighter.ParseFullSyntax(constraint, false)}";
}
}
else
constrainTxt = $"Any";
var rowObj = UIFactory.CreateHorizontalGroup(parent, "ArgRowObj", false, true, true, true, 4, default, new Color(1, 1, 1, 0));
UIFactory.SetLayoutElement(rowObj, minHeight: 25, flexibleWidth: 5000);
var argLabelObj = UIFactory.CreateLabel(rowObj, "ArgLabelObj", $"{constrainTxt} <color={SignatureHighlighter.CONST_VAR}>{arg.Name}</color>",
TextAnchor.MiddleLeft);
var argInputObj = UIFactory.CreateInputField(rowObj, "ArgInput", "...", out InputField argInput, 14, (int)TextAnchor.MiddleLeft, 1);
UIFactory.SetLayoutElement(argInputObj, flexibleWidth: 1200);
argInput.onValueChanged.AddListener((string val) => { m_genericArgInput[i] = val; });
}
#endregion
}
}

View File

@ -1,120 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using UnityEngine;
using UnityExplorer.UI;
using UnityEngine.UI;
using UnityExplorer.Core;
using UnityExplorer.UI.InteractiveValues;
using UnityExplorer.UI.Widgets;
namespace UnityExplorer.UI.CacheObject
{
public abstract class CacheObjectBase
{
public InteractiveValue IValue;
public virtual bool CanWrite => false;
public virtual bool HasParameters => false;
public virtual bool IsMember => false;
public virtual bool HasEvaluated => true;
public abstract Type FallbackType { get; }
public abstract void CreateIValue(object value, Type fallbackType);
public virtual void Enable()
{
if (!m_constructedUI)
{
ConstructUI();
UpdateValue();
}
}
public virtual void Disable()
{
if (UIRoot)
UIRoot.SetActive(false);
}
public void Destroy()
{
if (this.UIRoot)
GameObject.Destroy(this.UIRoot);
}
public virtual void UpdateValue()
{
var value = IValue.Value;
// if the type has changed fundamentally, make a new interactivevalue for it
var type = value == null
? FallbackType
: ReflectionUtility.GetActualType(value);
var ivalueType = InteractiveValue.GetIValueForType(type);
if (ivalueType != IValue.GetType())
{
IValue.OnDestroy();
CreateIValue(value, FallbackType);
SubContentGroup.SetActive(false);
}
IValue.OnValueUpdated();
IValue.RefreshElementsAfterUpdate();
}
public virtual void SetValue() => throw new NotImplementedException();
#region UI CONSTRUCTION
internal bool m_constructedUI;
internal GameObject m_parentContent;
internal RectTransform m_mainRect;
internal GameObject UIRoot;
internal GameObject SubContentGroup;
internal bool constructedSubcontent;
// Make base UI holder for CacheObject, this doesnt actually display anything.
internal virtual void ConstructUI()
{
m_constructedUI = true;
//UIRoot = UIFactory.CreateVerticalGroup(m_parentContent, $"{this.GetType().Name}.MainContent", true, true, true, true, 2,
// new Vector4(0, 5, 0, 0), new Color(0.1f, 0.1f, 0.1f), TextAnchor.UpperLeft);
UIRoot = UIFactory.CreateUIObject($"{this.GetType().Name}.MainContent", m_parentContent);
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(UIRoot, true, true, true, true, 2, 0, 5, 0, 0, TextAnchor.UpperLeft);
m_mainRect = UIRoot.GetComponent<RectTransform>();
m_mainRect.pivot = new Vector2(0, 1);
m_mainRect.anchorMin = Vector2.zero;
m_mainRect.anchorMax = Vector2.one;
UIFactory.SetLayoutElement(UIRoot, minHeight: 30, flexibleHeight: 9999, minWidth: 200, flexibleWidth: 5000);
SubContentGroup = new GameObject("SubContent");
SubContentGroup.transform.parent = UIRoot.transform;
UIFactory.SetLayoutElement(SubContentGroup, minHeight: 30, flexibleHeight: 9999, minWidth: 125, flexibleWidth: 9000);
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(SubContentGroup, true, false, true, true);
SubContentGroup.SetActive(false);
IValue.m_subContentParent = SubContentGroup;
}
public virtual void CheckSubcontentCreation()
{
if (!constructedSubcontent)
{
SubContentGroup.AddComponent<Image>().color = new Color(0.08f, 0.08f, 0.08f);
constructedSubcontent = true;
}
}
#endregion
}
}

View File

@ -1,72 +0,0 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityExplorer.UI;
using UnityEngine;
using UnityEngine.UI;
using UnityExplorer.UI.InteractiveValues;
namespace UnityExplorer.UI.CacheObject
{
public enum PairTypes
{
Key,
Value
}
public class CachePaired : CacheObjectBase
{
public override Type FallbackType => PairType == PairTypes.Key
? ParentDictionary.m_typeOfKeys
: ParentDictionary.m_typeofValues;
public override bool CanWrite => false; // todo?
public PairTypes PairType;
public int Index { get; private set; }
public InteractiveDictionary ParentDictionary { get; private set; }
internal IDictionary RefIDict;
public CachePaired(int index, InteractiveDictionary parentDict, IDictionary refIDict, PairTypes pairType, GameObject parentContent)
{
Index = index;
ParentDictionary = parentDict;
RefIDict = refIDict;
this.PairType = pairType;
this.m_parentContent = parentContent;
}
public override void CreateIValue(object value, Type fallbackType)
{
IValue = InteractiveValue.Create(value, fallbackType);
IValue.Owner = this;
}
#region UI CONSTRUCTION
internal override void ConstructUI()
{
base.ConstructUI();
Color bgColor = this.PairType == PairTypes.Key
? new Color(0.07f, 0.07f, 0.07f)
: new Color(0.1f, 0.1f, 0.1f);
var rowObj = UIFactory.CreateHorizontalGroup(UIRoot, "PairedGroup", false, false, true, true, 0, new Vector4(0,0,5,2),
bgColor);
string lbl = $"{this.PairType}";
if (this.PairType == PairTypes.Key)
lbl = $"[{Index}] {lbl}";
var indexLabel = UIFactory.CreateLabel(rowObj, "IndexLabel", lbl, TextAnchor.MiddleLeft);
UIFactory.SetLayoutElement(indexLabel.gameObject, minWidth: 80, flexibleWidth: 30, minHeight: 25);
IValue.m_mainContentParent = rowObj;
}
#endregion
}
}

View File

@ -1,70 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using UnityExplorer.UI;
using UnityEngine;
namespace UnityExplorer.UI.CacheObject
{
public class CacheProperty : CacheMember
{
public override Type FallbackType => (MemInfo as PropertyInfo).PropertyType;
public override bool IsStatic => (MemInfo as PropertyInfo).GetAccessors(true)[0].IsStatic;
public CacheProperty(PropertyInfo propertyInfo, object declaringInstance, GameObject parent) : base(propertyInfo, declaringInstance, parent)
{
this.m_arguments = propertyInfo.GetIndexParameters();
this.m_argumentInput = new string[m_arguments.Length];
CreateIValue(null, propertyInfo.PropertyType);
}
public override void UpdateReflection()
{
if (HasParameters && !m_isEvaluating)
{
// Need to enter parameters first.
return;
}
var pi = MemInfo as PropertyInfo;
if (pi.CanRead)
{
var target = pi.GetAccessors(true)[0].IsStatic ? null : DeclaringInstance;
IValue.Value = pi.GetValue(target, ParseArguments());
m_evaluated = true;
ReflectionException = null;
}
else
{
if (FallbackType == typeof(string))
{
IValue.Value = "";
}
else if (FallbackType.IsPrimitive)
{
IValue.Value = Activator.CreateInstance(FallbackType);
}
m_evaluated = true;
ReflectionException = null;
}
}
public override void SetValue()
{
var pi = MemInfo as PropertyInfo;
var target = pi.GetAccessors()[0].IsStatic ? null : DeclaringInstance;
pi.SetValue(target, IValue.Value, ParseArguments());
if (this.ParentInspector?.ParentMember != null)
this.ParentInspector.ParentMember.SetValue();
}
}
}

View File

@ -1,110 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using UnityEngine.UI;
using UnityExplorer.UI;
using UnityExplorer.UI.CacheObject;
namespace UnityExplorer.UI.InteractiveValues
{
public class InteractiveBool : InteractiveValue
{
public InteractiveBool(object value, Type valueType) : base(value, valueType) { }
public override bool HasSubContent => false;
public override bool SubContentWanted => false;
public override bool WantInspectBtn => false;
internal Toggle m_toggle;
internal Button m_applyBtn;
public override void OnValueUpdated()
{
base.OnValueUpdated();
}
public override void RefreshUIForValue()
{
GetDefaultLabel();
if (Owner.HasEvaluated)
{
var val = (bool)Value;
if (!m_toggle.gameObject.activeSelf)
m_toggle.gameObject.SetActive(true);
if (val != m_toggle.isOn)
m_toggle.isOn = val;
if (Owner.CanWrite)
{
if (!m_applyBtn.gameObject.activeSelf)
m_applyBtn.gameObject.SetActive(true);
}
var color = val
? "6bc981" // on
: "c96b6b"; // off
m_baseLabel.text = $"<color=#{color}>{val}</color>";
}
else
{
m_baseLabel.text = DefaultLabel;
}
}
public override void OnException(CacheMember member)
{
base.OnException(member);
if (Owner.CanWrite)
{
if (m_toggle.gameObject.activeSelf)
m_toggle.gameObject.SetActive(false);
if (m_applyBtn.gameObject.activeSelf)
m_applyBtn.gameObject.SetActive(false);
}
}
internal void OnToggleValueChanged(bool val)
{
Value = val;
RefreshUIForValue();
}
public override void ConstructUI(GameObject parent, GameObject subGroup)
{
base.ConstructUI(parent, subGroup);
var baseLayout = m_baseLabel.gameObject.GetComponent<LayoutElement>();
baseLayout.flexibleWidth = 0;
baseLayout.minWidth = 50;
var toggleObj = UIFactory.CreateToggle(m_mainContent, "InteractiveBoolToggle", out m_toggle, out _, new Color(0.1f, 0.1f, 0.1f));
UIFactory.SetLayoutElement(toggleObj, minWidth: 24);
m_toggle.onValueChanged.AddListener(OnToggleValueChanged);
m_baseLabel.transform.SetAsLastSibling();
m_applyBtn = UIFactory.CreateButton(m_mainContent,
"ApplyButton",
"Apply",
() => { Owner.SetValue(); },
new Color(0.2f, 0.2f, 0.2f));
UIFactory.SetLayoutElement(m_applyBtn.gameObject, minWidth: 50, minHeight: 25, flexibleWidth: 0);
toggleObj.SetActive(false);
if (!Owner.CanWrite)
m_toggle.interactable = false;
m_applyBtn.gameObject.SetActive(false);
}
}
}

View File

@ -1,167 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using UnityEngine.UI;
namespace UnityExplorer.UI.InteractiveValues
{
public class InteractiveColor : InteractiveValue
{
//~~~~~~~~~ Instance ~~~~~~~~~~
public InteractiveColor(object value, Type valueType) : base(value, valueType) { }
public override bool HasSubContent => true;
public override bool SubContentWanted => true;
public override bool WantInspectBtn => true;
public override void RefreshUIForValue()
{
base.RefreshUIForValue();
if (m_subContentConstructed)
RefreshUI();
}
private void RefreshUI()
{
var color = (Color)this.Value;
m_inputs[0].text = color.r.ToString();
m_inputs[1].text = color.g.ToString();
m_inputs[2].text = color.b.ToString();
m_inputs[3].text = color.a.ToString();
if (m_colorImage)
m_colorImage.color = color;
}
internal override void OnToggleSubcontent(bool toggle)
{
base.OnToggleSubcontent(toggle);
RefreshUI();
}
#region UI CONSTRUCTION
private Image m_colorImage;
private readonly InputField[] m_inputs = new InputField[4];
private readonly Slider[] m_sliders = new Slider[4];
public override void ConstructUI(GameObject parent, GameObject subGroup)
{
base.ConstructUI(parent, subGroup);
//// Limit the label width for colors, they're always about the same so make use of that space.
//UIFactory.SetLayoutElement(this.m_baseLabel.gameObject, flexibleWidth: 0, minWidth: 250);
}
public override void ConstructSubcontent()
{
base.ConstructSubcontent();
var horiGroup = UIFactory.CreateHorizontalGroup(m_subContentParent, "ColorEditor", false, false, true, true, 5,
default, default, TextAnchor.MiddleLeft);
var editorContainer = UIFactory.CreateVerticalGroup(horiGroup, "EditorContent", false, true, true, true, 2, new Vector4(4, 4, 4, 4),
new Color(0.08f, 0.08f, 0.08f));
UIFactory.SetLayoutElement(editorContainer, minWidth: 300, flexibleWidth: 0);
for (int i = 0; i < 4; i++)
AddEditorRow(i, editorContainer);
if (Owner.CanWrite)
{
var applyBtn = UIFactory.CreateButton(editorContainer, "ApplyButton", "Apply", OnSetValue, new Color(0.2f, 0.2f, 0.2f));
UIFactory.SetLayoutElement(applyBtn.gameObject, minWidth: 175, minHeight: 25, flexibleWidth: 0);
void OnSetValue()
{
Owner.SetValue();
RefreshUIForValue();
}
}
var imgHolder = UIFactory.CreateVerticalGroup(horiGroup, "ImgHolder", true, true, true, true, 0, new Vector4(1, 1, 1, 1),
new Color(0.08f, 0.08f, 0.08f));
UIFactory.SetLayoutElement(imgHolder, minWidth: 128, minHeight: 128, flexibleWidth: 0, flexibleHeight: 0);
var imgObj = UIFactory.CreateUIObject("ColorImageHelper", imgHolder, new Vector2(100, 25));
m_colorImage = imgObj.AddComponent<Image>();
m_colorImage.color = (Color)this.Value;
}
private static readonly string[] s_fieldNames = new[] { "R", "G", "B", "A" };
internal void AddEditorRow(int index, GameObject groupObj)
{
var row = UIFactory.CreateHorizontalGroup(groupObj, "EditorRow_" + s_fieldNames[index],
false, true, true, true, 5, default, new Color(1, 1, 1, 0));
var label = UIFactory.CreateLabel(row, "RowLabel", $"{s_fieldNames[index]}:", TextAnchor.MiddleRight, Color.cyan);
UIFactory.SetLayoutElement(label.gameObject, minWidth: 50, flexibleWidth: 0, minHeight: 25);
var inputFieldObj = UIFactory.CreateInputField(row, "InputField", "...", out InputField inputField, 14, 3, 1);
UIFactory.SetLayoutElement(inputFieldObj, minWidth: 120, minHeight: 25, flexibleWidth: 0);
m_inputs[index] = inputField;
inputField.characterValidation = InputField.CharacterValidation.Decimal;
inputField.onValueChanged.AddListener((string value) =>
{
float val = float.Parse(value);
SetValueToColor(val);
m_sliders[index].value = val;
});
var sliderObj = UIFactory.CreateSlider(row, "Slider", out Slider slider);
m_sliders[index] = slider;
UIFactory.SetLayoutElement(sliderObj, minWidth: 200, minHeight: 25, flexibleWidth: 0, flexibleHeight: 0);
slider.minValue = 0;
slider.maxValue = 1;
slider.value = GetValueFromColor();
slider.onValueChanged.AddListener((float value) =>
{
inputField.text = value.ToString();
SetValueToColor(value);
m_inputs[index].text = value.ToString();
});
// methods for writing to the color for this field
void SetValueToColor(float floatValue)
{
Color _color = (Color)Value;
switch (index)
{
case 0: _color.r = floatValue; break;
case 1: _color.g = floatValue; break;
case 2: _color.b = floatValue; break;
case 3: _color.a = floatValue; break;
}
Value = _color;
m_colorImage.color = _color;
}
float GetValueFromColor()
{
Color _color = (Color)Value;
switch (index)
{
case 0: return _color.r;
case 1: return _color.g;
case 2: return _color.b;
case 3: return _color.a;
default: throw new NotImplementedException();
}
}
}
#endregion
}
}

View File

@ -1,246 +0,0 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using UnityEngine.UI;
using UnityExplorer.Core.Config;
using UnityExplorer.UI;
using System.Reflection;
using UnityExplorer.UI.CacheObject;
using UnityExplorer.Core;
using UnityExplorer.UI.Utility;
#if CPP
using AltIDictionary = Il2CppSystem.Collections.IDictionary;
#else
using AltIDictionary = System.Collections.IDictionary;
#endif
namespace UnityExplorer.UI.InteractiveValues
{
public class InteractiveDictionary : InteractiveValue
{
public InteractiveDictionary(object value, Type valueType) : base(value, valueType)
{
if (valueType.IsGenericType)
{
var gArgs = valueType.GetGenericArguments();
m_typeOfKeys = gArgs[0];
m_typeofValues = gArgs[1];
}
else
{
m_typeOfKeys = typeof(object);
m_typeofValues = typeof(object);
}
}
public override bool WantInspectBtn => false;
public override bool HasSubContent => true;
public override bool SubContentWanted
{
get
{
if (m_recacheWanted && Value != null)
return true;
else return m_entries.Count > 0;
}
}
internal IDictionary RefIDictionary;
internal AltIDictionary RefAltIDictionary;
internal Type m_typeOfKeys;
internal Type m_typeofValues;
internal readonly List<KeyValuePair<CachePaired, CachePaired>> m_entries
= new List<KeyValuePair<CachePaired, CachePaired>>();
internal readonly KeyValuePair<CachePaired, CachePaired>[] m_displayedEntries
= new KeyValuePair<CachePaired, CachePaired>[ConfigManager.Default_Page_Limit.Value];
internal bool m_recacheWanted = true;
public override void OnDestroy()
{
base.OnDestroy();
}
public override void OnValueUpdated()
{
RefIDictionary = Value as IDictionary;
if (RefIDictionary == null)
{
try { RefAltIDictionary = Value.TryCast<AltIDictionary>(); }
catch { }
}
if (m_subContentParent.activeSelf)
{
GetCacheEntries();
RefreshDisplay();
}
else
m_recacheWanted = true;
base.OnValueUpdated();
}
internal void OnPageTurned()
{
RefreshDisplay();
}
public override void RefreshUIForValue()
{
GetDefaultLabel();
if (Value != null)
{
string count = "?";
if (m_recacheWanted && RefIDictionary != null)
count = RefIDictionary.Count.ToString();
else if (!m_recacheWanted)
count = m_entries.Count.ToString();
m_baseLabel.text = $"[{count}] {m_richValueType}";
}
else
{
m_baseLabel.text = DefaultLabel;
}
}
public void GetCacheEntries()
{
if (m_entries.Any())
{
// maybe improve this, probably could be more efficient i guess
foreach (var pair in m_entries)
{
pair.Key.Destroy();
pair.Value.Destroy();
}
m_entries.Clear();
}
if (RefIDictionary == null && Value != null)
RefIDictionary = RuntimeProvider.Instance.Reflection.EnumerateDictionary(Value, m_typeOfKeys, m_typeofValues);
if (RefIDictionary != null)
{
int index = 0;
foreach (var key in RefIDictionary.Keys)
{
var value = RefIDictionary[key];
var cacheKey = new CachePaired(index, this, this.RefIDictionary, PairTypes.Key, m_listContent);
cacheKey.CreateIValue(key, this.m_typeOfKeys);
cacheKey.Disable();
var cacheValue = new CachePaired(index, this, this.RefIDictionary, PairTypes.Value, m_listContent);
cacheValue.CreateIValue(value, this.m_typeofValues);
cacheValue.Disable();
//holder.SetActive(false);
m_entries.Add(new KeyValuePair<CachePaired, CachePaired>(cacheKey, cacheValue));
index++;
}
}
RefreshDisplay();
}
public void RefreshDisplay()
{
//var entries = m_entries;
//m_pageHandler.ListCount = entries.Count;
//
//for (int i = 0; i < m_displayedEntries.Length; i++)
//{
// var entry = m_displayedEntries[i];
// if (entry.Key != null && entry.Value != null)
// {
// //m_rowHolders[i].SetActive(false);
// entry.Key.Disable();
// entry.Value.Disable();
// }
// else
// break;
//}
//
//if (entries.Count < 1)
// return;
//
//foreach (var itemIndex in m_pageHandler)
//{
// if (itemIndex >= entries.Count)
// break;
//
// var entry = entries[itemIndex];
// m_displayedEntries[itemIndex - m_pageHandler.StartIndex] = entry;
//
// //m_rowHolders[itemIndex].SetActive(true);
// entry.Key.Enable();
// entry.Value.Enable();
//}
//
////UpdateSubcontentHeight();
}
internal override void OnToggleSubcontent(bool active)
{
base.OnToggleSubcontent(active);
if (active && m_recacheWanted)
{
m_recacheWanted = false;
GetCacheEntries();
RefreshUIForValue();
}
RefreshDisplay();
}
internal GameObject m_listContent;
internal LayoutElement m_listLayout;
// internal PageHandler m_pageHandler;
public override void ConstructUI(GameObject parent, GameObject subGroup)
{
base.ConstructUI(parent, subGroup);
}
public override void ConstructSubcontent()
{
base.ConstructSubcontent();
//m_pageHandler = new PageHandler(null);
//m_pageHandler.ConstructUI(m_subContentParent);
//m_pageHandler.OnPageChanged += OnPageTurned;
m_listContent = UIFactory.CreateVerticalGroup(m_subContentParent, "DictionaryContent", true, true, true, true, 2, new Vector4(5,5,5,5),
new Color(0.08f, 0.08f, 0.08f));
var scrollRect = m_listContent.GetComponent<RectTransform>();
scrollRect.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, 0);
m_listLayout = Owner.UIRoot.GetComponent<LayoutElement>();
m_listLayout.minHeight = 25;
m_listLayout.flexibleHeight = 0;
Owner.m_mainRect.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, 25);
var contentFitter = m_listContent.AddComponent<ContentSizeFitter>();
contentFitter.horizontalFit = ContentSizeFitter.FitMode.Unconstrained;
contentFitter.verticalFit = ContentSizeFitter.FitMode.PreferredSize;
}
}
}

View File

@ -1,163 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using UnityEngine.UI;
using UnityExplorer.UI;
namespace UnityExplorer.UI.InteractiveValues
{
public class InteractiveEnum : InteractiveValue
{
internal static Dictionary<Type, KeyValuePair<int,string>[]> s_enumNamesCache = new Dictionary<Type, KeyValuePair<int, string>[]>();
public InteractiveEnum(object value, Type valueType) : base(value, valueType)
{
GetNames();
}
public override bool HasSubContent => true;
public override bool SubContentWanted => Owner.CanWrite;
public override bool WantInspectBtn => false;
internal KeyValuePair<int,string>[] m_values = new KeyValuePair<int, string>[0];
internal Type m_lastEnumType;
internal void GetNames()
{
var type = Value?.GetType() ?? FallbackType;
if (m_lastEnumType == type)
return;
m_lastEnumType = type;
if (m_subContentConstructed)
{
DestroySubContent();
}
if (!s_enumNamesCache.ContainsKey(type))
{
// using GetValues not GetNames, to catch instances of weird enums (eg CameraClearFlags)
var values = Enum.GetValues(type);
var list = new List<KeyValuePair<int, string>>();
var set = new HashSet<string>();
foreach (var value in values)
{
var name = value.ToString();
if (set.Contains(name))
continue;
set.Add(name);
var backingType = Enum.GetUnderlyingType(type);
int intValue;
try
{
// this approach is necessary, a simple '(int)value' is not sufficient.
var unbox = Convert.ChangeType(value, backingType);
intValue = (int)Convert.ChangeType(unbox, typeof(int));
}
catch (Exception ex)
{
ExplorerCore.LogWarning("[InteractiveEnum] Could not Unbox underlying type " + backingType.Name + " from " + type.FullName);
ExplorerCore.Log(ex.ToString());
continue;
}
list.Add(new KeyValuePair<int, string>(intValue, name));
}
s_enumNamesCache.Add(type, list.ToArray());
}
m_values = s_enumNamesCache[type];
}
public override void OnValueUpdated()
{
GetNames();
base.OnValueUpdated();
}
public override void RefreshUIForValue()
{
base.RefreshUIForValue();
if (m_subContentConstructed && !(this is InteractiveFlags))
{
m_dropdownText.text = Value?.ToString() ?? "<no value set>";
}
}
internal override void OnToggleSubcontent(bool toggle)
{
base.OnToggleSubcontent(toggle);
RefreshUIForValue();
}
private void SetValueFromDropdown()
{
var type = Value?.GetType() ?? FallbackType;
var index = m_dropdown.value;
var value = Enum.Parse(type, s_enumNamesCache[type][index].Value);
if (value != null)
{
Value = value;
Owner.SetValue();
RefreshUIForValue();
}
}
internal Dropdown m_dropdown;
internal Text m_dropdownText;
public override void ConstructUI(GameObject parent, GameObject subGroup)
{
base.ConstructUI(parent, subGroup);
}
public override void ConstructSubcontent()
{
base.ConstructSubcontent();
if (Owner.CanWrite)
{
var groupObj = UIFactory.CreateHorizontalGroup(m_subContentParent, "InteractiveEnumGroup", false, true, true, true, 5,
new Vector4(3,3,3,3),new Color(1, 1, 1, 0));
// apply button
var apply = UIFactory.CreateButton(groupObj, "ApplyButton", "Apply", SetValueFromDropdown, new Color(0.3f, 0.3f, 0.3f));
UIFactory.SetLayoutElement(apply.gameObject, minHeight: 25, minWidth: 50);
// dropdown
var dropdownObj = UIFactory.CreateDropdown(groupObj, out m_dropdown, "", 14, null);
UIFactory.SetLayoutElement(dropdownObj, minWidth: 150, minHeight: 25, flexibleWidth: 120);
foreach (var kvp in m_values)
{
m_dropdown.options.Add(new Dropdown.OptionData
{
text = $"{kvp.Key}: {kvp.Value}"
});
}
m_dropdownText = m_dropdown.transform.Find("Label").GetComponent<Text>();
}
}
}
}

View File

@ -1,245 +0,0 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using UnityEngine;
using UnityEngine.UI;
using UnityExplorer.Core;
using UnityExplorer.Core.Config;
using UnityExplorer.UI;
using UnityExplorer.UI.CacheObject;
using UnityExplorer.UI.Utility;
using UnityExplorer.UI.Widgets;
namespace UnityExplorer.UI.InteractiveValues
{
public class InteractiveEnumerable : InteractiveValue, IPoolDataSource
{
// IPoolDataSource
public ScrollPool ScrollPool;
public GameObject InactiveHolder;
internal LayoutElement listLayout;
public int ItemCount => m_entries?.Count ?? 0;
public void SetCell(ICell icell, int index)
{
var cell = icell as CellViewHolder;
if (index < 0 || index >= ItemCount)
{
var existing = cell.DisableContent();
if (existing)
existing.transform.SetParent(InactiveHolder.transform, false);
return;
}
var cache = m_entries[index];
cache.Enable();
var prev = cell.SetContent(cache.UIRoot);
if (prev)
prev.transform.SetParent(InactiveHolder.transform, false);
}
public void DisableCell(ICell cell, int index)
{
var content = (cell as CellViewHolder).DisableContent();
if (content)
content.transform.SetParent(InactiveHolder.transform, false);
}
//public void SetCell(ICell cell, int index)
//{
// var root = (cell as CellViewHolder).UIRoot;
// if (index < 0 || index >= ItemCount)
// {
// DisableContent(root);
// cell.Disable();
// return;
// }
// var cache = m_entries[index];
// cache.Enable();
// var content = cache.UIRoot;
// if (content.transform.parent.ReferenceEqual(root.transform))
// return;
// DisableContent(root);
// content.transform.SetParent(root.transform, false);
//}
//public void DisableCell(ICell cell, int index)
//{
// var root = (cell as CellViewHolder).UIRoot;
// DisableContent(root);
// cell.Disable();
//}
//private void DisableContent(GameObject cellRoot)
//{
// if (cellRoot.transform.childCount > 0 && cellRoot.transform.GetChild(0) is Transform existing)
// existing.transform.SetParent(InactiveHolder.transform, false);
//}
public ICell CreateCell(RectTransform cellTransform) => new CellViewHolder(cellTransform.gameObject);
public int GetRealIndexOfTempIndex(int tempIndex) => throw new NotImplementedException("Filtering not supported");
// InteractiveEnumerable
public InteractiveEnumerable(object value, Type valueType) : base(value, valueType)
{
if (valueType.IsGenericType)
m_baseEntryType = valueType.GetGenericArguments()[0];
else
m_baseEntryType = typeof(object);
}
public override bool WantInspectBtn => false;
public override bool HasSubContent => true;
public override bool SubContentWanted
{
get
{
if (m_recacheWanted && Value != null)
return true;
else return m_entries.Count > 0;
}
}
internal IEnumerable RefIEnumerable;
internal IList RefIList;
internal readonly Type m_baseEntryType;
internal readonly List<CacheEnumerated> m_entries = new List<CacheEnumerated>();
internal readonly CacheEnumerated[] m_displayedEntries = new CacheEnumerated[ConfigManager.Default_Page_Limit.Value];
internal bool m_recacheWanted = true;
public override void OnValueUpdated()
{
RefIEnumerable = Value as IEnumerable;
RefIList = Value as IList;
if (m_subContentParent && m_subContentParent.activeSelf)
{
ToggleSubcontent();
//GetCacheEntries();
//RefreshDisplay();
}
m_recacheWanted = true;
base.OnValueUpdated();
}
public override void OnException(CacheMember member)
{
base.OnException(member);
}
public override void RefreshUIForValue()
{
GetDefaultLabel();
if (Value != null)
{
string count = "?";
if (m_recacheWanted && RefIList != null)
count = RefIList.Count.ToString();
else if (!m_recacheWanted)
count = m_entries.Count.ToString();
m_baseLabel.text = $"[{count}] {m_richValueType}";
}
else
{
m_baseLabel.text = DefaultLabel;
}
}
public void GetCacheEntries()
{
if (m_entries.Any())
{
foreach (var entry in m_entries)
entry.Destroy();
m_entries.Clear();
}
if (RefIEnumerable == null && Value != null)
RefIEnumerable = RuntimeProvider.Instance.Reflection.EnumerateEnumerable(Value);
if (RefIEnumerable != null)
{
int index = 0;
foreach (var entry in RefIEnumerable)
{
var cache = new CacheEnumerated(index, this, RefIList, this.InactiveHolder);
cache.CreateIValue(entry, m_baseEntryType);
m_entries.Add(cache);
cache.Disable();
index++;
}
}
RefreshDisplay();
}
public void RefreshDisplay()
{
ScrollPool.RefreshCells(true);
listLayout.minHeight = Math.Min(500f, m_entries.Count * 32f);
}
internal override void OnToggleSubcontent(bool active)
{
base.OnToggleSubcontent(active);
if (active && m_recacheWanted)
{
m_recacheWanted = false;
GetCacheEntries();
RefreshUIForValue();
}
RefreshDisplay();
}
public override void ConstructUI(GameObject parent, GameObject subGroup)
{
base.ConstructUI(parent, subGroup);
InactiveHolder = new GameObject("InactiveHolder");
InactiveHolder.transform.SetParent(parent.transform, false);
InactiveHolder.SetActive(false);
}
public override void ConstructSubcontent()
{
base.ConstructSubcontent();
ScrollPool = UIFactory.CreateScrollPool(m_subContentParent, "ListEntries", out GameObject scrollRoot, out GameObject scrollContent,
new Color(0.05f, 0.05f, 0.05f));
listLayout = scrollRoot.AddComponent<LayoutElement>();
var proto = CellViewHolder.CreatePrototypeCell(scrollRoot);
proto.sizeDelta = new Vector2(100, 30);
ScrollPool.Initialize(this, proto);
}
}
}

View File

@ -1,125 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using UnityEngine.UI;
using UnityExplorer.UI;
namespace UnityExplorer.UI.InteractiveValues
{
public class InteractiveFlags : InteractiveEnum
{
public InteractiveFlags(object value, Type valueType) : base(value, valueType)
{
m_toggles = new Toggle[m_values.Length];
m_enabledFlags = new bool[m_values.Length];
}
public override bool HasSubContent => true;
public override bool SubContentWanted => Owner.CanWrite;
public override bool WantInspectBtn => false;
internal bool[] m_enabledFlags;
internal Toggle[] m_toggles;
public override void OnValueUpdated()
{
if (Owner.CanWrite)
{
var enabledNames = new List<string>();
var enabled = Value?.ToString().Split(',').Select(it => it.Trim());
if (enabled != null)
enabledNames.AddRange(enabled);
for (int i = 0; i < m_values.Length; i++)
m_enabledFlags[i] = enabledNames.Contains(m_values[i].Value);
}
base.OnValueUpdated();
}
public override void RefreshUIForValue()
{
GetDefaultLabel();
m_baseLabel.text = DefaultLabel;
base.RefreshUIForValue();
if (m_subContentConstructed)
{
for (int i = 0; i < m_values.Length; i++)
{
var toggle = m_toggles[i];
if (toggle.isOn != m_enabledFlags[i])
toggle.isOn = m_enabledFlags[i];
}
}
}
private void SetValueFromToggles()
{
string val = "";
for (int i = 0; i < m_values.Length; i++)
{
if (m_enabledFlags[i])
{
if (val != "") val += ", ";
val += m_values[i].Value;
}
}
var type = Value?.GetType() ?? FallbackType;
Value = Enum.Parse(type, val);
RefreshUIForValue();
Owner.SetValue();
}
internal override void OnToggleSubcontent(bool toggle)
{
base.OnToggleSubcontent(toggle);
RefreshUIForValue();
}
public override void ConstructUI(GameObject parent, GameObject subGroup)
{
base.ConstructUI(parent, subGroup);
}
public override void ConstructSubcontent()
{
m_subContentConstructed = true;
if (Owner.CanWrite)
{
var groupObj = UIFactory.CreateVerticalGroup(m_subContentParent, "InteractiveFlagsContent", false, true, true, true, 5,
new Vector4(3,3,3,3), new Color(1, 1, 1, 0));
// apply button
var apply = UIFactory.CreateButton(groupObj, "ApplyButton", "Apply", SetValueFromToggles, new Color(0.3f, 0.3f, 0.3f));
UIFactory.SetLayoutElement(apply.gameObject, minWidth: 50, minHeight: 25);
// toggles
for (int i = 0; i < m_values.Length; i++)
AddToggle(i, groupObj);
}
}
internal void AddToggle(int index, GameObject groupObj)
{
var value = m_values[index];
var toggleObj = UIFactory.CreateToggle(groupObj, "FlagToggle", out Toggle toggle, out Text text, new Color(0.1f, 0.1f, 0.1f));
UIFactory.SetLayoutElement(toggleObj, minWidth: 100, flexibleWidth: 2000, minHeight: 25);
m_toggles[index] = toggle;
toggle.onValueChanged.AddListener((bool val) => { m_enabledFlags[index] = val; });
text.text = $"{value.Key}: {value.Value}";
}
}
}

View File

@ -1,203 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using UnityEngine.UI;
using System.Reflection;
namespace UnityExplorer.UI.InteractiveValues
{
// Class for supporting any "float struct" (ie Vector, Rect, etc).
// Supports any struct where all the public instance fields are floats (or types assignable to float)
public class StructInfo
{
public string[] FieldNames { get; }
private readonly FieldInfo[] m_fields;
public StructInfo(Type type)
{
m_fields = type.GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public)
.Where(it => !it.IsLiteral)
.ToArray();
FieldNames = m_fields.Select(it => it.Name)
.ToArray();
}
public object SetValue(ref object instance, int fieldIndex, float val)
{
m_fields[fieldIndex].SetValue(instance, val);
return instance;
}
public float GetValue(object instance, int fieldIndex)
=> (float)m_fields[fieldIndex].GetValue(instance);
public void RefreshUI(InputField[] inputs, object instance)
{
try
{
for (int i = 0; i < m_fields.Length; i++)
{
var field = m_fields[i];
float val = (float)field.GetValue(instance);
inputs[i].text = val.ToString();
}
}
catch (Exception ex)
{
ExplorerCore.Log(ex);
}
}
}
public class InteractiveFloatStruct : InteractiveValue
{
private static readonly Dictionary<string, bool> _typeSupportCache = new Dictionary<string, bool>();
public static bool IsTypeSupported(Type type)
{
if (!type.IsValueType)
return false;
if (string.IsNullOrEmpty(type.AssemblyQualifiedName))
return false;
if (_typeSupportCache.TryGetValue(type.AssemblyQualifiedName, out bool ret))
return ret;
if (type.FullName == "System.Void")
return false;
ret = true;
var fields = type.GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
foreach (var field in fields)
{
if (field.IsLiteral)
continue;
if (!typeof(float).IsAssignableFrom(field.FieldType))
{
ret = false;
break;
}
}
_typeSupportCache.Add(type.AssemblyQualifiedName, ret);
return ret;
}
//~~~~~~~~~ Instance ~~~~~~~~~~
public InteractiveFloatStruct(object value, Type valueType) : base(value, valueType) { }
public override bool HasSubContent => true;
public override bool SubContentWanted => true;
public StructInfo StructInfo;
public override void RefreshUIForValue()
{
InitializeStructInfo();
base.RefreshUIForValue();
if (m_subContentConstructed)
StructInfo.RefreshUI(m_inputs, this.Value);
}
internal override void OnToggleSubcontent(bool toggle)
{
InitializeStructInfo();
base.OnToggleSubcontent(toggle);
StructInfo.RefreshUI(m_inputs, this.Value);
}
internal Type m_lastStructType;
internal void InitializeStructInfo()
{
var type = Value?.GetType() ?? FallbackType;
if (StructInfo != null && type == m_lastStructType)
return;
if (StructInfo != null && m_subContentConstructed)
DestroySubContent();
m_lastStructType = type;
StructInfo = new StructInfo(type);
if (m_subContentParent.activeSelf)
ConstructSubcontent();
}
#region UI CONSTRUCTION
internal InputField[] m_inputs;
public override void ConstructUI(GameObject parent, GameObject subGroup)
{
base.ConstructUI(parent, subGroup);
}
public override void ConstructSubcontent()
{
base.ConstructSubcontent();
if (StructInfo == null)
{
ExplorerCore.LogWarning("Setting up subcontent but structinfo is null");
return;
}
var editorContainer = UIFactory.CreateVerticalGroup(m_subContentParent, "EditorContent", false, true, true, true, 2, new Vector4(4, 4, 4, 4),
new Color(0.08f, 0.08f, 0.08f));
m_inputs = new InputField[StructInfo.FieldNames.Length];
for (int i = 0; i < StructInfo.FieldNames.Length; i++)
AddEditorRow(i, editorContainer);
RefreshUIForValue();
}
internal void AddEditorRow(int index, GameObject groupObj)
{
try
{
var row = UIFactory.CreateHorizontalGroup(groupObj, "EditorRow", false, true, true, true, 5, default, new Color(1, 1, 1, 0));
string name = StructInfo.FieldNames[index];
var label = UIFactory.CreateLabel(row, "RowLabel", $"{name}:", TextAnchor.MiddleRight, Color.cyan);
UIFactory.SetLayoutElement(label.gameObject, minWidth: 30, flexibleWidth: 0, minHeight: 25);
var inputFieldObj = UIFactory.CreateInputField(row, "InputField", "...", out InputField inputField, 14, 3, 1);
UIFactory.SetLayoutElement(inputFieldObj, minWidth: 120, minHeight: 25, flexibleWidth: 0);
m_inputs[index] = inputField;
inputField.onValueChanged.AddListener((string val) =>
{
try
{
float f = float.Parse(val);
Value = StructInfo.SetValue(ref this.Value, index, f);
Owner.SetValue();
}
catch { }
});
}
catch (Exception ex)
{
ExplorerCore.Log(ex);
}
}
#endregion
}
}

View File

@ -1,115 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using UnityEngine;
using UnityEngine.UI;
using UnityExplorer.UI;
using UnityExplorer.Core;
using UnityExplorer.UI.Utility;
using UnityExplorer.UI.CacheObject;
namespace UnityExplorer.UI.InteractiveValues
{
public class InteractiveNumber : InteractiveValue
{
public InteractiveNumber(object value, Type valueType) : base(value, valueType) { }
public override bool HasSubContent => false;
public override bool SubContentWanted => false;
public override bool WantInspectBtn => false;
public override void OnValueUpdated()
{
base.OnValueUpdated();
}
public override void OnException(CacheMember member)
{
base.OnException(member);
if (m_valueInput.gameObject.activeSelf)
m_valueInput.gameObject.SetActive(false);
if (Owner.CanWrite)
{
if (m_applyBtn.gameObject.activeSelf)
m_applyBtn.gameObject.SetActive(false);
}
}
public override void RefreshUIForValue()
{
if (!Owner.HasEvaluated)
{
GetDefaultLabel();
m_baseLabel.text = DefaultLabel;
return;
}
m_baseLabel.text = SignatureHighlighter.ParseFullSyntax(FallbackType, false);
m_valueInput.text = Value.ToString();
var type = Value.GetType();
if (type == typeof(float)
|| type == typeof(double)
|| type == typeof(decimal))
{
m_valueInput.characterValidation = InputField.CharacterValidation.Decimal;
}
else
{
m_valueInput.characterValidation = InputField.CharacterValidation.Integer;
}
if (Owner.CanWrite)
{
if (!m_applyBtn.gameObject.activeSelf)
m_applyBtn.gameObject.SetActive(true);
}
if (!m_valueInput.gameObject.activeSelf)
m_valueInput.gameObject.SetActive(true);
}
public MethodInfo ParseMethod => m_parseMethod ?? (m_parseMethod = Value.GetType().GetMethod("Parse", new Type[] { typeof(string) }));
private MethodInfo m_parseMethod;
internal void OnApplyClicked()
{
try
{
Value = ParseMethod.Invoke(null, new object[] { m_valueInput.text });
Owner.SetValue();
RefreshUIForValue();
}
catch (Exception e)
{
ExplorerCore.LogWarning("Could not parse input! " + ReflectionUtility.ReflectionExToString(e, true));
}
}
internal InputField m_valueInput;
internal Button m_applyBtn;
public override void ConstructUI(GameObject parent, GameObject subGroup)
{
base.ConstructUI(parent, subGroup);
var labelLayout = m_baseLabel.gameObject.GetComponent<LayoutElement>();
labelLayout.minWidth = 50;
labelLayout.flexibleWidth = 0;
var inputObj = UIFactory.CreateInputField(m_mainContent, "InteractiveNumberInput", "...", out m_valueInput);
UIFactory.SetLayoutElement(inputObj, minWidth: 120, minHeight: 25, flexibleWidth: 0);
m_valueInput.gameObject.SetActive(false);
if (Owner.CanWrite)
{
m_applyBtn = UIFactory.CreateButton(m_mainContent, "ApplyButton", "Apply", OnApplyClicked, new Color(0.2f, 0.2f, 0.2f));
UIFactory.SetLayoutElement(m_applyBtn.gameObject, minWidth: 50, minHeight: 25, flexibleWidth: 0);
}
}
}
}

View File

@ -1,186 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using UnityEngine;
using UnityEngine.UI;
using UnityExplorer.UI;
using UnityExplorer.UI.Utility;
using UnityExplorer.UI.CacheObject;
using UnityExplorer.Core.Runtime;
namespace UnityExplorer.UI.InteractiveValues
{
public class InteractiveString : InteractiveValue
{
public InteractiveString(object value, Type valueType) : base(value, valueType) { }
public override bool HasSubContent => true;
public override bool SubContentWanted => true;
public override bool WantInspectBtn => false;
public override void OnValueUpdated()
{
if (!(Value is string) && Value != null)
Value = RuntimeProvider.Instance.Reflection.UnboxString(Value);
base.OnValueUpdated();
}
public override void OnException(CacheMember member)
{
base.OnException(member);
if (m_subContentConstructed && m_hiddenObj.gameObject.activeSelf)
m_hiddenObj.gameObject.SetActive(false);
m_labelLayout.minWidth = 200;
m_labelLayout.flexibleWidth = 5000;
}
public override void RefreshUIForValue()
{
GetDefaultLabel(false);
if (!Owner.HasEvaluated)
{
m_baseLabel.text = DefaultLabel;
return;
}
m_baseLabel.text = m_richValueType;
if (m_subContentConstructed)
{
if (!m_hiddenObj.gameObject.activeSelf)
m_hiddenObj.gameObject.SetActive(true);
}
if (!string.IsNullOrEmpty((string)Value))
{
var toString = (string)Value;
if (toString.Length > 15000)
toString = toString.Substring(0, 15000);
m_readonlyInput.text = toString;
if (m_subContentConstructed)
{
m_valueInput.text = toString;
m_placeholderText.text = toString;
}
}
else
{
string s = Value == null
? "null"
: "empty";
m_readonlyInput.text = $"<i><color=grey>{s}</color></i>";
if (m_subContentConstructed)
{
m_valueInput.text = "";
m_placeholderText.text = s;
}
}
m_labelLayout.minWidth = 50;
m_labelLayout.flexibleWidth = 0;
}
internal void SetValueFromInput()
{
Value = m_valueInput.text;
if (!typeof(string).IsAssignableFrom(Owner.FallbackType))
ReflectionProvider.Instance.BoxStringToType(ref Value, Owner.FallbackType);
Owner.SetValue();
// revert back to string now
OnValueUpdated();
RefreshUIForValue();
}
// for the default label
internal LayoutElement m_labelLayout;
//internal InputField m_readonlyInput;
internal Text m_readonlyInput;
// for input
internal InputField m_valueInput;
internal GameObject m_hiddenObj;
internal Text m_placeholderText;
public override void ConstructUI(GameObject parent, GameObject subGroup)
{
base.ConstructUI(parent, subGroup);
GetDefaultLabel(false);
m_richValueType = SignatureHighlighter.ParseFullSyntax(FallbackType, false);
m_labelLayout = m_baseLabel.gameObject.GetComponent<LayoutElement>();
m_readonlyInput = UIFactory.CreateLabel(m_mainContent, "ReadonlyLabel", "", TextAnchor.MiddleLeft);
m_readonlyInput.horizontalOverflow = HorizontalWrapMode.Overflow;
var testFitter = m_readonlyInput.gameObject.AddComponent<ContentSizeFitter>();
testFitter.verticalFit = ContentSizeFitter.FitMode.MinSize;
UIFactory.SetLayoutElement(m_readonlyInput.gameObject, minHeight: 25, preferredHeight: 25, flexibleHeight: 0);
}
public override void ConstructSubcontent()
{
base.ConstructSubcontent();
var groupObj = UIFactory.CreateVerticalGroup(m_subContentParent, "SubContent", false, false, true, true, 4, new Vector4(3,3,3,3),
new Color(1, 1, 1, 0));
m_hiddenObj = UIFactory.CreateLabel(groupObj, "HiddenLabel", "", TextAnchor.MiddleLeft).gameObject;
m_hiddenObj.SetActive(false);
var hiddenText = m_hiddenObj.GetComponent<Text>();
hiddenText.color = Color.clear;
hiddenText.fontSize = 14;
hiddenText.raycastTarget = false;
hiddenText.supportRichText = false;
var hiddenFitter = m_hiddenObj.AddComponent<ContentSizeFitter>();
hiddenFitter.verticalFit = ContentSizeFitter.FitMode.PreferredSize;
UIFactory.SetLayoutElement(m_hiddenObj, minHeight: 25, flexibleHeight: 500, minWidth: 250, flexibleWidth: 9000);
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(m_hiddenObj, true, true, true, true);
var inputObj = UIFactory.CreateInputField(m_hiddenObj, "StringInputField", "...", out m_valueInput, 14, 3);
UIFactory.SetLayoutElement(inputObj, minWidth: 120, minHeight: 25, flexibleWidth: 5000, flexibleHeight: 5000);
m_valueInput.lineType = InputField.LineType.MultiLineNewline;
m_placeholderText = m_valueInput.placeholder.GetComponent<Text>();
m_placeholderText.supportRichText = false;
m_valueInput.textComponent.supportRichText = false;
m_valueInput.onValueChanged.AddListener((string val) =>
{
hiddenText.text = val ?? "";
LayoutRebuilder.ForceRebuildLayoutImmediate(Owner.m_mainRect);
});
if (Owner.CanWrite)
{
var apply = UIFactory.CreateButton(groupObj, "ApplyButton", "Apply", SetValueFromInput, new Color(0.2f, 0.2f, 0.2f));
UIFactory.SetLayoutElement(apply.gameObject, minWidth: 50, minHeight: 25, flexibleWidth: 0);
}
else
{
m_valueInput.readOnly = true;
}
RefreshUIForValue();
}
}
}

View File

@ -1,355 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
using UnityExplorer.Core;
using UnityExplorer.Core.Runtime;
using UnityExplorer.UI;
using UnityExplorer.UI.Utility;
using UnityExplorer.UI.CacheObject;
using UnityExplorer.UI.Inspectors;
namespace UnityExplorer.UI.InteractiveValues
{
public class InteractiveValue
{
/// <summary>
/// Get the <see cref="InteractiveValue"/> subclass which supports the provided <paramref name="type"/>.
/// </summary>
/// <param name="type">The <see cref="Type"/> which you want the <see cref="InteractiveValue"/> Type for.</param>
/// <returns>The best subclass of <see cref="InteractiveValue"/> which supports the provided <paramref name="type"/>.</returns>
public static Type GetIValueForType(Type type)
{
// rather ugly but I couldn't think of a cleaner way that was worth it.
// switch-case doesn't really work here.
// arbitrarily check some types, fastest methods first.
if (type == typeof(bool))
return typeof(InteractiveBool);
// if type is primitive then it must be a number if its not a bool. Also check for decimal.
else if (type.IsPrimitive || type == typeof(decimal))
return typeof(InteractiveNumber);
// check for strings
else if (type == typeof(string))
return typeof(InteractiveString);
// check for enum/flags
else if (typeof(Enum).IsAssignableFrom(type))
{
// NET 3.5 doesn't have "GetCustomAttribute", gotta use the multiple version.
if (type.GetCustomAttributes(typeof(FlagsAttribute), true) is object[] fa && fa.Any())
return typeof(InteractiveFlags);
else
return typeof(InteractiveEnum);
}
// check for unity struct types
else if (typeof(Color).IsAssignableFrom(type))
return typeof(InteractiveColor);
else if (InteractiveFloatStruct.IsTypeSupported(type))
return typeof(InteractiveFloatStruct);
// check Transform, force InteractiveValue so they dont become InteractiveEnumerables.
else if (typeof(Transform).IsAssignableFrom(type))
return typeof(InteractiveValue);
// check Dictionaries before Enumerables
else if (ReflectionUtility.IsDictionary(type))
return typeof(InteractiveDictionary);
// finally check for Enumerables
else if (ReflectionUtility.IsEnumerable(type))
return typeof(InteractiveEnumerable);
// fallback to default
else
return typeof(InteractiveValue);
}
public static InteractiveValue Create(object value, Type fallbackType)
{
var type = ReflectionUtility.GetActualType(value) ?? fallbackType;
var iType = GetIValueForType(type);
return (InteractiveValue)Activator.CreateInstance(iType, new object[] { value, type });
}
// ~~~~~~~~~ Instance ~~~~~~~~~
public InteractiveValue(object value, Type valueType)
{
this.Value = value;
this.FallbackType = valueType;
}
public CacheObjectBase Owner;
public object Value;
public readonly Type FallbackType;
public virtual bool HasSubContent => false;
public virtual bool SubContentWanted => false;
public virtual bool WantInspectBtn => true;
public string DefaultLabel => m_defaultLabel ?? GetDefaultLabel();
internal string m_defaultLabel;
internal string m_richValueType;
public bool m_UIConstructed;
public virtual void OnDestroy()
{
if (this.m_mainContent)
{
m_mainContent.transform.SetParent(null, false);
m_mainContent.SetActive(false);
GameObject.Destroy(this.m_mainContent.gameObject);
}
DestroySubContent();
}
public virtual void DestroySubContent()
{
if (this.m_subContentParent && HasSubContent)
{
for (int i = 0; i < this.m_subContentParent.transform.childCount; i++)
{
var child = m_subContentParent.transform.GetChild(i);
if (child)
GameObject.Destroy(child.gameObject);
}
}
m_subContentConstructed = false;
}
public virtual void OnValueUpdated()
{
if (!m_UIConstructed)
ConstructUI(m_mainContentParent, m_subContentParent);
if (Owner is CacheMember ownerMember && !string.IsNullOrEmpty(ownerMember.ReflectionException))
OnException(ownerMember);
else
RefreshUIForValue();
}
public virtual void OnException(CacheMember member)
{
if (m_UIConstructed)
m_baseLabel.text = "<color=red>" + member.ReflectionException + "</color>";
Value = null;
}
public virtual void RefreshUIForValue()
{
GetDefaultLabel();
m_baseLabel.text = DefaultLabel;
}
public void RefreshElementsAfterUpdate()
{
if (WantInspectBtn)
{
bool shouldShowInspect = !Value.IsNullOrDestroyed();
if (m_inspectButton.activeSelf != shouldShowInspect)
m_inspectButton.SetActive(shouldShowInspect);
}
bool subContentWanted = SubContentWanted;
if (Owner is CacheMember cm && (!cm.HasEvaluated || !string.IsNullOrEmpty(cm.ReflectionException)))
subContentWanted = false;
if (HasSubContent)
{
if (m_subExpandBtn.gameObject.activeSelf != subContentWanted)
m_subExpandBtn.gameObject.SetActive(subContentWanted);
if (!subContentWanted && m_subContentParent.activeSelf)
ToggleSubcontent();
}
}
public virtual void ConstructSubcontent()
{
Owner.CheckSubcontentCreation();
m_subContentConstructed = true;
}
public void ToggleSubcontent()
{
if (!this.m_subContentParent.activeSelf)
{
this.m_subContentParent.SetActive(true);
this.m_subContentParent.transform.SetAsLastSibling();
m_subExpandBtn.GetComponentInChildren<Text>().text = "▼";
}
else
{
this.m_subContentParent.SetActive(false);
m_subExpandBtn.GetComponentInChildren<Text>().text = "▲";
}
OnToggleSubcontent(m_subContentParent.activeSelf);
RefreshElementsAfterUpdate();
}
internal virtual void OnToggleSubcontent(bool toggle)
{
if (!m_subContentConstructed)
ConstructSubcontent();
}
internal MethodInfo m_toStringMethod;
internal MethodInfo m_toStringFormatMethod;
internal bool m_gotToStringMethods;
public string GetDefaultLabel(bool updateType = true)
{
var valueType = Value?.GetType() ?? this.FallbackType;
if (updateType)
m_richValueType = SignatureHighlighter.ParseFullSyntax(valueType, true);
if (!Owner.HasEvaluated)
return m_defaultLabel = $"<i><color=grey>Not yet evaluated</color> ({m_richValueType})</i>";
if (Value.IsNullOrDestroyed())
return m_defaultLabel = $"<color=grey>null</color> ({m_richValueType})";
string label;
// Two dirty fixes for TextAsset and EventSystem, which can have very long ToString results.
if (Value is TextAsset textAsset)
{
label = textAsset.text;
if (label.Length > 10)
label = $"{label.Substring(0, 10)}...";
label = $"\"{label}\" {textAsset.name} ({m_richValueType})";
}
else if (Value is EventSystem)
{
label = m_richValueType;
}
else // For everything else...
{
if (!m_gotToStringMethods)
{
m_gotToStringMethods = true;
m_toStringMethod = valueType.GetMethod("ToString", new Type[0]);
m_toStringFormatMethod = valueType.GetMethod("ToString", new Type[] { typeof(string) });
// test format method actually works
try
{
m_toStringFormatMethod.Invoke(Value, new object[] { "F3" });
}
catch
{
m_toStringFormatMethod = null;
}
}
string toString;
if (m_toStringFormatMethod != null)
toString = (string)m_toStringFormatMethod.Invoke(Value, new object[] { "F3" });
else
toString = (string)m_toStringMethod.Invoke(Value, new object[0]);
toString = toString ?? "";
string typeName = valueType.FullName;
if (typeName.StartsWith("Il2CppSystem."))
typeName = typeName.Substring(6, typeName.Length - 6);
toString = ReflectionProvider.Instance.ProcessTypeFullNameInString(valueType, toString, ref typeName);
// If the ToString is just the type name, use our syntax highlighted type name instead.
if (toString == typeName)
{
label = m_richValueType;
}
else // Otherwise, parse the result and put our highlighted name in.
{
if (toString.Length > 200)
toString = toString.Substring(0, 200) + "...";
label = toString;
var unityType = $"({valueType.FullName})";
if (Value is UnityEngine.Object && label.Contains(unityType))
label = label.Replace(unityType, $"({m_richValueType})");
else
label += $" ({m_richValueType})";
}
}
return m_defaultLabel = label;
}
#region UI CONSTRUCTION
internal GameObject m_mainContentParent;
internal GameObject m_subContentParent;
internal GameObject m_mainContent;
internal GameObject m_inspectButton;
internal Text m_baseLabel;
internal Button m_subExpandBtn;
internal bool m_subContentConstructed;
public virtual void ConstructUI(GameObject parent, GameObject subGroup)
{
m_UIConstructed = true;
//m_mainContent = UIFactory.CreateHorizontalGroup(parent, $"InteractiveValue_{this.GetType().Name}", false, false, true, true, 4, default,
// new Color(1, 1, 1, 0), TextAnchor.UpperLeft);
m_mainContent = UIFactory.CreateUIObject($"InteractiveValue_{this.GetType().Name}", parent);
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(m_mainContent, false, false, true, true, 4, 0, 0, 0, 0, TextAnchor.UpperLeft);
var mainRect = m_mainContent.GetComponent<RectTransform>();
mainRect.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, 25);
UIFactory.SetLayoutElement(m_mainContent, flexibleWidth: 9000, minWidth: 175, minHeight: 25, flexibleHeight: 0);
// subcontent expand button
if (HasSubContent)
{
m_subExpandBtn = UIFactory.CreateButton(m_mainContent, "ExpandSubcontentButton", "▲", ToggleSubcontent, new Color(1,1,1,0));
UIFactory.SetLayoutElement(m_subExpandBtn.gameObject, minHeight: 25, minWidth: 25, flexibleWidth: 0, flexibleHeight: 0);
}
// inspect button
var inspectBtn = UIFactory.CreateButton(m_mainContent,
"InspectButton",
"Inspect",
() =>
{
if (!Value.IsNullOrDestroyed(false))
InspectorManager.Inspect(this.Value, this.Owner);
},
new Color(0.3f, 0.3f, 0.3f, 0.2f));
m_inspectButton = inspectBtn.gameObject;
UIFactory.SetLayoutElement(m_inspectButton, minWidth: 60, minHeight: 25, flexibleWidth: 0, flexibleHeight: 0);
m_inspectButton.SetActive(false);
// value label
m_baseLabel = UIFactory.CreateLabel(m_mainContent, "ValueLabel", "", TextAnchor.MiddleLeft);
UIFactory.SetLayoutElement(m_baseLabel.gameObject, flexibleWidth: 9000, minHeight: 25);
m_subContentParent = subGroup;
}
#endregion
}
}

View File

@ -7,6 +7,7 @@ using UnityEngine.UI;
using UnityExplorer.Core.Search;
using UnityExplorer.UI.Inspectors;
using UnityExplorer.UI.Models;
using UnityExplorer.UI.ObjectPool;
using UnityExplorer.UI.Panels;
using UnityExplorer.UI.Utility;
using UnityExplorer.UI.Widgets.AutoComplete;
@ -28,7 +29,7 @@ namespace UnityExplorer.UI.Widgets
public ButtonListSource<object> dataHandler;
private ScrollPool resultsScrollPool;
private ScrollPool<ButtonCell> resultsScrollPool;
private List<object> currentResults = new List<object>();
public override GameObject UIRoot => uiRoot;
@ -90,7 +91,7 @@ namespace UnityExplorer.UI.Widgets
// Cache the syntax-highlighted text for each search result to reduce allocs.
private static readonly Dictionary<int, string> cachedCellTexts = new Dictionary<int, string>();
public void SetCell(ButtonCell<object> cell, int index)
public void SetCell(ButtonCell cell, int index)
{
if (!cachedCellTexts.ContainsKey(index))
{
@ -103,7 +104,7 @@ namespace UnityExplorer.UI.Widgets
cachedCellTexts.Add(index, text);
}
cell.buttonText.text = cachedCellTexts[index];
cell.Button.ButtonText.text = cachedCellTexts[index];
}
private void OnCellClicked(int dataIndex)
@ -192,8 +193,9 @@ namespace UnityExplorer.UI.Widgets
// Search button
var searchButton = UIFactory.CreateButton(uiRoot, "SearchButton", "Search", DoSearch);
UIFactory.SetLayoutElement(searchButton.gameObject, minHeight: 25, flexibleHeight: 0);
var searchButton = UIFactory.CreateButton(uiRoot, "SearchButton", "Search");
UIFactory.SetLayoutElement(searchButton.Button.gameObject, minHeight: 25, flexibleHeight: 0);
searchButton.OnClick += DoSearch;
// Results count label
@ -205,8 +207,12 @@ namespace UnityExplorer.UI.Widgets
// RESULTS SCROLL POOL
dataHandler = new ButtonListSource<object>(resultsScrollPool, GetEntries, SetCell, ShouldDisplayCell, OnCellClicked);
resultsScrollPool = UIFactory.CreateScrollPool(uiRoot, "ResultsList", out GameObject scrollObj, out GameObject scrollContent);
resultsScrollPool.Initialize(dataHandler, ButtonCell<object>.CreatePrototypeCell(uiRoot));
resultsScrollPool = UIFactory.CreateScrollPool<ButtonCell>(uiRoot, "ResultsList", out GameObject scrollObj, out GameObject scrollContent);
//if (!Pool<ButtonCell>.PrototypeObject)
// Pool<ButtonCell>.PrototypeObject = ButtonCell.CreatePrototypeCell(Pool<ButtonCell>.InactiveHolder).gameObject;
resultsScrollPool.Initialize(dataHandler);//, ButtonCell.CreatePrototypeCell(uiRoot));
UIFactory.SetLayoutElement(scrollObj, flexibleHeight: 9999);
}
}

View File

@ -159,8 +159,14 @@ namespace UnityExplorer.UI.Widgets
// Scene selector dropdown
var dropdownObj = UIFactory.CreateDropdown(toolbar, out sceneDropdown, "<notset>", 13, OnDropdownChanged);
UIFactory.SetLayoutElement(dropdownObj, minHeight: 25, flexibleHeight: 0);
var dropRow = UIFactory.CreateHorizontalGroup(toolbar, "DropdownRow", true, true, true, true, 5, default, new Color(1, 1, 1, 0));
UIFactory.SetLayoutElement(dropRow, minHeight: 25, flexibleWidth: 9999);
var dropLabel = UIFactory.CreateLabel(dropRow, "SelectorLabel", "Scene:", TextAnchor.MiddleLeft, Color.cyan, false, 15);
UIFactory.SetLayoutElement(dropLabel.gameObject, minHeight: 25, minWidth: 60, flexibleWidth: 0);
var dropdownObj = UIFactory.CreateDropdown(dropRow, out sceneDropdown, "<notset>", 13, OnDropdownChanged);
UIFactory.SetLayoutElement(dropdownObj, minHeight: 25, flexibleHeight: 0, flexibleWidth: 9999);
SceneHandler.Update();
PopulateSceneDropdown();
@ -183,8 +189,9 @@ namespace UnityExplorer.UI.Widgets
refreshRow = UIFactory.CreateHorizontalGroup(toolbar, "RefreshGroup", true, true, true, true, 2, new Vector4(2, 2, 2, 2));
UIFactory.SetLayoutElement(refreshRow, minHeight: 30, flexibleHeight: 0);
var refreshButton = UIFactory.CreateButton(refreshRow, "RefreshButton", "Update", ForceUpdate);
UIFactory.SetLayoutElement(refreshButton.gameObject, minWidth: 65, flexibleWidth: 0);
var refreshButton = UIFactory.CreateButton(refreshRow, "RefreshButton", "Update");
UIFactory.SetLayoutElement(refreshButton.Button.gameObject, minWidth: 65, flexibleWidth: 0);
refreshButton.OnClick += ForceUpdate;
var refreshToggle = UIFactory.CreateToggle(refreshRow, "RefreshToggle", out Toggle toggle, out Text text);
UIFactory.SetLayoutElement(refreshToggle, flexibleWidth: 9999);
@ -199,14 +206,14 @@ namespace UnityExplorer.UI.Widgets
// Transform Tree
var scrollPool = UIFactory.CreateScrollPool(m_uiRoot, "TransformTree", out GameObject scrollObj,
out GameObject scrollContent, new Color(0.15f, 0.15f, 0.15f));
var scrollPool = UIFactory.CreateScrollPool<TransformCell>(m_uiRoot, "TransformTree", out GameObject scrollObj,
out GameObject scrollContent, new Color(0.11f, 0.11f, 0.11f));
UIFactory.SetLayoutElement(scrollObj, flexibleHeight: 9999);
UIFactory.SetLayoutElement(scrollContent, flexibleHeight: 9999);
Tree = new TransformTree(scrollPool) { GetRootEntriesMethod = GetRootEntries };
Tree.Init();
Tree.RefreshData(true, true);
//scrollPool.Viewport.GetComponent<Mask>().enabled = false;
//UIRoot.GetComponent<Mask>().enabled = false;
@ -244,37 +251,39 @@ namespace UnityExplorer.UI.Widgets
var buttonRow = UIFactory.CreateHorizontalGroup(sceneLoaderObj, "LoadButtons", true, true, true, true, 4);
var loadButton = UIFactory.CreateButton(buttonRow, "LoadSceneButton", "Load (Single)", () =>
var loadButton = UIFactory.CreateButton(buttonRow, "LoadSceneButton", "Load (Single)", new Color(0.1f, 0.3f, 0.3f));
UIFactory.SetLayoutElement(loadButton.Button.gameObject, minHeight: 25, minWidth: 150);
loadButton.OnClick += () =>
{
TryLoadScene(LoadSceneMode.Single, allSceneDrop);
}, new Color(0.1f, 0.3f, 0.3f));
UIFactory.SetLayoutElement(loadButton.gameObject, minHeight: 25, minWidth: 150);
};
var loadAdditiveButton = UIFactory.CreateButton(buttonRow, "LoadSceneButton", "Load (Additive)", () =>
var loadAdditiveButton = UIFactory.CreateButton(buttonRow, "LoadSceneButton", "Load (Additive)", new Color(0.1f, 0.3f, 0.3f));
UIFactory.SetLayoutElement(loadAdditiveButton.Button.gameObject, minHeight: 25, minWidth: 150);
loadAdditiveButton.OnClick += () =>
{
TryLoadScene(LoadSceneMode.Additive, allSceneDrop);
}, new Color(0.1f, 0.3f, 0.3f));
UIFactory.SetLayoutElement(loadAdditiveButton.gameObject, minHeight: 25, minWidth: 150);
};
var disabledColor = new Color(0.24f, 0.24f, 0.24f);
RuntimeProvider.Instance.SetColorBlock(loadButton, disabled: disabledColor);
RuntimeProvider.Instance.SetColorBlock(loadAdditiveButton, disabled: disabledColor);
RuntimeProvider.Instance.SetColorBlock(loadButton.Button, disabled: disabledColor);
RuntimeProvider.Instance.SetColorBlock(loadAdditiveButton.Button, disabled: disabledColor);
loadButton.interactable = false;
loadAdditiveButton.interactable = false;
loadButton.Button.interactable = false;
loadAdditiveButton.Button.interactable = false;
allSceneDrop.onValueChanged.AddListener((int val) =>
{
var text = allSceneDrop.options[val].text;
if (text == DEFAULT_LOAD_TEXT)
{
loadButton.interactable = false;
loadAdditiveButton.interactable = false;
loadButton.Button.interactable = false;
loadAdditiveButton.Button.interactable = false;
}
else
{
loadButton.interactable = true;
loadAdditiveButton.interactable = true;
loadButton.Button.interactable = true;
loadAdditiveButton.Button.interactable = true;
}
});
}

View File

@ -1,83 +1,83 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using UnityEngine.UI;
//using System;
//using System.Collections.Generic;
//using System.Linq;
//using System.Text;
//using UnityEngine;
//using UnityEngine.UI;
namespace UnityExplorer.UI.Widgets
{
public class CellViewHolder : ICell
{
public CellViewHolder(GameObject uiRoot)
{
this.UIRoot = uiRoot;
this.Rect = uiRoot.GetComponent<RectTransform>();
m_enabled = uiRoot.activeSelf;
}
//namespace UnityExplorer.UI.Widgets
//{
// public class CellViewHolder : ICell
// {
// public CellViewHolder(GameObject uiRoot)
// {
// this.UIRoot = uiRoot;
// this.Rect = uiRoot.GetComponent<RectTransform>();
// m_enabled = uiRoot.activeSelf;
// }
public bool Enabled => m_enabled;
private bool m_enabled;
// public bool Enabled => m_enabled;
// private bool m_enabled;
public GameObject UIRoot { get; }
public RectTransform Rect { get; }
// public GameObject UIRoot { get; }
// public RectTransform Rect { get; }
private GameObject m_content;
// private GameObject m_content;
public GameObject SetContent(GameObject newContent)
{
var ret = m_content;
// public GameObject SetContent(GameObject newContent)
// {
// var ret = m_content;
if (ret && newContent && ret.ReferenceEqual(newContent))
return null;
// if (ret && newContent && ret.ReferenceEqual(newContent))
// return null;
newContent.transform.SetParent(this.UIRoot.transform, false);
(this as ICell).Enable();
// newContent.transform.SetParent(this.UIRoot.transform, false);
// (this as ICell).Enable();
m_content = newContent;
return ret;
}
// m_content = newContent;
// return ret;
// }
public GameObject DisableContent()
{
var ret = m_content;
(this as ICell).Disable();
return ret;
}
// public GameObject DisableContent()
// {
// var ret = m_content;
// (this as ICell).Disable();
// return ret;
// }
void ICell.Enable()
{
m_enabled = true;
UIRoot.SetActive(true);
}
// void ICell.Enable()
// {
// m_enabled = true;
// UIRoot.SetActive(true);
// }
void ICell.Disable()
{
m_enabled = false;
UIRoot.SetActive(false);
}
// void ICell.Disable()
// {
// m_enabled = false;
// UIRoot.SetActive(false);
// }
public static RectTransform CreatePrototypeCell(GameObject parent)
{
// using an image on the cell view holder is fine, we only need to make about 20-50 of these per pool.
var prototype = UIFactory.CreateVerticalGroup(parent, "PrototypeCell", true, true, true, true, 0, new Vector4(0, 0, 0, 0),
new Color(0.11f, 0.11f, 0.11f), TextAnchor.MiddleCenter);
// public static RectTransform CreatePrototypeCell(GameObject parent)
// {
// // using an image on the cell view holder is fine, we only need to make about 20-50 of these per pool.
// var prototype = UIFactory.CreateVerticalGroup(parent, "PrototypeCell", true, true, true, true, 0, new Vector4(0, 0, 0, 0),
// new Color(0.11f, 0.11f, 0.11f), TextAnchor.MiddleCenter);
var rect = prototype.GetComponent<RectTransform>();
rect.anchorMin = new Vector2(0, 1);
rect.anchorMax = new Vector2(0, 1);
rect.pivot = new Vector2(0.5f, 1);
rect.sizeDelta = new Vector2(100, 30);
// var rect = prototype.GetComponent<RectTransform>();
// rect.anchorMin = new Vector2(0, 1);
// rect.anchorMax = new Vector2(0, 1);
// rect.pivot = new Vector2(0.5f, 1);
// rect.sizeDelta = new Vector2(100, 30);
prototype.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize;
// prototype.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize;
var sepObj = UIFactory.CreateUIObject("separator", prototype);
sepObj.AddComponent<Image>().color = Color.black;
UIFactory.SetLayoutElement(sepObj, minHeight: 1, preferredHeight: 1, flexibleHeight: 0);
// var sepObj = UIFactory.CreateUIObject("separator", prototype);
// sepObj.AddComponent<Image>().color = Color.black;
// UIFactory.SetLayoutElement(sepObj, minHeight: 1, preferredHeight: 1, flexibleHeight: 0);
prototype.SetActive(false);
// prototype.SetActive(false);
return rect;
}
}
}
// return rect;
// }
// }
//}

View File

@ -15,11 +15,11 @@ namespace UnityExplorer.UI.Widgets
public static implicit operator float(DataViewInfo it) => it.height;
}
public class DataHeightCache
public class DataHeightCache<T> where T : ICell
{
private ScrollPool ScrollPool { get; }
private ScrollPool<T> ScrollPool { get; }
public DataHeightCache(ScrollPool scrollPool)
public DataHeightCache(ScrollPool<T> scrollPool)
{
ScrollPool = scrollPool;
}
@ -38,7 +38,7 @@ namespace UnityExplorer.UI.Widgets
public float TotalHeight => totalHeight;
private float totalHeight;
public float DefaultHeight => m_defaultHeight ?? (float)(m_defaultHeight = ScrollPool.PrototypeCell.rect.height);
public float DefaultHeight => m_defaultHeight ?? (float)(m_defaultHeight = ScrollPool.PrototypeHeight);
private float? m_defaultHeight;
/// <summary>
@ -100,8 +100,16 @@ namespace UnityExplorer.UI.Widgets
return;
var val = heightCache[heightCache.Count - 1];
totalHeight -= val;
totalHeight -= val;
heightCache.RemoveAt(heightCache.Count - 1);
int idx = heightCache.Count;
if (idx > 0)
{
while (rangeCache[rangeCache.Count - 1] == idx)
rangeCache.RemoveAt(rangeCache.Count - 1);
}
}
/// <summary>Get the data index at the specific position of the total height cache.</summary>

View File

@ -3,10 +3,11 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using UnityExplorer.UI.ObjectPool;
namespace UnityExplorer.UI.Widgets
{
public interface ICell
public interface ICell : IPooledObject
{
bool Enabled { get; }

View File

@ -6,15 +6,15 @@ using UnityEngine;
namespace UnityExplorer.UI.Widgets
{
public interface IPoolDataSource
public interface IPoolDataSource<T> where T : ICell
{
int ItemCount { get; }
void SetCell(ICell cell, int index);
void DisableCell(ICell cell, int index);
int GetRealIndexOfTempIndex(int tempIndex);
ICell CreateCell(RectTransform cellTransform);
void OnCellBorrowed(T cell);
void OnCellReturned(T cell);
void SetCell(T cell, int index);
void DisableCell(T cell, int index);
}
}

View File

@ -7,6 +7,7 @@ using UnityEngine;
using UnityEngine.UI;
using UnityExplorer.Core.Input;
using UnityExplorer.UI.Models;
using UnityExplorer.UI.ObjectPool;
namespace UnityExplorer.UI.Widgets
{
@ -15,20 +16,31 @@ namespace UnityExplorer.UI.Widgets
public int cellIndex, dataIndex;
}
//public abstract class ScrollPool : UIBehaviourModel
//{
// public abstract IPoolDataSource DataSource { get; set; }
// public abstract RectTransform PrototypeCell { get; }
//
// public abstract void Initialize(IPoolDataSource dataSource);
//
//}
/// <summary>
/// An object-pooled ScrollRect, attempts to support content of any size and provide a scrollbar for it.
/// </summary>
public class ScrollPool : UIBehaviourModel
public class ScrollPool<T> : UIBehaviourModel where T : ICell
{
public ScrollPool(ScrollRect scrollRect)
{
this.ScrollRect = scrollRect;
}
public IPoolDataSource DataSource;
public RectTransform PrototypeCell;
public IPoolDataSource<T> DataSource { get; set; }
private float PrototypeHeight => PrototypeCell.rect.height;
public float PrototypeHeight => _protoHeight ?? (float)(_protoHeight = Pool<T>.Instance.DefaultHeight);
private float? _protoHeight;
//private float PrototypeHeight => DefaultHeight.rect.height;
public int ExtraPoolCells => 6;
public float RecycleThreshold => PrototypeHeight * ExtraPoolCells;
@ -64,9 +76,9 @@ namespace UnityExplorer.UI.Widgets
private int bottomDataIndex;
private int TopDataIndex => Math.Max(0, bottomDataIndex - CellPool.Count + 1);
private readonly List<ICell> CellPool = new List<ICell>();
private readonly List<T> CellPool = new List<T>();
internal DataHeightCache HeightCache;
internal DataHeightCache<T> HeightCache;
private float TotalDataHeight => HeightCache.TotalHeight + contentLayout.padding.top + contentLayout.padding.bottom;
@ -99,8 +111,16 @@ namespace UnityExplorer.UI.Widgets
private float prevContentHeight;
public void SetUninitialized()
{
m_initialized = false;
}
public override void Update()
{
if (!m_initialized || !ScrollRect || DataSource == null)
return;
if (writingLocked && timeofLastWriteLock < Time.time)
writingLocked = false;
@ -125,6 +145,8 @@ namespace UnityExplorer.UI.Widgets
writingLocked = false;
Content.anchoredPosition = Vector2.zero;
UpdateSliderHandle(true);
m_initialized = true;
}
public void RefreshAndJumpToTop()
@ -137,22 +159,10 @@ namespace UnityExplorer.UI.Widgets
public void RecreateHeightCache()
{
//if (tempHeightCache == null)
// tempHeightCache = HeightCache;
HeightCache = new DataHeightCache(this);
HeightCache = new DataHeightCache<T>(this);
CheckDataSourceCountChange(out _);
}
//public void DisableTempCache()
//{
// if (tempHeightCache == null)
// return;
// HeightCache = tempHeightCache;
// tempHeightCache = null;
//}
public void RefreshCells(bool reloadData)
{
RefreshCells(reloadData, true);
@ -160,15 +170,14 @@ namespace UnityExplorer.UI.Widgets
// Initialize
public void Initialize(IPoolDataSource dataSource, RectTransform prototypeCell)
private bool m_initialized;
public void Initialize(IPoolDataSource<T> dataSource)
{
if (!prototypeCell)
throw new Exception("No prototype cell set, cannot initialize");
// Ensure the pool for the cell type is initialized.
Pool<T>.GetPool();
this.PrototypeCell = prototypeCell;
PrototypeCell.transform.SetParent(Viewport, false);
HeightCache = new DataHeightCache(this);
HeightCache = new DataHeightCache<T>(this);
DataSource = dataSource;
this.contentLayout = ScrollRect.content.GetComponent<VerticalLayoutGroup>();
@ -200,6 +209,8 @@ namespace UnityExplorer.UI.Widgets
// add onValueChanged listener after setup
ScrollRect.onValueChanged.AddListener(OnValueChangedListener);
m_initialized = true;
}
private void SetScrollBounds()
@ -209,14 +220,22 @@ namespace UnityExplorer.UI.Widgets
// Cell pool
private void CreateCellPool(bool andResetDataIndex = true)
public void ReturnCells()
{
if (CellPool.Any())
{
foreach (var cell in CellPool)
GameObject.Destroy(cell.Rect.gameObject);
{
DataSource.OnCellReturned(cell);
Pool<T>.Return(cell);
}
CellPool.Clear();
}
}
private void CreateCellPool(bool andResetDataIndex = true)
{
ReturnCells();
float currentPoolCoverage = 0f;
float requiredCoverage = ScrollRect.viewport.rect.height + RecycleThreshold;
@ -230,11 +249,17 @@ namespace UnityExplorer.UI.Widgets
{
bottomPoolIndex++;
//Instantiate and add to Pool
RectTransform rect = GameObject.Instantiate(PrototypeCell.gameObject).GetComponent<RectTransform>();
rect.gameObject.SetActive(true);
rect.name = $"Cell_{CellPool.Count}";
var cell = DataSource.CreateCell(rect);
////Instantiate and add to Pool
//RectTransform rect = GameObject.Instantiate(PrototypeCell.gameObject).GetComponent<RectTransform>();
//rect.gameObject.SetActive(true);
//rect.name = $"Cell_{CellPool.Count}";
//var cell = DataSource.CreateCell(rect);
//CellPool.Add(cell);
//rect.SetParent(ScrollRect.content, false);
var cell = Pool<T>.Borrow();
DataSource.OnCellBorrowed(cell);
var rect = cell.Rect;
CellPool.Add(cell);
rect.SetParent(ScrollRect.content, false);
@ -400,7 +425,7 @@ namespace UnityExplorer.UI.Widgets
ScrollRect.UpdatePrevData();
}
private void SetCell(ICell cachedCell, int dataIndex)
private void SetCell(T cachedCell, int dataIndex)
{
cachedCell.Enable();
DataSource.SetCell(cachedCell, dataIndex);

View File

@ -19,21 +19,21 @@ namespace UnityExplorer.UI.Widgets
public bool Expanded => Tree.IsCellExpanded(InstanceID);
public CachedTransform(TransformTree tree, Transform transform, CachedTransform parent = null)
public CachedTransform(TransformTree tree, Transform transform, int depth, CachedTransform parent = null)
{
Tree = tree;
Value = transform;
Parent = parent;
Update(transform);
Update(transform, depth);
}
public void Update(Transform transform)
public void Update(Transform transform, int depth)
{
Value = transform;
InstanceID = transform.GetInstanceID();
//Name = Value.name;
//ChildCount = Value.childCount;
Depth = Parent?.Depth + 1 ?? 0;
Depth = depth;
}
}
}

View File

@ -4,48 +4,33 @@ using System.Linq;
using System.Text;
using UnityEngine;
using UnityEngine.UI;
using UnityExplorer.UI.Inspectors;
using UnityExplorer.UI.Widgets;
namespace UnityExplorer.UI.Widgets
{
public class TransformCell : ICell
{
public float DefaultHeight => 25f;
public bool Enabled => m_enabled;
private bool m_enabled;
public TransformTree tree;
public Action<CachedTransform> OnExpandToggled;
public CachedTransform cachedTransform;
public int _cellIndex;
public GameObject UIRoot => uiRoot;
public GameObject uiRoot;
public RectTransform Rect => m_rect;
private readonly RectTransform m_rect;
private RectTransform m_rect;
public Text nameLabel;
public Button nameButton;
public Text expandLabel;
public Button expandButton;
public ButtonRef ExpandButton;
public ButtonRef NameButton;
public LayoutElement spacer;
public TransformCell(TransformTree tree, GameObject cellUI, Button nameButton, Button expandButton, LayoutElement spacer)
{
this.tree = tree;
this.uiRoot = cellUI;
m_rect = uiRoot.GetComponent<RectTransform>();
this.nameButton = nameButton;
this.nameLabel = nameButton.GetComponentInChildren<Text>();
this.expandButton = expandButton;
this.expandLabel = expandButton.GetComponentInChildren<Text>();
this.spacer = spacer;
nameButton.onClick.AddListener(OnMainButtonClicked);
expandButton.onClick.AddListener(OnExpandClicked);
}
//This is called from the SetCell method in DataSource
public void ConfigureCell(CachedTransform cached, int cellIndex)
{
if (cached == null)
@ -64,29 +49,29 @@ namespace UnityExplorer.UI.Widgets
if (cached.Value)
{
nameLabel.text = cached.Value.name;
nameLabel.color = cached.Value.gameObject.activeSelf ? Color.white : Color.grey;
NameButton.ButtonText.text = cached.Value.name;
NameButton.ButtonText.color = cached.Value.gameObject.activeSelf ? Color.white : Color.grey;
int childCount = cached.Value.childCount;
if (childCount > 0)
{
nameLabel.text = $"<color=grey>[{childCount}]</color> {nameLabel.text}";
NameButton.ButtonText.text = $"<color=grey>[{childCount}]</color> {NameButton.ButtonText.text}";
expandButton.interactable = true;
expandLabel.text = cached.Expanded ? "▼" : "►";
expandLabel.color = cached.Expanded ? new Color(0.5f, 0.5f, 0.5f) : new Color(0.3f, 0.3f, 0.3f);
ExpandButton.Button.interactable = true;
ExpandButton.ButtonText.text = cached.Expanded ? "▼" : "►";
ExpandButton.ButtonText.color = cached.Expanded ? new Color(0.5f, 0.5f, 0.5f) : new Color(0.3f, 0.3f, 0.3f);
}
else
{
expandButton.interactable = false;
expandLabel.text = "▪";
expandLabel.color = new Color(0.3f, 0.3f, 0.3f);
ExpandButton.Button.interactable = false;
ExpandButton.ButtonText.text = "▪";
ExpandButton.ButtonText.color = new Color(0.3f, 0.3f, 0.3f);
}
}
else
{
nameLabel.text = $"[Destroyed]";
nameLabel.color = Color.red;
NameButton.ButtonText.text = $"[Destroyed]";
NameButton.ButtonText.color = Color.red;
}
}
@ -104,51 +89,54 @@ namespace UnityExplorer.UI.Widgets
public void OnExpandClicked()
{
tree.ToggleExpandCell(this);
OnExpandToggled?.Invoke(cachedTransform);
}
public void OnMainButtonClicked()
{
if (cachedTransform.Value)
ExplorerCore.Log($"TODO Inspect {cachedTransform.Value.name}");
InspectorManager.Inspect(cachedTransform.Value.gameObject);
else
ExplorerCore.LogWarning("The object was destroyed!");
}
public static RectTransform CreatePrototypeCell(GameObject parent)
public GameObject CreateContent(GameObject parent)
{
var prototype = UIFactory.CreateHorizontalGroup(parent, "PrototypeCell", true, true, true, true, 2, default,
new Color(0.15f, 0.15f, 0.15f), TextAnchor.MiddleCenter);
//var cell = prototype.AddComponent<TransformCell>();
var rect = prototype.GetComponent<RectTransform>();
rect.anchorMin = new Vector2(0, 1);
rect.anchorMax = new Vector2(0, 1);
rect.pivot = new Vector2(0.5f, 1);
rect.sizeDelta = new Vector2(25, 25);
UIFactory.SetLayoutElement(prototype, minWidth: 100, flexibleWidth: 9999, minHeight: 25, flexibleHeight: 0);
uiRoot = UIFactory.CreateUIObject("TransformCell", parent);
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(uiRoot, true, true, true, true, 2, childAlignment: TextAnchor.MiddleCenter);
m_rect = uiRoot.GetComponent<RectTransform>();
m_rect.anchorMin = new Vector2(0, 1);
m_rect.anchorMax = new Vector2(0, 1);
m_rect.pivot = new Vector2(0.5f, 1);
m_rect.sizeDelta = new Vector2(25, 25);
UIFactory.SetLayoutElement(uiRoot, minWidth: 100, flexibleWidth: 9999, minHeight: 25, flexibleHeight: 0);
var spacer = UIFactory.CreateUIObject("Spacer", prototype, new Vector2(0, 0));
UIFactory.SetLayoutElement(spacer, minWidth: 0, flexibleWidth: 0, minHeight: 0, flexibleHeight: 0);
var spacerObj = UIFactory.CreateUIObject("Spacer", uiRoot, new Vector2(0, 0));
UIFactory.SetLayoutElement(spacerObj, minWidth: 0, flexibleWidth: 0, minHeight: 0, flexibleHeight: 0);
this.spacer = spacerObj.GetComponent<LayoutElement>();
var expandButton = UIFactory.CreateButton(prototype, "ExpandButton", "►", null);
UIFactory.SetLayoutElement(expandButton.gameObject, minWidth: 15, flexibleWidth: 0, minHeight: 25, flexibleHeight: 0);
ExpandButton = UIFactory.CreateButton(this.uiRoot, "ExpandButton", "►");
UIFactory.SetLayoutElement(ExpandButton.Button.gameObject, minWidth: 15, flexibleWidth: 0, minHeight: 25, flexibleHeight: 0);
var nameButton = UIFactory.CreateButton(prototype, "NameButton", "Name", null);
UIFactory.SetLayoutElement(nameButton.gameObject, flexibleWidth: 9999, minHeight: 25, flexibleHeight: 0);
var nameLabel = nameButton.GetComponentInChildren<Text>();
NameButton = UIFactory.CreateButton(this.uiRoot, "NameButton", "Name", null);
UIFactory.SetLayoutElement(NameButton.Button.gameObject, flexibleWidth: 9999, minHeight: 25, flexibleHeight: 0);
var nameLabel = NameButton.Button.GetComponentInChildren<Text>();
nameLabel.horizontalOverflow = HorizontalWrapMode.Overflow;
nameLabel.alignment = TextAnchor.MiddleLeft;
Color normal = new Color(0.15f, 0.15f, 0.15f);
Color normal = new Color(0.11f, 0.11f, 0.11f);
Color highlight = new Color(0.25f, 0.25f, 0.25f);
Color pressed = new Color(0.05f, 0.05f, 0.05f);
Color disabled = new Color(1, 1, 1, 0);
RuntimeProvider.Instance.SetColorBlock(expandButton, normal, highlight, pressed, disabled);
RuntimeProvider.Instance.SetColorBlock(nameButton, normal, highlight, pressed, disabled);
RuntimeProvider.Instance.SetColorBlock(ExpandButton.Button, normal, highlight, pressed, disabled);
RuntimeProvider.Instance.SetColorBlock(NameButton.Button, normal, highlight, pressed, disabled);
prototype.SetActive(false);
NameButton.OnClick += OnMainButtonClicked;
ExpandButton.OnClick += OnExpandClicked;
return rect;
uiRoot.SetActive(false);
return this.uiRoot;
}
}
}

View File

@ -5,14 +5,13 @@ using System.Linq;
using System.Text;
using UnityEngine;
using UnityEngine.UI;
using UnityExplorer.UI.ObjectPool;
using UnityExplorer.UI.Widgets;
namespace UnityExplorer.UI.Widgets
{
public class TransformTree : IPoolDataSource
public class TransformTree : IPoolDataSource<TransformCell>
{
public int GetRealIndexOfTempIndex(int index) => throw new NotImplementedException("TODO");
public Func<IEnumerable<GameObject>> GetRootEntriesMethod;
public bool Filtering => !string.IsNullOrEmpty(currentFilter);
@ -35,7 +34,7 @@ namespace UnityExplorer.UI.Widgets
}
private string currentFilter;
internal ScrollPool Scroller;
internal ScrollPool<TransformCell> ScrollPool;
internal readonly List<CachedTransform> displayedObjects = new List<CachedTransform>();
@ -46,48 +45,20 @@ namespace UnityExplorer.UI.Widgets
public int ItemCount => displayedObjects.Count;
public TransformTree(ScrollPool infiniteScroller)
public TransformTree(ScrollPool<TransformCell> scrollPool)
{
Scroller = infiniteScroller;
ScrollPool = scrollPool;
}
public void Init()
{
RuntimeProvider.Instance.StartCoroutine(InitCoroutine());
//test
var root = new GameObject("StressTest");
for (int i = 0; i < 100; i++)
{
var obj = new GameObject("GameObject " + i);
obj.transform.parent = root.transform;
for (int j = 0; j < 100; j++)
{
new GameObject("Child " + j).transform.parent = obj.transform;
}
}
ScrollPool.Initialize(this);
}
private IEnumerator InitCoroutine()
{
yield return null;
public int GetRealIndexOfTempIndex(int index) => -1;// not needed
var prototype = TransformCell.CreatePrototypeCell(Scroller.UIRoot);
public void DisableCell(TransformCell cell, int index) => cell.Disable();
RefreshData();
Scroller.Initialize(this, prototype);
}
public void DisableCell(ICell cell, int index) => cell.Disable();
public ICell CreateCell(RectTransform cellTransform)
{
var nameButton = cellTransform.Find("NameButton").GetComponent<Button>();
var expandButton = cellTransform.Find("ExpandButton").GetComponent<Button>();
var spacer = cellTransform.Find("Spacer").GetComponent<LayoutElement>();
return new TransformCell(this, cellTransform.gameObject, nameButton, expandButton, spacer);
}
public bool IsCellExpanded(int instanceID)
{
@ -95,6 +66,14 @@ namespace UnityExplorer.UI.Widgets
: expandedInstanceIDs.Contains(instanceID);
}
public void Rebuild()
{
autoExpandedIDs.Clear();
expandedInstanceIDs.Clear();
RefreshData(true, true);
}
public void RefreshData(bool andReload = false, bool hardReload = false)
{
displayedObjects.Clear();
@ -110,13 +89,13 @@ namespace UnityExplorer.UI.Widgets
if (andReload)
{
if (!hardReload)
Scroller.RefreshCells(true);
ScrollPool.RefreshCells(true);
else
Scroller.Rebuild();
ScrollPool.Rebuild();
}
}
private void Traverse(Transform transform, CachedTransform parent = null)
private void Traverse(Transform transform, CachedTransform parent = null, int depth = 0)
{
int instanceID = transform.GetInstanceID();
@ -137,11 +116,11 @@ namespace UnityExplorer.UI.Widgets
if (objectCache.ContainsKey(instanceID))
{
cached = objectCache[instanceID];
cached.Update(transform);
cached.Update(transform, depth);
}
else
{
cached = new CachedTransform(this, transform, parent);
cached = new CachedTransform(this, transform, depth, parent);
objectCache.Add(instanceID, cached);
}
@ -150,7 +129,7 @@ namespace UnityExplorer.UI.Widgets
if (IsCellExpanded(instanceID) && cached.Value.childCount > 0)
{
for (int i = 0; i < transform.childCount; i++)
Traverse(transform.GetChild(i), cached);
Traverse(transform.GetChild(i), cached, depth + 1);
}
}
@ -169,7 +148,7 @@ namespace UnityExplorer.UI.Widgets
return false;
}
public void SetCell(ICell iCell, int index)
public void SetCell(TransformCell iCell, int index)
{
var cell = iCell as TransformCell;
@ -179,9 +158,9 @@ namespace UnityExplorer.UI.Widgets
cell.Disable();
}
public void ToggleExpandCell(TransformCell cell)
public void ToggleExpandCell(CachedTransform cache)
{
var instanceID = cell.cachedTransform.InstanceID;
var instanceID = cache.InstanceID;
if (expandedInstanceIDs.Contains(instanceID))
expandedInstanceIDs.Remove(instanceID);
else
@ -189,5 +168,15 @@ namespace UnityExplorer.UI.Widgets
RefreshData(true);
}
public void OnCellBorrowed(TransformCell cell)
{
cell.OnExpandToggled += ToggleExpandCell;
}
public void OnCellReturned(TransformCell cell)
{
cell.OnExpandToggled -= ToggleExpandCell;
}
}
}

View File

@ -219,17 +219,24 @@
<Compile Include="Core\Config\InternalConfigHandler.cs" />
<Compile Include="Core\CSharp\ScriptEvaluator.cs" />
<Compile Include="Core\CSharp\ScriptInteraction.cs" />
<Compile Include="UI\Inspectors\GameObjects\ChildList.cs" />
<Compile Include="UI\Inspectors\GameObjects\ComponentList.cs" />
<Compile Include="UI\Inspectors\GameObjects\GameObjectControls.cs" />
<Compile Include="UI\Inspectors\GameObjects\GameObjectInspector.cs" />
<Compile Include="UI\Inspectors\InspectorBase.cs" />
<Compile Include="Inspectors_OLD\GameObjects\ChildList.cs" />
<Compile Include="Inspectors_OLD\GameObjects\ComponentList.cs" />
<Compile Include="Inspectors_OLD\GameObjects\GameObjectControls.cs" />
<Compile Include="Inspectors_OLD\GameObjects\GameObjectInspector.cs" />
<Compile Include="Inspectors_OLD\InspectorBase.cs" />
<Compile Include="Inspectors_OLD\InspectorManager.cs" />
<Compile Include="Inspectors_OLD\InspectUnderMouse.cs" />
<Compile Include="Inspectors_OLD\Reflection\CacheMemberList.cs" />
<Compile Include="Inspectors_OLD\Reflection\InstanceInspector.cs" />
<Compile Include="Inspectors_OLD\Reflection\ReflectionInspector.cs" />
<Compile Include="Inspectors_OLD\Reflection\StaticInspector.cs" />
<Compile Include="UI\Inspectors\GameObjectInspector.cs" />
<Compile Include="UI\Inspectors\InspectorManager.cs" />
<Compile Include="UI\Inspectors\InspectUnderMouse.cs" />
<Compile Include="UI\Inspectors\Reflection\CacheMemberList.cs" />
<Compile Include="UI\Inspectors\Reflection\InstanceInspector.cs" />
<Compile Include="UI\Inspectors\Reflection\ReflectionInspector.cs" />
<Compile Include="UI\Inspectors\Reflection\StaticInspector.cs" />
<Compile Include="UI\Inspectors\InspectorTab.cs" />
<Compile Include="UI\Inspectors\InspectorBase.cs" />
<Compile Include="UI\Inspectors\ReflectionInspector.cs" />
<Compile Include="UI\ObjectPool\IPooledObject.cs" />
<Compile Include="UI\ObjectPool\Pool.cs" />
<Compile Include="UI\Widgets\AutoComplete\ISuggestionProvider.cs" />
<Compile Include="UI\Widgets\AutoComplete\Suggestion.cs" />
<Compile Include="Core\Config\ConfigElement.cs" />
@ -285,24 +292,25 @@
<Compile Include="UI\Utility\ToStringUtility.cs" />
<Compile Include="UI\Widgets\AutoComplete\AutoCompleter.cs" />
<Compile Include="UI\Widgets\AutoComplete\TypeCompleter.cs" />
<Compile Include="UI\Widgets\CacheObject\CacheConfigEntry.cs" />
<Compile Include="UI\Widgets\CacheObject\CacheEnumerated.cs" />
<Compile Include="UI\Widgets\CacheObject\CacheField.cs" />
<Compile Include="UI\Widgets\CacheObject\CacheMember.cs" />
<Compile Include="UI\Widgets\CacheObject\CacheMethod.cs" />
<Compile Include="UI\Widgets\CacheObject\CacheObjectBase.cs" />
<Compile Include="UI\Widgets\CacheObject\CachePaired.cs" />
<Compile Include="UI\Widgets\CacheObject\CacheProperty.cs" />
<Compile Include="UI\Widgets\InteractiveValues\InteractiveBool.cs" />
<Compile Include="UI\Widgets\InteractiveValues\InteractiveColor.cs" />
<Compile Include="UI\Widgets\InteractiveValues\InteractiveDictionary.cs" />
<Compile Include="UI\Widgets\InteractiveValues\InteractiveEnum.cs" />
<Compile Include="UI\Widgets\InteractiveValues\InteractiveEnumerable.cs" />
<Compile Include="UI\Widgets\InteractiveValues\InteractiveFlags.cs" />
<Compile Include="UI\Widgets\InteractiveValues\InteractiveFloatStruct.cs" />
<Compile Include="UI\Widgets\InteractiveValues\InteractiveNumber.cs" />
<Compile Include="UI\Widgets\InteractiveValues\InteractiveString.cs" />
<Compile Include="UI\Widgets\InteractiveValues\InteractiveValue.cs" />
<Compile Include="Inspectors_OLD\CacheObject\CacheConfigEntry.cs" />
<Compile Include="Inspectors_OLD\CacheObject\CacheEnumerated.cs" />
<Compile Include="Inspectors_OLD\CacheObject\CacheField.cs" />
<Compile Include="Inspectors_OLD\CacheObject\CacheMember.cs" />
<Compile Include="Inspectors_OLD\CacheObject\CacheMethod.cs" />
<Compile Include="Inspectors_OLD\CacheObject\CacheObjectBase.cs" />
<Compile Include="Inspectors_OLD\CacheObject\CachePaired.cs" />
<Compile Include="Inspectors_OLD\CacheObject\CacheProperty.cs" />
<Compile Include="Inspectors_OLD\InteractiveValues\InteractiveBool.cs" />
<Compile Include="Inspectors_OLD\InteractiveValues\InteractiveColor.cs" />
<Compile Include="Inspectors_OLD\InteractiveValues\InteractiveDictionary.cs" />
<Compile Include="Inspectors_OLD\InteractiveValues\InteractiveEnum.cs" />
<Compile Include="Inspectors_OLD\InteractiveValues\InteractiveEnumerable.cs" />
<Compile Include="Inspectors_OLD\InteractiveValues\InteractiveFlags.cs" />
<Compile Include="Inspectors_OLD\InteractiveValues\InteractiveFloatStruct.cs" />
<Compile Include="Inspectors_OLD\InteractiveValues\InteractiveNumber.cs" />
<Compile Include="Inspectors_OLD\InteractiveValues\InteractiveString.cs" />
<Compile Include="Inspectors_OLD\InteractiveValues\InteractiveValue.cs" />
<Compile Include="UI\Widgets\ButtonRef.cs" />
<Compile Include="UI\Widgets\ObjectExplorer\ObjectSearch.cs" />
<Compile Include="UI\Widgets\ObjectExplorer\SceneExplorer.cs" />
<Compile Include="UI\Widgets\ScrollPool\DataHeightCache.cs" />