2021-04-26 19:56:21 +10:00
|
|
|
|
using System;
|
2021-04-27 21:22:48 +10:00
|
|
|
|
using System.Collections;
|
2021-04-26 19:56:21 +10:00
|
|
|
|
using System.Collections.Generic;
|
2021-04-27 21:22:48 +10:00
|
|
|
|
using System.IO;
|
2021-04-26 19:56:21 +10:00
|
|
|
|
using System.Linq;
|
2021-04-27 21:22:48 +10:00
|
|
|
|
using System.Reflection;
|
2021-04-26 19:56:21 +10:00
|
|
|
|
using System.Text;
|
|
|
|
|
using UnityEngine;
|
2021-04-27 21:22:48 +10:00
|
|
|
|
using UnityEngine.UI;
|
|
|
|
|
using UnityExplorer.UI.Inspectors.CacheObject;
|
|
|
|
|
using UnityExplorer.UI.Inspectors.CacheObject.Views;
|
|
|
|
|
using UnityExplorer.UI.ObjectPool;
|
|
|
|
|
using UnityExplorer.UI.Panels;
|
|
|
|
|
using UnityExplorer.UI.Utility;
|
|
|
|
|
using UnityExplorer.UI.Widgets;
|
2021-04-26 19:56:21 +10:00
|
|
|
|
|
|
|
|
|
namespace UnityExplorer.UI.Inspectors
|
|
|
|
|
{
|
2021-04-27 21:22:48 +10:00
|
|
|
|
public class ReflectionInspector : InspectorBase, IPoolDataSource<CacheMemberCell>
|
|
|
|
|
{
|
|
|
|
|
public bool StaticOnly { get; internal set; }
|
2021-04-26 19:56:21 +10:00
|
|
|
|
|
2021-04-27 21:22:48 +10:00
|
|
|
|
public object Target { get; private set; }
|
|
|
|
|
public Type TargetType { get; private set; }
|
2021-04-26 19:56:21 +10:00
|
|
|
|
|
2021-04-27 21:22:48 +10:00
|
|
|
|
public ScrollPool<CacheMemberCell> MemberScrollPool { get; private set; }
|
|
|
|
|
|
|
|
|
|
private List<CacheMember> members = new List<CacheMember>();
|
|
|
|
|
private readonly List<CacheMember> filteredMembers = new List<CacheMember>();
|
2021-04-29 21:01:08 +10:00
|
|
|
|
private readonly HashSet<CacheMember> displayedMembers = new HashSet<CacheMember>();
|
2021-04-27 21:22:48 +10:00
|
|
|
|
|
|
|
|
|
public override GameObject UIRoot => uiRoot;
|
|
|
|
|
private GameObject uiRoot;
|
|
|
|
|
|
|
|
|
|
public Text NameText;
|
|
|
|
|
public Text AssemblyText;
|
|
|
|
|
|
|
|
|
|
private LayoutElement memberTitleLayout;
|
|
|
|
|
|
2021-04-30 21:34:50 +10:00
|
|
|
|
private Toggle autoUpdateToggle;
|
|
|
|
|
|
2021-04-27 21:22:48 +10:00
|
|
|
|
public override void OnBorrowedFromPool(object target)
|
|
|
|
|
{
|
|
|
|
|
base.OnBorrowedFromPool(target);
|
|
|
|
|
|
|
|
|
|
SetTitleLayouts();
|
|
|
|
|
SetTarget(target);
|
|
|
|
|
|
2021-04-30 21:34:50 +10:00
|
|
|
|
MemberScrollPool.Initialize(this);
|
2021-04-27 21:22:48 +10:00
|
|
|
|
RuntimeProvider.Instance.StartCoroutine(InitCoroutine());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private IEnumerator InitCoroutine()
|
|
|
|
|
{
|
|
|
|
|
yield return null;
|
|
|
|
|
|
|
|
|
|
LayoutRebuilder.ForceRebuildLayoutImmediate(InspectorPanel.Instance.ContentRect);
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-29 21:01:08 +10:00
|
|
|
|
public override void OnReturnToPool()
|
|
|
|
|
{
|
|
|
|
|
foreach (var member in members)
|
|
|
|
|
member.OnDestroyed();
|
|
|
|
|
|
|
|
|
|
// release all cachememberviews
|
|
|
|
|
MemberScrollPool.ReturnCells();
|
|
|
|
|
MemberScrollPool.SetUninitialized();
|
|
|
|
|
|
|
|
|
|
members.Clear();
|
|
|
|
|
filteredMembers.Clear();
|
|
|
|
|
displayedMembers.Clear();
|
|
|
|
|
|
2021-04-30 21:34:50 +10:00
|
|
|
|
autoUpdateToggle.isOn = false;
|
|
|
|
|
|
2021-04-29 21:01:08 +10:00
|
|
|
|
base.OnReturnToPool();
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-27 21:22:48 +10:00
|
|
|
|
private void SetTarget(object target)
|
|
|
|
|
{
|
|
|
|
|
string prefix;
|
|
|
|
|
if (StaticOnly)
|
|
|
|
|
{
|
|
|
|
|
Target = null;
|
|
|
|
|
TargetType = target as Type;
|
|
|
|
|
prefix = "[S]";
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
Target = target;
|
|
|
|
|
TargetType = target.GetActualType();
|
|
|
|
|
prefix = "[R]";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NameText.text = SignatureHighlighter.ParseFullSyntax(TargetType, true);
|
|
|
|
|
|
|
|
|
|
string asmText;
|
|
|
|
|
if (TargetType.Assembly != null && !string.IsNullOrEmpty(TargetType.Assembly.Location))
|
|
|
|
|
asmText = Path.GetFileName(TargetType.Assembly.Location);
|
|
|
|
|
else
|
|
|
|
|
asmText = $"{TargetType.Assembly.GetName().Name} <color=grey><i>(in memory)</i></color>";
|
|
|
|
|
AssemblyText.text = $"<color=grey>Assembly:</color> {asmText}";
|
|
|
|
|
|
2021-04-28 23:58:13 +10:00
|
|
|
|
Tab.TabText.text = $"{prefix} {SignatureHighlighter.ParseFullType(TargetType)}";
|
2021-04-27 21:22:48 +10:00
|
|
|
|
|
|
|
|
|
this.members = CacheMember.GetCacheMembers(Target, TargetType, this);
|
|
|
|
|
FilterMembers();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void FilterMembers()
|
|
|
|
|
{
|
|
|
|
|
// todo
|
|
|
|
|
for (int i = 0; i < members.Count; i++)
|
|
|
|
|
{
|
|
|
|
|
var member = members[i];
|
|
|
|
|
filteredMembers.Add(member);
|
|
|
|
|
}
|
2021-04-30 21:34:50 +10:00
|
|
|
|
|
|
|
|
|
//MemberScrollPool.RecreateHeightCache();
|
2021-04-27 21:22:48 +10:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override void OnSetActive()
|
|
|
|
|
{
|
|
|
|
|
base.OnSetActive();
|
|
|
|
|
}
|
2021-04-26 19:56:21 +10:00
|
|
|
|
|
2021-04-27 21:22:48 +10:00
|
|
|
|
public override void OnSetInactive()
|
2021-04-26 19:56:21 +10:00
|
|
|
|
{
|
2021-04-27 21:22:48 +10:00
|
|
|
|
base.OnSetInactive();
|
2021-04-26 19:56:21 +10:00
|
|
|
|
}
|
|
|
|
|
|
2021-04-29 21:01:08 +10:00
|
|
|
|
protected override void OnCloseClicked()
|
|
|
|
|
{
|
|
|
|
|
InspectorManager.ReleaseInspector(this);
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-27 21:22:48 +10:00
|
|
|
|
private float timeOfLastUpdate;
|
|
|
|
|
|
2021-04-26 19:56:21 +10:00
|
|
|
|
public override void Update()
|
|
|
|
|
{
|
2021-04-27 21:22:48 +10:00
|
|
|
|
if (!this.IsActive)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (!StaticOnly && Target.IsNullOrDestroyed(false))
|
|
|
|
|
{
|
|
|
|
|
InspectorManager.ReleaseInspector(this);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-29 21:01:08 +10:00
|
|
|
|
if (Time.time - timeOfLastUpdate > 1f)
|
2021-04-27 21:22:48 +10:00
|
|
|
|
{
|
|
|
|
|
timeOfLastUpdate = Time.time;
|
|
|
|
|
|
2021-04-29 21:01:08 +10:00
|
|
|
|
UpdateDisplayedMembers(true);
|
2021-04-27 21:22:48 +10:00
|
|
|
|
}
|
2021-04-26 19:56:21 +10:00
|
|
|
|
}
|
|
|
|
|
|
2021-04-29 21:01:08 +10:00
|
|
|
|
private void UpdateDisplayedMembers()
|
2021-04-26 19:56:21 +10:00
|
|
|
|
{
|
2021-04-29 21:01:08 +10:00
|
|
|
|
UpdateDisplayedMembers(false);
|
2021-04-27 21:22:48 +10:00
|
|
|
|
}
|
|
|
|
|
|
2021-04-29 21:01:08 +10:00
|
|
|
|
private void UpdateDisplayedMembers(bool onlyAutoUpdate)
|
2021-04-27 21:22:48 +10:00
|
|
|
|
{
|
2021-04-29 21:01:08 +10:00
|
|
|
|
bool shouldRefresh = false;
|
|
|
|
|
foreach (var member in displayedMembers)
|
|
|
|
|
{
|
2021-04-30 21:34:50 +10:00
|
|
|
|
if (member.ShouldAutoEvaluate && (!onlyAutoUpdate || member.AutoUpdateWanted))
|
2021-04-29 21:01:08 +10:00
|
|
|
|
{
|
|
|
|
|
shouldRefresh = true;
|
|
|
|
|
member.Evaluate();
|
2021-04-30 21:34:50 +10:00
|
|
|
|
member.SetCell(member.CellView);
|
2021-04-29 21:01:08 +10:00
|
|
|
|
}
|
|
|
|
|
}
|
2021-04-27 21:22:48 +10:00
|
|
|
|
|
2021-04-29 21:01:08 +10:00
|
|
|
|
if (shouldRefresh)
|
|
|
|
|
MemberScrollPool.RefreshCells(false);
|
2021-04-27 21:22:48 +10:00
|
|
|
|
}
|
|
|
|
|
|
2021-04-29 21:01:08 +10:00
|
|
|
|
// Member cells
|
2021-04-28 20:47:48 +10:00
|
|
|
|
|
2021-04-29 21:01:08 +10:00
|
|
|
|
public int ItemCount => filteredMembers.Count;
|
2021-04-27 21:22:48 +10:00
|
|
|
|
|
2021-04-29 21:01:08 +10:00
|
|
|
|
public void OnCellBorrowed(CacheMemberCell cell)
|
2021-04-28 20:47:48 +10:00
|
|
|
|
{
|
2021-04-29 21:01:08 +10:00
|
|
|
|
cell.CurrentOwner = this;
|
2021-04-28 20:47:48 +10:00
|
|
|
|
}
|
2021-04-27 21:22:48 +10:00
|
|
|
|
|
2021-04-28 20:47:48 +10:00
|
|
|
|
public void OnCellReturned(CacheMemberCell cell)
|
|
|
|
|
{
|
|
|
|
|
cell.OnReturnToPool();
|
2021-04-27 21:22:48 +10:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void SetCell(CacheMemberCell cell, int index)
|
|
|
|
|
{
|
|
|
|
|
if (index < 0 || index >= filteredMembers.Count)
|
|
|
|
|
{
|
2021-04-30 21:34:50 +10:00
|
|
|
|
if (cell.Occupant != null)
|
2021-04-29 21:01:08 +10:00
|
|
|
|
{
|
2021-04-30 21:34:50 +10:00
|
|
|
|
if (displayedMembers.Contains(cell.MemberOccupant))
|
|
|
|
|
displayedMembers.Remove(cell.MemberOccupant);
|
2021-04-29 21:01:08 +10:00
|
|
|
|
|
2021-04-30 21:34:50 +10:00
|
|
|
|
cell.Occupant.CellView = null;
|
2021-04-29 21:01:08 +10:00
|
|
|
|
}
|
|
|
|
|
|
2021-04-27 21:22:48 +10:00
|
|
|
|
cell.Disable();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-28 20:47:48 +10:00
|
|
|
|
var member = filteredMembers[index];
|
2021-04-29 21:01:08 +10:00
|
|
|
|
|
2021-04-30 21:34:50 +10:00
|
|
|
|
if (member != cell.Occupant)
|
2021-04-29 21:01:08 +10:00
|
|
|
|
{
|
2021-04-30 21:34:50 +10:00
|
|
|
|
if (cell.Occupant != null)
|
2021-04-29 21:01:08 +10:00
|
|
|
|
{
|
2021-04-30 21:34:50 +10:00
|
|
|
|
cell.Occupant.HideIValue();
|
|
|
|
|
displayedMembers.Remove(cell.MemberOccupant);
|
|
|
|
|
cell.Occupant.CellView = null;
|
2021-04-29 21:01:08 +10:00
|
|
|
|
}
|
|
|
|
|
|
2021-04-30 21:34:50 +10:00
|
|
|
|
cell.Occupant = member;
|
|
|
|
|
member.CellView = cell;
|
2021-04-29 21:01:08 +10:00
|
|
|
|
displayedMembers.Add(member);
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-28 20:47:48 +10:00
|
|
|
|
member.SetCell(cell);
|
2021-04-27 21:22:48 +10:00
|
|
|
|
|
|
|
|
|
SetCellLayout(cell);
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-30 21:34:50 +10:00
|
|
|
|
private void ToggleAllAutoUpdateStates(bool state)
|
|
|
|
|
{
|
|
|
|
|
if (members == null || !members.Any())
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
foreach (var member in members)
|
|
|
|
|
member.AutoUpdateWanted = state;
|
|
|
|
|
|
|
|
|
|
foreach (var cell in MemberScrollPool.CellPool)
|
|
|
|
|
cell.UpdateToggle.isOn = state;
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-28 20:47:48 +10:00
|
|
|
|
// Cell layout (fake table alignment)
|
|
|
|
|
|
|
|
|
|
private static float MemLabelWidth { get; set; }
|
|
|
|
|
private static float RightGroupWidth { get; set; }
|
2021-04-27 21:22:48 +10:00
|
|
|
|
|
|
|
|
|
private void SetTitleLayouts()
|
|
|
|
|
{
|
2021-04-28 20:47:48 +10:00
|
|
|
|
// Calculate sizes
|
|
|
|
|
MemLabelWidth = Math.Max(200, Math.Min(450f, 0.4f * InspectorManager.PanelWidth - 5));
|
|
|
|
|
RightGroupWidth = Math.Max(200, InspectorManager.PanelWidth - MemLabelWidth - 55);
|
|
|
|
|
|
2021-04-27 21:22:48 +10:00
|
|
|
|
memberTitleLayout.minWidth = MemLabelWidth;
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-30 21:34:50 +10:00
|
|
|
|
private void SetCellLayout(CacheObjectCell cell)
|
2021-04-27 21:22:48 +10:00
|
|
|
|
{
|
|
|
|
|
cell.MemberLayout.minWidth = MemLabelWidth;
|
|
|
|
|
cell.RightGroupLayout.minWidth = RightGroupWidth;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
internal void SetLayouts()
|
|
|
|
|
{
|
|
|
|
|
SetTitleLayouts();
|
|
|
|
|
|
|
|
|
|
foreach (var cell in MemberScrollPool.CellPool)
|
|
|
|
|
SetCellLayout(cell);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override GameObject CreateContent(GameObject parent)
|
|
|
|
|
{
|
|
|
|
|
uiRoot = UIFactory.CreateVerticalGroup(parent, "ReflectionInspector", true, true, true, true, 5,
|
|
|
|
|
new Vector4(4, 4, 4, 4), new Color(0.12f, 0.12f, 0.12f));
|
|
|
|
|
|
2021-04-29 21:01:08 +10:00
|
|
|
|
// Class name, assembly. TODO more details
|
|
|
|
|
|
2021-04-27 21:22:48 +10:00
|
|
|
|
NameText = UIFactory.CreateLabel(uiRoot, "Title", "not set", TextAnchor.MiddleLeft, fontSize: 20);
|
|
|
|
|
UIFactory.SetLayoutElement(NameText.gameObject, minHeight: 25, flexibleHeight: 0);
|
|
|
|
|
|
|
|
|
|
AssemblyText = UIFactory.CreateLabel(uiRoot, "AssemblyLabel", "not set", TextAnchor.MiddleLeft);
|
|
|
|
|
UIFactory.SetLayoutElement(AssemblyText.gameObject, minHeight: 25, flexibleWidth: 9999);
|
|
|
|
|
|
2021-04-29 21:01:08 +10:00
|
|
|
|
// TODO filter row
|
|
|
|
|
|
|
|
|
|
// Member list
|
|
|
|
|
|
2021-04-27 21:22:48 +10:00
|
|
|
|
var listTitles = UIFactory.CreateUIObject("ListTitles", uiRoot);
|
|
|
|
|
UIFactory.SetLayoutElement(listTitles, minHeight: 25);
|
|
|
|
|
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(listTitles, true, true, true, true, 5, 1, 1, 1, 1);
|
|
|
|
|
|
|
|
|
|
var memberTitle = UIFactory.CreateLabel(listTitles, "MemberTitle", "Member Name", TextAnchor.LowerLeft, Color.grey, fontSize: 15);
|
|
|
|
|
memberTitleLayout = memberTitle.gameObject.AddComponent<LayoutElement>();
|
|
|
|
|
|
|
|
|
|
var valueTitle = UIFactory.CreateLabel(listTitles, "ValueTitle", "Value", TextAnchor.LowerLeft, Color.grey, fontSize: 15);
|
2021-04-30 21:34:50 +10:00
|
|
|
|
UIFactory.SetLayoutElement(valueTitle.gameObject, minWidth: 50, flexibleWidth: 9999);
|
2021-04-27 21:22:48 +10:00
|
|
|
|
|
2021-04-29 21:01:08 +10:00
|
|
|
|
var updateButton = UIFactory.CreateButton(listTitles, "UpdateButton", "Update values", new Color(0.22f, 0.28f, 0.22f));
|
|
|
|
|
UIFactory.SetLayoutElement(updateButton.Button.gameObject, minHeight: 25, minWidth: 130, flexibleWidth: 0);
|
|
|
|
|
updateButton.OnClick += UpdateDisplayedMembers;
|
|
|
|
|
|
|
|
|
|
var updateText = UIFactory.CreateLabel(listTitles, "AutoUpdateLabel", "Auto-update", TextAnchor.MiddleRight, Color.grey);
|
|
|
|
|
UIFactory.SetLayoutElement(updateText.gameObject, minHeight: 25, minWidth: 80, flexibleWidth: 0);
|
|
|
|
|
|
2021-04-30 21:34:50 +10:00
|
|
|
|
var toggleObj = UIFactory.CreateToggle(listTitles, "AutoUpdateToggle", out autoUpdateToggle, out Text toggleText);
|
|
|
|
|
GameObject.DestroyImmediate(toggleText);
|
|
|
|
|
UIFactory.SetLayoutElement(toggleObj, minHeight: 25, minWidth: 25);
|
|
|
|
|
autoUpdateToggle.isOn = false;
|
|
|
|
|
autoUpdateToggle.onValueChanged.AddListener((bool val) => { ToggleAllAutoUpdateStates(val); });
|
|
|
|
|
|
|
|
|
|
var spacer = UIFactory.CreateUIObject("spacer", listTitles);
|
|
|
|
|
UIFactory.SetLayoutElement(spacer, minWidth: 25, flexibleWidth: 0);
|
|
|
|
|
|
2021-04-29 21:01:08 +10:00
|
|
|
|
// Member scroll pool
|
|
|
|
|
|
2021-04-27 21:22:48 +10:00
|
|
|
|
MemberScrollPool = UIFactory.CreateScrollPool<CacheMemberCell>(uiRoot, "MemberList", out GameObject scrollObj,
|
2021-04-29 21:01:08 +10:00
|
|
|
|
out GameObject _, new Color(0.09f, 0.09f, 0.09f));
|
2021-04-27 21:22:48 +10:00
|
|
|
|
UIFactory.SetLayoutElement(scrollObj, flexibleHeight: 9999);
|
|
|
|
|
|
2021-04-30 21:34:50 +10:00
|
|
|
|
//InspectorPanel.Instance.UIRoot.GetComponent<Mask>().enabled = false;
|
|
|
|
|
//MemberScrollPool.Viewport.GetComponent<Mask>().enabled = false;
|
|
|
|
|
//MemberScrollPool.Viewport.GetComponent<Image>().color = new Color(0.12f, 0.12f, 0.12f);
|
2021-04-27 21:22:48 +10:00
|
|
|
|
|
|
|
|
|
return uiRoot;
|
2021-04-26 19:56:21 +10:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|