mirror of
https://github.com/GrahamKracker/UnityExplorer.git
synced 2025-07-18 09:07:51 +08:00
Rewriting everything from scratch, developed generic ObjectPool system
This commit is contained in:
173
src/UI/Inspectors/GameObjectInspector.cs
Normal file
173
src/UI/Inspectors/GameObjectInspector.cs
Normal file
@ -0,0 +1,173 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.UI.ObjectPool;
|
||||
using UnityExplorer.UI.Utility;
|
||||
using UnityExplorer.UI.Widgets;
|
||||
|
||||
namespace UnityExplorer.UI.Inspectors
|
||||
{
|
||||
public class GameObjectInspector : InspectorBase
|
||||
{
|
||||
public GameObject Target;
|
||||
|
||||
public override GameObject UIRoot => uiRoot;
|
||||
private GameObject uiRoot;
|
||||
|
||||
private Text NameText;
|
||||
|
||||
public TransformTree TransformTree;
|
||||
private ScrollPool<TransformCell> transformScroll;
|
||||
|
||||
public ButtonListSource<Component> ComponentList;
|
||||
private ScrollPool<ButtonCell> componentScroll;
|
||||
|
||||
public override GameObject CreateContent(GameObject parent)
|
||||
{
|
||||
uiRoot = UIFactory.CreateVerticalGroup(Pool<GameObjectInspector>.Instance.InactiveHolder,
|
||||
"GameObjectInspector", true, true, true, true, 5, new Vector4(4, 4, 4, 4), new Color(0.12f, 0.12f, 0.12f));
|
||||
|
||||
NameText = UIFactory.CreateLabel(uiRoot, "Title", "not set", TextAnchor.MiddleLeft, fontSize: 20);
|
||||
UIFactory.SetLayoutElement(NameText.gameObject, minHeight: 30, flexibleHeight: 0);
|
||||
|
||||
var listHolder = UIFactory.CreateHorizontalGroup(uiRoot, "ListHolder", true, true, true, true, 5, new Vector4(2, 2, 2, 2));
|
||||
UIFactory.SetLayoutElement(listHolder, flexibleWidth: 9999, flexibleHeight: 9999);
|
||||
|
||||
transformScroll = UIFactory.CreateScrollPool<TransformCell>(listHolder, "TransformTree", out GameObject transformObj,
|
||||
out GameObject transformContent, new Color(0.11f, 0.11f, 0.11f));
|
||||
UIFactory.SetLayoutElement(transformObj, flexibleHeight: 9999);
|
||||
UIFactory.SetLayoutElement(transformContent, flexibleHeight: 9999);
|
||||
|
||||
componentScroll = UIFactory.CreateScrollPool<ButtonCell>(listHolder, "ComponentList", out GameObject compObj,
|
||||
out GameObject compContent, new Color(0.11f, 0.11f, 0.11f));
|
||||
UIFactory.SetLayoutElement(compObj, flexibleHeight: 9999);
|
||||
UIFactory.SetLayoutElement(compContent, flexibleHeight: 9999);
|
||||
|
||||
TransformTree = new TransformTree(transformScroll) { GetRootEntriesMethod = GetTransformEntries };
|
||||
TransformTree.Init();
|
||||
|
||||
ComponentList = new ButtonListSource<Component>(componentScroll, GetComponentEntries, SetComponentCell, ShouldDisplay, OnComponentClicked);
|
||||
componentScroll.Initialize(ComponentList);
|
||||
|
||||
return uiRoot;
|
||||
}
|
||||
|
||||
private readonly List<GameObject> _rootEntries = new List<GameObject>();
|
||||
|
||||
private IEnumerable<GameObject> GetTransformEntries()
|
||||
{
|
||||
_rootEntries.Clear();
|
||||
for (int i = 0; i < Target.transform.childCount; i++)
|
||||
_rootEntries.Add(Target.transform.GetChild(i).gameObject);
|
||||
return _rootEntries;
|
||||
}
|
||||
|
||||
private readonly List<Component> _componentEntries = new List<Component>();
|
||||
|
||||
private List<Component> GetComponentEntries()
|
||||
{
|
||||
return _componentEntries;
|
||||
}
|
||||
|
||||
private static readonly Dictionary<Type, string> compToStringCache = new Dictionary<Type, string>();
|
||||
|
||||
private void SetComponentCell(ButtonCell cell, int index)
|
||||
{
|
||||
if (index < 0 || index >= _componentEntries.Count)
|
||||
{
|
||||
cell.Disable();
|
||||
return;
|
||||
}
|
||||
|
||||
cell.Enable();
|
||||
|
||||
var comp = _componentEntries[index];
|
||||
var type = comp.GetActualType();
|
||||
|
||||
if (!compToStringCache.ContainsKey(type))
|
||||
{
|
||||
compToStringCache.Add(type,
|
||||
$"<color={SignatureHighlighter.NAMESPACE}>{type.Namespace}</color>.{SignatureHighlighter.HighlightTypeName(type)}");
|
||||
}
|
||||
|
||||
cell.Button.ButtonText.text = compToStringCache[type];
|
||||
}
|
||||
|
||||
private bool ShouldDisplay(Component comp, string filter) => true;
|
||||
|
||||
private void OnComponentClicked(int index)
|
||||
{
|
||||
if (index < 0 || index >= _componentEntries.Count)
|
||||
return;
|
||||
|
||||
var comp = _componentEntries[index];
|
||||
if (comp)
|
||||
InspectorManager.Inspect(comp);
|
||||
}
|
||||
|
||||
public override void OnBorrowedFromPool(object target)
|
||||
{
|
||||
base.OnBorrowedFromPool(target);
|
||||
|
||||
Target = target as GameObject;
|
||||
|
||||
NameText.text = Target.name;
|
||||
this.Tab.TabText.text = $"[G] {Target.name}";
|
||||
|
||||
TransformTree.Rebuild();
|
||||
|
||||
ComponentList.ScrollPool.Rebuild();
|
||||
UpdateComponents();
|
||||
}
|
||||
|
||||
public override void OnReturnToPool()
|
||||
{
|
||||
base.OnReturnToPool();
|
||||
|
||||
// release component and transform lists
|
||||
this.TransformTree.ScrollPool.ReturnCells();
|
||||
this.TransformTree.ScrollPool.SetUninitialized();
|
||||
|
||||
this.ComponentList.ScrollPool.ReturnCells();
|
||||
this.ComponentList.ScrollPool.SetUninitialized();
|
||||
}
|
||||
|
||||
private float timeOfLastUpdate;
|
||||
|
||||
public override void Update()
|
||||
{
|
||||
// todo update tab title? or put that in InspectorBase update?
|
||||
|
||||
if (!this.IsActive)
|
||||
return;
|
||||
|
||||
if (Time.time - timeOfLastUpdate > 1f)
|
||||
{
|
||||
timeOfLastUpdate = Time.time;
|
||||
|
||||
// Refresh children and components
|
||||
TransformTree.RefreshData(true, false);
|
||||
|
||||
UpdateComponents();
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateComponents()
|
||||
{
|
||||
_componentEntries.Clear();
|
||||
foreach (var comp in Target.GetComponents<Component>())
|
||||
_componentEntries.Add(comp);
|
||||
|
||||
ComponentList.RefreshData();
|
||||
ComponentList.ScrollPool.RefreshCells(true);
|
||||
}
|
||||
|
||||
protected override void OnCloseClicked()
|
||||
{
|
||||
InspectorManager.ReleaseInspector(this);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,193 +0,0 @@
|
||||
//using System;
|
||||
//using System.Collections.Generic;
|
||||
//using System.Linq;
|
||||
//using System.Text;
|
||||
//using UnityEngine;
|
||||
//using UnityEngine.UI;
|
||||
//using UnityExplorer.Core.Runtime;
|
||||
//using UnityExplorer.UI.Utility;
|
||||
|
||||
//namespace UnityExplorer.UI.Inspectors.GameObjects
|
||||
//{
|
||||
// public class ChildList
|
||||
// {
|
||||
// internal static ChildList Instance;
|
||||
|
||||
// public ChildList()
|
||||
// {
|
||||
// Instance = this;
|
||||
// }
|
||||
|
||||
// public static PageHandler s_childListPageHandler;
|
||||
// private static GameObject s_childListContent;
|
||||
|
||||
// private static GameObject[] s_allChildren = new GameObject[0];
|
||||
// private static readonly List<GameObject> s_childrenShortlist = new List<GameObject>();
|
||||
// private static int s_lastChildCount;
|
||||
|
||||
// private static readonly List<Text> s_childListTexts = new List<Text>();
|
||||
// private static readonly List<Toggle> s_childListToggles = new List<Toggle>();
|
||||
|
||||
// internal void RefreshChildObjectList()
|
||||
// {
|
||||
// var go = GameObjectInspector.ActiveInstance.TargetGO;
|
||||
|
||||
// s_allChildren = new GameObject[go.transform.childCount];
|
||||
// for (int i = 0; i < go.transform.childCount; i++)
|
||||
// {
|
||||
// var child = go.transform.GetChild(i);
|
||||
// s_allChildren[i] = child.gameObject;
|
||||
// }
|
||||
|
||||
// var objects = s_allChildren;
|
||||
// s_childListPageHandler.ListCount = objects.Length;
|
||||
|
||||
// int newCount = 0;
|
||||
|
||||
// foreach (var itemIndex in s_childListPageHandler)
|
||||
// {
|
||||
// newCount++;
|
||||
|
||||
// // normalized index starting from 0
|
||||
// var i = itemIndex - s_childListPageHandler.StartIndex;
|
||||
|
||||
// if (itemIndex >= objects.Length)
|
||||
// {
|
||||
// if (i > s_lastChildCount || i >= s_childListTexts.Count)
|
||||
// break;
|
||||
|
||||
// GameObject label = s_childListTexts[i].transform.parent.parent.gameObject;
|
||||
// if (label.activeSelf)
|
||||
// label.SetActive(false);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// GameObject obj = objects[itemIndex];
|
||||
|
||||
// if (!obj)
|
||||
// continue;
|
||||
|
||||
// if (i >= s_childrenShortlist.Count)
|
||||
// {
|
||||
// s_childrenShortlist.Add(obj);
|
||||
// AddChildListButton();
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// s_childrenShortlist[i] = obj;
|
||||
// }
|
||||
|
||||
// var text = s_childListTexts[i];
|
||||
|
||||
// var name = obj.name;
|
||||
|
||||
// if (obj.transform.childCount > 0)
|
||||
// name = $"<color=grey>[{obj.transform.childCount}]</color> {name}";
|
||||
|
||||
// text.text = name;
|
||||
// text.color = obj.activeSelf ? Color.green : Color.red;
|
||||
|
||||
// var tog = s_childListToggles[i];
|
||||
// tog.isOn = obj.activeSelf;
|
||||
|
||||
// var label = text.transform.parent.parent.gameObject;
|
||||
// if (!label.activeSelf)
|
||||
// {
|
||||
// label.SetActive(true);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// s_lastChildCount = newCount;
|
||||
// }
|
||||
|
||||
// internal static void OnChildListObjectClicked(int index)
|
||||
// {
|
||||
// if (GameObjectInspector.ActiveInstance == null)
|
||||
// return;
|
||||
|
||||
// if (index >= s_childrenShortlist.Count || !s_childrenShortlist[index])
|
||||
// return;
|
||||
|
||||
// GameObjectInspector.ActiveInstance.ChangeInspectorTarget(s_childrenShortlist[index]);
|
||||
// GameObjectInspector.ActiveInstance.Update();
|
||||
// }
|
||||
|
||||
// internal static void OnChildListPageTurn()
|
||||
// {
|
||||
// if (Instance == null)
|
||||
// return;
|
||||
|
||||
// Instance.RefreshChildObjectList();
|
||||
// }
|
||||
|
||||
// internal static void OnToggleClicked(int index, bool newVal)
|
||||
// {
|
||||
// if (GameObjectInspector.ActiveInstance == null)
|
||||
// return;
|
||||
|
||||
// if (index >= s_childrenShortlist.Count || !s_childrenShortlist[index])
|
||||
// return;
|
||||
|
||||
// var obj = s_childrenShortlist[index];
|
||||
// obj.SetActive(newVal);
|
||||
// }
|
||||
|
||||
// #region UI CONSTRUCTION
|
||||
|
||||
// internal void ConstructChildList(GameObject parent)
|
||||
// {
|
||||
// var vertGroupObj = UIFactory.CreateVerticalGroup(parent, "ChildListGroup", false, true, true, true, 5, default, new Color(1, 1, 1, 0));
|
||||
// UIFactory.SetLayoutElement(vertGroupObj, minWidth: 120, flexibleWidth: 25000, minHeight: 200, flexibleHeight: 5000);
|
||||
|
||||
// var childTitle = UIFactory.CreateLabel(vertGroupObj, "ChildListTitle", "Children:", TextAnchor.MiddleLeft, Color.grey, true, 14);
|
||||
// UIFactory.SetLayoutElement(childTitle.gameObject, minHeight: 30);
|
||||
|
||||
// var childrenScrollObj = UIFactory.CreateScrollView(vertGroupObj, "ChildListScrollView", out s_childListContent,
|
||||
// out SliderScrollbar scroller, new Color(0.07f, 0.07f, 0.07f));
|
||||
// UIFactory.SetLayoutElement(childrenScrollObj, minHeight: 50);
|
||||
|
||||
// s_childListPageHandler = new PageHandler(scroller);
|
||||
// s_childListPageHandler.ConstructUI(vertGroupObj);
|
||||
// s_childListPageHandler.OnPageChanged += OnChildListPageTurn;
|
||||
// }
|
||||
|
||||
// internal void AddChildListButton()
|
||||
// {
|
||||
// int thisIndex = s_childListTexts.Count;
|
||||
|
||||
// var btnGroupObj = UIFactory.CreateHorizontalGroup(s_childListContent, "ChildButtonGroup", true, false, true, true,
|
||||
// 0, default, new Color(0.07f, 0.07f, 0.07f));
|
||||
// UIFactory.SetLayoutElement(btnGroupObj, flexibleWidth: 320, minHeight: 25, flexibleHeight: 0);
|
||||
// btnGroupObj.AddComponent<Mask>();
|
||||
|
||||
// var toggleObj = UIFactory.CreateToggle(btnGroupObj, "Toggle", out Toggle toggle, out Text toggleText, new Color(0.3f, 0.3f, 0.3f));
|
||||
// UIFactory.SetLayoutElement(toggleObj, minHeight: 25, minWidth: 25);
|
||||
// toggleText.text = "";
|
||||
// toggle.isOn = false;
|
||||
// s_childListToggles.Add(toggle);
|
||||
// toggle.onValueChanged.AddListener((bool val) => { OnToggleClicked(thisIndex, val); });
|
||||
|
||||
// var mainBtn = UIFactory.CreateButton(btnGroupObj,
|
||||
// "MainButton",
|
||||
// "",
|
||||
// () => { OnChildListObjectClicked(thisIndex); });
|
||||
|
||||
// RuntimeProvider.Instance.SetColorBlock(mainBtn, new Color(0.07f, 0.07f, 0.07f),
|
||||
// new Color(0.2f, 0.2f, 0.2f, 1), new Color(0.05f, 0.05f, 0.05f));
|
||||
|
||||
// UIFactory.SetLayoutElement(mainBtn.gameObject, minHeight: 25, flexibleHeight: 0, minWidth: 25, flexibleWidth: 9999);
|
||||
|
||||
// Text mainText = mainBtn.GetComponentInChildren<Text>();
|
||||
// mainText.alignment = TextAnchor.MiddleLeft;
|
||||
// mainText.horizontalOverflow = HorizontalWrapMode.Overflow;
|
||||
// mainText.resizeTextForBestFit = true;
|
||||
// mainText.resizeTextMaxSize = 14;
|
||||
// mainText.resizeTextMinSize = 10;
|
||||
|
||||
// s_childListTexts.Add(mainText);
|
||||
// }
|
||||
|
||||
// #endregion
|
||||
// }
|
||||
//}
|
@ -1,192 +0,0 @@
|
||||
//using System;
|
||||
//using System.Collections.Generic;
|
||||
//using System.Linq;
|
||||
//using System.Text;
|
||||
//using UnityEngine;
|
||||
//using UnityEngine.UI;
|
||||
//using UnityExplorer.Core;
|
||||
//using UnityExplorer.Core.Runtime;
|
||||
//using UnityExplorer.UI.Utility;
|
||||
|
||||
//namespace UnityExplorer.UI.Inspectors.GameObjects
|
||||
//{
|
||||
// public class ComponentList
|
||||
// {
|
||||
// internal static ComponentList Instance;
|
||||
|
||||
// public ComponentList()
|
||||
// {
|
||||
// Instance = this;
|
||||
// }
|
||||
|
||||
// public static PageHandler s_compListPageHandler;
|
||||
// private static Component[] s_allComps = new Component[0];
|
||||
// private static readonly List<Component> s_compShortlist = new List<Component>();
|
||||
// private static GameObject s_compListContent;
|
||||
// private static readonly List<Text> s_compListTexts = new List<Text>();
|
||||
// private static int s_lastCompCount;
|
||||
// public static readonly List<Toggle> s_compToggles = new List<Toggle>();
|
||||
|
||||
// internal void RefreshComponentList()
|
||||
// {
|
||||
// var go = GameObjectInspector.ActiveInstance.TargetGO;
|
||||
|
||||
// s_allComps = go.GetComponents<Component>().ToArray();
|
||||
|
||||
// var components = s_allComps;
|
||||
// s_compListPageHandler.ListCount = components.Length;
|
||||
|
||||
// //int startIndex = m_sceneListPageHandler.StartIndex;
|
||||
|
||||
// int newCount = 0;
|
||||
|
||||
// foreach (var itemIndex in s_compListPageHandler)
|
||||
// {
|
||||
// newCount++;
|
||||
|
||||
// // normalized index starting from 0
|
||||
// var i = itemIndex - s_compListPageHandler.StartIndex;
|
||||
|
||||
// if (itemIndex >= components.Length)
|
||||
// {
|
||||
// if (i > s_lastCompCount || i >= s_compListTexts.Count)
|
||||
// break;
|
||||
|
||||
// GameObject label = s_compListTexts[i].transform.parent.parent.gameObject;
|
||||
// if (label.activeSelf)
|
||||
// label.SetActive(false);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// Component comp = components[itemIndex];
|
||||
|
||||
// if (!comp)
|
||||
// continue;
|
||||
|
||||
// if (i >= s_compShortlist.Count)
|
||||
// {
|
||||
// s_compShortlist.Add(comp);
|
||||
// AddCompListButton();
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// s_compShortlist[i] = comp;
|
||||
// }
|
||||
|
||||
// var text = s_compListTexts[i];
|
||||
|
||||
// text.text = SignatureHighlighter.ParseFullSyntax(ReflectionUtility.GetActualType(comp), true);
|
||||
|
||||
// var toggle = s_compToggles[i];
|
||||
// if (comp.TryCast<Behaviour>() is Behaviour behaviour)
|
||||
// {
|
||||
// if (!toggle.gameObject.activeSelf)
|
||||
// toggle.gameObject.SetActive(true);
|
||||
|
||||
// toggle.isOn = behaviour.enabled;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// if (toggle.gameObject.activeSelf)
|
||||
// toggle.gameObject.SetActive(false);
|
||||
// }
|
||||
|
||||
// var label = text.transform.parent.parent.gameObject;
|
||||
// if (!label.activeSelf)
|
||||
// {
|
||||
// label.SetActive(true);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// s_lastCompCount = newCount;
|
||||
// }
|
||||
|
||||
// internal static void OnCompToggleClicked(int index, bool value)
|
||||
// {
|
||||
// var comp = s_compShortlist[index];
|
||||
// comp.TryCast<Behaviour>().enabled = value;
|
||||
// }
|
||||
|
||||
// internal static void OnCompListObjectClicked(int index)
|
||||
// {
|
||||
// if (index >= s_compShortlist.Count || !s_compShortlist[index])
|
||||
// return;
|
||||
|
||||
// InspectorManager.Instance.Inspect(s_compShortlist[index]);
|
||||
// }
|
||||
|
||||
// internal static void OnCompListPageTurn()
|
||||
// {
|
||||
// if (Instance == null)
|
||||
// return;
|
||||
|
||||
// Instance.RefreshComponentList();
|
||||
// }
|
||||
|
||||
|
||||
// #region UI CONSTRUCTION
|
||||
|
||||
// internal void ConstructCompList(GameObject parent)
|
||||
// {
|
||||
// var vertGroupObj = UIFactory.CreateVerticalGroup(parent, "ComponentList", false, true, true, true, 5, default, new Color(1, 1, 1, 0));
|
||||
// UIFactory.SetLayoutElement(vertGroupObj, minWidth: 120, flexibleWidth: 25000, minHeight: 200, flexibleHeight: 5000);
|
||||
|
||||
// var compTitle = UIFactory.CreateLabel(vertGroupObj, "ComponentsTitle", "Components:", TextAnchor.MiddleLeft, Color.grey);
|
||||
// UIFactory.SetLayoutElement(compTitle.gameObject, minHeight: 30);
|
||||
|
||||
// var compScrollObj = UIFactory.CreateScrollView(vertGroupObj, "ComponentListScrollView", out s_compListContent,
|
||||
// out SliderScrollbar scroller, new Color(0.07f, 0.07f, 0.07f));
|
||||
|
||||
// UIFactory.SetLayoutElement(compScrollObj, minHeight: 50, flexibleHeight: 5000);
|
||||
|
||||
// s_compListPageHandler = new PageHandler(scroller);
|
||||
// s_compListPageHandler.ConstructUI(vertGroupObj);
|
||||
// s_compListPageHandler.OnPageChanged += OnCompListPageTurn;
|
||||
// }
|
||||
|
||||
// internal void AddCompListButton()
|
||||
// {
|
||||
// int thisIndex = s_compListTexts.Count;
|
||||
|
||||
// GameObject groupObj = UIFactory.CreateHorizontalGroup(s_compListContent, "CompListButton", true, false, true, true, 0, default,
|
||||
// new Color(0.07f, 0.07f, 0.07f), TextAnchor.MiddleLeft);
|
||||
// UIFactory.SetLayoutElement(groupObj, minWidth: 25, flexibleWidth: 999, minHeight: 25, flexibleHeight: 0);
|
||||
// groupObj.AddComponent<Mask>();
|
||||
|
||||
// // Behaviour enabled toggle
|
||||
|
||||
// var toggleObj = UIFactory.CreateToggle(groupObj, "EnabledToggle", out Toggle toggle, out Text toggleText, new Color(0.3f, 0.3f, 0.3f));
|
||||
// UIFactory.SetLayoutElement(toggleObj, minWidth: 25, minHeight: 25);
|
||||
// toggleText.text = "";
|
||||
// toggle.isOn = true;
|
||||
// s_compToggles.Add(toggle);
|
||||
// toggle.onValueChanged.AddListener((bool val) => { OnCompToggleClicked(thisIndex, val); });
|
||||
|
||||
// // Main component button
|
||||
|
||||
// var mainBtn = UIFactory.CreateButton(groupObj,
|
||||
// "MainButton",
|
||||
// "",
|
||||
// () => { OnCompListObjectClicked(thisIndex); });
|
||||
|
||||
// RuntimeProvider.Instance.SetColorBlock(mainBtn, new Color(0.07f, 0.07f, 0.07f),
|
||||
// new Color(0.2f, 0.2f, 0.2f, 1), new Color(0.05f, 0.05f, 0.05f));
|
||||
|
||||
// UIFactory.SetLayoutElement(mainBtn.gameObject, minHeight: 25, flexibleHeight: 0, minWidth: 25, flexibleWidth: 999);
|
||||
|
||||
// // Component button text
|
||||
|
||||
// Text mainText = mainBtn.GetComponentInChildren<Text>();
|
||||
// mainText.alignment = TextAnchor.MiddleLeft;
|
||||
// mainText.horizontalOverflow = HorizontalWrapMode.Overflow;
|
||||
// mainText.resizeTextForBestFit = true;
|
||||
// mainText.resizeTextMaxSize = 14;
|
||||
// mainText.resizeTextMinSize = 8;
|
||||
|
||||
// s_compListTexts.Add(mainText);
|
||||
// }
|
||||
|
||||
// #endregion
|
||||
// }
|
||||
//}
|
@ -1,467 +0,0 @@
|
||||
//using System;
|
||||
//using System.Collections.Generic;
|
||||
//using System.Linq;
|
||||
//using System.Text;
|
||||
//using UnityEngine;
|
||||
//using UnityEngine.UI;
|
||||
//using UnityExplorer.Core.Input;
|
||||
//using UnityExplorer.Core.Runtime;
|
||||
|
||||
//namespace UnityExplorer.UI.Inspectors.GameObjects
|
||||
//{
|
||||
// public class GameObjectControls
|
||||
// {
|
||||
// internal static GameObjectControls Instance;
|
||||
|
||||
// public GameObjectControls()
|
||||
// {
|
||||
// Instance = this;
|
||||
// }
|
||||
|
||||
// internal static bool Showing;
|
||||
|
||||
// internal static void ToggleVisibility() => SetVisibility(!Showing);
|
||||
|
||||
// internal static void SetVisibility(bool show)
|
||||
// {
|
||||
// if (show == Showing)
|
||||
// return;
|
||||
|
||||
// Showing = show;
|
||||
|
||||
// m_hideShowLabel.text = show ? "Hide" : "Show";
|
||||
// m_contentObj.SetActive(show);
|
||||
// }
|
||||
|
||||
// internal static GameObject m_contentObj;
|
||||
// internal static Text m_hideShowLabel;
|
||||
|
||||
// private static InputField s_setParentInput;
|
||||
|
||||
// private static ControlEditor s_positionControl;
|
||||
// private static ControlEditor s_localPosControl;
|
||||
// private static ControlEditor s_rotationControl;
|
||||
// private static ControlEditor s_scaleControl;
|
||||
|
||||
// // Transform Vector editors
|
||||
|
||||
// internal struct ControlEditor
|
||||
// {
|
||||
// public InputField fullValue;
|
||||
// public Slider[] sliders;
|
||||
// public InputField[] inputs;
|
||||
// public Text[] values;
|
||||
// }
|
||||
|
||||
// internal static bool s_sliderChangedWanted;
|
||||
// private static Slider s_currentSlider;
|
||||
// private static ControlType s_currentSliderType;
|
||||
// private static VectorValue s_currentSliderValueType;
|
||||
// private static float s_currentSliderValue;
|
||||
|
||||
// internal enum ControlType
|
||||
// {
|
||||
// position,
|
||||
// localPosition,
|
||||
// eulerAngles,
|
||||
// localScale
|
||||
// }
|
||||
|
||||
// internal enum VectorValue
|
||||
// {
|
||||
// x, y, z
|
||||
// };
|
||||
|
||||
// internal void RefreshControls()
|
||||
// {
|
||||
// var go = GameObjectInspector.ActiveInstance.TargetGO;
|
||||
|
||||
// s_positionControl.fullValue.text = go.transform.position.ToStringPretty();
|
||||
// s_positionControl.values[0].text = go.transform.position.x.ToString("F3");
|
||||
// s_positionControl.values[1].text = go.transform.position.y.ToString("F3");
|
||||
// s_positionControl.values[2].text = go.transform.position.z.ToString("F3");
|
||||
|
||||
// s_localPosControl.fullValue.text = go.transform.localPosition.ToStringPretty();
|
||||
// s_localPosControl.values[0].text = go.transform.localPosition.x.ToString("F3");
|
||||
// s_localPosControl.values[1].text = go.transform.localPosition.y.ToString("F3");
|
||||
// s_localPosControl.values[2].text = go.transform.localPosition.z.ToString("F3");
|
||||
|
||||
// s_rotationControl.fullValue.text = go.transform.eulerAngles.ToStringPretty();
|
||||
// s_rotationControl.values[0].text = go.transform.eulerAngles.x.ToString("F3");
|
||||
// s_rotationControl.values[1].text = go.transform.eulerAngles.y.ToString("F3");
|
||||
// s_rotationControl.values[2].text = go.transform.eulerAngles.z.ToString("F3");
|
||||
|
||||
// s_scaleControl.fullValue.text = go.transform.localScale.ToStringPretty();
|
||||
// s_scaleControl.values[0].text = go.transform.localScale.x.ToString("F3");
|
||||
// s_scaleControl.values[1].text = go.transform.localScale.y.ToString("F3");
|
||||
// s_scaleControl.values[2].text = go.transform.localScale.z.ToString("F3");
|
||||
|
||||
// }
|
||||
|
||||
// internal static void OnSetParentClicked()
|
||||
// {
|
||||
// var go = GameObjectInspector.ActiveInstance.TargetGO;
|
||||
|
||||
// if (!go)
|
||||
// return;
|
||||
|
||||
// var input = s_setParentInput.text;
|
||||
|
||||
// if (string.IsNullOrEmpty(input))
|
||||
// {
|
||||
// go.transform.parent = null;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// if (GameObject.Find(input) is GameObject newParent)
|
||||
// {
|
||||
// go.transform.parent = newParent.transform;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// ExplorerCore.Log($"Could not find any GameObject from name or path '{input}'! Note: The target must be enabled.");
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// internal static void OnSliderControlChanged(float value, Slider slider, ControlType controlType, VectorValue vectorValue)
|
||||
// {
|
||||
// if (value == 0)
|
||||
// s_sliderChangedWanted = false;
|
||||
// else
|
||||
// {
|
||||
// if (!s_sliderChangedWanted)
|
||||
// {
|
||||
// s_sliderChangedWanted = true;
|
||||
// s_currentSlider = slider;
|
||||
// s_currentSliderType = controlType;
|
||||
// s_currentSliderValueType = vectorValue;
|
||||
// }
|
||||
|
||||
// s_currentSliderValue = value;
|
||||
// }
|
||||
// }
|
||||
|
||||
// internal static void UpdateSliderControl()
|
||||
// {
|
||||
// if (!InputManager.GetMouseButton(0))
|
||||
// {
|
||||
// s_sliderChangedWanted = false;
|
||||
// s_currentSlider.value = 0;
|
||||
|
||||
// return;
|
||||
// }
|
||||
|
||||
// if (GameObjectInspector.ActiveInstance == null) return;
|
||||
|
||||
// var transform = GameObjectInspector.ActiveInstance.TargetGO.transform;
|
||||
|
||||
// // get the current vector for the control type
|
||||
// Vector3 vector = Vector2.zero;
|
||||
// switch (s_currentSliderType)
|
||||
// {
|
||||
// case ControlType.position:
|
||||
// vector = transform.position; break;
|
||||
// case ControlType.localPosition:
|
||||
// vector = transform.localPosition; break;
|
||||
// case ControlType.eulerAngles:
|
||||
// vector = transform.eulerAngles; break;
|
||||
// case ControlType.localScale:
|
||||
// vector = transform.localScale; break;
|
||||
// }
|
||||
|
||||
// // apply vector value change
|
||||
// switch (s_currentSliderValueType)
|
||||
// {
|
||||
// case VectorValue.x:
|
||||
// vector.x += s_currentSliderValue; break;
|
||||
// case VectorValue.y:
|
||||
// vector.y += s_currentSliderValue; break;
|
||||
// case VectorValue.z:
|
||||
// vector.z += s_currentSliderValue; break;
|
||||
// }
|
||||
|
||||
// // set vector to transform member
|
||||
// switch (s_currentSliderType)
|
||||
// {
|
||||
// case ControlType.position:
|
||||
// transform.position = vector; break;
|
||||
// case ControlType.localPosition:
|
||||
// transform.localPosition = vector; break;
|
||||
// case ControlType.eulerAngles:
|
||||
// transform.eulerAngles = vector; break;
|
||||
// case ControlType.localScale:
|
||||
// transform.localScale = vector; break;
|
||||
// }
|
||||
// }
|
||||
|
||||
// internal static void OnVectorControlInputApplied(ControlType controlType, VectorValue vectorValue)
|
||||
// {
|
||||
// if (!(InspectorManager.Instance.m_activeInspector is GameObjectInspector instance)) return;
|
||||
|
||||
// // get relevant input for controltype + value
|
||||
|
||||
// InputField[] inputs = null;
|
||||
// switch (controlType)
|
||||
// {
|
||||
// case ControlType.position:
|
||||
// inputs = s_positionControl.inputs; break;
|
||||
// case ControlType.localPosition:
|
||||
// inputs = s_localPosControl.inputs; break;
|
||||
// case ControlType.eulerAngles:
|
||||
// inputs = s_rotationControl.inputs; break;
|
||||
// case ControlType.localScale:
|
||||
// inputs = s_scaleControl.inputs; break;
|
||||
// }
|
||||
// InputField input = inputs[(int)vectorValue];
|
||||
|
||||
// float val = float.Parse(input.text);
|
||||
|
||||
// // apply transform value
|
||||
|
||||
// Vector3 vector = Vector3.zero;
|
||||
// var transform = instance.TargetGO.transform;
|
||||
// switch (controlType)
|
||||
// {
|
||||
// case ControlType.position:
|
||||
// vector = transform.position; break;
|
||||
// case ControlType.localPosition:
|
||||
// vector = transform.localPosition; break;
|
||||
// case ControlType.eulerAngles:
|
||||
// vector = transform.eulerAngles; break;
|
||||
// case ControlType.localScale:
|
||||
// vector = transform.localScale; break;
|
||||
// }
|
||||
|
||||
// switch (vectorValue)
|
||||
// {
|
||||
// case VectorValue.x:
|
||||
// vector.x = val; break;
|
||||
// case VectorValue.y:
|
||||
// vector.y = val; break;
|
||||
// case VectorValue.z:
|
||||
// vector.z = val; break;
|
||||
// }
|
||||
|
||||
// // set back to transform
|
||||
// switch (controlType)
|
||||
// {
|
||||
// case ControlType.position:
|
||||
// transform.position = vector; break;
|
||||
// case ControlType.localPosition:
|
||||
// transform.localPosition = vector; break;
|
||||
// case ControlType.eulerAngles:
|
||||
// transform.eulerAngles = vector; break;
|
||||
// case ControlType.localScale:
|
||||
// transform.localScale = vector; break;
|
||||
// }
|
||||
// }
|
||||
|
||||
// //#region UI CONSTRUCTION
|
||||
|
||||
// //internal void ConstructControls(GameObject parent)
|
||||
// //{
|
||||
// // var mainGroup = UIFactory.CreateVerticalGroup(parent, "ControlsGroup", false, false, true, true, 5, new Vector4(4,4,4,4),
|
||||
// // new Color(0.07f, 0.07f, 0.07f));
|
||||
|
||||
// // // ~~~~~~ Top row ~~~~~~
|
||||
|
||||
// // var topRow = UIFactory.CreateHorizontalGroup(mainGroup, "TopRow", false, false, true, true, 5, default, new Color(1, 1, 1, 0));
|
||||
|
||||
// // var hideButton = UIFactory.CreateButton(topRow, "ToggleShowButton", "Show", ToggleVisibility, new Color(0.16f, 0.16f, 0.16f));
|
||||
// // UIFactory.SetLayoutElement(hideButton.gameObject, minWidth: 40, flexibleWidth: 0, minHeight: 25, flexibleHeight: 0);
|
||||
// // m_hideShowLabel = hideButton.GetComponentInChildren<Text>();
|
||||
|
||||
// // var topTitle = UIFactory.CreateLabel(topRow, "ControlsLabel", "Controls", TextAnchor.MiddleLeft);
|
||||
// // UIFactory.SetLayoutElement(topTitle.gameObject, minWidth: 100, flexibleWidth: 9500, minHeight: 25);
|
||||
|
||||
// // //// ~~~~~~~~ Content ~~~~~~~~ //
|
||||
|
||||
// // m_contentObj = UIFactory.CreateVerticalGroup(mainGroup, "ContentGroup", true, false, true, true, 5, default, new Color(1, 1, 1, 0));
|
||||
|
||||
// // // transform controls
|
||||
// // ConstructVector3Editor(m_contentObj, "Position", ControlType.position, out s_positionControl);
|
||||
// // ConstructVector3Editor(m_contentObj, "Local Position", ControlType.localPosition, out s_localPosControl);
|
||||
// // ConstructVector3Editor(m_contentObj, "Rotation", ControlType.eulerAngles, out s_rotationControl);
|
||||
// // ConstructVector3Editor(m_contentObj, "Scale", ControlType.localScale, out s_scaleControl);
|
||||
|
||||
// // // set parent
|
||||
// // ConstructSetParent(m_contentObj);
|
||||
|
||||
// // // bottom row buttons
|
||||
// // ConstructBottomButtons(m_contentObj);
|
||||
|
||||
// // // set controls content inactive now that content is made (otherwise TMP font size goes way too big?)
|
||||
// // m_contentObj.SetActive(false);
|
||||
// //}
|
||||
|
||||
// //internal void ConstructSetParent(GameObject contentObj)
|
||||
// //{
|
||||
// // var setParentGroupObj = UIFactory.CreateHorizontalGroup(contentObj, "SetParentRow", false, false, true, true, 5, default,
|
||||
// // new Color(1, 1, 1, 0));
|
||||
// // UIFactory.SetLayoutElement(setParentGroupObj, minHeight: 25, flexibleHeight: 0);
|
||||
|
||||
// // var title = UIFactory.CreateLabel(setParentGroupObj, "SetParentLabel", "Set Parent:", TextAnchor.MiddleLeft, Color.grey);
|
||||
// // UIFactory.SetLayoutElement(title.gameObject, minWidth: 110, minHeight: 25, flexibleHeight: 0);
|
||||
|
||||
// // var inputFieldObj = UIFactory.CreateInputField(setParentGroupObj, "SetParentInputField", "Enter a GameObject name or path...");
|
||||
// // s_setParentInput = inputFieldObj.GetComponent<InputField>();
|
||||
// // UIFactory.SetLayoutElement(inputFieldObj, minHeight: 25, preferredWidth: 400, flexibleWidth: 9999);
|
||||
|
||||
// // var applyButton = UIFactory.CreateButton(setParentGroupObj, "SetParentButton", "Apply", OnSetParentClicked);
|
||||
// // UIFactory.SetLayoutElement(applyButton.gameObject, minWidth: 55, flexibleWidth: 0, minHeight: 25, flexibleHeight: 0);
|
||||
// //}
|
||||
|
||||
// //internal void ConstructVector3Editor(GameObject parent, string titleText, ControlType type, out ControlEditor editor)
|
||||
// //{
|
||||
// // editor = new ControlEditor();
|
||||
|
||||
// // var topBarObj = UIFactory.CreateHorizontalGroup(parent, "Vector3Editor", false, false, true, true, 5, default, new Color(1, 1, 1, 0));
|
||||
// // UIFactory.SetLayoutElement(topBarObj, minHeight: 25, flexibleHeight: 0);
|
||||
|
||||
// // var title = UIFactory.CreateLabel(topBarObj, "Title", titleText, TextAnchor.MiddleLeft, Color.grey);
|
||||
// // UIFactory.SetLayoutElement(title.gameObject, minWidth: 110, flexibleWidth: 0, minHeight: 25);
|
||||
|
||||
// // // expand button
|
||||
// // var expandButton = UIFactory.CreateButton(topBarObj, "ExpandArrow", "▼");
|
||||
// // var expandText = expandButton.GetComponentInChildren<Text>();
|
||||
// // expandText.fontSize = 12;
|
||||
// // UIFactory.SetLayoutElement(expandButton.gameObject, minWidth: 35, flexibleWidth: 0, minHeight: 25, flexibleHeight: 0);
|
||||
|
||||
// // // readonly value input
|
||||
|
||||
// // var valueInputObj = UIFactory.CreateInputField(topBarObj, "ValueInput", "...");
|
||||
// // var valueInput = valueInputObj.GetComponent<InputField>();
|
||||
// // valueInput.readOnly = true;
|
||||
// // UIFactory.SetLayoutElement(valueInputObj, minHeight: 25, flexibleHeight: 0, preferredWidth: 400, flexibleWidth: 9999);
|
||||
|
||||
// // editor.fullValue = valueInput;
|
||||
|
||||
// // editor.sliders = new Slider[3];
|
||||
// // editor.inputs = new InputField[3];
|
||||
// // editor.values = new Text[3];
|
||||
|
||||
// // var xRow = ConstructEditorRow(parent, editor, type, VectorValue.x);
|
||||
// // xRow.SetActive(false);
|
||||
// // var yRow = ConstructEditorRow(parent, editor, type, VectorValue.y);
|
||||
// // yRow.SetActive(false);
|
||||
// // var zRow = ConstructEditorRow(parent, editor, type, VectorValue.z);
|
||||
// // zRow.SetActive(false);
|
||||
|
||||
// // // add expand callback now that we have group reference
|
||||
// // expandButton.onClick.AddListener(ToggleExpand);
|
||||
// // void ToggleExpand()
|
||||
// // {
|
||||
// // if (xRow.activeSelf)
|
||||
// // {
|
||||
// // xRow.SetActive(false);
|
||||
// // yRow.SetActive(false);
|
||||
// // zRow.SetActive(false);
|
||||
// // expandText.text = "▼";
|
||||
// // }
|
||||
// // else
|
||||
// // {
|
||||
// // xRow.SetActive(true);
|
||||
// // yRow.SetActive(true);
|
||||
// // zRow.SetActive(true);
|
||||
// // expandText.text = "▲";
|
||||
// // }
|
||||
// // }
|
||||
// //}
|
||||
|
||||
// //internal GameObject ConstructEditorRow(GameObject parent, ControlEditor editor, ControlType type, VectorValue vectorValue)
|
||||
// //{
|
||||
// // var rowObject = UIFactory.CreateHorizontalGroup(parent, "EditorRow", false, false, true, true, 5, default, new Color(1, 1, 1, 0));
|
||||
// // UIFactory.SetLayoutElement(rowObject, minHeight: 25, flexibleHeight: 0, minWidth: 100);
|
||||
|
||||
// // // Value labels
|
||||
|
||||
// // var valueTitle = UIFactory.CreateLabel(rowObject, "ValueTitle", $"{vectorValue.ToString().ToUpper()}:", TextAnchor.MiddleLeft, Color.cyan);
|
||||
// // UIFactory.SetLayoutElement(valueTitle.gameObject, minHeight: 25, flexibleHeight: 0, minWidth: 25, flexibleWidth: 0);
|
||||
|
||||
// // // actual value label
|
||||
// // var valueLabel = UIFactory.CreateLabel(rowObject, "ValueLabel", "", TextAnchor.MiddleLeft);
|
||||
// // editor.values[(int)vectorValue] = valueLabel;
|
||||
// // UIFactory.SetLayoutElement(valueLabel.gameObject, minWidth: 85, flexibleWidth: 0, minHeight: 25);
|
||||
|
||||
// // // input field
|
||||
|
||||
// // var inputHolder = UIFactory.CreateVerticalGroup(rowObject, "InputFieldGroup", false, false, true, true, 0, default, new Color(1, 1, 1, 0));
|
||||
|
||||
// // var inputObj = UIFactory.CreateInputField(inputHolder, "InputField", "...");
|
||||
// // var input = inputObj.GetComponent<InputField>();
|
||||
// // //input.characterValidation = InputField.CharacterValidation.Decimal;
|
||||
|
||||
// // UIFactory.SetLayoutElement(inputObj, minHeight: 25, flexibleHeight: 0, minWidth: 90, flexibleWidth: 50);
|
||||
|
||||
// // editor.inputs[(int)vectorValue] = input;
|
||||
|
||||
// // // apply button
|
||||
|
||||
// // var applyBtn = UIFactory.CreateButton(rowObject, "ApplyButton", "Apply", () => { OnVectorControlInputApplied(type, vectorValue); });
|
||||
// // UIFactory.SetLayoutElement(applyBtn.gameObject, minWidth: 60, minHeight: 25);
|
||||
|
||||
|
||||
// // // Slider
|
||||
|
||||
// // var sliderObj = UIFactory.CreateSlider(rowObject, "VectorSlider", out Slider slider);
|
||||
// // UIFactory.SetLayoutElement(sliderObj, minHeight: 20, flexibleHeight: 0, minWidth: 200, flexibleWidth: 9000);
|
||||
// // sliderObj.transform.Find("Fill Area").gameObject.SetActive(false);
|
||||
// // RuntimeProvider.Instance.SetColorBlock(slider, new Color(0.65f, 0.65f, 0.65f));
|
||||
// // slider.minValue = -2;
|
||||
// // slider.maxValue = 2;
|
||||
// // slider.value = 0;
|
||||
// // slider.onValueChanged.AddListener((float val) => { OnSliderControlChanged(val, slider, type, vectorValue); });
|
||||
// // editor.sliders[(int)vectorValue] = slider;
|
||||
|
||||
// // return rowObject;
|
||||
// //}
|
||||
|
||||
// //internal void ConstructBottomButtons(GameObject contentObj)
|
||||
// //{
|
||||
// // var bottomRow = UIFactory.CreateHorizontalGroup(contentObj, "BottomButtons", true, true, false, false, 4, default, new Color(1, 1, 1, 0));
|
||||
|
||||
// // var instantiateBtn = UIFactory.CreateButton(bottomRow, "InstantiateBtn", "Instantiate", InstantiateBtn, new Color(0.2f, 0.2f, 0.2f));
|
||||
// // UIFactory.SetLayoutElement(instantiateBtn.gameObject, minWidth: 150);
|
||||
|
||||
// // void InstantiateBtn()
|
||||
// // {
|
||||
// // var go = GameObjectInspector.ActiveInstance.TargetGO;
|
||||
// // if (!go)
|
||||
// // return;
|
||||
|
||||
// // var clone = GameObject.Instantiate(go);
|
||||
// // InspectorManager.Instance.Inspect(clone);
|
||||
// // }
|
||||
|
||||
// // var dontDestroyBtn = UIFactory.CreateButton(bottomRow, "DontDestroyButton", "Set DontDestroyOnLoad", DontDestroyOnLoadBtn,
|
||||
// // new Color(0.2f, 0.2f, 0.2f));
|
||||
// // UIFactory.SetLayoutElement(dontDestroyBtn.gameObject, flexibleWidth: 5000);
|
||||
|
||||
// // void DontDestroyOnLoadBtn()
|
||||
// // {
|
||||
// // var go = GameObjectInspector.ActiveInstance.TargetGO;
|
||||
// // if (!go)
|
||||
// // return;
|
||||
|
||||
// // GameObject.DontDestroyOnLoad(go);
|
||||
// // }
|
||||
|
||||
// // var destroyBtn = UIFactory.CreateButton(bottomRow, "DestroyButton", "Destroy", DestroyBtn, new Color(0.2f, 0.2f, 0.2f));
|
||||
// // UIFactory.SetLayoutElement(destroyBtn.gameObject, minWidth: 150);
|
||||
// // var destroyText = destroyBtn.GetComponentInChildren<Text>();
|
||||
// // destroyText.color = Color.red;
|
||||
|
||||
// // void DestroyBtn()
|
||||
// // {
|
||||
// // var go = GameObjectInspector.ActiveInstance.TargetGO;
|
||||
// // if (!go)
|
||||
// // return;
|
||||
|
||||
// // GameObject.Destroy(go);
|
||||
// // }
|
||||
// //}
|
||||
|
||||
// //#endregion
|
||||
// }
|
||||
//}
|
@ -1,349 +0,0 @@
|
||||
//using System;
|
||||
//using System.Collections.Generic;
|
||||
//using System.Linq;
|
||||
//using System.Text;
|
||||
//using UnityEngine;
|
||||
//using UnityEngine.UI;
|
||||
//using UnityExplorer.Core.Runtime;
|
||||
|
||||
//namespace UnityExplorer.UI.Inspectors.GameObjects
|
||||
//{
|
||||
// public class GameObjectInspector : InspectorBase
|
||||
// {
|
||||
// public override string TabLabel => $" <color=cyan>[G]</color> {TargetGO?.name}";
|
||||
|
||||
// public static GameObjectInspector ActiveInstance { get; private set; }
|
||||
|
||||
// public GameObject TargetGO;
|
||||
|
||||
// //// sub modules
|
||||
// //internal static ChildList s_childList;
|
||||
// //internal static ComponentList s_compList;
|
||||
// //internal static GameObjectControls s_controls;
|
||||
|
||||
// internal static bool m_UIConstructed;
|
||||
|
||||
// public GameObjectInspector(GameObject target) : base(target)
|
||||
// {
|
||||
// ActiveInstance = this;
|
||||
|
||||
// TargetGO = target;
|
||||
|
||||
// if (!TargetGO)
|
||||
// {
|
||||
// ExplorerCore.LogWarning("Target GameObject is null!");
|
||||
// return;
|
||||
// }
|
||||
|
||||
// // one UI is used for all gameobject inspectors. no point recreating it.
|
||||
// if (!m_UIConstructed)
|
||||
// {
|
||||
// m_UIConstructed = true;
|
||||
|
||||
// //s_childList = new ChildList();
|
||||
// //s_compList = new ComponentList();
|
||||
// //s_controls = new GameObjectControls();
|
||||
|
||||
// //ConstructUI();
|
||||
// }
|
||||
// }
|
||||
|
||||
// public override void SetActive()
|
||||
// {
|
||||
// base.SetActive();
|
||||
// ActiveInstance = this;
|
||||
// }
|
||||
|
||||
// public override void SetInactive()
|
||||
// {
|
||||
// base.SetInactive();
|
||||
// ActiveInstance = null;
|
||||
// }
|
||||
|
||||
// internal void ChangeInspectorTarget(GameObject newTarget)
|
||||
// {
|
||||
// if (!newTarget)
|
||||
// return;
|
||||
|
||||
// this.Target = this.TargetGO = newTarget;
|
||||
// }
|
||||
|
||||
// // Update
|
||||
|
||||
// //public override void Update()
|
||||
// //{
|
||||
// // base.Update();
|
||||
|
||||
// // if (m_pendingDestroy || !this.IsActive)
|
||||
// // return;
|
||||
|
||||
// // RefreshTopInfo();
|
||||
|
||||
// // s_childList.RefreshChildObjectList();
|
||||
|
||||
// // s_compList.RefreshComponentList();
|
||||
|
||||
// // s_controls.RefreshControls();
|
||||
|
||||
// // if (GameObjectControls.s_sliderChangedWanted)
|
||||
// // GameObjectControls.UpdateSliderControl();
|
||||
// //}
|
||||
|
||||
// private static GameObject s_content;
|
||||
// public override GameObject Content
|
||||
// {
|
||||
// get => s_content;
|
||||
// set => s_content = value;
|
||||
// }
|
||||
|
||||
// private static string m_lastName;
|
||||
// public static InputField m_nameInput;
|
||||
|
||||
// private static string m_lastPath;
|
||||
// public static InputField m_pathInput;
|
||||
// private static RectTransform m_pathInputRect;
|
||||
// private static GameObject m_pathGroupObj;
|
||||
// private static Text m_hiddenPathText;
|
||||
// private static RectTransform m_hiddenPathRect;
|
||||
|
||||
// private static Toggle m_enabledToggle;
|
||||
// private static Text m_enabledText;
|
||||
// private static bool? m_lastEnabledState;
|
||||
|
||||
// private static Dropdown m_layerDropdown;
|
||||
// private static int m_lastLayer = -1;
|
||||
|
||||
// private static Text m_sceneText;
|
||||
// private static string m_lastScene;
|
||||
|
||||
// internal void RefreshTopInfo()
|
||||
// {
|
||||
// var target = TargetGO;
|
||||
// string name = target.name;
|
||||
|
||||
// if (m_lastName != name)
|
||||
// {
|
||||
// m_lastName = name;
|
||||
// m_nameInput.text = m_lastName;
|
||||
// }
|
||||
|
||||
// if (target.transform.parent)
|
||||
// {
|
||||
// if (!m_pathGroupObj.activeSelf)
|
||||
// m_pathGroupObj.SetActive(true);
|
||||
|
||||
// var path = target.transform.GetTransformPath(true);
|
||||
// if (m_lastPath != path)
|
||||
// {
|
||||
// m_lastPath = path;
|
||||
|
||||
// m_pathInput.text = path;
|
||||
// m_hiddenPathText.text = path;
|
||||
|
||||
// LayoutRebuilder.ForceRebuildLayoutImmediate(m_pathInputRect);
|
||||
// LayoutRebuilder.ForceRebuildLayoutImmediate(m_hiddenPathRect);
|
||||
// }
|
||||
// }
|
||||
// else if (m_pathGroupObj.activeSelf)
|
||||
// m_pathGroupObj.SetActive(false);
|
||||
|
||||
// if (m_lastEnabledState != target.activeSelf)
|
||||
// {
|
||||
// m_lastEnabledState = target.activeSelf;
|
||||
|
||||
// m_enabledToggle.isOn = target.activeSelf;
|
||||
// m_enabledText.text = target.activeSelf ? "Enabled" : "Disabled";
|
||||
// m_enabledText.color = target.activeSelf ? Color.green : Color.red;
|
||||
// }
|
||||
|
||||
// if (m_lastLayer != target.layer)
|
||||
// {
|
||||
// m_lastLayer = target.layer;
|
||||
// m_layerDropdown.value = target.layer;
|
||||
// }
|
||||
|
||||
// if (string.IsNullOrEmpty(m_lastScene) || m_lastScene != target.scene.name)
|
||||
// {
|
||||
// m_lastScene = target.scene.name;
|
||||
|
||||
// if (!string.IsNullOrEmpty(target.scene.name))
|
||||
// m_sceneText.text = m_lastScene;
|
||||
// else
|
||||
// m_sceneText.text = "None (Asset/Resource)";
|
||||
// }
|
||||
// }
|
||||
|
||||
// // UI Callbacks
|
||||
|
||||
// private static void OnApplyNameClicked()
|
||||
// {
|
||||
// if (ActiveInstance == null)
|
||||
// return;
|
||||
|
||||
// ActiveInstance.TargetGO.name = m_nameInput.text;
|
||||
// }
|
||||
|
||||
// private static void OnEnableToggled(bool enabled)
|
||||
// {
|
||||
// if (ActiveInstance == null)
|
||||
// return;
|
||||
|
||||
// ActiveInstance.TargetGO.SetActive(enabled);
|
||||
// }
|
||||
|
||||
// private static void OnLayerSelected(int layer)
|
||||
// {
|
||||
// if (ActiveInstance == null)
|
||||
// return;
|
||||
|
||||
// ActiveInstance.TargetGO.layer = layer;
|
||||
// }
|
||||
|
||||
// internal static void OnBackButtonClicked()
|
||||
// {
|
||||
// if (ActiveInstance == null)
|
||||
// return;
|
||||
|
||||
// ActiveInstance.ChangeInspectorTarget(ActiveInstance.TargetGO.transform.parent.gameObject);
|
||||
// }
|
||||
|
||||
// //#region UI CONSTRUCTION
|
||||
|
||||
// //internal void ConstructUI()
|
||||
// //{
|
||||
// // var parent = InspectorManager.m_inspectorContent;
|
||||
|
||||
// // s_content = UIFactory.CreateScrollView(parent, "GameObjectInspector_Content", out GameObject scrollContent, out _,
|
||||
// // new Color(0.1f, 0.1f, 0.1f));
|
||||
|
||||
// // UIFactory.SetLayoutGroup<VerticalLayoutGroup>(scrollContent.transform.parent.gameObject, true, true, true, true);
|
||||
|
||||
// // UIFactory.SetLayoutGroup<VerticalLayoutGroup>(scrollContent, true, true, true, true, 5);
|
||||
// // var contentFitter = scrollContent.GetComponent<ContentSizeFitter>();
|
||||
// // contentFitter.verticalFit = ContentSizeFitter.FitMode.Unconstrained;
|
||||
|
||||
// // ConstructTopArea(scrollContent);
|
||||
|
||||
// // s_controls.ConstructControls(scrollContent);
|
||||
|
||||
// // var midGroupObj = ConstructMidGroup(scrollContent);
|
||||
|
||||
// // s_childList.ConstructChildList(midGroupObj);
|
||||
// // s_compList.ConstructCompList(midGroupObj);
|
||||
|
||||
// // LayoutRebuilder.ForceRebuildLayoutImmediate(s_content.GetComponent<RectTransform>());
|
||||
// // Canvas.ForceUpdateCanvases();
|
||||
// //}
|
||||
|
||||
// //private void ConstructTopArea(GameObject scrollContent)
|
||||
// //{
|
||||
// // // path row
|
||||
|
||||
// // m_pathGroupObj = UIFactory.CreateHorizontalGroup(scrollContent, "TopArea", false, false, true, true, 5, default, new Color(0.1f, 0.1f, 0.1f));
|
||||
|
||||
// // var pathRect = m_pathGroupObj.GetComponent<RectTransform>();
|
||||
// // pathRect.sizeDelta = new Vector2(pathRect.sizeDelta.x, 20);
|
||||
// // UIFactory.SetLayoutElement(m_pathGroupObj, minHeight: 20, flexibleHeight: 75);
|
||||
|
||||
// // // Back button
|
||||
|
||||
// // var backButton = UIFactory.CreateButton(m_pathGroupObj, "BackButton", "◄", OnBackButtonClicked, new Color(0.15f, 0.15f, 0.15f));
|
||||
// // UIFactory.SetLayoutElement(backButton.gameObject, minWidth: 55, flexibleWidth: 0, minHeight: 25, flexibleHeight: 0);
|
||||
|
||||
// // m_hiddenPathText = UIFactory.CreateLabel(m_pathGroupObj, "HiddenPathText", "", TextAnchor.MiddleLeft);
|
||||
// // m_hiddenPathText.color = Color.clear;
|
||||
// // m_hiddenPathText.fontSize = 14;
|
||||
// // m_hiddenPathText.raycastTarget = false;
|
||||
|
||||
// // var hiddenFitter = m_hiddenPathText.gameObject.AddComponent<ContentSizeFitter>();
|
||||
// // hiddenFitter.verticalFit = ContentSizeFitter.FitMode.PreferredSize;
|
||||
|
||||
// // UIFactory.SetLayoutElement(m_hiddenPathText.gameObject, minHeight: 25, flexibleHeight: 125, minWidth: 250, flexibleWidth: 9000);
|
||||
// // UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(m_hiddenPathText.gameObject, true, true, true, true);
|
||||
|
||||
// // // Path input
|
||||
|
||||
// // var pathInputObj = UIFactory.CreateInputField(m_hiddenPathText.gameObject, "PathInputField", "...");
|
||||
// // UIFactory.SetLayoutElement(pathInputObj, minHeight: 25, flexibleHeight: 75, preferredWidth: 400, flexibleWidth: 9999);
|
||||
// // var pathInputRect = pathInputObj.GetComponent<RectTransform>();
|
||||
// // pathInputRect.sizeDelta = new Vector2(pathInputRect.sizeDelta.x, 25);
|
||||
|
||||
// // m_pathInput = pathInputObj.GetComponent<InputField>();
|
||||
// // m_pathInput.text = ActiveInstance.TargetGO.transform.GetTransformPath();
|
||||
// // m_pathInput.readOnly = true;
|
||||
// // m_pathInput.lineType = InputField.LineType.MultiLineNewline;
|
||||
// // m_pathInput.textComponent.color = new Color(0.75f, 0.75f, 0.75f);
|
||||
|
||||
// // var textRect = m_pathInput.textComponent.GetComponent<RectTransform>();
|
||||
// // textRect.offsetMin = new Vector2(3, 3);
|
||||
// // textRect.offsetMax = new Vector2(3, 3);
|
||||
|
||||
// // m_pathInputRect = m_pathInput.GetComponent<RectTransform>();
|
||||
// // m_hiddenPathRect = m_hiddenPathText.GetComponent<RectTransform>();
|
||||
|
||||
// // // name and enabled row
|
||||
|
||||
// // var nameRowObj = UIFactory.CreateHorizontalGroup(scrollContent, "NameGroup", false, false, true, true, 5, default, new Color(0.1f, 0.1f, 0.1f));
|
||||
// // UIFactory.SetLayoutElement(nameRowObj, minHeight: 25, flexibleHeight: 0);
|
||||
// // var nameRect = nameRowObj.GetComponent<RectTransform>();
|
||||
// // nameRect.sizeDelta = new Vector2(nameRect.sizeDelta.x, 25);
|
||||
|
||||
// // var nameLabel = UIFactory.CreateLabel(nameRowObj, "NameLabel", "Name:", TextAnchor.MiddleCenter, Color.grey, true, 14);
|
||||
// // UIFactory.SetLayoutElement(nameLabel.gameObject, minHeight: 25, flexibleHeight: 0, minWidth: 55, flexibleWidth: 0);
|
||||
|
||||
// // var nameInputObj = UIFactory.CreateInputField(nameRowObj, "NameInput", "...");
|
||||
// // var nameInputRect = nameInputObj.GetComponent<RectTransform>();
|
||||
// // nameInputRect.sizeDelta = new Vector2(nameInputRect.sizeDelta.x, 25);
|
||||
// // m_nameInput = nameInputObj.GetComponent<InputField>();
|
||||
// // m_nameInput.text = ActiveInstance.TargetGO.name;
|
||||
|
||||
// // var applyNameBtn = UIFactory.CreateButton(nameRowObj, "ApplyNameButton", "Apply", OnApplyNameClicked);
|
||||
// // UIFactory.SetLayoutElement(applyNameBtn.gameObject, minWidth: 65, minHeight: 25, flexibleHeight: 0);
|
||||
// // var applyNameRect = applyNameBtn.GetComponent<RectTransform>();
|
||||
// // applyNameRect.sizeDelta = new Vector2(applyNameRect.sizeDelta.x, 25);
|
||||
|
||||
// // var activeLabel = UIFactory.CreateLabel(nameRowObj, "ActiveLabel", "Active:", TextAnchor.MiddleCenter, Color.grey, true, 14);
|
||||
// // UIFactory.SetLayoutElement(activeLabel.gameObject, minWidth: 55, minHeight: 25);
|
||||
|
||||
// // var enabledToggleObj = UIFactory.CreateToggle(nameRowObj, "EnabledToggle", out m_enabledToggle, out m_enabledText);
|
||||
// // UIFactory.SetLayoutElement(enabledToggleObj, minHeight: 25, minWidth: 100, flexibleWidth: 0);
|
||||
// // m_enabledText.text = "Enabled";
|
||||
// // m_enabledText.color = Color.green;
|
||||
// // m_enabledToggle.onValueChanged.AddListener(OnEnableToggled);
|
||||
|
||||
// // // layer and scene row
|
||||
|
||||
// // var sceneLayerRow = UIFactory.CreateHorizontalGroup(scrollContent, "SceneLayerRow", false, true, true, true, 5, default, new Color(0.1f, 0.1f, 0.1f));
|
||||
|
||||
// // // layer
|
||||
|
||||
// // var layerLabel = UIFactory.CreateLabel(sceneLayerRow, "LayerLabel", "Layer:", TextAnchor.MiddleCenter, Color.grey, true, 14);
|
||||
// // UIFactory.SetLayoutElement(layerLabel.gameObject, minWidth: 55, flexibleWidth: 0);
|
||||
|
||||
// // var layerDropdownObj = UIFactory.CreateDropdown(sceneLayerRow, out m_layerDropdown, "", 14, OnLayerSelected);
|
||||
// // m_layerDropdown.options.Clear();
|
||||
// // for (int i = 0; i < 32; i++)
|
||||
// // {
|
||||
// // var layer = RuntimeProvider.Instance.LayerToName(i);
|
||||
// // m_layerDropdown.options.Add(new Dropdown.OptionData { text = $"{i}: {layer}" });
|
||||
// // }
|
||||
// // UIFactory.SetLayoutElement(layerDropdownObj, minWidth: 120, flexibleWidth: 2000, minHeight: 25);
|
||||
|
||||
// // // scene
|
||||
|
||||
// // var sceneLabel = UIFactory.CreateLabel(sceneLayerRow, "SceneLabel", "Scene:", TextAnchor.MiddleCenter, Color.grey, true, 14);
|
||||
// // UIFactory.SetLayoutElement(sceneLabel.gameObject, minWidth: 55, flexibleWidth: 0);
|
||||
|
||||
// // m_sceneText = UIFactory.CreateLabel(sceneLayerRow, "SceneText", "", TextAnchor.MiddleLeft);
|
||||
// // UIFactory.SetLayoutElement(m_sceneText.gameObject, minWidth: 120, flexibleWidth: 2000);
|
||||
// //}
|
||||
|
||||
// //private GameObject ConstructMidGroup(GameObject parent)
|
||||
// //{
|
||||
// // var midGroupObj = UIFactory.CreateHorizontalGroup(parent, "MidGroup", true, true, true, true, 5, default, new Color(1, 1, 1, 0));
|
||||
// // UIFactory.SetLayoutElement(midGroupObj, minHeight: 300, flexibleHeight: 3000);
|
||||
// // return midGroupObj;
|
||||
// //}
|
||||
// //#endregion
|
||||
// }
|
||||
//}
|
@ -1,327 +0,0 @@
|
||||
//using System;
|
||||
//using System.Collections.Generic;
|
||||
//using System.Linq;
|
||||
//using System.Text;
|
||||
//using UnityEngine;
|
||||
//using UnityEngine.EventSystems;
|
||||
//using UnityEngine.UI;
|
||||
//using UnityExplorer.Core;
|
||||
//using UnityExplorer.Core.Input;
|
||||
//using UnityExplorer.Core.Runtime;
|
||||
//using UnityExplorer.UI;
|
||||
//using UnityExplorer.UI.Main;
|
||||
//using UnityExplorer.UI.Inspectors;
|
||||
|
||||
//namespace UnityExplorer.UI.Main.Home
|
||||
//{
|
||||
// public class InspectUnderMouse
|
||||
// {
|
||||
// public enum MouseInspectMode
|
||||
// {
|
||||
// World,
|
||||
// UI
|
||||
// }
|
||||
|
||||
// public static bool Inspecting { get; set; }
|
||||
|
||||
// public static MouseInspectMode Mode { get; set; }
|
||||
|
||||
// private static GameObject s_lastHit;
|
||||
// private static Vector3 s_lastMousePos;
|
||||
|
||||
// private static readonly List<Graphic> _wasDisabledGraphics = new List<Graphic>();
|
||||
// private static readonly List<CanvasGroup> _wasDisabledCanvasGroups = new List<CanvasGroup>();
|
||||
// private static readonly List<GameObject> _objectsAddedCastersTo = new List<GameObject>();
|
||||
|
||||
// internal static Camera MainCamera;
|
||||
// internal static GraphicRaycaster[] graphicRaycasters;
|
||||
|
||||
// public static void Init()
|
||||
// {
|
||||
// ConstructUI();
|
||||
// }
|
||||
|
||||
// public static void StartInspect(MouseInspectMode mode)
|
||||
// {
|
||||
// MainCamera = Camera.main;
|
||||
// if (!MainCamera)
|
||||
// return;
|
||||
|
||||
// Mode = mode;
|
||||
// Inspecting = true;
|
||||
// MainMenu.Instance.MainPanel.SetActive(false);
|
||||
|
||||
// s_UIContent.SetActive(true);
|
||||
|
||||
// if (mode == MouseInspectMode.UI)
|
||||
// SetupUIRaycast();
|
||||
// }
|
||||
|
||||
// internal static void ClearHitData()
|
||||
// {
|
||||
// s_lastHit = null;
|
||||
// s_objNameLabel.text = "No hits...";
|
||||
// s_objPathLabel.text = "";
|
||||
// }
|
||||
|
||||
// public static void StopInspect()
|
||||
// {
|
||||
// Inspecting = false;
|
||||
// MainMenu.Instance.MainPanel.SetActive(true);
|
||||
// s_UIContent.SetActive(false);
|
||||
|
||||
// if (Mode == MouseInspectMode.UI)
|
||||
// StopUIInspect();
|
||||
|
||||
// ClearHitData();
|
||||
// }
|
||||
|
||||
// public static void UpdateInspect()
|
||||
// {
|
||||
// if (InputManager.GetKeyDown(KeyCode.Escape))
|
||||
// {
|
||||
// StopInspect();
|
||||
// return;
|
||||
// }
|
||||
|
||||
// var mousePos = InputManager.MousePosition;
|
||||
|
||||
// if (mousePos != s_lastMousePos)
|
||||
// UpdatePosition(mousePos);
|
||||
|
||||
// // actual inspect raycast
|
||||
|
||||
// switch (Mode)
|
||||
// {
|
||||
// case MouseInspectMode.UI:
|
||||
// RaycastUI(mousePos); break;
|
||||
// case MouseInspectMode.World:
|
||||
// RaycastWorld(mousePos); break;
|
||||
// }
|
||||
// }
|
||||
|
||||
// internal static void UpdatePosition(Vector2 mousePos)
|
||||
// {
|
||||
// s_lastMousePos = mousePos;
|
||||
|
||||
// var inversePos = UIManager.CanvasRoot.transform.InverseTransformPoint(mousePos);
|
||||
|
||||
// s_mousePosLabel.text = $"<color=grey>Mouse Position:</color> {mousePos.ToString()}";
|
||||
|
||||
// float yFix = mousePos.y < 120 ? 80 : -80;
|
||||
// s_UIContent.transform.localPosition = new Vector3(inversePos.x, inversePos.y + yFix, 0);
|
||||
// }
|
||||
|
||||
// internal static void OnHitGameObject(GameObject obj)
|
||||
// {
|
||||
// if (obj != s_lastHit)
|
||||
// {
|
||||
// s_lastHit = obj;
|
||||
// s_objNameLabel.text = $"<b>Click to Inspect:</b> <color=cyan>{obj.name}</color>";
|
||||
// s_objPathLabel.text = $"Path: {obj.transform.GetTransformPath(true)}";
|
||||
// }
|
||||
|
||||
// if (InputManager.GetMouseButtonDown(0))
|
||||
// {
|
||||
// StopInspect();
|
||||
// InspectorManager.Instance.Inspect(obj);
|
||||
// }
|
||||
// }
|
||||
|
||||
// // Collider raycasting
|
||||
|
||||
// internal static void RaycastWorld(Vector2 mousePos)
|
||||
// {
|
||||
// var ray = MainCamera.ScreenPointToRay(mousePos);
|
||||
// Physics.Raycast(ray, out RaycastHit hit, 1000f);
|
||||
|
||||
// if (hit.transform)
|
||||
// {
|
||||
// var obj = hit.transform.gameObject;
|
||||
// OnHitGameObject(obj);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// if (s_lastHit)
|
||||
// ClearHitData();
|
||||
// }
|
||||
// }
|
||||
|
||||
// // UI Graphic raycasting
|
||||
|
||||
// private static void SetupUIRaycast()
|
||||
// {
|
||||
// foreach (var obj in RuntimeProvider.Instance.FindObjectsOfTypeAll(typeof(Canvas)))
|
||||
// {
|
||||
// var canvas = obj.Cast(typeof(Canvas)) as Canvas;
|
||||
// if (!canvas || !canvas.enabled || !canvas.gameObject.activeInHierarchy)
|
||||
// continue;
|
||||
// if (!canvas.GetComponent<GraphicRaycaster>())
|
||||
// {
|
||||
// canvas.gameObject.AddComponent<GraphicRaycaster>();
|
||||
// //ExplorerCore.Log("Added raycaster to " + canvas.name);
|
||||
// _objectsAddedCastersTo.Add(canvas.gameObject);
|
||||
// }
|
||||
// }
|
||||
|
||||
// // recache Graphic Raycasters each time we start
|
||||
// var casters = RuntimeProvider.Instance.FindObjectsOfTypeAll(typeof(GraphicRaycaster));
|
||||
// graphicRaycasters = new GraphicRaycaster[casters.Length];
|
||||
// for (int i = 0; i < casters.Length; i++)
|
||||
// {
|
||||
// graphicRaycasters[i] = casters[i].Cast(typeof(GraphicRaycaster)) as GraphicRaycaster;
|
||||
// }
|
||||
|
||||
// // enable raycastTarget on Graphics
|
||||
// foreach (var obj in RuntimeProvider.Instance.FindObjectsOfTypeAll(typeof(Graphic)))
|
||||
// {
|
||||
// var graphic = obj.Cast(typeof(Graphic)) as Graphic;
|
||||
// if (!graphic || !graphic.enabled || graphic.raycastTarget || !graphic.gameObject.activeInHierarchy)
|
||||
// continue;
|
||||
// graphic.raycastTarget = true;
|
||||
// //ExplorerCore.Log("Enabled raycastTarget on " + graphic.name);
|
||||
// _wasDisabledGraphics.Add(graphic);
|
||||
// }
|
||||
|
||||
// // enable blocksRaycasts on CanvasGroups
|
||||
// foreach (var obj in RuntimeProvider.Instance.FindObjectsOfTypeAll(typeof(CanvasGroup)))
|
||||
// {
|
||||
// var canvas = obj.Cast(typeof(CanvasGroup)) as CanvasGroup;
|
||||
// if (!canvas || !canvas.gameObject.activeInHierarchy || canvas.blocksRaycasts)
|
||||
// continue;
|
||||
// canvas.blocksRaycasts = true;
|
||||
// //ExplorerCore.Log("Enabled raycasts on " + canvas.name);
|
||||
// _wasDisabledCanvasGroups.Add(canvas);
|
||||
// }
|
||||
// }
|
||||
|
||||
// internal static void RaycastUI(Vector2 mousePos)
|
||||
// {
|
||||
// var ped = new PointerEventData(null)
|
||||
// {
|
||||
// position = mousePos
|
||||
// };
|
||||
|
||||
// //ExplorerCore.Log("~~~~~~~~~ begin raycast ~~~~~~~~");
|
||||
// GameObject hitObject = null;
|
||||
// int highestLayer = int.MinValue;
|
||||
// int highestOrder = int.MinValue;
|
||||
// int highestDepth = int.MinValue;
|
||||
// foreach (var gr in graphicRaycasters)
|
||||
// {
|
||||
// var list = new List<RaycastResult>();
|
||||
// RuntimeProvider.Instance.GraphicRaycast(gr, ped, list);
|
||||
|
||||
// //gr.Raycast(ped, list);
|
||||
|
||||
// if (list.Count > 0)
|
||||
// {
|
||||
// foreach (var hit in list)
|
||||
// {
|
||||
// // Manual trying to determine which object is "on top".
|
||||
// // Not perfect, but not terrible.
|
||||
|
||||
// if (!hit.gameObject)
|
||||
// continue;
|
||||
|
||||
// if (hit.gameObject.GetComponent<CanvasGroup>() is CanvasGroup group && group.alpha == 0)
|
||||
// continue;
|
||||
|
||||
// if (hit.gameObject.GetComponent<Graphic>() is Graphic graphic && graphic.color.a == 0f)
|
||||
// continue;
|
||||
|
||||
// if (hit.sortingLayer < highestLayer)
|
||||
// continue;
|
||||
|
||||
// if (hit.sortingLayer > highestLayer)
|
||||
// {
|
||||
// highestLayer = hit.sortingLayer;
|
||||
// highestDepth = int.MinValue;
|
||||
// }
|
||||
|
||||
// if (hit.depth < highestDepth)
|
||||
// continue;
|
||||
|
||||
// if (hit.depth > highestDepth)
|
||||
// {
|
||||
// highestDepth = hit.depth;
|
||||
// highestOrder = int.MinValue;
|
||||
// }
|
||||
|
||||
// if (hit.sortingOrder <= highestOrder)
|
||||
// continue;
|
||||
|
||||
// highestOrder = hit.sortingOrder;
|
||||
// hitObject = hit.gameObject;
|
||||
// }
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// if (s_lastHit)
|
||||
// ClearHitData();
|
||||
// }
|
||||
// }
|
||||
|
||||
// if (hitObject)
|
||||
// OnHitGameObject(hitObject);
|
||||
|
||||
// //ExplorerCore.Log("~~~~~~~~~ end raycast ~~~~~~~~");
|
||||
// }
|
||||
|
||||
// private static void StopUIInspect()
|
||||
// {
|
||||
// foreach (var obj in _objectsAddedCastersTo)
|
||||
// {
|
||||
// if (obj.GetComponent<GraphicRaycaster>() is GraphicRaycaster raycaster)
|
||||
// GameObject.Destroy(raycaster);
|
||||
// }
|
||||
|
||||
// foreach (var graphic in _wasDisabledGraphics)
|
||||
// graphic.raycastTarget = false;
|
||||
|
||||
// foreach (var canvas in _wasDisabledCanvasGroups)
|
||||
// canvas.blocksRaycasts = false;
|
||||
|
||||
// _objectsAddedCastersTo.Clear();
|
||||
// _wasDisabledCanvasGroups.Clear();
|
||||
// _wasDisabledGraphics.Clear();
|
||||
// }
|
||||
|
||||
// internal static Text s_objNameLabel;
|
||||
// internal static Text s_objPathLabel;
|
||||
// internal static Text s_mousePosLabel;
|
||||
// internal static GameObject s_UIContent;
|
||||
|
||||
// internal static void ConstructUI()
|
||||
// {
|
||||
// s_UIContent = UIFactory.CreatePanel("InspectUnderMouse_UI", out GameObject content);
|
||||
|
||||
// var baseRect = s_UIContent.GetComponent<RectTransform>();
|
||||
// var half = new Vector2(0.5f, 0.5f);
|
||||
// baseRect.anchorMin = half;
|
||||
// baseRect.anchorMax = half;
|
||||
// baseRect.pivot = half;
|
||||
// baseRect.sizeDelta = new Vector2(700, 150);
|
||||
|
||||
// var group = content.GetComponent<VerticalLayoutGroup>();
|
||||
// group.childForceExpandHeight = true;
|
||||
|
||||
// // Title text
|
||||
|
||||
// UIFactory.CreateLabel(content, "InspectLabel", "<b>Mouse Inspector</b> (press <b>ESC</b> to cancel)", TextAnchor.MiddleCenter);
|
||||
|
||||
// s_mousePosLabel = UIFactory.CreateLabel(content, "MousePosLabel", "Mouse Position:", TextAnchor.MiddleCenter);
|
||||
|
||||
// s_objNameLabel = UIFactory.CreateLabel(content, "HitLabelObj", "No hits...", TextAnchor.MiddleLeft);
|
||||
// s_objNameLabel.horizontalOverflow = HorizontalWrapMode.Overflow;
|
||||
|
||||
// s_objPathLabel = UIFactory.CreateLabel(content, "PathLabel", "", TextAnchor.MiddleLeft);
|
||||
// s_objPathLabel.fontStyle = FontStyle.Italic;
|
||||
// s_objPathLabel.horizontalOverflow = HorizontalWrapMode.Wrap;
|
||||
|
||||
// UIFactory.SetLayoutElement(s_objPathLabel.gameObject, minHeight: 75);
|
||||
|
||||
// s_UIContent.SetActive(false);
|
||||
// }
|
||||
// }
|
||||
//}
|
@ -1,122 +1,64 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.UI.ObjectPool;
|
||||
using UnityExplorer.UI.Panels;
|
||||
|
||||
namespace UnityExplorer.UI.Inspectors
|
||||
{
|
||||
public abstract class InspectorBase
|
||||
public abstract class InspectorBase : IPooledObject
|
||||
{
|
||||
public object Target;
|
||||
public bool IsActive { get; private set; }
|
||||
public InspectorTab Tab { get; internal set; }
|
||||
public bool IsActive { get; internal set; }
|
||||
|
||||
public abstract string TabLabel { get; }
|
||||
public abstract GameObject UIRoot { get; }
|
||||
|
||||
internal bool m_pendingDestroy;
|
||||
private static readonly Color _enabledTabColor = new Color(0.2f, 0.4f, 0.2f);
|
||||
private static readonly Color _disabledTabColor = new Color(0.25f, 0.25f, 0.25f);
|
||||
|
||||
public InspectorBase(object target)
|
||||
public float DefaultHeight => -1f;
|
||||
public abstract GameObject CreateContent(GameObject content);
|
||||
|
||||
public abstract void Update();
|
||||
|
||||
public virtual void OnBorrowedFromPool(object target)
|
||||
{
|
||||
Target = target;
|
||||
Tab = Pool<InspectorTab>.Borrow();
|
||||
Tab.UIRoot.transform.SetParent(InspectorPanel.Instance.NavbarHolder.transform, false);
|
||||
|
||||
if (Target.IsNullOrDestroyed(false))
|
||||
{
|
||||
Destroy();
|
||||
return;
|
||||
}
|
||||
|
||||
AddInspectorTab(this);
|
||||
Tab.TabButton.OnClick += OnTabButtonClicked;
|
||||
Tab.CloseButton.OnClick += OnCloseClicked;
|
||||
}
|
||||
|
||||
public virtual void SetActive()
|
||||
public virtual void OnReturnToPool()
|
||||
{
|
||||
this.IsActive = true;
|
||||
Content?.SetActive(true);
|
||||
Pool<InspectorTab>.Return(Tab);
|
||||
|
||||
Tab.TabButton.OnClick -= OnTabButtonClicked;
|
||||
Tab.CloseButton.OnClick -= OnCloseClicked;
|
||||
}
|
||||
|
||||
public virtual void SetInactive()
|
||||
public virtual void OnSetActive()
|
||||
{
|
||||
this.IsActive = false;
|
||||
Content?.SetActive(false);
|
||||
RuntimeProvider.Instance.SetColorBlock(Tab.TabButton.Button, _enabledTabColor, _enabledTabColor * 1.2f);
|
||||
UIRoot.SetActive(true);
|
||||
IsActive = true;
|
||||
}
|
||||
|
||||
public virtual void Update()
|
||||
public virtual void OnSetInactive()
|
||||
{
|
||||
if (Target.IsNullOrDestroyed(false))
|
||||
{
|
||||
Destroy();
|
||||
return;
|
||||
}
|
||||
|
||||
m_tabText.text = TabLabel;
|
||||
RuntimeProvider.Instance.SetColorBlock(Tab.TabButton.Button, _disabledTabColor, _disabledTabColor * 1.2f);
|
||||
UIRoot.SetActive(false);
|
||||
IsActive = false;
|
||||
}
|
||||
|
||||
public virtual void Destroy()
|
||||
private void OnTabButtonClicked()
|
||||
{
|
||||
m_pendingDestroy = true;
|
||||
|
||||
GameObject tabGroup = m_tabButton?.transform.parent.gameObject;
|
||||
|
||||
if (tabGroup)
|
||||
GameObject.Destroy(tabGroup);
|
||||
|
||||
int thisIndex = -1;
|
||||
if (InspectorManager.ActiveInspectors.Contains(this))
|
||||
{
|
||||
thisIndex = InspectorManager.ActiveInspectors.IndexOf(this);
|
||||
InspectorManager.ActiveInspectors.Remove(this);
|
||||
}
|
||||
|
||||
if (ReferenceEquals(InspectorManager.m_activeInspector, this))
|
||||
{
|
||||
InspectorManager.UnsetInspectorTab();
|
||||
|
||||
if (InspectorManager.ActiveInspectors.Count > 0)
|
||||
{
|
||||
var prevTab = InspectorManager.ActiveInspectors[thisIndex > 0 ? thisIndex - 1 : 0];
|
||||
InspectorManager.SetInspectorTab(prevTab);
|
||||
}
|
||||
}
|
||||
InspectorManager.SetInspectorActive(this);
|
||||
}
|
||||
|
||||
#region UI
|
||||
|
||||
public abstract GameObject Content { get; set; }
|
||||
public Button m_tabButton;
|
||||
public Text m_tabText;
|
||||
|
||||
public void AddInspectorTab(InspectorBase parent)
|
||||
{
|
||||
var tabContent = InspectorPanel.Instance.NavbarHolder;
|
||||
|
||||
var tabGroupObj = UIFactory.CreateHorizontalGroup(tabContent, "TabObject", true, true, true, true);
|
||||
UIFactory.SetLayoutElement(tabGroupObj, minWidth: 185, flexibleWidth: 0);
|
||||
tabGroupObj.AddComponent<Mask>();
|
||||
|
||||
m_tabButton = UIFactory.CreateButton(tabGroupObj,
|
||||
"TabButton",
|
||||
"",
|
||||
() => { InspectorManager.SetInspectorTab(parent); });
|
||||
|
||||
UIFactory.SetLayoutElement(m_tabButton.gameObject, minWidth: 165, flexibleWidth: 0);
|
||||
|
||||
m_tabText = m_tabButton.GetComponentInChildren<Text>();
|
||||
m_tabText.horizontalOverflow = HorizontalWrapMode.Overflow;
|
||||
m_tabText.alignment = TextAnchor.MiddleLeft;
|
||||
|
||||
var closeBtn = UIFactory.CreateButton(tabGroupObj,
|
||||
"CloseButton",
|
||||
"X",
|
||||
() => { InspectorManager.DestroyInspector(parent); },
|
||||
new Color(0.2f, 0.2f, 0.2f, 1));
|
||||
|
||||
UIFactory.SetLayoutElement(closeBtn.gameObject, minWidth: 20, flexibleWidth: 0);
|
||||
|
||||
var closeBtnText = closeBtn.GetComponentInChildren<Text>();
|
||||
closeBtnText.color = new Color(1, 0, 0, 1);
|
||||
}
|
||||
|
||||
public virtual void OnPanelResized() { }
|
||||
|
||||
#endregion
|
||||
protected abstract void OnCloseClicked();
|
||||
}
|
||||
}
|
||||
|
@ -1,151 +1,79 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityExplorer.UI;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.Core.Runtime;
|
||||
using UnityExplorer.UI.CacheObject;
|
||||
using UnityExplorer.UI.Inspectors.Reflection;
|
||||
using UnityExplorer.UI.ObjectPool;
|
||||
using UnityExplorer.UI.Panels;
|
||||
|
||||
namespace UnityExplorer.UI.Inspectors
|
||||
{
|
||||
public static class InspectorManager
|
||||
{
|
||||
public static InspectorBase m_activeInspector;
|
||||
public static readonly List<InspectorBase> ActiveInspectors = new List<InspectorBase>();
|
||||
public static readonly List<InspectorBase> Inspectors = new List<InspectorBase>();
|
||||
|
||||
public static void Update()
|
||||
public static InspectorBase ActiveInspector { get; private set; }
|
||||
|
||||
public static void Inspect(object obj)
|
||||
{
|
||||
try
|
||||
{
|
||||
for (int i = 0; i < ActiveInspectors.Count; i++)
|
||||
ActiveInspectors[i].Update();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ExplorerCore.LogWarning(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public static void DestroyInspector(InspectorBase inspector)
|
||||
{
|
||||
if (inspector is ReflectionInspector ri)
|
||||
ri.Destroy();
|
||||
obj = obj.TryCast();
|
||||
if (obj is GameObject)
|
||||
CreateInspector<GameObjectInspector>(obj);
|
||||
else
|
||||
inspector.Destroy();
|
||||
}
|
||||
|
||||
public static void Inspect(object obj, CacheObjectBase parentMember = null)
|
||||
{
|
||||
var type = ReflectionProvider.Instance.GetActualType(obj);
|
||||
|
||||
// only need to set parent member for structs
|
||||
if (!type.IsValueType)
|
||||
parentMember = null;
|
||||
|
||||
obj = ReflectionProvider.Instance.Cast(obj, type);
|
||||
|
||||
if (obj.IsNullOrDestroyed(false))
|
||||
return;
|
||||
|
||||
// check if currently inspecting this object
|
||||
foreach (InspectorBase tab in ActiveInspectors)
|
||||
{
|
||||
if (obj.ReferenceEqual(tab.Target))
|
||||
{
|
||||
SetInspectorTab(tab);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
InspectorBase inspector;
|
||||
if (obj is GameObject go)
|
||||
{
|
||||
ExplorerCore.Log("TODO");
|
||||
return;
|
||||
// inspector = new GameObjectInspector(go);
|
||||
}
|
||||
else
|
||||
inspector = new InstanceInspector(obj);
|
||||
|
||||
if (inspector is ReflectionInspector ri)
|
||||
ri.ParentMember = parentMember;
|
||||
|
||||
ActiveInspectors.Add(inspector);
|
||||
SetInspectorTab(inspector);
|
||||
CreateInspector<InstanceInspector>(obj);
|
||||
}
|
||||
|
||||
public static void Inspect(Type type)
|
||||
{
|
||||
if (type == null)
|
||||
{
|
||||
ExplorerCore.LogWarning("The provided type was null!");
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var tab in ActiveInspectors.Where(x => x is StaticInspector))
|
||||
{
|
||||
if (ReferenceEquals(tab.Target as Type, type))
|
||||
{
|
||||
SetInspectorTab(tab);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
var inspector = new StaticInspector(type);
|
||||
|
||||
ActiveInspectors.Add(inspector);
|
||||
SetInspectorTab(inspector);
|
||||
CreateInspector<StaticInspector>(type);
|
||||
}
|
||||
|
||||
public static void SetInspectorTab(InspectorBase inspector)
|
||||
public static void SetInspectorActive(InspectorBase inspector)
|
||||
{
|
||||
UnsetActiveInspector();
|
||||
|
||||
ActiveInspector = inspector;
|
||||
inspector.OnSetActive();
|
||||
}
|
||||
|
||||
public static void UnsetActiveInspector()
|
||||
{
|
||||
if (ActiveInspector != null)
|
||||
ActiveInspector.OnSetInactive();
|
||||
}
|
||||
|
||||
private static void CreateInspector<T>(object target) where T : InspectorBase
|
||||
{
|
||||
var inspector = Pool<T>.Borrow();
|
||||
Inspectors.Add(inspector);
|
||||
|
||||
inspector.UIRoot.transform.SetParent(InspectorPanel.Instance.ContentHolder.transform, false);
|
||||
|
||||
inspector.OnBorrowedFromPool(target);
|
||||
SetInspectorActive(inspector);
|
||||
|
||||
UIManager.SetPanelActive(UIManager.Panels.Inspector, true);
|
||||
|
||||
if (m_activeInspector == inspector)
|
||||
return;
|
||||
|
||||
UnsetInspectorTab();
|
||||
|
||||
m_activeInspector = inspector;
|
||||
inspector.SetActive();
|
||||
|
||||
OnSetInspectorTab(inspector);
|
||||
}
|
||||
|
||||
public static void UnsetInspectorTab()
|
||||
internal static void ReleaseInspector<T>(T inspector) where T : InspectorBase
|
||||
{
|
||||
if (m_activeInspector == null)
|
||||
return;
|
||||
inspector.OnReturnToPool();
|
||||
Pool<T>.Return(inspector);
|
||||
|
||||
m_activeInspector.SetInactive();
|
||||
|
||||
OnUnsetInspectorTab();
|
||||
|
||||
m_activeInspector = null;
|
||||
Inspectors.Remove(inspector);
|
||||
}
|
||||
|
||||
public static void OnSetInspectorTab(InspectorBase inspector)
|
||||
internal static void Update()
|
||||
{
|
||||
Color activeColor = new Color(0, 0.25f, 0, 1);
|
||||
RuntimeProvider.Instance.SetColorBlock(inspector.m_tabButton, activeColor, activeColor);
|
||||
}
|
||||
|
||||
public static void OnUnsetInspectorTab()
|
||||
{
|
||||
RuntimeProvider.Instance.SetColorBlock(m_activeInspector.m_tabButton,
|
||||
new Color(0.2f, 0.2f, 0.2f, 1), new Color(0.1f, 0.3f, 0.1f, 1));
|
||||
foreach (var inspector in Inspectors)
|
||||
{
|
||||
inspector.Update();
|
||||
}
|
||||
}
|
||||
|
||||
internal static void OnPanelResized()
|
||||
{
|
||||
foreach (var instance in ActiveInspectors)
|
||||
{
|
||||
instance.OnPanelResized();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
46
src/UI/Inspectors/InspectorTab.cs
Normal file
46
src/UI/Inspectors/InspectorTab.cs
Normal file
@ -0,0 +1,46 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.UI.ObjectPool;
|
||||
using UnityExplorer.UI.Widgets;
|
||||
|
||||
namespace UnityExplorer.UI.Inspectors
|
||||
{
|
||||
public class InspectorTab : IPooledObject
|
||||
{
|
||||
public GameObject UIRoot => uiRoot;
|
||||
private GameObject uiRoot;
|
||||
|
||||
public float DefaultHeight => 25f;
|
||||
|
||||
public ButtonRef TabButton;
|
||||
public Text TabText;
|
||||
|
||||
public ButtonRef CloseButton;
|
||||
|
||||
public GameObject CreateContent(GameObject parent)
|
||||
{
|
||||
uiRoot = UIFactory.CreateHorizontalGroup(parent, "TabObject", true, true, true, true, 0, new Vector4(0, 0, 3, 0));
|
||||
UIFactory.SetLayoutElement(uiRoot, minWidth: 185, flexibleWidth: 0);
|
||||
uiRoot.AddComponent<Mask>();
|
||||
|
||||
TabButton = UIFactory.CreateButton(uiRoot, "TabButton", "");
|
||||
|
||||
UIFactory.SetLayoutElement(TabButton.Button.gameObject, minWidth: 165, flexibleWidth: 0);
|
||||
|
||||
TabText = TabButton.Button.GetComponentInChildren<Text>();
|
||||
TabText.horizontalOverflow = HorizontalWrapMode.Overflow;
|
||||
TabText.alignment = TextAnchor.MiddleLeft;
|
||||
|
||||
CloseButton = UIFactory.CreateButton(uiRoot, "CloseButton", "X", new Color(0.2f, 0.2f, 0.2f, 1));
|
||||
UIFactory.SetLayoutElement(CloseButton.Button.gameObject, minWidth: 20, flexibleWidth: 0);
|
||||
var closeBtnText = CloseButton.Button.GetComponentInChildren<Text>();
|
||||
closeBtnText.color = Color.red;
|
||||
|
||||
return uiRoot;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,61 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityExplorer.UI.Widgets;
|
||||
|
||||
namespace UnityExplorer.UI.Inspectors.Reflection
|
||||
{
|
||||
public class CacheMemberList : IPoolDataSource
|
||||
{
|
||||
public ScrollPool ScrollPool { get; }
|
||||
public ReflectionInspector Inspector { get; }
|
||||
|
||||
public CacheMemberList(ScrollPool scrollPool, ReflectionInspector inspector)
|
||||
{
|
||||
this.ScrollPool = scrollPool;
|
||||
this.Inspector = inspector;
|
||||
}
|
||||
|
||||
public int ItemCount => Inspector.filteredMembers.Count;
|
||||
|
||||
public int GetRealIndexOfTempIndex(int index)
|
||||
{
|
||||
if (index < 0 || index >= Inspector.filteredToRealIndices.Count)
|
||||
return -1;
|
||||
return Inspector.filteredToRealIndices[index];
|
||||
}
|
||||
|
||||
public ICell CreateCell(RectTransform cellTransform) => new CellViewHolder(cellTransform.gameObject);
|
||||
|
||||
public void SetCell(ICell icell, int index)
|
||||
{
|
||||
var cell = icell as CellViewHolder;
|
||||
|
||||
if (index < 0 || index >= ItemCount)
|
||||
{
|
||||
var existing = cell.DisableContent();
|
||||
if (existing)
|
||||
existing.transform.SetParent(Inspector.InactiveHolder.transform, false);
|
||||
return;
|
||||
}
|
||||
|
||||
index = GetRealIndexOfTempIndex(index);
|
||||
|
||||
var cache = Inspector.allMembers[index];
|
||||
cache.Enable();
|
||||
|
||||
var prev = cell.SetContent(cache.UIRoot);
|
||||
if (prev)
|
||||
prev.transform.SetParent(Inspector.InactiveHolder.transform, false);
|
||||
}
|
||||
|
||||
public void DisableCell(ICell cell, int index)
|
||||
{
|
||||
var content = (cell as CellViewHolder).DisableContent();
|
||||
if (content)
|
||||
content.transform.SetParent(Inspector.InactiveHolder.transform, false);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,254 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.Core;
|
||||
using UnityExplorer.Core.Config;
|
||||
using UnityExplorer.Core.Runtime;
|
||||
|
||||
namespace UnityExplorer.UI.Inspectors.Reflection
|
||||
{
|
||||
public enum MemberScopes
|
||||
{
|
||||
All,
|
||||
Instance,
|
||||
Static
|
||||
}
|
||||
|
||||
public class InstanceInspector : ReflectionInspector
|
||||
{
|
||||
public override string TabLabel => $" <color=cyan>[R]</color> {base.TabLabel}";
|
||||
|
||||
internal MemberScopes m_scopeFilter;
|
||||
internal Button m_lastActiveScopeButton;
|
||||
|
||||
public InstanceInspector(object target) : base(target) { }
|
||||
|
||||
internal void OnScopeFilterClicked(MemberScopes type, Button button)
|
||||
{
|
||||
if (m_lastActiveScopeButton)
|
||||
RuntimeProvider.Instance.SetColorBlock(m_lastActiveScopeButton, new Color(0.2f, 0.2f, 0.2f));
|
||||
|
||||
m_scopeFilter = type;
|
||||
m_lastActiveScopeButton = button;
|
||||
|
||||
RuntimeProvider.Instance.SetColorBlock(m_lastActiveScopeButton, new Color(0.2f, 0.6f, 0.2f));
|
||||
|
||||
FilterMembers(null, true);
|
||||
|
||||
ScrollPool.RecreateHeightCache();
|
||||
ScrollPool.RefreshAndJumpToTop();
|
||||
//RefreshDisplay();
|
||||
//m_sliderScroller.m_slider.value = 1f;
|
||||
}
|
||||
|
||||
public void ConstructInstanceScopeFilters(GameObject parent)
|
||||
{
|
||||
var memberFilterRowObj = UIFactory.CreateHorizontalGroup(parent, "InstanceFilterRow", false, false, true, true, 5, default,
|
||||
new Color(1, 1, 1, 0));
|
||||
UIFactory.SetLayoutElement(memberFilterRowObj, minHeight: 25, flexibleHeight: 0, flexibleWidth: 5000);
|
||||
|
||||
var memLabel = UIFactory.CreateLabel(memberFilterRowObj, "MemberLabel", "Filter scope:", TextAnchor.MiddleLeft);
|
||||
UIFactory.SetLayoutElement(memLabel.gameObject, minWidth: 100, minHeight: 25, flexibleWidth: 0);
|
||||
|
||||
AddFilterButton(memberFilterRowObj, MemberScopes.All, true);
|
||||
AddFilterButton(memberFilterRowObj, MemberScopes.Instance);
|
||||
AddFilterButton(memberFilterRowObj, MemberScopes.Static);
|
||||
}
|
||||
|
||||
private void AddFilterButton(GameObject parent, MemberScopes type, bool setEnabled = false)
|
||||
{
|
||||
var btn = UIFactory.CreateButton(parent,
|
||||
"ScopeFilterButton_" + type,
|
||||
type.ToString(),
|
||||
null,
|
||||
new Color(0.2f, 0.2f, 0.2f));
|
||||
|
||||
UIFactory.SetLayoutElement(btn.gameObject, minHeight: 25, minWidth: 70);
|
||||
|
||||
btn.onClick.AddListener(() => { OnScopeFilterClicked(type, btn); });
|
||||
|
||||
RuntimeProvider.Instance.SetColorBlock(btn, highlighted: new Color(0.3f, 0.7f, 0.3f));
|
||||
|
||||
if (setEnabled)
|
||||
{
|
||||
RuntimeProvider.Instance.SetColorBlock(btn, new Color(0.2f, 0.6f, 0.2f));
|
||||
m_scopeFilter = type;
|
||||
m_lastActiveScopeButton = btn;
|
||||
}
|
||||
}
|
||||
|
||||
public void ConstructUnityInstanceHelpers()
|
||||
{
|
||||
if (!typeof(UnityEngine.Object).IsAssignableFrom(m_targetType))
|
||||
return;
|
||||
|
||||
var rowObj = UIFactory.CreateHorizontalGroup(Content, "InstanceHelperRow", true, true, true, true, 5, new Vector4(2, 2, 2, 2),
|
||||
new Color(0.1f, 0.1f, 0.1f));
|
||||
UIFactory.SetLayoutElement(rowObj, minHeight: 25, flexibleWidth: 5000);
|
||||
|
||||
if (typeof(Component).IsAssignableFrom(m_targetType))
|
||||
ConstructCompHelper(rowObj);
|
||||
|
||||
ConstructUnityObjHelper(rowObj);
|
||||
|
||||
if (m_targetType == typeof(Texture2D))
|
||||
ConstructTextureHelper();
|
||||
}
|
||||
|
||||
internal void ConstructCompHelper(GameObject rowObj)
|
||||
{
|
||||
//var gameObjectLabel = UIFactory.CreateLabel(rowObj, "GameObjectLabel", "GameObject:", TextAnchor.MiddleLeft);
|
||||
//UIFactory.SetLayoutElement(gameObjectLabel.gameObject, minWidth: 90, minHeight: 25, flexibleWidth: 0);
|
||||
|
||||
var comp = Target.TryCast(typeof(Component)) as Component;
|
||||
|
||||
var btn = UIFactory.CreateButton(rowObj,
|
||||
"GameObjectButton",
|
||||
"View GameObject",
|
||||
() => { InspectorManager.Inspect(comp.gameObject); },
|
||||
new Color(0.2f, 0.5f, 0.2f));
|
||||
UIFactory.SetLayoutElement(btn.gameObject, minHeight: 25, minWidth: 120, flexibleWidth: 0);
|
||||
}
|
||||
|
||||
internal void ConstructUnityObjHelper(GameObject rowObj)
|
||||
{
|
||||
var label = UIFactory.CreateLabel(rowObj, "NameLabel", "Name:", TextAnchor.MiddleLeft);
|
||||
UIFactory.SetLayoutElement(label.gameObject, minWidth: 60, minHeight: 25, flexibleWidth: 0);
|
||||
|
||||
var uObj = Target.TryCast(typeof(UnityEngine.Object)) as UnityEngine.Object;
|
||||
|
||||
var inputObj = UIFactory.CreateInputField(rowObj, "NameInput", "...", out InputField inputField, 14, 3, 1);
|
||||
UIFactory.SetLayoutElement(inputObj, minHeight: 25, flexibleWidth: 2000);
|
||||
inputField.readOnly = true;
|
||||
inputField.text = uObj.name;
|
||||
}
|
||||
|
||||
internal bool showingTextureHelper;
|
||||
internal bool constructedTextureViewer;
|
||||
|
||||
internal GameObject m_textureViewerObj;
|
||||
|
||||
internal void ConstructTextureHelper()
|
||||
{
|
||||
var rowObj = UIFactory.CreateHorizontalGroup(Content, "TextureHelper", false, false, true, true, 5, new Vector4(3, 3, 3, 3),
|
||||
new Color(0.1f, 0.1f, 0.1f));
|
||||
UIFactory.SetLayoutElement(rowObj, minHeight: 25, flexibleHeight: 0);
|
||||
|
||||
var showBtn = UIFactory.CreateButton(rowObj, "ShowButton", "Show", null, new Color(0.2f, 0.3f, 0.2f));
|
||||
UIFactory.SetLayoutElement(showBtn.gameObject, minWidth: 50, flexibleWidth: 0, minHeight: 20);
|
||||
|
||||
UIFactory.CreateLabel(rowObj, "TextureViewerLabel", "Texture Viewer", TextAnchor.MiddleLeft);
|
||||
|
||||
m_textureViewerObj = UIFactory.CreateScrollView(Content, "TextureViewerContent", out GameObject scrollContent, out _,
|
||||
new Color(0.1f, 0.1f, 0.1f));
|
||||
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(scrollContent, false, false, true, true);
|
||||
UIFactory.SetLayoutElement(m_textureViewerObj, minHeight: 100, flexibleHeight: 9999, flexibleWidth: 9999);
|
||||
|
||||
m_textureViewerObj.SetActive(false);
|
||||
|
||||
var showText = showBtn.GetComponentInChildren<Text>();
|
||||
showBtn.onClick.AddListener(() =>
|
||||
{
|
||||
showingTextureHelper = !showingTextureHelper;
|
||||
|
||||
if (showingTextureHelper)
|
||||
{
|
||||
if (!constructedTextureViewer)
|
||||
ConstructTextureViewerArea(scrollContent);
|
||||
|
||||
showText.text = "Hide";
|
||||
ToggleTextureViewer(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
showText.text = "Show";
|
||||
ToggleTextureViewer(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
internal void ConstructTextureViewerArea(GameObject parent)
|
||||
{
|
||||
constructedTextureViewer = true;
|
||||
|
||||
var tex = Target.TryCast(typeof(Texture2D)) as Texture2D;
|
||||
|
||||
if (!tex)
|
||||
{
|
||||
ExplorerCore.LogWarning("Could not cast the target instance to Texture2D! Maybe its null or destroyed?");
|
||||
return;
|
||||
}
|
||||
|
||||
// Save helper
|
||||
|
||||
var saveRowObj = UIFactory.CreateHorizontalGroup(parent, "SaveRow", true, true, true, true, 2, new Vector4(2, 2, 2, 2),
|
||||
new Color(0.1f, 0.1f, 0.1f));
|
||||
|
||||
var saveBtn = UIFactory.CreateButton(saveRowObj, "SaveButton", "Save .PNG", null, new Color(0.2f, 0.2f, 0.2f));
|
||||
UIFactory.SetLayoutElement(saveBtn.gameObject, minHeight: 25, minWidth: 100, flexibleWidth: 0);
|
||||
|
||||
var inputObj = UIFactory.CreateInputField(saveRowObj, "SaveInput", "...", out InputField inputField);
|
||||
UIFactory.SetLayoutElement(inputObj, minHeight: 25, minWidth: 100, flexibleWidth: 9999);
|
||||
|
||||
var name = tex.name;
|
||||
if (string.IsNullOrEmpty(name))
|
||||
name = "untitled";
|
||||
|
||||
inputField.text = Path.Combine(ConfigManager.Default_Output_Path.Value, $"{name}.png");
|
||||
|
||||
saveBtn.onClick.AddListener(() =>
|
||||
{
|
||||
if (tex && !string.IsNullOrEmpty(inputField.text))
|
||||
{
|
||||
var path = inputField.text;
|
||||
if (!path.EndsWith(".png", StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
ExplorerCore.LogWarning("Desired save path must end with '.png'!");
|
||||
return;
|
||||
}
|
||||
|
||||
var dir = Path.GetDirectoryName(path);
|
||||
if (!Directory.Exists(dir))
|
||||
Directory.CreateDirectory(dir);
|
||||
|
||||
if (File.Exists(path))
|
||||
File.Delete(path);
|
||||
|
||||
if (!TextureUtilProvider.IsReadable(tex))
|
||||
tex = TextureUtilProvider.ForceReadTexture(tex);
|
||||
|
||||
byte[] data = TextureUtilProvider.Instance.EncodeToPNG(tex);
|
||||
|
||||
File.WriteAllBytes(path, data);
|
||||
}
|
||||
});
|
||||
|
||||
// Actual texture viewer
|
||||
|
||||
var imageObj = UIFactory.CreateUIObject("TextureViewerImage", parent);
|
||||
var image = imageObj.AddComponent<Image>();
|
||||
var sprite = TextureUtilProvider.Instance.CreateSprite(tex);
|
||||
image.sprite = sprite;
|
||||
|
||||
var fitter = imageObj.AddComponent<ContentSizeFitter>();
|
||||
fitter.verticalFit = ContentSizeFitter.FitMode.PreferredSize;
|
||||
|
||||
var imageLayout = imageObj.AddComponent<LayoutElement>();
|
||||
imageLayout.preferredHeight = sprite.rect.height;
|
||||
imageLayout.preferredWidth = sprite.rect.width;
|
||||
}
|
||||
|
||||
internal void ToggleTextureViewer(bool enabled)
|
||||
{
|
||||
m_textureViewerObj.SetActive(enabled);
|
||||
|
||||
m_filterAreaObj.SetActive(!enabled);
|
||||
this.ScrollPool.UIRoot.SetActive(!enabled);
|
||||
m_updateRowObj.SetActive(!enabled);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,487 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.Core;
|
||||
using UnityExplorer.Core.Config;
|
||||
using UnityExplorer.Core.Runtime;
|
||||
using UnityExplorer.UI.CacheObject;
|
||||
using UnityExplorer.UI.Panels;
|
||||
using UnityExplorer.UI.Utility;
|
||||
using UnityExplorer.UI.Widgets;
|
||||
|
||||
namespace UnityExplorer.UI.Inspectors.Reflection
|
||||
{
|
||||
public class ReflectionInspector : InspectorBase
|
||||
{
|
||||
#region STATIC
|
||||
|
||||
public static ReflectionInspector ActiveInstance { get; private set; }
|
||||
|
||||
//static ReflectionInspector()
|
||||
//{
|
||||
// PanelDragger.OnFinishResize += (RectTransform _) => OnContainerResized();
|
||||
// SceneExplorer.OnToggleShow += OnContainerResized;
|
||||
//}
|
||||
|
||||
//private static void OnContainerResized(bool _ = false)
|
||||
//{
|
||||
// if (ActiveInstance == null)
|
||||
// return;
|
||||
|
||||
// ActiveInstance.m_widthUpdateWanted = true;
|
||||
//}
|
||||
|
||||
// Blacklists
|
||||
private static readonly HashSet<string> bl_typeAndMember = new HashSet<string>
|
||||
{
|
||||
#if CPP
|
||||
// these cause a crash in IL2CPP
|
||||
"Type.DeclaringMethod",
|
||||
"Rigidbody2D.Cast",
|
||||
"Collider2D.Cast",
|
||||
"Collider2D.Raycast",
|
||||
"Texture2D.SetPixelDataImpl",
|
||||
"Camera.CalculateProjectionMatrixFromPhysicalProperties",
|
||||
#endif
|
||||
};
|
||||
private static readonly HashSet<string> bl_methodNameStartsWith = new HashSet<string>
|
||||
{
|
||||
// these are redundant, just adds noise, properties are supported directly
|
||||
"get_",
|
||||
"set_",
|
||||
};
|
||||
|
||||
#endregion
|
||||
|
||||
#region INSTANCE
|
||||
|
||||
public override string TabLabel => m_targetTypeShortName;
|
||||
|
||||
public CacheObjectBase ParentMember { get; internal set; }
|
||||
|
||||
public ScrollPool ScrollPool { get; private set; }
|
||||
public CacheMemberList CacheMemberList { get; private set; }
|
||||
|
||||
public GameObject InactiveHolder => m_inactiveHolder;
|
||||
private GameObject m_inactiveHolder;
|
||||
|
||||
internal readonly Type m_targetType;
|
||||
internal readonly string m_targetTypeShortName;
|
||||
|
||||
// all cached members of the target
|
||||
internal CacheMember[] allMembers;
|
||||
// filtered members based on current filters
|
||||
internal readonly List<CacheMember> filteredMembers = new List<CacheMember>();
|
||||
// actual shortlist of displayed members
|
||||
internal readonly List<CacheMember> displayedMembers = new List<CacheMember>();
|
||||
|
||||
// index: Index in filter list, Value: Actual real index in allMembers list.
|
||||
internal readonly List<int> filteredToRealIndices = new List<int>();
|
||||
|
||||
internal bool autoUpdate;
|
||||
|
||||
public override void OnPanelResized()
|
||||
{
|
||||
foreach (var member in displayedMembers)
|
||||
{
|
||||
member.memberLabelElement.minWidth = 0.4f * InspectorPanel.CurrentPanelWidth;
|
||||
}
|
||||
}
|
||||
|
||||
public ReflectionInspector(object target) : base(target)
|
||||
{
|
||||
if (this is StaticInspector)
|
||||
m_targetType = target as Type;
|
||||
else
|
||||
m_targetType = ReflectionUtility.GetActualType(target);
|
||||
|
||||
m_targetTypeShortName = SignatureHighlighter.ParseFullSyntax(m_targetType, false);
|
||||
|
||||
ConstructUI();
|
||||
|
||||
CacheMembers(m_targetType);
|
||||
|
||||
FilterMembers();
|
||||
}
|
||||
|
||||
public override void SetActive()
|
||||
{
|
||||
base.SetActive();
|
||||
ActiveInstance = this;
|
||||
}
|
||||
|
||||
public override void SetInactive()
|
||||
{
|
||||
base.SetInactive();
|
||||
ActiveInstance = null;
|
||||
}
|
||||
|
||||
public override void Destroy()
|
||||
{
|
||||
base.Destroy();
|
||||
|
||||
if (this.Content)
|
||||
{
|
||||
GameObject.Destroy(this.InactiveHolder);
|
||||
GameObject.Destroy(this.Content);
|
||||
}
|
||||
}
|
||||
|
||||
internal bool IsBlacklisted(string sig) => bl_typeAndMember.Any(it => sig.Contains(it));
|
||||
internal bool IsBlacklisted(MethodInfo method) => bl_methodNameStartsWith.Any(it => method.Name.StartsWith(it));
|
||||
|
||||
internal string GetSig(MemberInfo member) => $"{member.DeclaringType.Name}.{member.Name}";
|
||||
internal string AppendArgsToSig(ParameterInfo[] args)
|
||||
{
|
||||
string ret = " (";
|
||||
foreach (var param in args)
|
||||
ret += $"{param.ParameterType.Name} {param.Name}, ";
|
||||
ret += ")";
|
||||
return ret;
|
||||
}
|
||||
|
||||
public void CacheMembers(Type type)
|
||||
{
|
||||
var list = new List<CacheMember>();
|
||||
var cachedSigs = new HashSet<string>();
|
||||
|
||||
var types = ReflectionUtility.GetAllBaseTypes(type);
|
||||
|
||||
var flags = BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static;
|
||||
if (this is InstanceInspector)
|
||||
flags |= BindingFlags.Instance;
|
||||
|
||||
foreach (var declaringType in types)
|
||||
{
|
||||
var target = Target;
|
||||
target = target.TryCast(declaringType);
|
||||
|
||||
IEnumerable<MemberInfo> infos = declaringType.GetMethods(flags);
|
||||
infos = infos.Concat(declaringType.GetProperties(flags));
|
||||
infos = infos.Concat(declaringType.GetFields(flags));
|
||||
|
||||
foreach (var member in infos)
|
||||
{
|
||||
try
|
||||
{
|
||||
var sig = GetSig(member);
|
||||
|
||||
//ExplorerCore.Log($"Trying to cache member {sig}...");
|
||||
//ExplorerCore.Log(member.DeclaringType.FullName + "." + member.Name);
|
||||
|
||||
var mi = member as MethodInfo;
|
||||
var pi = member as PropertyInfo;
|
||||
var fi = member as FieldInfo;
|
||||
|
||||
if (IsBlacklisted(sig) || (mi != null && IsBlacklisted(mi)))
|
||||
continue;
|
||||
|
||||
var args = mi?.GetParameters() ?? pi?.GetIndexParameters();
|
||||
if (args != null)
|
||||
{
|
||||
if (!CacheMember.CanProcessArgs(args))
|
||||
continue;
|
||||
|
||||
sig += AppendArgsToSig(args);
|
||||
}
|
||||
|
||||
if (cachedSigs.Contains(sig))
|
||||
continue;
|
||||
|
||||
cachedSigs.Add(sig);
|
||||
|
||||
if (mi != null)
|
||||
list.Add(new CacheMethod(mi, target, InactiveHolder));
|
||||
else if (pi != null)
|
||||
list.Add(new CacheProperty(pi, target, InactiveHolder));
|
||||
else
|
||||
list.Add(new CacheField(fi, target, InactiveHolder));
|
||||
|
||||
var cached = list[list.Count - 1];
|
||||
cached.ParentInspector = this;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
ExplorerCore.LogWarning($"Exception caching member {member.DeclaringType.FullName}.{member.Name}!");
|
||||
ExplorerCore.Log(e.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var typeList = types.ToList();
|
||||
|
||||
var sorted = new List<CacheMember>();
|
||||
sorted.AddRange(list.Where(it => it is CacheProperty)
|
||||
.OrderBy(it => typeList.IndexOf(it.DeclaringType))
|
||||
.ThenBy(it => it.NameForFiltering));
|
||||
sorted.AddRange(list.Where(it => it is CacheField)
|
||||
.OrderBy(it => typeList.IndexOf(it.DeclaringType))
|
||||
.ThenBy(it => it.NameForFiltering));
|
||||
sorted.AddRange(list.Where(it => it is CacheMethod)
|
||||
.OrderBy(it => typeList.IndexOf(it.DeclaringType))
|
||||
.ThenBy(it => it.NameForFiltering));
|
||||
|
||||
allMembers = sorted.ToArray();
|
||||
}
|
||||
|
||||
public override void Update()
|
||||
{
|
||||
base.Update();
|
||||
|
||||
if (autoUpdate)
|
||||
{
|
||||
foreach (var member in displayedMembers)
|
||||
{
|
||||
if (member == null) break;
|
||||
member.UpdateValue();
|
||||
}
|
||||
}
|
||||
|
||||
//if (m_widthUpdateWanted)
|
||||
//{
|
||||
// if (!m_widthUpdateWaiting)
|
||||
// m_widthUpdateWaiting = true;
|
||||
// else
|
||||
// {
|
||||
// UpdateWidths();
|
||||
// m_widthUpdateWaiting = false;
|
||||
// m_widthUpdateWanted = false;
|
||||
// }
|
||||
//}
|
||||
}
|
||||
|
||||
internal void OnMemberFilterClicked(MemberTypes type, Button button)
|
||||
{
|
||||
if (m_lastActiveMemButton)
|
||||
RuntimeProvider.Instance.SetColorBlock(m_lastActiveMemButton, new Color(0.2f, 0.2f, 0.2f));
|
||||
|
||||
m_memberFilter = type;
|
||||
m_lastActiveMemButton = button;
|
||||
|
||||
RuntimeProvider.Instance.SetColorBlock(m_lastActiveMemButton, new Color(0.2f, 0.6f, 0.2f));
|
||||
|
||||
FilterMembers(null, true);
|
||||
ScrollPool.RecreateHeightCache();
|
||||
ScrollPool.Rebuild();
|
||||
}
|
||||
|
||||
public void FilterMembers(string nameFilter = null, bool force = false)
|
||||
{
|
||||
int lastCount = filteredMembers.Count;
|
||||
filteredMembers.Clear();
|
||||
|
||||
nameFilter = nameFilter?.ToLower() ?? m_nameFilterText.text.ToLower();
|
||||
|
||||
filteredToRealIndices.Clear();
|
||||
|
||||
for (int i = 0; i < allMembers.Length; i++)
|
||||
{
|
||||
var mem = allMembers[i];
|
||||
|
||||
// membertype filter
|
||||
if (m_memberFilter != MemberTypes.All && mem.MemInfo.MemberType != m_memberFilter)
|
||||
continue;
|
||||
|
||||
if (this is InstanceInspector ii && ii.m_scopeFilter != MemberScopes.All)
|
||||
{
|
||||
if (mem.IsStatic && ii.m_scopeFilter != MemberScopes.Static)
|
||||
continue;
|
||||
else if (!mem.IsStatic && ii.m_scopeFilter != MemberScopes.Instance)
|
||||
continue;
|
||||
}
|
||||
|
||||
// name filter
|
||||
if (!string.IsNullOrEmpty(nameFilter) && !mem.NameForFiltering.Contains(nameFilter))
|
||||
continue;
|
||||
|
||||
filteredMembers.Add(mem);
|
||||
filteredToRealIndices.Add(i);
|
||||
}
|
||||
|
||||
//if (force || lastCount != filteredMembers.Count)
|
||||
//{
|
||||
// ScrollPool.EnableTempCache();
|
||||
// ScrollPool.Rebuild();
|
||||
//}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region UI
|
||||
|
||||
private GameObject m_content;
|
||||
public override GameObject Content
|
||||
{
|
||||
get => m_content;
|
||||
set => m_content = value;
|
||||
}
|
||||
|
||||
internal Text m_nameFilterText;
|
||||
internal MemberTypes m_memberFilter;
|
||||
internal Button m_lastActiveMemButton;
|
||||
|
||||
internal GameObject m_filterAreaObj;
|
||||
internal GameObject m_updateRowObj;
|
||||
|
||||
internal void ConstructUI()
|
||||
{
|
||||
var parent = InspectorPanel.Instance.ContentHolder;
|
||||
|
||||
this.Content = UIFactory.CreateVerticalGroup(parent, "ReflectionInspector", true, false, true, true, 5, new Vector4(4, 4, 4, 4),
|
||||
new Color(0.15f, 0.15f, 0.15f));
|
||||
|
||||
this.m_inactiveHolder = new GameObject("InactiveContentHolder");
|
||||
m_inactiveHolder.transform.SetParent(Content.transform, false);
|
||||
m_inactiveHolder.SetActive(false);
|
||||
|
||||
ConstructTopArea();
|
||||
|
||||
ConstructMemberList();
|
||||
}
|
||||
|
||||
internal void ConstructTopArea()
|
||||
{
|
||||
var nameRowObj = UIFactory.CreateHorizontalGroup(Content, "NameRowObj", true, true, true, true, 2, default, new Color(1, 1, 1, 0));
|
||||
UIFactory.SetLayoutElement(nameRowObj, minHeight: 25, flexibleHeight: 0, minWidth: 200, flexibleWidth: 5000);
|
||||
|
||||
var typeLabelText = UIFactory.CreateLabel(nameRowObj, "TypeLabel", "Type:", TextAnchor.MiddleLeft);
|
||||
typeLabelText.horizontalOverflow = HorizontalWrapMode.Overflow;
|
||||
UIFactory.SetLayoutElement(typeLabelText.gameObject, minWidth: 40, flexibleWidth: 0, minHeight: 25);
|
||||
|
||||
var typeDisplay = UIFactory.CreateLabel(nameRowObj, "TypeDisplayText", SignatureHighlighter.ParseFullSyntax(m_targetType, true),
|
||||
TextAnchor.MiddleLeft);
|
||||
|
||||
UIFactory.SetLayoutElement(typeDisplay.gameObject, minHeight: 25, flexibleWidth: 5000);
|
||||
|
||||
// instance helper tools
|
||||
|
||||
if (this is InstanceInspector instanceInspector)
|
||||
{
|
||||
instanceInspector.ConstructUnityInstanceHelpers();
|
||||
}
|
||||
|
||||
ConstructFilterArea();
|
||||
|
||||
ConstructUpdateRow();
|
||||
}
|
||||
|
||||
internal void ConstructFilterArea()
|
||||
{
|
||||
// Filters
|
||||
|
||||
m_filterAreaObj = UIFactory.CreateVerticalGroup(Content, "FilterGroup", true, true, true, true, 4, new Vector4(4, 4, 4, 4),
|
||||
new Color(0.1f, 0.1f, 0.1f));
|
||||
UIFactory.SetLayoutElement(m_filterAreaObj, minHeight: 60);
|
||||
|
||||
// name filter
|
||||
|
||||
var nameFilterRowObj = UIFactory.CreateHorizontalGroup(m_filterAreaObj, "NameFilterRow", false, false, true, true, 5, default,
|
||||
new Color(1, 1, 1, 0));
|
||||
UIFactory.SetLayoutElement(nameFilterRowObj, minHeight: 25, flexibleHeight: 0, flexibleWidth: 5000);
|
||||
|
||||
var nameLabel = UIFactory.CreateLabel(nameFilterRowObj, "NameLabel", "Filter names:", TextAnchor.MiddleLeft, Color.grey);
|
||||
UIFactory.SetLayoutElement(nameLabel.gameObject, minWidth: 100, minHeight: 25, flexibleWidth: 0);
|
||||
|
||||
var nameInputObj = UIFactory.CreateInputField(nameFilterRowObj, "NameInput", "...", out InputField nameInput, 14, (int)TextAnchor.MiddleLeft,
|
||||
(int)HorizontalWrapMode.Overflow);
|
||||
UIFactory.SetLayoutElement(nameInputObj, flexibleWidth: 5000, minWidth: 100, minHeight: 25);
|
||||
nameInput.onValueChanged.AddListener((string val) =>
|
||||
{
|
||||
FilterMembers(val, true);
|
||||
ScrollPool.RecreateHeightCache();
|
||||
ScrollPool.Rebuild();
|
||||
});
|
||||
m_nameFilterText = nameInput.textComponent;
|
||||
|
||||
// membertype filter
|
||||
|
||||
var memberFilterRowObj = UIFactory.CreateHorizontalGroup(m_filterAreaObj, "MemberFilter", false, false, true, true, 5, default,
|
||||
new Color(1, 1, 1, 0));
|
||||
UIFactory.SetLayoutElement(memberFilterRowObj, minHeight: 25, flexibleHeight: 0, flexibleWidth: 5000);
|
||||
|
||||
var memLabel = UIFactory.CreateLabel(memberFilterRowObj, "MemberFilterLabel", "Filter members:", TextAnchor.MiddleLeft, Color.grey);
|
||||
UIFactory.SetLayoutElement(memLabel.gameObject, minWidth: 100, minHeight: 25, flexibleWidth: 0);
|
||||
|
||||
AddFilterButton(memberFilterRowObj, MemberTypes.All, true);
|
||||
AddFilterButton(memberFilterRowObj, MemberTypes.Method);
|
||||
AddFilterButton(memberFilterRowObj, MemberTypes.Property);
|
||||
AddFilterButton(memberFilterRowObj, MemberTypes.Field);
|
||||
|
||||
// Instance filters
|
||||
|
||||
if (this is InstanceInspector instanceInspector)
|
||||
{
|
||||
instanceInspector.ConstructInstanceScopeFilters(m_filterAreaObj);
|
||||
}
|
||||
}
|
||||
|
||||
private void AddFilterButton(GameObject parent, MemberTypes type, bool setEnabled = false)
|
||||
{
|
||||
var btn = UIFactory.CreateButton(parent,
|
||||
"FilterButton_" + type,
|
||||
type.ToString(),
|
||||
null,
|
||||
new Color(0.2f, 0.2f, 0.2f));
|
||||
UIFactory.SetLayoutElement(btn.gameObject, minHeight: 25, minWidth: 70);
|
||||
btn.onClick.AddListener(() => { OnMemberFilterClicked(type, btn); });
|
||||
|
||||
RuntimeProvider.Instance.SetColorBlock(btn, highlighted: new Color(0.3f, 0.7f, 0.3f));
|
||||
|
||||
if (setEnabled)
|
||||
{
|
||||
RuntimeProvider.Instance.SetColorBlock(btn, new Color(0.2f, 0.6f, 0.2f));
|
||||
m_memberFilter = type;
|
||||
m_lastActiveMemButton = btn;
|
||||
}
|
||||
}
|
||||
|
||||
internal void ConstructUpdateRow()
|
||||
{
|
||||
m_updateRowObj = UIFactory.CreateHorizontalGroup(Content, "UpdateRow", false, true, true, true, 10, default, new Color(1, 1, 1, 0));
|
||||
UIFactory.SetLayoutElement(m_updateRowObj, minHeight: 25);
|
||||
|
||||
// update button
|
||||
|
||||
var updateBtn = UIFactory.CreateButton(m_updateRowObj, "UpdateButton", "Update Values", null, new Color(0.2f, 0.2f, 0.2f));
|
||||
UIFactory.SetLayoutElement(updateBtn.gameObject, minWidth: 110, flexibleWidth: 0);
|
||||
updateBtn.onClick.AddListener(() =>
|
||||
{
|
||||
bool orig = autoUpdate;
|
||||
autoUpdate = true;
|
||||
Update();
|
||||
if (!orig)
|
||||
autoUpdate = orig;
|
||||
});
|
||||
|
||||
// auto update
|
||||
|
||||
var autoUpdateObj = UIFactory.CreateToggle(m_updateRowObj, "UpdateToggle", out Toggle autoUpdateToggle, out Text autoUpdateText);
|
||||
var autoUpdateLayout = autoUpdateObj.AddComponent<LayoutElement>();
|
||||
autoUpdateLayout.minWidth = 150;
|
||||
autoUpdateLayout.minHeight = 25;
|
||||
autoUpdateText.text = "Auto-update?";
|
||||
autoUpdateToggle.isOn = false;
|
||||
autoUpdateToggle.onValueChanged.AddListener((bool val) => { autoUpdate = val; });
|
||||
}
|
||||
|
||||
internal void ConstructMemberList()
|
||||
{
|
||||
ScrollPool = UIFactory.CreateScrollPool(Content, "MemberList", out GameObject scrollRoot, out GameObject scrollContent,
|
||||
new Color(0.05f, 0.05f, 0.05f));
|
||||
UIFactory.SetLayoutElement(scrollRoot, flexibleHeight: 9999);
|
||||
UIFactory.SetLayoutElement(scrollContent, flexibleHeight: 9999);
|
||||
|
||||
CacheMemberList = new CacheMemberList(ScrollPool, this);
|
||||
|
||||
ScrollPool.Initialize(CacheMemberList, CellViewHolder.CreatePrototypeCell(scrollRoot));
|
||||
|
||||
// ScrollPool.Viewport.GetComponent<Mask>().enabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
@ -1,14 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace UnityExplorer.UI.Inspectors.Reflection
|
||||
{
|
||||
public class StaticInspector : ReflectionInspector
|
||||
{
|
||||
public override string TabLabel => $" <color=cyan>[S]</color> {base.TabLabel}";
|
||||
|
||||
public StaticInspector(Type type) : base(type) { }
|
||||
}
|
||||
}
|
32
src/UI/Inspectors/ReflectionInspector.cs
Normal file
32
src/UI/Inspectors/ReflectionInspector.cs
Normal file
@ -0,0 +1,32 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityExplorer.UI.Inspectors
|
||||
{
|
||||
public class InstanceInspector : ReflectionInspector { }
|
||||
|
||||
public class StaticInspector : ReflectionInspector { }
|
||||
|
||||
public class ReflectionInspector : InspectorBase
|
||||
{
|
||||
public override GameObject UIRoot => throw new NotImplementedException();
|
||||
|
||||
public override GameObject CreateContent(GameObject content)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override void Update()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
protected override void OnCloseClicked()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
@ -127,13 +127,15 @@ namespace UnityExplorer.UI.Models
|
||||
|
||||
// close button
|
||||
|
||||
var closeBtn = UIFactory.CreateButton(titleGroup, "CloseButton", "X", () =>
|
||||
var closeBtn = UIFactory.CreateButton(titleGroup, "CloseButton", "X");
|
||||
UIFactory.SetLayoutElement(closeBtn.Button.gameObject, minHeight: 25, minWidth: 25, flexibleWidth: 0);
|
||||
RuntimeProvider.Instance.SetColorBlock(closeBtn.Button, new Color(0.63f, 0.32f, 0.31f),
|
||||
new Color(0.81f, 0.25f, 0.2f), new Color(0.6f, 0.18f, 0.16f));
|
||||
|
||||
closeBtn.OnClick += () =>
|
||||
{
|
||||
UIManager.SetPanelActive(this.PanelType, false);
|
||||
});
|
||||
UIFactory.SetLayoutElement(closeBtn.gameObject, minHeight: 25, minWidth: 25, flexibleWidth: 0);
|
||||
RuntimeProvider.Instance.SetColorBlock(closeBtn, new Color(0.63f, 0.32f, 0.31f),
|
||||
new Color(0.81f, 0.25f, 0.2f), new Color(0.6f, 0.18f, 0.16f));
|
||||
};
|
||||
|
||||
if (!CanDrag)
|
||||
titleGroup.SetActive(false);
|
||||
|
19
src/UI/ObjectPool/IPooledObject.cs
Normal file
19
src/UI/ObjectPool/IPooledObject.cs
Normal file
@ -0,0 +1,19 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityExplorer.UI.ObjectPool
|
||||
{
|
||||
public interface IPooledObject
|
||||
{
|
||||
GameObject UIRoot { get; }
|
||||
|
||||
GameObject CreateContent(GameObject parent);
|
||||
|
||||
float DefaultHeight { get; }
|
||||
|
||||
//GameObject CreatePrototype();
|
||||
}
|
||||
}
|
106
src/UI/ObjectPool/Pool.cs
Normal file
106
src/UI/ObjectPool/Pool.cs
Normal file
@ -0,0 +1,106 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityExplorer.UI.ObjectPool
|
||||
{
|
||||
public interface IObjectPool { }
|
||||
|
||||
public class Pool<T> : IObjectPool where T : IPooledObject
|
||||
{
|
||||
// internal pool management
|
||||
|
||||
private static readonly Dictionary<Type, IObjectPool> pools = new Dictionary<Type, IObjectPool>();
|
||||
|
||||
public static Pool<T> GetPool()
|
||||
{
|
||||
var type = typeof(T);
|
||||
if (!pools.ContainsKey(type))
|
||||
CreatePool();
|
||||
return (Pool<T>)pools[type];
|
||||
}
|
||||
|
||||
private static Pool<T> CreatePool()
|
||||
{
|
||||
var pool = new Pool<T>();
|
||||
pools.Add(typeof(T), pool);
|
||||
return pool;
|
||||
}
|
||||
|
||||
public static T Borrow()
|
||||
{
|
||||
return GetPool().BorrowObject();
|
||||
}
|
||||
|
||||
public static void Return(T obj)
|
||||
{
|
||||
GetPool().ReturnObject(obj);
|
||||
}
|
||||
|
||||
// Instance
|
||||
|
||||
public static Pool<T> Instance
|
||||
{
|
||||
get => s_instance ?? CreatePool();
|
||||
}
|
||||
private static Pool<T> s_instance;
|
||||
|
||||
public Pool()
|
||||
{
|
||||
s_instance = this;
|
||||
|
||||
ExplorerCore.LogWarning("Creating Pool<" + typeof(T).Name + ">");
|
||||
|
||||
InactiveHolder = new GameObject($"InactiveHolder_{typeof(T).Name}");
|
||||
InactiveHolder.transform.parent = UIManager.PoolHolder.transform;
|
||||
InactiveHolder.hideFlags |= HideFlags.HideAndDontSave;
|
||||
InactiveHolder.SetActive(false);
|
||||
|
||||
// Create an instance (not content) to grab the default height.
|
||||
// Tiny bit wasteful, but not a big deal, only happens once per type
|
||||
// and its just the C# wrapper class being created.
|
||||
var obj = (T)Activator.CreateInstance(typeof(T));
|
||||
DefaultHeight = obj.DefaultHeight;
|
||||
}
|
||||
|
||||
public GameObject InactiveHolder { get; }
|
||||
public float DefaultHeight { get; }
|
||||
|
||||
private readonly HashSet<T> available = new HashSet<T>();
|
||||
private readonly HashSet<T> borrowed = new HashSet<T>();
|
||||
|
||||
public int AvailableObjects => available.Count;
|
||||
|
||||
private void IncrementPool()
|
||||
{
|
||||
var obj = (T)Activator.CreateInstance(typeof(T));
|
||||
obj.CreateContent(InactiveHolder);
|
||||
available.Add(obj);
|
||||
}
|
||||
|
||||
public T BorrowObject()
|
||||
{
|
||||
if (available.Count <= 0)
|
||||
IncrementPool();
|
||||
|
||||
var obj = available.First();
|
||||
available.Remove(obj);
|
||||
borrowed.Add(obj);
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
public void ReturnObject(T obj)
|
||||
{
|
||||
if (!borrowed.Contains(obj))
|
||||
ExplorerCore.LogWarning($"Returning an item to object pool ({typeof(T).Name}) but the item didn't exist in the borrowed list?");
|
||||
else
|
||||
borrowed.Remove(obj);
|
||||
|
||||
available.Add(obj);
|
||||
obj.UIRoot.transform.SetParent(InactiveHolder.transform, false);
|
||||
}
|
||||
}
|
||||
}
|
@ -26,7 +26,7 @@ namespace UnityExplorer.UI.Panels
|
||||
|
||||
public int SelectedTab = -1;
|
||||
private readonly List<UIModel> tabPages = new List<UIModel>();
|
||||
private readonly List<Button> tabButtons = new List<Button>();
|
||||
private readonly List<ButtonRef> tabButtons = new List<ButtonRef>();
|
||||
|
||||
public void SetTab(int tabIndex)
|
||||
{
|
||||
@ -37,7 +37,7 @@ namespace UnityExplorer.UI.Panels
|
||||
content.SetActive(true);
|
||||
|
||||
var button = tabButtons[tabIndex];
|
||||
RuntimeProvider.Instance.SetColorBlock(button, UIManager.navButtonEnabledColor, UIManager.navButtonEnabledColor * 1.2f);
|
||||
RuntimeProvider.Instance.SetColorBlock(button.Button, UIManager.navButtonEnabledColor, UIManager.navButtonEnabledColor * 1.2f);
|
||||
|
||||
SelectedTab = tabIndex;
|
||||
SaveToConfigManager();
|
||||
@ -46,7 +46,7 @@ namespace UnityExplorer.UI.Panels
|
||||
private void DisableTab(int tabIndex)
|
||||
{
|
||||
tabPages[tabIndex].SetActive(false);
|
||||
RuntimeProvider.Instance.SetColorBlock(tabButtons[tabIndex], UIManager.navButtonDisabledColor, UIManager.navButtonDisabledColor * 1.2f);
|
||||
RuntimeProvider.Instance.SetColorBlock(tabButtons[tabIndex].Button, UIManager.navButtonDisabledColor, UIManager.navButtonDisabledColor * 1.2f);
|
||||
}
|
||||
|
||||
public override void Update()
|
||||
@ -130,7 +130,8 @@ namespace UnityExplorer.UI.Panels
|
||||
var button = UIFactory.CreateButton(tabGroup, $"Button_{label}", label);
|
||||
|
||||
int idx = tabButtons.Count;
|
||||
button.onClick.AddListener(() => { SetTab(idx); });
|
||||
//button.onClick.AddListener(() => { SetTab(idx); });
|
||||
button.OnClick += () => { SetTab(idx); };
|
||||
|
||||
tabButtons.Add(button);
|
||||
|
||||
|
@ -27,6 +27,7 @@ namespace UnityExplorer.UI
|
||||
if (!parent)
|
||||
{
|
||||
ExplorerCore.LogWarning("Cannot create UI object as the parent is null or destroyed! (" + name + ")");
|
||||
ExplorerCore.Log(Environment.StackTrace);
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -56,10 +57,6 @@ namespace UnityExplorer.UI
|
||||
{
|
||||
RuntimeProvider.Instance.SetColorBlock(selectable, new Color(0.2f, 0.2f, 0.2f),
|
||||
new Color(0.3f, 0.3f, 0.3f), new Color(0.15f, 0.15f, 0.15f));
|
||||
|
||||
// Deselect all Buttons after they are clicked.
|
||||
if (selectable is Button button)
|
||||
button.onClick.AddListener(() => { button.OnDeselect(null); });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -258,19 +255,19 @@ namespace UnityExplorer.UI
|
||||
return textComp;
|
||||
}
|
||||
|
||||
public static Button CreateButton(GameObject parent, string name, string text, Action onClick = null, Color? normalColor = null)
|
||||
public static ButtonRef CreateButton(GameObject parent, string name, string text, Color? normalColor = null)
|
||||
{
|
||||
var colors = new ColorBlock();
|
||||
normalColor = normalColor ?? new Color(0.25f, 0.25f, 0.25f);
|
||||
|
||||
var btn = CreateButton(parent, name, text, onClick, colors);
|
||||
var btn = CreateButton(parent, name, text, colors);
|
||||
|
||||
RuntimeProvider.Instance.SetColorBlock(btn, normalColor, new Color(0.4f, 0.4f, 0.4f), new Color(0.15f, 0.15f, 0.15f));
|
||||
RuntimeProvider.Instance.SetColorBlock(btn.Button, normalColor, normalColor * 1.2f, normalColor * 0.7f);
|
||||
|
||||
return btn;
|
||||
}
|
||||
|
||||
public static Button CreateButton(GameObject parent, string name, string text, Action onClick, ColorBlock colors)
|
||||
public static ButtonRef CreateButton(GameObject parent, string name, string text, ColorBlock colors)
|
||||
{
|
||||
GameObject buttonObj = CreateUIObject(name, parent, _smallElementSize);
|
||||
|
||||
@ -296,10 +293,17 @@ namespace UnityExplorer.UI
|
||||
rect.anchorMax = Vector2.one;
|
||||
rect.sizeDelta = Vector2.zero;
|
||||
|
||||
if (onClick != null)
|
||||
button.onClick.AddListener(onClick);
|
||||
SetButtonDeselectListener(button);
|
||||
|
||||
return button;
|
||||
return new ButtonRef(button);
|
||||
}
|
||||
|
||||
public static void SetButtonDeselectListener(Button button)
|
||||
{
|
||||
button.onClick.AddListener(() =>
|
||||
{
|
||||
button.OnDeselect(null);
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -720,8 +724,8 @@ namespace UnityExplorer.UI
|
||||
return dropdownObj;
|
||||
}
|
||||
|
||||
public static ScrollPool CreateScrollPool(GameObject parent, string name, out GameObject uiRoot,
|
||||
out GameObject content, Color? bgColor = null)
|
||||
public static ScrollPool<T> CreateScrollPool<T>(GameObject parent, string name, out GameObject uiRoot,
|
||||
out GameObject content, Color? bgColor = null) where T : ICell
|
||||
{
|
||||
var mainObj = CreateUIObject(name, parent, new Vector2(1, 1));
|
||||
mainObj.AddComponent<Image>().color = bgColor ?? new Color(0.12f, 0.12f, 0.12f);
|
||||
@ -787,7 +791,7 @@ namespace UnityExplorer.UI
|
||||
// finalize and create ScrollPool
|
||||
|
||||
uiRoot = mainObj;
|
||||
var scrollPool = new ScrollPool(scrollRect);
|
||||
var scrollPool = new ScrollPool<T>(scrollRect);
|
||||
|
||||
//viewportObj.GetComponent<Mask>().enabled = false;
|
||||
|
||||
|
@ -32,6 +32,8 @@ namespace UnityExplorer.UI
|
||||
public static Canvas Canvas { get; private set; }
|
||||
public static EventSystem EventSys { get; private set; }
|
||||
|
||||
internal static GameObject PoolHolder { get; private set; }
|
||||
|
||||
// panels
|
||||
internal static GameObject PanelHolder { get; private set; }
|
||||
|
||||
@ -138,6 +140,11 @@ namespace UnityExplorer.UI
|
||||
UIFactory.Init();
|
||||
|
||||
CreateRootCanvas();
|
||||
|
||||
PoolHolder = new GameObject("PoolHolder");
|
||||
PoolHolder.transform.parent = CanvasRoot.transform;
|
||||
PoolHolder.SetActive(false);
|
||||
|
||||
CreateTopNavBar();
|
||||
|
||||
AutoCompleter = new AutoCompleter();
|
||||
@ -213,22 +220,24 @@ namespace UnityExplorer.UI
|
||||
|
||||
// close button
|
||||
|
||||
var closeBtn = UIFactory.CreateButton(panel, "CloseButton", "X", () => { ShowMenu = false; });
|
||||
UIFactory.SetLayoutElement(closeBtn.gameObject, minHeight: 25, minWidth: 25, flexibleWidth: 0);
|
||||
RuntimeProvider.Instance.SetColorBlock(closeBtn, new Color(0.63f, 0.32f, 0.31f),
|
||||
var closeBtn = UIFactory.CreateButton(panel, "CloseButton", "X");
|
||||
UIFactory.SetLayoutElement(closeBtn.Button.gameObject, minHeight: 25, minWidth: 25, flexibleWidth: 0);
|
||||
RuntimeProvider.Instance.SetColorBlock(closeBtn.Button, new Color(0.63f, 0.32f, 0.31f),
|
||||
new Color(0.81f, 0.25f, 0.2f), new Color(0.6f, 0.18f, 0.16f));
|
||||
|
||||
closeBtn.OnClick += () => { ShowMenu = false; };
|
||||
}
|
||||
|
||||
private static void CreateNavButton(GameObject navbar, Panels panel, string label)
|
||||
{
|
||||
var button = UIFactory.CreateButton(navbar, $"Button_{panel}", label);
|
||||
UIFactory.SetLayoutElement(button.gameObject, minWidth: 118, flexibleWidth: 0);
|
||||
RuntimeProvider.Instance.SetColorBlock(button, navButtonDisabledColor, navButtonDisabledColor * 1.2f);
|
||||
button.onClick.AddListener(() =>
|
||||
UIFactory.SetLayoutElement(button.Button.gameObject, minWidth: 118, flexibleWidth: 0);
|
||||
RuntimeProvider.Instance.SetColorBlock(button.Button, navButtonDisabledColor, navButtonDisabledColor * 1.2f);
|
||||
button.OnClick += () =>
|
||||
{
|
||||
TogglePanel(panel);
|
||||
});
|
||||
navButtonDict.Add(panel, button);
|
||||
};
|
||||
navButtonDict.Add(panel, button.Button);
|
||||
}
|
||||
|
||||
// Could be cool, need to investigate properly.
|
||||
|
@ -61,7 +61,7 @@ namespace UnityExplorer.UI.Utility
|
||||
else
|
||||
{
|
||||
if (includeNamespace && !string.IsNullOrEmpty(type.Namespace))
|
||||
syntaxBuilder.Append($"<color=#{NAMESPACE}>{type.Namespace}</color>.");
|
||||
syntaxBuilder.Append($"<color={NAMESPACE}>{type.Namespace}</color>.");
|
||||
|
||||
var declaring = type.DeclaringType;
|
||||
while (declaring != null)
|
||||
|
@ -8,6 +8,7 @@ using UnityExplorer.Core.Input;
|
||||
using UnityExplorer.Core.Runtime;
|
||||
using UnityExplorer.UI;
|
||||
using UnityExplorer.UI.Models;
|
||||
using UnityExplorer.UI.ObjectPool;
|
||||
|
||||
namespace UnityExplorer.UI.Widgets.AutoComplete
|
||||
{
|
||||
@ -58,7 +59,7 @@ namespace UnityExplorer.UI.Widgets.AutoComplete
|
||||
public ISuggestionProvider CurrentHandler { get; private set; }
|
||||
|
||||
public ButtonListSource<Suggestion> dataHandler;
|
||||
public ScrollPool scrollPool;
|
||||
public ScrollPool<ButtonCell> scrollPool;
|
||||
|
||||
private List<Suggestion> suggestions = new List<Suggestion>();
|
||||
|
||||
@ -123,7 +124,7 @@ namespace UnityExplorer.UI.Widgets.AutoComplete
|
||||
CurrentHandler.OnSuggestionClicked(suggestion);
|
||||
}
|
||||
|
||||
private void SetCell(ButtonCell<Suggestion> cell, int index)
|
||||
private void SetCell(ButtonCell cell, int index)
|
||||
{
|
||||
if (index < 0 || index >= suggestions.Count)
|
||||
{
|
||||
@ -132,7 +133,7 @@ namespace UnityExplorer.UI.Widgets.AutoComplete
|
||||
}
|
||||
|
||||
var suggestion = suggestions[index];
|
||||
cell.buttonText.text = suggestion.DisplayText;
|
||||
cell.Button.ButtonText.text = suggestion.DisplayText;
|
||||
}
|
||||
|
||||
private void UpdatePosition()
|
||||
@ -173,11 +174,8 @@ namespace UnityExplorer.UI.Widgets.AutoComplete
|
||||
{
|
||||
dataHandler = new ButtonListSource<Suggestion>(scrollPool, GetEntries, SetCell, ShouldDisplay, OnCellClicked);
|
||||
|
||||
var prototypeCell = ButtonCell<Suggestion>.CreatePrototypeCell(this.content);
|
||||
prototypeCell.GetComponentInChildren<Text>().supportRichText = true;
|
||||
|
||||
scrollPool = UIFactory.CreateScrollPool(this.content, "AutoCompleter", out GameObject scrollObj, out GameObject scrollContent);
|
||||
scrollPool.Initialize(dataHandler, prototypeCell);
|
||||
scrollPool = UIFactory.CreateScrollPool<ButtonCell>(this.content, "AutoCompleter", out GameObject scrollObj, out GameObject scrollContent);
|
||||
scrollPool.Initialize(dataHandler);
|
||||
UIFactory.SetLayoutElement(scrollObj, flexibleHeight: 9999);
|
||||
|
||||
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(scrollContent, true, false, true, false);
|
||||
|
@ -4,35 +4,29 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.UI.ObjectPool;
|
||||
|
||||
namespace UnityExplorer.UI.Widgets
|
||||
{
|
||||
public class ButtonCell<T> : ICell
|
||||
public class ButtonCell : ICell
|
||||
{
|
||||
public bool Enabled => m_enabled;
|
||||
private bool m_enabled;
|
||||
public float DefaultHeight => 25f;
|
||||
|
||||
public Action<int> OnClick;
|
||||
public int CurrentDataIndex;
|
||||
|
||||
public ButtonListSource<T> list;
|
||||
|
||||
public GameObject UIRoot => uiRoot;
|
||||
public GameObject uiRoot;
|
||||
private RectTransform m_rect;
|
||||
|
||||
public ButtonRef Button;
|
||||
|
||||
#region ICell
|
||||
|
||||
public bool Enabled => m_enabled;
|
||||
private bool m_enabled;
|
||||
|
||||
public RectTransform Rect => m_rect;
|
||||
public Text buttonText;
|
||||
public Button button;
|
||||
|
||||
public ButtonCell(ButtonListSource<T> list, GameObject uiRoot, Button button, Text text)
|
||||
{
|
||||
this.list = list;
|
||||
this.uiRoot = uiRoot;
|
||||
this.m_rect = uiRoot.GetComponent<RectTransform>();
|
||||
this.buttonText = text;
|
||||
this.button = button;
|
||||
|
||||
button.onClick.AddListener(() => { OnClick?.Invoke(CurrentDataIndex); });
|
||||
}
|
||||
private RectTransform m_rect;
|
||||
|
||||
public void Disable()
|
||||
{
|
||||
@ -46,33 +40,36 @@ namespace UnityExplorer.UI.Widgets
|
||||
uiRoot.SetActive(true);
|
||||
}
|
||||
|
||||
public static RectTransform CreatePrototypeCell(GameObject parent)
|
||||
#endregion
|
||||
|
||||
public GameObject CreateContent(GameObject parent)
|
||||
{
|
||||
var prototype = UIFactory.CreateHorizontalGroup(parent, "PrototypeCell", true, true, true, true, 2, default,
|
||||
new Color(0.15f, 0.15f, 0.15f), TextAnchor.MiddleCenter);
|
||||
//var cell = prototype.AddComponent<TransformCell>();
|
||||
var rect = prototype.GetComponent<RectTransform>();
|
||||
rect.anchorMin = new Vector2(0, 1);
|
||||
rect.anchorMax = new Vector2(0, 1);
|
||||
rect.pivot = new Vector2(0.5f, 1);
|
||||
rect.sizeDelta = new Vector2(25, 25);
|
||||
UIFactory.SetLayoutElement(prototype, minWidth: 100, flexibleWidth: 9999, minHeight: 25, flexibleHeight: 0);
|
||||
uiRoot = UIFactory.CreateHorizontalGroup(parent, "ButtonCell", true, true, true, true, 2, default,
|
||||
new Color(0.11f, 0.11f, 0.11f), TextAnchor.MiddleCenter);
|
||||
m_rect = uiRoot.GetComponent<RectTransform>();
|
||||
m_rect.anchorMin = new Vector2(0, 1);
|
||||
m_rect.anchorMax = new Vector2(0, 1);
|
||||
m_rect.pivot = new Vector2(0.5f, 1);
|
||||
m_rect.sizeDelta = new Vector2(25, 25);
|
||||
UIFactory.SetLayoutElement(uiRoot, minWidth: 100, flexibleWidth: 9999, minHeight: 25, flexibleHeight: 0);
|
||||
|
||||
var nameButton = UIFactory.CreateButton(prototype, "NameButton", "Name", null);
|
||||
UIFactory.SetLayoutElement(nameButton.gameObject, flexibleWidth: 9999, minHeight: 25, flexibleHeight: 0);
|
||||
var nameLabel = nameButton.GetComponentInChildren<Text>();
|
||||
nameLabel.horizontalOverflow = HorizontalWrapMode.Overflow;
|
||||
nameLabel.alignment = TextAnchor.MiddleLeft;
|
||||
uiRoot.SetActive(false);
|
||||
|
||||
Color normal = new Color(0.15f, 0.15f, 0.15f);
|
||||
this.Button = UIFactory.CreateButton(uiRoot, "NameButton", "Name");
|
||||
UIFactory.SetLayoutElement(Button.Button.gameObject, flexibleWidth: 9999, minHeight: 25, flexibleHeight: 0);
|
||||
var buttonText = Button.Button.GetComponentInChildren<Text>();
|
||||
buttonText.horizontalOverflow = HorizontalWrapMode.Overflow;
|
||||
buttonText.alignment = TextAnchor.MiddleLeft;
|
||||
|
||||
Color normal = new Color(0.11f, 0.11f, 0.11f);
|
||||
Color highlight = new Color(0.25f, 0.25f, 0.25f);
|
||||
Color pressed = new Color(0.05f, 0.05f, 0.05f);
|
||||
Color disabled = new Color(1, 1, 1, 0);
|
||||
RuntimeProvider.Instance.SetColorBlock(nameButton, normal, highlight, pressed, disabled);
|
||||
RuntimeProvider.Instance.SetColorBlock(Button.Button, normal, highlight, pressed, disabled);
|
||||
|
||||
prototype.SetActive(false);
|
||||
Button.OnClick += () => { OnClick?.Invoke(CurrentDataIndex); };
|
||||
|
||||
return rect;
|
||||
return m_rect.gameObject;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,21 +5,22 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.UI.ObjectPool;
|
||||
using UnityExplorer.UI.Widgets;
|
||||
|
||||
namespace UnityExplorer.UI.Widgets
|
||||
{
|
||||
public class ButtonListSource<T> : IPoolDataSource
|
||||
public class ButtonListSource<T> : IPoolDataSource<ButtonCell>
|
||||
{
|
||||
public int GetRealIndexOfTempIndex(int index) => throw new NotImplementedException("TODO");
|
||||
|
||||
internal ScrollPool Scroller;
|
||||
internal ScrollPool<ButtonCell> ScrollPool;
|
||||
|
||||
public int ItemCount => currentEntries.Count;
|
||||
public readonly List<T> currentEntries = new List<T>();
|
||||
|
||||
public Func<List<T>> GetEntries;
|
||||
public Action<ButtonCell<T>, int> SetICell;
|
||||
public Action<ButtonCell, int> SetICell;
|
||||
public Func<T, string, bool> ShouldDisplay;
|
||||
public Action<int> OnCellClicked;
|
||||
|
||||
@ -30,11 +31,11 @@ namespace UnityExplorer.UI.Widgets
|
||||
}
|
||||
private string currentFilter;
|
||||
|
||||
public ButtonListSource(ScrollPool scrollPool, Func<List<T>> getEntriesMethod,
|
||||
Action<ButtonCell<T>, int> setICellMethod, Func<T, string, bool> shouldDisplayMethod,
|
||||
public ButtonListSource(ScrollPool<ButtonCell> scrollPool, Func<List<T>> getEntriesMethod,
|
||||
Action<ButtonCell, int> setICellMethod, Func<T, string, bool> shouldDisplayMethod,
|
||||
Action<int> onCellClickedMethod)
|
||||
{
|
||||
Scroller = scrollPool;
|
||||
ScrollPool = scrollPool;
|
||||
|
||||
GetEntries = getEntriesMethod;
|
||||
SetICell = setICellMethod;
|
||||
@ -42,15 +43,6 @@ namespace UnityExplorer.UI.Widgets
|
||||
OnCellClicked = onCellClickedMethod;
|
||||
}
|
||||
|
||||
public void Init()
|
||||
{
|
||||
var proto = ButtonCell<T>.CreatePrototypeCell(Scroller.UIRoot);
|
||||
|
||||
RefreshData();
|
||||
Scroller.DataSource = this;
|
||||
Scroller.Initialize(this, proto);
|
||||
}
|
||||
|
||||
public void RefreshData()
|
||||
{
|
||||
var allEntries = GetEntries.Invoke();
|
||||
@ -70,16 +62,17 @@ namespace UnityExplorer.UI.Widgets
|
||||
}
|
||||
}
|
||||
|
||||
public ICell CreateCell(RectTransform rect)
|
||||
public void OnCellBorrowed(ButtonCell cell)
|
||||
{
|
||||
var button = rect.GetComponentInChildren<Button>();
|
||||
var text = button.GetComponentInChildren<Text>();
|
||||
var cell = new ButtonCell<T>(this, rect.gameObject, button, text);
|
||||
cell.OnClick += OnCellClicked;
|
||||
return cell;
|
||||
}
|
||||
|
||||
public void SetCell(ICell cell, int index)
|
||||
public void OnCellReturned(ButtonCell cell)
|
||||
{
|
||||
cell.OnClick -= OnCellClicked;
|
||||
}
|
||||
|
||||
public void SetCell(ButtonCell cell, int index)
|
||||
{
|
||||
if (currentEntries == null)
|
||||
RefreshData();
|
||||
@ -89,11 +82,11 @@ namespace UnityExplorer.UI.Widgets
|
||||
else
|
||||
{
|
||||
cell.Enable();
|
||||
(cell as ButtonCell<T>).CurrentDataIndex = index;
|
||||
SetICell.Invoke((ButtonCell<T>)cell, index);
|
||||
cell.CurrentDataIndex = index;
|
||||
SetICell.Invoke(cell, index);
|
||||
}
|
||||
}
|
||||
|
||||
public void DisableCell(ICell cell, int index) => cell.Disable();
|
||||
public void DisableCell(ButtonCell cell, int index) => cell.Disable();
|
||||
}
|
||||
}
|
||||
|
26
src/UI/Widgets/ButtonRef.cs
Normal file
26
src/UI/Widgets/ButtonRef.cs
Normal file
@ -0,0 +1,26 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace UnityExplorer.UI.Widgets
|
||||
{
|
||||
// A simple helper class to handle a button's OnClick more effectively.
|
||||
|
||||
public class ButtonRef
|
||||
{
|
||||
public Action OnClick;
|
||||
|
||||
public Button Button { get; }
|
||||
public Text ButtonText { get; }
|
||||
|
||||
public ButtonRef(Button button)
|
||||
{
|
||||
this.Button = button;
|
||||
this.ButtonText = button.GetComponentInChildren<Text>();
|
||||
|
||||
button.onClick.AddListener(() => { OnClick?.Invoke(); });
|
||||
}
|
||||
}
|
||||
}
|
@ -1,102 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.Core.Config;
|
||||
using UnityExplorer.UI.InteractiveValues;
|
||||
|
||||
namespace UnityExplorer.UI.CacheObject
|
||||
{
|
||||
public class CacheConfigEntry : CacheObjectBase
|
||||
{
|
||||
public IConfigElement RefConfig { get; }
|
||||
|
||||
public override Type FallbackType => RefConfig.ElementType;
|
||||
|
||||
public override bool HasEvaluated => true;
|
||||
public override bool HasParameters => false;
|
||||
public override bool IsMember => false;
|
||||
public override bool CanWrite => true;
|
||||
|
||||
public CacheConfigEntry(IConfigElement config, GameObject parent)
|
||||
{
|
||||
RefConfig = config;
|
||||
|
||||
m_parentContent = parent;
|
||||
|
||||
config.OnValueChangedNotify += () => { UpdateValue(); };
|
||||
|
||||
CreateIValue(config.BoxedValue, config.ElementType);
|
||||
}
|
||||
|
||||
public override void CreateIValue(object value, Type fallbackType)
|
||||
{
|
||||
IValue = InteractiveValue.Create(value, fallbackType);
|
||||
IValue.Owner = this;
|
||||
IValue.m_mainContentParent = m_mainGroup;
|
||||
IValue.m_subContentParent = this.SubContentGroup;
|
||||
}
|
||||
|
||||
public override void UpdateValue()
|
||||
{
|
||||
IValue.Value = RefConfig.BoxedValue;
|
||||
|
||||
base.UpdateValue();
|
||||
}
|
||||
|
||||
public override void SetValue()
|
||||
{
|
||||
RefConfig.BoxedValue = IValue.Value;
|
||||
}
|
||||
|
||||
internal GameObject m_mainGroup;
|
||||
|
||||
internal override void ConstructUI()
|
||||
{
|
||||
base.ConstructUI();
|
||||
|
||||
m_mainGroup = UIFactory.CreateVerticalGroup(UIRoot, "ConfigHolder", true, false, true, true, 5, new Vector4(2, 2, 2, 2));
|
||||
|
||||
var horiGroup = UIFactory.CreateHorizontalGroup(m_mainGroup, "ConfigEntryHolder", false, false, true, true, childAlignment: TextAnchor.MiddleLeft);
|
||||
UIFactory.SetLayoutElement(horiGroup, minHeight: 30, flexibleHeight: 0);
|
||||
|
||||
// config entry label
|
||||
|
||||
var configLabel = UIFactory.CreateLabel(horiGroup, "ConfigLabel", this.RefConfig.Name, TextAnchor.MiddleLeft);
|
||||
var leftRect = configLabel.GetComponent<RectTransform>();
|
||||
leftRect.anchorMin = Vector2.zero;
|
||||
leftRect.anchorMax = Vector2.one;
|
||||
leftRect.offsetMin = Vector2.zero;
|
||||
leftRect.offsetMax = Vector2.zero;
|
||||
leftRect.sizeDelta = Vector2.zero;
|
||||
UIFactory.SetLayoutElement(configLabel.gameObject, minWidth: 250, minHeight: 25, flexibleWidth: 0, flexibleHeight: 0);
|
||||
|
||||
// Default button
|
||||
|
||||
var defaultButton = UIFactory.CreateButton(horiGroup,
|
||||
"RevertDefaultButton",
|
||||
"Default",
|
||||
() => { RefConfig.RevertToDefaultValue(); },
|
||||
new Color(0.3f, 0.3f, 0.3f));
|
||||
UIFactory.SetLayoutElement(defaultButton.gameObject, minWidth: 80, minHeight: 22, flexibleWidth: 0);
|
||||
|
||||
// Description label
|
||||
|
||||
var desc = UIFactory.CreateLabel(m_mainGroup, "Description", $"<i>{RefConfig.Description}</i>", TextAnchor.MiddleLeft, Color.grey);
|
||||
UIFactory.SetLayoutElement(desc.gameObject, minWidth: 250, minHeight: 20, flexibleWidth: 9999, flexibleHeight: 0);
|
||||
|
||||
// IValue
|
||||
|
||||
if (IValue != null)
|
||||
{
|
||||
IValue.m_mainContentParent = m_mainGroup;
|
||||
IValue.m_subContentParent = this.SubContentGroup;
|
||||
}
|
||||
|
||||
// makes the subcontent look nicer
|
||||
SubContentGroup.transform.SetParent(m_mainGroup.transform, false);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,57 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityExplorer.UI;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.UI.InteractiveValues;
|
||||
|
||||
namespace UnityExplorer.UI.CacheObject
|
||||
{
|
||||
public class CacheEnumerated : CacheObjectBase
|
||||
{
|
||||
public override Type FallbackType => ParentEnumeration.m_baseEntryType;
|
||||
public override bool CanWrite => RefIList != null && ParentEnumeration.Owner.CanWrite;
|
||||
|
||||
public int Index { get; set; }
|
||||
public IList RefIList { get; set; }
|
||||
public InteractiveEnumerable ParentEnumeration { get; set; }
|
||||
|
||||
public CacheEnumerated(int index, InteractiveEnumerable parentEnumeration, IList refIList, GameObject parentContent)
|
||||
{
|
||||
this.ParentEnumeration = parentEnumeration;
|
||||
this.Index = index;
|
||||
this.RefIList = refIList;
|
||||
this.m_parentContent = parentContent;
|
||||
}
|
||||
|
||||
public override void CreateIValue(object value, Type fallbackType)
|
||||
{
|
||||
IValue = InteractiveValue.Create(value, fallbackType);
|
||||
IValue.Owner = this;
|
||||
}
|
||||
|
||||
public override void SetValue()
|
||||
{
|
||||
RefIList[Index] = IValue.Value;
|
||||
ParentEnumeration.Value = RefIList;
|
||||
|
||||
ParentEnumeration.Owner.SetValue();
|
||||
}
|
||||
|
||||
internal override void ConstructUI()
|
||||
{
|
||||
base.ConstructUI();
|
||||
|
||||
var rowObj = UIFactory.CreateHorizontalGroup(UIRoot, "CacheEnumeratedGroup", false, true, true, true, 0, new Vector4(0,0,5,2),
|
||||
new Color(1, 1, 1, 0));
|
||||
|
||||
var indexLabel = UIFactory.CreateLabel(rowObj, "IndexLabel", $"{this.Index}:", TextAnchor.MiddleLeft);
|
||||
UIFactory.SetLayoutElement(indexLabel.gameObject, minWidth: 20, flexibleWidth: 30, minHeight: 25);
|
||||
|
||||
IValue.m_mainContentParent = rowObj;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,40 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Reflection;
|
||||
using UnityExplorer.UI;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityExplorer.UI.CacheObject
|
||||
{
|
||||
public class CacheField : CacheMember
|
||||
{
|
||||
public override bool IsStatic => (MemInfo as FieldInfo).IsStatic;
|
||||
|
||||
public override Type FallbackType => (MemInfo as FieldInfo).FieldType;
|
||||
|
||||
public CacheField(FieldInfo fieldInfo, object declaringInstance, GameObject parent) : base(fieldInfo, declaringInstance, parent)
|
||||
{
|
||||
CreateIValue(null, fieldInfo.FieldType);
|
||||
}
|
||||
|
||||
public override void UpdateReflection()
|
||||
{
|
||||
var fi = MemInfo as FieldInfo;
|
||||
IValue.Value = fi.GetValue(fi.IsStatic ? null : DeclaringInstance);
|
||||
|
||||
m_evaluated = true;
|
||||
ReflectionException = null;
|
||||
}
|
||||
|
||||
public override void SetValue()
|
||||
{
|
||||
var fi = MemInfo as FieldInfo;
|
||||
fi.SetValue(fi.IsStatic ? null : DeclaringInstance, IValue.Value);
|
||||
|
||||
if (this.ParentInspector?.ParentMember != null)
|
||||
this.ParentInspector.ParentMember.SetValue();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,360 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.UI;
|
||||
using UnityExplorer.Core.Runtime;
|
||||
using UnityExplorer.Core;
|
||||
using UnityExplorer.UI.Utility;
|
||||
using UnityExplorer.UI.InteractiveValues;
|
||||
using UnityExplorer.UI.Inspectors.Reflection;
|
||||
using UnityExplorer.UI.Panels;
|
||||
|
||||
namespace UnityExplorer.UI.CacheObject
|
||||
{
|
||||
public abstract class CacheMember : CacheObjectBase
|
||||
{
|
||||
public override bool IsMember => true;
|
||||
|
||||
public override Type FallbackType { get; }
|
||||
|
||||
public ReflectionInspector ParentInspector { get; set; }
|
||||
public MemberInfo MemInfo { get; set; }
|
||||
public Type DeclaringType { get; set; }
|
||||
public object DeclaringInstance { get; set; }
|
||||
public virtual bool IsStatic { get; private set; }
|
||||
|
||||
public string ReflectionException { get; set; }
|
||||
|
||||
public override bool CanWrite => m_canWrite ?? GetCanWrite();
|
||||
private bool? m_canWrite;
|
||||
|
||||
public override bool HasParameters => ParamCount > 0;
|
||||
public virtual int ParamCount => m_arguments.Length;
|
||||
public override bool HasEvaluated => m_evaluated;
|
||||
public bool m_evaluated = false;
|
||||
public bool m_isEvaluating;
|
||||
public ParameterInfo[] m_arguments = new ParameterInfo[0];
|
||||
public string[] m_argumentInput = new string[0];
|
||||
|
||||
public string NameForFiltering => m_nameForFilter ?? (m_nameForFilter = $"{MemInfo.DeclaringType.Name}.{MemInfo.Name}".ToLower());
|
||||
private string m_nameForFilter;
|
||||
|
||||
public string RichTextName => m_richTextName ?? GetRichTextName();
|
||||
private string m_richTextName;
|
||||
|
||||
public CacheMember(MemberInfo memberInfo, object declaringInstance, GameObject parentContent)
|
||||
{
|
||||
MemInfo = memberInfo;
|
||||
DeclaringType = memberInfo.DeclaringType;
|
||||
DeclaringInstance = declaringInstance;
|
||||
this.m_parentContent = parentContent;
|
||||
|
||||
DeclaringInstance = ReflectionProvider.Instance.Cast(declaringInstance, DeclaringType);
|
||||
}
|
||||
|
||||
public override void Enable()
|
||||
{
|
||||
base.Enable();
|
||||
|
||||
ParentInspector.displayedMembers.Add(this);
|
||||
|
||||
memberLabelElement.minWidth = 0.4f * InspectorPanel.CurrentPanelWidth;
|
||||
}
|
||||
|
||||
public override void Disable()
|
||||
{
|
||||
base.Disable();
|
||||
|
||||
ParentInspector.displayedMembers.Remove(this);
|
||||
}
|
||||
|
||||
public static bool CanProcessArgs(ParameterInfo[] parameters)
|
||||
{
|
||||
foreach (var param in parameters)
|
||||
{
|
||||
var pType = param.ParameterType;
|
||||
|
||||
if (pType.IsByRef && pType.HasElementType)
|
||||
pType = pType.GetElementType();
|
||||
|
||||
if (pType != null && (pType.IsPrimitive || pType == typeof(string)))
|
||||
continue;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public override void CreateIValue(object value, Type fallbackType)
|
||||
{
|
||||
IValue = InteractiveValue.Create(value, fallbackType);
|
||||
IValue.Owner = this;
|
||||
IValue.m_mainContentParent = this.ContentGroup;
|
||||
IValue.m_subContentParent = this.SubContentGroup;
|
||||
}
|
||||
|
||||
public override void UpdateValue()
|
||||
{
|
||||
if (!HasParameters || m_isEvaluating)
|
||||
{
|
||||
try
|
||||
{
|
||||
Type baseType = ReflectionUtility.GetActualType(IValue.Value) ?? FallbackType;
|
||||
|
||||
if (!ReflectionProvider.Instance.IsReflectionSupported(baseType))
|
||||
throw new Exception("Type not supported with reflection");
|
||||
|
||||
UpdateReflection();
|
||||
|
||||
if (IValue.Value != null)
|
||||
IValue.Value = IValue.Value.TryCast(ReflectionUtility.GetActualType(IValue.Value));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
ReflectionException = e.ReflectionExToString(true);
|
||||
}
|
||||
}
|
||||
|
||||
base.UpdateValue();
|
||||
}
|
||||
|
||||
public abstract void UpdateReflection();
|
||||
|
||||
public override void SetValue()
|
||||
{
|
||||
// no implementation for base class
|
||||
}
|
||||
|
||||
public object[] ParseArguments()
|
||||
{
|
||||
if (m_arguments.Length < 1)
|
||||
return new object[0];
|
||||
|
||||
var parsedArgs = new List<object>();
|
||||
for (int i = 0; i < m_arguments.Length; i++)
|
||||
{
|
||||
var input = m_argumentInput[i];
|
||||
var type = m_arguments[i].ParameterType;
|
||||
|
||||
if (type.IsByRef)
|
||||
type = type.GetElementType();
|
||||
|
||||
if (!string.IsNullOrEmpty(input))
|
||||
{
|
||||
if (type == typeof(string))
|
||||
{
|
||||
parsedArgs.Add(input);
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
var arg = type.GetMethod("Parse", new Type[] { typeof(string) })
|
||||
.Invoke(null, new object[] { input });
|
||||
|
||||
parsedArgs.Add(arg);
|
||||
continue;
|
||||
}
|
||||
catch
|
||||
{
|
||||
ExplorerCore.Log($"Could not parse input '{input}' for argument #{i} '{m_arguments[i].Name}' ({type.FullName})");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// No input, see if there is a default value.
|
||||
if (m_arguments[i].IsOptional)
|
||||
{
|
||||
parsedArgs.Add(m_arguments[i].DefaultValue);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Try add a null arg I guess
|
||||
parsedArgs.Add(null);
|
||||
}
|
||||
|
||||
return parsedArgs.ToArray();
|
||||
}
|
||||
|
||||
private bool GetCanWrite()
|
||||
{
|
||||
if (MemInfo is FieldInfo fi)
|
||||
m_canWrite = !(fi.IsLiteral && !fi.IsInitOnly);
|
||||
else if (MemInfo is PropertyInfo pi)
|
||||
m_canWrite = pi.CanWrite;
|
||||
else
|
||||
m_canWrite = false;
|
||||
|
||||
return (bool)m_canWrite;
|
||||
}
|
||||
|
||||
private string GetRichTextName()
|
||||
{
|
||||
return m_richTextName = SignatureHighlighter.ParseFullSyntax(MemInfo.DeclaringType, false, MemInfo);
|
||||
}
|
||||
|
||||
#region UI
|
||||
|
||||
internal Text memberLabelText;
|
||||
internal GameObject ContentGroup;
|
||||
|
||||
internal LayoutElement memberLabelElement;
|
||||
|
||||
internal override void ConstructUI()
|
||||
{
|
||||
base.ConstructUI();
|
||||
|
||||
var horiGroup = UIFactory.CreateUIObject("HoriGroup", UIRoot);
|
||||
var groupRect = horiGroup.GetComponent<RectTransform>();
|
||||
groupRect.pivot = new Vector2(0, 1);
|
||||
groupRect.anchorMin = Vector2.zero;
|
||||
groupRect.anchorMax = Vector2.one;
|
||||
UIFactory.SetLayoutElement(horiGroup, minHeight: 30, flexibleHeight: 9999);
|
||||
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(horiGroup, true, true, true, true, 2, 2, 2, 2, 2, childAlignment: TextAnchor.UpperLeft);
|
||||
|
||||
memberLabelText = UIFactory.CreateLabel(horiGroup, "MemLabelText", RichTextName, TextAnchor.UpperLeft);
|
||||
memberLabelText.horizontalOverflow = HorizontalWrapMode.Wrap;
|
||||
UIFactory.SetLayoutElement(memberLabelText.gameObject, minHeight: 25, flexibleHeight: 9999, minWidth: 150, flexibleWidth: 0);
|
||||
|
||||
memberLabelElement = memberLabelText.GetComponent<LayoutElement>();
|
||||
|
||||
ContentGroup = UIFactory.CreateUIObject("ContentGroup", horiGroup, default);
|
||||
UIFactory.SetLayoutElement(ContentGroup, minHeight: 30, flexibleWidth: 9999);
|
||||
var contentRect = ContentGroup.GetComponent<RectTransform>();
|
||||
contentRect.pivot = new Vector2(0, 1);
|
||||
contentRect.anchorMin = new Vector2(0, 0);
|
||||
contentRect.anchorMax = new Vector2(1, 1);
|
||||
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(ContentGroup, false, false, true, true, childAlignment: TextAnchor.MiddleLeft);
|
||||
|
||||
ConstructArgInput(out GameObject argsHolder);
|
||||
|
||||
ConstructEvaluateButtons(argsHolder);
|
||||
|
||||
IValue.m_mainContentParent = this.ContentGroup;
|
||||
|
||||
//RightContentGroup.SetActive(false);
|
||||
|
||||
// ParentInspector.CacheObjectContents.Add(this.m_mainContent);
|
||||
}
|
||||
|
||||
internal void ConstructArgInput(out GameObject argsHolder)
|
||||
{
|
||||
argsHolder = null;
|
||||
|
||||
if (HasParameters)
|
||||
{
|
||||
argsHolder = UIFactory.CreateVerticalGroup(ContentGroup, "ArgsHolder", true, false, true, true, 4, new Color(1, 1, 1, 0));
|
||||
|
||||
if (this is CacheMethod cm && cm.GenericArgs.Length > 0)
|
||||
cm.ConstructGenericArgInput(argsHolder);
|
||||
|
||||
if (m_arguments.Length > 0)
|
||||
{
|
||||
UIFactory.CreateLabel(argsHolder, "ArgumentsLabel", "Arguments:", TextAnchor.MiddleLeft);
|
||||
|
||||
for (int i = 0; i < m_arguments.Length; i++)
|
||||
AddArgRow(i, argsHolder);
|
||||
}
|
||||
|
||||
argsHolder.SetActive(false);
|
||||
}
|
||||
}
|
||||
|
||||
internal void AddArgRow(int i, GameObject parent)
|
||||
{
|
||||
var arg = m_arguments[i];
|
||||
|
||||
var rowObj = UIFactory.CreateHorizontalGroup(parent, "ArgRow", true, false, true, true, 4, default, new Color(1, 1, 1, 0));
|
||||
UIFactory.SetLayoutElement(rowObj, minHeight: 25, flexibleWidth: 5000);
|
||||
|
||||
var argTypeTxt = SignatureHighlighter.ParseFullSyntax(arg.ParameterType, false);
|
||||
var argLabel = UIFactory.CreateLabel(rowObj, "ArgLabel", $"{argTypeTxt} <color={SignatureHighlighter.LOCAL_ARG}>{arg.Name}</color>",
|
||||
TextAnchor.MiddleLeft);
|
||||
UIFactory.SetLayoutElement(argLabel.gameObject, minHeight: 25);
|
||||
|
||||
var argInputObj = UIFactory.CreateInputField(rowObj, "ArgInput", "...", out InputField argInput, 14, (int)TextAnchor.MiddleLeft, 1);
|
||||
UIFactory.SetLayoutElement(argInputObj, flexibleWidth: 1200, preferredWidth: 150, minWidth: 20, minHeight: 25, flexibleHeight: 0);
|
||||
|
||||
argInput.onValueChanged.AddListener((string val) => { m_argumentInput[i] = val; });
|
||||
|
||||
if (arg.IsOptional)
|
||||
{
|
||||
var phInput = argInput.placeholder.GetComponent<Text>();
|
||||
phInput.text = " = " + arg.DefaultValue?.ToString() ?? "null";
|
||||
}
|
||||
}
|
||||
|
||||
internal void ConstructEvaluateButtons(GameObject argsHolder)
|
||||
{
|
||||
if (HasParameters)
|
||||
{
|
||||
var evalGroupObj = UIFactory.CreateHorizontalGroup(ContentGroup, "EvalGroup", false, false, true, true, 5,
|
||||
default, new Color(1, 1, 1, 0));
|
||||
UIFactory.SetLayoutElement(evalGroupObj, minHeight: 25, flexibleHeight: 0, flexibleWidth: 5000);
|
||||
|
||||
var evalButton = UIFactory.CreateButton(evalGroupObj,
|
||||
"EvalButton",
|
||||
$"Evaluate ({ParamCount})",
|
||||
null);
|
||||
|
||||
RuntimeProvider.Instance.SetColorBlock(evalButton, new Color(0.4f, 0.4f, 0.4f),
|
||||
new Color(0.4f, 0.7f, 0.4f), new Color(0.3f, 0.3f, 0.3f));
|
||||
|
||||
UIFactory.SetLayoutElement(evalButton.gameObject, minWidth: 100, minHeight: 22, flexibleWidth: 0);
|
||||
|
||||
var evalText = evalButton.GetComponentInChildren<Text>();
|
||||
|
||||
var cancelButton = UIFactory.CreateButton(evalGroupObj, "CancelButton", "Close", null, new Color(0.3f, 0.3f, 0.3f));
|
||||
UIFactory.SetLayoutElement(cancelButton.gameObject, minWidth: 100, minHeight: 22, flexibleWidth: 0);
|
||||
|
||||
cancelButton.gameObject.SetActive(false);
|
||||
|
||||
evalButton.onClick.AddListener(() =>
|
||||
{
|
||||
if (!m_isEvaluating)
|
||||
{
|
||||
argsHolder.SetActive(true);
|
||||
m_isEvaluating = true;
|
||||
evalText.text = "Evaluate";
|
||||
RuntimeProvider.Instance.SetColorBlock(evalButton, new Color(0.3f, 0.6f, 0.3f));
|
||||
|
||||
cancelButton.gameObject.SetActive(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (this is CacheMethod cm)
|
||||
cm.Evaluate();
|
||||
else
|
||||
UpdateValue();
|
||||
}
|
||||
});
|
||||
|
||||
cancelButton.onClick.AddListener(() =>
|
||||
{
|
||||
cancelButton.gameObject.SetActive(false);
|
||||
argsHolder.SetActive(false);
|
||||
m_isEvaluating = false;
|
||||
|
||||
evalText.text = $"Evaluate ({ParamCount})";
|
||||
RuntimeProvider.Instance.SetColorBlock(evalButton, new Color(0.4f, 0.4f, 0.4f));
|
||||
});
|
||||
}
|
||||
else if (this is CacheMethod)
|
||||
{
|
||||
// simple method evaluate button
|
||||
|
||||
var evalButton = UIFactory.CreateButton(ContentGroup, "EvalButton", "Evaluate", () => { (this as CacheMethod).Evaluate(); });
|
||||
RuntimeProvider.Instance.SetColorBlock(evalButton, new Color(0.4f, 0.4f, 0.4f),
|
||||
new Color(0.4f, 0.7f, 0.4f), new Color(0.3f, 0.3f, 0.3f));
|
||||
|
||||
UIFactory.SetLayoutElement(evalButton.gameObject, minWidth: 100, minHeight: 22, flexibleWidth: 0);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
@ -1,170 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.UI;
|
||||
using UnityExplorer.Core;
|
||||
using UnityExplorer.UI.Utility;
|
||||
|
||||
namespace UnityExplorer.UI.CacheObject
|
||||
{
|
||||
public class CacheMethod : CacheMember
|
||||
{
|
||||
//private CacheObjectBase m_cachedReturnValue;
|
||||
|
||||
public override Type FallbackType => (MemInfo as MethodInfo).ReturnType;
|
||||
|
||||
public override bool HasParameters => base.HasParameters || GenericArgs.Length > 0;
|
||||
|
||||
public override bool IsStatic => (MemInfo as MethodInfo).IsStatic;
|
||||
|
||||
public override int ParamCount => base.ParamCount + m_genericArgInput.Length;
|
||||
|
||||
public Type[] GenericArgs { get; private set; }
|
||||
public Type[][] GenericConstraints { get; private set; }
|
||||
|
||||
public string[] m_genericArgInput = new string[0];
|
||||
|
||||
public CacheMethod(MethodInfo methodInfo, object declaringInstance, GameObject parent) : base(methodInfo, declaringInstance, parent)
|
||||
{
|
||||
GenericArgs = methodInfo.GetGenericArguments();
|
||||
|
||||
GenericConstraints = GenericArgs.Select(x => x.GetGenericParameterConstraints())
|
||||
.Where(x => x != null)
|
||||
.ToArray();
|
||||
|
||||
m_genericArgInput = new string[GenericArgs.Length];
|
||||
|
||||
m_arguments = methodInfo.GetParameters();
|
||||
m_argumentInput = new string[m_arguments.Length];
|
||||
|
||||
CreateIValue(null, methodInfo.ReturnType);
|
||||
}
|
||||
|
||||
public override void UpdateReflection()
|
||||
{
|
||||
// CacheMethod cannot UpdateValue directly. Need to Evaluate.
|
||||
}
|
||||
|
||||
public void Evaluate()
|
||||
{
|
||||
MethodInfo mi;
|
||||
if (GenericArgs.Length > 0)
|
||||
{
|
||||
mi = MakeGenericMethodFromInput();
|
||||
if (mi == null) return;
|
||||
}
|
||||
else
|
||||
{
|
||||
mi = MemInfo as MethodInfo;
|
||||
}
|
||||
|
||||
object ret = null;
|
||||
|
||||
try
|
||||
{
|
||||
ret = mi.Invoke(mi.IsStatic ? null : DeclaringInstance, ParseArguments());
|
||||
m_evaluated = true;
|
||||
m_isEvaluating = false;
|
||||
ReflectionException = null;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
while (e.InnerException != null)
|
||||
e = e.InnerException;
|
||||
|
||||
ExplorerCore.LogWarning($"Exception evaluating: {e.GetType()}, {e.Message}");
|
||||
ReflectionException = ReflectionUtility.ReflectionExToString(e);
|
||||
}
|
||||
|
||||
IValue.Value = ret;
|
||||
UpdateValue();
|
||||
}
|
||||
|
||||
private MethodInfo MakeGenericMethodFromInput()
|
||||
{
|
||||
var mi = MemInfo as MethodInfo;
|
||||
|
||||
var list = new List<Type>();
|
||||
for (int i = 0; i < GenericArgs.Length; i++)
|
||||
{
|
||||
var input = m_genericArgInput[i];
|
||||
if (ReflectionUtility.GetTypeByName(input) is Type t)
|
||||
{
|
||||
if (GenericConstraints[i].Length == 0)
|
||||
{
|
||||
list.Add(t);
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var constraint in GenericConstraints[i].Where(x => x != null))
|
||||
{
|
||||
if (!constraint.IsAssignableFrom(t))
|
||||
{
|
||||
ExplorerCore.LogWarning($"Generic argument #{i}, '{input}' is not assignable from the constraint '{constraint}'!");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
list.Add(t);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ExplorerCore.LogWarning($"Generic argument #{i}, could not get any type by the name of '{input}'!" +
|
||||
$" Make sure you use the full name including the namespace.");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// make into a generic with type list
|
||||
mi = mi.MakeGenericMethod(list.ToArray());
|
||||
|
||||
return mi;
|
||||
}
|
||||
|
||||
#region UI CONSTRUCTION
|
||||
|
||||
internal void ConstructGenericArgInput(GameObject parent)
|
||||
{
|
||||
UIFactory.CreateLabel(parent, "GenericArgLabel", "Generic Arguments:", TextAnchor.MiddleLeft);
|
||||
|
||||
for (int i = 0; i < GenericArgs.Length; i++)
|
||||
AddGenericArgRow(i, parent);
|
||||
}
|
||||
|
||||
internal void AddGenericArgRow(int i, GameObject parent)
|
||||
{
|
||||
var arg = GenericArgs[i];
|
||||
|
||||
string constrainTxt = "";
|
||||
if (this.GenericConstraints[i].Length > 0)
|
||||
{
|
||||
foreach (var constraint in this.GenericConstraints[i])
|
||||
{
|
||||
if (constrainTxt != "")
|
||||
constrainTxt += ", ";
|
||||
|
||||
constrainTxt += $"{SignatureHighlighter.ParseFullSyntax(constraint, false)}";
|
||||
}
|
||||
}
|
||||
else
|
||||
constrainTxt = $"Any";
|
||||
|
||||
var rowObj = UIFactory.CreateHorizontalGroup(parent, "ArgRowObj", false, true, true, true, 4, default, new Color(1, 1, 1, 0));
|
||||
UIFactory.SetLayoutElement(rowObj, minHeight: 25, flexibleWidth: 5000);
|
||||
|
||||
var argLabelObj = UIFactory.CreateLabel(rowObj, "ArgLabelObj", $"{constrainTxt} <color={SignatureHighlighter.CONST_VAR}>{arg.Name}</color>",
|
||||
TextAnchor.MiddleLeft);
|
||||
|
||||
var argInputObj = UIFactory.CreateInputField(rowObj, "ArgInput", "...", out InputField argInput, 14, (int)TextAnchor.MiddleLeft, 1);
|
||||
UIFactory.SetLayoutElement(argInputObj, flexibleWidth: 1200);
|
||||
argInput.onValueChanged.AddListener((string val) => { m_genericArgInput[i] = val; });
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
@ -1,120 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using UnityEngine;
|
||||
using UnityExplorer.UI;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.Core;
|
||||
using UnityExplorer.UI.InteractiveValues;
|
||||
using UnityExplorer.UI.Widgets;
|
||||
|
||||
namespace UnityExplorer.UI.CacheObject
|
||||
{
|
||||
public abstract class CacheObjectBase
|
||||
{
|
||||
public InteractiveValue IValue;
|
||||
|
||||
public virtual bool CanWrite => false;
|
||||
public virtual bool HasParameters => false;
|
||||
public virtual bool IsMember => false;
|
||||
public virtual bool HasEvaluated => true;
|
||||
|
||||
public abstract Type FallbackType { get; }
|
||||
|
||||
public abstract void CreateIValue(object value, Type fallbackType);
|
||||
|
||||
public virtual void Enable()
|
||||
{
|
||||
if (!m_constructedUI)
|
||||
{
|
||||
ConstructUI();
|
||||
UpdateValue();
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void Disable()
|
||||
{
|
||||
if (UIRoot)
|
||||
UIRoot.SetActive(false);
|
||||
}
|
||||
|
||||
public void Destroy()
|
||||
{
|
||||
if (this.UIRoot)
|
||||
GameObject.Destroy(this.UIRoot);
|
||||
}
|
||||
|
||||
public virtual void UpdateValue()
|
||||
{
|
||||
var value = IValue.Value;
|
||||
|
||||
// if the type has changed fundamentally, make a new interactivevalue for it
|
||||
var type = value == null
|
||||
? FallbackType
|
||||
: ReflectionUtility.GetActualType(value);
|
||||
|
||||
var ivalueType = InteractiveValue.GetIValueForType(type);
|
||||
|
||||
if (ivalueType != IValue.GetType())
|
||||
{
|
||||
IValue.OnDestroy();
|
||||
CreateIValue(value, FallbackType);
|
||||
SubContentGroup.SetActive(false);
|
||||
}
|
||||
|
||||
IValue.OnValueUpdated();
|
||||
|
||||
IValue.RefreshElementsAfterUpdate();
|
||||
}
|
||||
|
||||
public virtual void SetValue() => throw new NotImplementedException();
|
||||
|
||||
#region UI CONSTRUCTION
|
||||
|
||||
internal bool m_constructedUI;
|
||||
internal GameObject m_parentContent;
|
||||
internal RectTransform m_mainRect;
|
||||
internal GameObject UIRoot;
|
||||
|
||||
internal GameObject SubContentGroup;
|
||||
internal bool constructedSubcontent;
|
||||
|
||||
// Make base UI holder for CacheObject, this doesnt actually display anything.
|
||||
internal virtual void ConstructUI()
|
||||
{
|
||||
m_constructedUI = true;
|
||||
|
||||
//UIRoot = UIFactory.CreateVerticalGroup(m_parentContent, $"{this.GetType().Name}.MainContent", true, true, true, true, 2,
|
||||
// new Vector4(0, 5, 0, 0), new Color(0.1f, 0.1f, 0.1f), TextAnchor.UpperLeft);
|
||||
|
||||
UIRoot = UIFactory.CreateUIObject($"{this.GetType().Name}.MainContent", m_parentContent);
|
||||
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(UIRoot, true, true, true, true, 2, 0, 5, 0, 0, TextAnchor.UpperLeft);
|
||||
m_mainRect = UIRoot.GetComponent<RectTransform>();
|
||||
m_mainRect.pivot = new Vector2(0, 1);
|
||||
m_mainRect.anchorMin = Vector2.zero;
|
||||
m_mainRect.anchorMax = Vector2.one;
|
||||
UIFactory.SetLayoutElement(UIRoot, minHeight: 30, flexibleHeight: 9999, minWidth: 200, flexibleWidth: 5000);
|
||||
|
||||
SubContentGroup = new GameObject("SubContent");
|
||||
SubContentGroup.transform.parent = UIRoot.transform;
|
||||
UIFactory.SetLayoutElement(SubContentGroup, minHeight: 30, flexibleHeight: 9999, minWidth: 125, flexibleWidth: 9000);
|
||||
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(SubContentGroup, true, false, true, true);
|
||||
SubContentGroup.SetActive(false);
|
||||
|
||||
IValue.m_subContentParent = SubContentGroup;
|
||||
}
|
||||
|
||||
public virtual void CheckSubcontentCreation()
|
||||
{
|
||||
if (!constructedSubcontent)
|
||||
{
|
||||
SubContentGroup.AddComponent<Image>().color = new Color(0.08f, 0.08f, 0.08f);
|
||||
constructedSubcontent = true;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
@ -1,72 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityExplorer.UI;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.UI.InteractiveValues;
|
||||
|
||||
namespace UnityExplorer.UI.CacheObject
|
||||
{
|
||||
public enum PairTypes
|
||||
{
|
||||
Key,
|
||||
Value
|
||||
}
|
||||
|
||||
public class CachePaired : CacheObjectBase
|
||||
{
|
||||
public override Type FallbackType => PairType == PairTypes.Key
|
||||
? ParentDictionary.m_typeOfKeys
|
||||
: ParentDictionary.m_typeofValues;
|
||||
|
||||
public override bool CanWrite => false; // todo?
|
||||
|
||||
public PairTypes PairType;
|
||||
public int Index { get; private set; }
|
||||
public InteractiveDictionary ParentDictionary { get; private set; }
|
||||
internal IDictionary RefIDict;
|
||||
|
||||
public CachePaired(int index, InteractiveDictionary parentDict, IDictionary refIDict, PairTypes pairType, GameObject parentContent)
|
||||
{
|
||||
Index = index;
|
||||
ParentDictionary = parentDict;
|
||||
RefIDict = refIDict;
|
||||
this.PairType = pairType;
|
||||
this.m_parentContent = parentContent;
|
||||
}
|
||||
|
||||
public override void CreateIValue(object value, Type fallbackType)
|
||||
{
|
||||
IValue = InteractiveValue.Create(value, fallbackType);
|
||||
IValue.Owner = this;
|
||||
}
|
||||
|
||||
#region UI CONSTRUCTION
|
||||
|
||||
internal override void ConstructUI()
|
||||
{
|
||||
base.ConstructUI();
|
||||
|
||||
Color bgColor = this.PairType == PairTypes.Key
|
||||
? new Color(0.07f, 0.07f, 0.07f)
|
||||
: new Color(0.1f, 0.1f, 0.1f);
|
||||
|
||||
var rowObj = UIFactory.CreateHorizontalGroup(UIRoot, "PairedGroup", false, false, true, true, 0, new Vector4(0,0,5,2),
|
||||
bgColor);
|
||||
|
||||
string lbl = $"{this.PairType}";
|
||||
if (this.PairType == PairTypes.Key)
|
||||
lbl = $"[{Index}] {lbl}";
|
||||
|
||||
var indexLabel = UIFactory.CreateLabel(rowObj, "IndexLabel", lbl, TextAnchor.MiddleLeft);
|
||||
UIFactory.SetLayoutElement(indexLabel.gameObject, minWidth: 80, flexibleWidth: 30, minHeight: 25);
|
||||
|
||||
IValue.m_mainContentParent = rowObj;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
@ -1,70 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Reflection;
|
||||
using UnityExplorer.UI;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityExplorer.UI.CacheObject
|
||||
{
|
||||
public class CacheProperty : CacheMember
|
||||
{
|
||||
public override Type FallbackType => (MemInfo as PropertyInfo).PropertyType;
|
||||
|
||||
public override bool IsStatic => (MemInfo as PropertyInfo).GetAccessors(true)[0].IsStatic;
|
||||
|
||||
public CacheProperty(PropertyInfo propertyInfo, object declaringInstance, GameObject parent) : base(propertyInfo, declaringInstance, parent)
|
||||
{
|
||||
this.m_arguments = propertyInfo.GetIndexParameters();
|
||||
this.m_argumentInput = new string[m_arguments.Length];
|
||||
|
||||
CreateIValue(null, propertyInfo.PropertyType);
|
||||
}
|
||||
|
||||
public override void UpdateReflection()
|
||||
{
|
||||
if (HasParameters && !m_isEvaluating)
|
||||
{
|
||||
// Need to enter parameters first.
|
||||
return;
|
||||
}
|
||||
|
||||
var pi = MemInfo as PropertyInfo;
|
||||
|
||||
if (pi.CanRead)
|
||||
{
|
||||
var target = pi.GetAccessors(true)[0].IsStatic ? null : DeclaringInstance;
|
||||
|
||||
IValue.Value = pi.GetValue(target, ParseArguments());
|
||||
|
||||
m_evaluated = true;
|
||||
ReflectionException = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (FallbackType == typeof(string))
|
||||
{
|
||||
IValue.Value = "";
|
||||
}
|
||||
else if (FallbackType.IsPrimitive)
|
||||
{
|
||||
IValue.Value = Activator.CreateInstance(FallbackType);
|
||||
}
|
||||
m_evaluated = true;
|
||||
ReflectionException = null;
|
||||
}
|
||||
}
|
||||
|
||||
public override void SetValue()
|
||||
{
|
||||
var pi = MemInfo as PropertyInfo;
|
||||
var target = pi.GetAccessors()[0].IsStatic ? null : DeclaringInstance;
|
||||
|
||||
pi.SetValue(target, IValue.Value, ParseArguments());
|
||||
|
||||
if (this.ParentInspector?.ParentMember != null)
|
||||
this.ParentInspector.ParentMember.SetValue();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,110 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.UI;
|
||||
using UnityExplorer.UI.CacheObject;
|
||||
|
||||
namespace UnityExplorer.UI.InteractiveValues
|
||||
{
|
||||
public class InteractiveBool : InteractiveValue
|
||||
{
|
||||
public InteractiveBool(object value, Type valueType) : base(value, valueType) { }
|
||||
|
||||
public override bool HasSubContent => false;
|
||||
public override bool SubContentWanted => false;
|
||||
public override bool WantInspectBtn => false;
|
||||
|
||||
internal Toggle m_toggle;
|
||||
internal Button m_applyBtn;
|
||||
|
||||
public override void OnValueUpdated()
|
||||
{
|
||||
base.OnValueUpdated();
|
||||
}
|
||||
|
||||
public override void RefreshUIForValue()
|
||||
{
|
||||
GetDefaultLabel();
|
||||
|
||||
if (Owner.HasEvaluated)
|
||||
{
|
||||
var val = (bool)Value;
|
||||
|
||||
if (!m_toggle.gameObject.activeSelf)
|
||||
m_toggle.gameObject.SetActive(true);
|
||||
|
||||
if (val != m_toggle.isOn)
|
||||
m_toggle.isOn = val;
|
||||
|
||||
if (Owner.CanWrite)
|
||||
{
|
||||
if (!m_applyBtn.gameObject.activeSelf)
|
||||
m_applyBtn.gameObject.SetActive(true);
|
||||
}
|
||||
|
||||
var color = val
|
||||
? "6bc981" // on
|
||||
: "c96b6b"; // off
|
||||
|
||||
m_baseLabel.text = $"<color=#{color}>{val}</color>";
|
||||
}
|
||||
else
|
||||
{
|
||||
m_baseLabel.text = DefaultLabel;
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnException(CacheMember member)
|
||||
{
|
||||
base.OnException(member);
|
||||
|
||||
if (Owner.CanWrite)
|
||||
{
|
||||
if (m_toggle.gameObject.activeSelf)
|
||||
m_toggle.gameObject.SetActive(false);
|
||||
|
||||
if (m_applyBtn.gameObject.activeSelf)
|
||||
m_applyBtn.gameObject.SetActive(false);
|
||||
}
|
||||
}
|
||||
|
||||
internal void OnToggleValueChanged(bool val)
|
||||
{
|
||||
Value = val;
|
||||
RefreshUIForValue();
|
||||
}
|
||||
|
||||
public override void ConstructUI(GameObject parent, GameObject subGroup)
|
||||
{
|
||||
base.ConstructUI(parent, subGroup);
|
||||
|
||||
var baseLayout = m_baseLabel.gameObject.GetComponent<LayoutElement>();
|
||||
baseLayout.flexibleWidth = 0;
|
||||
baseLayout.minWidth = 50;
|
||||
|
||||
var toggleObj = UIFactory.CreateToggle(m_mainContent, "InteractiveBoolToggle", out m_toggle, out _, new Color(0.1f, 0.1f, 0.1f));
|
||||
UIFactory.SetLayoutElement(toggleObj, minWidth: 24);
|
||||
m_toggle.onValueChanged.AddListener(OnToggleValueChanged);
|
||||
|
||||
m_baseLabel.transform.SetAsLastSibling();
|
||||
|
||||
m_applyBtn = UIFactory.CreateButton(m_mainContent,
|
||||
"ApplyButton",
|
||||
"Apply",
|
||||
() => { Owner.SetValue(); },
|
||||
new Color(0.2f, 0.2f, 0.2f));
|
||||
|
||||
UIFactory.SetLayoutElement(m_applyBtn.gameObject, minWidth: 50, minHeight: 25, flexibleWidth: 0);
|
||||
|
||||
toggleObj.SetActive(false);
|
||||
|
||||
if (!Owner.CanWrite)
|
||||
m_toggle.interactable = false;
|
||||
|
||||
m_applyBtn.gameObject.SetActive(false);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,167 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace UnityExplorer.UI.InteractiveValues
|
||||
{
|
||||
public class InteractiveColor : InteractiveValue
|
||||
{
|
||||
//~~~~~~~~~ Instance ~~~~~~~~~~
|
||||
|
||||
public InteractiveColor(object value, Type valueType) : base(value, valueType) { }
|
||||
|
||||
public override bool HasSubContent => true;
|
||||
public override bool SubContentWanted => true;
|
||||
public override bool WantInspectBtn => true;
|
||||
|
||||
public override void RefreshUIForValue()
|
||||
{
|
||||
base.RefreshUIForValue();
|
||||
|
||||
if (m_subContentConstructed)
|
||||
RefreshUI();
|
||||
}
|
||||
|
||||
private void RefreshUI()
|
||||
{
|
||||
var color = (Color)this.Value;
|
||||
|
||||
m_inputs[0].text = color.r.ToString();
|
||||
m_inputs[1].text = color.g.ToString();
|
||||
m_inputs[2].text = color.b.ToString();
|
||||
m_inputs[3].text = color.a.ToString();
|
||||
|
||||
if (m_colorImage)
|
||||
m_colorImage.color = color;
|
||||
}
|
||||
|
||||
internal override void OnToggleSubcontent(bool toggle)
|
||||
{
|
||||
base.OnToggleSubcontent(toggle);
|
||||
|
||||
RefreshUI();
|
||||
}
|
||||
|
||||
#region UI CONSTRUCTION
|
||||
|
||||
private Image m_colorImage;
|
||||
|
||||
private readonly InputField[] m_inputs = new InputField[4];
|
||||
private readonly Slider[] m_sliders = new Slider[4];
|
||||
|
||||
public override void ConstructUI(GameObject parent, GameObject subGroup)
|
||||
{
|
||||
base.ConstructUI(parent, subGroup);
|
||||
|
||||
//// Limit the label width for colors, they're always about the same so make use of that space.
|
||||
//UIFactory.SetLayoutElement(this.m_baseLabel.gameObject, flexibleWidth: 0, minWidth: 250);
|
||||
}
|
||||
|
||||
public override void ConstructSubcontent()
|
||||
{
|
||||
base.ConstructSubcontent();
|
||||
|
||||
var horiGroup = UIFactory.CreateHorizontalGroup(m_subContentParent, "ColorEditor", false, false, true, true, 5,
|
||||
default, default, TextAnchor.MiddleLeft);
|
||||
|
||||
var editorContainer = UIFactory.CreateVerticalGroup(horiGroup, "EditorContent", false, true, true, true, 2, new Vector4(4, 4, 4, 4),
|
||||
new Color(0.08f, 0.08f, 0.08f));
|
||||
UIFactory.SetLayoutElement(editorContainer, minWidth: 300, flexibleWidth: 0);
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
AddEditorRow(i, editorContainer);
|
||||
|
||||
if (Owner.CanWrite)
|
||||
{
|
||||
var applyBtn = UIFactory.CreateButton(editorContainer, "ApplyButton", "Apply", OnSetValue, new Color(0.2f, 0.2f, 0.2f));
|
||||
UIFactory.SetLayoutElement(applyBtn.gameObject, minWidth: 175, minHeight: 25, flexibleWidth: 0);
|
||||
|
||||
void OnSetValue()
|
||||
{
|
||||
Owner.SetValue();
|
||||
RefreshUIForValue();
|
||||
}
|
||||
}
|
||||
|
||||
var imgHolder = UIFactory.CreateVerticalGroup(horiGroup, "ImgHolder", true, true, true, true, 0, new Vector4(1, 1, 1, 1),
|
||||
new Color(0.08f, 0.08f, 0.08f));
|
||||
UIFactory.SetLayoutElement(imgHolder, minWidth: 128, minHeight: 128, flexibleWidth: 0, flexibleHeight: 0);
|
||||
|
||||
var imgObj = UIFactory.CreateUIObject("ColorImageHelper", imgHolder, new Vector2(100, 25));
|
||||
m_colorImage = imgObj.AddComponent<Image>();
|
||||
m_colorImage.color = (Color)this.Value;
|
||||
}
|
||||
|
||||
private static readonly string[] s_fieldNames = new[] { "R", "G", "B", "A" };
|
||||
|
||||
internal void AddEditorRow(int index, GameObject groupObj)
|
||||
{
|
||||
var row = UIFactory.CreateHorizontalGroup(groupObj, "EditorRow_" + s_fieldNames[index],
|
||||
false, true, true, true, 5, default, new Color(1, 1, 1, 0));
|
||||
|
||||
var label = UIFactory.CreateLabel(row, "RowLabel", $"{s_fieldNames[index]}:", TextAnchor.MiddleRight, Color.cyan);
|
||||
UIFactory.SetLayoutElement(label.gameObject, minWidth: 50, flexibleWidth: 0, minHeight: 25);
|
||||
|
||||
var inputFieldObj = UIFactory.CreateInputField(row, "InputField", "...", out InputField inputField, 14, 3, 1);
|
||||
UIFactory.SetLayoutElement(inputFieldObj, minWidth: 120, minHeight: 25, flexibleWidth: 0);
|
||||
|
||||
m_inputs[index] = inputField;
|
||||
inputField.characterValidation = InputField.CharacterValidation.Decimal;
|
||||
|
||||
inputField.onValueChanged.AddListener((string value) =>
|
||||
{
|
||||
float val = float.Parse(value);
|
||||
SetValueToColor(val);
|
||||
m_sliders[index].value = val;
|
||||
});
|
||||
|
||||
var sliderObj = UIFactory.CreateSlider(row, "Slider", out Slider slider);
|
||||
m_sliders[index] = slider;
|
||||
UIFactory.SetLayoutElement(sliderObj, minWidth: 200, minHeight: 25, flexibleWidth: 0, flexibleHeight: 0);
|
||||
slider.minValue = 0;
|
||||
slider.maxValue = 1;
|
||||
slider.value = GetValueFromColor();
|
||||
|
||||
slider.onValueChanged.AddListener((float value) =>
|
||||
{
|
||||
inputField.text = value.ToString();
|
||||
SetValueToColor(value);
|
||||
m_inputs[index].text = value.ToString();
|
||||
});
|
||||
|
||||
// methods for writing to the color for this field
|
||||
|
||||
void SetValueToColor(float floatValue)
|
||||
{
|
||||
Color _color = (Color)Value;
|
||||
switch (index)
|
||||
{
|
||||
case 0: _color.r = floatValue; break;
|
||||
case 1: _color.g = floatValue; break;
|
||||
case 2: _color.b = floatValue; break;
|
||||
case 3: _color.a = floatValue; break;
|
||||
}
|
||||
Value = _color;
|
||||
m_colorImage.color = _color;
|
||||
}
|
||||
|
||||
float GetValueFromColor()
|
||||
{
|
||||
Color _color = (Color)Value;
|
||||
switch (index)
|
||||
{
|
||||
case 0: return _color.r;
|
||||
case 1: return _color.g;
|
||||
case 2: return _color.b;
|
||||
case 3: return _color.a;
|
||||
default: throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
@ -1,246 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.Core.Config;
|
||||
using UnityExplorer.UI;
|
||||
using System.Reflection;
|
||||
using UnityExplorer.UI.CacheObject;
|
||||
using UnityExplorer.Core;
|
||||
using UnityExplorer.UI.Utility;
|
||||
#if CPP
|
||||
using AltIDictionary = Il2CppSystem.Collections.IDictionary;
|
||||
#else
|
||||
using AltIDictionary = System.Collections.IDictionary;
|
||||
#endif
|
||||
|
||||
namespace UnityExplorer.UI.InteractiveValues
|
||||
{
|
||||
public class InteractiveDictionary : InteractiveValue
|
||||
{
|
||||
public InteractiveDictionary(object value, Type valueType) : base(value, valueType)
|
||||
{
|
||||
if (valueType.IsGenericType)
|
||||
{
|
||||
var gArgs = valueType.GetGenericArguments();
|
||||
m_typeOfKeys = gArgs[0];
|
||||
m_typeofValues = gArgs[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
m_typeOfKeys = typeof(object);
|
||||
m_typeofValues = typeof(object);
|
||||
}
|
||||
}
|
||||
|
||||
public override bool WantInspectBtn => false;
|
||||
public override bool HasSubContent => true;
|
||||
public override bool SubContentWanted
|
||||
{
|
||||
get
|
||||
{
|
||||
if (m_recacheWanted && Value != null)
|
||||
return true;
|
||||
else return m_entries.Count > 0;
|
||||
}
|
||||
}
|
||||
|
||||
internal IDictionary RefIDictionary;
|
||||
internal AltIDictionary RefAltIDictionary;
|
||||
internal Type m_typeOfKeys;
|
||||
internal Type m_typeofValues;
|
||||
|
||||
internal readonly List<KeyValuePair<CachePaired, CachePaired>> m_entries
|
||||
= new List<KeyValuePair<CachePaired, CachePaired>>();
|
||||
|
||||
internal readonly KeyValuePair<CachePaired, CachePaired>[] m_displayedEntries
|
||||
= new KeyValuePair<CachePaired, CachePaired>[ConfigManager.Default_Page_Limit.Value];
|
||||
|
||||
internal bool m_recacheWanted = true;
|
||||
|
||||
public override void OnDestroy()
|
||||
{
|
||||
base.OnDestroy();
|
||||
}
|
||||
|
||||
public override void OnValueUpdated()
|
||||
{
|
||||
RefIDictionary = Value as IDictionary;
|
||||
|
||||
if (RefIDictionary == null)
|
||||
{
|
||||
try { RefAltIDictionary = Value.TryCast<AltIDictionary>(); }
|
||||
catch { }
|
||||
}
|
||||
|
||||
if (m_subContentParent.activeSelf)
|
||||
{
|
||||
GetCacheEntries();
|
||||
RefreshDisplay();
|
||||
}
|
||||
else
|
||||
m_recacheWanted = true;
|
||||
|
||||
base.OnValueUpdated();
|
||||
}
|
||||
|
||||
internal void OnPageTurned()
|
||||
{
|
||||
RefreshDisplay();
|
||||
}
|
||||
|
||||
public override void RefreshUIForValue()
|
||||
{
|
||||
GetDefaultLabel();
|
||||
|
||||
if (Value != null)
|
||||
{
|
||||
string count = "?";
|
||||
if (m_recacheWanted && RefIDictionary != null)
|
||||
count = RefIDictionary.Count.ToString();
|
||||
else if (!m_recacheWanted)
|
||||
count = m_entries.Count.ToString();
|
||||
|
||||
m_baseLabel.text = $"[{count}] {m_richValueType}";
|
||||
}
|
||||
else
|
||||
{
|
||||
m_baseLabel.text = DefaultLabel;
|
||||
}
|
||||
}
|
||||
|
||||
public void GetCacheEntries()
|
||||
{
|
||||
if (m_entries.Any())
|
||||
{
|
||||
// maybe improve this, probably could be more efficient i guess
|
||||
|
||||
foreach (var pair in m_entries)
|
||||
{
|
||||
pair.Key.Destroy();
|
||||
pair.Value.Destroy();
|
||||
}
|
||||
|
||||
m_entries.Clear();
|
||||
}
|
||||
|
||||
if (RefIDictionary == null && Value != null)
|
||||
RefIDictionary = RuntimeProvider.Instance.Reflection.EnumerateDictionary(Value, m_typeOfKeys, m_typeofValues);
|
||||
|
||||
if (RefIDictionary != null)
|
||||
{
|
||||
int index = 0;
|
||||
|
||||
foreach (var key in RefIDictionary.Keys)
|
||||
{
|
||||
var value = RefIDictionary[key];
|
||||
|
||||
var cacheKey = new CachePaired(index, this, this.RefIDictionary, PairTypes.Key, m_listContent);
|
||||
cacheKey.CreateIValue(key, this.m_typeOfKeys);
|
||||
cacheKey.Disable();
|
||||
|
||||
var cacheValue = new CachePaired(index, this, this.RefIDictionary, PairTypes.Value, m_listContent);
|
||||
cacheValue.CreateIValue(value, this.m_typeofValues);
|
||||
cacheValue.Disable();
|
||||
|
||||
//holder.SetActive(false);
|
||||
|
||||
m_entries.Add(new KeyValuePair<CachePaired, CachePaired>(cacheKey, cacheValue));
|
||||
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
RefreshDisplay();
|
||||
}
|
||||
|
||||
public void RefreshDisplay()
|
||||
{
|
||||
//var entries = m_entries;
|
||||
//m_pageHandler.ListCount = entries.Count;
|
||||
//
|
||||
//for (int i = 0; i < m_displayedEntries.Length; i++)
|
||||
//{
|
||||
// var entry = m_displayedEntries[i];
|
||||
// if (entry.Key != null && entry.Value != null)
|
||||
// {
|
||||
// //m_rowHolders[i].SetActive(false);
|
||||
// entry.Key.Disable();
|
||||
// entry.Value.Disable();
|
||||
// }
|
||||
// else
|
||||
// break;
|
||||
//}
|
||||
//
|
||||
//if (entries.Count < 1)
|
||||
// return;
|
||||
//
|
||||
//foreach (var itemIndex in m_pageHandler)
|
||||
//{
|
||||
// if (itemIndex >= entries.Count)
|
||||
// break;
|
||||
//
|
||||
// var entry = entries[itemIndex];
|
||||
// m_displayedEntries[itemIndex - m_pageHandler.StartIndex] = entry;
|
||||
//
|
||||
// //m_rowHolders[itemIndex].SetActive(true);
|
||||
// entry.Key.Enable();
|
||||
// entry.Value.Enable();
|
||||
//}
|
||||
//
|
||||
////UpdateSubcontentHeight();
|
||||
}
|
||||
|
||||
internal override void OnToggleSubcontent(bool active)
|
||||
{
|
||||
base.OnToggleSubcontent(active);
|
||||
|
||||
if (active && m_recacheWanted)
|
||||
{
|
||||
m_recacheWanted = false;
|
||||
GetCacheEntries();
|
||||
RefreshUIForValue();
|
||||
}
|
||||
|
||||
RefreshDisplay();
|
||||
}
|
||||
|
||||
internal GameObject m_listContent;
|
||||
internal LayoutElement m_listLayout;
|
||||
|
||||
// internal PageHandler m_pageHandler;
|
||||
|
||||
public override void ConstructUI(GameObject parent, GameObject subGroup)
|
||||
{
|
||||
base.ConstructUI(parent, subGroup);
|
||||
}
|
||||
|
||||
public override void ConstructSubcontent()
|
||||
{
|
||||
base.ConstructSubcontent();
|
||||
|
||||
//m_pageHandler = new PageHandler(null);
|
||||
//m_pageHandler.ConstructUI(m_subContentParent);
|
||||
//m_pageHandler.OnPageChanged += OnPageTurned;
|
||||
|
||||
m_listContent = UIFactory.CreateVerticalGroup(m_subContentParent, "DictionaryContent", true, true, true, true, 2, new Vector4(5,5,5,5),
|
||||
new Color(0.08f, 0.08f, 0.08f));
|
||||
|
||||
var scrollRect = m_listContent.GetComponent<RectTransform>();
|
||||
scrollRect.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, 0);
|
||||
|
||||
m_listLayout = Owner.UIRoot.GetComponent<LayoutElement>();
|
||||
m_listLayout.minHeight = 25;
|
||||
m_listLayout.flexibleHeight = 0;
|
||||
|
||||
Owner.m_mainRect.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, 25);
|
||||
|
||||
var contentFitter = m_listContent.AddComponent<ContentSizeFitter>();
|
||||
contentFitter.horizontalFit = ContentSizeFitter.FitMode.Unconstrained;
|
||||
contentFitter.verticalFit = ContentSizeFitter.FitMode.PreferredSize;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,163 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.UI;
|
||||
|
||||
namespace UnityExplorer.UI.InteractiveValues
|
||||
{
|
||||
public class InteractiveEnum : InteractiveValue
|
||||
{
|
||||
internal static Dictionary<Type, KeyValuePair<int,string>[]> s_enumNamesCache = new Dictionary<Type, KeyValuePair<int, string>[]>();
|
||||
|
||||
public InteractiveEnum(object value, Type valueType) : base(value, valueType)
|
||||
{
|
||||
GetNames();
|
||||
}
|
||||
|
||||
public override bool HasSubContent => true;
|
||||
public override bool SubContentWanted => Owner.CanWrite;
|
||||
public override bool WantInspectBtn => false;
|
||||
|
||||
internal KeyValuePair<int,string>[] m_values = new KeyValuePair<int, string>[0];
|
||||
|
||||
internal Type m_lastEnumType;
|
||||
|
||||
internal void GetNames()
|
||||
{
|
||||
var type = Value?.GetType() ?? FallbackType;
|
||||
|
||||
if (m_lastEnumType == type)
|
||||
return;
|
||||
|
||||
m_lastEnumType = type;
|
||||
|
||||
if (m_subContentConstructed)
|
||||
{
|
||||
DestroySubContent();
|
||||
}
|
||||
|
||||
if (!s_enumNamesCache.ContainsKey(type))
|
||||
{
|
||||
// using GetValues not GetNames, to catch instances of weird enums (eg CameraClearFlags)
|
||||
var values = Enum.GetValues(type);
|
||||
|
||||
var list = new List<KeyValuePair<int, string>>();
|
||||
var set = new HashSet<string>();
|
||||
|
||||
foreach (var value in values)
|
||||
{
|
||||
var name = value.ToString();
|
||||
|
||||
if (set.Contains(name))
|
||||
continue;
|
||||
|
||||
set.Add(name);
|
||||
|
||||
var backingType = Enum.GetUnderlyingType(type);
|
||||
int intValue;
|
||||
try
|
||||
{
|
||||
// this approach is necessary, a simple '(int)value' is not sufficient.
|
||||
|
||||
var unbox = Convert.ChangeType(value, backingType);
|
||||
|
||||
intValue = (int)Convert.ChangeType(unbox, typeof(int));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ExplorerCore.LogWarning("[InteractiveEnum] Could not Unbox underlying type " + backingType.Name + " from " + type.FullName);
|
||||
ExplorerCore.Log(ex.ToString());
|
||||
continue;
|
||||
}
|
||||
|
||||
list.Add(new KeyValuePair<int, string>(intValue, name));
|
||||
}
|
||||
|
||||
s_enumNamesCache.Add(type, list.ToArray());
|
||||
}
|
||||
|
||||
m_values = s_enumNamesCache[type];
|
||||
}
|
||||
|
||||
public override void OnValueUpdated()
|
||||
{
|
||||
GetNames();
|
||||
|
||||
base.OnValueUpdated();
|
||||
}
|
||||
|
||||
public override void RefreshUIForValue()
|
||||
{
|
||||
base.RefreshUIForValue();
|
||||
|
||||
if (m_subContentConstructed && !(this is InteractiveFlags))
|
||||
{
|
||||
m_dropdownText.text = Value?.ToString() ?? "<no value set>";
|
||||
}
|
||||
}
|
||||
|
||||
internal override void OnToggleSubcontent(bool toggle)
|
||||
{
|
||||
base.OnToggleSubcontent(toggle);
|
||||
|
||||
RefreshUIForValue();
|
||||
}
|
||||
|
||||
private void SetValueFromDropdown()
|
||||
{
|
||||
var type = Value?.GetType() ?? FallbackType;
|
||||
var index = m_dropdown.value;
|
||||
|
||||
var value = Enum.Parse(type, s_enumNamesCache[type][index].Value);
|
||||
|
||||
if (value != null)
|
||||
{
|
||||
Value = value;
|
||||
Owner.SetValue();
|
||||
RefreshUIForValue();
|
||||
}
|
||||
}
|
||||
|
||||
internal Dropdown m_dropdown;
|
||||
internal Text m_dropdownText;
|
||||
|
||||
public override void ConstructUI(GameObject parent, GameObject subGroup)
|
||||
{
|
||||
base.ConstructUI(parent, subGroup);
|
||||
}
|
||||
|
||||
public override void ConstructSubcontent()
|
||||
{
|
||||
base.ConstructSubcontent();
|
||||
|
||||
if (Owner.CanWrite)
|
||||
{
|
||||
var groupObj = UIFactory.CreateHorizontalGroup(m_subContentParent, "InteractiveEnumGroup", false, true, true, true, 5,
|
||||
new Vector4(3,3,3,3),new Color(1, 1, 1, 0));
|
||||
|
||||
// apply button
|
||||
|
||||
var apply = UIFactory.CreateButton(groupObj, "ApplyButton", "Apply", SetValueFromDropdown, new Color(0.3f, 0.3f, 0.3f));
|
||||
UIFactory.SetLayoutElement(apply.gameObject, minHeight: 25, minWidth: 50);
|
||||
|
||||
// dropdown
|
||||
|
||||
var dropdownObj = UIFactory.CreateDropdown(groupObj, out m_dropdown, "", 14, null);
|
||||
UIFactory.SetLayoutElement(dropdownObj, minWidth: 150, minHeight: 25, flexibleWidth: 120);
|
||||
|
||||
foreach (var kvp in m_values)
|
||||
{
|
||||
m_dropdown.options.Add(new Dropdown.OptionData
|
||||
{
|
||||
text = $"{kvp.Key}: {kvp.Value}"
|
||||
});
|
||||
}
|
||||
|
||||
m_dropdownText = m_dropdown.transform.Find("Label").GetComponent<Text>();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,245 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.Core;
|
||||
using UnityExplorer.Core.Config;
|
||||
using UnityExplorer.UI;
|
||||
using UnityExplorer.UI.CacheObject;
|
||||
using UnityExplorer.UI.Utility;
|
||||
using UnityExplorer.UI.Widgets;
|
||||
|
||||
namespace UnityExplorer.UI.InteractiveValues
|
||||
{
|
||||
public class InteractiveEnumerable : InteractiveValue, IPoolDataSource
|
||||
{
|
||||
// IPoolDataSource
|
||||
|
||||
public ScrollPool ScrollPool;
|
||||
public GameObject InactiveHolder;
|
||||
internal LayoutElement listLayout;
|
||||
|
||||
public int ItemCount => m_entries?.Count ?? 0;
|
||||
|
||||
public void SetCell(ICell icell, int index)
|
||||
{
|
||||
var cell = icell as CellViewHolder;
|
||||
|
||||
if (index < 0 || index >= ItemCount)
|
||||
{
|
||||
var existing = cell.DisableContent();
|
||||
if (existing)
|
||||
existing.transform.SetParent(InactiveHolder.transform, false);
|
||||
return;
|
||||
}
|
||||
|
||||
var cache = m_entries[index];
|
||||
cache.Enable();
|
||||
|
||||
var prev = cell.SetContent(cache.UIRoot);
|
||||
if (prev)
|
||||
prev.transform.SetParent(InactiveHolder.transform, false);
|
||||
}
|
||||
|
||||
public void DisableCell(ICell cell, int index)
|
||||
{
|
||||
var content = (cell as CellViewHolder).DisableContent();
|
||||
if (content)
|
||||
content.transform.SetParent(InactiveHolder.transform, false);
|
||||
}
|
||||
|
||||
//public void SetCell(ICell cell, int index)
|
||||
//{
|
||||
// var root = (cell as CellViewHolder).UIRoot;
|
||||
|
||||
// if (index < 0 || index >= ItemCount)
|
||||
// {
|
||||
// DisableContent(root);
|
||||
// cell.Disable();
|
||||
// return;
|
||||
// }
|
||||
|
||||
// var cache = m_entries[index];
|
||||
// cache.Enable();
|
||||
|
||||
// var content = cache.UIRoot;
|
||||
|
||||
// if (content.transform.parent.ReferenceEqual(root.transform))
|
||||
// return;
|
||||
|
||||
// DisableContent(root);
|
||||
|
||||
// content.transform.SetParent(root.transform, false);
|
||||
//}
|
||||
|
||||
//public void DisableCell(ICell cell, int index)
|
||||
//{
|
||||
// var root = (cell as CellViewHolder).UIRoot;
|
||||
// DisableContent(root);
|
||||
// cell.Disable();
|
||||
//}
|
||||
|
||||
//private void DisableContent(GameObject cellRoot)
|
||||
//{
|
||||
// if (cellRoot.transform.childCount > 0 && cellRoot.transform.GetChild(0) is Transform existing)
|
||||
// existing.transform.SetParent(InactiveHolder.transform, false);
|
||||
//}
|
||||
|
||||
public ICell CreateCell(RectTransform cellTransform) => new CellViewHolder(cellTransform.gameObject);
|
||||
|
||||
public int GetRealIndexOfTempIndex(int tempIndex) => throw new NotImplementedException("Filtering not supported");
|
||||
|
||||
// InteractiveEnumerable
|
||||
|
||||
public InteractiveEnumerable(object value, Type valueType) : base(value, valueType)
|
||||
{
|
||||
if (valueType.IsGenericType)
|
||||
m_baseEntryType = valueType.GetGenericArguments()[0];
|
||||
else
|
||||
m_baseEntryType = typeof(object);
|
||||
}
|
||||
|
||||
public override bool WantInspectBtn => false;
|
||||
public override bool HasSubContent => true;
|
||||
public override bool SubContentWanted
|
||||
{
|
||||
get
|
||||
{
|
||||
if (m_recacheWanted && Value != null)
|
||||
return true;
|
||||
else return m_entries.Count > 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
internal IEnumerable RefIEnumerable;
|
||||
internal IList RefIList;
|
||||
|
||||
internal readonly Type m_baseEntryType;
|
||||
|
||||
internal readonly List<CacheEnumerated> m_entries = new List<CacheEnumerated>();
|
||||
internal readonly CacheEnumerated[] m_displayedEntries = new CacheEnumerated[ConfigManager.Default_Page_Limit.Value];
|
||||
internal bool m_recacheWanted = true;
|
||||
|
||||
public override void OnValueUpdated()
|
||||
{
|
||||
RefIEnumerable = Value as IEnumerable;
|
||||
RefIList = Value as IList;
|
||||
|
||||
if (m_subContentParent && m_subContentParent.activeSelf)
|
||||
{
|
||||
ToggleSubcontent();
|
||||
//GetCacheEntries();
|
||||
//RefreshDisplay();
|
||||
}
|
||||
|
||||
m_recacheWanted = true;
|
||||
|
||||
base.OnValueUpdated();
|
||||
}
|
||||
|
||||
public override void OnException(CacheMember member)
|
||||
{
|
||||
base.OnException(member);
|
||||
}
|
||||
|
||||
public override void RefreshUIForValue()
|
||||
{
|
||||
GetDefaultLabel();
|
||||
|
||||
if (Value != null)
|
||||
{
|
||||
string count = "?";
|
||||
if (m_recacheWanted && RefIList != null)
|
||||
count = RefIList.Count.ToString();
|
||||
else if (!m_recacheWanted)
|
||||
count = m_entries.Count.ToString();
|
||||
|
||||
m_baseLabel.text = $"[{count}] {m_richValueType}";
|
||||
}
|
||||
else
|
||||
{
|
||||
m_baseLabel.text = DefaultLabel;
|
||||
}
|
||||
}
|
||||
|
||||
public void GetCacheEntries()
|
||||
{
|
||||
if (m_entries.Any())
|
||||
{
|
||||
foreach (var entry in m_entries)
|
||||
entry.Destroy();
|
||||
|
||||
m_entries.Clear();
|
||||
}
|
||||
|
||||
if (RefIEnumerable == null && Value != null)
|
||||
RefIEnumerable = RuntimeProvider.Instance.Reflection.EnumerateEnumerable(Value);
|
||||
|
||||
if (RefIEnumerable != null)
|
||||
{
|
||||
int index = 0;
|
||||
foreach (var entry in RefIEnumerable)
|
||||
{
|
||||
var cache = new CacheEnumerated(index, this, RefIList, this.InactiveHolder);
|
||||
cache.CreateIValue(entry, m_baseEntryType);
|
||||
m_entries.Add(cache);
|
||||
|
||||
cache.Disable();
|
||||
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
RefreshDisplay();
|
||||
}
|
||||
|
||||
public void RefreshDisplay()
|
||||
{
|
||||
ScrollPool.RefreshCells(true);
|
||||
|
||||
listLayout.minHeight = Math.Min(500f, m_entries.Count * 32f);
|
||||
}
|
||||
|
||||
internal override void OnToggleSubcontent(bool active)
|
||||
{
|
||||
base.OnToggleSubcontent(active);
|
||||
|
||||
if (active && m_recacheWanted)
|
||||
{
|
||||
m_recacheWanted = false;
|
||||
GetCacheEntries();
|
||||
RefreshUIForValue();
|
||||
}
|
||||
|
||||
RefreshDisplay();
|
||||
}
|
||||
|
||||
public override void ConstructUI(GameObject parent, GameObject subGroup)
|
||||
{
|
||||
base.ConstructUI(parent, subGroup);
|
||||
|
||||
InactiveHolder = new GameObject("InactiveHolder");
|
||||
InactiveHolder.transform.SetParent(parent.transform, false);
|
||||
InactiveHolder.SetActive(false);
|
||||
}
|
||||
|
||||
public override void ConstructSubcontent()
|
||||
{
|
||||
base.ConstructSubcontent();
|
||||
|
||||
ScrollPool = UIFactory.CreateScrollPool(m_subContentParent, "ListEntries", out GameObject scrollRoot, out GameObject scrollContent,
|
||||
new Color(0.05f, 0.05f, 0.05f));
|
||||
|
||||
listLayout = scrollRoot.AddComponent<LayoutElement>();
|
||||
|
||||
var proto = CellViewHolder.CreatePrototypeCell(scrollRoot);
|
||||
proto.sizeDelta = new Vector2(100, 30);
|
||||
ScrollPool.Initialize(this, proto);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,125 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.UI;
|
||||
|
||||
namespace UnityExplorer.UI.InteractiveValues
|
||||
{
|
||||
public class InteractiveFlags : InteractiveEnum
|
||||
{
|
||||
public InteractiveFlags(object value, Type valueType) : base(value, valueType)
|
||||
{
|
||||
m_toggles = new Toggle[m_values.Length];
|
||||
m_enabledFlags = new bool[m_values.Length];
|
||||
}
|
||||
|
||||
public override bool HasSubContent => true;
|
||||
public override bool SubContentWanted => Owner.CanWrite;
|
||||
public override bool WantInspectBtn => false;
|
||||
|
||||
internal bool[] m_enabledFlags;
|
||||
internal Toggle[] m_toggles;
|
||||
|
||||
public override void OnValueUpdated()
|
||||
{
|
||||
if (Owner.CanWrite)
|
||||
{
|
||||
var enabledNames = new List<string>();
|
||||
|
||||
var enabled = Value?.ToString().Split(',').Select(it => it.Trim());
|
||||
if (enabled != null)
|
||||
enabledNames.AddRange(enabled);
|
||||
|
||||
for (int i = 0; i < m_values.Length; i++)
|
||||
m_enabledFlags[i] = enabledNames.Contains(m_values[i].Value);
|
||||
}
|
||||
|
||||
base.OnValueUpdated();
|
||||
}
|
||||
|
||||
public override void RefreshUIForValue()
|
||||
{
|
||||
GetDefaultLabel();
|
||||
m_baseLabel.text = DefaultLabel;
|
||||
|
||||
base.RefreshUIForValue();
|
||||
|
||||
if (m_subContentConstructed)
|
||||
{
|
||||
for (int i = 0; i < m_values.Length; i++)
|
||||
{
|
||||
var toggle = m_toggles[i];
|
||||
if (toggle.isOn != m_enabledFlags[i])
|
||||
toggle.isOn = m_enabledFlags[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void SetValueFromToggles()
|
||||
{
|
||||
string val = "";
|
||||
for (int i = 0; i < m_values.Length; i++)
|
||||
{
|
||||
if (m_enabledFlags[i])
|
||||
{
|
||||
if (val != "") val += ", ";
|
||||
val += m_values[i].Value;
|
||||
}
|
||||
}
|
||||
var type = Value?.GetType() ?? FallbackType;
|
||||
Value = Enum.Parse(type, val);
|
||||
RefreshUIForValue();
|
||||
Owner.SetValue();
|
||||
}
|
||||
|
||||
internal override void OnToggleSubcontent(bool toggle)
|
||||
{
|
||||
base.OnToggleSubcontent(toggle);
|
||||
|
||||
RefreshUIForValue();
|
||||
}
|
||||
|
||||
public override void ConstructUI(GameObject parent, GameObject subGroup)
|
||||
{
|
||||
base.ConstructUI(parent, subGroup);
|
||||
}
|
||||
|
||||
public override void ConstructSubcontent()
|
||||
{
|
||||
m_subContentConstructed = true;
|
||||
|
||||
if (Owner.CanWrite)
|
||||
{
|
||||
var groupObj = UIFactory.CreateVerticalGroup(m_subContentParent, "InteractiveFlagsContent", false, true, true, true, 5,
|
||||
new Vector4(3,3,3,3), new Color(1, 1, 1, 0));
|
||||
|
||||
// apply button
|
||||
|
||||
var apply = UIFactory.CreateButton(groupObj, "ApplyButton", "Apply", SetValueFromToggles, new Color(0.3f, 0.3f, 0.3f));
|
||||
UIFactory.SetLayoutElement(apply.gameObject, minWidth: 50, minHeight: 25);
|
||||
|
||||
// toggles
|
||||
|
||||
for (int i = 0; i < m_values.Length; i++)
|
||||
AddToggle(i, groupObj);
|
||||
}
|
||||
}
|
||||
|
||||
internal void AddToggle(int index, GameObject groupObj)
|
||||
{
|
||||
var value = m_values[index];
|
||||
|
||||
var toggleObj = UIFactory.CreateToggle(groupObj, "FlagToggle", out Toggle toggle, out Text text, new Color(0.1f, 0.1f, 0.1f));
|
||||
UIFactory.SetLayoutElement(toggleObj, minWidth: 100, flexibleWidth: 2000, minHeight: 25);
|
||||
|
||||
m_toggles[index] = toggle;
|
||||
|
||||
toggle.onValueChanged.AddListener((bool val) => { m_enabledFlags[index] = val; });
|
||||
|
||||
text.text = $"{value.Key}: {value.Value}";
|
||||
}
|
||||
}
|
||||
}
|
@ -1,203 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using System.Reflection;
|
||||
|
||||
namespace UnityExplorer.UI.InteractiveValues
|
||||
{
|
||||
// Class for supporting any "float struct" (ie Vector, Rect, etc).
|
||||
// Supports any struct where all the public instance fields are floats (or types assignable to float)
|
||||
|
||||
public class StructInfo
|
||||
{
|
||||
public string[] FieldNames { get; }
|
||||
private readonly FieldInfo[] m_fields;
|
||||
|
||||
public StructInfo(Type type)
|
||||
{
|
||||
m_fields = type.GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public)
|
||||
.Where(it => !it.IsLiteral)
|
||||
.ToArray();
|
||||
|
||||
FieldNames = m_fields.Select(it => it.Name)
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
public object SetValue(ref object instance, int fieldIndex, float val)
|
||||
{
|
||||
m_fields[fieldIndex].SetValue(instance, val);
|
||||
return instance;
|
||||
}
|
||||
|
||||
public float GetValue(object instance, int fieldIndex)
|
||||
=> (float)m_fields[fieldIndex].GetValue(instance);
|
||||
|
||||
public void RefreshUI(InputField[] inputs, object instance)
|
||||
{
|
||||
try
|
||||
{
|
||||
for (int i = 0; i < m_fields.Length; i++)
|
||||
{
|
||||
var field = m_fields[i];
|
||||
float val = (float)field.GetValue(instance);
|
||||
inputs[i].text = val.ToString();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ExplorerCore.Log(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class InteractiveFloatStruct : InteractiveValue
|
||||
{
|
||||
private static readonly Dictionary<string, bool> _typeSupportCache = new Dictionary<string, bool>();
|
||||
public static bool IsTypeSupported(Type type)
|
||||
{
|
||||
if (!type.IsValueType)
|
||||
return false;
|
||||
|
||||
if (string.IsNullOrEmpty(type.AssemblyQualifiedName))
|
||||
return false;
|
||||
|
||||
if (_typeSupportCache.TryGetValue(type.AssemblyQualifiedName, out bool ret))
|
||||
return ret;
|
||||
|
||||
if (type.FullName == "System.Void")
|
||||
return false;
|
||||
|
||||
ret = true;
|
||||
var fields = type.GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
|
||||
foreach (var field in fields)
|
||||
{
|
||||
if (field.IsLiteral)
|
||||
continue;
|
||||
|
||||
if (!typeof(float).IsAssignableFrom(field.FieldType))
|
||||
{
|
||||
ret = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
_typeSupportCache.Add(type.AssemblyQualifiedName, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
//~~~~~~~~~ Instance ~~~~~~~~~~
|
||||
|
||||
public InteractiveFloatStruct(object value, Type valueType) : base(value, valueType) { }
|
||||
|
||||
public override bool HasSubContent => true;
|
||||
public override bool SubContentWanted => true;
|
||||
|
||||
public StructInfo StructInfo;
|
||||
|
||||
public override void RefreshUIForValue()
|
||||
{
|
||||
InitializeStructInfo();
|
||||
|
||||
base.RefreshUIForValue();
|
||||
|
||||
if (m_subContentConstructed)
|
||||
StructInfo.RefreshUI(m_inputs, this.Value);
|
||||
}
|
||||
|
||||
internal override void OnToggleSubcontent(bool toggle)
|
||||
{
|
||||
InitializeStructInfo();
|
||||
|
||||
base.OnToggleSubcontent(toggle);
|
||||
|
||||
StructInfo.RefreshUI(m_inputs, this.Value);
|
||||
}
|
||||
|
||||
internal Type m_lastStructType;
|
||||
|
||||
internal void InitializeStructInfo()
|
||||
{
|
||||
var type = Value?.GetType() ?? FallbackType;
|
||||
|
||||
if (StructInfo != null && type == m_lastStructType)
|
||||
return;
|
||||
|
||||
if (StructInfo != null && m_subContentConstructed)
|
||||
DestroySubContent();
|
||||
|
||||
m_lastStructType = type;
|
||||
|
||||
StructInfo = new StructInfo(type);
|
||||
|
||||
if (m_subContentParent.activeSelf)
|
||||
ConstructSubcontent();
|
||||
}
|
||||
|
||||
#region UI CONSTRUCTION
|
||||
|
||||
internal InputField[] m_inputs;
|
||||
|
||||
public override void ConstructUI(GameObject parent, GameObject subGroup)
|
||||
{
|
||||
base.ConstructUI(parent, subGroup);
|
||||
}
|
||||
|
||||
public override void ConstructSubcontent()
|
||||
{
|
||||
base.ConstructSubcontent();
|
||||
|
||||
if (StructInfo == null)
|
||||
{
|
||||
ExplorerCore.LogWarning("Setting up subcontent but structinfo is null");
|
||||
return;
|
||||
}
|
||||
|
||||
var editorContainer = UIFactory.CreateVerticalGroup(m_subContentParent, "EditorContent", false, true, true, true, 2, new Vector4(4, 4, 4, 4),
|
||||
new Color(0.08f, 0.08f, 0.08f));
|
||||
|
||||
m_inputs = new InputField[StructInfo.FieldNames.Length];
|
||||
|
||||
for (int i = 0; i < StructInfo.FieldNames.Length; i++)
|
||||
AddEditorRow(i, editorContainer);
|
||||
|
||||
RefreshUIForValue();
|
||||
}
|
||||
|
||||
internal void AddEditorRow(int index, GameObject groupObj)
|
||||
{
|
||||
try
|
||||
{
|
||||
var row = UIFactory.CreateHorizontalGroup(groupObj, "EditorRow", false, true, true, true, 5, default, new Color(1, 1, 1, 0));
|
||||
|
||||
string name = StructInfo.FieldNames[index];
|
||||
|
||||
var label = UIFactory.CreateLabel(row, "RowLabel", $"{name}:", TextAnchor.MiddleRight, Color.cyan);
|
||||
UIFactory.SetLayoutElement(label.gameObject, minWidth: 30, flexibleWidth: 0, minHeight: 25);
|
||||
|
||||
var inputFieldObj = UIFactory.CreateInputField(row, "InputField", "...", out InputField inputField, 14, 3, 1);
|
||||
UIFactory.SetLayoutElement(inputFieldObj, minWidth: 120, minHeight: 25, flexibleWidth: 0);
|
||||
|
||||
m_inputs[index] = inputField;
|
||||
|
||||
inputField.onValueChanged.AddListener((string val) =>
|
||||
{
|
||||
try
|
||||
{
|
||||
float f = float.Parse(val);
|
||||
Value = StructInfo.SetValue(ref this.Value, index, f);
|
||||
Owner.SetValue();
|
||||
}
|
||||
catch { }
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ExplorerCore.Log(ex);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
@ -1,115 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Reflection;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.UI;
|
||||
using UnityExplorer.Core;
|
||||
using UnityExplorer.UI.Utility;
|
||||
using UnityExplorer.UI.CacheObject;
|
||||
|
||||
namespace UnityExplorer.UI.InteractiveValues
|
||||
{
|
||||
public class InteractiveNumber : InteractiveValue
|
||||
{
|
||||
public InteractiveNumber(object value, Type valueType) : base(value, valueType) { }
|
||||
|
||||
public override bool HasSubContent => false;
|
||||
public override bool SubContentWanted => false;
|
||||
public override bool WantInspectBtn => false;
|
||||
|
||||
public override void OnValueUpdated()
|
||||
{
|
||||
base.OnValueUpdated();
|
||||
}
|
||||
|
||||
public override void OnException(CacheMember member)
|
||||
{
|
||||
base.OnException(member);
|
||||
|
||||
if (m_valueInput.gameObject.activeSelf)
|
||||
m_valueInput.gameObject.SetActive(false);
|
||||
|
||||
if (Owner.CanWrite)
|
||||
{
|
||||
if (m_applyBtn.gameObject.activeSelf)
|
||||
m_applyBtn.gameObject.SetActive(false);
|
||||
}
|
||||
}
|
||||
|
||||
public override void RefreshUIForValue()
|
||||
{
|
||||
if (!Owner.HasEvaluated)
|
||||
{
|
||||
GetDefaultLabel();
|
||||
m_baseLabel.text = DefaultLabel;
|
||||
return;
|
||||
}
|
||||
|
||||
m_baseLabel.text = SignatureHighlighter.ParseFullSyntax(FallbackType, false);
|
||||
m_valueInput.text = Value.ToString();
|
||||
|
||||
var type = Value.GetType();
|
||||
if (type == typeof(float)
|
||||
|| type == typeof(double)
|
||||
|| type == typeof(decimal))
|
||||
{
|
||||
m_valueInput.characterValidation = InputField.CharacterValidation.Decimal;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_valueInput.characterValidation = InputField.CharacterValidation.Integer;
|
||||
}
|
||||
|
||||
if (Owner.CanWrite)
|
||||
{
|
||||
if (!m_applyBtn.gameObject.activeSelf)
|
||||
m_applyBtn.gameObject.SetActive(true);
|
||||
}
|
||||
|
||||
if (!m_valueInput.gameObject.activeSelf)
|
||||
m_valueInput.gameObject.SetActive(true);
|
||||
}
|
||||
|
||||
public MethodInfo ParseMethod => m_parseMethod ?? (m_parseMethod = Value.GetType().GetMethod("Parse", new Type[] { typeof(string) }));
|
||||
private MethodInfo m_parseMethod;
|
||||
|
||||
internal void OnApplyClicked()
|
||||
{
|
||||
try
|
||||
{
|
||||
Value = ParseMethod.Invoke(null, new object[] { m_valueInput.text });
|
||||
Owner.SetValue();
|
||||
RefreshUIForValue();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
ExplorerCore.LogWarning("Could not parse input! " + ReflectionUtility.ReflectionExToString(e, true));
|
||||
}
|
||||
}
|
||||
|
||||
internal InputField m_valueInput;
|
||||
internal Button m_applyBtn;
|
||||
|
||||
public override void ConstructUI(GameObject parent, GameObject subGroup)
|
||||
{
|
||||
base.ConstructUI(parent, subGroup);
|
||||
|
||||
var labelLayout = m_baseLabel.gameObject.GetComponent<LayoutElement>();
|
||||
labelLayout.minWidth = 50;
|
||||
labelLayout.flexibleWidth = 0;
|
||||
|
||||
var inputObj = UIFactory.CreateInputField(m_mainContent, "InteractiveNumberInput", "...", out m_valueInput);
|
||||
UIFactory.SetLayoutElement(inputObj, minWidth: 120, minHeight: 25, flexibleWidth: 0);
|
||||
m_valueInput.gameObject.SetActive(false);
|
||||
|
||||
if (Owner.CanWrite)
|
||||
{
|
||||
m_applyBtn = UIFactory.CreateButton(m_mainContent, "ApplyButton", "Apply", OnApplyClicked, new Color(0.2f, 0.2f, 0.2f));
|
||||
UIFactory.SetLayoutElement(m_applyBtn.gameObject, minWidth: 50, minHeight: 25, flexibleWidth: 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,186 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Reflection;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.UI;
|
||||
using UnityExplorer.UI.Utility;
|
||||
using UnityExplorer.UI.CacheObject;
|
||||
using UnityExplorer.Core.Runtime;
|
||||
|
||||
namespace UnityExplorer.UI.InteractiveValues
|
||||
{
|
||||
public class InteractiveString : InteractiveValue
|
||||
{
|
||||
public InteractiveString(object value, Type valueType) : base(value, valueType) { }
|
||||
|
||||
public override bool HasSubContent => true;
|
||||
public override bool SubContentWanted => true;
|
||||
|
||||
public override bool WantInspectBtn => false;
|
||||
|
||||
public override void OnValueUpdated()
|
||||
{
|
||||
if (!(Value is string) && Value != null)
|
||||
Value = RuntimeProvider.Instance.Reflection.UnboxString(Value);
|
||||
|
||||
base.OnValueUpdated();
|
||||
}
|
||||
|
||||
public override void OnException(CacheMember member)
|
||||
{
|
||||
base.OnException(member);
|
||||
|
||||
if (m_subContentConstructed && m_hiddenObj.gameObject.activeSelf)
|
||||
m_hiddenObj.gameObject.SetActive(false);
|
||||
|
||||
m_labelLayout.minWidth = 200;
|
||||
m_labelLayout.flexibleWidth = 5000;
|
||||
}
|
||||
|
||||
public override void RefreshUIForValue()
|
||||
{
|
||||
GetDefaultLabel(false);
|
||||
|
||||
if (!Owner.HasEvaluated)
|
||||
{
|
||||
m_baseLabel.text = DefaultLabel;
|
||||
return;
|
||||
}
|
||||
|
||||
m_baseLabel.text = m_richValueType;
|
||||
|
||||
if (m_subContentConstructed)
|
||||
{
|
||||
if (!m_hiddenObj.gameObject.activeSelf)
|
||||
m_hiddenObj.gameObject.SetActive(true);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty((string)Value))
|
||||
{
|
||||
var toString = (string)Value;
|
||||
if (toString.Length > 15000)
|
||||
toString = toString.Substring(0, 15000);
|
||||
|
||||
m_readonlyInput.text = toString;
|
||||
|
||||
if (m_subContentConstructed)
|
||||
{
|
||||
m_valueInput.text = toString;
|
||||
m_placeholderText.text = toString;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
string s = Value == null
|
||||
? "null"
|
||||
: "empty";
|
||||
|
||||
m_readonlyInput.text = $"<i><color=grey>{s}</color></i>";
|
||||
|
||||
if (m_subContentConstructed)
|
||||
{
|
||||
m_valueInput.text = "";
|
||||
m_placeholderText.text = s;
|
||||
}
|
||||
}
|
||||
|
||||
m_labelLayout.minWidth = 50;
|
||||
m_labelLayout.flexibleWidth = 0;
|
||||
}
|
||||
|
||||
internal void SetValueFromInput()
|
||||
{
|
||||
Value = m_valueInput.text;
|
||||
|
||||
if (!typeof(string).IsAssignableFrom(Owner.FallbackType))
|
||||
ReflectionProvider.Instance.BoxStringToType(ref Value, Owner.FallbackType);
|
||||
|
||||
Owner.SetValue();
|
||||
|
||||
// revert back to string now
|
||||
OnValueUpdated();
|
||||
|
||||
RefreshUIForValue();
|
||||
}
|
||||
|
||||
// for the default label
|
||||
internal LayoutElement m_labelLayout;
|
||||
|
||||
//internal InputField m_readonlyInput;
|
||||
internal Text m_readonlyInput;
|
||||
|
||||
// for input
|
||||
internal InputField m_valueInput;
|
||||
internal GameObject m_hiddenObj;
|
||||
internal Text m_placeholderText;
|
||||
|
||||
public override void ConstructUI(GameObject parent, GameObject subGroup)
|
||||
{
|
||||
base.ConstructUI(parent, subGroup);
|
||||
|
||||
GetDefaultLabel(false);
|
||||
m_richValueType = SignatureHighlighter.ParseFullSyntax(FallbackType, false);
|
||||
|
||||
m_labelLayout = m_baseLabel.gameObject.GetComponent<LayoutElement>();
|
||||
|
||||
m_readonlyInput = UIFactory.CreateLabel(m_mainContent, "ReadonlyLabel", "", TextAnchor.MiddleLeft);
|
||||
m_readonlyInput.horizontalOverflow = HorizontalWrapMode.Overflow;
|
||||
|
||||
var testFitter = m_readonlyInput.gameObject.AddComponent<ContentSizeFitter>();
|
||||
testFitter.verticalFit = ContentSizeFitter.FitMode.MinSize;
|
||||
|
||||
UIFactory.SetLayoutElement(m_readonlyInput.gameObject, minHeight: 25, preferredHeight: 25, flexibleHeight: 0);
|
||||
}
|
||||
|
||||
public override void ConstructSubcontent()
|
||||
{
|
||||
base.ConstructSubcontent();
|
||||
|
||||
var groupObj = UIFactory.CreateVerticalGroup(m_subContentParent, "SubContent", false, false, true, true, 4, new Vector4(3,3,3,3),
|
||||
new Color(1, 1, 1, 0));
|
||||
|
||||
m_hiddenObj = UIFactory.CreateLabel(groupObj, "HiddenLabel", "", TextAnchor.MiddleLeft).gameObject;
|
||||
m_hiddenObj.SetActive(false);
|
||||
var hiddenText = m_hiddenObj.GetComponent<Text>();
|
||||
hiddenText.color = Color.clear;
|
||||
hiddenText.fontSize = 14;
|
||||
hiddenText.raycastTarget = false;
|
||||
hiddenText.supportRichText = false;
|
||||
var hiddenFitter = m_hiddenObj.AddComponent<ContentSizeFitter>();
|
||||
hiddenFitter.verticalFit = ContentSizeFitter.FitMode.PreferredSize;
|
||||
UIFactory.SetLayoutElement(m_hiddenObj, minHeight: 25, flexibleHeight: 500, minWidth: 250, flexibleWidth: 9000);
|
||||
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(m_hiddenObj, true, true, true, true);
|
||||
|
||||
var inputObj = UIFactory.CreateInputField(m_hiddenObj, "StringInputField", "...", out m_valueInput, 14, 3);
|
||||
UIFactory.SetLayoutElement(inputObj, minWidth: 120, minHeight: 25, flexibleWidth: 5000, flexibleHeight: 5000);
|
||||
|
||||
m_valueInput.lineType = InputField.LineType.MultiLineNewline;
|
||||
|
||||
m_placeholderText = m_valueInput.placeholder.GetComponent<Text>();
|
||||
|
||||
m_placeholderText.supportRichText = false;
|
||||
m_valueInput.textComponent.supportRichText = false;
|
||||
|
||||
m_valueInput.onValueChanged.AddListener((string val) =>
|
||||
{
|
||||
hiddenText.text = val ?? "";
|
||||
LayoutRebuilder.ForceRebuildLayoutImmediate(Owner.m_mainRect);
|
||||
});
|
||||
|
||||
if (Owner.CanWrite)
|
||||
{
|
||||
var apply = UIFactory.CreateButton(groupObj, "ApplyButton", "Apply", SetValueFromInput, new Color(0.2f, 0.2f, 0.2f));
|
||||
UIFactory.SetLayoutElement(apply.gameObject, minWidth: 50, minHeight: 25, flexibleWidth: 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_valueInput.readOnly = true;
|
||||
}
|
||||
|
||||
RefreshUIForValue();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,355 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.Core;
|
||||
using UnityExplorer.Core.Runtime;
|
||||
using UnityExplorer.UI;
|
||||
using UnityExplorer.UI.Utility;
|
||||
using UnityExplorer.UI.CacheObject;
|
||||
using UnityExplorer.UI.Inspectors;
|
||||
|
||||
namespace UnityExplorer.UI.InteractiveValues
|
||||
{
|
||||
public class InteractiveValue
|
||||
{
|
||||
/// <summary>
|
||||
/// Get the <see cref="InteractiveValue"/> subclass which supports the provided <paramref name="type"/>.
|
||||
/// </summary>
|
||||
/// <param name="type">The <see cref="Type"/> which you want the <see cref="InteractiveValue"/> Type for.</param>
|
||||
/// <returns>The best subclass of <see cref="InteractiveValue"/> which supports the provided <paramref name="type"/>.</returns>
|
||||
public static Type GetIValueForType(Type type)
|
||||
{
|
||||
// rather ugly but I couldn't think of a cleaner way that was worth it.
|
||||
// switch-case doesn't really work here.
|
||||
|
||||
// arbitrarily check some types, fastest methods first.
|
||||
if (type == typeof(bool))
|
||||
return typeof(InteractiveBool);
|
||||
// if type is primitive then it must be a number if its not a bool. Also check for decimal.
|
||||
else if (type.IsPrimitive || type == typeof(decimal))
|
||||
return typeof(InteractiveNumber);
|
||||
// check for strings
|
||||
else if (type == typeof(string))
|
||||
return typeof(InteractiveString);
|
||||
// check for enum/flags
|
||||
else if (typeof(Enum).IsAssignableFrom(type))
|
||||
{
|
||||
// NET 3.5 doesn't have "GetCustomAttribute", gotta use the multiple version.
|
||||
if (type.GetCustomAttributes(typeof(FlagsAttribute), true) is object[] fa && fa.Any())
|
||||
return typeof(InteractiveFlags);
|
||||
else
|
||||
return typeof(InteractiveEnum);
|
||||
}
|
||||
// check for unity struct types
|
||||
else if (typeof(Color).IsAssignableFrom(type))
|
||||
return typeof(InteractiveColor);
|
||||
else if (InteractiveFloatStruct.IsTypeSupported(type))
|
||||
return typeof(InteractiveFloatStruct);
|
||||
// check Transform, force InteractiveValue so they dont become InteractiveEnumerables.
|
||||
else if (typeof(Transform).IsAssignableFrom(type))
|
||||
return typeof(InteractiveValue);
|
||||
// check Dictionaries before Enumerables
|
||||
else if (ReflectionUtility.IsDictionary(type))
|
||||
return typeof(InteractiveDictionary);
|
||||
// finally check for Enumerables
|
||||
else if (ReflectionUtility.IsEnumerable(type))
|
||||
return typeof(InteractiveEnumerable);
|
||||
// fallback to default
|
||||
else
|
||||
return typeof(InteractiveValue);
|
||||
}
|
||||
|
||||
public static InteractiveValue Create(object value, Type fallbackType)
|
||||
{
|
||||
var type = ReflectionUtility.GetActualType(value) ?? fallbackType;
|
||||
var iType = GetIValueForType(type);
|
||||
|
||||
return (InteractiveValue)Activator.CreateInstance(iType, new object[] { value, type });
|
||||
}
|
||||
|
||||
// ~~~~~~~~~ Instance ~~~~~~~~~
|
||||
|
||||
public InteractiveValue(object value, Type valueType)
|
||||
{
|
||||
this.Value = value;
|
||||
this.FallbackType = valueType;
|
||||
}
|
||||
|
||||
public CacheObjectBase Owner;
|
||||
|
||||
public object Value;
|
||||
public readonly Type FallbackType;
|
||||
|
||||
public virtual bool HasSubContent => false;
|
||||
public virtual bool SubContentWanted => false;
|
||||
public virtual bool WantInspectBtn => true;
|
||||
|
||||
public string DefaultLabel => m_defaultLabel ?? GetDefaultLabel();
|
||||
internal string m_defaultLabel;
|
||||
internal string m_richValueType;
|
||||
|
||||
public bool m_UIConstructed;
|
||||
|
||||
public virtual void OnDestroy()
|
||||
{
|
||||
if (this.m_mainContent)
|
||||
{
|
||||
m_mainContent.transform.SetParent(null, false);
|
||||
m_mainContent.SetActive(false);
|
||||
GameObject.Destroy(this.m_mainContent.gameObject);
|
||||
}
|
||||
|
||||
DestroySubContent();
|
||||
}
|
||||
|
||||
public virtual void DestroySubContent()
|
||||
{
|
||||
if (this.m_subContentParent && HasSubContent)
|
||||
{
|
||||
for (int i = 0; i < this.m_subContentParent.transform.childCount; i++)
|
||||
{
|
||||
var child = m_subContentParent.transform.GetChild(i);
|
||||
if (child)
|
||||
GameObject.Destroy(child.gameObject);
|
||||
}
|
||||
}
|
||||
|
||||
m_subContentConstructed = false;
|
||||
}
|
||||
|
||||
public virtual void OnValueUpdated()
|
||||
{
|
||||
if (!m_UIConstructed)
|
||||
ConstructUI(m_mainContentParent, m_subContentParent);
|
||||
|
||||
if (Owner is CacheMember ownerMember && !string.IsNullOrEmpty(ownerMember.ReflectionException))
|
||||
OnException(ownerMember);
|
||||
else
|
||||
RefreshUIForValue();
|
||||
}
|
||||
|
||||
public virtual void OnException(CacheMember member)
|
||||
{
|
||||
if (m_UIConstructed)
|
||||
m_baseLabel.text = "<color=red>" + member.ReflectionException + "</color>";
|
||||
|
||||
Value = null;
|
||||
}
|
||||
|
||||
public virtual void RefreshUIForValue()
|
||||
{
|
||||
GetDefaultLabel();
|
||||
m_baseLabel.text = DefaultLabel;
|
||||
}
|
||||
|
||||
public void RefreshElementsAfterUpdate()
|
||||
{
|
||||
if (WantInspectBtn)
|
||||
{
|
||||
bool shouldShowInspect = !Value.IsNullOrDestroyed();
|
||||
|
||||
if (m_inspectButton.activeSelf != shouldShowInspect)
|
||||
m_inspectButton.SetActive(shouldShowInspect);
|
||||
}
|
||||
|
||||
bool subContentWanted = SubContentWanted;
|
||||
if (Owner is CacheMember cm && (!cm.HasEvaluated || !string.IsNullOrEmpty(cm.ReflectionException)))
|
||||
subContentWanted = false;
|
||||
|
||||
if (HasSubContent)
|
||||
{
|
||||
if (m_subExpandBtn.gameObject.activeSelf != subContentWanted)
|
||||
m_subExpandBtn.gameObject.SetActive(subContentWanted);
|
||||
|
||||
if (!subContentWanted && m_subContentParent.activeSelf)
|
||||
ToggleSubcontent();
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void ConstructSubcontent()
|
||||
{
|
||||
Owner.CheckSubcontentCreation();
|
||||
|
||||
m_subContentConstructed = true;
|
||||
}
|
||||
|
||||
public void ToggleSubcontent()
|
||||
{
|
||||
if (!this.m_subContentParent.activeSelf)
|
||||
{
|
||||
this.m_subContentParent.SetActive(true);
|
||||
this.m_subContentParent.transform.SetAsLastSibling();
|
||||
m_subExpandBtn.GetComponentInChildren<Text>().text = "▼";
|
||||
}
|
||||
else
|
||||
{
|
||||
this.m_subContentParent.SetActive(false);
|
||||
m_subExpandBtn.GetComponentInChildren<Text>().text = "▲";
|
||||
}
|
||||
|
||||
OnToggleSubcontent(m_subContentParent.activeSelf);
|
||||
|
||||
RefreshElementsAfterUpdate();
|
||||
}
|
||||
|
||||
internal virtual void OnToggleSubcontent(bool toggle)
|
||||
{
|
||||
if (!m_subContentConstructed)
|
||||
ConstructSubcontent();
|
||||
}
|
||||
|
||||
internal MethodInfo m_toStringMethod;
|
||||
internal MethodInfo m_toStringFormatMethod;
|
||||
internal bool m_gotToStringMethods;
|
||||
|
||||
public string GetDefaultLabel(bool updateType = true)
|
||||
{
|
||||
var valueType = Value?.GetType() ?? this.FallbackType;
|
||||
if (updateType)
|
||||
m_richValueType = SignatureHighlighter.ParseFullSyntax(valueType, true);
|
||||
|
||||
if (!Owner.HasEvaluated)
|
||||
return m_defaultLabel = $"<i><color=grey>Not yet evaluated</color> ({m_richValueType})</i>";
|
||||
|
||||
if (Value.IsNullOrDestroyed())
|
||||
return m_defaultLabel = $"<color=grey>null</color> ({m_richValueType})";
|
||||
|
||||
string label;
|
||||
|
||||
// Two dirty fixes for TextAsset and EventSystem, which can have very long ToString results.
|
||||
if (Value is TextAsset textAsset)
|
||||
{
|
||||
label = textAsset.text;
|
||||
|
||||
if (label.Length > 10)
|
||||
label = $"{label.Substring(0, 10)}...";
|
||||
|
||||
label = $"\"{label}\" {textAsset.name} ({m_richValueType})";
|
||||
}
|
||||
else if (Value is EventSystem)
|
||||
{
|
||||
label = m_richValueType;
|
||||
}
|
||||
else // For everything else...
|
||||
{
|
||||
if (!m_gotToStringMethods)
|
||||
{
|
||||
m_gotToStringMethods = true;
|
||||
|
||||
m_toStringMethod = valueType.GetMethod("ToString", new Type[0]);
|
||||
m_toStringFormatMethod = valueType.GetMethod("ToString", new Type[] { typeof(string) });
|
||||
|
||||
// test format method actually works
|
||||
try
|
||||
{
|
||||
m_toStringFormatMethod.Invoke(Value, new object[] { "F3" });
|
||||
}
|
||||
catch
|
||||
{
|
||||
m_toStringFormatMethod = null;
|
||||
}
|
||||
}
|
||||
|
||||
string toString;
|
||||
if (m_toStringFormatMethod != null)
|
||||
toString = (string)m_toStringFormatMethod.Invoke(Value, new object[] { "F3" });
|
||||
else
|
||||
toString = (string)m_toStringMethod.Invoke(Value, new object[0]);
|
||||
|
||||
toString = toString ?? "";
|
||||
|
||||
string typeName = valueType.FullName;
|
||||
if (typeName.StartsWith("Il2CppSystem."))
|
||||
typeName = typeName.Substring(6, typeName.Length - 6);
|
||||
|
||||
toString = ReflectionProvider.Instance.ProcessTypeFullNameInString(valueType, toString, ref typeName);
|
||||
|
||||
// If the ToString is just the type name, use our syntax highlighted type name instead.
|
||||
if (toString == typeName)
|
||||
{
|
||||
label = m_richValueType;
|
||||
}
|
||||
else // Otherwise, parse the result and put our highlighted name in.
|
||||
{
|
||||
if (toString.Length > 200)
|
||||
toString = toString.Substring(0, 200) + "...";
|
||||
|
||||
label = toString;
|
||||
|
||||
var unityType = $"({valueType.FullName})";
|
||||
if (Value is UnityEngine.Object && label.Contains(unityType))
|
||||
label = label.Replace(unityType, $"({m_richValueType})");
|
||||
else
|
||||
label += $" ({m_richValueType})";
|
||||
}
|
||||
}
|
||||
|
||||
return m_defaultLabel = label;
|
||||
}
|
||||
|
||||
#region UI CONSTRUCTION
|
||||
|
||||
internal GameObject m_mainContentParent;
|
||||
internal GameObject m_subContentParent;
|
||||
|
||||
internal GameObject m_mainContent;
|
||||
internal GameObject m_inspectButton;
|
||||
internal Text m_baseLabel;
|
||||
|
||||
internal Button m_subExpandBtn;
|
||||
internal bool m_subContentConstructed;
|
||||
|
||||
public virtual void ConstructUI(GameObject parent, GameObject subGroup)
|
||||
{
|
||||
m_UIConstructed = true;
|
||||
|
||||
//m_mainContent = UIFactory.CreateHorizontalGroup(parent, $"InteractiveValue_{this.GetType().Name}", false, false, true, true, 4, default,
|
||||
// new Color(1, 1, 1, 0), TextAnchor.UpperLeft);
|
||||
|
||||
m_mainContent = UIFactory.CreateUIObject($"InteractiveValue_{this.GetType().Name}", parent);
|
||||
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(m_mainContent, false, false, true, true, 4, 0, 0, 0, 0, TextAnchor.UpperLeft);
|
||||
|
||||
var mainRect = m_mainContent.GetComponent<RectTransform>();
|
||||
mainRect.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, 25);
|
||||
|
||||
UIFactory.SetLayoutElement(m_mainContent, flexibleWidth: 9000, minWidth: 175, minHeight: 25, flexibleHeight: 0);
|
||||
|
||||
// subcontent expand button
|
||||
if (HasSubContent)
|
||||
{
|
||||
m_subExpandBtn = UIFactory.CreateButton(m_mainContent, "ExpandSubcontentButton", "▲", ToggleSubcontent, new Color(1,1,1,0));
|
||||
UIFactory.SetLayoutElement(m_subExpandBtn.gameObject, minHeight: 25, minWidth: 25, flexibleWidth: 0, flexibleHeight: 0);
|
||||
}
|
||||
|
||||
// inspect button
|
||||
|
||||
var inspectBtn = UIFactory.CreateButton(m_mainContent,
|
||||
"InspectButton",
|
||||
"Inspect",
|
||||
() =>
|
||||
{
|
||||
if (!Value.IsNullOrDestroyed(false))
|
||||
InspectorManager.Inspect(this.Value, this.Owner);
|
||||
},
|
||||
new Color(0.3f, 0.3f, 0.3f, 0.2f));
|
||||
|
||||
m_inspectButton = inspectBtn.gameObject;
|
||||
UIFactory.SetLayoutElement(m_inspectButton, minWidth: 60, minHeight: 25, flexibleWidth: 0, flexibleHeight: 0);
|
||||
|
||||
m_inspectButton.SetActive(false);
|
||||
|
||||
// value label
|
||||
|
||||
m_baseLabel = UIFactory.CreateLabel(m_mainContent, "ValueLabel", "", TextAnchor.MiddleLeft);
|
||||
UIFactory.SetLayoutElement(m_baseLabel.gameObject, flexibleWidth: 9000, minHeight: 25);
|
||||
|
||||
m_subContentParent = subGroup;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
@ -7,6 +7,7 @@ using UnityEngine.UI;
|
||||
using UnityExplorer.Core.Search;
|
||||
using UnityExplorer.UI.Inspectors;
|
||||
using UnityExplorer.UI.Models;
|
||||
using UnityExplorer.UI.ObjectPool;
|
||||
using UnityExplorer.UI.Panels;
|
||||
using UnityExplorer.UI.Utility;
|
||||
using UnityExplorer.UI.Widgets.AutoComplete;
|
||||
@ -28,7 +29,7 @@ namespace UnityExplorer.UI.Widgets
|
||||
|
||||
public ButtonListSource<object> dataHandler;
|
||||
|
||||
private ScrollPool resultsScrollPool;
|
||||
private ScrollPool<ButtonCell> resultsScrollPool;
|
||||
private List<object> currentResults = new List<object>();
|
||||
|
||||
public override GameObject UIRoot => uiRoot;
|
||||
@ -90,7 +91,7 @@ namespace UnityExplorer.UI.Widgets
|
||||
// Cache the syntax-highlighted text for each search result to reduce allocs.
|
||||
private static readonly Dictionary<int, string> cachedCellTexts = new Dictionary<int, string>();
|
||||
|
||||
public void SetCell(ButtonCell<object> cell, int index)
|
||||
public void SetCell(ButtonCell cell, int index)
|
||||
{
|
||||
if (!cachedCellTexts.ContainsKey(index))
|
||||
{
|
||||
@ -103,7 +104,7 @@ namespace UnityExplorer.UI.Widgets
|
||||
cachedCellTexts.Add(index, text);
|
||||
}
|
||||
|
||||
cell.buttonText.text = cachedCellTexts[index];
|
||||
cell.Button.ButtonText.text = cachedCellTexts[index];
|
||||
}
|
||||
|
||||
private void OnCellClicked(int dataIndex)
|
||||
@ -192,8 +193,9 @@ namespace UnityExplorer.UI.Widgets
|
||||
|
||||
// Search button
|
||||
|
||||
var searchButton = UIFactory.CreateButton(uiRoot, "SearchButton", "Search", DoSearch);
|
||||
UIFactory.SetLayoutElement(searchButton.gameObject, minHeight: 25, flexibleHeight: 0);
|
||||
var searchButton = UIFactory.CreateButton(uiRoot, "SearchButton", "Search");
|
||||
UIFactory.SetLayoutElement(searchButton.Button.gameObject, minHeight: 25, flexibleHeight: 0);
|
||||
searchButton.OnClick += DoSearch;
|
||||
|
||||
// Results count label
|
||||
|
||||
@ -205,8 +207,12 @@ namespace UnityExplorer.UI.Widgets
|
||||
// RESULTS SCROLL POOL
|
||||
|
||||
dataHandler = new ButtonListSource<object>(resultsScrollPool, GetEntries, SetCell, ShouldDisplayCell, OnCellClicked);
|
||||
resultsScrollPool = UIFactory.CreateScrollPool(uiRoot, "ResultsList", out GameObject scrollObj, out GameObject scrollContent);
|
||||
resultsScrollPool.Initialize(dataHandler, ButtonCell<object>.CreatePrototypeCell(uiRoot));
|
||||
resultsScrollPool = UIFactory.CreateScrollPool<ButtonCell>(uiRoot, "ResultsList", out GameObject scrollObj, out GameObject scrollContent);
|
||||
|
||||
//if (!Pool<ButtonCell>.PrototypeObject)
|
||||
// Pool<ButtonCell>.PrototypeObject = ButtonCell.CreatePrototypeCell(Pool<ButtonCell>.InactiveHolder).gameObject;
|
||||
|
||||
resultsScrollPool.Initialize(dataHandler);//, ButtonCell.CreatePrototypeCell(uiRoot));
|
||||
UIFactory.SetLayoutElement(scrollObj, flexibleHeight: 9999);
|
||||
}
|
||||
}
|
||||
|
@ -159,8 +159,14 @@ namespace UnityExplorer.UI.Widgets
|
||||
|
||||
// Scene selector dropdown
|
||||
|
||||
var dropdownObj = UIFactory.CreateDropdown(toolbar, out sceneDropdown, "<notset>", 13, OnDropdownChanged);
|
||||
UIFactory.SetLayoutElement(dropdownObj, minHeight: 25, flexibleHeight: 0);
|
||||
var dropRow = UIFactory.CreateHorizontalGroup(toolbar, "DropdownRow", true, true, true, true, 5, default, new Color(1, 1, 1, 0));
|
||||
UIFactory.SetLayoutElement(dropRow, minHeight: 25, flexibleWidth: 9999);
|
||||
|
||||
var dropLabel = UIFactory.CreateLabel(dropRow, "SelectorLabel", "Scene:", TextAnchor.MiddleLeft, Color.cyan, false, 15);
|
||||
UIFactory.SetLayoutElement(dropLabel.gameObject, minHeight: 25, minWidth: 60, flexibleWidth: 0);
|
||||
|
||||
var dropdownObj = UIFactory.CreateDropdown(dropRow, out sceneDropdown, "<notset>", 13, OnDropdownChanged);
|
||||
UIFactory.SetLayoutElement(dropdownObj, minHeight: 25, flexibleHeight: 0, flexibleWidth: 9999);
|
||||
|
||||
SceneHandler.Update();
|
||||
PopulateSceneDropdown();
|
||||
@ -183,8 +189,9 @@ namespace UnityExplorer.UI.Widgets
|
||||
refreshRow = UIFactory.CreateHorizontalGroup(toolbar, "RefreshGroup", true, true, true, true, 2, new Vector4(2, 2, 2, 2));
|
||||
UIFactory.SetLayoutElement(refreshRow, minHeight: 30, flexibleHeight: 0);
|
||||
|
||||
var refreshButton = UIFactory.CreateButton(refreshRow, "RefreshButton", "Update", ForceUpdate);
|
||||
UIFactory.SetLayoutElement(refreshButton.gameObject, minWidth: 65, flexibleWidth: 0);
|
||||
var refreshButton = UIFactory.CreateButton(refreshRow, "RefreshButton", "Update");
|
||||
UIFactory.SetLayoutElement(refreshButton.Button.gameObject, minWidth: 65, flexibleWidth: 0);
|
||||
refreshButton.OnClick += ForceUpdate;
|
||||
|
||||
var refreshToggle = UIFactory.CreateToggle(refreshRow, "RefreshToggle", out Toggle toggle, out Text text);
|
||||
UIFactory.SetLayoutElement(refreshToggle, flexibleWidth: 9999);
|
||||
@ -199,14 +206,14 @@ namespace UnityExplorer.UI.Widgets
|
||||
|
||||
// Transform Tree
|
||||
|
||||
var scrollPool = UIFactory.CreateScrollPool(m_uiRoot, "TransformTree", out GameObject scrollObj,
|
||||
out GameObject scrollContent, new Color(0.15f, 0.15f, 0.15f));
|
||||
var scrollPool = UIFactory.CreateScrollPool<TransformCell>(m_uiRoot, "TransformTree", out GameObject scrollObj,
|
||||
out GameObject scrollContent, new Color(0.11f, 0.11f, 0.11f));
|
||||
UIFactory.SetLayoutElement(scrollObj, flexibleHeight: 9999);
|
||||
UIFactory.SetLayoutElement(scrollContent, flexibleHeight: 9999);
|
||||
|
||||
Tree = new TransformTree(scrollPool) { GetRootEntriesMethod = GetRootEntries };
|
||||
Tree.Init();
|
||||
|
||||
Tree.RefreshData(true, true);
|
||||
//scrollPool.Viewport.GetComponent<Mask>().enabled = false;
|
||||
//UIRoot.GetComponent<Mask>().enabled = false;
|
||||
|
||||
@ -244,37 +251,39 @@ namespace UnityExplorer.UI.Widgets
|
||||
|
||||
var buttonRow = UIFactory.CreateHorizontalGroup(sceneLoaderObj, "LoadButtons", true, true, true, true, 4);
|
||||
|
||||
var loadButton = UIFactory.CreateButton(buttonRow, "LoadSceneButton", "Load (Single)", () =>
|
||||
var loadButton = UIFactory.CreateButton(buttonRow, "LoadSceneButton", "Load (Single)", new Color(0.1f, 0.3f, 0.3f));
|
||||
UIFactory.SetLayoutElement(loadButton.Button.gameObject, minHeight: 25, minWidth: 150);
|
||||
loadButton.OnClick += () =>
|
||||
{
|
||||
TryLoadScene(LoadSceneMode.Single, allSceneDrop);
|
||||
}, new Color(0.1f, 0.3f, 0.3f));
|
||||
UIFactory.SetLayoutElement(loadButton.gameObject, minHeight: 25, minWidth: 150);
|
||||
};
|
||||
|
||||
var loadAdditiveButton = UIFactory.CreateButton(buttonRow, "LoadSceneButton", "Load (Additive)", () =>
|
||||
var loadAdditiveButton = UIFactory.CreateButton(buttonRow, "LoadSceneButton", "Load (Additive)", new Color(0.1f, 0.3f, 0.3f));
|
||||
UIFactory.SetLayoutElement(loadAdditiveButton.Button.gameObject, minHeight: 25, minWidth: 150);
|
||||
loadAdditiveButton.OnClick += () =>
|
||||
{
|
||||
TryLoadScene(LoadSceneMode.Additive, allSceneDrop);
|
||||
}, new Color(0.1f, 0.3f, 0.3f));
|
||||
UIFactory.SetLayoutElement(loadAdditiveButton.gameObject, minHeight: 25, minWidth: 150);
|
||||
};
|
||||
|
||||
var disabledColor = new Color(0.24f, 0.24f, 0.24f);
|
||||
RuntimeProvider.Instance.SetColorBlock(loadButton, disabled: disabledColor);
|
||||
RuntimeProvider.Instance.SetColorBlock(loadAdditiveButton, disabled: disabledColor);
|
||||
RuntimeProvider.Instance.SetColorBlock(loadButton.Button, disabled: disabledColor);
|
||||
RuntimeProvider.Instance.SetColorBlock(loadAdditiveButton.Button, disabled: disabledColor);
|
||||
|
||||
loadButton.interactable = false;
|
||||
loadAdditiveButton.interactable = false;
|
||||
loadButton.Button.interactable = false;
|
||||
loadAdditiveButton.Button.interactable = false;
|
||||
|
||||
allSceneDrop.onValueChanged.AddListener((int val) =>
|
||||
{
|
||||
var text = allSceneDrop.options[val].text;
|
||||
if (text == DEFAULT_LOAD_TEXT)
|
||||
{
|
||||
loadButton.interactable = false;
|
||||
loadAdditiveButton.interactable = false;
|
||||
loadButton.Button.interactable = false;
|
||||
loadAdditiveButton.Button.interactable = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
loadButton.interactable = true;
|
||||
loadAdditiveButton.interactable = true;
|
||||
loadButton.Button.interactable = true;
|
||||
loadAdditiveButton.Button.interactable = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -1,83 +1,83 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
//using System;
|
||||
//using System.Collections.Generic;
|
||||
//using System.Linq;
|
||||
//using System.Text;
|
||||
//using UnityEngine;
|
||||
//using UnityEngine.UI;
|
||||
|
||||
namespace UnityExplorer.UI.Widgets
|
||||
{
|
||||
public class CellViewHolder : ICell
|
||||
{
|
||||
public CellViewHolder(GameObject uiRoot)
|
||||
{
|
||||
this.UIRoot = uiRoot;
|
||||
this.Rect = uiRoot.GetComponent<RectTransform>();
|
||||
m_enabled = uiRoot.activeSelf;
|
||||
}
|
||||
//namespace UnityExplorer.UI.Widgets
|
||||
//{
|
||||
// public class CellViewHolder : ICell
|
||||
// {
|
||||
// public CellViewHolder(GameObject uiRoot)
|
||||
// {
|
||||
// this.UIRoot = uiRoot;
|
||||
// this.Rect = uiRoot.GetComponent<RectTransform>();
|
||||
// m_enabled = uiRoot.activeSelf;
|
||||
// }
|
||||
|
||||
public bool Enabled => m_enabled;
|
||||
private bool m_enabled;
|
||||
// public bool Enabled => m_enabled;
|
||||
// private bool m_enabled;
|
||||
|
||||
public GameObject UIRoot { get; }
|
||||
public RectTransform Rect { get; }
|
||||
// public GameObject UIRoot { get; }
|
||||
// public RectTransform Rect { get; }
|
||||
|
||||
private GameObject m_content;
|
||||
// private GameObject m_content;
|
||||
|
||||
public GameObject SetContent(GameObject newContent)
|
||||
{
|
||||
var ret = m_content;
|
||||
// public GameObject SetContent(GameObject newContent)
|
||||
// {
|
||||
// var ret = m_content;
|
||||
|
||||
if (ret && newContent && ret.ReferenceEqual(newContent))
|
||||
return null;
|
||||
// if (ret && newContent && ret.ReferenceEqual(newContent))
|
||||
// return null;
|
||||
|
||||
newContent.transform.SetParent(this.UIRoot.transform, false);
|
||||
(this as ICell).Enable();
|
||||
// newContent.transform.SetParent(this.UIRoot.transform, false);
|
||||
// (this as ICell).Enable();
|
||||
|
||||
m_content = newContent;
|
||||
return ret;
|
||||
}
|
||||
// m_content = newContent;
|
||||
// return ret;
|
||||
// }
|
||||
|
||||
public GameObject DisableContent()
|
||||
{
|
||||
var ret = m_content;
|
||||
(this as ICell).Disable();
|
||||
return ret;
|
||||
}
|
||||
// public GameObject DisableContent()
|
||||
// {
|
||||
// var ret = m_content;
|
||||
// (this as ICell).Disable();
|
||||
// return ret;
|
||||
// }
|
||||
|
||||
void ICell.Enable()
|
||||
{
|
||||
m_enabled = true;
|
||||
UIRoot.SetActive(true);
|
||||
}
|
||||
// void ICell.Enable()
|
||||
// {
|
||||
// m_enabled = true;
|
||||
// UIRoot.SetActive(true);
|
||||
// }
|
||||
|
||||
void ICell.Disable()
|
||||
{
|
||||
m_enabled = false;
|
||||
UIRoot.SetActive(false);
|
||||
}
|
||||
// void ICell.Disable()
|
||||
// {
|
||||
// m_enabled = false;
|
||||
// UIRoot.SetActive(false);
|
||||
// }
|
||||
|
||||
public static RectTransform CreatePrototypeCell(GameObject parent)
|
||||
{
|
||||
// using an image on the cell view holder is fine, we only need to make about 20-50 of these per pool.
|
||||
var prototype = UIFactory.CreateVerticalGroup(parent, "PrototypeCell", true, true, true, true, 0, new Vector4(0, 0, 0, 0),
|
||||
new Color(0.11f, 0.11f, 0.11f), TextAnchor.MiddleCenter);
|
||||
// public static RectTransform CreatePrototypeCell(GameObject parent)
|
||||
// {
|
||||
// // using an image on the cell view holder is fine, we only need to make about 20-50 of these per pool.
|
||||
// var prototype = UIFactory.CreateVerticalGroup(parent, "PrototypeCell", true, true, true, true, 0, new Vector4(0, 0, 0, 0),
|
||||
// new Color(0.11f, 0.11f, 0.11f), TextAnchor.MiddleCenter);
|
||||
|
||||
var rect = prototype.GetComponent<RectTransform>();
|
||||
rect.anchorMin = new Vector2(0, 1);
|
||||
rect.anchorMax = new Vector2(0, 1);
|
||||
rect.pivot = new Vector2(0.5f, 1);
|
||||
rect.sizeDelta = new Vector2(100, 30);
|
||||
// var rect = prototype.GetComponent<RectTransform>();
|
||||
// rect.anchorMin = new Vector2(0, 1);
|
||||
// rect.anchorMax = new Vector2(0, 1);
|
||||
// rect.pivot = new Vector2(0.5f, 1);
|
||||
// rect.sizeDelta = new Vector2(100, 30);
|
||||
|
||||
prototype.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize;
|
||||
// prototype.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize;
|
||||
|
||||
var sepObj = UIFactory.CreateUIObject("separator", prototype);
|
||||
sepObj.AddComponent<Image>().color = Color.black;
|
||||
UIFactory.SetLayoutElement(sepObj, minHeight: 1, preferredHeight: 1, flexibleHeight: 0);
|
||||
// var sepObj = UIFactory.CreateUIObject("separator", prototype);
|
||||
// sepObj.AddComponent<Image>().color = Color.black;
|
||||
// UIFactory.SetLayoutElement(sepObj, minHeight: 1, preferredHeight: 1, flexibleHeight: 0);
|
||||
|
||||
prototype.SetActive(false);
|
||||
// prototype.SetActive(false);
|
||||
|
||||
return rect;
|
||||
}
|
||||
}
|
||||
}
|
||||
// return rect;
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
@ -15,11 +15,11 @@ namespace UnityExplorer.UI.Widgets
|
||||
public static implicit operator float(DataViewInfo it) => it.height;
|
||||
}
|
||||
|
||||
public class DataHeightCache
|
||||
public class DataHeightCache<T> where T : ICell
|
||||
{
|
||||
private ScrollPool ScrollPool { get; }
|
||||
private ScrollPool<T> ScrollPool { get; }
|
||||
|
||||
public DataHeightCache(ScrollPool scrollPool)
|
||||
public DataHeightCache(ScrollPool<T> scrollPool)
|
||||
{
|
||||
ScrollPool = scrollPool;
|
||||
}
|
||||
@ -38,7 +38,7 @@ namespace UnityExplorer.UI.Widgets
|
||||
public float TotalHeight => totalHeight;
|
||||
private float totalHeight;
|
||||
|
||||
public float DefaultHeight => m_defaultHeight ?? (float)(m_defaultHeight = ScrollPool.PrototypeCell.rect.height);
|
||||
public float DefaultHeight => m_defaultHeight ?? (float)(m_defaultHeight = ScrollPool.PrototypeHeight);
|
||||
private float? m_defaultHeight;
|
||||
|
||||
/// <summary>
|
||||
@ -100,8 +100,16 @@ namespace UnityExplorer.UI.Widgets
|
||||
return;
|
||||
|
||||
var val = heightCache[heightCache.Count - 1];
|
||||
totalHeight -= val;
|
||||
totalHeight -= val;
|
||||
heightCache.RemoveAt(heightCache.Count - 1);
|
||||
|
||||
int idx = heightCache.Count;
|
||||
if (idx > 0)
|
||||
{
|
||||
while (rangeCache[rangeCache.Count - 1] == idx)
|
||||
rangeCache.RemoveAt(rangeCache.Count - 1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>Get the data index at the specific position of the total height cache.</summary>
|
||||
|
@ -3,10 +3,11 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityExplorer.UI.ObjectPool;
|
||||
|
||||
namespace UnityExplorer.UI.Widgets
|
||||
{
|
||||
public interface ICell
|
||||
public interface ICell : IPooledObject
|
||||
{
|
||||
bool Enabled { get; }
|
||||
|
||||
|
@ -6,15 +6,15 @@ using UnityEngine;
|
||||
|
||||
namespace UnityExplorer.UI.Widgets
|
||||
{
|
||||
public interface IPoolDataSource
|
||||
public interface IPoolDataSource<T> where T : ICell
|
||||
{
|
||||
int ItemCount { get; }
|
||||
|
||||
void SetCell(ICell cell, int index);
|
||||
void DisableCell(ICell cell, int index);
|
||||
|
||||
int GetRealIndexOfTempIndex(int tempIndex);
|
||||
|
||||
ICell CreateCell(RectTransform cellTransform);
|
||||
void OnCellBorrowed(T cell);
|
||||
void OnCellReturned(T cell);
|
||||
|
||||
void SetCell(T cell, int index);
|
||||
void DisableCell(T cell, int index);
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.Core.Input;
|
||||
using UnityExplorer.UI.Models;
|
||||
using UnityExplorer.UI.ObjectPool;
|
||||
|
||||
namespace UnityExplorer.UI.Widgets
|
||||
{
|
||||
@ -15,20 +16,31 @@ namespace UnityExplorer.UI.Widgets
|
||||
public int cellIndex, dataIndex;
|
||||
}
|
||||
|
||||
//public abstract class ScrollPool : UIBehaviourModel
|
||||
//{
|
||||
// public abstract IPoolDataSource DataSource { get; set; }
|
||||
// public abstract RectTransform PrototypeCell { get; }
|
||||
//
|
||||
// public abstract void Initialize(IPoolDataSource dataSource);
|
||||
//
|
||||
//}
|
||||
|
||||
/// <summary>
|
||||
/// An object-pooled ScrollRect, attempts to support content of any size and provide a scrollbar for it.
|
||||
/// </summary>
|
||||
public class ScrollPool : UIBehaviourModel
|
||||
public class ScrollPool<T> : UIBehaviourModel where T : ICell
|
||||
{
|
||||
public ScrollPool(ScrollRect scrollRect)
|
||||
{
|
||||
this.ScrollRect = scrollRect;
|
||||
}
|
||||
|
||||
public IPoolDataSource DataSource;
|
||||
public RectTransform PrototypeCell;
|
||||
public IPoolDataSource<T> DataSource { get; set; }
|
||||
|
||||
private float PrototypeHeight => PrototypeCell.rect.height;
|
||||
public float PrototypeHeight => _protoHeight ?? (float)(_protoHeight = Pool<T>.Instance.DefaultHeight);
|
||||
private float? _protoHeight;
|
||||
|
||||
//private float PrototypeHeight => DefaultHeight.rect.height;
|
||||
|
||||
public int ExtraPoolCells => 6;
|
||||
public float RecycleThreshold => PrototypeHeight * ExtraPoolCells;
|
||||
@ -64,9 +76,9 @@ namespace UnityExplorer.UI.Widgets
|
||||
private int bottomDataIndex;
|
||||
private int TopDataIndex => Math.Max(0, bottomDataIndex - CellPool.Count + 1);
|
||||
|
||||
private readonly List<ICell> CellPool = new List<ICell>();
|
||||
private readonly List<T> CellPool = new List<T>();
|
||||
|
||||
internal DataHeightCache HeightCache;
|
||||
internal DataHeightCache<T> HeightCache;
|
||||
|
||||
private float TotalDataHeight => HeightCache.TotalHeight + contentLayout.padding.top + contentLayout.padding.bottom;
|
||||
|
||||
@ -99,8 +111,16 @@ namespace UnityExplorer.UI.Widgets
|
||||
|
||||
private float prevContentHeight;
|
||||
|
||||
public void SetUninitialized()
|
||||
{
|
||||
m_initialized = false;
|
||||
}
|
||||
|
||||
public override void Update()
|
||||
{
|
||||
if (!m_initialized || !ScrollRect || DataSource == null)
|
||||
return;
|
||||
|
||||
if (writingLocked && timeofLastWriteLock < Time.time)
|
||||
writingLocked = false;
|
||||
|
||||
@ -125,6 +145,8 @@ namespace UnityExplorer.UI.Widgets
|
||||
writingLocked = false;
|
||||
Content.anchoredPosition = Vector2.zero;
|
||||
UpdateSliderHandle(true);
|
||||
|
||||
m_initialized = true;
|
||||
}
|
||||
|
||||
public void RefreshAndJumpToTop()
|
||||
@ -137,22 +159,10 @@ namespace UnityExplorer.UI.Widgets
|
||||
|
||||
public void RecreateHeightCache()
|
||||
{
|
||||
//if (tempHeightCache == null)
|
||||
// tempHeightCache = HeightCache;
|
||||
|
||||
HeightCache = new DataHeightCache(this);
|
||||
HeightCache = new DataHeightCache<T>(this);
|
||||
CheckDataSourceCountChange(out _);
|
||||
}
|
||||
|
||||
//public void DisableTempCache()
|
||||
//{
|
||||
// if (tempHeightCache == null)
|
||||
// return;
|
||||
|
||||
// HeightCache = tempHeightCache;
|
||||
// tempHeightCache = null;
|
||||
//}
|
||||
|
||||
public void RefreshCells(bool reloadData)
|
||||
{
|
||||
RefreshCells(reloadData, true);
|
||||
@ -160,15 +170,14 @@ namespace UnityExplorer.UI.Widgets
|
||||
|
||||
// Initialize
|
||||
|
||||
public void Initialize(IPoolDataSource dataSource, RectTransform prototypeCell)
|
||||
private bool m_initialized;
|
||||
|
||||
public void Initialize(IPoolDataSource<T> dataSource)
|
||||
{
|
||||
if (!prototypeCell)
|
||||
throw new Exception("No prototype cell set, cannot initialize");
|
||||
// Ensure the pool for the cell type is initialized.
|
||||
Pool<T>.GetPool();
|
||||
|
||||
this.PrototypeCell = prototypeCell;
|
||||
PrototypeCell.transform.SetParent(Viewport, false);
|
||||
|
||||
HeightCache = new DataHeightCache(this);
|
||||
HeightCache = new DataHeightCache<T>(this);
|
||||
DataSource = dataSource;
|
||||
|
||||
this.contentLayout = ScrollRect.content.GetComponent<VerticalLayoutGroup>();
|
||||
@ -200,6 +209,8 @@ namespace UnityExplorer.UI.Widgets
|
||||
|
||||
// add onValueChanged listener after setup
|
||||
ScrollRect.onValueChanged.AddListener(OnValueChangedListener);
|
||||
|
||||
m_initialized = true;
|
||||
}
|
||||
|
||||
private void SetScrollBounds()
|
||||
@ -209,14 +220,22 @@ namespace UnityExplorer.UI.Widgets
|
||||
|
||||
// Cell pool
|
||||
|
||||
private void CreateCellPool(bool andResetDataIndex = true)
|
||||
public void ReturnCells()
|
||||
{
|
||||
if (CellPool.Any())
|
||||
{
|
||||
foreach (var cell in CellPool)
|
||||
GameObject.Destroy(cell.Rect.gameObject);
|
||||
{
|
||||
DataSource.OnCellReturned(cell);
|
||||
Pool<T>.Return(cell);
|
||||
}
|
||||
CellPool.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
private void CreateCellPool(bool andResetDataIndex = true)
|
||||
{
|
||||
ReturnCells();
|
||||
|
||||
float currentPoolCoverage = 0f;
|
||||
float requiredCoverage = ScrollRect.viewport.rect.height + RecycleThreshold;
|
||||
@ -230,11 +249,17 @@ namespace UnityExplorer.UI.Widgets
|
||||
{
|
||||
bottomPoolIndex++;
|
||||
|
||||
//Instantiate and add to Pool
|
||||
RectTransform rect = GameObject.Instantiate(PrototypeCell.gameObject).GetComponent<RectTransform>();
|
||||
rect.gameObject.SetActive(true);
|
||||
rect.name = $"Cell_{CellPool.Count}";
|
||||
var cell = DataSource.CreateCell(rect);
|
||||
////Instantiate and add to Pool
|
||||
//RectTransform rect = GameObject.Instantiate(PrototypeCell.gameObject).GetComponent<RectTransform>();
|
||||
//rect.gameObject.SetActive(true);
|
||||
//rect.name = $"Cell_{CellPool.Count}";
|
||||
//var cell = DataSource.CreateCell(rect);
|
||||
//CellPool.Add(cell);
|
||||
//rect.SetParent(ScrollRect.content, false);
|
||||
|
||||
var cell = Pool<T>.Borrow();
|
||||
DataSource.OnCellBorrowed(cell);
|
||||
var rect = cell.Rect;
|
||||
CellPool.Add(cell);
|
||||
rect.SetParent(ScrollRect.content, false);
|
||||
|
||||
@ -400,7 +425,7 @@ namespace UnityExplorer.UI.Widgets
|
||||
ScrollRect.UpdatePrevData();
|
||||
}
|
||||
|
||||
private void SetCell(ICell cachedCell, int dataIndex)
|
||||
private void SetCell(T cachedCell, int dataIndex)
|
||||
{
|
||||
cachedCell.Enable();
|
||||
DataSource.SetCell(cachedCell, dataIndex);
|
||||
|
@ -19,21 +19,21 @@ namespace UnityExplorer.UI.Widgets
|
||||
|
||||
public bool Expanded => Tree.IsCellExpanded(InstanceID);
|
||||
|
||||
public CachedTransform(TransformTree tree, Transform transform, CachedTransform parent = null)
|
||||
public CachedTransform(TransformTree tree, Transform transform, int depth, CachedTransform parent = null)
|
||||
{
|
||||
Tree = tree;
|
||||
Value = transform;
|
||||
Parent = parent;
|
||||
Update(transform);
|
||||
Update(transform, depth);
|
||||
}
|
||||
|
||||
public void Update(Transform transform)
|
||||
public void Update(Transform transform, int depth)
|
||||
{
|
||||
Value = transform;
|
||||
InstanceID = transform.GetInstanceID();
|
||||
//Name = Value.name;
|
||||
//ChildCount = Value.childCount;
|
||||
Depth = Parent?.Depth + 1 ?? 0;
|
||||
Depth = depth;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,48 +4,33 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.UI.Inspectors;
|
||||
using UnityExplorer.UI.Widgets;
|
||||
|
||||
namespace UnityExplorer.UI.Widgets
|
||||
{
|
||||
public class TransformCell : ICell
|
||||
{
|
||||
public float DefaultHeight => 25f;
|
||||
|
||||
public bool Enabled => m_enabled;
|
||||
private bool m_enabled;
|
||||
|
||||
public TransformTree tree;
|
||||
public Action<CachedTransform> OnExpandToggled;
|
||||
|
||||
public CachedTransform cachedTransform;
|
||||
public int _cellIndex;
|
||||
|
||||
public GameObject UIRoot => uiRoot;
|
||||
public GameObject uiRoot;
|
||||
public RectTransform Rect => m_rect;
|
||||
private readonly RectTransform m_rect;
|
||||
private RectTransform m_rect;
|
||||
|
||||
public Text nameLabel;
|
||||
public Button nameButton;
|
||||
|
||||
public Text expandLabel;
|
||||
public Button expandButton;
|
||||
public ButtonRef ExpandButton;
|
||||
public ButtonRef NameButton;
|
||||
|
||||
public LayoutElement spacer;
|
||||
|
||||
public TransformCell(TransformTree tree, GameObject cellUI, Button nameButton, Button expandButton, LayoutElement spacer)
|
||||
{
|
||||
this.tree = tree;
|
||||
this.uiRoot = cellUI;
|
||||
m_rect = uiRoot.GetComponent<RectTransform>();
|
||||
this.nameButton = nameButton;
|
||||
this.nameLabel = nameButton.GetComponentInChildren<Text>();
|
||||
this.expandButton = expandButton;
|
||||
this.expandLabel = expandButton.GetComponentInChildren<Text>();
|
||||
this.spacer = spacer;
|
||||
|
||||
nameButton.onClick.AddListener(OnMainButtonClicked);
|
||||
expandButton.onClick.AddListener(OnExpandClicked);
|
||||
}
|
||||
|
||||
//This is called from the SetCell method in DataSource
|
||||
public void ConfigureCell(CachedTransform cached, int cellIndex)
|
||||
{
|
||||
if (cached == null)
|
||||
@ -64,29 +49,29 @@ namespace UnityExplorer.UI.Widgets
|
||||
|
||||
if (cached.Value)
|
||||
{
|
||||
nameLabel.text = cached.Value.name;
|
||||
nameLabel.color = cached.Value.gameObject.activeSelf ? Color.white : Color.grey;
|
||||
NameButton.ButtonText.text = cached.Value.name;
|
||||
NameButton.ButtonText.color = cached.Value.gameObject.activeSelf ? Color.white : Color.grey;
|
||||
|
||||
int childCount = cached.Value.childCount;
|
||||
if (childCount > 0)
|
||||
{
|
||||
nameLabel.text = $"<color=grey>[{childCount}]</color> {nameLabel.text}";
|
||||
NameButton.ButtonText.text = $"<color=grey>[{childCount}]</color> {NameButton.ButtonText.text}";
|
||||
|
||||
expandButton.interactable = true;
|
||||
expandLabel.text = cached.Expanded ? "▼" : "►";
|
||||
expandLabel.color = cached.Expanded ? new Color(0.5f, 0.5f, 0.5f) : new Color(0.3f, 0.3f, 0.3f);
|
||||
ExpandButton.Button.interactable = true;
|
||||
ExpandButton.ButtonText.text = cached.Expanded ? "▼" : "►";
|
||||
ExpandButton.ButtonText.color = cached.Expanded ? new Color(0.5f, 0.5f, 0.5f) : new Color(0.3f, 0.3f, 0.3f);
|
||||
}
|
||||
else
|
||||
{
|
||||
expandButton.interactable = false;
|
||||
expandLabel.text = "▪";
|
||||
expandLabel.color = new Color(0.3f, 0.3f, 0.3f);
|
||||
ExpandButton.Button.interactable = false;
|
||||
ExpandButton.ButtonText.text = "▪";
|
||||
ExpandButton.ButtonText.color = new Color(0.3f, 0.3f, 0.3f);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
nameLabel.text = $"[Destroyed]";
|
||||
nameLabel.color = Color.red;
|
||||
NameButton.ButtonText.text = $"[Destroyed]";
|
||||
NameButton.ButtonText.color = Color.red;
|
||||
}
|
||||
}
|
||||
|
||||
@ -104,51 +89,54 @@ namespace UnityExplorer.UI.Widgets
|
||||
|
||||
public void OnExpandClicked()
|
||||
{
|
||||
tree.ToggleExpandCell(this);
|
||||
OnExpandToggled?.Invoke(cachedTransform);
|
||||
}
|
||||
|
||||
public void OnMainButtonClicked()
|
||||
{
|
||||
if (cachedTransform.Value)
|
||||
ExplorerCore.Log($"TODO Inspect {cachedTransform.Value.name}");
|
||||
InspectorManager.Inspect(cachedTransform.Value.gameObject);
|
||||
else
|
||||
ExplorerCore.LogWarning("The object was destroyed!");
|
||||
}
|
||||
|
||||
public static RectTransform CreatePrototypeCell(GameObject parent)
|
||||
public GameObject CreateContent(GameObject parent)
|
||||
{
|
||||
var prototype = UIFactory.CreateHorizontalGroup(parent, "PrototypeCell", true, true, true, true, 2, default,
|
||||
new Color(0.15f, 0.15f, 0.15f), TextAnchor.MiddleCenter);
|
||||
//var cell = prototype.AddComponent<TransformCell>();
|
||||
var rect = prototype.GetComponent<RectTransform>();
|
||||
rect.anchorMin = new Vector2(0, 1);
|
||||
rect.anchorMax = new Vector2(0, 1);
|
||||
rect.pivot = new Vector2(0.5f, 1);
|
||||
rect.sizeDelta = new Vector2(25, 25);
|
||||
UIFactory.SetLayoutElement(prototype, minWidth: 100, flexibleWidth: 9999, minHeight: 25, flexibleHeight: 0);
|
||||
uiRoot = UIFactory.CreateUIObject("TransformCell", parent);
|
||||
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(uiRoot, true, true, true, true, 2, childAlignment: TextAnchor.MiddleCenter);
|
||||
m_rect = uiRoot.GetComponent<RectTransform>();
|
||||
m_rect.anchorMin = new Vector2(0, 1);
|
||||
m_rect.anchorMax = new Vector2(0, 1);
|
||||
m_rect.pivot = new Vector2(0.5f, 1);
|
||||
m_rect.sizeDelta = new Vector2(25, 25);
|
||||
UIFactory.SetLayoutElement(uiRoot, minWidth: 100, flexibleWidth: 9999, minHeight: 25, flexibleHeight: 0);
|
||||
|
||||
var spacer = UIFactory.CreateUIObject("Spacer", prototype, new Vector2(0, 0));
|
||||
UIFactory.SetLayoutElement(spacer, minWidth: 0, flexibleWidth: 0, minHeight: 0, flexibleHeight: 0);
|
||||
var spacerObj = UIFactory.CreateUIObject("Spacer", uiRoot, new Vector2(0, 0));
|
||||
UIFactory.SetLayoutElement(spacerObj, minWidth: 0, flexibleWidth: 0, minHeight: 0, flexibleHeight: 0);
|
||||
this.spacer = spacerObj.GetComponent<LayoutElement>();
|
||||
|
||||
var expandButton = UIFactory.CreateButton(prototype, "ExpandButton", "►", null);
|
||||
UIFactory.SetLayoutElement(expandButton.gameObject, minWidth: 15, flexibleWidth: 0, minHeight: 25, flexibleHeight: 0);
|
||||
ExpandButton = UIFactory.CreateButton(this.uiRoot, "ExpandButton", "►");
|
||||
UIFactory.SetLayoutElement(ExpandButton.Button.gameObject, minWidth: 15, flexibleWidth: 0, minHeight: 25, flexibleHeight: 0);
|
||||
|
||||
var nameButton = UIFactory.CreateButton(prototype, "NameButton", "Name", null);
|
||||
UIFactory.SetLayoutElement(nameButton.gameObject, flexibleWidth: 9999, minHeight: 25, flexibleHeight: 0);
|
||||
var nameLabel = nameButton.GetComponentInChildren<Text>();
|
||||
NameButton = UIFactory.CreateButton(this.uiRoot, "NameButton", "Name", null);
|
||||
UIFactory.SetLayoutElement(NameButton.Button.gameObject, flexibleWidth: 9999, minHeight: 25, flexibleHeight: 0);
|
||||
var nameLabel = NameButton.Button.GetComponentInChildren<Text>();
|
||||
nameLabel.horizontalOverflow = HorizontalWrapMode.Overflow;
|
||||
nameLabel.alignment = TextAnchor.MiddleLeft;
|
||||
|
||||
Color normal = new Color(0.15f, 0.15f, 0.15f);
|
||||
Color normal = new Color(0.11f, 0.11f, 0.11f);
|
||||
Color highlight = new Color(0.25f, 0.25f, 0.25f);
|
||||
Color pressed = new Color(0.05f, 0.05f, 0.05f);
|
||||
Color disabled = new Color(1, 1, 1, 0);
|
||||
RuntimeProvider.Instance.SetColorBlock(expandButton, normal, highlight, pressed, disabled);
|
||||
RuntimeProvider.Instance.SetColorBlock(nameButton, normal, highlight, pressed, disabled);
|
||||
RuntimeProvider.Instance.SetColorBlock(ExpandButton.Button, normal, highlight, pressed, disabled);
|
||||
RuntimeProvider.Instance.SetColorBlock(NameButton.Button, normal, highlight, pressed, disabled);
|
||||
|
||||
prototype.SetActive(false);
|
||||
NameButton.OnClick += OnMainButtonClicked;
|
||||
ExpandButton.OnClick += OnExpandClicked;
|
||||
|
||||
return rect;
|
||||
uiRoot.SetActive(false);
|
||||
|
||||
return this.uiRoot;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,14 +5,13 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.UI.ObjectPool;
|
||||
using UnityExplorer.UI.Widgets;
|
||||
|
||||
namespace UnityExplorer.UI.Widgets
|
||||
{
|
||||
public class TransformTree : IPoolDataSource
|
||||
public class TransformTree : IPoolDataSource<TransformCell>
|
||||
{
|
||||
public int GetRealIndexOfTempIndex(int index) => throw new NotImplementedException("TODO");
|
||||
|
||||
public Func<IEnumerable<GameObject>> GetRootEntriesMethod;
|
||||
|
||||
public bool Filtering => !string.IsNullOrEmpty(currentFilter);
|
||||
@ -35,7 +34,7 @@ namespace UnityExplorer.UI.Widgets
|
||||
}
|
||||
private string currentFilter;
|
||||
|
||||
internal ScrollPool Scroller;
|
||||
internal ScrollPool<TransformCell> ScrollPool;
|
||||
|
||||
internal readonly List<CachedTransform> displayedObjects = new List<CachedTransform>();
|
||||
|
||||
@ -46,48 +45,20 @@ namespace UnityExplorer.UI.Widgets
|
||||
|
||||
public int ItemCount => displayedObjects.Count;
|
||||
|
||||
public TransformTree(ScrollPool infiniteScroller)
|
||||
public TransformTree(ScrollPool<TransformCell> scrollPool)
|
||||
{
|
||||
Scroller = infiniteScroller;
|
||||
ScrollPool = scrollPool;
|
||||
}
|
||||
|
||||
public void Init()
|
||||
{
|
||||
RuntimeProvider.Instance.StartCoroutine(InitCoroutine());
|
||||
|
||||
//test
|
||||
var root = new GameObject("StressTest");
|
||||
for (int i = 0; i < 100; i++)
|
||||
{
|
||||
var obj = new GameObject("GameObject " + i);
|
||||
obj.transform.parent = root.transform;
|
||||
for (int j = 0; j < 100; j++)
|
||||
{
|
||||
new GameObject("Child " + j).transform.parent = obj.transform;
|
||||
}
|
||||
}
|
||||
ScrollPool.Initialize(this);
|
||||
}
|
||||
|
||||
private IEnumerator InitCoroutine()
|
||||
{
|
||||
yield return null;
|
||||
public int GetRealIndexOfTempIndex(int index) => -1;// not needed
|
||||
|
||||
var prototype = TransformCell.CreatePrototypeCell(Scroller.UIRoot);
|
||||
public void DisableCell(TransformCell cell, int index) => cell.Disable();
|
||||
|
||||
RefreshData();
|
||||
Scroller.Initialize(this, prototype);
|
||||
}
|
||||
|
||||
public void DisableCell(ICell cell, int index) => cell.Disable();
|
||||
|
||||
public ICell CreateCell(RectTransform cellTransform)
|
||||
{
|
||||
var nameButton = cellTransform.Find("NameButton").GetComponent<Button>();
|
||||
var expandButton = cellTransform.Find("ExpandButton").GetComponent<Button>();
|
||||
var spacer = cellTransform.Find("Spacer").GetComponent<LayoutElement>();
|
||||
|
||||
return new TransformCell(this, cellTransform.gameObject, nameButton, expandButton, spacer);
|
||||
}
|
||||
|
||||
public bool IsCellExpanded(int instanceID)
|
||||
{
|
||||
@ -95,6 +66,14 @@ namespace UnityExplorer.UI.Widgets
|
||||
: expandedInstanceIDs.Contains(instanceID);
|
||||
}
|
||||
|
||||
public void Rebuild()
|
||||
{
|
||||
autoExpandedIDs.Clear();
|
||||
expandedInstanceIDs.Clear();
|
||||
|
||||
RefreshData(true, true);
|
||||
}
|
||||
|
||||
public void RefreshData(bool andReload = false, bool hardReload = false)
|
||||
{
|
||||
displayedObjects.Clear();
|
||||
@ -110,13 +89,13 @@ namespace UnityExplorer.UI.Widgets
|
||||
if (andReload)
|
||||
{
|
||||
if (!hardReload)
|
||||
Scroller.RefreshCells(true);
|
||||
ScrollPool.RefreshCells(true);
|
||||
else
|
||||
Scroller.Rebuild();
|
||||
ScrollPool.Rebuild();
|
||||
}
|
||||
}
|
||||
|
||||
private void Traverse(Transform transform, CachedTransform parent = null)
|
||||
private void Traverse(Transform transform, CachedTransform parent = null, int depth = 0)
|
||||
{
|
||||
int instanceID = transform.GetInstanceID();
|
||||
|
||||
@ -137,11 +116,11 @@ namespace UnityExplorer.UI.Widgets
|
||||
if (objectCache.ContainsKey(instanceID))
|
||||
{
|
||||
cached = objectCache[instanceID];
|
||||
cached.Update(transform);
|
||||
cached.Update(transform, depth);
|
||||
}
|
||||
else
|
||||
{
|
||||
cached = new CachedTransform(this, transform, parent);
|
||||
cached = new CachedTransform(this, transform, depth, parent);
|
||||
objectCache.Add(instanceID, cached);
|
||||
}
|
||||
|
||||
@ -150,7 +129,7 @@ namespace UnityExplorer.UI.Widgets
|
||||
if (IsCellExpanded(instanceID) && cached.Value.childCount > 0)
|
||||
{
|
||||
for (int i = 0; i < transform.childCount; i++)
|
||||
Traverse(transform.GetChild(i), cached);
|
||||
Traverse(transform.GetChild(i), cached, depth + 1);
|
||||
}
|
||||
}
|
||||
|
||||
@ -169,7 +148,7 @@ namespace UnityExplorer.UI.Widgets
|
||||
return false;
|
||||
}
|
||||
|
||||
public void SetCell(ICell iCell, int index)
|
||||
public void SetCell(TransformCell iCell, int index)
|
||||
{
|
||||
var cell = iCell as TransformCell;
|
||||
|
||||
@ -179,9 +158,9 @@ namespace UnityExplorer.UI.Widgets
|
||||
cell.Disable();
|
||||
}
|
||||
|
||||
public void ToggleExpandCell(TransformCell cell)
|
||||
public void ToggleExpandCell(CachedTransform cache)
|
||||
{
|
||||
var instanceID = cell.cachedTransform.InstanceID;
|
||||
var instanceID = cache.InstanceID;
|
||||
if (expandedInstanceIDs.Contains(instanceID))
|
||||
expandedInstanceIDs.Remove(instanceID);
|
||||
else
|
||||
@ -189,5 +168,15 @@ namespace UnityExplorer.UI.Widgets
|
||||
|
||||
RefreshData(true);
|
||||
}
|
||||
|
||||
public void OnCellBorrowed(TransformCell cell)
|
||||
{
|
||||
cell.OnExpandToggled += ToggleExpandCell;
|
||||
}
|
||||
|
||||
public void OnCellReturned(TransformCell cell)
|
||||
{
|
||||
cell.OnExpandToggled -= ToggleExpandCell;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user