mirror of
https://github.com/GrahamKracker/UnityExplorer.git
synced 2025-07-17 08:37:49 +08:00
More progress
This commit is contained in:
@ -7,8 +7,10 @@ using System.Reflection;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.UI.Inspectors.CacheObject;
|
||||
using UnityExplorer.UI.Inspectors.CacheObject.Views;
|
||||
using UnityExplorer.Core.Config;
|
||||
using UnityExplorer.Core.Runtime;
|
||||
using UnityExplorer.UI.CacheObject;
|
||||
using UnityExplorer.UI.CacheObject.Views;
|
||||
using UnityExplorer.UI.ObjectPool;
|
||||
using UnityExplorer.UI.Panels;
|
||||
using UnityExplorer.UI.Utility;
|
||||
@ -20,34 +22,57 @@ namespace UnityExplorer.UI.Inspectors
|
||||
{
|
||||
public CacheObjectBase ParentCacheObject { get; set; }
|
||||
|
||||
public bool StaticOnly { get; internal set; }
|
||||
|
||||
//public object Target { get; private set; }
|
||||
public Type TargetType { get; private set; }
|
||||
public bool CanWrite => true;
|
||||
|
||||
public ScrollPool<CacheMemberCell> MemberScrollPool { get; private set; }
|
||||
// Instance state
|
||||
|
||||
public bool StaticOnly { get; internal set; }
|
||||
|
||||
public BindingFlags FlagsFilter { get; private set; }
|
||||
public string NameFilter { get; private set; }
|
||||
|
||||
public bool AutoUpdateWanted { get; set; }
|
||||
|
||||
private List<CacheMember> members = new List<CacheMember>();
|
||||
private readonly List<CacheMember> filteredMembers = new List<CacheMember>();
|
||||
// private readonly HashSet<CacheMember> displayedMembers = new HashSet<CacheMember>();
|
||||
|
||||
|
||||
// UI
|
||||
|
||||
public ScrollPool<CacheMemberCell> MemberScrollPool { get; private set; }
|
||||
|
||||
public Text NameText;
|
||||
public Text AssemblyText;
|
||||
|
||||
private LayoutElement memberTitleLayout;
|
||||
// Unity object helpers
|
||||
private UnityEngine.Object ObjectRef;
|
||||
private Component ComponentRef;
|
||||
private Texture2D TextureRef;
|
||||
private bool TextureViewerWanted;
|
||||
private GameObject unityObjectRow;
|
||||
private ButtonRef gameObjectButton;
|
||||
private InputField nameInput;
|
||||
private InputField instanceIdInput;
|
||||
private ButtonRef textureButton;
|
||||
private GameObject textureViewer;
|
||||
|
||||
private readonly Color disabledButtonColor = new Color(0.24f, 0.24f, 0.24f);
|
||||
private readonly Color enabledButtonColor = new Color(0.2f, 0.27f, 0.2f);
|
||||
private readonly Dictionary<BindingFlags, ButtonRef> scopeFilterButtons = new Dictionary<BindingFlags, ButtonRef>();
|
||||
private InputField filterInputField;
|
||||
|
||||
//private LayoutElement memberTitleLayout;
|
||||
|
||||
public bool AutoUpdateWanted { get; set; }
|
||||
private Toggle autoUpdateToggle;
|
||||
|
||||
public override void OnBorrowedFromPool(object target)
|
||||
{
|
||||
base.OnBorrowedFromPool(target);
|
||||
CalculateLayouts();
|
||||
|
||||
SetTitleLayouts();
|
||||
SetTarget(target);
|
||||
|
||||
MemberScrollPool.Refresh(true, true);
|
||||
RuntimeProvider.Instance.StartCoroutine(InitCoroutine());
|
||||
}
|
||||
|
||||
@ -58,10 +83,18 @@ namespace UnityExplorer.UI.Inspectors
|
||||
LayoutRebuilder.ForceRebuildLayoutImmediate(InspectorPanel.Instance.ContentRect);
|
||||
}
|
||||
|
||||
protected override void OnCloseClicked()
|
||||
{
|
||||
InspectorManager.ReleaseInspector(this);
|
||||
}
|
||||
|
||||
public override void OnReturnToPool()
|
||||
{
|
||||
foreach (var member in members)
|
||||
{
|
||||
member.UnlinkFromView();
|
||||
member.ReleasePooledObjects();
|
||||
}
|
||||
|
||||
members.Clear();
|
||||
filteredMembers.Clear();
|
||||
@ -69,9 +102,16 @@ namespace UnityExplorer.UI.Inspectors
|
||||
autoUpdateToggle.isOn = false;
|
||||
AutoUpdateWanted = false;
|
||||
|
||||
ObjectRef = null;
|
||||
ComponentRef = null;
|
||||
TextureRef = null;
|
||||
CleanupTextureViewer();
|
||||
|
||||
base.OnReturnToPool();
|
||||
}
|
||||
|
||||
// Setting target
|
||||
|
||||
private void SetTarget(object target)
|
||||
{
|
||||
string prefix;
|
||||
@ -87,50 +127,33 @@ namespace UnityExplorer.UI.Inspectors
|
||||
prefix = "[R]";
|
||||
}
|
||||
|
||||
// Setup main labels and tab text
|
||||
Tab.TabText.text = $"{prefix} {SignatureHighlighter.ParseType(TargetType)}";
|
||||
|
||||
NameText.text = SignatureHighlighter.ParseFullSyntax(TargetType, true);
|
||||
|
||||
string asmText;
|
||||
if (TargetType.Assembly != null && !string.IsNullOrEmpty(TargetType.Assembly.Location))
|
||||
asmText = Path.GetFileName(TargetType.Assembly.Location);
|
||||
asmText = Path.GetFileName(TargetType.Assembly.Location);
|
||||
else
|
||||
asmText = $"{TargetType.Assembly.GetName().Name} <color=grey><i>(in memory)</i></color>";
|
||||
AssemblyText.text = $"<color=grey>Assembly:</color> {asmText}";
|
||||
|
||||
// unity helpers
|
||||
SetUnityTargets();
|
||||
|
||||
// Get cache members, and set filter to default
|
||||
this.members = CacheMember.GetCacheMembers(Target, TargetType, this);
|
||||
FilterMembers();
|
||||
this.filterInputField.text = "";
|
||||
SetFilter("", StaticOnly ? BindingFlags.Static : BindingFlags.Instance);
|
||||
refreshWanted = true;
|
||||
}
|
||||
|
||||
public void FilterMembers()
|
||||
{
|
||||
// todo
|
||||
for (int i = 0; i < members.Count; i++)
|
||||
{
|
||||
var member = members[i];
|
||||
filteredMembers.Add(member);
|
||||
}
|
||||
// Updating
|
||||
|
||||
//MemberScrollPool.Refresh
|
||||
}
|
||||
|
||||
public override void OnSetActive()
|
||||
{
|
||||
base.OnSetActive();
|
||||
}
|
||||
|
||||
public override void OnSetInactive()
|
||||
{
|
||||
base.OnSetInactive();
|
||||
}
|
||||
|
||||
protected override void OnCloseClicked()
|
||||
{
|
||||
InspectorManager.ReleaseInspector(this);
|
||||
}
|
||||
|
||||
private float timeOfLastUpdate;
|
||||
private bool refreshWanted;
|
||||
private string lastNameFilter;
|
||||
private BindingFlags lastFlagsFilter;
|
||||
private float timeOfLastAutoUpdate;
|
||||
|
||||
public override void Update()
|
||||
{
|
||||
@ -143,15 +166,68 @@ namespace UnityExplorer.UI.Inspectors
|
||||
return;
|
||||
}
|
||||
|
||||
if (timeOfLastUpdate.OccuredEarlierThan(1))
|
||||
if (refreshWanted || NameFilter != lastNameFilter || FlagsFilter != lastFlagsFilter)
|
||||
{
|
||||
timeOfLastUpdate = Time.realtimeSinceStartup;
|
||||
lastNameFilter = NameFilter;
|
||||
lastFlagsFilter = FlagsFilter;
|
||||
|
||||
FilterMembers();
|
||||
MemberScrollPool.Refresh(true, true);
|
||||
refreshWanted = false;
|
||||
}
|
||||
|
||||
if (timeOfLastAutoUpdate.OccuredEarlierThan(1))
|
||||
{
|
||||
timeOfLastAutoUpdate = Time.realtimeSinceStartup;
|
||||
|
||||
if (AutoUpdateWanted)
|
||||
UpdateDisplayedMembers();// true);
|
||||
}
|
||||
}
|
||||
|
||||
// Filtering
|
||||
|
||||
public void SetFilter(string filter) => SetFilter(filter, FlagsFilter);
|
||||
|
||||
public void SetFilter(BindingFlags flagsFilter) => SetFilter(NameFilter, flagsFilter);
|
||||
|
||||
public void SetFilter(string nameFilter, BindingFlags flagsFilter)
|
||||
{
|
||||
this.NameFilter = nameFilter;
|
||||
|
||||
if (flagsFilter != FlagsFilter)
|
||||
{
|
||||
var btn = scopeFilterButtons[FlagsFilter].Button;
|
||||
RuntimeProvider.Instance.SetColorBlock(btn, disabledButtonColor, disabledButtonColor * 1.3f);
|
||||
|
||||
this.FlagsFilter = flagsFilter;
|
||||
btn = scopeFilterButtons[FlagsFilter].Button;
|
||||
RuntimeProvider.Instance.SetColorBlock(btn, enabledButtonColor, enabledButtonColor * 1.3f);
|
||||
}
|
||||
}
|
||||
|
||||
private void FilterMembers()
|
||||
{
|
||||
filteredMembers.Clear();
|
||||
|
||||
for (int i = 0; i < members.Count; i++)
|
||||
{
|
||||
var member = members[i];
|
||||
|
||||
if (!string.IsNullOrEmpty(NameFilter) && !member.NameForFiltering.ContainsIgnoreCase(NameFilter))
|
||||
continue;
|
||||
|
||||
if (FlagsFilter != BindingFlags.Default)
|
||||
{
|
||||
if (FlagsFilter == BindingFlags.Instance && member.IsStatic
|
||||
|| FlagsFilter == BindingFlags.Static && !member.IsStatic)
|
||||
continue;
|
||||
}
|
||||
|
||||
filteredMembers.Add(member);
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateDisplayedMembers()// bool onlyAutoUpdate)
|
||||
{
|
||||
bool shouldRefresh = false;
|
||||
@ -164,7 +240,7 @@ namespace UnityExplorer.UI.Inspectors
|
||||
{
|
||||
shouldRefresh = true;
|
||||
member.Evaluate();
|
||||
member.SetCell(member.CellView);
|
||||
member.SetDataToCell(member.CellView);
|
||||
}
|
||||
}
|
||||
|
||||
@ -176,20 +252,14 @@ namespace UnityExplorer.UI.Inspectors
|
||||
|
||||
public int ItemCount => filteredMembers.Count;
|
||||
|
||||
public void OnCellBorrowed(CacheMemberCell cell)
|
||||
{
|
||||
cell.Owner = this;
|
||||
}
|
||||
public void OnCellBorrowed(CacheMemberCell cell) { } // not needed
|
||||
|
||||
public void SetCell(CacheMemberCell cell, int index)
|
||||
{
|
||||
if (index < 0 || index >= filteredMembers.Count)
|
||||
{
|
||||
if (cell.Occupant != null)
|
||||
{
|
||||
cell.Occupant.CellView = null;
|
||||
cell.Occupant = null;
|
||||
}
|
||||
cell.Occupant.UnlinkFromView();
|
||||
|
||||
cell.Disable();
|
||||
return;
|
||||
@ -197,20 +267,11 @@ namespace UnityExplorer.UI.Inspectors
|
||||
|
||||
var member = filteredMembers[index];
|
||||
|
||||
if (member != cell.Occupant)
|
||||
{
|
||||
if (cell.Occupant != null)
|
||||
{
|
||||
cell.Occupant.HidePooledObjects();
|
||||
cell.Occupant.CellView = null;
|
||||
cell.Occupant = null;
|
||||
}
|
||||
if (cell.Occupant != null && member != cell.Occupant)
|
||||
cell.Occupant.UnlinkFromView();
|
||||
|
||||
cell.Occupant = member;
|
||||
member.CellView = cell;
|
||||
}
|
||||
|
||||
member.SetCell(cell);
|
||||
member.SetView(cell);
|
||||
member.SetDataToCell(cell);
|
||||
|
||||
SetCellLayout(cell);
|
||||
}
|
||||
@ -220,13 +281,21 @@ namespace UnityExplorer.UI.Inspectors
|
||||
private static int LeftGroupWidth { get; set; }
|
||||
private static int RightGroupWidth { get; set; }
|
||||
|
||||
private void SetTitleLayouts()
|
||||
internal void SetLayouts()
|
||||
{
|
||||
CalculateLayouts();
|
||||
|
||||
foreach (var cell in MemberScrollPool.CellPool)
|
||||
SetCellLayout(cell);
|
||||
}
|
||||
|
||||
private void CalculateLayouts()
|
||||
{
|
||||
// Calculate sizes
|
||||
LeftGroupWidth = (int)Math.Max(200, (0.45f * InspectorManager.PanelWidth) - 5);// Math.Min(450f, 0.4f * InspectorManager.PanelWidth - 5));
|
||||
RightGroupWidth = (int)Math.Max(200, InspectorManager.PanelWidth - LeftGroupWidth - 55);
|
||||
LeftGroupWidth = (int)Math.Max(200, (0.4f * InspectorManager.PanelWidth) - 5);// Math.Min(450f, 0.4f * InspectorManager.PanelWidth - 5));
|
||||
RightGroupWidth = (int)Math.Max(200, InspectorManager.PanelWidth - LeftGroupWidth - 65);
|
||||
|
||||
memberTitleLayout.minWidth = LeftGroupWidth;
|
||||
//memberTitleLayout.minWidth = LeftGroupWidth;
|
||||
}
|
||||
|
||||
private void SetCellLayout(CacheObjectCell cell)
|
||||
@ -238,57 +307,40 @@ namespace UnityExplorer.UI.Inspectors
|
||||
cell.Occupant.IValue.SetLayout();
|
||||
}
|
||||
|
||||
internal void SetLayouts()
|
||||
{
|
||||
SetTitleLayouts();
|
||||
// UI Construction
|
||||
|
||||
foreach (var cell in MemberScrollPool.CellPool)
|
||||
SetCellLayout(cell);
|
||||
}
|
||||
private GameObject mainContentHolder;
|
||||
|
||||
public override GameObject CreateContent(GameObject parent)
|
||||
{
|
||||
UIRoot = UIFactory.CreateVerticalGroup(parent, "ReflectionInspector", true, true, true, true, 5,
|
||||
new Vector4(4, 4, 4, 4), new Color(0.12f, 0.12f, 0.12f));
|
||||
UIRoot = UIFactory.CreateVerticalGroup(parent, "ReflectionInspector", true, true, true, true, 5,
|
||||
new Vector4(4, 4, 4, 4), new Color(0.065f, 0.065f, 0.065f));
|
||||
|
||||
// Class name, assembly. TODO more details
|
||||
// Class name, assembly
|
||||
|
||||
NameText = UIFactory.CreateLabel(UIRoot, "Title", "not set", TextAnchor.MiddleLeft, fontSize: 20);
|
||||
NameText = UIFactory.CreateLabel(UIRoot, "Title", "not set", TextAnchor.MiddleLeft, fontSize: 17);
|
||||
UIFactory.SetLayoutElement(NameText.gameObject, minHeight: 25, flexibleHeight: 0);
|
||||
|
||||
AssemblyText = UIFactory.CreateLabel(UIRoot, "AssemblyLabel", "not set", TextAnchor.MiddleLeft);
|
||||
UIFactory.SetLayoutElement(AssemblyText.gameObject, minHeight: 25, flexibleWidth: 9999);
|
||||
|
||||
// TODO filter row
|
||||
ConstructUnityObjectRow();
|
||||
|
||||
mainContentHolder = UIFactory.CreateVerticalGroup(UIRoot, "MemberHolder", false, false, true, true, 5, new Vector4(2,2,2,2),
|
||||
new Color(0.12f, 0.12f, 0.12f));
|
||||
UIFactory.SetLayoutElement(mainContentHolder, flexibleWidth: 9999, flexibleHeight: 9999);
|
||||
|
||||
ConstructFilterRow(mainContentHolder);
|
||||
|
||||
// Member list titles
|
||||
|
||||
var listTitles = UIFactory.CreateUIObject("ListTitles", UIRoot);
|
||||
UIFactory.SetLayoutElement(listTitles, minHeight: 25);
|
||||
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(listTitles, true, true, true, true, 5, 1, 1, 1, 1);
|
||||
|
||||
var memberTitle = UIFactory.CreateLabel(listTitles, "MemberTitle", "Member Name", TextAnchor.LowerLeft, Color.grey, fontSize: 15);
|
||||
memberTitleLayout = memberTitle.gameObject.AddComponent<LayoutElement>();
|
||||
|
||||
var valueTitle = UIFactory.CreateLabel(listTitles, "ValueTitle", "Value", TextAnchor.LowerLeft, Color.grey, fontSize: 15);
|
||||
UIFactory.SetLayoutElement(valueTitle.gameObject, minWidth: 50, flexibleWidth: 9999);
|
||||
|
||||
var updateButton = UIFactory.CreateButton(listTitles, "UpdateButton", "Update displayed values", new Color(0.22f, 0.28f, 0.22f));
|
||||
UIFactory.SetLayoutElement(updateButton.Button.gameObject, minHeight: 25, minWidth: 160, flexibleWidth: 0);
|
||||
updateButton.OnClick += UpdateDisplayedMembers;
|
||||
|
||||
var toggleObj = UIFactory.CreateToggle(listTitles, "AutoUpdateToggle", out autoUpdateToggle, out Text toggleText);
|
||||
//GameObject.DestroyImmediate(toggleText);
|
||||
UIFactory.SetLayoutElement(toggleObj, minWidth: 185, minHeight: 25);
|
||||
autoUpdateToggle.isOn = false;
|
||||
autoUpdateToggle.onValueChanged.AddListener((bool val) => { AutoUpdateWanted = val; });
|
||||
toggleText.text = "Auto-update displayed";
|
||||
ConstructUpdateRow(mainContentHolder);
|
||||
|
||||
// Member scroll pool
|
||||
|
||||
MemberScrollPool = UIFactory.CreateScrollPool<CacheMemberCell>(UIRoot, "MemberList", out GameObject scrollObj,
|
||||
var memberBorder = UIFactory.CreateVerticalGroup(mainContentHolder, "ScrollPoolHolder", false, false, true, true, padding: new Vector4(2,2,2,2),
|
||||
bgColor: new Color(0.05f, 0.05f, 0.05f));
|
||||
UIFactory.SetLayoutElement(memberBorder, flexibleWidth: 9999, flexibleHeight: 9999);
|
||||
|
||||
MemberScrollPool = UIFactory.CreateScrollPool<CacheMemberCell>(memberBorder, "MemberList", out GameObject scrollObj,
|
||||
out GameObject _, new Color(0.09f, 0.09f, 0.09f));
|
||||
UIFactory.SetLayoutElement(scrollObj, flexibleHeight: 9999);
|
||||
MemberScrollPool.Initialize(this);
|
||||
@ -299,5 +351,278 @@ namespace UnityExplorer.UI.Inspectors
|
||||
|
||||
return UIRoot;
|
||||
}
|
||||
|
||||
// Filter row
|
||||
|
||||
private void ConstructFilterRow(GameObject parent)
|
||||
{
|
||||
var filterRow = UIFactory.CreateUIObject("FilterRow", parent);
|
||||
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(filterRow, true, true, true, true, 5, 2, 2, 2, 2);
|
||||
UIFactory.SetLayoutElement(filterRow, minHeight: 25, flexibleHeight: 0, flexibleWidth: 9999);
|
||||
|
||||
var nameLabel = UIFactory.CreateLabel(filterRow, "NameFilterLabel", "Filter names:", TextAnchor.MiddleLeft, Color.grey);
|
||||
UIFactory.SetLayoutElement(nameLabel.gameObject, minHeight: 25, minWidth: 90, flexibleWidth: 0);
|
||||
var nameFilterObj = UIFactory.CreateInputField(filterRow, "NameFilterInput", "...", out filterInputField);
|
||||
UIFactory.SetLayoutElement(nameFilterObj, minHeight: 25, flexibleWidth: 300);
|
||||
filterInputField.onValueChanged.AddListener((string val) => { SetFilter(val); });
|
||||
|
||||
var spacer = UIFactory.CreateUIObject("Spacer", filterRow);
|
||||
UIFactory.SetLayoutElement(spacer, minWidth: 25);
|
||||
|
||||
var scopeLabel = UIFactory.CreateLabel(filterRow, "ScopeLabel", "Scope:", TextAnchor.MiddleLeft, Color.grey);
|
||||
UIFactory.SetLayoutElement(scopeLabel.gameObject, minHeight: 25, minWidth: 60, flexibleWidth: 0);
|
||||
AddFilterButton(filterRow, BindingFlags.Default, true);
|
||||
AddFilterButton(filterRow, BindingFlags.Instance);
|
||||
AddFilterButton(filterRow, BindingFlags.Static);
|
||||
}
|
||||
|
||||
private void AddFilterButton(GameObject parent, BindingFlags flags, bool setAsActive = false)
|
||||
{
|
||||
string lbl = flags == BindingFlags.Default ? "All" : flags.ToString();
|
||||
var color = setAsActive ? enabledButtonColor : disabledButtonColor;
|
||||
|
||||
var button = UIFactory.CreateButton(parent, "Filter_" + flags, lbl, color);
|
||||
UIFactory.SetLayoutElement(button.Button.gameObject, minHeight: 25, flexibleHeight: 0, minWidth: 100, flexibleWidth: 0);
|
||||
scopeFilterButtons.Add(flags, button);
|
||||
|
||||
button.OnClick += () => { SetFilter(flags); };
|
||||
}
|
||||
|
||||
// Update row
|
||||
|
||||
private void ConstructUpdateRow(GameObject parent)
|
||||
{
|
||||
var updateRow = UIFactory.CreateUIObject("UpdateRow", parent);
|
||||
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(updateRow, false, false, true, true, 4);
|
||||
UIFactory.SetLayoutElement(updateRow, minHeight: 25, flexibleHeight: 0, flexibleWidth: 9999);
|
||||
|
||||
var updateButton = UIFactory.CreateButton(updateRow, "UpdateButton", "Update displayed values", new Color(0.22f, 0.28f, 0.22f));
|
||||
UIFactory.SetLayoutElement(updateButton.Button.gameObject, minHeight: 25, minWidth: 175, flexibleWidth: 0);
|
||||
updateButton.OnClick += UpdateDisplayedMembers;
|
||||
|
||||
var toggleObj = UIFactory.CreateToggle(updateRow, "AutoUpdateToggle", out autoUpdateToggle, out Text toggleText);
|
||||
//GameObject.DestroyImmediate(toggleText);
|
||||
UIFactory.SetLayoutElement(toggleObj, minWidth: 185, minHeight: 25);
|
||||
autoUpdateToggle.isOn = false;
|
||||
autoUpdateToggle.onValueChanged.AddListener((bool val) => { AutoUpdateWanted = val; });
|
||||
toggleText.text = "Auto-update displayed";
|
||||
}
|
||||
|
||||
#region UNITY OBJECT SPECIFIC
|
||||
|
||||
// Unity object helpers
|
||||
|
||||
private void SetUnityTargets()
|
||||
{
|
||||
if (!typeof(UnityEngine.Object).IsAssignableFrom(TargetType))
|
||||
{
|
||||
unityObjectRow.SetActive(false);
|
||||
textureViewer.SetActive(false);
|
||||
return;
|
||||
}
|
||||
|
||||
ObjectRef = (UnityEngine.Object)Target.TryCast(typeof(UnityEngine.Object));
|
||||
unityObjectRow.SetActive(true);
|
||||
|
||||
nameInput.text = ObjectRef.name;
|
||||
instanceIdInput.text = ObjectRef.GetInstanceID().ToString();
|
||||
|
||||
if (typeof(Component).IsAssignableFrom(TargetType))
|
||||
{
|
||||
ComponentRef = (Component)Target.TryCast(typeof(Component));
|
||||
gameObjectButton.Button.gameObject.SetActive(true);
|
||||
}
|
||||
else
|
||||
gameObjectButton.Button.gameObject.SetActive(false);
|
||||
|
||||
if (typeof(Texture2D).IsAssignableFrom(TargetType))
|
||||
{
|
||||
TextureRef = (Texture2D)Target.TryCast(typeof(Texture2D));
|
||||
textureButton.Button.gameObject.SetActive(true);
|
||||
}
|
||||
else
|
||||
textureButton.Button.gameObject.SetActive(false);
|
||||
}
|
||||
|
||||
private void OnGameObjectButtonClicked()
|
||||
{
|
||||
if (!ComponentRef)
|
||||
{
|
||||
ExplorerCore.LogWarning("Component reference is null or destroyed!");
|
||||
return;
|
||||
}
|
||||
|
||||
InspectorManager.Inspect(ComponentRef.gameObject);
|
||||
}
|
||||
|
||||
private void ToggleTextureViewer()
|
||||
{
|
||||
if (TextureViewerWanted)
|
||||
{
|
||||
// disable
|
||||
TextureViewerWanted = false;
|
||||
textureViewer.gameObject.SetActive(false);
|
||||
mainContentHolder.SetActive(true);
|
||||
textureButton.ButtonText.text = "View Texture";
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!textureImage.sprite)
|
||||
{
|
||||
// First show, need to create sprite for displaying texture
|
||||
SetTextureViewer();
|
||||
}
|
||||
|
||||
// enable
|
||||
TextureViewerWanted = true;
|
||||
textureViewer.gameObject.SetActive(true);
|
||||
mainContentHolder.gameObject.SetActive(false);
|
||||
textureButton.ButtonText.text = "Hide Texture";
|
||||
}
|
||||
}
|
||||
|
||||
// UI construction
|
||||
|
||||
private void ConstructUnityObjectRow()
|
||||
{
|
||||
unityObjectRow = UIFactory.CreateUIObject("UnityObjectRow", UIRoot);
|
||||
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(unityObjectRow, false, false, true, true, 5);
|
||||
UIFactory.SetLayoutElement(unityObjectRow, minHeight: 25, flexibleHeight: 0, flexibleWidth: 9999);
|
||||
|
||||
textureButton = UIFactory.CreateButton(unityObjectRow, "TextureButton", "View Texture", new Color(0.2f, 0.2f, 0.2f));
|
||||
UIFactory.SetLayoutElement(textureButton.Button.gameObject, minHeight: 25, minWidth: 150);
|
||||
textureButton.OnClick += ToggleTextureViewer;
|
||||
|
||||
gameObjectButton = UIFactory.CreateButton(unityObjectRow, "GameObjectButton", "Inspect GameObject", new Color(0.2f, 0.2f, 0.2f));
|
||||
UIFactory.SetLayoutElement(gameObjectButton.Button.gameObject, minHeight: 25, minWidth: 170);
|
||||
gameObjectButton.OnClick += OnGameObjectButtonClicked;
|
||||
|
||||
var nameLabel = UIFactory.CreateLabel(unityObjectRow, "NameLabel", "Name:", TextAnchor.MiddleLeft, Color.grey);
|
||||
UIFactory.SetLayoutElement(nameLabel.gameObject, minHeight: 25, minWidth: 45, flexibleWidth: 0);
|
||||
|
||||
var nameInputObj = UIFactory.CreateInputField(unityObjectRow, "NameInput", "untitled", out nameInput);
|
||||
UIFactory.SetLayoutElement(nameInputObj, minHeight: 25, minWidth: 100, flexibleWidth: 1000);
|
||||
nameInput.readOnly = true;
|
||||
|
||||
var instanceLabel = UIFactory.CreateLabel(unityObjectRow, "InstanceLabel", "Instance ID:", TextAnchor.MiddleRight, Color.grey);
|
||||
UIFactory.SetLayoutElement(instanceLabel.gameObject, minHeight: 25, minWidth: 100, flexibleWidth: 0);
|
||||
|
||||
var instanceInputObj = UIFactory.CreateInputField(unityObjectRow, "InstanceIDInput", "ERROR", out instanceIdInput);
|
||||
UIFactory.SetLayoutElement(instanceInputObj, minHeight: 25, minWidth: 100, flexibleWidth: 0);
|
||||
instanceIdInput.readOnly = true;
|
||||
|
||||
unityObjectRow.SetActive(false);
|
||||
|
||||
ConstructTextureHelper();
|
||||
}
|
||||
|
||||
// Texture viewer helper
|
||||
|
||||
private InputField textureSavePathInput;
|
||||
private Image textureImage;
|
||||
private LayoutElement textureImageLayout;
|
||||
|
||||
private void CleanupTextureViewer()
|
||||
{
|
||||
if (textureImage.sprite)
|
||||
GameObject.Destroy(textureImage.sprite);
|
||||
|
||||
if (TextureViewerWanted)
|
||||
ToggleTextureViewer();
|
||||
}
|
||||
|
||||
private void ConstructTextureHelper()
|
||||
{
|
||||
textureViewer = UIFactory.CreateVerticalGroup(UIRoot, "TextureViewer", false, false, true, true, 2, new Vector4(5, 5, 5, 5),
|
||||
new Color(0.1f, 0.1f, 0.1f));
|
||||
UIFactory.SetLayoutElement(textureViewer, flexibleWidth: 9999, flexibleHeight: 9999);
|
||||
|
||||
// Save helper
|
||||
|
||||
var saveRowObj = UIFactory.CreateHorizontalGroup(textureViewer, "SaveRow", false, false, true, true, 2, new Vector4(2, 2, 2, 2),
|
||||
new Color(0.1f, 0.1f, 0.1f));
|
||||
|
||||
var saveBtn = UIFactory.CreateButton(saveRowObj, "SaveButton", "Save .PNG", new Color(0.2f, 0.25f, 0.2f));
|
||||
UIFactory.SetLayoutElement(saveBtn.Button.gameObject, minHeight: 25, minWidth: 100, flexibleWidth: 0);
|
||||
saveBtn.OnClick += OnSaveTextureClicked;
|
||||
|
||||
var inputObj = UIFactory.CreateInputField(saveRowObj, "SaveInput", "...", out textureSavePathInput);
|
||||
UIFactory.SetLayoutElement(inputObj, minHeight: 25, minWidth: 100, flexibleWidth: 9999);
|
||||
|
||||
// Actual texture viewer
|
||||
|
||||
var imageObj = UIFactory.CreateUIObject("TextureViewerImage", textureViewer);
|
||||
textureImage = imageObj.AddComponent<Image>();
|
||||
textureImageLayout = textureImage.gameObject.AddComponent<LayoutElement>();
|
||||
|
||||
var fitter = imageObj.AddComponent<ContentSizeFitter>();
|
||||
fitter.verticalFit = ContentSizeFitter.FitMode.PreferredSize;
|
||||
|
||||
textureViewer.SetActive(false);
|
||||
}
|
||||
|
||||
private void SetTextureViewer()
|
||||
{
|
||||
if (!this.TextureRef)
|
||||
return;
|
||||
|
||||
var name = TextureRef.name;
|
||||
if (string.IsNullOrEmpty(name))
|
||||
name = "untitled";
|
||||
|
||||
textureSavePathInput.text = Path.Combine(ConfigManager.Default_Output_Path.Value, $"{name}.png");
|
||||
|
||||
var sprite = TextureUtilProvider.Instance.CreateSprite(TextureRef);
|
||||
textureImage.sprite = sprite;
|
||||
|
||||
textureImageLayout.preferredHeight = sprite.rect.height;
|
||||
textureImageLayout.preferredWidth = sprite.rect.width;
|
||||
}
|
||||
|
||||
private void OnSaveTextureClicked()
|
||||
{
|
||||
if (!TextureRef)
|
||||
{
|
||||
ExplorerCore.LogWarning("Ref Texture is null, maybe it was destroyed?");
|
||||
return;
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(textureSavePathInput.text))
|
||||
{
|
||||
ExplorerCore.LogWarning("Save path cannot be empty!");
|
||||
return;
|
||||
}
|
||||
|
||||
var path = textureSavePathInput.text;
|
||||
if (!path.EndsWith(".png", StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
ExplorerCore.LogWarning("Desired save path must end with '.png'!");
|
||||
return;
|
||||
}
|
||||
|
||||
var dir = Path.GetDirectoryName(path);
|
||||
if (!Directory.Exists(dir))
|
||||
Directory.CreateDirectory(dir);
|
||||
|
||||
if (File.Exists(path))
|
||||
File.Delete(path);
|
||||
|
||||
var tex = TextureRef;
|
||||
|
||||
if (!TextureUtilProvider.IsReadable(tex))
|
||||
tex = TextureUtilProvider.ForceReadTexture(tex);
|
||||
|
||||
byte[] data = TextureUtilProvider.Instance.EncodeToPNG(tex);
|
||||
|
||||
File.WriteAllBytes(path, data);
|
||||
|
||||
if (tex != TextureRef)
|
||||
{
|
||||
// cleanup temp texture if we had to force-read it.
|
||||
GameObject.Destroy(tex);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user