mirror of
https://github.com/sinai-dev/UnityExplorer.git
synced 2025-06-16 22:27:45 +08:00
progress on lists and dictionaries, fixes for scrollpool
This commit is contained in:
parent
bfaba56b76
commit
ad61ff243a
@ -10,22 +10,21 @@ namespace UnityExplorer.UI.Inspectors.CacheObject
|
|||||||
{
|
{
|
||||||
public FieldInfo FieldInfo { get; internal set; }
|
public FieldInfo FieldInfo { get; internal set; }
|
||||||
public override Type DeclaringType => FieldInfo.DeclaringType;
|
public override Type DeclaringType => FieldInfo.DeclaringType;
|
||||||
|
public override bool CanWrite => m_canWrite ?? (bool)(m_canWrite = !(FieldInfo.IsLiteral && !FieldInfo.IsInitOnly));
|
||||||
|
private bool? m_canWrite;
|
||||||
|
|
||||||
public override bool ShouldAutoEvaluate => true;
|
public override bool ShouldAutoEvaluate => true;
|
||||||
|
|
||||||
public override void SetInspectorOwner(ReflectionInspector inspector, MemberInfo member)
|
public override void SetInspectorOwner(ReflectionInspector inspector, MemberInfo member)
|
||||||
{
|
{
|
||||||
base.SetInspectorOwner(inspector, member);
|
base.SetInspectorOwner(inspector, member);
|
||||||
|
|
||||||
// not constant
|
|
||||||
CanWrite = !(FieldInfo.IsLiteral && !FieldInfo.IsInitOnly);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void TryEvaluate()
|
protected override void TryEvaluate()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Value = FieldInfo.GetValue(this.ParentInspector.Target.TryCast(this.DeclaringType));
|
Value = FieldInfo.GetValue(this.Owner.Target.TryCast(this.DeclaringType));
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@ -38,7 +37,7 @@ namespace UnityExplorer.UI.Inspectors.CacheObject
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
FieldInfo.SetValue(FieldInfo.IsStatic ? null : ParentInspector.Target, value);
|
FieldInfo.SetValue(FieldInfo.IsStatic ? null : Owner.Target, value);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
97
src/UI/Inspectors/CacheObject/CacheKeyValuePair.cs
Normal file
97
src/UI/Inspectors/CacheObject/CacheKeyValuePair.cs
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using UnityExplorer.UI.Inspectors.CacheObject.Views;
|
||||||
|
using UnityExplorer.UI.Inspectors.IValues;
|
||||||
|
using UnityExplorer.UI.Utility;
|
||||||
|
|
||||||
|
namespace UnityExplorer.UI.Inspectors.CacheObject
|
||||||
|
{
|
||||||
|
public class CacheKeyValuePair : CacheObjectBase
|
||||||
|
{
|
||||||
|
//public InteractiveList CurrentList { get; set; }
|
||||||
|
|
||||||
|
public int DictIndex;
|
||||||
|
public object DictKey;
|
||||||
|
|
||||||
|
public bool KeyInputWanted;
|
||||||
|
public bool InspectWanted;
|
||||||
|
public string KeyLabelText;
|
||||||
|
public string KeyInputText;
|
||||||
|
public string KeyInputTypeText;
|
||||||
|
|
||||||
|
public float DesiredKeyWidth;
|
||||||
|
public float DesiredValueWidth;
|
||||||
|
|
||||||
|
public override bool ShouldAutoEvaluate => true;
|
||||||
|
public override bool HasArguments => false;
|
||||||
|
public override bool CanWrite => false; // TODO Parent.CanWrite;
|
||||||
|
|
||||||
|
public void SetDictOwner(InteractiveDictionary dict, int index)
|
||||||
|
{
|
||||||
|
this.Owner = dict;
|
||||||
|
this.DictIndex = index;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetKey(object key)
|
||||||
|
{
|
||||||
|
this.DictKey = key;
|
||||||
|
var type = key.GetActualType();
|
||||||
|
if (type == typeof(string) || (type.IsPrimitive && !(type == typeof(bool))) || type == typeof(decimal))
|
||||||
|
{
|
||||||
|
KeyInputWanted = true;
|
||||||
|
KeyInputText = key.ToString();
|
||||||
|
KeyInputTypeText = SignatureHighlighter.ParseFullType(type, false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
KeyInputWanted = false;
|
||||||
|
InspectWanted = type != typeof(bool) && !type.IsEnum;
|
||||||
|
KeyLabelText = ToStringUtility.ToStringWithType(key, type, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void SetCell(CacheObjectCell cell)
|
||||||
|
{
|
||||||
|
base.SetCell(cell);
|
||||||
|
|
||||||
|
var kvpCell = cell as CacheKeyValuePairCell;
|
||||||
|
|
||||||
|
kvpCell.NameLabel.text = $"{DictIndex}:";
|
||||||
|
kvpCell.Image.color = DictIndex % 2 == 0 ? CacheListEntryCell.EvenColor : CacheListEntryCell.OddColor;
|
||||||
|
|
||||||
|
if (KeyInputWanted)
|
||||||
|
{
|
||||||
|
kvpCell.KeyInputField.gameObject.SetActive(true);
|
||||||
|
kvpCell.KeyInputTypeLabel.gameObject.SetActive(true);
|
||||||
|
kvpCell.KeyLabel.gameObject.SetActive(false);
|
||||||
|
kvpCell.KeyInspectButton.Button.gameObject.SetActive(false);
|
||||||
|
|
||||||
|
kvpCell.KeyInputField.text = KeyInputText;
|
||||||
|
kvpCell.KeyInputTypeLabel.text = KeyInputTypeText;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
kvpCell.KeyInputField.gameObject.SetActive(false);
|
||||||
|
kvpCell.KeyInputTypeLabel.gameObject.SetActive(false);
|
||||||
|
kvpCell.KeyLabel.gameObject.SetActive(true);
|
||||||
|
kvpCell.KeyInspectButton.Button.gameObject.SetActive(InspectWanted);
|
||||||
|
|
||||||
|
kvpCell.KeyLabel.text = KeyLabelText;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void SetUserValue(object value)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException("TODO");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected override bool SetCellEvaluateState(CacheObjectCell cell)
|
||||||
|
{
|
||||||
|
// not needed
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -9,16 +9,15 @@ namespace UnityExplorer.UI.Inspectors.CacheObject
|
|||||||
{
|
{
|
||||||
public class CacheListEntry : CacheObjectBase
|
public class CacheListEntry : CacheObjectBase
|
||||||
{
|
{
|
||||||
public InteractiveList CurrentList { get; set; }
|
|
||||||
|
|
||||||
public int ListIndex;
|
public int ListIndex;
|
||||||
|
|
||||||
public override bool ShouldAutoEvaluate => true;
|
public override bool ShouldAutoEvaluate => true;
|
||||||
public override bool HasArguments => false;
|
public override bool HasArguments => false;
|
||||||
|
public override bool CanWrite => Owner.CanWrite;
|
||||||
|
|
||||||
public void SetListOwner(InteractiveList iList, int listIndex)
|
public void SetListOwner(InteractiveList list, int listIndex)
|
||||||
{
|
{
|
||||||
this.CurrentList = iList;
|
this.Owner = list;
|
||||||
this.ListIndex = listIndex;
|
this.ListIndex = listIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -29,6 +28,7 @@ namespace UnityExplorer.UI.Inspectors.CacheObject
|
|||||||
var listCell = cell as CacheListEntryCell;
|
var listCell = cell as CacheListEntryCell;
|
||||||
|
|
||||||
listCell.NameLabel.text = $"{ListIndex}:";
|
listCell.NameLabel.text = $"{ListIndex}:";
|
||||||
|
listCell.Image.color = ListIndex % 2 == 0 ? CacheListEntryCell.EvenColor : CacheListEntryCell.OddColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void SetUserValue(object value)
|
public override void SetUserValue(object value)
|
||||||
|
@ -11,7 +11,7 @@ namespace UnityExplorer.UI.Inspectors.CacheObject
|
|||||||
{
|
{
|
||||||
public abstract class CacheMember : CacheObjectBase
|
public abstract class CacheMember : CacheObjectBase
|
||||||
{
|
{
|
||||||
public ReflectionInspector ParentInspector { get; internal set; }
|
//public ReflectionInspector ParentInspector { get; internal set; }
|
||||||
//public bool AutoUpdateWanted { get; internal set; }
|
//public bool AutoUpdateWanted { get; internal set; }
|
||||||
|
|
||||||
public abstract Type DeclaringType { get; }
|
public abstract Type DeclaringType { get; }
|
||||||
@ -23,7 +23,7 @@ namespace UnityExplorer.UI.Inspectors.CacheObject
|
|||||||
|
|
||||||
public virtual void SetInspectorOwner(ReflectionInspector inspector, MemberInfo member)
|
public virtual void SetInspectorOwner(ReflectionInspector inspector, MemberInfo member)
|
||||||
{
|
{
|
||||||
this.ParentInspector = inspector;
|
this.Owner = inspector;
|
||||||
this.NameLabelText = SignatureHighlighter.ParseFullSyntax(member.DeclaringType, false, member);
|
this.NameLabelText = SignatureHighlighter.ParseFullSyntax(member.DeclaringType, false, member);
|
||||||
this.NameForFiltering = $"{member.DeclaringType.Name}.{member.Name}";
|
this.NameForFiltering = $"{member.DeclaringType.Name}.{member.Name}";
|
||||||
}
|
}
|
||||||
@ -82,6 +82,7 @@ namespace UnityExplorer.UI.Inspectors.CacheObject
|
|||||||
{
|
{
|
||||||
// todo evaluate buttons etc
|
// todo evaluate buttons etc
|
||||||
SetValueState(cell, ValueStateArgs.Default);
|
SetValueState(cell, ValueStateArgs.Default);
|
||||||
|
cell.RefreshSubcontentButton();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -235,7 +236,7 @@ namespace UnityExplorer.UI.Inspectors.CacheObject
|
|||||||
cachedSigs.Add(sig);
|
cachedSigs.Add(sig);
|
||||||
|
|
||||||
//cached.Initialize(_inspector, declaringType, member, returnType);
|
//cached.Initialize(_inspector, declaringType, member, returnType);
|
||||||
cached.Initialize(returnType);
|
cached.SetFallbackType(returnType);
|
||||||
cached.SetInspectorOwner(_inspector, member);
|
cached.SetInspectorOwner(_inspector, member);
|
||||||
|
|
||||||
list.Add(cached);
|
list.Add(cached);
|
||||||
|
@ -10,6 +10,7 @@ namespace UnityExplorer.UI.Inspectors.CacheObject
|
|||||||
{
|
{
|
||||||
public MethodInfo MethodInfo { get; internal set; }
|
public MethodInfo MethodInfo { get; internal set; }
|
||||||
public override Type DeclaringType => MethodInfo.DeclaringType;
|
public override Type DeclaringType => MethodInfo.DeclaringType;
|
||||||
|
public override bool CanWrite => false;
|
||||||
|
|
||||||
public override bool ShouldAutoEvaluate => false;
|
public override bool ShouldAutoEvaluate => false;
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@ using System.Linq;
|
|||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
using UnityEngine.UI;
|
||||||
using UnityExplorer.UI.Inspectors.CacheObject.Views;
|
using UnityExplorer.UI.Inspectors.CacheObject.Views;
|
||||||
using UnityExplorer.UI.Inspectors.IValues;
|
using UnityExplorer.UI.Inspectors.IValues;
|
||||||
using UnityExplorer.UI.ObjectPool;
|
using UnityExplorer.UI.ObjectPool;
|
||||||
@ -29,30 +30,30 @@ namespace UnityExplorer.UI.Inspectors.CacheObject
|
|||||||
|
|
||||||
public abstract class CacheObjectBase
|
public abstract class CacheObjectBase
|
||||||
{
|
{
|
||||||
public CacheObjectCell CellView { get; internal set; }
|
public ICacheObjectController Owner { get; set; }
|
||||||
|
|
||||||
public InteractiveValue IValue { get; private set; }
|
public CacheObjectCell CellView { get; internal set; }
|
||||||
public Type CurrentIValueType { get; private set; }
|
|
||||||
public bool SubContentState { get; private set; }
|
|
||||||
|
|
||||||
public object Value { get; protected set; }
|
public object Value { get; protected set; }
|
||||||
public Type FallbackType { get; protected set; }
|
public Type FallbackType { get; protected set; }
|
||||||
|
|
||||||
|
public InteractiveValue IValue { get; private set; }
|
||||||
|
public Type CurrentIValueType { get; private set; }
|
||||||
|
public bool SubContentShowWanted { get; private set; }
|
||||||
|
|
||||||
public string NameLabelText { get; protected set; }
|
public string NameLabelText { get; protected set; }
|
||||||
//public string TypeLabelText { get; set; }
|
|
||||||
public string ValueLabelText { get; protected set; }
|
public string ValueLabelText { get; protected set; }
|
||||||
|
|
||||||
public abstract bool ShouldAutoEvaluate { get; }
|
public abstract bool ShouldAutoEvaluate { get; }
|
||||||
public abstract bool HasArguments { get; }
|
public abstract bool HasArguments { get; }
|
||||||
public bool CanWrite { get; protected set; }
|
public abstract bool CanWrite { get; }
|
||||||
public bool HadException { get; protected set; }
|
public bool HadException { get; protected set; }
|
||||||
public Exception LastException { get; protected set; }
|
public Exception LastException { get; protected set; }
|
||||||
|
|
||||||
public virtual void Initialize(Type fallbackType)
|
public virtual void SetFallbackType(Type fallbackType)
|
||||||
{
|
{
|
||||||
this.FallbackType = fallbackType;
|
this.FallbackType = fallbackType;
|
||||||
//this.TypeLabelText = SignatureHighlighter.ParseFullType(FallbackType, false);
|
GetValueLabel();
|
||||||
this.ValueLabelText = GetValueLabel();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// internals
|
// internals
|
||||||
@ -144,44 +145,50 @@ namespace UnityExplorer.UI.Inspectors.CacheObject
|
|||||||
State = ValueState.String;
|
State = ValueState.String;
|
||||||
else if (type.IsEnum)
|
else if (type.IsEnum)
|
||||||
State = ValueState.Enum;
|
State = ValueState.Enum;
|
||||||
else if (type.IsEnumerable())
|
|
||||||
State = ValueState.Collection;
|
// todo Color and ValueStruct
|
||||||
|
|
||||||
else if (type.IsDictionary())
|
else if (type.IsDictionary())
|
||||||
State = ValueState.Dictionary;
|
State = ValueState.Dictionary;
|
||||||
// todo Color and ValueStruct
|
else if (type.IsEnumerable())
|
||||||
|
State = ValueState.Collection;
|
||||||
else
|
else
|
||||||
State = ValueState.Unsupported;
|
State = ValueState.Unsupported;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set label text
|
// Set label text
|
||||||
ValueLabelText = GetValueLabel();
|
GetValueLabel();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected string GetValueLabel()
|
protected void GetValueLabel()
|
||||||
{
|
{
|
||||||
|
string label;
|
||||||
switch (State)
|
switch (State)
|
||||||
{
|
{
|
||||||
case ValueState.NotEvaluated:
|
case ValueState.NotEvaluated:
|
||||||
return $"<i>{NOT_YET_EVAL} ({SignatureHighlighter.ParseFullType(FallbackType, true)})</i>";
|
label = $"<i>{NOT_YET_EVAL} ({SignatureHighlighter.ParseFullType(FallbackType, true)})</i>"; break;
|
||||||
case ValueState.Exception:
|
case ValueState.Exception:
|
||||||
return $"<i><color=red>{ReflectionUtility.ReflectionExToString(LastException)}</color></i>";
|
label = $"<i><color=red>{ReflectionUtility.ReflectionExToString(LastException)}</color></i>"; break;
|
||||||
case ValueState.Boolean:
|
case ValueState.Boolean:
|
||||||
case ValueState.Number:
|
case ValueState.Number:
|
||||||
return null;
|
label = null; break;
|
||||||
case ValueState.String:
|
case ValueState.String:
|
||||||
string s = Value as string;
|
string s = Value as string;
|
||||||
if (s.Length > 200)
|
if (s.Length > 200)
|
||||||
s = $"{s.Substring(0, 200)}...";
|
s = $"{s.Substring(0, 200)}...";
|
||||||
return $"\"{s}\"";
|
label = $"\"{s}\""; break;
|
||||||
case ValueState.NullValue:
|
case ValueState.NullValue:
|
||||||
return $"<i>{ToStringUtility.ToStringWithType(Value, FallbackType, true)}</i>";
|
label = $"<i>{ToStringUtility.ToStringWithType(Value, FallbackType, true)}</i>"; break;
|
||||||
case ValueState.Enum:
|
case ValueState.Enum:
|
||||||
case ValueState.Collection:
|
case ValueState.Collection:
|
||||||
|
case ValueState.Dictionary:
|
||||||
case ValueState.ValueStruct:
|
case ValueState.ValueStruct:
|
||||||
|
case ValueState.Color:
|
||||||
case ValueState.Unsupported:
|
case ValueState.Unsupported:
|
||||||
default:
|
default:
|
||||||
return ToStringUtility.ToStringWithType(Value, FallbackType, true);
|
label = ToStringUtility.ToStringWithType(Value, FallbackType, true); break;
|
||||||
}
|
}
|
||||||
|
this.ValueLabelText = label;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Return true if SetCell should abort, false if it should continue.</summary>
|
/// <summary>Return true if SetCell should abort, false if it should continue.</summary>
|
||||||
@ -192,9 +199,12 @@ namespace UnityExplorer.UI.Inspectors.CacheObject
|
|||||||
cell.NameLabel.text = NameLabelText;
|
cell.NameLabel.text = NameLabelText;
|
||||||
cell.ValueLabel.gameObject.SetActive(true);
|
cell.ValueLabel.gameObject.SetActive(true);
|
||||||
|
|
||||||
cell.SubContentHolder.gameObject.SetActive(SubContentState);
|
cell.SubContentHolder.gameObject.SetActive(SubContentShowWanted);
|
||||||
if (IValue != null)
|
if (IValue != null)
|
||||||
|
{
|
||||||
IValue.UIRoot.transform.SetParent(cell.SubContentHolder.transform, false);
|
IValue.UIRoot.transform.SetParent(cell.SubContentHolder.transform, false);
|
||||||
|
IValue.SetLayout();
|
||||||
|
}
|
||||||
|
|
||||||
if (SetCellEvaluateState(cell))
|
if (SetCellEvaluateState(cell))
|
||||||
return;
|
return;
|
||||||
@ -221,7 +231,9 @@ namespace UnityExplorer.UI.Inspectors.CacheObject
|
|||||||
SetValueState(cell, new ValueStateArgs(true, subContentButtonActive: true));
|
SetValueState(cell, new ValueStateArgs(true, subContentButtonActive: true));
|
||||||
break;
|
break;
|
||||||
case ValueState.Collection:
|
case ValueState.Collection:
|
||||||
|
case ValueState.Dictionary:
|
||||||
case ValueState.ValueStruct:
|
case ValueState.ValueStruct:
|
||||||
|
case ValueState.Color:
|
||||||
SetIValueState();
|
SetIValueState();
|
||||||
SetValueState(cell, new ValueStateArgs(true, inspectActive: true, subContentButtonActive: true));
|
SetValueState(cell, new ValueStateArgs(true, inspectActive: true, subContentButtonActive: true));
|
||||||
break;
|
break;
|
||||||
@ -229,6 +241,8 @@ namespace UnityExplorer.UI.Inspectors.CacheObject
|
|||||||
SetValueState(cell, new ValueStateArgs(true, inspectActive: true));
|
SetValueState(cell, new ValueStateArgs(true, inspectActive: true));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cell.RefreshSubcontentButton();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void SetValueState(CacheObjectCell cell, ValueStateArgs args)
|
protected virtual void SetValueState(CacheObjectCell cell, ValueStateArgs args)
|
||||||
@ -285,11 +299,11 @@ namespace UnityExplorer.UI.Inspectors.CacheObject
|
|||||||
IValue = (InteractiveValue)Pool.Borrow(ivalueType);
|
IValue = (InteractiveValue)Pool.Borrow(ivalueType);
|
||||||
CurrentIValueType = ivalueType;
|
CurrentIValueType = ivalueType;
|
||||||
|
|
||||||
IValue.SetOwner(this);
|
IValue.OnBorrowed(this);
|
||||||
IValue.SetValue(this.Value);
|
IValue.SetValue(this.Value);
|
||||||
IValue.UIRoot.transform.SetParent(CellView.SubContentHolder.transform, false);
|
IValue.UIRoot.transform.SetParent(CellView.SubContentHolder.transform, false);
|
||||||
CellView.SubContentHolder.SetActive(true);
|
CellView.SubContentHolder.SetActive(true);
|
||||||
SubContentState = true;
|
SubContentShowWanted = true;
|
||||||
|
|
||||||
// update our cell after creating the ivalue (the value may have updated, make sure its consistent)
|
// update our cell after creating the ivalue (the value may have updated, make sure its consistent)
|
||||||
this.ProcessOnEvaluate();
|
this.ProcessOnEvaluate();
|
||||||
@ -297,9 +311,11 @@ namespace UnityExplorer.UI.Inspectors.CacheObject
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SubContentState = !SubContentState;
|
SubContentShowWanted = !SubContentShowWanted;
|
||||||
CellView.SubContentHolder.SetActive(SubContentState);
|
CellView.SubContentHolder.SetActive(SubContentShowWanted);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CellView.RefreshSubcontentButton();
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void ReleaseIValue()
|
public virtual void ReleaseIValue()
|
||||||
@ -335,13 +351,14 @@ namespace UnityExplorer.UI.Inspectors.CacheObject
|
|||||||
SetUserValue(this.CellView.Toggle.isOn);
|
SetUserValue(this.CellView.Toggle.isOn);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!numberParseMethods.ContainsKey(FallbackType.AssemblyQualifiedName))
|
var type = Value.GetActualType();
|
||||||
|
if (!numberParseMethods.ContainsKey(type.AssemblyQualifiedName))
|
||||||
{
|
{
|
||||||
var method = FallbackType.GetMethod("Parse", new Type[] { typeof(string) });
|
var method = type.GetMethod("Parse", new Type[] { typeof(string) });
|
||||||
numberParseMethods.Add(FallbackType.AssemblyQualifiedName, method);
|
numberParseMethods.Add(type.AssemblyQualifiedName, method);
|
||||||
}
|
}
|
||||||
|
|
||||||
var val = numberParseMethods[FallbackType.AssemblyQualifiedName]
|
var val = numberParseMethods[type.AssemblyQualifiedName]
|
||||||
.Invoke(null, new object[] { CellView.InputField.text });
|
.Invoke(null, new object[] { CellView.InputField.text });
|
||||||
SetUserValue(val);
|
SetUserValue(val);
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@ namespace UnityExplorer.UI.Inspectors.CacheObject
|
|||||||
{
|
{
|
||||||
public PropertyInfo PropertyInfo { get; internal set; }
|
public PropertyInfo PropertyInfo { get; internal set; }
|
||||||
public override Type DeclaringType => PropertyInfo.DeclaringType;
|
public override Type DeclaringType => PropertyInfo.DeclaringType;
|
||||||
|
public override bool CanWrite => PropertyInfo.CanWrite;
|
||||||
|
|
||||||
public override bool ShouldAutoEvaluate => !HasArguments;
|
public override bool ShouldAutoEvaluate => !HasArguments;
|
||||||
|
|
||||||
@ -17,7 +18,6 @@ namespace UnityExplorer.UI.Inspectors.CacheObject
|
|||||||
{
|
{
|
||||||
base.SetInspectorOwner(inspector, member);
|
base.SetInspectorOwner(inspector, member);
|
||||||
|
|
||||||
this.CanWrite = PropertyInfo.CanWrite;
|
|
||||||
Arguments = PropertyInfo.GetIndexParameters();
|
Arguments = PropertyInfo.GetIndexParameters();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -25,7 +25,7 @@ namespace UnityExplorer.UI.Inspectors.CacheObject
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Value = PropertyInfo.GetValue(ParentInspector.Target.TryCast(DeclaringType), null);
|
Value = PropertyInfo.GetValue(Owner.Target.TryCast(DeclaringType), null);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@ -43,7 +43,7 @@ namespace UnityExplorer.UI.Inspectors.CacheObject
|
|||||||
{
|
{
|
||||||
// TODO property indexers
|
// TODO property indexers
|
||||||
|
|
||||||
PropertyInfo.SetValue(PropertyInfo.GetSetMethod().IsStatic ? null : ParentInspector.Target, value, null);
|
PropertyInfo.SetValue(PropertyInfo.GetSetMethod().IsStatic ? null : Owner.Target, value, null);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
92
src/UI/Inspectors/CacheObject/Views/CacheKeyValuePairCell.cs
Normal file
92
src/UI/Inspectors/CacheObject/Views/CacheKeyValuePairCell.cs
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.UI;
|
||||||
|
using UnityExplorer.UI.Inspectors.IValues;
|
||||||
|
using UnityExplorer.UI.Widgets;
|
||||||
|
|
||||||
|
namespace UnityExplorer.UI.Inspectors.CacheObject.Views
|
||||||
|
{
|
||||||
|
public class CacheKeyValuePairCell : CacheObjectCell
|
||||||
|
{
|
||||||
|
public Image Image { get; private set; }
|
||||||
|
public InteractiveDictionary DictOwner => Occupant.Owner as InteractiveDictionary;
|
||||||
|
|
||||||
|
public LayoutElement KeyGroupLayout;
|
||||||
|
public Text KeyLabel;
|
||||||
|
public ButtonRef KeyInspectButton;
|
||||||
|
public InputField KeyInputField;
|
||||||
|
public Text KeyInputTypeLabel;
|
||||||
|
|
||||||
|
public static Color EvenColor = new Color(0.07f, 0.07f, 0.07f);
|
||||||
|
public static Color OddColor = new Color(0.063f, 0.063f, 0.063f);
|
||||||
|
|
||||||
|
public int HalfWidth => (int)(0.5f * Rect.rect.width);
|
||||||
|
public int AdjustedKeyWidth => HalfWidth - 50;
|
||||||
|
|
||||||
|
private void KeyInspectClicked()
|
||||||
|
{
|
||||||
|
InspectorManager.Inspect((Occupant as CacheKeyValuePair).DictKey, this.Occupant);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override GameObject CreateContent(GameObject parent)
|
||||||
|
{
|
||||||
|
var root = base.CreateContent(parent);
|
||||||
|
|
||||||
|
Image = root.AddComponent<Image>();
|
||||||
|
|
||||||
|
this.NameLayout.minWidth = 40;
|
||||||
|
this.NameLayout.flexibleWidth = 50;
|
||||||
|
this.NameLayout.minHeight = 30;
|
||||||
|
this.NameLabel.alignment = TextAnchor.MiddleRight;
|
||||||
|
|
||||||
|
this.RightGroupLayout.minWidth = HalfWidth;
|
||||||
|
|
||||||
|
// Key area
|
||||||
|
var keyGroup = UIFactory.CreateUIObject("KeyHolder", root.transform.Find("HoriGroup").gameObject);
|
||||||
|
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(keyGroup, false, false, true, true, 2, 0, 0, 4, 4, childAlignment: TextAnchor.MiddleLeft);
|
||||||
|
UIFactory.SetLayoutElement(keyGroup, minHeight: 30, minWidth: AdjustedKeyWidth, flexibleWidth: 0);
|
||||||
|
KeyGroupLayout = keyGroup.GetComponent<LayoutElement>();
|
||||||
|
|
||||||
|
// set to be after the NameLabel (our index label), and before the main horizontal group.
|
||||||
|
keyGroup.transform.SetSiblingIndex(1);
|
||||||
|
|
||||||
|
// key Inspect
|
||||||
|
|
||||||
|
KeyInspectButton = UIFactory.CreateButton(keyGroup, "KeyInspectButton", "Inspect", new Color(0.15f, 0.15f, 0.15f));
|
||||||
|
UIFactory.SetLayoutElement(KeyInspectButton.Button.gameObject, minWidth: 60, flexibleWidth: 0, minHeight: 25, flexibleHeight: 0);
|
||||||
|
InspectButton.OnClick += KeyInspectClicked;
|
||||||
|
|
||||||
|
// label
|
||||||
|
|
||||||
|
KeyLabel = UIFactory.CreateLabel(keyGroup, "KeyLabel", "not set (key)", TextAnchor.MiddleLeft);
|
||||||
|
UIFactory.SetLayoutElement(KeyLabel.gameObject, minWidth: 50, flexibleWidth: 999, minHeight: 30);
|
||||||
|
|
||||||
|
// Type label for input field
|
||||||
|
|
||||||
|
KeyInputTypeLabel = UIFactory.CreateLabel(keyGroup, "InputTypeLabel", "not set", TextAnchor.MiddleLeft);
|
||||||
|
UIFactory.SetLayoutElement(KeyInputTypeLabel.gameObject, minWidth: 55, flexibleWidth: 0, minHeight: 30);
|
||||||
|
|
||||||
|
// input field
|
||||||
|
|
||||||
|
var keyInputObj = UIFactory.CreateInputField(keyGroup, "KeyInput", "not set", out KeyInputField);
|
||||||
|
UIFactory.SetLayoutElement(keyInputObj, minHeight: 30, flexibleHeight: 0, flexibleWidth: 200);
|
||||||
|
//KeyInputField.lineType = InputField.LineType.MultiLineNewline;
|
||||||
|
KeyInputField.readOnly = true;
|
||||||
|
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void ConstructEvaluateHolder(GameObject parent)
|
||||||
|
{
|
||||||
|
// not used
|
||||||
|
}
|
||||||
|
|
||||||
|
//protected override void ConstructUpdateToggle(GameObject parent)
|
||||||
|
//{
|
||||||
|
// // not used
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
}
|
@ -3,20 +3,29 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
using UnityEngine.UI;
|
||||||
using UnityExplorer.UI.Inspectors.IValues;
|
using UnityExplorer.UI.Inspectors.IValues;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.Inspectors.CacheObject.Views
|
namespace UnityExplorer.UI.Inspectors.CacheObject.Views
|
||||||
{
|
{
|
||||||
public class CacheListEntryCell : CacheObjectCell
|
public class CacheListEntryCell : CacheObjectCell
|
||||||
{
|
{
|
||||||
public InteractiveList ListOwner { get; set; }
|
public Image Image { get; private set; }
|
||||||
|
public InteractiveList ListOwner => Occupant.Owner as InteractiveList;
|
||||||
|
|
||||||
|
public static Color EvenColor = new Color(0.07f, 0.07f, 0.07f);
|
||||||
|
public static Color OddColor = new Color(0.063f, 0.063f, 0.063f);
|
||||||
|
|
||||||
public override GameObject CreateContent(GameObject parent)
|
public override GameObject CreateContent(GameObject parent)
|
||||||
{
|
{
|
||||||
var root = base.CreateContent(parent);
|
var root = base.CreateContent(parent);
|
||||||
|
|
||||||
this.NameLayout.minWidth = 50;
|
Image = root.AddComponent<Image>();
|
||||||
this.NameLayout.flexibleWidth = 50f;
|
|
||||||
|
this.NameLayout.minWidth = 40;
|
||||||
|
this.NameLayout.flexibleWidth = 50;
|
||||||
|
this.NameLayout.minHeight = 30;
|
||||||
|
this.NameLabel.alignment = TextAnchor.MiddleRight;
|
||||||
|
|
||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
|
@ -64,7 +64,7 @@ namespace UnityExplorer.UI.Inspectors.CacheObject.Views
|
|||||||
|
|
||||||
protected virtual void InspectClicked()
|
protected virtual void InspectClicked()
|
||||||
{
|
{
|
||||||
InspectorManager.Inspect(Occupant.Value);
|
InspectorManager.Inspect(Occupant.Value, this.Occupant);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void ToggleClicked(bool value)
|
protected virtual void ToggleClicked(bool value)
|
||||||
@ -77,6 +77,23 @@ namespace UnityExplorer.UI.Inspectors.CacheObject.Views
|
|||||||
this.Occupant.OnCellSubContentToggle();
|
this.Occupant.OnCellSubContentToggle();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private readonly Color subInactiveColor = new Color(0.23f, 0.23f, 0.23f);
|
||||||
|
private readonly Color subActiveColor = new Color(0.23f, 0.33f, 0.23f);
|
||||||
|
|
||||||
|
public void RefreshSubcontentButton()
|
||||||
|
{
|
||||||
|
if (!this.SubContentHolder.activeSelf)
|
||||||
|
{
|
||||||
|
this.SubContentButton.ButtonText.text = "▲";
|
||||||
|
RuntimeProvider.Instance.SetColorBlock(SubContentButton.Button, subInactiveColor, subInactiveColor * 1.3f);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.SubContentButton.ButtonText.text = "▼";
|
||||||
|
RuntimeProvider.Instance.SetColorBlock(SubContentButton.Button, subActiveColor, subActiveColor * 1.3f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected abstract void ConstructEvaluateHolder(GameObject parent);
|
protected abstract void ConstructEvaluateHolder(GameObject parent);
|
||||||
|
|
||||||
// protected abstract void ConstructUpdateToggle(GameObject parent);
|
// protected abstract void ConstructUpdateToggle(GameObject parent);
|
||||||
@ -89,16 +106,16 @@ namespace UnityExplorer.UI.Inspectors.CacheObject.Views
|
|||||||
|
|
||||||
UIRoot = UIFactory.CreateUIObject(this.GetType().Name, parent, new Vector2(100, 30));
|
UIRoot = UIFactory.CreateUIObject(this.GetType().Name, parent, new Vector2(100, 30));
|
||||||
Rect = UIRoot.GetComponent<RectTransform>();
|
Rect = UIRoot.GetComponent<RectTransform>();
|
||||||
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(UIRoot, true, false, true, true, 0, 0);
|
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(UIRoot, false, false, true, true, 0, 0);
|
||||||
UIFactory.SetLayoutElement(UIRoot, minWidth: 100, flexibleWidth: 9999, minHeight: 30, flexibleHeight: 600);
|
UIFactory.SetLayoutElement(UIRoot, minWidth: 100, flexibleWidth: 9999, minHeight: 30, flexibleHeight: 600);
|
||||||
UIRoot.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize;
|
UIRoot.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize;
|
||||||
|
|
||||||
var content = UIFactory.CreateUIObject("Content", UIRoot);
|
//var content = UIFactory.CreateUIObject("Content", UIRoot);
|
||||||
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(content, true, false, true, true, 2, 0);
|
//UIFactory.SetLayoutGroup<VerticalLayoutGroup>(content, true, false, true, true, 2, 0);
|
||||||
UIFactory.SetLayoutElement(content, minWidth: 100, flexibleWidth: 9999, minHeight: 30, flexibleHeight: 600);
|
//UIFactory.SetLayoutElement(content, minWidth: 100, flexibleWidth: 9999, minHeight: 30, flexibleHeight: 600);
|
||||||
content.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize;
|
//content.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize;
|
||||||
|
|
||||||
var horiRow = UIFactory.CreateUIObject("HoriGroup", content);
|
var horiRow = UIFactory.CreateUIObject("HoriGroup", UIRoot);
|
||||||
UIFactory.SetLayoutElement(horiRow, minHeight: 29, flexibleHeight: 150, flexibleWidth: 9999);
|
UIFactory.SetLayoutElement(horiRow, minHeight: 29, flexibleHeight: 150, flexibleWidth: 9999);
|
||||||
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(horiRow, false, false, true, true, 5, 2, childAlignment: TextAnchor.UpperLeft);
|
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(horiRow, false, false, true, true, 5, 2, childAlignment: TextAnchor.UpperLeft);
|
||||||
horiRow.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize;
|
horiRow.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize;
|
||||||
@ -125,7 +142,7 @@ namespace UnityExplorer.UI.Inspectors.CacheObject.Views
|
|||||||
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(rightHoriGroup, false, false, true, true, 4, childAlignment: TextAnchor.UpperLeft);
|
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(rightHoriGroup, false, false, true, true, 4, childAlignment: TextAnchor.UpperLeft);
|
||||||
UIFactory.SetLayoutElement(rightHoriGroup, minHeight: 25, minWidth: 200, flexibleWidth: 9999, flexibleHeight: 800);
|
UIFactory.SetLayoutElement(rightHoriGroup, minHeight: 25, minWidth: 200, flexibleWidth: 9999, flexibleHeight: 800);
|
||||||
|
|
||||||
SubContentButton = UIFactory.CreateButton(rightHoriGroup, "SubContentButton", "▲");
|
SubContentButton = UIFactory.CreateButton(rightHoriGroup, "SubContentButton", "▲", subInactiveColor);
|
||||||
UIFactory.SetLayoutElement(SubContentButton.Button.gameObject, minWidth: 25, minHeight: 25, flexibleWidth: 0, flexibleHeight: 0);
|
UIFactory.SetLayoutElement(SubContentButton.Button.gameObject, minWidth: 25, minHeight: 25, flexibleWidth: 0, flexibleHeight: 0);
|
||||||
SubContentButton.OnClick += SubContentClicked;
|
SubContentButton.OnClick += SubContentClicked;
|
||||||
|
|
||||||
@ -163,10 +180,10 @@ namespace UnityExplorer.UI.Inspectors.CacheObject.Views
|
|||||||
|
|
||||||
// Subcontent
|
// Subcontent
|
||||||
|
|
||||||
SubContentHolder = UIFactory.CreateUIObject("SubContent", content);
|
SubContentHolder = UIFactory.CreateUIObject("SubContent", UIRoot);
|
||||||
UIFactory.SetLayoutElement(SubContentHolder.gameObject, minHeight: 30, flexibleHeight: 500, minWidth: 100, flexibleWidth: 9999);
|
UIFactory.SetLayoutElement(SubContentHolder.gameObject, minHeight: 30, flexibleHeight: 600, minWidth: 100, flexibleWidth: 9999);
|
||||||
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(SubContentHolder, true, false, true, true, 2, childAlignment: TextAnchor.UpperLeft);
|
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(SubContentHolder, true, true, true, true, 2, childAlignment: TextAnchor.UpperLeft);
|
||||||
|
//SubContentHolder.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.MinSize;
|
||||||
SubContentHolder.SetActive(false);
|
SubContentHolder.SetActive(false);
|
||||||
|
|
||||||
// Bottom separator
|
// Bottom separator
|
||||||
|
@ -14,7 +14,8 @@ namespace UnityExplorer.UI.Inspectors
|
|||||||
{
|
{
|
||||||
public class GameObjectInspector : InspectorBase
|
public class GameObjectInspector : InspectorBase
|
||||||
{
|
{
|
||||||
public GameObject Target;
|
//public GameObject Target;
|
||||||
|
public GameObject GOTarget => Target as GameObject;
|
||||||
|
|
||||||
private Text NameText;
|
private Text NameText;
|
||||||
|
|
||||||
@ -32,8 +33,8 @@ namespace UnityExplorer.UI.Inspectors
|
|||||||
|
|
||||||
Target = target as GameObject;
|
Target = target as GameObject;
|
||||||
|
|
||||||
NameText.text = Target.name;
|
NameText.text = GOTarget.name;
|
||||||
Tab.TabText.text = $"[G] {Target.name}";
|
Tab.TabText.text = $"[G] {GOTarget.name}";
|
||||||
|
|
||||||
RuntimeProvider.Instance.StartCoroutine(InitCoroutine());
|
RuntimeProvider.Instance.StartCoroutine(InitCoroutine());
|
||||||
}
|
}
|
||||||
@ -84,15 +85,15 @@ namespace UnityExplorer.UI.Inspectors
|
|||||||
|
|
||||||
UpdateComponents();
|
UpdateComponents();
|
||||||
|
|
||||||
Tab.TabText.text = $"[G] {Target.name}";
|
Tab.TabText.text = $"[G] {GOTarget.name}";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private IEnumerable<GameObject> GetTransformEntries()
|
private IEnumerable<GameObject> GetTransformEntries()
|
||||||
{
|
{
|
||||||
_rootEntries.Clear();
|
_rootEntries.Clear();
|
||||||
for (int i = 0; i < Target.transform.childCount; i++)
|
for (int i = 0; i < GOTarget.transform.childCount; i++)
|
||||||
_rootEntries.Add(Target.transform.GetChild(i).gameObject);
|
_rootEntries.Add(GOTarget.transform.GetChild(i).gameObject);
|
||||||
return _rootEntries;
|
return _rootEntries;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -141,7 +142,7 @@ namespace UnityExplorer.UI.Inspectors
|
|||||||
private void UpdateComponents()
|
private void UpdateComponents()
|
||||||
{
|
{
|
||||||
_componentEntries.Clear();
|
_componentEntries.Clear();
|
||||||
var comps = Target.GetComponents<Component>();
|
var comps = GOTarget.GetComponents<Component>();
|
||||||
foreach (var comp in comps)
|
foreach (var comp in comps)
|
||||||
_componentEntries.Add(comp);
|
_componentEntries.Add(comp);
|
||||||
|
|
||||||
|
18
src/UI/Inspectors/ICacheObjectController.cs
Normal file
18
src/UI/Inspectors/ICacheObjectController.cs
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using UnityExplorer.UI.Inspectors.CacheObject;
|
||||||
|
|
||||||
|
namespace UnityExplorer.UI.Inspectors
|
||||||
|
{
|
||||||
|
public interface ICacheObjectController
|
||||||
|
{
|
||||||
|
CacheObjectBase ParentCacheObject { get; } // TODO
|
||||||
|
|
||||||
|
object Target { get; }
|
||||||
|
Type TargetType { get; }
|
||||||
|
|
||||||
|
bool CanWrite { get; }
|
||||||
|
}
|
||||||
|
}
|
250
src/UI/Inspectors/IValues/InteractiveDictionary.cs
Normal file
250
src/UI/Inspectors/IValues/InteractiveDictionary.cs
Normal file
@ -0,0 +1,250 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.UI;
|
||||||
|
using UnityExplorer.UI.Inspectors.CacheObject;
|
||||||
|
using UnityExplorer.UI.Inspectors.CacheObject.Views;
|
||||||
|
using UnityExplorer.UI.Utility;
|
||||||
|
using UnityExplorer.UI.Widgets;
|
||||||
|
|
||||||
|
namespace UnityExplorer.UI.Inspectors.IValues
|
||||||
|
{
|
||||||
|
public class InteractiveDictionary : InteractiveValue, IPoolDataSource<CacheKeyValuePairCell>, ICacheObjectController
|
||||||
|
{
|
||||||
|
CacheObjectBase ICacheObjectController.ParentCacheObject => this.CurrentOwner;
|
||||||
|
object ICacheObjectController.Target => this.CurrentOwner.Value;
|
||||||
|
public Type TargetType { get; private set; }
|
||||||
|
|
||||||
|
public override bool CanWrite => false;// TODO RefIDictionary != null && !RefIDictionary.IsReadOnly;
|
||||||
|
|
||||||
|
public Type KeyType;
|
||||||
|
public Type ValueType;
|
||||||
|
public IDictionary RefIDictionary;
|
||||||
|
|
||||||
|
public int ItemCount => values.Count;
|
||||||
|
private readonly List<object> keys = new List<object>();
|
||||||
|
private readonly List<object> values = new List<object>();
|
||||||
|
private readonly List<CacheKeyValuePair> cachedEntries = new List<CacheKeyValuePair>();
|
||||||
|
|
||||||
|
public ScrollPool<CacheKeyValuePairCell> DictScrollPool { get; private set; }
|
||||||
|
|
||||||
|
public Text TopLabel;
|
||||||
|
|
||||||
|
public LayoutElement KeyTitleLayout;
|
||||||
|
public LayoutElement ValueTitleLayout;
|
||||||
|
|
||||||
|
public override void OnBorrowed(CacheObjectBase owner)
|
||||||
|
{
|
||||||
|
base.OnBorrowed(owner);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void ReleaseFromOwner()
|
||||||
|
{
|
||||||
|
base.ReleaseFromOwner();
|
||||||
|
|
||||||
|
ClearAndRelease();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ClearAndRelease()
|
||||||
|
{
|
||||||
|
keys.Clear();
|
||||||
|
values.Clear();
|
||||||
|
|
||||||
|
foreach (var entry in cachedEntries)
|
||||||
|
entry.ReleasePooledObjects();
|
||||||
|
|
||||||
|
cachedEntries.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void SetValue(object value)
|
||||||
|
{
|
||||||
|
if (value == null)
|
||||||
|
{
|
||||||
|
// should never be null
|
||||||
|
if (keys.Any())
|
||||||
|
ClearAndRelease();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var type = value.GetActualType();
|
||||||
|
if (type.IsGenericType && type.GetGenericArguments().Length == 2)
|
||||||
|
{
|
||||||
|
KeyType = type.GetGenericArguments()[0];
|
||||||
|
ValueType = type.GetGenericArguments()[1];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
KeyType = typeof(object);
|
||||||
|
ValueType = typeof(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
CacheEntries(value);
|
||||||
|
|
||||||
|
TopLabel.text = $"[{cachedEntries.Count}] {SignatureHighlighter.ParseFullType(type, true)}";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
this.DictScrollPool.Refresh(true, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CacheEntries(object value)
|
||||||
|
{
|
||||||
|
RefIDictionary = value as IDictionary;
|
||||||
|
|
||||||
|
if (RefIDictionary == null)
|
||||||
|
{
|
||||||
|
// todo il2cpp
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
keys.Clear();
|
||||||
|
foreach (var k in RefIDictionary.Keys)
|
||||||
|
keys.Add(k);
|
||||||
|
|
||||||
|
values.Clear();
|
||||||
|
foreach (var v in RefIDictionary.Values)
|
||||||
|
values.Add(v);
|
||||||
|
|
||||||
|
int idx = 0;
|
||||||
|
for (int i = 0; i < keys.Count; i++)
|
||||||
|
{
|
||||||
|
CacheKeyValuePair cache;
|
||||||
|
if (idx >= cachedEntries.Count)
|
||||||
|
{
|
||||||
|
cache = new CacheKeyValuePair();
|
||||||
|
cache.SetDictOwner(this, i);
|
||||||
|
cachedEntries.Add(cache);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
cache = cachedEntries[i];
|
||||||
|
|
||||||
|
cache.SetFallbackType(ValueType);
|
||||||
|
cache.SetKey(keys[i]);
|
||||||
|
cache.SetValueFromSource(values[i]);
|
||||||
|
|
||||||
|
idx++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove excess cached entries if dict count decreased
|
||||||
|
if (cachedEntries.Count > values.Count)
|
||||||
|
{
|
||||||
|
for (int i = cachedEntries.Count - 1; i >= values.Count; i--)
|
||||||
|
{
|
||||||
|
var cache = cachedEntries[i];
|
||||||
|
if (cache.CellView != null)
|
||||||
|
{
|
||||||
|
cache.CellView.Occupant = null;
|
||||||
|
cache.CellView = null;
|
||||||
|
}
|
||||||
|
cache.ReleasePooledObjects();
|
||||||
|
cachedEntries.RemoveAt(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// KVP entry scroll pool
|
||||||
|
|
||||||
|
public void OnCellBorrowed(CacheKeyValuePairCell cell)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetCell(CacheKeyValuePairCell cell, int index)
|
||||||
|
{
|
||||||
|
if (index < 0 || index >= cachedEntries.Count)
|
||||||
|
{
|
||||||
|
if (cell.Occupant != null)
|
||||||
|
{
|
||||||
|
cell.Occupant.CellView = null;
|
||||||
|
cell.Occupant = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
cell.Disable();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var entry = cachedEntries[index];
|
||||||
|
|
||||||
|
if (entry != cell.Occupant)
|
||||||
|
{
|
||||||
|
if (cell.Occupant != null)
|
||||||
|
{
|
||||||
|
cell.Occupant.HideIValue();
|
||||||
|
cell.Occupant.CellView = null;
|
||||||
|
cell.Occupant = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
cell.Occupant = entry;
|
||||||
|
entry.CellView = cell;
|
||||||
|
}
|
||||||
|
|
||||||
|
entry.SetCell(cell);
|
||||||
|
|
||||||
|
SetCellLayout(cell);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void SetLayout()
|
||||||
|
{
|
||||||
|
var minHeight = 5f;
|
||||||
|
|
||||||
|
foreach (var cell in DictScrollPool.CellPool)
|
||||||
|
{
|
||||||
|
SetCellLayout(cell);
|
||||||
|
if (cell.Enabled)
|
||||||
|
minHeight += cell.Rect.rect.height;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.scrollLayout.minHeight = Math.Min(400f, minHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetCellLayout(CacheKeyValuePairCell cell)
|
||||||
|
{
|
||||||
|
cell.KeyGroupLayout.minWidth = cell.AdjustedKeyWidth;
|
||||||
|
cell.RightGroupLayout.minWidth = cell.HalfWidth;
|
||||||
|
|
||||||
|
if (cell.Occupant?.IValue != null)
|
||||||
|
cell.Occupant.IValue.SetLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
private LayoutElement scrollLayout;
|
||||||
|
|
||||||
|
public override GameObject CreateContent(GameObject parent)
|
||||||
|
{
|
||||||
|
UIRoot = UIFactory.CreateVerticalGroup(parent, "InteractiveDict", true, true, true, true, 6, new Vector4(10, 3, 15, 4),
|
||||||
|
new Color(0.05f, 0.05f, 0.05f));
|
||||||
|
UIFactory.SetLayoutElement(UIRoot, flexibleWidth: 9999, minHeight: 25, flexibleHeight: 475);
|
||||||
|
UIRoot.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize;
|
||||||
|
|
||||||
|
// Entries label
|
||||||
|
|
||||||
|
TopLabel = UIFactory.CreateLabel(UIRoot, "EntryLabel", "not set", TextAnchor.MiddleLeft, fontSize: 16);
|
||||||
|
TopLabel.horizontalOverflow = HorizontalWrapMode.Overflow;
|
||||||
|
|
||||||
|
// key / value titles
|
||||||
|
|
||||||
|
var titleGroup = UIFactory.CreateUIObject("TitleGroup", UIRoot);
|
||||||
|
UIFactory.SetLayoutElement(titleGroup, minHeight: 25, flexibleWidth: 9999, flexibleHeight: 0);
|
||||||
|
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(titleGroup, true, true, true, true, padLeft: 50, padRight: 65);
|
||||||
|
|
||||||
|
var keyTitle = UIFactory.CreateLabel(titleGroup, "KeyTitle", "Keys", TextAnchor.MiddleLeft);
|
||||||
|
//UIFactory.SetLayoutElement(keyTitle.gameObject, minWidth: ReflectionInspector.LeftGroupWidth);
|
||||||
|
KeyTitleLayout = keyTitle.GetComponent<LayoutElement>();
|
||||||
|
|
||||||
|
var valueTitle = UIFactory.CreateLabel(titleGroup, "ValueTitle", "Values", TextAnchor.MiddleLeft);
|
||||||
|
//UIFactory.SetLayoutElement(valueTitle.gameObject, minWidth: ReflectionInspector.RightGroupWidth);
|
||||||
|
ValueTitleLayout = valueTitle.GetComponent<LayoutElement>();
|
||||||
|
|
||||||
|
// entry scroll pool
|
||||||
|
|
||||||
|
DictScrollPool = UIFactory.CreateScrollPool<CacheKeyValuePairCell>(UIRoot, "EntryList", out GameObject scrollObj,
|
||||||
|
out GameObject _, new Color(0.09f, 0.09f, 0.09f));
|
||||||
|
UIFactory.SetLayoutElement(scrollObj, minHeight: 150, flexibleHeight: 0);
|
||||||
|
DictScrollPool.Initialize(this, SetLayout);
|
||||||
|
scrollLayout = scrollObj.GetComponent<LayoutElement>();
|
||||||
|
|
||||||
|
return UIRoot;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -2,7 +2,6 @@
|
|||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using UnityExplorer.UI.Inspectors.CacheObject;
|
using UnityExplorer.UI.Inspectors.CacheObject;
|
||||||
@ -12,16 +11,15 @@ using UnityExplorer.UI.Widgets;
|
|||||||
|
|
||||||
namespace UnityExplorer.UI.Inspectors.IValues
|
namespace UnityExplorer.UI.Inspectors.IValues
|
||||||
{
|
{
|
||||||
// TODO
|
public class InteractiveList : InteractiveValue, IPoolDataSource<CacheListEntryCell>, ICacheObjectController
|
||||||
// - set fallback type from generic arguments
|
|
||||||
// - handle setting through IList
|
|
||||||
// - handle il2cpp lists
|
|
||||||
|
|
||||||
public class InteractiveList : InteractiveValue, IPoolDataSource<CacheListEntryCell>
|
|
||||||
{
|
{
|
||||||
public override bool CanWrite => base.CanWrite && RefIList != null;
|
CacheObjectBase ICacheObjectController.ParentCacheObject => this.CurrentOwner;
|
||||||
|
object ICacheObjectController.Target => this.CurrentOwner.Value;
|
||||||
|
public Type TargetType { get; private set; }
|
||||||
|
|
||||||
public Type FallbackEntryType;
|
public override bool CanWrite => RefIList != null && !RefIList.IsReadOnly;
|
||||||
|
|
||||||
|
public Type EntryType;
|
||||||
public IEnumerable RefIEnumerable;
|
public IEnumerable RefIEnumerable;
|
||||||
public IList RefIList;
|
public IList RefIList;
|
||||||
|
|
||||||
@ -31,14 +29,27 @@ namespace UnityExplorer.UI.Inspectors.IValues
|
|||||||
|
|
||||||
public ScrollPool<CacheListEntryCell> ListScrollPool { get; private set; }
|
public ScrollPool<CacheListEntryCell> ListScrollPool { get; private set; }
|
||||||
|
|
||||||
public LayoutElement ScrollPoolLayout;
|
|
||||||
public Text TopLabel;
|
public Text TopLabel;
|
||||||
|
|
||||||
public override void SetOwner(CacheObjectBase owner)
|
public override void OnBorrowed(CacheObjectBase owner)
|
||||||
{
|
{
|
||||||
base.SetOwner(owner);
|
base.OnBorrowed(owner);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void SetLayout()
|
||||||
|
{
|
||||||
|
var minHeight = 5f;
|
||||||
|
|
||||||
|
foreach (var cell in ListScrollPool.CellPool)
|
||||||
|
{
|
||||||
|
if (cell.Enabled)
|
||||||
|
minHeight += cell.Rect.rect.height;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.scrollLayout.minHeight = Math.Min(400f, minHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public override void ReleaseFromOwner()
|
public override void ReleaseFromOwner()
|
||||||
{
|
{
|
||||||
base.ReleaseFromOwner();
|
base.ReleaseFromOwner();
|
||||||
@ -56,33 +67,28 @@ namespace UnityExplorer.UI.Inspectors.IValues
|
|||||||
cachedEntries.Clear();
|
cachedEntries.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO temp for testing, needs improvement
|
|
||||||
public override void SetValue(object value)
|
public override void SetValue(object value)
|
||||||
{
|
{
|
||||||
//// TEMP
|
|
||||||
//if (values.Any())
|
|
||||||
// ClearAndRelease();
|
|
||||||
|
|
||||||
if (value == null)
|
if (value == null)
|
||||||
{
|
{
|
||||||
|
// should never be null
|
||||||
if (values.Any())
|
if (values.Any())
|
||||||
ClearAndRelease();
|
ClearAndRelease();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// todo can improve this
|
|
||||||
var type = value.GetActualType();
|
var type = value.GetActualType();
|
||||||
if (type.IsGenericType)
|
if (type.IsGenericType)
|
||||||
FallbackEntryType = type.GetGenericArguments()[0];
|
EntryType = type.GetGenericArguments()[0];
|
||||||
else
|
else
|
||||||
FallbackEntryType = typeof(object);
|
EntryType = typeof(object);
|
||||||
|
|
||||||
CacheEntries(value);
|
CacheEntries(value);
|
||||||
|
|
||||||
|
TopLabel.text = $"[{cachedEntries.Count}] {SignatureHighlighter.ParseFullType(type, true)}";
|
||||||
}
|
}
|
||||||
|
|
||||||
TopLabel.text = $"{cachedEntries.Count} entries";
|
//this.ScrollPoolLayout.minHeight = Math.Min(400f, 35f * values.Count);
|
||||||
|
|
||||||
this.ScrollPoolLayout.minHeight = Math.Min(400f, 35f * values.Count);
|
|
||||||
this.ListScrollPool.Refresh(true, false);
|
this.ListScrollPool.Refresh(true, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -93,7 +99,8 @@ namespace UnityExplorer.UI.Inspectors.IValues
|
|||||||
|
|
||||||
if (RefIEnumerable == null)
|
if (RefIEnumerable == null)
|
||||||
{
|
{
|
||||||
// todo il2cpp ...?
|
// todo il2cpp
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
values.Clear();
|
values.Clear();
|
||||||
@ -113,7 +120,7 @@ namespace UnityExplorer.UI.Inspectors.IValues
|
|||||||
else
|
else
|
||||||
cache = cachedEntries[idx];
|
cache = cachedEntries[idx];
|
||||||
|
|
||||||
cache.Initialize(this.FallbackEntryType);
|
cache.SetFallbackType(this.EntryType);
|
||||||
cache.SetValueFromSource(entry);
|
cache.SetValueFromSource(entry);
|
||||||
idx++;
|
idx++;
|
||||||
}
|
}
|
||||||
@ -139,7 +146,7 @@ namespace UnityExplorer.UI.Inspectors.IValues
|
|||||||
|
|
||||||
public void OnCellBorrowed(CacheListEntryCell cell)
|
public void OnCellBorrowed(CacheListEntryCell cell)
|
||||||
{
|
{
|
||||||
cell.ListOwner = this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetCell(CacheListEntryCell cell, int index)
|
public void SetCell(CacheListEntryCell cell, int index)
|
||||||
@ -174,24 +181,27 @@ namespace UnityExplorer.UI.Inspectors.IValues
|
|||||||
entry.SetCell(cell);
|
entry.SetCell(cell);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private LayoutElement scrollLayout;
|
||||||
|
|
||||||
public override GameObject CreateContent(GameObject parent)
|
public override GameObject CreateContent(GameObject parent)
|
||||||
{
|
{
|
||||||
UIRoot = UIFactory.CreateVerticalGroup(parent, "InteractiveList", true, true, true, true, 2, new Vector4(4, 4, 4, 4),
|
UIRoot = UIFactory.CreateVerticalGroup(parent, "InteractiveList", true, true, true, true, 6, new Vector4(10, 3, 15, 4),
|
||||||
new Color(0.05f, 0.05f, 0.05f));
|
new Color(0.05f, 0.05f, 0.05f));
|
||||||
|
|
||||||
UIFactory.SetLayoutElement(UIRoot, flexibleWidth: 9999, minHeight: 25, flexibleHeight: 600);
|
UIFactory.SetLayoutElement(UIRoot, flexibleWidth: 9999, minHeight: 25, flexibleHeight: 600);
|
||||||
|
UIRoot.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize;
|
||||||
|
|
||||||
// Entries label
|
// Entries label
|
||||||
|
|
||||||
TopLabel = UIFactory.CreateLabel(UIRoot, "EntryLabel", "not set", TextAnchor.MiddleLeft);
|
TopLabel = UIFactory.CreateLabel(UIRoot, "EntryLabel", "not set", TextAnchor.MiddleLeft, fontSize: 16);
|
||||||
|
TopLabel.horizontalOverflow = HorizontalWrapMode.Overflow;
|
||||||
|
|
||||||
// entry scroll pool
|
// entry scroll pool
|
||||||
|
|
||||||
ListScrollPool = UIFactory.CreateScrollPool<CacheListEntryCell>(UIRoot, "EntryList", out GameObject scrollObj,
|
ListScrollPool = UIFactory.CreateScrollPool<CacheListEntryCell>(UIRoot, "EntryList", out GameObject scrollObj,
|
||||||
out GameObject _, new Color(0.09f, 0.09f, 0.09f));
|
out GameObject _, new Color(0.09f, 0.09f, 0.09f));
|
||||||
UIFactory.SetLayoutElement(scrollObj, minHeight: 25, flexibleHeight: 0);
|
UIFactory.SetLayoutElement(scrollObj, minHeight: 400, flexibleHeight: 0);
|
||||||
ListScrollPool.Initialize(this);
|
ListScrollPool.Initialize(this, SetLayout);
|
||||||
ScrollPoolLayout = scrollObj.GetComponent<LayoutElement>();
|
scrollLayout = scrollObj.GetComponent<LayoutElement>();
|
||||||
|
|
||||||
return UIRoot;
|
return UIRoot;
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,8 @@ namespace UnityExplorer.UI.Inspectors.IValues
|
|||||||
|
|
||||||
public object EditedValue { get; private set; }
|
public object EditedValue { get; private set; }
|
||||||
|
|
||||||
|
public virtual void SetLayout() { }
|
||||||
|
|
||||||
public static Type GetIValueTypeForState(ValueState state)
|
public static Type GetIValueTypeForState(ValueState state)
|
||||||
{
|
{
|
||||||
switch (state)
|
switch (state)
|
||||||
@ -32,8 +34,8 @@ namespace UnityExplorer.UI.Inspectors.IValues
|
|||||||
// return null;
|
// return null;
|
||||||
case ValueState.Collection:
|
case ValueState.Collection:
|
||||||
return typeof(InteractiveList);
|
return typeof(InteractiveList);
|
||||||
//case ValueState.Dictionary:
|
case ValueState.Dictionary:
|
||||||
// return null;
|
return typeof(InteractiveDictionary);
|
||||||
//case ValueState.ValueStruct:
|
//case ValueState.ValueStruct:
|
||||||
// return null;
|
// return null;
|
||||||
//case ValueState.Color:
|
//case ValueState.Color:
|
||||||
@ -42,7 +44,7 @@ namespace UnityExplorer.UI.Inspectors.IValues
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void SetOwner(CacheObjectBase owner)
|
public virtual void OnBorrowed(CacheObjectBase owner)
|
||||||
{
|
{
|
||||||
if (this.m_owner != null)
|
if (this.m_owner != null)
|
||||||
{
|
{
|
||||||
|
@ -3,6 +3,7 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
using UnityEngine.UI;
|
||||||
using UnityExplorer.UI.ObjectPool;
|
using UnityExplorer.UI.ObjectPool;
|
||||||
using UnityExplorer.UI.Panels;
|
using UnityExplorer.UI.Panels;
|
||||||
|
|
||||||
@ -11,7 +12,7 @@ namespace UnityExplorer.UI.Inspectors
|
|||||||
public abstract class InspectorBase : IPooledObject
|
public abstract class InspectorBase : IPooledObject
|
||||||
{
|
{
|
||||||
public bool IsActive { get; internal set; }
|
public bool IsActive { get; internal set; }
|
||||||
public object InspectorTarget { get; internal set; }
|
public object Target { get; set; }
|
||||||
|
|
||||||
public InspectorTab Tab { get; internal set; }
|
public InspectorTab Tab { get; internal set; }
|
||||||
|
|
||||||
@ -24,6 +25,7 @@ namespace UnityExplorer.UI.Inspectors
|
|||||||
|
|
||||||
public virtual void OnBorrowedFromPool(object target)
|
public virtual void OnBorrowedFromPool(object target)
|
||||||
{
|
{
|
||||||
|
this.Target = target;
|
||||||
Tab = Pool<InspectorTab>.Borrow();
|
Tab = Pool<InspectorTab>.Borrow();
|
||||||
Tab.UIRoot.transform.SetParent(InspectorPanel.Instance.NavbarHolder.transform, false);
|
Tab.UIRoot.transform.SetParent(InspectorPanel.Instance.NavbarHolder.transform, false);
|
||||||
|
|
||||||
@ -44,6 +46,7 @@ namespace UnityExplorer.UI.Inspectors
|
|||||||
Tab.SetTabColor(true);
|
Tab.SetTabColor(true);
|
||||||
UIRoot.SetActive(true);
|
UIRoot.SetActive(true);
|
||||||
IsActive = true;
|
IsActive = true;
|
||||||
|
LayoutRebuilder.ForceRebuildLayoutImmediate(UIRoot.GetComponent<RectTransform>());
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void OnSetInactive()
|
public virtual void OnSetInactive()
|
||||||
|
@ -4,6 +4,7 @@ using System.Linq;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
|
using UnityExplorer.UI.Inspectors.CacheObject;
|
||||||
using UnityExplorer.UI.ObjectPool;
|
using UnityExplorer.UI.ObjectPool;
|
||||||
using UnityExplorer.UI.Panels;
|
using UnityExplorer.UI.Panels;
|
||||||
|
|
||||||
@ -17,7 +18,7 @@ namespace UnityExplorer.UI.Inspectors
|
|||||||
|
|
||||||
public static float PanelWidth;
|
public static float PanelWidth;
|
||||||
|
|
||||||
public static void Inspect(object obj)
|
public static void Inspect(object obj, CacheObjectBase sourceCache = null)
|
||||||
{
|
{
|
||||||
if (obj.IsNullOrDestroyed())
|
if (obj.IsNullOrDestroyed())
|
||||||
return;
|
return;
|
||||||
@ -27,17 +28,21 @@ namespace UnityExplorer.UI.Inspectors
|
|||||||
if (TryFocusActiveInspector(obj))
|
if (TryFocusActiveInspector(obj))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// var type = obj.GetActualType();
|
||||||
|
//if (type.IsEnumerable())
|
||||||
|
// CreateInspector<ListInspector>(obj, false, sourceCache);
|
||||||
|
//// todo dict
|
||||||
if (obj is GameObject)
|
if (obj is GameObject)
|
||||||
CreateInspector<GameObjectInspector>(obj);
|
CreateInspector<GameObjectInspector>(obj);
|
||||||
else
|
else
|
||||||
CreateInspector<ReflectionInspector>(obj);
|
CreateInspector<ReflectionInspector>(obj, false, sourceCache);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool TryFocusActiveInspector(object target)
|
private static bool TryFocusActiveInspector(object target)
|
||||||
{
|
{
|
||||||
foreach (var inspector in Inspectors)
|
foreach (var inspector in Inspectors)
|
||||||
{
|
{
|
||||||
if (inspector.InspectorTarget.ReferenceEqual(target))
|
if (inspector.Target.ReferenceEqual(target))
|
||||||
{
|
{
|
||||||
UIManager.SetPanelActive(UIManager.Panels.Inspector, true);
|
UIManager.SetPanelActive(UIManager.Panels.Inspector, true);
|
||||||
SetInspectorActive(inspector);
|
SetInspectorActive(inspector);
|
||||||
@ -66,11 +71,14 @@ namespace UnityExplorer.UI.Inspectors
|
|||||||
ActiveInspector.OnSetInactive();
|
ActiveInspector.OnSetInactive();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void CreateInspector<T>(object target, bool staticReflection = false) where T : InspectorBase
|
private static void CreateInspector<T>(object target, bool staticReflection = false, CacheObjectBase sourceCache = null) where T : InspectorBase
|
||||||
{
|
{
|
||||||
var inspector = Pool<T>.Borrow();
|
var inspector = Pool<T>.Borrow();
|
||||||
Inspectors.Add(inspector);
|
Inspectors.Add(inspector);
|
||||||
inspector.InspectorTarget = target;
|
inspector.Target = target;
|
||||||
|
|
||||||
|
if (sourceCache != null && inspector is ReflectionInspector ri)
|
||||||
|
ri.ParentCacheObject = sourceCache;
|
||||||
|
|
||||||
UIManager.SetPanelActive(UIManager.Panels.Inspector, true);
|
UIManager.SetPanelActive(UIManager.Panels.Inspector, true);
|
||||||
inspector.UIRoot.transform.SetParent(InspectorPanel.Instance.ContentHolder.transform, false);
|
inspector.UIRoot.transform.SetParent(InspectorPanel.Instance.ContentHolder.transform, false);
|
||||||
|
197
src/UI/Inspectors/ListInspector.cs
Normal file
197
src/UI/Inspectors/ListInspector.cs
Normal file
@ -0,0 +1,197 @@
|
|||||||
|
//using System;
|
||||||
|
//using System.Collections;
|
||||||
|
//using System.Collections.Generic;
|
||||||
|
//using System.Linq;
|
||||||
|
//using System.Text;
|
||||||
|
//using UnityEngine;
|
||||||
|
//using UnityEngine.UI;
|
||||||
|
//using UnityExplorer.UI.Inspectors.CacheObject;
|
||||||
|
//using UnityExplorer.UI.Inspectors.CacheObject.Views;
|
||||||
|
//using UnityExplorer.UI.Utility;
|
||||||
|
//using UnityExplorer.UI.Widgets;
|
||||||
|
|
||||||
|
//namespace UnityExplorer.UI.Inspectors
|
||||||
|
//{
|
||||||
|
// // TODO
|
||||||
|
// // - set fallback type from generic arguments
|
||||||
|
// // - handle setting through IList
|
||||||
|
// // - handle il2cpp lists
|
||||||
|
|
||||||
|
// public class ListInspector : InspectorBase, IPoolDataSource<CacheListEntryCell>, ICacheObjectController
|
||||||
|
// {
|
||||||
|
// // TODO
|
||||||
|
// public CacheObjectBase ParentCacheObject { get; set; }
|
||||||
|
|
||||||
|
// public Type TargetType { get; private set; }
|
||||||
|
|
||||||
|
// public bool CanWrite => RefIList != null && !RefIList.IsReadOnly;
|
||||||
|
|
||||||
|
// public Type EntryType;
|
||||||
|
// public IEnumerable RefIEnumerable;
|
||||||
|
// public IList RefIList;
|
||||||
|
|
||||||
|
// public int ItemCount => values.Count;
|
||||||
|
// private readonly List<object> values = new List<object>();
|
||||||
|
// private readonly List<CacheListEntry> cachedEntries = new List<CacheListEntry>();
|
||||||
|
|
||||||
|
// public ScrollPool<CacheListEntryCell> ListScrollPool { get; private set; }
|
||||||
|
|
||||||
|
// public LayoutElement ScrollPoolLayout;
|
||||||
|
// public Text TopLabel;
|
||||||
|
|
||||||
|
// public override void OnBorrowedFromPool(object target)
|
||||||
|
// {
|
||||||
|
// base.OnBorrowedFromPool(target);
|
||||||
|
|
||||||
|
// var type = target.GetActualType();
|
||||||
|
// if (type.IsGenericType)
|
||||||
|
// EntryType = type.GetGenericArguments()[0];
|
||||||
|
// else
|
||||||
|
// EntryType = typeof(object);
|
||||||
|
|
||||||
|
// // Set tab
|
||||||
|
|
||||||
|
// Tab.TabText.text = $"[L] {SignatureHighlighter.ParseFullType(type, false)}";
|
||||||
|
|
||||||
|
// // Get cache entries
|
||||||
|
|
||||||
|
// CacheEntries(target);
|
||||||
|
|
||||||
|
// TopLabel.text = $"{cachedEntries.Count} entries";
|
||||||
|
|
||||||
|
// this.ListScrollPool.Refresh(true, false);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// public override void OnReturnToPool()
|
||||||
|
// {
|
||||||
|
// base.OnReturnToPool();
|
||||||
|
|
||||||
|
// values.Clear();
|
||||||
|
|
||||||
|
// foreach (var entry in cachedEntries)
|
||||||
|
// entry.ReleasePooledObjects();
|
||||||
|
|
||||||
|
// cachedEntries.Clear();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// public override void Update()
|
||||||
|
// {
|
||||||
|
// // ...
|
||||||
|
// }
|
||||||
|
|
||||||
|
// protected override void OnCloseClicked()
|
||||||
|
// {
|
||||||
|
// InspectorManager.ReleaseInspector(this);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// private void CacheEntries(object value)
|
||||||
|
// {
|
||||||
|
// RefIEnumerable = value as IEnumerable;
|
||||||
|
// RefIList = value as IList;
|
||||||
|
|
||||||
|
// if (RefIEnumerable == null)
|
||||||
|
// {
|
||||||
|
// // todo il2cpp ...?
|
||||||
|
// }
|
||||||
|
|
||||||
|
// values.Clear();
|
||||||
|
// int idx = 0;
|
||||||
|
// foreach (var entry in RefIEnumerable)
|
||||||
|
// {
|
||||||
|
// values.Add(entry);
|
||||||
|
|
||||||
|
// // If list count increased, create new cache entries
|
||||||
|
// CacheListEntry cache;
|
||||||
|
// if (idx >= cachedEntries.Count)
|
||||||
|
// {
|
||||||
|
// cache = new CacheListEntry();
|
||||||
|
// cache.SetListOwner(this, idx);
|
||||||
|
// cachedEntries.Add(cache);
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// cache = cachedEntries[idx];
|
||||||
|
|
||||||
|
// cache.Initialize(this.EntryType);
|
||||||
|
// cache.SetValueFromSource(entry);
|
||||||
|
// idx++;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // Remove excess cached entries if list count decreased
|
||||||
|
// if (cachedEntries.Count > values.Count)
|
||||||
|
// {
|
||||||
|
// for (int i = cachedEntries.Count - 1; i >= values.Count; i--)
|
||||||
|
// {
|
||||||
|
// var cache = cachedEntries[i];
|
||||||
|
// if (cache.CellView != null)
|
||||||
|
// {
|
||||||
|
// cache.CellView.Occupant = null;
|
||||||
|
// cache.CellView = null;
|
||||||
|
// }
|
||||||
|
// cache.ReleasePooledObjects();
|
||||||
|
// cachedEntries.RemoveAt(i);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // List entry scroll pool
|
||||||
|
|
||||||
|
// public void OnCellBorrowed(CacheListEntryCell cell)
|
||||||
|
// {
|
||||||
|
// cell.ListOwner = this;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// public void SetCell(CacheListEntryCell cell, int index)
|
||||||
|
// {
|
||||||
|
// if (index < 0 || index >= cachedEntries.Count)
|
||||||
|
// {
|
||||||
|
// if (cell.Occupant != null)
|
||||||
|
// {
|
||||||
|
// cell.Occupant.CellView = null;
|
||||||
|
// cell.Occupant = null;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// cell.Disable();
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// var entry = cachedEntries[index];
|
||||||
|
|
||||||
|
// if (entry != cell.Occupant)
|
||||||
|
// {
|
||||||
|
// if (cell.Occupant != null)
|
||||||
|
// {
|
||||||
|
// cell.Occupant.HideIValue();
|
||||||
|
// cell.Occupant.CellView = null;
|
||||||
|
// cell.Occupant = null;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// cell.Occupant = entry;
|
||||||
|
// entry.CellView = cell;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// entry.SetCell(cell);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// public override GameObject CreateContent(GameObject parent)
|
||||||
|
// {
|
||||||
|
// UIRoot = UIFactory.CreateVerticalGroup(parent, "InteractiveList", true, true, true, true, 2, new Vector4(4, 4, 4, 4),
|
||||||
|
// new Color(0.05f, 0.05f, 0.05f));
|
||||||
|
|
||||||
|
// UIFactory.SetLayoutElement(UIRoot, flexibleWidth: 9999, minHeight: 25, flexibleHeight: 600);
|
||||||
|
|
||||||
|
// // Entries label
|
||||||
|
|
||||||
|
// TopLabel = UIFactory.CreateLabel(UIRoot, "EntryLabel", "not set", TextAnchor.MiddleLeft);
|
||||||
|
|
||||||
|
// // entry scroll pool
|
||||||
|
|
||||||
|
// ListScrollPool = UIFactory.CreateScrollPool<CacheListEntryCell>(UIRoot, "EntryList", out GameObject scrollObj,
|
||||||
|
// out GameObject _, new Color(0.09f, 0.09f, 0.09f));
|
||||||
|
// UIFactory.SetLayoutElement(scrollObj, minHeight: 25, flexibleHeight: 9999);
|
||||||
|
// ListScrollPool.Initialize(this);
|
||||||
|
// ScrollPoolLayout = scrollObj.GetComponent<LayoutElement>();
|
||||||
|
|
||||||
|
// return UIRoot;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//}
|
@ -16,12 +16,16 @@ using UnityExplorer.UI.Widgets;
|
|||||||
|
|
||||||
namespace UnityExplorer.UI.Inspectors
|
namespace UnityExplorer.UI.Inspectors
|
||||||
{
|
{
|
||||||
public class ReflectionInspector : InspectorBase, IPoolDataSource<CacheMemberCell>
|
public class ReflectionInspector : InspectorBase, IPoolDataSource<CacheMemberCell>, ICacheObjectController
|
||||||
{
|
{
|
||||||
|
// TODO
|
||||||
|
public CacheObjectBase ParentCacheObject { get; set; }
|
||||||
|
|
||||||
public bool StaticOnly { get; internal set; }
|
public bool StaticOnly { get; internal set; }
|
||||||
|
|
||||||
public object Target { get; private set; }
|
//public object Target { get; private set; }
|
||||||
public Type TargetType { get; private set; }
|
public Type TargetType { get; private set; }
|
||||||
|
public bool CanWrite => true;
|
||||||
|
|
||||||
public ScrollPool<CacheMemberCell> MemberScrollPool { get; private set; }
|
public ScrollPool<CacheMemberCell> MemberScrollPool { get; private set; }
|
||||||
|
|
||||||
@ -81,11 +85,12 @@ namespace UnityExplorer.UI.Inspectors
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Target = target;
|
|
||||||
TargetType = target.GetActualType();
|
TargetType = target.GetActualType();
|
||||||
prefix = "[R]";
|
prefix = "[R]";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Tab.TabText.text = $"{prefix} {SignatureHighlighter.ParseFullType(TargetType)}";
|
||||||
|
|
||||||
NameText.text = SignatureHighlighter.ParseFullSyntax(TargetType, true);
|
NameText.text = SignatureHighlighter.ParseFullSyntax(TargetType, true);
|
||||||
|
|
||||||
string asmText;
|
string asmText;
|
||||||
@ -95,7 +100,6 @@ namespace UnityExplorer.UI.Inspectors
|
|||||||
asmText = $"{TargetType.Assembly.GetName().Name} <color=grey><i>(in memory)</i></color>";
|
asmText = $"{TargetType.Assembly.GetName().Name} <color=grey><i>(in memory)</i></color>";
|
||||||
AssemblyText.text = $"<color=grey>Assembly:</color> {asmText}";
|
AssemblyText.text = $"<color=grey>Assembly:</color> {asmText}";
|
||||||
|
|
||||||
Tab.TabText.text = $"{prefix} {SignatureHighlighter.ParseFullType(TargetType)}";
|
|
||||||
|
|
||||||
this.members = CacheMember.GetCacheMembers(Target, TargetType, this);
|
this.members = CacheMember.GetCacheMembers(Target, TargetType, this);
|
||||||
FilterMembers();
|
FilterMembers();
|
||||||
@ -217,22 +221,25 @@ namespace UnityExplorer.UI.Inspectors
|
|||||||
|
|
||||||
// Cell layout (fake table alignment)
|
// Cell layout (fake table alignment)
|
||||||
|
|
||||||
private static float MemLabelWidth { get; set; }
|
private static int LeftGroupWidth { get; set; }
|
||||||
private static float RightGroupWidth { get; set; }
|
private static int RightGroupWidth { get; set; }
|
||||||
|
|
||||||
private void SetTitleLayouts()
|
private void SetTitleLayouts()
|
||||||
{
|
{
|
||||||
// Calculate sizes
|
// Calculate sizes
|
||||||
MemLabelWidth = Math.Max(200, Math.Min(450f, 0.4f * InspectorManager.PanelWidth - 5));
|
LeftGroupWidth = (int)Math.Max(200, (0.45f * InspectorManager.PanelWidth) - 5);// Math.Min(450f, 0.4f * InspectorManager.PanelWidth - 5));
|
||||||
RightGroupWidth = Math.Max(200, InspectorManager.PanelWidth - MemLabelWidth - 55);
|
RightGroupWidth = (int)Math.Max(200, InspectorManager.PanelWidth - LeftGroupWidth - 55);
|
||||||
|
|
||||||
memberTitleLayout.minWidth = MemLabelWidth;
|
memberTitleLayout.minWidth = LeftGroupWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetCellLayout(CacheObjectCell cell)
|
private void SetCellLayout(CacheObjectCell cell)
|
||||||
{
|
{
|
||||||
cell.NameLayout.minWidth = MemLabelWidth;
|
cell.NameLayout.minWidth = LeftGroupWidth;
|
||||||
cell.RightGroupLayout.minWidth = RightGroupWidth;
|
cell.RightGroupLayout.minWidth = RightGroupWidth;
|
||||||
|
|
||||||
|
if (cell.Occupant?.IValue != null)
|
||||||
|
cell.Occupant.IValue.SetLayout();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void SetLayouts()
|
internal void SetLayouts()
|
||||||
|
@ -51,6 +51,9 @@ namespace UnityExplorer.UI.Panels
|
|||||||
|
|
||||||
private void InvokeOnValueChanged(string value)
|
private void InvokeOnValueChanged(string value)
|
||||||
{
|
{
|
||||||
|
if (value.Length == UIManager.MAX_INPUTFIELD_CHARS)
|
||||||
|
ExplorerCore.LogWarning($"Reached maximum InputField character length! ({UIManager.MAX_INPUTFIELD_CHARS})");
|
||||||
|
|
||||||
if (Time.time <= m_timeOfLastInputInvoke)
|
if (Time.time <= m_timeOfLastInputInvoke)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -531,7 +531,7 @@ namespace UnityExplorer.UI
|
|||||||
placeHolderRect.offsetMin = Vector2.zero;
|
placeHolderRect.offsetMin = Vector2.zero;
|
||||||
placeHolderRect.offsetMax = Vector2.zero;
|
placeHolderRect.offsetMax = Vector2.zero;
|
||||||
|
|
||||||
SetLayoutElement(placeHolderObj, minWidth: 200, flexibleWidth: 5000);
|
//SetLayoutElement(placeHolderObj, minWidth: 20, flexibleWidth: 5000);
|
||||||
|
|
||||||
inputField.placeholder = placeholderText;
|
inputField.placeholder = placeholderText;
|
||||||
|
|
||||||
@ -550,9 +550,10 @@ namespace UnityExplorer.UI
|
|||||||
inputTextRect.offsetMin = Vector2.zero;
|
inputTextRect.offsetMin = Vector2.zero;
|
||||||
inputTextRect.offsetMax = Vector2.zero;
|
inputTextRect.offsetMax = Vector2.zero;
|
||||||
|
|
||||||
SetLayoutElement(inputTextObj, minWidth: 200, flexibleWidth: 5000);
|
//SetLayoutElement(inputTextObj, minWidth: 200, flexibleWidth: 5000);
|
||||||
|
|
||||||
inputField.textComponent = inputText;
|
inputField.textComponent = inputText;
|
||||||
|
inputField.characterLimit = UIManager.MAX_INPUTFIELD_CHARS;
|
||||||
|
|
||||||
new InputFieldRefresher(inputField);
|
new InputFieldRefresher(inputField);
|
||||||
|
|
||||||
|
@ -52,6 +52,8 @@ namespace UnityExplorer.UI
|
|||||||
internal static readonly Color navButtonEnabledColor = new Color(0.2f, 0.4f, 0.28f);
|
internal static readonly Color navButtonEnabledColor = new Color(0.2f, 0.4f, 0.28f);
|
||||||
internal static readonly Color navButtonDisabledColor = new Color(0.25f, 0.25f, 0.25f);
|
internal static readonly Color navButtonDisabledColor = new Color(0.25f, 0.25f, 0.25f);
|
||||||
|
|
||||||
|
public const int MAX_INPUTFIELD_CHARS = 16000;
|
||||||
|
|
||||||
public static UIPanel GetPanel(Panels panel)
|
public static UIPanel GetPanel(Panels panel)
|
||||||
{
|
{
|
||||||
switch (panel)
|
switch (panel)
|
||||||
|
@ -63,10 +63,9 @@ namespace UnityExplorer.UI.Widgets
|
|||||||
// get the remainder of the start position divided by min height
|
// get the remainder of the start position divided by min height
|
||||||
float rem = startPosition % DefaultHeight;
|
float rem = startPosition % DefaultHeight;
|
||||||
|
|
||||||
// if there is a remainder, this means the previous cell started in
|
// if there is a remainder, this means the previous cell started in our first cell and
|
||||||
// our first cell and they take priority, so reduce our height by
|
// they take priority, so reduce our height by (minHeight - remainder) to account for that.
|
||||||
// (minHeight - remainder) to account for that. We need to fill that
|
// We need to fill that gap and reach the next cell before we take priority.
|
||||||
// gap and reach the next cell before we take priority.
|
|
||||||
if (rem != 0.0f)
|
if (rem != 0.0f)
|
||||||
height -= (DefaultHeight - rem);
|
height -= (DefaultHeight - rem);
|
||||||
|
|
||||||
@ -107,10 +106,10 @@ namespace UnityExplorer.UI.Widgets
|
|||||||
rangeCache.RemoveAt(rangeCache.Count - 1);
|
rangeCache.RemoveAt(rangeCache.Count - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Get the data index at the specific position of the total height cache.</summary>
|
/// <summary>Get the data index at the specified position of the total height cache.</summary>
|
||||||
public int GetDataIndexAtPosition(float desiredHeight) => GetDataIndexAtPosition(desiredHeight, out _);
|
public int GetDataIndexAtPosition(float desiredHeight) => GetDataIndexAtPosition(desiredHeight, out _);
|
||||||
|
|
||||||
/// <summary>Get the data index at the specific position of the total height cache.</summary>
|
/// <summary>Get the data index and DataViewInfo at the specified position of the total height cache.</summary>
|
||||||
public int GetDataIndexAtPosition(float desiredHeight, out DataViewInfo cache)
|
public int GetDataIndexAtPosition(float desiredHeight, out DataViewInfo cache)
|
||||||
{
|
{
|
||||||
cache = default;
|
cache = default;
|
||||||
@ -135,18 +134,18 @@ namespace UnityExplorer.UI.Widgets
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Set a given data index with the specified value.</summary>
|
/// <summary>Set a given data index with the specified value.</summary>
|
||||||
public void SetIndex(int dataIndex, float height, bool inRebuild = false)
|
public void SetIndex(int dataIndex, float height)
|
||||||
{
|
{
|
||||||
|
// If the index being set is beyond the DataSource item count, prune and return.
|
||||||
if (dataIndex >= ScrollPool.DataSource.ItemCount)
|
if (dataIndex >= ScrollPool.DataSource.ItemCount)
|
||||||
{
|
{
|
||||||
if (heightCache.Count > dataIndex)
|
while (heightCache.Count > dataIndex)
|
||||||
{
|
RemoveLast();
|
||||||
while (heightCache.Count > dataIndex)
|
|
||||||
RemoveLast();
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If the data index exceeds our cache count, fill the gap.
|
||||||
|
// This is done by the ScrollPool when the DataSource sets its initial count, or the count increases.
|
||||||
if (dataIndex >= heightCache.Count)
|
if (dataIndex >= heightCache.Count)
|
||||||
{
|
{
|
||||||
while (dataIndex > heightCache.Count)
|
while (dataIndex > heightCache.Count)
|
||||||
@ -155,12 +154,11 @@ namespace UnityExplorer.UI.Widgets
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We are actually updating an index. First, update the height and the totalHeight.
|
||||||
var cache = heightCache[dataIndex];
|
var cache = heightCache[dataIndex];
|
||||||
var prevHeight = cache.height;
|
if (cache.height != height)
|
||||||
|
|
||||||
var diff = height - prevHeight;
|
|
||||||
if (diff != 0.0f)
|
|
||||||
{
|
{
|
||||||
|
var diff = height - cache.height;
|
||||||
totalHeight += diff;
|
totalHeight += diff;
|
||||||
cache.height = height;
|
cache.height = height;
|
||||||
}
|
}
|
||||||
@ -172,93 +170,71 @@ namespace UnityExplorer.UI.Widgets
|
|||||||
cache.startPosition = prev.startPosition + prev.height;
|
cache.startPosition = prev.startPosition + prev.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get the normalized range index (actually ceiling) and spread based on our start position and height
|
||||||
int rangeIndex = GetRangeCeilingOfPosition(cache.startPosition);
|
int rangeIndex = GetRangeCeilingOfPosition(cache.startPosition);
|
||||||
int spread = GetRangeSpread(cache.startPosition, height);
|
int spread = GetRangeSpread(cache.startPosition, height);
|
||||||
|
|
||||||
if (rangeCache.Count <= rangeIndex)
|
// If the previous item in the range cache is not the previous data index, there is a gap.
|
||||||
|
if (dataIndex > 0 && rangeCache.Count > rangeIndex && rangeCache[rangeIndex - 1] != (dataIndex - 1))
|
||||||
{
|
{
|
||||||
if (rangeCache[rangeCache.Count - 1] != dataIndex - 1)
|
// Recalculate start positions up to this index. The gap could be anywhere.
|
||||||
{
|
RecalculateStartPositions(dataIndex);
|
||||||
// The previous index in the range cache is not the previous data index for the data we were given.
|
// Get the range index and spread again after rebuilding
|
||||||
// Need to rebuild.
|
rangeIndex = GetRangeCeilingOfPosition(cache.startPosition);
|
||||||
if (!inRebuild)
|
spread = GetRangeSpread(cache.startPosition, height);
|
||||||
RebuildCache();
|
|
||||||
else
|
|
||||||
throw new Exception($"DataHeightCache rebuild failed. Trying to set {rangeIndex} but current count is {rangeCache.Count}!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Should never happen
|
||||||
|
if (rangeCache.Count <= rangeIndex || rangeCache[rangeIndex] != dataIndex)
|
||||||
|
throw new Exception($"Trying to set range index but cache is corrupt after rebuild!\r\n" +
|
||||||
|
$"dataIndex: {dataIndex}, rangeIndex: {rangeIndex}, rangeCache.Count: {rangeCache.Count}, " +
|
||||||
|
$"startPos: {cache.startPosition}/{TotalHeight}");
|
||||||
|
|
||||||
if (spread != cache.normalizedSpread)
|
if (spread != cache.normalizedSpread)
|
||||||
{
|
{
|
||||||
// The cell's spread has changed, need to update.
|
ExplorerCore.Log("Updating spread for " + dataIndex + " from " + cache.normalizedSpread + " to " + spread);
|
||||||
|
|
||||||
int spreadDiff = spread - cache.normalizedSpread;
|
int spreadDiff = spread - cache.normalizedSpread;
|
||||||
cache.normalizedSpread = spread;
|
cache.normalizedSpread = spread;
|
||||||
|
|
||||||
if (rangeCache[rangeIndex] != dataIndex)
|
SetSpread(dataIndex, rangeIndex, spreadDiff);
|
||||||
{
|
|
||||||
// In some rare cases we may not find our data index at the expected range index.
|
|
||||||
// We can make some educated guesses and find the real index pretty quickly.
|
|
||||||
int minStart = GetRangeIndexOfPosition(dataIndex * DefaultHeight);
|
|
||||||
if (minStart < 0) minStart = 0;
|
|
||||||
for (int i = minStart; i < rangeCache.Count; i++)
|
|
||||||
{
|
|
||||||
if (rangeCache[i] == dataIndex)
|
|
||||||
{
|
|
||||||
rangeIndex = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we somehow reached the end and didn't find the data index...
|
|
||||||
if (i == rangeCache.Count - 1)
|
|
||||||
{
|
|
||||||
if (!inRebuild)
|
|
||||||
RebuildCache();
|
|
||||||
else
|
|
||||||
ExplorerCore.LogWarning($"DataHeightCache: Looking for range index of data {dataIndex} but " +
|
|
||||||
$"reached the end and didn't find it. Count: {rangeCache.Count}, last index: {rangeCache[rangeCache.Count - 1]}");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// our data index is further down. add the min difference and try again.
|
|
||||||
// the iterator will add 1 on the next loop so account for that.
|
|
||||||
|
|
||||||
int jmp = dataIndex - rangeCache[i] - 1;
|
|
||||||
i = (jmp < 1 ? i : i + jmp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (spreadDiff > 0)
|
|
||||||
{
|
|
||||||
// need to insert
|
|
||||||
for (int i = 0; i < spreadDiff; i++)
|
|
||||||
{
|
|
||||||
if (rangeCache[rangeIndex] == dataIndex)
|
|
||||||
rangeCache.Insert(rangeIndex, dataIndex);
|
|
||||||
else
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// need to remove
|
|
||||||
for (int i = 0; i < -spreadDiff; i++)
|
|
||||||
{
|
|
||||||
if (rangeCache[rangeIndex] == dataIndex)
|
|
||||||
rangeCache.RemoveAt(rangeIndex);
|
|
||||||
else
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RebuildCache()
|
private void SetSpread(int dataIndex, int rangeIndex, int spreadDiff)
|
||||||
{
|
{
|
||||||
//start at 1 because 0's start pos is always 0
|
if (spreadDiff > 0)
|
||||||
for (int i = 1; i < heightCache.Count; i++)
|
{
|
||||||
SetIndex(i, heightCache[i].height, true);
|
for (int i = 0; i < spreadDiff; i++)
|
||||||
|
rangeCache.Insert(rangeIndex, dataIndex);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (int i = 0; i < -spreadDiff; i++)
|
||||||
|
rangeCache.RemoveAt(rangeIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RecalculateStartPositions(int toIndex)
|
||||||
|
{
|
||||||
|
if (heightCache.Count < 2)
|
||||||
|
return;
|
||||||
|
|
||||||
|
DataViewInfo cache;
|
||||||
|
DataViewInfo prev = heightCache[0];
|
||||||
|
for (int i = 1; i <= toIndex && i < heightCache.Count; i++)
|
||||||
|
{
|
||||||
|
cache = heightCache[i];
|
||||||
|
|
||||||
|
cache.startPosition = prev.startPosition + prev.height;
|
||||||
|
|
||||||
|
var prevSpread = cache.normalizedSpread;
|
||||||
|
cache.normalizedSpread = GetRangeSpread(cache.startPosition, cache.height);
|
||||||
|
if (cache.normalizedSpread != prevSpread)
|
||||||
|
SetSpread(i, GetRangeCeilingOfPosition(cache.startPosition), cache.normalizedSpread - prevSpread);
|
||||||
|
|
||||||
|
prev = cache;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -98,6 +98,7 @@ namespace UnityExplorer.UI.Widgets
|
|||||||
private float timeofLastWriteLock;
|
private float timeofLastWriteLock;
|
||||||
|
|
||||||
private float prevContentHeight = 1.0f;
|
private float prevContentHeight = 1.0f;
|
||||||
|
private event Action onHeightChanged;
|
||||||
|
|
||||||
public override void Update()
|
public override void Update()
|
||||||
{
|
{
|
||||||
@ -116,6 +117,8 @@ namespace UnityExplorer.UI.Widgets
|
|||||||
prevContentHeight = Content.rect.height;
|
prevContentHeight = Content.rect.height;
|
||||||
if (!writingLocked)
|
if (!writingLocked)
|
||||||
OnValueChangedListener(Vector2.zero);
|
OnValueChangedListener(Vector2.zero);
|
||||||
|
|
||||||
|
onHeightChanged?.Invoke();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
@ -138,7 +141,7 @@ namespace UnityExplorer.UI.Widgets
|
|||||||
//private bool Initialized;
|
//private bool Initialized;
|
||||||
|
|
||||||
/// <summary>Should be called only once, when the scroll pool is created.</summary>
|
/// <summary>Should be called only once, when the scroll pool is created.</summary>
|
||||||
public void Initialize(IPoolDataSource<T> dataSource)
|
public void Initialize(IPoolDataSource<T> dataSource, Action onHeightChangedListener = null)
|
||||||
{
|
{
|
||||||
this.DataSource = dataSource;
|
this.DataSource = dataSource;
|
||||||
HeightCache = new DataHeightCache<T>(this);
|
HeightCache = new DataHeightCache<T>(this);
|
||||||
@ -153,14 +156,16 @@ namespace UnityExplorer.UI.Widgets
|
|||||||
ScrollRect.vertical = true;
|
ScrollRect.vertical = true;
|
||||||
ScrollRect.horizontal = false;
|
ScrollRect.horizontal = false;
|
||||||
|
|
||||||
LayoutRebuilder.ForceRebuildLayoutImmediate(Content);
|
RuntimeProvider.Instance.StartCoroutine(InitCoroutine(onHeightChangedListener));
|
||||||
RuntimeProvider.Instance.StartCoroutine(InitCoroutine());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private IEnumerator InitCoroutine()
|
private readonly WaitForEndOfFrame waitForEndOfFrame = new WaitForEndOfFrame();
|
||||||
|
|
||||||
|
private IEnumerator InitCoroutine(Action onHeightChangedListener)
|
||||||
{
|
{
|
||||||
ScrollRect.content.anchoredPosition = Vector2.zero;
|
ScrollRect.content.anchoredPosition = Vector2.zero;
|
||||||
yield return null;
|
//yield return null;
|
||||||
|
yield return waitForEndOfFrame;
|
||||||
|
|
||||||
LayoutRebuilder.ForceRebuildLayoutImmediate(Content);
|
LayoutRebuilder.ForceRebuildLayoutImmediate(Content);
|
||||||
|
|
||||||
@ -184,7 +189,8 @@ namespace UnityExplorer.UI.Widgets
|
|||||||
// add onValueChanged listener after setup
|
// add onValueChanged listener after setup
|
||||||
ScrollRect.onValueChanged.AddListener(OnValueChangedListener);
|
ScrollRect.onValueChanged.AddListener(OnValueChangedListener);
|
||||||
|
|
||||||
ExplorerCore.Log("ScrollPool Init finished");
|
onHeightChanged += onHeightChangedListener;
|
||||||
|
onHeightChangedListener?.Invoke();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetScrollBounds()
|
private void SetScrollBounds()
|
||||||
@ -564,7 +570,11 @@ namespace UnityExplorer.UI.Widgets
|
|||||||
|
|
||||||
var scrollPos = topPos + Content.anchoredPosition.y;
|
var scrollPos = topPos + Content.anchoredPosition.y;
|
||||||
|
|
||||||
val = (float)((decimal)scrollPos / (decimal)(TotalDataHeight - Viewport.rect.height));
|
var viewHeight = TotalDataHeight - Viewport.rect.height;
|
||||||
|
if (viewHeight != 0.0f)
|
||||||
|
val = (float)((decimal)scrollPos / (decimal)(viewHeight));
|
||||||
|
else
|
||||||
|
val = 0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool prev = writingLocked;
|
bool prev = writingLocked;
|
||||||
|
@ -75,6 +75,8 @@
|
|||||||
<AssemblyName>UnityExplorer.BIE5.Mono</AssemblyName>
|
<AssemblyName>UnityExplorer.BIE5.Mono</AssemblyName>
|
||||||
<IsCpp>false</IsCpp>
|
<IsCpp>false</IsCpp>
|
||||||
<IsBepInEx>true</IsBepInEx>
|
<IsBepInEx>true</IsBepInEx>
|
||||||
|
<DebugType>none</DebugType>
|
||||||
|
<DebugSymbols>false</DebugSymbols>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<!-- STANDALONE IL2CPP -->
|
<!-- STANDALONE IL2CPP -->
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release_STANDALONE_Mono|AnyCPU'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release_STANDALONE_Mono|AnyCPU'">
|
||||||
@ -234,20 +236,25 @@
|
|||||||
<Compile Include="Inspectors_OLD\Reflection\StaticInspector.cs" />
|
<Compile Include="Inspectors_OLD\Reflection\StaticInspector.cs" />
|
||||||
<Compile Include="UI\CSConsole\CSConsoleManager.cs" />
|
<Compile Include="UI\CSConsole\CSConsoleManager.cs" />
|
||||||
<Compile Include="UI\Inspectors\CacheObject\CacheField.cs" />
|
<Compile Include="UI\Inspectors\CacheObject\CacheField.cs" />
|
||||||
|
<Compile Include="UI\Inspectors\CacheObject\CacheKeyValuePair.cs" />
|
||||||
<Compile Include="UI\Inspectors\CacheObject\CacheListEntry.cs" />
|
<Compile Include="UI\Inspectors\CacheObject\CacheListEntry.cs" />
|
||||||
<Compile Include="UI\Inspectors\CacheObject\CacheMember.cs" />
|
<Compile Include="UI\Inspectors\CacheObject\CacheMember.cs" />
|
||||||
<Compile Include="UI\Inspectors\CacheObject\CacheMethod.cs" />
|
<Compile Include="UI\Inspectors\CacheObject\CacheMethod.cs" />
|
||||||
<Compile Include="UI\Inspectors\CacheObject\CacheObjectBase.cs" />
|
<Compile Include="UI\Inspectors\CacheObject\CacheObjectBase.cs" />
|
||||||
<Compile Include="UI\Inspectors\CacheObject\CacheProperty.cs" />
|
<Compile Include="UI\Inspectors\CacheObject\CacheProperty.cs" />
|
||||||
|
<Compile Include="UI\Inspectors\CacheObject\Views\CacheKeyValuePairCell.cs" />
|
||||||
<Compile Include="UI\Inspectors\CacheObject\Views\CacheListEntryCell.cs" />
|
<Compile Include="UI\Inspectors\CacheObject\Views\CacheListEntryCell.cs" />
|
||||||
<Compile Include="UI\Inspectors\CacheObject\Views\CacheMemberCell.cs" />
|
<Compile Include="UI\Inspectors\CacheObject\Views\CacheMemberCell.cs" />
|
||||||
<Compile Include="UI\Inspectors\CacheObject\Views\CacheObjectCell.cs" />
|
<Compile Include="UI\Inspectors\CacheObject\Views\CacheObjectCell.cs" />
|
||||||
<Compile Include="UI\Inspectors\GameObjectInspector.cs" />
|
<Compile Include="UI\Inspectors\GameObjectInspector.cs" />
|
||||||
|
<Compile Include="UI\Inspectors\ICacheObjectController.cs" />
|
||||||
<Compile Include="UI\Inspectors\InspectorManager.cs" />
|
<Compile Include="UI\Inspectors\InspectorManager.cs" />
|
||||||
<Compile Include="UI\Inspectors\InspectorTab.cs" />
|
<Compile Include="UI\Inspectors\InspectorTab.cs" />
|
||||||
<Compile Include="UI\Inspectors\InspectorBase.cs" />
|
<Compile Include="UI\Inspectors\InspectorBase.cs" />
|
||||||
|
<Compile Include="UI\Inspectors\IValues\InteractiveDictionary.cs" />
|
||||||
<Compile Include="UI\Inspectors\IValues\InteractiveList.cs" />
|
<Compile Include="UI\Inspectors\IValues\InteractiveList.cs" />
|
||||||
<Compile Include="UI\Inspectors\IValues\InteractiveValue.cs" />
|
<Compile Include="UI\Inspectors\IValues\InteractiveValue.cs" />
|
||||||
|
<Compile Include="UI\Inspectors\ListInspector.cs" />
|
||||||
<Compile Include="UI\Inspectors\ReflectionInspector.cs" />
|
<Compile Include="UI\Inspectors\ReflectionInspector.cs" />
|
||||||
<Compile Include="UI\ObjectPool\IPooledObject.cs" />
|
<Compile Include="UI\ObjectPool\IPooledObject.cs" />
|
||||||
<Compile Include="UI\ObjectPool\Pool.cs" />
|
<Compile Include="UI\ObjectPool\Pool.cs" />
|
||||||
|
Loading…
x
Reference in New Issue
Block a user