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-05-16 21:46:19 +10:00
|
|
|
|
using System.Reflection.Emit;
|
2021-04-26 19:56:21 +10:00
|
|
|
|
using System.Text;
|
|
|
|
|
using UnityEngine;
|
2021-04-27 21:22:48 +10:00
|
|
|
|
using UnityEngine.UI;
|
2021-05-05 21:27:09 +10:00
|
|
|
|
using UnityExplorer.Core.Config;
|
|
|
|
|
using UnityExplorer.Core.Runtime;
|
2021-06-30 07:49:58 +10:00
|
|
|
|
using UnityExplorer.CacheObject;
|
|
|
|
|
using UnityExplorer.CacheObject.Views;
|
2021-04-27 21:22:48 +10:00
|
|
|
|
using UnityExplorer.UI.Panels;
|
|
|
|
|
using UnityExplorer.UI.Widgets;
|
2021-06-30 07:49:58 +10:00
|
|
|
|
using UnityExplorer.UI;
|
2021-04-26 19:56:21 +10:00
|
|
|
|
|
2021-06-30 07:49:58 +10:00
|
|
|
|
namespace UnityExplorer.Inspectors
|
2021-04-26 19:56:21 +10:00
|
|
|
|
{
|
2021-05-13 23:03:30 +10:00
|
|
|
|
public class ReflectionInspector : InspectorBase, ICellPoolDataSource<CacheMemberCell>, ICacheObjectController
|
2021-04-27 21:22:48 +10:00
|
|
|
|
{
|
2021-05-03 01:29:02 +10:00
|
|
|
|
public CacheObjectBase ParentCacheObject { get; set; }
|
2021-04-27 21:22:48 +10:00
|
|
|
|
public Type TargetType { get; private set; }
|
2021-05-05 21:27:09 +10:00
|
|
|
|
public bool StaticOnly { get; internal set; }
|
2021-05-09 20:18:33 +10:00
|
|
|
|
public bool CanWrite => true;
|
2021-05-05 21:27:09 +10:00
|
|
|
|
|
2021-05-09 20:18:33 +10:00
|
|
|
|
private List<CacheMember> members = new List<CacheMember>();
|
|
|
|
|
private readonly List<CacheMember> filteredMembers = new List<CacheMember>();
|
2021-05-05 21:27:09 +10:00
|
|
|
|
|
2021-05-16 21:46:19 +10:00
|
|
|
|
public bool AutoUpdateWanted => autoUpdateToggle.isOn;
|
2021-04-27 21:22:48 +10:00
|
|
|
|
|
2021-05-09 20:18:33 +10:00
|
|
|
|
private BindingFlags FlagsFilter;
|
|
|
|
|
private string NameFilter;
|
2021-05-05 21:27:09 +10:00
|
|
|
|
|
2021-05-09 20:18:33 +10:00
|
|
|
|
private MemberFlags MemberFilter = MemberFlags.All;
|
|
|
|
|
private enum MemberFlags
|
|
|
|
|
{
|
|
|
|
|
None = 0,
|
|
|
|
|
Property = 1,
|
|
|
|
|
Field = 2,
|
|
|
|
|
Method = 4,
|
|
|
|
|
All = 7
|
|
|
|
|
}
|
2021-05-05 21:27:09 +10:00
|
|
|
|
|
|
|
|
|
// UI
|
|
|
|
|
|
|
|
|
|
public ScrollPool<CacheMemberCell> MemberScrollPool { get; private set; }
|
2021-04-27 21:22:48 +10:00
|
|
|
|
|
2021-08-23 18:35:08 +10:00
|
|
|
|
public InputFieldRef HiddenNameText;
|
2021-04-27 21:22:48 +10:00
|
|
|
|
public Text NameText;
|
|
|
|
|
public Text AssemblyText;
|
2021-05-09 20:18:33 +10:00
|
|
|
|
private Toggle autoUpdateToggle;
|
2021-05-05 21:27:09 +10:00
|
|
|
|
|
2021-05-16 21:46:19 +10:00
|
|
|
|
private string currentBaseTabText;
|
|
|
|
|
|
2021-05-05 21:27:09 +10:00
|
|
|
|
private readonly Color disabledButtonColor = new Color(0.24f, 0.24f, 0.24f);
|
|
|
|
|
private readonly Color enabledButtonColor = new Color(0.2f, 0.27f, 0.2f);
|
2021-06-05 19:36:09 +10:00
|
|
|
|
|
2021-05-05 21:27:09 +10:00
|
|
|
|
private readonly Dictionary<BindingFlags, ButtonRef> scopeFilterButtons = new Dictionary<BindingFlags, ButtonRef>();
|
2021-05-09 20:18:33 +10:00
|
|
|
|
private readonly List<Toggle> memberTypeToggles = new List<Toggle>();
|
2021-05-07 17:06:56 +10:00
|
|
|
|
private InputFieldRef filterInputField;
|
2021-05-05 21:27:09 +10:00
|
|
|
|
|
2021-05-09 20:18:33 +10:00
|
|
|
|
// Setup / return
|
2021-04-30 21:34:50 +10:00
|
|
|
|
|
2021-04-27 21:22:48 +10:00
|
|
|
|
public override void OnBorrowedFromPool(object target)
|
|
|
|
|
{
|
|
|
|
|
base.OnBorrowedFromPool(target);
|
2021-05-05 21:27:09 +10:00
|
|
|
|
CalculateLayouts();
|
2021-04-27 21:22:48 +10:00
|
|
|
|
|
|
|
|
|
SetTarget(target);
|
|
|
|
|
|
|
|
|
|
RuntimeProvider.Instance.StartCoroutine(InitCoroutine());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private IEnumerator InitCoroutine()
|
|
|
|
|
{
|
|
|
|
|
yield return null;
|
|
|
|
|
LayoutRebuilder.ForceRebuildLayoutImmediate(InspectorPanel.Instance.ContentRect);
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-16 21:46:19 +10:00
|
|
|
|
public override void CloseInspector()
|
2021-05-05 21:27:09 +10:00
|
|
|
|
{
|
|
|
|
|
InspectorManager.ReleaseInspector(this);
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-29 21:01:08 +10:00
|
|
|
|
public override void OnReturnToPool()
|
|
|
|
|
{
|
|
|
|
|
foreach (var member in members)
|
2021-05-05 21:27:09 +10:00
|
|
|
|
{
|
|
|
|
|
member.UnlinkFromView();
|
2021-04-30 23:12:18 +10:00
|
|
|
|
member.ReleasePooledObjects();
|
2021-05-05 21:27:09 +10:00
|
|
|
|
}
|
2021-04-29 21:01:08 +10:00
|
|
|
|
|
|
|
|
|
members.Clear();
|
|
|
|
|
filteredMembers.Clear();
|
|
|
|
|
|
2021-04-30 21:34:50 +10:00
|
|
|
|
autoUpdateToggle.isOn = false;
|
|
|
|
|
|
2021-05-13 23:03:30 +10:00
|
|
|
|
UnityObjectRef = null;
|
2021-05-05 21:27:09 +10:00
|
|
|
|
ComponentRef = null;
|
|
|
|
|
TextureRef = null;
|
|
|
|
|
CleanupTextureViewer();
|
|
|
|
|
|
2021-04-29 21:01:08 +10:00
|
|
|
|
base.OnReturnToPool();
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-05 21:27:09 +10:00
|
|
|
|
// Setting target
|
|
|
|
|
|
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
|
|
|
|
|
{
|
|
|
|
|
TargetType = target.GetActualType();
|
|
|
|
|
prefix = "[R]";
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-05 21:27:09 +10:00
|
|
|
|
// Setup main labels and tab text
|
2021-05-16 21:46:19 +10:00
|
|
|
|
currentBaseTabText = $"{prefix} {SignatureHighlighter.Parse(TargetType, false)}";
|
|
|
|
|
Tab.TabText.text = currentBaseTabText;
|
2021-05-06 04:02:42 +10:00
|
|
|
|
NameText.text = SignatureHighlighter.Parse(TargetType, true);
|
2021-08-23 18:35:08 +10:00
|
|
|
|
HiddenNameText.Text = TargetType.FullName;
|
2021-04-27 21:22:48 +10:00
|
|
|
|
|
|
|
|
|
string asmText;
|
2021-05-16 21:46:19 +10:00
|
|
|
|
if (TargetType.Assembly is AssemblyBuilder || string.IsNullOrEmpty(TargetType.Assembly.Location))
|
2021-04-27 21:22:48 +10:00
|
|
|
|
asmText = $"{TargetType.Assembly.GetName().Name} <color=grey><i>(in memory)</i></color>";
|
2021-05-16 21:46:19 +10:00
|
|
|
|
else
|
|
|
|
|
asmText = Path.GetFileName(TargetType.Assembly.Location);
|
2021-04-27 21:22:48 +10:00
|
|
|
|
AssemblyText.text = $"<color=grey>Assembly:</color> {asmText}";
|
|
|
|
|
|
2021-05-05 21:27:09 +10:00
|
|
|
|
// unity helpers
|
|
|
|
|
SetUnityTargets();
|
2021-04-27 21:22:48 +10:00
|
|
|
|
|
2021-05-16 21:46:19 +10:00
|
|
|
|
// Get cache members
|
|
|
|
|
|
2021-04-27 21:22:48 +10:00
|
|
|
|
this.members = CacheMember.GetCacheMembers(Target, TargetType, this);
|
2021-05-16 21:46:19 +10:00
|
|
|
|
|
|
|
|
|
// reset filters
|
|
|
|
|
|
2021-05-07 17:06:56 +10:00
|
|
|
|
this.filterInputField.Text = "";
|
2021-06-05 19:36:09 +10:00
|
|
|
|
|
2021-05-05 21:27:09 +10:00
|
|
|
|
SetFilter("", StaticOnly ? BindingFlags.Static : BindingFlags.Instance);
|
2021-05-11 19:18:27 +10:00
|
|
|
|
scopeFilterButtons[BindingFlags.Default].Component.gameObject.SetActive(!StaticOnly);
|
|
|
|
|
scopeFilterButtons[BindingFlags.Instance].Component.gameObject.SetActive(!StaticOnly);
|
2021-05-09 20:18:33 +10:00
|
|
|
|
|
|
|
|
|
foreach (var toggle in memberTypeToggles)
|
|
|
|
|
toggle.isOn = true;
|
|
|
|
|
|
2021-05-05 21:27:09 +10:00
|
|
|
|
refreshWanted = true;
|
2021-04-27 21:22:48 +10:00
|
|
|
|
}
|
2021-04-26 19:56:21 +10:00
|
|
|
|
|
2021-05-05 21:27:09 +10:00
|
|
|
|
// Updating
|
2021-04-26 19:56:21 +10:00
|
|
|
|
|
2021-05-05 21:27:09 +10:00
|
|
|
|
private bool refreshWanted;
|
|
|
|
|
private string lastNameFilter;
|
|
|
|
|
private BindingFlags lastFlagsFilter;
|
2021-05-09 20:18:33 +10:00
|
|
|
|
private MemberFlags lastMemberFilter = MemberFlags.All;
|
2021-05-05 21:27:09 +10:00
|
|
|
|
private float timeOfLastAutoUpdate;
|
2021-04-27 21:22:48 +10:00
|
|
|
|
|
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-05-16 21:46:19 +10:00
|
|
|
|
// check filter changes or force-refresh
|
2021-05-09 20:18:33 +10:00
|
|
|
|
if (refreshWanted || NameFilter != lastNameFilter || FlagsFilter != lastFlagsFilter || lastMemberFilter != MemberFilter)
|
2021-04-27 21:22:48 +10:00
|
|
|
|
{
|
2021-05-05 21:27:09 +10:00
|
|
|
|
lastNameFilter = NameFilter;
|
|
|
|
|
lastFlagsFilter = FlagsFilter;
|
2021-05-09 20:18:33 +10:00
|
|
|
|
lastMemberFilter = MemberFilter;
|
2021-05-05 21:27:09 +10:00
|
|
|
|
|
|
|
|
|
FilterMembers();
|
|
|
|
|
MemberScrollPool.Refresh(true, true);
|
|
|
|
|
refreshWanted = false;
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-16 21:46:19 +10:00
|
|
|
|
// once-per-second updates
|
2021-05-05 21:27:09 +10:00
|
|
|
|
if (timeOfLastAutoUpdate.OccuredEarlierThan(1))
|
|
|
|
|
{
|
|
|
|
|
timeOfLastAutoUpdate = Time.realtimeSinceStartup;
|
2021-04-27 21:22:48 +10:00
|
|
|
|
|
2021-05-16 21:46:19 +10:00
|
|
|
|
if (this.UnityObjectRef)
|
|
|
|
|
{
|
|
|
|
|
nameInput.Text = UnityObjectRef.name;
|
|
|
|
|
this.Tab.TabText.text = $"{currentBaseTabText} \"{UnityObjectRef.name}\"";
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-01 20:55:27 +10:00
|
|
|
|
if (AutoUpdateWanted)
|
2021-05-06 16:47:37 +10:00
|
|
|
|
UpdateDisplayedMembers();
|
2021-04-27 21:22:48 +10:00
|
|
|
|
}
|
2021-04-26 19:56:21 +10:00
|
|
|
|
}
|
|
|
|
|
|
2021-05-13 23:03:30 +10:00
|
|
|
|
public void UpdateClicked()
|
|
|
|
|
{
|
|
|
|
|
UpdateDisplayedMembers();
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-05 21:27:09 +10:00
|
|
|
|
// 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)
|
|
|
|
|
{
|
2021-05-11 19:18:27 +10:00
|
|
|
|
var btn = scopeFilterButtons[FlagsFilter].Component;
|
2021-05-05 21:27:09 +10:00
|
|
|
|
RuntimeProvider.Instance.SetColorBlock(btn, disabledButtonColor, disabledButtonColor * 1.3f);
|
|
|
|
|
|
|
|
|
|
this.FlagsFilter = flagsFilter;
|
2021-05-11 19:18:27 +10:00
|
|
|
|
btn = scopeFilterButtons[FlagsFilter].Component;
|
2021-05-05 21:27:09 +10:00
|
|
|
|
RuntimeProvider.Instance.SetColorBlock(btn, enabledButtonColor, enabledButtonColor * 1.3f);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-09 20:18:33 +10:00
|
|
|
|
private void OnMemberTypeToggled(MemberFlags flag, bool val)
|
|
|
|
|
{
|
|
|
|
|
if (!val)
|
|
|
|
|
MemberFilter &= ~flag;
|
|
|
|
|
else
|
|
|
|
|
MemberFilter |= flag;
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-05 21:27:09 +10:00
|
|
|
|
private void FilterMembers()
|
|
|
|
|
{
|
|
|
|
|
filteredMembers.Clear();
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < members.Count; i++)
|
|
|
|
|
{
|
|
|
|
|
var member = members[i];
|
|
|
|
|
|
|
|
|
|
if (FlagsFilter != BindingFlags.Default)
|
|
|
|
|
{
|
|
|
|
|
if (FlagsFilter == BindingFlags.Instance && member.IsStatic
|
|
|
|
|
|| FlagsFilter == BindingFlags.Static && !member.IsStatic)
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-09 20:18:33 +10:00
|
|
|
|
if ((member is CacheMethod && !MemberFilter.HasFlag(MemberFlags.Method))
|
|
|
|
|
|| (member is CacheField && !MemberFilter.HasFlag(MemberFlags.Field))
|
|
|
|
|
|| (member is CacheProperty && !MemberFilter.HasFlag(MemberFlags.Property)))
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if (!string.IsNullOrEmpty(NameFilter) && !member.NameForFiltering.ContainsIgnoreCase(NameFilter))
|
|
|
|
|
continue;
|
|
|
|
|
|
2021-05-05 21:27:09 +10:00
|
|
|
|
filteredMembers.Add(member);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-06 16:47:37 +10:00
|
|
|
|
private void UpdateDisplayedMembers()
|
2021-04-27 21:22:48 +10:00
|
|
|
|
{
|
2021-04-29 21:01:08 +10:00
|
|
|
|
bool shouldRefresh = false;
|
2021-05-04 20:10:46 +10:00
|
|
|
|
foreach (var cell in MemberScrollPool.CellPool)
|
2021-04-29 21:01:08 +10:00
|
|
|
|
{
|
2021-05-04 20:10:46 +10:00
|
|
|
|
if (!cell.Enabled || cell.Occupant == null)
|
|
|
|
|
continue;
|
|
|
|
|
var member = cell.MemberOccupant;
|
2021-05-06 16:47:37 +10:00
|
|
|
|
if (member.ShouldAutoEvaluate)
|
2021-04-29 21:01:08 +10:00
|
|
|
|
{
|
|
|
|
|
shouldRefresh = true;
|
|
|
|
|
member.Evaluate();
|
2021-05-05 21:27:09 +10:00
|
|
|
|
member.SetDataToCell(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)
|
2021-04-30 23:12:18 +10:00
|
|
|
|
MemberScrollPool.Refresh(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-05-05 21:27:09 +10:00
|
|
|
|
public void OnCellBorrowed(CacheMemberCell cell) { } // not needed
|
2021-04-27 21:22:48 +10:00
|
|
|
|
|
|
|
|
|
public void SetCell(CacheMemberCell cell, int index)
|
|
|
|
|
{
|
2021-05-07 06:27:44 +10:00
|
|
|
|
CacheObjectControllerHelper.SetCell(cell, index, filteredMembers, SetCellLayout);
|
2021-04-27 21:22:48 +10:00
|
|
|
|
}
|
|
|
|
|
|
2021-04-28 20:47:48 +10:00
|
|
|
|
// Cell layout (fake table alignment)
|
|
|
|
|
|
2021-05-03 01:29:02 +10:00
|
|
|
|
private static int LeftGroupWidth { get; set; }
|
|
|
|
|
private static int RightGroupWidth { get; set; }
|
2021-04-27 21:22:48 +10:00
|
|
|
|
|
2021-05-05 21:27:09 +10:00
|
|
|
|
internal void SetLayouts()
|
|
|
|
|
{
|
|
|
|
|
CalculateLayouts();
|
|
|
|
|
|
|
|
|
|
foreach (var cell in MemberScrollPool.CellPool)
|
|
|
|
|
SetCellLayout(cell);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void CalculateLayouts()
|
2021-04-27 21:22:48 +10:00
|
|
|
|
{
|
2021-06-05 19:36:09 +10:00
|
|
|
|
LeftGroupWidth = (int)Math.Max(200, (0.4f * InspectorManager.PanelWidth) - 5);
|
2021-05-05 21:27:09 +10:00
|
|
|
|
RightGroupWidth = (int)Math.Max(200, InspectorManager.PanelWidth - LeftGroupWidth - 65);
|
2021-04-27 21:22:48 +10:00
|
|
|
|
}
|
|
|
|
|
|
2021-04-30 21:34:50 +10:00
|
|
|
|
private void SetCellLayout(CacheObjectCell cell)
|
2021-04-27 21:22:48 +10:00
|
|
|
|
{
|
2021-05-03 01:29:02 +10:00
|
|
|
|
cell.NameLayout.minWidth = LeftGroupWidth;
|
2021-04-27 21:22:48 +10:00
|
|
|
|
cell.RightGroupLayout.minWidth = RightGroupWidth;
|
2021-05-03 01:29:02 +10:00
|
|
|
|
|
|
|
|
|
if (cell.Occupant?.IValue != null)
|
|
|
|
|
cell.Occupant.IValue.SetLayout();
|
2021-04-27 21:22:48 +10:00
|
|
|
|
}
|
|
|
|
|
|
2021-05-05 21:27:09 +10:00
|
|
|
|
// UI Construction
|
2021-04-27 21:22:48 +10:00
|
|
|
|
|
2021-05-05 21:27:09 +10:00
|
|
|
|
private GameObject mainContentHolder;
|
2021-04-27 21:22:48 +10:00
|
|
|
|
|
|
|
|
|
public override GameObject CreateContent(GameObject parent)
|
|
|
|
|
{
|
2021-05-05 21:27:09 +10:00
|
|
|
|
UIRoot = UIFactory.CreateVerticalGroup(parent, "ReflectionInspector", true, true, true, true, 5,
|
|
|
|
|
new Vector4(4, 4, 4, 4), new Color(0.065f, 0.065f, 0.065f));
|
2021-04-27 21:22:48 +10:00
|
|
|
|
|
2021-05-05 21:27:09 +10:00
|
|
|
|
// Class name, assembly
|
2021-04-29 21:01:08 +10:00
|
|
|
|
|
2021-08-23 18:35:08 +10:00
|
|
|
|
var titleHolder = UIFactory.CreateUIObject("TitleHolder", UIRoot);
|
|
|
|
|
UIFactory.SetLayoutElement(titleHolder, minHeight: 35, flexibleHeight: 0, flexibleWidth: 9999);
|
|
|
|
|
|
|
|
|
|
NameText = UIFactory.CreateLabel(titleHolder, "VisibleTitle", "NotSet", TextAnchor.MiddleLeft);
|
|
|
|
|
var namerect = NameText.GetComponent<RectTransform>();
|
|
|
|
|
namerect.anchorMin = new Vector2(0, 0);
|
|
|
|
|
namerect.anchorMax = new Vector2(1, 1);
|
|
|
|
|
NameText.fontSize = 17;
|
|
|
|
|
UIFactory.SetLayoutElement(NameText.gameObject, minHeight: 35, flexibleHeight: 0, minWidth: 300, flexibleWidth: 9999);
|
|
|
|
|
|
|
|
|
|
HiddenNameText = UIFactory.CreateInputField(titleHolder, "Title", "not set");
|
|
|
|
|
var hiddenrect = HiddenNameText.Component.gameObject.GetComponent<RectTransform>();
|
|
|
|
|
hiddenrect.anchorMin = new Vector2(0, 0);
|
|
|
|
|
hiddenrect.anchorMax = new Vector2(1, 1);
|
|
|
|
|
HiddenNameText.Component.readOnly = true;
|
|
|
|
|
HiddenNameText.Component.lineType = InputField.LineType.MultiLineNewline;
|
|
|
|
|
HiddenNameText.Component.gameObject.GetComponent<Image>().color = Color.clear;
|
|
|
|
|
HiddenNameText.Component.textComponent.horizontalOverflow = HorizontalWrapMode.Wrap;
|
|
|
|
|
HiddenNameText.Component.textComponent.fontSize = 17;
|
|
|
|
|
HiddenNameText.Component.textComponent.color = Color.clear;
|
|
|
|
|
UIFactory.SetLayoutElement(HiddenNameText.Component.gameObject, minHeight: 35, flexibleHeight: 0, flexibleWidth: 9999);
|
2021-04-27 21:22:48 +10:00
|
|
|
|
|
2021-05-01 20:55:27 +10:00
|
|
|
|
AssemblyText = UIFactory.CreateLabel(UIRoot, "AssemblyLabel", "not set", TextAnchor.MiddleLeft);
|
2021-04-27 21:22:48 +10:00
|
|
|
|
UIFactory.SetLayoutElement(AssemblyText.gameObject, minHeight: 25, flexibleWidth: 9999);
|
|
|
|
|
|
2021-05-05 21:27:09 +10:00
|
|
|
|
ConstructUnityObjectRow();
|
|
|
|
|
|
2021-06-05 19:36:09 +10:00
|
|
|
|
mainContentHolder = UIFactory.CreateVerticalGroup(UIRoot, "MemberHolder", false, false, true, true, 5, new Vector4(2, 2, 2, 2),
|
2021-05-05 21:27:09 +10:00
|
|
|
|
new Color(0.12f, 0.12f, 0.12f));
|
|
|
|
|
UIFactory.SetLayoutElement(mainContentHolder, flexibleWidth: 9999, flexibleHeight: 9999);
|
|
|
|
|
|
2021-05-09 20:18:33 +10:00
|
|
|
|
ConstructFirstRow(mainContentHolder);
|
2021-05-05 21:27:09 +10:00
|
|
|
|
|
2021-05-09 20:18:33 +10:00
|
|
|
|
ConstructSecondRow(mainContentHolder);
|
2021-05-05 21:27:09 +10:00
|
|
|
|
|
|
|
|
|
// Member scroll pool
|
|
|
|
|
|
2021-06-05 19:36:09 +10:00
|
|
|
|
var memberBorder = UIFactory.CreateVerticalGroup(mainContentHolder, "ScrollPoolHolder", false, false, true, true, padding: new Vector4(2, 2, 2, 2),
|
2021-05-05 21:27:09 +10:00
|
|
|
|
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);
|
|
|
|
|
|
2021-05-16 21:46:19 +10:00
|
|
|
|
// For debugging scroll pool
|
2021-05-05 21:27:09 +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);
|
|
|
|
|
|
|
|
|
|
return UIRoot;
|
|
|
|
|
}
|
2021-04-29 21:01:08 +10:00
|
|
|
|
|
2021-05-09 20:18:33 +10:00
|
|
|
|
// First row
|
2021-04-29 21:01:08 +10:00
|
|
|
|
|
2021-05-09 20:18:33 +10:00
|
|
|
|
private void ConstructFirstRow(GameObject parent)
|
2021-05-05 21:27:09 +10:00
|
|
|
|
{
|
2021-05-09 20:18:33 +10:00
|
|
|
|
var rowObj = UIFactory.CreateUIObject("FirstRow", parent);
|
|
|
|
|
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(rowObj, true, true, true, true, 5, 2, 2, 2, 2);
|
|
|
|
|
UIFactory.SetLayoutElement(rowObj, minHeight: 25, flexibleHeight: 0, flexibleWidth: 9999);
|
2021-05-05 21:27:09 +10:00
|
|
|
|
|
2021-05-09 20:18:33 +10:00
|
|
|
|
var nameLabel = UIFactory.CreateLabel(rowObj, "NameFilterLabel", "Filter names:", TextAnchor.MiddleLeft, Color.grey);
|
2021-05-05 21:27:09 +10:00
|
|
|
|
UIFactory.SetLayoutElement(nameLabel.gameObject, minHeight: 25, minWidth: 90, flexibleWidth: 0);
|
2021-05-07 17:06:56 +10:00
|
|
|
|
|
2021-05-09 20:18:33 +10:00
|
|
|
|
filterInputField = UIFactory.CreateInputField(rowObj, "NameFilterInput", "...");
|
2021-05-07 17:06:56 +10:00
|
|
|
|
UIFactory.SetLayoutElement(filterInputField.UIRoot, minHeight: 25, flexibleWidth: 300);
|
|
|
|
|
filterInputField.OnValueChanged += (string val) => { SetFilter(val); };
|
2021-05-05 21:27:09 +10:00
|
|
|
|
|
2021-05-09 20:18:33 +10:00
|
|
|
|
var spacer = UIFactory.CreateUIObject("Spacer", rowObj);
|
2021-05-05 21:27:09 +10:00
|
|
|
|
UIFactory.SetLayoutElement(spacer, minWidth: 25);
|
|
|
|
|
|
2021-05-09 20:18:33 +10:00
|
|
|
|
// Update button and toggle
|
|
|
|
|
|
|
|
|
|
var updateButton = UIFactory.CreateButton(rowObj, "UpdateButton", "Update displayed values", new Color(0.22f, 0.28f, 0.22f));
|
2021-05-11 19:18:27 +10:00
|
|
|
|
UIFactory.SetLayoutElement(updateButton.Component.gameObject, minHeight: 25, minWidth: 175, flexibleWidth: 0);
|
2021-05-13 23:03:30 +10:00
|
|
|
|
updateButton.OnClick += UpdateClicked;
|
2021-05-09 20:18:33 +10:00
|
|
|
|
|
|
|
|
|
var toggleObj = UIFactory.CreateToggle(rowObj, "AutoUpdateToggle", out autoUpdateToggle, out Text toggleText);
|
|
|
|
|
UIFactory.SetLayoutElement(toggleObj, minWidth: 125, minHeight: 25);
|
|
|
|
|
autoUpdateToggle.isOn = false;
|
|
|
|
|
toggleText.text = "Auto-update";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Second row
|
|
|
|
|
|
|
|
|
|
private void ConstructSecondRow(GameObject parent)
|
|
|
|
|
{
|
|
|
|
|
var rowObj = UIFactory.CreateUIObject("SecondRow", parent);
|
|
|
|
|
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(rowObj, false, false, true, true, 5, 2, 2, 2, 2);
|
|
|
|
|
UIFactory.SetLayoutElement(rowObj, minHeight: 25, flexibleHeight: 0, flexibleWidth: 9999);
|
|
|
|
|
|
|
|
|
|
// Scope buttons
|
|
|
|
|
|
|
|
|
|
var scopeLabel = UIFactory.CreateLabel(rowObj, "ScopeLabel", "Scope:", TextAnchor.MiddleLeft, Color.grey);
|
2021-05-05 21:27:09 +10:00
|
|
|
|
UIFactory.SetLayoutElement(scopeLabel.gameObject, minHeight: 25, minWidth: 60, flexibleWidth: 0);
|
2021-05-09 20:18:33 +10:00
|
|
|
|
AddScopeFilterButton(rowObj, BindingFlags.Default, true);
|
|
|
|
|
AddScopeFilterButton(rowObj, BindingFlags.Instance);
|
|
|
|
|
AddScopeFilterButton(rowObj, BindingFlags.Static);
|
|
|
|
|
|
|
|
|
|
var spacer = UIFactory.CreateUIObject("Spacer", rowObj);
|
|
|
|
|
UIFactory.SetLayoutElement(spacer, minWidth: 15);
|
|
|
|
|
|
|
|
|
|
// Member type toggles
|
|
|
|
|
|
|
|
|
|
AddMemberTypeToggle(rowObj, MemberTypes.Property, 90);
|
|
|
|
|
AddMemberTypeToggle(rowObj, MemberTypes.Field, 70);
|
|
|
|
|
AddMemberTypeToggle(rowObj, MemberTypes.Method, 90);
|
2021-05-05 21:27:09 +10:00
|
|
|
|
}
|
2021-05-01 20:55:27 +10:00
|
|
|
|
|
2021-05-09 20:18:33 +10:00
|
|
|
|
private void AddScopeFilterButton(GameObject parent, BindingFlags flags, bool setAsActive = false)
|
2021-05-05 21:27:09 +10:00
|
|
|
|
{
|
|
|
|
|
string lbl = flags == BindingFlags.Default ? "All" : flags.ToString();
|
|
|
|
|
var color = setAsActive ? enabledButtonColor : disabledButtonColor;
|
|
|
|
|
|
|
|
|
|
var button = UIFactory.CreateButton(parent, "Filter_" + flags, lbl, color);
|
2021-05-11 19:18:27 +10:00
|
|
|
|
UIFactory.SetLayoutElement(button.Component.gameObject, minHeight: 25, flexibleHeight: 0, minWidth: 70, flexibleWidth: 0);
|
2021-05-05 21:27:09 +10:00
|
|
|
|
scopeFilterButtons.Add(flags, button);
|
2021-05-01 20:55:27 +10:00
|
|
|
|
|
2021-05-05 21:27:09 +10:00
|
|
|
|
button.OnClick += () => { SetFilter(flags); };
|
|
|
|
|
}
|
2021-04-27 21:22:48 +10:00
|
|
|
|
|
2021-05-09 20:18:33 +10:00
|
|
|
|
private void AddMemberTypeToggle(GameObject parent, MemberTypes type, int width)
|
2021-05-05 21:27:09 +10:00
|
|
|
|
{
|
2021-05-09 20:18:33 +10:00
|
|
|
|
var toggleObj = UIFactory.CreateToggle(parent, "Toggle_" + type, out Toggle toggle, out Text toggleText);
|
|
|
|
|
UIFactory.SetLayoutElement(toggleObj, minHeight: 25, minWidth: width);
|
2021-05-10 23:09:21 +10:00
|
|
|
|
var color = SignatureHighlighter.GetMemberInfoColor(type);
|
|
|
|
|
toggleText.text = $"<color={color}>{type}</color>";
|
2021-04-27 21:22:48 +10:00
|
|
|
|
|
2021-05-10 23:09:21 +10:00
|
|
|
|
toggle.graphic.TryCast<Image>().color = color.ToColor() * 0.65f;
|
2021-04-29 21:01:08 +10:00
|
|
|
|
|
2021-05-09 20:18:33 +10:00
|
|
|
|
MemberFlags flag;
|
|
|
|
|
switch (type)
|
|
|
|
|
{
|
|
|
|
|
case MemberTypes.Method: flag = MemberFlags.Method; break;
|
|
|
|
|
case MemberTypes.Property: flag = MemberFlags.Property; break;
|
|
|
|
|
case MemberTypes.Field: flag = MemberFlags.Field; break;
|
|
|
|
|
default: return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
toggle.onValueChanged.AddListener((bool val) => { OnMemberTypeToggled(flag, val); });
|
|
|
|
|
|
|
|
|
|
memberTypeToggles.Add(toggle);
|
2021-05-05 21:27:09 +10:00
|
|
|
|
}
|
2021-04-30 21:34:50 +10:00
|
|
|
|
|
2021-05-16 21:46:19 +10:00
|
|
|
|
|
|
|
|
|
// Todo should probably put this in a separate class or maybe as a widget
|
|
|
|
|
|
2021-05-05 21:27:09 +10:00
|
|
|
|
#region UNITY OBJECT SPECIFIC
|
2021-04-29 21:01:08 +10:00
|
|
|
|
|
2021-05-05 21:27:09 +10:00
|
|
|
|
// Unity object helpers
|
2021-04-27 21:22:48 +10:00
|
|
|
|
|
2021-05-13 23:03:30 +10:00
|
|
|
|
private UnityEngine.Object UnityObjectRef;
|
2021-05-09 20:18:33 +10:00
|
|
|
|
private Component ComponentRef;
|
|
|
|
|
private Texture2D TextureRef;
|
|
|
|
|
private bool TextureViewerWanted;
|
|
|
|
|
private GameObject unityObjectRow;
|
|
|
|
|
private ButtonRef gameObjectButton;
|
|
|
|
|
private InputFieldRef nameInput;
|
|
|
|
|
private InputFieldRef instanceIdInput;
|
|
|
|
|
private ButtonRef textureButton;
|
|
|
|
|
private GameObject textureViewer;
|
|
|
|
|
|
2021-05-05 21:27:09 +10:00
|
|
|
|
private void SetUnityTargets()
|
|
|
|
|
{
|
2021-05-28 18:23:30 +10:00
|
|
|
|
if (StaticOnly || !typeof(UnityEngine.Object).IsAssignableFrom(TargetType))
|
2021-05-05 21:27:09 +10:00
|
|
|
|
{
|
|
|
|
|
unityObjectRow.SetActive(false);
|
|
|
|
|
textureViewer.SetActive(false);
|
|
|
|
|
return;
|
|
|
|
|
}
|
2021-04-27 21:22:48 +10:00
|
|
|
|
|
2021-05-13 23:03:30 +10:00
|
|
|
|
UnityObjectRef = (UnityEngine.Object)Target.TryCast(typeof(UnityEngine.Object));
|
2021-05-05 21:27:09 +10:00
|
|
|
|
unityObjectRow.SetActive(true);
|
|
|
|
|
|
2021-05-13 23:03:30 +10:00
|
|
|
|
nameInput.Text = UnityObjectRef.name;
|
|
|
|
|
instanceIdInput.Text = UnityObjectRef.GetInstanceID().ToString();
|
2021-05-05 21:27:09 +10:00
|
|
|
|
|
|
|
|
|
if (typeof(Component).IsAssignableFrom(TargetType))
|
|
|
|
|
{
|
|
|
|
|
ComponentRef = (Component)Target.TryCast(typeof(Component));
|
2021-05-11 19:18:27 +10:00
|
|
|
|
gameObjectButton.Component.gameObject.SetActive(true);
|
2021-05-05 21:27:09 +10:00
|
|
|
|
}
|
|
|
|
|
else
|
2021-05-11 19:18:27 +10:00
|
|
|
|
gameObjectButton.Component.gameObject.SetActive(false);
|
2021-05-05 21:27:09 +10:00
|
|
|
|
|
|
|
|
|
if (typeof(Texture2D).IsAssignableFrom(TargetType))
|
|
|
|
|
{
|
|
|
|
|
TextureRef = (Texture2D)Target.TryCast(typeof(Texture2D));
|
2021-05-11 19:18:27 +10:00
|
|
|
|
textureButton.Component.gameObject.SetActive(true);
|
2021-05-05 21:27:09 +10:00
|
|
|
|
}
|
|
|
|
|
else
|
2021-05-11 19:18:27 +10:00
|
|
|
|
textureButton.Component.gameObject.SetActive(false);
|
2021-05-05 21:27:09 +10:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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;
|
2021-05-13 23:03:30 +10:00
|
|
|
|
textureViewer.SetActive(false);
|
2021-05-05 21:27:09 +10:00
|
|
|
|
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;
|
2021-05-13 23:03:30 +10:00
|
|
|
|
textureViewer.SetActive(true);
|
2021-05-05 21:27:09 +10:00
|
|
|
|
mainContentHolder.gameObject.SetActive(false);
|
|
|
|
|
textureButton.ButtonText.text = "Hide Texture";
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-06-05 19:36:09 +10:00
|
|
|
|
|
2021-05-05 21:27:09 +10:00
|
|
|
|
// 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));
|
2021-05-11 19:18:27 +10:00
|
|
|
|
UIFactory.SetLayoutElement(textureButton.Component.gameObject, minHeight: 25, minWidth: 150);
|
2021-05-05 21:27:09 +10:00
|
|
|
|
textureButton.OnClick += ToggleTextureViewer;
|
|
|
|
|
|
|
|
|
|
var nameLabel = UIFactory.CreateLabel(unityObjectRow, "NameLabel", "Name:", TextAnchor.MiddleLeft, Color.grey);
|
|
|
|
|
UIFactory.SetLayoutElement(nameLabel.gameObject, minHeight: 25, minWidth: 45, flexibleWidth: 0);
|
|
|
|
|
|
2021-05-07 17:06:56 +10:00
|
|
|
|
nameInput = UIFactory.CreateInputField(unityObjectRow, "NameInput", "untitled");
|
|
|
|
|
UIFactory.SetLayoutElement(nameInput.UIRoot, minHeight: 25, minWidth: 100, flexibleWidth: 1000);
|
2021-05-11 19:18:27 +10:00
|
|
|
|
nameInput.Component.readOnly = true;
|
2021-05-05 21:27:09 +10:00
|
|
|
|
|
2021-05-16 21:46:19 +10:00
|
|
|
|
gameObjectButton = UIFactory.CreateButton(unityObjectRow, "GameObjectButton", "Inspect GameObject", new Color(0.2f, 0.2f, 0.2f));
|
|
|
|
|
UIFactory.SetLayoutElement(gameObjectButton.Component.gameObject, minHeight: 25, minWidth: 160);
|
|
|
|
|
gameObjectButton.OnClick += OnGameObjectButtonClicked;
|
|
|
|
|
|
2021-05-05 21:27:09 +10:00
|
|
|
|
var instanceLabel = UIFactory.CreateLabel(unityObjectRow, "InstanceLabel", "Instance ID:", TextAnchor.MiddleRight, Color.grey);
|
|
|
|
|
UIFactory.SetLayoutElement(instanceLabel.gameObject, minHeight: 25, minWidth: 100, flexibleWidth: 0);
|
|
|
|
|
|
2021-05-07 17:06:56 +10:00
|
|
|
|
instanceIdInput = UIFactory.CreateInputField(unityObjectRow, "InstanceIDInput", "ERROR");
|
|
|
|
|
UIFactory.SetLayoutElement(instanceIdInput.UIRoot, minHeight: 25, minWidth: 100, flexibleWidth: 0);
|
2021-05-11 19:18:27 +10:00
|
|
|
|
instanceIdInput.Component.readOnly = true;
|
2021-05-05 21:27:09 +10:00
|
|
|
|
|
|
|
|
|
unityObjectRow.SetActive(false);
|
|
|
|
|
|
|
|
|
|
ConstructTextureHelper();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Texture viewer helper
|
|
|
|
|
|
2021-05-07 17:06:56 +10:00
|
|
|
|
private InputFieldRef textureSavePathInput;
|
2021-05-05 21:27:09 +10:00
|
|
|
|
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));
|
2021-05-11 19:18:27 +10:00
|
|
|
|
UIFactory.SetLayoutElement(saveBtn.Component.gameObject, minHeight: 25, minWidth: 100, flexibleWidth: 0);
|
2021-05-05 21:27:09 +10:00
|
|
|
|
saveBtn.OnClick += OnSaveTextureClicked;
|
|
|
|
|
|
2021-05-07 17:06:56 +10:00
|
|
|
|
textureSavePathInput = UIFactory.CreateInputField(saveRowObj, "SaveInput", "...");
|
|
|
|
|
UIFactory.SetLayoutElement(textureSavePathInput.UIRoot, minHeight: 25, minWidth: 100, flexibleWidth: 9999);
|
2021-05-05 21:27:09 +10:00
|
|
|
|
|
|
|
|
|
// Actual texture viewer
|
|
|
|
|
|
2021-05-31 19:10:05 +10:00
|
|
|
|
var imageViewport = UIFactory.CreateVerticalGroup(textureViewer, "Viewport", false, false, true, true);
|
|
|
|
|
imageViewport.GetComponent<Image>().color = Color.white;
|
|
|
|
|
imageViewport.AddComponent<Mask>().showMaskGraphic = false;
|
2021-05-05 21:27:09 +10:00
|
|
|
|
|
2021-05-31 19:10:05 +10:00
|
|
|
|
var imageObj = UIFactory.CreateUIObject("Image", imageViewport);
|
2021-05-05 21:27:09 +10:00
|
|
|
|
var fitter = imageObj.AddComponent<ContentSizeFitter>();
|
|
|
|
|
fitter.verticalFit = ContentSizeFitter.FitMode.PreferredSize;
|
2021-05-31 19:10:05 +10:00
|
|
|
|
textureImage = imageObj.AddComponent<Image>();
|
2021-10-16 18:10:23 +11:00
|
|
|
|
textureImageLayout = UIFactory.SetLayoutElement(imageObj, flexibleWidth: 1, flexibleHeight: 1);
|
2021-05-05 21:27:09 +10:00
|
|
|
|
|
|
|
|
|
textureViewer.SetActive(false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void SetTextureViewer()
|
|
|
|
|
{
|
|
|
|
|
if (!this.TextureRef)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
var name = TextureRef.name;
|
|
|
|
|
if (string.IsNullOrEmpty(name))
|
|
|
|
|
name = "untitled";
|
|
|
|
|
|
2021-05-07 17:06:56 +10:00
|
|
|
|
textureSavePathInput.Text = Path.Combine(ConfigManager.Default_Output_Path.Value, $"{name}.png");
|
2021-05-05 21:27:09 +10:00
|
|
|
|
|
|
|
|
|
var sprite = TextureUtilProvider.Instance.CreateSprite(TextureRef);
|
|
|
|
|
textureImage.sprite = sprite;
|
|
|
|
|
|
|
|
|
|
textureImageLayout.preferredHeight = sprite.rect.height;
|
2021-10-16 18:10:23 +11:00
|
|
|
|
// not really working, its always stretched horizontally for some reason.
|
2021-05-05 21:27:09 +10:00
|
|
|
|
textureImageLayout.preferredWidth = sprite.rect.width;
|
2021-04-26 19:56:21 +10:00
|
|
|
|
}
|
2021-05-05 21:27:09 +10:00
|
|
|
|
|
|
|
|
|
private void OnSaveTextureClicked()
|
|
|
|
|
{
|
|
|
|
|
if (!TextureRef)
|
|
|
|
|
{
|
|
|
|
|
ExplorerCore.LogWarning("Ref Texture is null, maybe it was destroyed?");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-07 17:06:56 +10:00
|
|
|
|
if (string.IsNullOrEmpty(textureSavePathInput.Text))
|
2021-05-05 21:27:09 +10:00
|
|
|
|
{
|
|
|
|
|
ExplorerCore.LogWarning("Save path cannot be empty!");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-07 17:06:56 +10:00
|
|
|
|
var path = textureSavePathInput.Text;
|
2021-05-05 21:27:09 +10:00
|
|
|
|
if (!path.EndsWith(".png", StringComparison.InvariantCultureIgnoreCase))
|
|
|
|
|
{
|
|
|
|
|
ExplorerCore.LogWarning("Desired save path must end with '.png'!");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-16 18:10:23 +11:00
|
|
|
|
path = IOUtility.EnsureValidFilePath(path);
|
2021-05-05 21:27:09 +10:00
|
|
|
|
|
|
|
|
|
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
|
2021-04-26 19:56:21 +10:00
|
|
|
|
}
|
|
|
|
|
}
|